diff --git a/client/src/app/shared/video/sort-field.type.ts b/client/src/app/shared/video/sort-field.type.ts index d1088d244..65b24d946 100644 --- a/client/src/app/shared/video/sort-field.type.ts +++ b/client/src/app/shared/video/sort-field.type.ts @@ -5,3 +5,6 @@ export type VideoSortField = 'name' | '-name' | 'views' | '-views' | 'likes' | '-likes' | 'trending' | '-trending' + +export type CommentSortField = 'createdAt' | '-createdAt' + | 'totalReplies' | '-totalReplies' diff --git a/client/src/app/videos/+video-watch/comment/video-comment.service.ts b/client/src/app/videos/+video-watch/comment/video-comment.service.ts index 550d42fa8..72fbf5d25 100644 --- a/client/src/app/videos/+video-watch/comment/video-comment.service.ts +++ b/client/src/app/videos/+video-watch/comment/video-comment.service.ts @@ -12,7 +12,7 @@ import { import { environment } from '../../../../environments/environment' import { RestExtractor, RestService } from '../../../shared/rest' import { ComponentPagination } from '../../../shared/rest/component-pagination.model' -import { VideoSortField } from '../../../shared/video/sort-field.type' +import { CommentSortField } from '../../../shared/video/sort-field.type' import { VideoComment } from './video-comment.model' @Injectable() @@ -51,7 +51,7 @@ export class VideoCommentService { getVideoCommentThreads (parameters: { videoId: number | string, componentPagination: ComponentPagination, - sort: VideoSortField + sort: CommentSortField }): Observable> { const { videoId, componentPagination, sort } = parameters diff --git a/client/src/app/videos/+video-watch/comment/video-comments.component.html b/client/src/app/videos/+video-watch/comment/video-comments.component.html index 5fabb7dfe..e284eab0a 100644 --- a/client/src/app/videos/+video-watch/comment/video-comments.component.html +++ b/client/src/app/videos/+video-watch/comment/video-comments.component.html @@ -10,6 +10,16 @@ + +
+ +
+ + +
+
diff --git a/client/src/app/videos/+video-watch/comment/video-comments.component.scss b/client/src/app/videos/+video-watch/comment/video-comments.component.scss index dde10b068..9e3682295 100644 --- a/client/src/app/videos/+video-watch/comment/video-comments.component.scss +++ b/client/src/app/videos/+video-watch/comment/video-comments.component.scss @@ -23,6 +23,12 @@ margin-right: 0; } +#dropdownSortComments { + font-weight: 600; + text-transform: uppercase; + border: none; +} + my-feed { display: inline-block; margin-left: 5px; diff --git a/client/src/app/videos/+video-watch/comment/video-comments.component.ts b/client/src/app/videos/+video-watch/comment/video-comments.component.ts index e81401553..974c61d6c 100644 --- a/client/src/app/videos/+video-watch/comment/video-comments.component.ts +++ b/client/src/app/videos/+video-watch/comment/video-comments.component.ts @@ -6,7 +6,7 @@ import { VideoCommentThreadTree } from '../../../../../../shared/models/videos/v import { AuthService } from '../../../core/auth' import { ComponentPagination, hasMoreItems } from '../../../shared/rest/component-pagination.model' import { User } from '../../../shared/users' -import { VideoSortField } from '../../../shared/video/sort-field.type' +import { CommentSortField } from '../../../shared/video/sort-field.type' import { VideoDetails } from '../../../shared/video/video-details.model' import { VideoComment } from './video-comment.model' import { VideoCommentService } from './video-comment.service' @@ -28,7 +28,7 @@ export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy { comments: VideoComment[] = [] highlightedThread: VideoComment - sort: VideoSortField = '-createdAt' + sort: CommentSortField = '-createdAt' componentPagination: ComponentPagination = { currentPage: 1, itemsPerPage: 10, @@ -152,6 +152,13 @@ export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy { this.viewReplies(commentTree.comment.id) } + handleSortChange (sort: CommentSortField) { + if (this.sort === sort) return + + this.sort = sort + this.resetVideo() + } + handleTimestampClicked (timestamp: number) { this.timestampClicked.emit(timestamp) } diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 79fcd0edf..1b7b94d74 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts @@ -46,7 +46,7 @@ const SORTABLE_COLUMNS = { VIDEO_ABUSES: [ 'id', 'createdAt', 'state' ], VIDEO_CHANNELS: [ 'id', 'name', 'updatedAt', 'createdAt' ], VIDEO_IMPORTS: [ 'createdAt' ], - VIDEO_COMMENT_THREADS: [ 'createdAt' ], + VIDEO_COMMENT_THREADS: [ 'createdAt', 'totalReplies' ], VIDEO_RATES: [ 'createdAt' ], BLACKLISTS: [ 'id', 'name', 'duration', 'views', 'likes', 'dislikes', 'uuid', 'createdAt' ], FOLLOWERS: [ 'createdAt', 'state', 'score' ], diff --git a/server/models/utils.ts b/server/models/utils.ts index b53a52a05..4199cc443 100644 --- a/server/models/utils.ts +++ b/server/models/utils.ts @@ -22,6 +22,19 @@ function getSort (value: string, lastSort: OrderItem = [ 'id', 'ASC' ]): OrderIt return [ [ finalField, direction ], lastSort ] } +function getCommentSort (value: string, lastSort: OrderItem = [ 'id', 'ASC' ]): OrderItem[] { + const { direction, field } = buildDirectionAndField(value) + + if (field === 'totalReplies') { + return [ + [ Sequelize.literal('"totalReplies"'), direction ], + lastSort + ] + } + + return getSort(value, lastSort) +} + function getVideoSort (value: string, lastSort: OrderItem = [ 'id', 'ASC' ]): OrderItem[] { const { direction, field } = buildDirectionAndField(value) @@ -167,6 +180,7 @@ export { SortType, buildLocalAccountIdsIn, getSort, + getCommentSort, getVideoSort, getBlacklistSort, createSimilarityAttribute, diff --git a/server/models/video/video-comment.ts b/server/models/video/video-comment.ts index 869a42afe..28f011b03 100644 --- a/server/models/video/video-comment.ts +++ b/server/models/video/video-comment.ts @@ -6,7 +6,7 @@ import { isActivityPubUrlValid } from '../../helpers/custom-validators/activityp import { CONSTRAINTS_FIELDS, WEBSERVER } from '../../initializers/constants' import { AccountModel } from '../account/account' import { ActorModel } from '../activitypub/actor' -import { buildBlockedAccountSQL, buildLocalAccountIdsIn, getSort, throwIfNotValid } from '../utils' +import { buildBlockedAccountSQL, buildLocalAccountIdsIn, getCommentSort, throwIfNotValid } from '../utils' import { VideoModel } from './video' import { VideoChannelModel } from './video-channel' import { getServerActor } from '../../helpers/utils' @@ -259,7 +259,7 @@ export class VideoCommentModel extends Model { const query = { offset: start, limit: count, - order: getSort(sort), + order: getCommentSort(sort), where: { videoId, inReplyToCommentId: null,