1 import { Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'
2 import { ActivatedRoute } from '@angular/router'
3 import { ConfirmService } from '@app/core'
4 import { NotificationsService } from 'angular2-notifications'
5 import { Subscription } from 'rxjs/Subscription'
6 import { VideoCommentThreadTree } from '../../../../../../shared/models/videos/video-comment.model'
7 import { AuthService } from '../../../core/auth'
8 import { ComponentPagination } from '../../../shared/rest/component-pagination.model'
9 import { User } from '../../../shared/users'
10 import { SortField } from '../../../shared/video/sort-field.type'
11 import { VideoDetails } from '../../../shared/video/video-details.model'
12 import { VideoComment } from './video-comment.model'
13 import { VideoCommentService } from './video-comment.service'
16 selector: 'my-video-comments',
17 templateUrl: './video-comments.component.html',
18 styleUrls: ['./video-comments.component.scss']
20 export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy {
21 @Input() video: VideoDetails
24 comments: VideoComment[] = []
25 highlightedComment: VideoComment
26 sort: SortField = '-createdAt'
27 componentPagination: ComponentPagination = {
32 inReplyToCommentId: number
33 threadComments: { [ id: number ]: VideoCommentThreadTree } = {}
34 threadLoading: { [ id: number ]: boolean } = {}
36 private sub: Subscription
39 private authService: AuthService,
40 private notificationsService: NotificationsService,
41 private confirmService: ConfirmService,
42 private videoCommentService: VideoCommentService,
43 private activatedRoute: ActivatedRoute
47 // Find highlighted comment in params
48 this.sub = this.activatedRoute.params.subscribe(
50 if (params['commentId']) {
51 const highlightedCommentId = +params['commentId']
52 this.processHighlightedComment(highlightedCommentId)
58 ngOnChanges (changes: SimpleChanges) {
59 if (changes['video']) {
65 if (this.sub) this.sub.unsubscribe()
68 viewReplies (commentId: number, highlightComment = false) {
69 this.threadLoading[commentId] = true
71 this.videoCommentService.getVideoThreadComments(this.video.id, commentId)
74 this.threadComments[commentId] = res
75 this.threadLoading[commentId] = false
77 if (highlightComment) this.highlightedComment = new VideoComment(res.comment)
80 err => this.notificationsService.error('Error', err.message)
85 this.videoCommentService.getVideoCommentThreads(this.video.id, this.componentPagination, this.sort)
88 this.comments = this.comments.concat(res.comments)
89 this.componentPagination.totalItems = res.totalComments
92 err => this.notificationsService.error('Error', err.message)
96 onCommentThreadCreated (comment: VideoComment) {
97 this.comments.unshift(comment)
100 onWantedToReply (comment: VideoComment) {
101 this.inReplyToCommentId = comment.id
105 this.inReplyToCommentId = undefined
108 onThreadCreated (commentTree: VideoCommentThreadTree) {
109 this.viewReplies(commentTree.comment.id)
112 onWantedToDelete (commentToDelete: VideoComment) {
113 let message = 'Do you really want to delete this comment?'
114 if (commentToDelete.totalReplies !== 0) message += `${commentToDelete.totalReplies} would be deleted too.`
116 this.confirmService.confirm(message, 'Delete').subscribe(
118 if (res === false) return
120 this.videoCommentService.deleteVideoComment(commentToDelete.videoId, commentToDelete.id)
123 // Delete the comment in the tree
124 if (commentToDelete.inReplyToCommentId) {
125 const thread = this.threadComments[commentToDelete.threadId]
127 console.error(`Cannot find thread ${commentToDelete.threadId} of the comment to delete ${commentToDelete.id}`)
131 this.deleteLocalCommentThread(thread, commentToDelete)
136 this.comments = this.comments.filter(c => c.id !== commentToDelete.id)
137 this.componentPagination.totalItems--
140 err => this.notificationsService.error('Error', err.message)
147 return this.authService.isLoggedIn()
151 this.componentPagination.currentPage++
153 if (this.hasMoreComments()) {
154 this.loadMoreComments()
158 private hasMoreComments () {
160 if (this.componentPagination.totalItems === 0) return false
163 if (!this.componentPagination.totalItems) return true
165 const maxPage = this.componentPagination.totalItems / this.componentPagination.itemsPerPage
166 return maxPage > this.componentPagination.currentPage
169 private deleteLocalCommentThread (parentComment: VideoCommentThreadTree, commentToDelete: VideoComment) {
170 for (const commentChild of parentComment.children) {
171 if (commentChild.comment.id === commentToDelete.id) {
172 parentComment.children = parentComment.children.filter(c => c.comment.id !== commentToDelete.id)
176 this.deleteLocalCommentThread(commentChild, commentToDelete)
180 private resetVideo () {
181 if (this.video.commentsEnabled === true) {
182 // Reset all our fields
183 this.highlightedComment = null
185 this.threadComments = {}
186 this.threadLoading = {}
187 this.inReplyToCommentId = undefined
188 this.componentPagination.currentPage = 1
189 this.componentPagination.totalItems = null
191 this.loadMoreComments()
195 private processHighlightedComment (highlightedCommentId: number) {
196 this.highlightedComment = this.comments.find(c => c.id === highlightedCommentId)
198 const highlightComment = true
199 this.viewReplies(highlightedCommentId, highlightComment)