]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/app/shared/shared-video-comment/video-comment.service.ts
Implement video comment list in admin
[github/Chocobozzz/PeerTube.git] / client / src / app / shared / shared-video-comment / video-comment.service.ts
1 import { Observable } from 'rxjs'
2 import { catchError, map } from 'rxjs/operators'
3 import { HttpClient, HttpParams } from '@angular/common/http'
4 import { Injectable } from '@angular/core'
5 import { ComponentPaginationLight, RestExtractor, RestPagination, RestService } from '@app/core'
6 import { objectLineFeedToHtml } from '@app/helpers'
7 import {
8 FeedFormat,
9 ResultList,
10 VideoComment as VideoCommentServerModel,
11 VideoCommentAdmin,
12 VideoCommentCreate,
13 VideoCommentThreadTree as VideoCommentThreadTreeServerModel
14 } from '@shared/models'
15 import { environment } from '../../../environments/environment'
16 import { VideoCommentThreadTree } from './video-comment-thread-tree.model'
17 import { VideoComment } from './video-comment.model'
18 import { SortMeta } from 'primeng/api'
19
20 @Injectable()
21 export class VideoCommentService {
22 private static BASE_VIDEO_URL = environment.apiUrl + '/api/v1/videos/'
23 private static BASE_FEEDS_URL = environment.apiUrl + '/feeds/video-comments.'
24
25 constructor (
26 private authHttp: HttpClient,
27 private restExtractor: RestExtractor,
28 private restService: RestService
29 ) {}
30
31 addCommentThread (videoId: number | string, comment: VideoCommentCreate) {
32 const url = VideoCommentService.BASE_VIDEO_URL + videoId + '/comment-threads'
33 const normalizedComment = objectLineFeedToHtml(comment, 'text')
34
35 return this.authHttp.post<{ comment: VideoCommentServerModel }>(url, normalizedComment)
36 .pipe(
37 map(data => this.extractVideoComment(data.comment)),
38 catchError(err => this.restExtractor.handleError(err))
39 )
40 }
41
42 addCommentReply (videoId: number | string, inReplyToCommentId: number, comment: VideoCommentCreate) {
43 const url = VideoCommentService.BASE_VIDEO_URL + videoId + '/comments/' + inReplyToCommentId
44 const normalizedComment = objectLineFeedToHtml(comment, 'text')
45
46 return this.authHttp.post<{ comment: VideoCommentServerModel }>(url, normalizedComment)
47 .pipe(
48 map(data => this.extractVideoComment(data.comment)),
49 catchError(err => this.restExtractor.handleError(err))
50 )
51 }
52
53 getAdminVideoComments (options: {
54 pagination: RestPagination,
55 sort: SortMeta,
56 search?: string
57 }): Observable<ResultList<VideoCommentAdmin>> {
58 const { pagination, sort, search } = options
59 const url = VideoCommentService.BASE_VIDEO_URL + '/comments'
60
61 let params = new HttpParams()
62 params = this.restService.addRestGetParams(params, pagination, sort)
63
64 if (search) {
65 params = this.buildParamsFromSearch(search, params)
66 }
67
68 return this.authHttp.get<ResultList<VideoCommentAdmin>>(url, { params })
69 .pipe(
70 catchError(res => this.restExtractor.handleError(res))
71 )
72 }
73
74 getVideoCommentThreads (parameters: {
75 videoId: number | string,
76 componentPagination: ComponentPaginationLight,
77 sort: string
78 }): Observable<ResultList<VideoComment>> {
79 const { videoId, componentPagination, sort } = parameters
80
81 const pagination = this.restService.componentPaginationToRestPagination(componentPagination)
82
83 let params = new HttpParams()
84 params = this.restService.addRestGetParams(params, pagination, sort)
85
86 const url = VideoCommentService.BASE_VIDEO_URL + videoId + '/comment-threads'
87 return this.authHttp.get<ResultList<VideoComment>>(url, { params })
88 .pipe(
89 map(result => this.extractVideoComments(result)),
90 catchError(err => this.restExtractor.handleError(err))
91 )
92 }
93
94 getVideoThreadComments (parameters: {
95 videoId: number | string,
96 threadId: number
97 }): Observable<VideoCommentThreadTree> {
98 const { videoId, threadId } = parameters
99 const url = `${VideoCommentService.BASE_VIDEO_URL + videoId}/comment-threads/${threadId}`
100
101 return this.authHttp
102 .get<VideoCommentThreadTreeServerModel>(url)
103 .pipe(
104 map(tree => this.extractVideoCommentTree(tree)),
105 catchError(err => this.restExtractor.handleError(err))
106 )
107 }
108
109 deleteVideoComment (videoId: number | string, commentId: number) {
110 const url = `${VideoCommentService.BASE_VIDEO_URL + videoId}/comments/${commentId}`
111
112 return this.authHttp
113 .delete(url)
114 .pipe(
115 map(this.restExtractor.extractDataBool),
116 catchError(err => this.restExtractor.handleError(err))
117 )
118 }
119
120 getVideoCommentsFeeds (videoUUID?: string) {
121 const feeds = [
122 {
123 format: FeedFormat.RSS,
124 label: 'rss 2.0',
125 url: VideoCommentService.BASE_FEEDS_URL + FeedFormat.RSS.toLowerCase()
126 },
127 {
128 format: FeedFormat.ATOM,
129 label: 'atom 1.0',
130 url: VideoCommentService.BASE_FEEDS_URL + FeedFormat.ATOM.toLowerCase()
131 },
132 {
133 format: FeedFormat.JSON,
134 label: 'json 1.0',
135 url: VideoCommentService.BASE_FEEDS_URL + FeedFormat.JSON.toLowerCase()
136 }
137 ]
138
139 if (videoUUID !== undefined) {
140 for (const feed of feeds) {
141 feed.url += '?videoId=' + videoUUID
142 }
143 }
144
145 return feeds
146 }
147
148 private extractVideoComment (videoComment: VideoCommentServerModel) {
149 return new VideoComment(videoComment)
150 }
151
152 private extractVideoComments (result: ResultList<VideoCommentServerModel>) {
153 const videoCommentsJson = result.data
154 const totalComments = result.total
155 const comments: VideoComment[] = []
156
157 for (const videoCommentJson of videoCommentsJson) {
158 comments.push(new VideoComment(videoCommentJson))
159 }
160
161 return { data: comments, total: totalComments }
162 }
163
164 private extractVideoCommentTree (tree: VideoCommentThreadTreeServerModel) {
165 if (!tree) return tree as VideoCommentThreadTree
166
167 tree.comment = new VideoComment(tree.comment)
168 tree.children.forEach(c => this.extractVideoCommentTree(c))
169
170 return tree as VideoCommentThreadTree
171 }
172
173 private buildParamsFromSearch (search: string, params: HttpParams) {
174 const filters = this.restService.parseQueryStringFilter(search, {
175 state: {
176 prefix: 'local:',
177 isBoolean: true,
178 handler: v => {
179 if (v === 'true') return v
180 if (v === 'false') return v
181
182 return undefined
183 }
184 },
185
186 searchAccount: { prefix: 'account:' },
187 searchVideo: { prefix: 'video:' }
188 })
189
190 return this.restService.addObjectParams(params, filters)
191 }
192 }