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