]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Add ability to bulk delete comments
authorChocobozzz <me@florianbigard.com>
Fri, 20 Nov 2020 12:55:33 +0000 (13:55 +0100)
committerChocobozzz <me@florianbigard.com>
Fri, 20 Nov 2020 12:59:21 +0000 (13:59 +0100)
client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.html
client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.scss
client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.ts
client/src/app/shared/shared-video-comment/video-comment.service.ts
client/src/sass/primeng-custom.scss

index 330ee24783887cecd0208e635c3fd601aba0467a..8b7c12ba35ca02d395021043723def77d7e8d9c6 100644 (file)
   [showCurrentPageReport]="true" i18n-currentPageReportTemplate
   currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} comments"
   (onPage)="onPage($event)" [expandedRowKeys]="expandedRows"
+  [(selection)]="selectedComments"
 >
   <ng-template pTemplate="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="input-group has-feedback has-clear">
           <div class="input-group-prepend c-hand" ngbDropdown placement="bottom-left auto" container="body">
@@ -42,6 +51,9 @@
 
   <ng-template pTemplate="header">
     <tr>
+      <th style="width: 40px">
+        <p-tableHeaderCheckbox></p-tableHeaderCheckbox>
+      </th>
       <th style="width: 40px"></th>
       <th style="width: 150px;"></th>
       <th style="width: 300px" i18n>Account</th>
   </ng-template>
 
   <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">
         <span class="expander">
           <i [ngClass]="expanded ? 'glyphicon glyphicon-menu-down' : 'glyphicon glyphicon-menu-right'"></i>
index 43983589904bf8c36f30bd685523b0fd3626ca4a..d208944fec52b692955417e7566c728bced71ef6 100644 (file)
@@ -45,7 +45,9 @@ my-global-icon {
   }
 
   a {
-    @include ellipsis
+    @include ellipsis;
+
+    color: pvar(--mainForegroundColor);
   }
 }
 
index 284ec541d919e9300d9b61981030db2b075fd00f..529e28f1168b9d17379d88dbd5def5a5ca79f851 100644 (file)
@@ -1,7 +1,6 @@
 import { SortMeta } from 'primeng/api'
-import { filter } from 'rxjs/operators'
 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 { DropdownAction } from '@app/shared/shared-main'
 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 () {
     return this.auth.getUser()
   }
@@ -78,6 +80,15 @@ export class VideoCommentListComponent extends RestTable implements OnInit, Afte
   ngOnInit () {
     this.initialize()
     this.listenToSearchChange()
+
+    this.bulkCommentActions = [
+      {
+        label: $localize`Delete`,
+        handler: comments => this.removeComments(comments),
+        isDisplayed: () => this.authUser.hasRight(UserRight.REMOVE_ANY_VIDEO_COMMENT),
+        iconName: 'delete'
+      }
+    ]
   }
 
   ngAfterViewInit () {
@@ -92,6 +103,10 @@ export class VideoCommentListComponent extends RestTable implements OnInit, Afte
     return this.markdownRenderer.textMarkdownToHTML(text, true, true)
   }
 
+  isInSelectionMode () {
+    return this.selectedComments.length !== 0
+  }
+
   protected loadData () {
     this.videoCommentService.getAdminVideoComments({
       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) {
     this.videoCommentService.deleteVideoComment(comment.video.id, comment.id)
       .subscribe(
index 1ab996a7647cb260986abd08086c79ca3977d204..c107a33abb5937bb9ee500b108175a2e503cd4f4 100644 (file)
@@ -1,5 +1,6 @@
-import { Observable } from 'rxjs'
-import { catchError, map } from 'rxjs/operators'
+import { SortMeta } from 'primeng/api'
+import { from, Observable } from 'rxjs'
+import { catchError, concatMap, map, toArray } from 'rxjs/operators'
 import { HttpClient, HttpParams } from '@angular/common/http'
 import { Injectable } from '@angular/core'
 import { ComponentPaginationLight, RestExtractor, RestPagination, RestService } from '@app/core'
@@ -15,7 +16,6 @@ import {
 import { environment } from '../../../environments/environment'
 import { VideoCommentThreadTree } from './video-comment-thread-tree.model'
 import { VideoComment } from './video-comment.model'
-import { SortMeta } from 'primeng/api'
 
 @Injectable()
 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) {
     const feeds = [
       {
index a48f797fc6bd3957d23e704f4a0a9d9617a46a3b..ed32a7b38e8be75752aec9e8b602055c8f460916 100644 (file)
@@ -924,7 +924,7 @@ p-toast {
     .notification-block {
       display: flex;
       align-items: center;
-      padding: 10px;
+      padding: 10px 20px;
 
       .message {
         flex-grow: 1;