Add comment filtering by reply count

pull/2367/head
Rigel Kent 2019-12-27 17:02:34 +01:00
parent 6f79be110d
commit c1125bcadc
No known key found for this signature in database
GPG Key ID: 5E53E96A494E452F
8 changed files with 47 additions and 7 deletions

View File

@ -5,3 +5,6 @@ export type VideoSortField = 'name' | '-name'
| 'views' | '-views'
| 'likes' | '-likes'
| 'trending' | '-trending'
export type CommentSortField = 'createdAt' | '-createdAt'
| 'totalReplies' | '-totalReplies'

View File

@ -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<ResultList<VideoComment>> {
const { videoId, componentPagination, sort } = parameters

View File

@ -10,6 +10,16 @@
</div>
<my-feed [syndicationItems]="syndicationItems"></my-feed>
<div ngbDropdown class="d-inline-block ml-4">
<button class="btn btn-sm btn-outline-secondary" id="dropdownSortComments" ngbDropdownToggle i18n>
Sort by
</button>
<div ngbDropdownMenu aria-labelledby="dropdownSortComments">
<button (click)="handleSortChange('-createdAt')" ngbDropdownItem i18n>Most recent first (default)</button>
<button (click)="handleSortChange('-totalReplies')" ngbDropdownItem i18n>Most replies first</button>
</div>
</div>
</div>
<ng-template [ngIf]="video.commentsEnabled === true">

View File

@ -23,6 +23,12 @@
margin-right: 0;
}
#dropdownSortComments {
font-weight: 600;
text-transform: uppercase;
border: none;
}
my-feed {
display: inline-block;
margin-left: 5px;

View File

@ -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)
}

View File

@ -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' ],

View File

@ -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,

View File

@ -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<VideoCommentModel> {
const query = {
offset: start,
limit: count,
order: getSort(sort),
order: getCommentSort(sort),
where: {
videoId,
inReplyToCommentId: null,