Add ability to bulk delete comments

This commit is contained in:
Chocobozzz 2020-11-20 13:55:33 +01:00
parent 4749078b8a
commit 939917705f
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
5 changed files with 65 additions and 8 deletions

View File

@ -13,9 +13,18 @@
[showCurrentPageReport]="true" i18n-currentPageReportTemplate [showCurrentPageReport]="true" i18n-currentPageReportTemplate
currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} comments" currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} comments"
(onPage)="onPage($event)" [expandedRowKeys]="expandedRows" (onPage)="onPage($event)" [expandedRowKeys]="expandedRows"
[(selection)]="selectedComments"
> >
<ng-template pTemplate="caption"> <ng-template pTemplate="caption">
<div class="caption"> <div class="caption">
<div>
<my-action-dropdown
*ngIf="isInSelectionMode()" i18n-label label="Batch actions" theme="orange"
[actions]="bulkCommentActions" [entry]="selectedComments"
>
</my-action-dropdown>
</div>
<div class="ml-auto"> <div class="ml-auto">
<div class="input-group has-feedback has-clear"> <div class="input-group has-feedback has-clear">
<div class="input-group-prepend c-hand" ngbDropdown placement="bottom-left auto" container="body"> <div class="input-group-prepend c-hand" ngbDropdown placement="bottom-left auto" container="body">
@ -42,6 +51,9 @@
<ng-template pTemplate="header"> <ng-template pTemplate="header">
<tr> <tr>
<th style="width: 40px">
<p-tableHeaderCheckbox></p-tableHeaderCheckbox>
</th>
<th style="width: 40px"></th> <th style="width: 40px"></th>
<th style="width: 150px;"></th> <th style="width: 150px;"></th>
<th style="width: 300px" i18n>Account</th> <th style="width: 300px" i18n>Account</th>
@ -52,7 +64,12 @@
</ng-template> </ng-template>
<ng-template pTemplate="body" let-videoComment let-expanded="expanded"> <ng-template pTemplate="body" let-videoComment let-expanded="expanded">
<tr> <tr [pSelectableRow]="videoComment">
<td class="checkbox-cell">
<p-tableCheckbox [value]="videoComment"></p-tableCheckbox>
</td>
<td class="expand-cell c-hand" [pRowToggler]="videoComment" i18n-ngbTooltip ngbTooltip="More information" placement="top-left" container="body"> <td class="expand-cell c-hand" [pRowToggler]="videoComment" i18n-ngbTooltip ngbTooltip="More information" placement="top-left" container="body">
<span class="expander"> <span class="expander">
<i [ngClass]="expanded ? 'glyphicon glyphicon-menu-down' : 'glyphicon glyphicon-menu-right'"></i> <i [ngClass]="expanded ? 'glyphicon glyphicon-menu-down' : 'glyphicon glyphicon-menu-right'"></i>

View File

@ -45,7 +45,9 @@ my-global-icon {
} }
a { a {
@include ellipsis @include ellipsis;
color: pvar(--mainForegroundColor);
} }
} }

View File

@ -1,7 +1,6 @@
import { SortMeta } from 'primeng/api' import { SortMeta } from 'primeng/api'
import { filter } from 'rxjs/operators'
import { AfterViewInit, Component, OnInit } from '@angular/core' import { AfterViewInit, Component, OnInit } from '@angular/core'
import { ActivatedRoute, Params, Router } from '@angular/router' import { ActivatedRoute, Router } from '@angular/router'
import { AuthService, ConfirmService, MarkdownService, Notifier, RestPagination, RestTable } from '@app/core' import { AuthService, ConfirmService, MarkdownService, Notifier, RestPagination, RestTable } from '@app/core'
import { DropdownAction } from '@app/shared/shared-main' import { DropdownAction } from '@app/shared/shared-main'
import { BulkService } from '@app/shared/shared-moderation' import { BulkService } from '@app/shared/shared-moderation'
@ -41,6 +40,9 @@ export class VideoCommentListComponent extends RestTable implements OnInit, Afte
} }
] ]
selectedComments: VideoCommentAdmin[] = []
bulkCommentActions: DropdownAction<VideoCommentAdmin[]>[] = []
get authUser () { get authUser () {
return this.auth.getUser() return this.auth.getUser()
} }
@ -78,6 +80,15 @@ export class VideoCommentListComponent extends RestTable implements OnInit, Afte
ngOnInit () { ngOnInit () {
this.initialize() this.initialize()
this.listenToSearchChange() this.listenToSearchChange()
this.bulkCommentActions = [
{
label: $localize`Delete`,
handler: comments => this.removeComments(comments),
isDisplayed: () => this.authUser.hasRight(UserRight.REMOVE_ANY_VIDEO_COMMENT),
iconName: 'delete'
}
]
} }
ngAfterViewInit () { ngAfterViewInit () {
@ -92,6 +103,10 @@ export class VideoCommentListComponent extends RestTable implements OnInit, Afte
return this.markdownRenderer.textMarkdownToHTML(text, true, true) return this.markdownRenderer.textMarkdownToHTML(text, true, true)
} }
isInSelectionMode () {
return this.selectedComments.length !== 0
}
protected loadData () { protected loadData () {
this.videoCommentService.getAdminVideoComments({ this.videoCommentService.getAdminVideoComments({
pagination: this.pagination, pagination: this.pagination,
@ -114,6 +129,21 @@ export class VideoCommentListComponent extends RestTable implements OnInit, Afte
) )
} }
private async removeComments (comments: VideoCommentAdmin[]) {
const commentArgs = comments.map(c => ({ videoId: c.video.id, commentId: c.id }))
this.videoCommentService.deleteVideoComments(commentArgs).subscribe(
() => {
this.notifier.success($localize`${commentArgs.length} comments deleted.`)
this.loadData()
},
err => this.notifier.error(err.message),
() => this.selectedComments = []
)
}
private deleteComment (comment: VideoCommentAdmin) { private deleteComment (comment: VideoCommentAdmin) {
this.videoCommentService.deleteVideoComment(comment.video.id, comment.id) this.videoCommentService.deleteVideoComment(comment.video.id, comment.id)
.subscribe( .subscribe(

View File

@ -1,5 +1,6 @@
import { Observable } from 'rxjs' import { SortMeta } from 'primeng/api'
import { catchError, map } from 'rxjs/operators' import { from, Observable } from 'rxjs'
import { catchError, concatMap, map, toArray } from 'rxjs/operators'
import { HttpClient, HttpParams } from '@angular/common/http' import { HttpClient, HttpParams } from '@angular/common/http'
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { ComponentPaginationLight, RestExtractor, RestPagination, RestService } from '@app/core' import { ComponentPaginationLight, RestExtractor, RestPagination, RestService } from '@app/core'
@ -15,7 +16,6 @@ import {
import { environment } from '../../../environments/environment' import { environment } from '../../../environments/environment'
import { VideoCommentThreadTree } from './video-comment-thread-tree.model' import { VideoCommentThreadTree } from './video-comment-thread-tree.model'
import { VideoComment } from './video-comment.model' import { VideoComment } from './video-comment.model'
import { SortMeta } from 'primeng/api'
@Injectable() @Injectable()
export class VideoCommentService { export class VideoCommentService {
@ -118,6 +118,14 @@ export class VideoCommentService {
) )
} }
deleteVideoComments (comments: { videoId: number | string, commentId: number }[]) {
return from(comments)
.pipe(
concatMap(c => this.deleteVideoComment(c.videoId, c.commentId)),
toArray()
)
}
getVideoCommentsFeeds (videoUUID?: string) { getVideoCommentsFeeds (videoUUID?: string) {
const feeds = [ const feeds = [
{ {

View File

@ -924,7 +924,7 @@ p-toast {
.notification-block { .notification-block {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 10px; padding: 10px 20px;
.message { .message {
flex-grow: 1; flex-grow: 1;