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