Add comment filtering by reply count
This commit is contained in:
parent
6f79be110d
commit
c1125bcadc
|
@ -5,3 +5,6 @@ export type VideoSortField = 'name' | '-name'
|
||||||
| 'views' | '-views'
|
| 'views' | '-views'
|
||||||
| 'likes' | '-likes'
|
| 'likes' | '-likes'
|
||||||
| 'trending' | '-trending'
|
| 'trending' | '-trending'
|
||||||
|
|
||||||
|
export type CommentSortField = 'createdAt' | '-createdAt'
|
||||||
|
| 'totalReplies' | '-totalReplies'
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {
|
||||||
import { environment } from '../../../../environments/environment'
|
import { environment } from '../../../../environments/environment'
|
||||||
import { RestExtractor, RestService } from '../../../shared/rest'
|
import { RestExtractor, RestService } from '../../../shared/rest'
|
||||||
import { ComponentPagination } from '../../../shared/rest/component-pagination.model'
|
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'
|
import { VideoComment } from './video-comment.model'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -51,7 +51,7 @@ export class VideoCommentService {
|
||||||
getVideoCommentThreads (parameters: {
|
getVideoCommentThreads (parameters: {
|
||||||
videoId: number | string,
|
videoId: number | string,
|
||||||
componentPagination: ComponentPagination,
|
componentPagination: ComponentPagination,
|
||||||
sort: VideoSortField
|
sort: CommentSortField
|
||||||
}): Observable<ResultList<VideoComment>> {
|
}): Observable<ResultList<VideoComment>> {
|
||||||
const { videoId, componentPagination, sort } = parameters
|
const { videoId, componentPagination, sort } = parameters
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,16 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<my-feed [syndicationItems]="syndicationItems"></my-feed>
|
<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>
|
</div>
|
||||||
|
|
||||||
<ng-template [ngIf]="video.commentsEnabled === true">
|
<ng-template [ngIf]="video.commentsEnabled === true">
|
||||||
|
|
|
@ -23,6 +23,12 @@
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#dropdownSortComments {
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
my-feed {
|
my-feed {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { VideoCommentThreadTree } from '../../../../../../shared/models/videos/v
|
||||||
import { AuthService } from '../../../core/auth'
|
import { AuthService } from '../../../core/auth'
|
||||||
import { ComponentPagination, hasMoreItems } from '../../../shared/rest/component-pagination.model'
|
import { ComponentPagination, hasMoreItems } from '../../../shared/rest/component-pagination.model'
|
||||||
import { User } from '../../../shared/users'
|
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 { VideoDetails } from '../../../shared/video/video-details.model'
|
||||||
import { VideoComment } from './video-comment.model'
|
import { VideoComment } from './video-comment.model'
|
||||||
import { VideoCommentService } from './video-comment.service'
|
import { VideoCommentService } from './video-comment.service'
|
||||||
|
@ -28,7 +28,7 @@ export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
|
|
||||||
comments: VideoComment[] = []
|
comments: VideoComment[] = []
|
||||||
highlightedThread: VideoComment
|
highlightedThread: VideoComment
|
||||||
sort: VideoSortField = '-createdAt'
|
sort: CommentSortField = '-createdAt'
|
||||||
componentPagination: ComponentPagination = {
|
componentPagination: ComponentPagination = {
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
itemsPerPage: 10,
|
itemsPerPage: 10,
|
||||||
|
@ -152,6 +152,13 @@ export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
this.viewReplies(commentTree.comment.id)
|
this.viewReplies(commentTree.comment.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleSortChange (sort: CommentSortField) {
|
||||||
|
if (this.sort === sort) return
|
||||||
|
|
||||||
|
this.sort = sort
|
||||||
|
this.resetVideo()
|
||||||
|
}
|
||||||
|
|
||||||
handleTimestampClicked (timestamp: number) {
|
handleTimestampClicked (timestamp: number) {
|
||||||
this.timestampClicked.emit(timestamp)
|
this.timestampClicked.emit(timestamp)
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ const SORTABLE_COLUMNS = {
|
||||||
VIDEO_ABUSES: [ 'id', 'createdAt', 'state' ],
|
VIDEO_ABUSES: [ 'id', 'createdAt', 'state' ],
|
||||||
VIDEO_CHANNELS: [ 'id', 'name', 'updatedAt', 'createdAt' ],
|
VIDEO_CHANNELS: [ 'id', 'name', 'updatedAt', 'createdAt' ],
|
||||||
VIDEO_IMPORTS: [ 'createdAt' ],
|
VIDEO_IMPORTS: [ 'createdAt' ],
|
||||||
VIDEO_COMMENT_THREADS: [ 'createdAt' ],
|
VIDEO_COMMENT_THREADS: [ 'createdAt', 'totalReplies' ],
|
||||||
VIDEO_RATES: [ 'createdAt' ],
|
VIDEO_RATES: [ 'createdAt' ],
|
||||||
BLACKLISTS: [ 'id', 'name', 'duration', 'views', 'likes', 'dislikes', 'uuid', 'createdAt' ],
|
BLACKLISTS: [ 'id', 'name', 'duration', 'views', 'likes', 'dislikes', 'uuid', 'createdAt' ],
|
||||||
FOLLOWERS: [ 'createdAt', 'state', 'score' ],
|
FOLLOWERS: [ 'createdAt', 'state', 'score' ],
|
||||||
|
|
|
@ -22,6 +22,19 @@ function getSort (value: string, lastSort: OrderItem = [ 'id', 'ASC' ]): OrderIt
|
||||||
return [ [ finalField, direction ], lastSort ]
|
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[] {
|
function getVideoSort (value: string, lastSort: OrderItem = [ 'id', 'ASC' ]): OrderItem[] {
|
||||||
const { direction, field } = buildDirectionAndField(value)
|
const { direction, field } = buildDirectionAndField(value)
|
||||||
|
|
||||||
|
@ -167,6 +180,7 @@ export {
|
||||||
SortType,
|
SortType,
|
||||||
buildLocalAccountIdsIn,
|
buildLocalAccountIdsIn,
|
||||||
getSort,
|
getSort,
|
||||||
|
getCommentSort,
|
||||||
getVideoSort,
|
getVideoSort,
|
||||||
getBlacklistSort,
|
getBlacklistSort,
|
||||||
createSimilarityAttribute,
|
createSimilarityAttribute,
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { isActivityPubUrlValid } from '../../helpers/custom-validators/activityp
|
||||||
import { CONSTRAINTS_FIELDS, WEBSERVER } from '../../initializers/constants'
|
import { CONSTRAINTS_FIELDS, WEBSERVER } from '../../initializers/constants'
|
||||||
import { AccountModel } from '../account/account'
|
import { AccountModel } from '../account/account'
|
||||||
import { ActorModel } from '../activitypub/actor'
|
import { ActorModel } from '../activitypub/actor'
|
||||||
import { buildBlockedAccountSQL, buildLocalAccountIdsIn, getSort, throwIfNotValid } from '../utils'
|
import { buildBlockedAccountSQL, buildLocalAccountIdsIn, getCommentSort, throwIfNotValid } from '../utils'
|
||||||
import { VideoModel } from './video'
|
import { VideoModel } from './video'
|
||||||
import { VideoChannelModel } from './video-channel'
|
import { VideoChannelModel } from './video-channel'
|
||||||
import { getServerActor } from '../../helpers/utils'
|
import { getServerActor } from '../../helpers/utils'
|
||||||
|
@ -259,7 +259,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
|
||||||
const query = {
|
const query = {
|
||||||
offset: start,
|
offset: start,
|
||||||
limit: count,
|
limit: count,
|
||||||
order: getSort(sort),
|
order: getCommentSort(sort),
|
||||||
where: {
|
where: {
|
||||||
videoId,
|
videoId,
|
||||||
inReplyToCommentId: null,
|
inReplyToCommentId: null,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user