]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts
Support ICU in TS components
[github/Chocobozzz/PeerTube.git] / client / src / app / shared / shared-abuse-list / abuse-list-table.component.ts
index 1d17c9ec99c3b215b99bb1892f1ab3431aa1029a..8781c16f5c3d99ca763370cd4e7d213e71e99b56 100644 (file)
@@ -1,17 +1,15 @@
 import * as debug from 'debug'
 import truncate from 'lodash-es/truncate'
 import { SortMeta } from 'primeng/api'
-import { buildVideoEmbed, buildVideoLink } from 'src/assets/player/utils'
-import { environment } from 'src/environments/environment'
-import { AfterViewInit, Component, OnInit, ViewChild, Input } from '@angular/core'
+import { Component, Input, OnInit, ViewChild } from '@angular/core'
 import { DomSanitizer } from '@angular/platform-browser'
-import { ActivatedRoute, Params, Router } from '@angular/router'
+import { ActivatedRoute, Router } from '@angular/router'
 import { ConfirmService, MarkdownService, Notifier, RestPagination, RestTable } from '@app/core'
 import { Account, Actor, DropdownAction, Video, VideoService } from '@app/shared/shared-main'
 import { AbuseService, BlocklistService, VideoBlockService } from '@app/shared/shared-moderation'
 import { VideoCommentService } from '@app/shared/shared-video-comment'
-import { I18n } from '@ngx-translate/i18n-polyfill'
 import { AbuseState, AdminAbuse } from '@shared/models'
+import { AdvancedInputFilter } from '../shared-forms'
 import { AbuseMessageModalComponent } from './abuse-message-modal.component'
 import { ModerationCommentModalComponent } from './moderation-comment-modal.component'
 import { ProcessedAbuse } from './processed-abuse.model'
@@ -23,9 +21,8 @@ const logger = debug('peertube:moderation:AbuseListTableComponent')
   templateUrl: './abuse-list-table.component.html',
   styleUrls: [ '../shared-moderation/moderation.scss', './abuse-list-table.component.scss' ]
 })
-export class AbuseListTableComponent extends RestTable implements OnInit, AfterViewInit {
+export class AbuseListTableComponent extends RestTable implements OnInit {
   @Input() viewType: 'admin' | 'user'
-  @Input() baseRoute: string
 
   @ViewChild('abuseMessagesModal', { static: true }) abuseMessagesModal: AbuseMessageModalComponent
   @ViewChild('moderationCommentModal', { static: true }) moderationCommentModal: ModerationCommentModalComponent
@@ -37,7 +34,37 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV
 
   abuseActions: DropdownAction<ProcessedAbuse>[][] = []
 
+  inputFilters: AdvancedInputFilter[] = [
+    {
+      title: $localize`Advanced filters`,
+      children: [
+        {
+          value: 'state:pending',
+          label: $localize`Unsolved reports`
+        },
+        {
+          value: 'state:accepted',
+          label: $localize`Accepted reports`
+        },
+        {
+          value: 'state:rejected',
+          label: $localize`Refused reports`
+        },
+        {
+          value: 'videoIs:blacklisted',
+          label: $localize`Reports with blocked videos`
+        },
+        {
+          value: 'videoIs:deleted',
+          label: $localize`Reports with deleted videos`
+        }
+      ]
+    }
+  ]
+
   constructor (
+    protected route: ActivatedRoute,
+    protected router: Router,
     private notifier: Notifier,
     private abuseService: AbuseService,
     private blocklistService: BlocklistService,
@@ -45,11 +72,8 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV
     private videoService: VideoService,
     private videoBlocklistService: VideoBlockService,
     private confirmService: ConfirmService,
-    private i18n: I18n,
     private markdownRenderer: MarkdownService,
-    private sanitizer: DomSanitizer,
-    private route: ActivatedRoute,
-    private router: Router
+    private sanitizer: DomSanitizer
   ) {
     super()
   }
@@ -68,20 +92,6 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV
     ]
 
     this.initialize()
-
-    this.route.queryParams
-      .subscribe(params => {
-        this.search = params.search || ''
-
-        logger('On URL change (search: %s).', this.search)
-
-        this.setTableFilter(this.search)
-        this.loadData()
-      })
-  }
-
-  ngAfterViewInit () {
-    if (this.search) this.setTableFilter(this.search)
   }
 
   isAdminView () {
@@ -97,29 +107,9 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV
   }
 
   onModerationCommentUpdated () {
-    this.loadData()
-  }
-
-  /* Table filter functions */
-  onAbuseSearch (event: Event) {
-    this.onSearch(event)
-    this.setQueryParams((event.target as HTMLInputElement).value)
-  }
-
-  setQueryParams (search: string) {
-    const queryParams: Params = {}
-    if (search) Object.assign(queryParams, { search })
-
-    this.router.navigate([ this.baseRoute ], { queryParams })
+    this.reloadData()
   }
 
-  resetTableFilter () {
-    this.setTableFilter('')
-    this.setQueryParams('')
-    this.resetSearch()
-  }
-  /* END Table filter functions */
-
   isAbuseAccepted (abuse: AdminAbuse) {
     return abuse.state.id === AbuseState.ACCEPTED
   }
@@ -129,54 +119,39 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV
   }
 
   getVideoUrl (abuse: AdminAbuse) {
-    return Video.buildClientUrl(abuse.video.uuid)
+    return Video.buildWatchUrl(abuse.video)
   }
 
   getCommentUrl (abuse: AdminAbuse) {
-    return Video.buildClientUrl(abuse.comment.video.uuid) + ';threadId=' + abuse.comment.threadId
+    return Video.buildWatchUrl(abuse.comment.video) + ';threadId=' + abuse.comment.threadId
   }
 
   getAccountUrl (abuse: ProcessedAbuse) {
-    return '/accounts/' + abuse.flaggedAccount.nameWithHost
-  }
-
-  getVideoEmbed (abuse: AdminAbuse) {
-    return buildVideoEmbed(
-      buildVideoLink({
-        baseUrl: `${environment.embedUrl}/videos/embed/${abuse.video.uuid}`,
-        title: false,
-        warningTitle: false,
-        startTime: abuse.startAt,
-        stopTime: abuse.endAt
-      })
-    )
-  }
-
-  switchToDefaultAvatar ($event: Event) {
-    ($event.target as HTMLImageElement).src = Actor.GET_DEFAULT_AVATAR_URL()
+    return '/a/' + abuse.flaggedAccount.nameWithHost
   }
 
   async removeAbuse (abuse: AdminAbuse) {
-    const res = await this.confirmService.confirm(this.i18n('Do you really want to delete this abuse report?'), this.i18n('Delete'))
+    const res = await this.confirmService.confirm($localize`Do you really want to delete this abuse report?`, $localize`Delete`)
     if (res === false) return
 
-    this.abuseService.removeAbuse(abuse).subscribe(
-      () => {
-        this.notifier.success(this.i18n('Abuse deleted.'))
-        this.loadData()
-      },
+    this.abuseService.removeAbuse(abuse)
+      .subscribe({
+        next: () => {
+          this.notifier.success($localize`Abuse deleted.`)
+          this.reloadData()
+        },
 
-      err => this.notifier.error(err.message)
-    )
+        error: err => this.notifier.error(err.message)
+      })
   }
 
   updateAbuseState (abuse: AdminAbuse, state: AbuseState) {
     this.abuseService.updateAbuse(abuse, { state })
-      .subscribe(
-        () => this.loadData(),
+      .subscribe({
+        next: () => this.reloadData(),
 
-        err => this.notifier.error(err.message)
-      )
+        error: err => this.notifier.error(err.message)
+      })
   }
 
   onCountMessagesUpdated (event: { abuseId: number, countMessages: number }) {
@@ -196,11 +171,12 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV
 
   isLocalAbuse (abuse: AdminAbuse) {
     if (this.viewType === 'user') return true
+    if (!abuse.reporterAccount) return false
 
     return Actor.IS_LOCAL(abuse.reporterAccount.host)
   }
 
-  protected loadData () {
+  protected reloadData () {
     logger('Loading data.')
 
     const options = {
@@ -213,92 +189,90 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV
       ? this.abuseService.getAdminAbuses(options)
       : this.abuseService.getUserAbuses(options)
 
-    return observable.subscribe(
-        async resultList => {
-          this.totalRecords = resultList.total
-
-          this.abuses = []
+    return observable.subscribe({
+      next: async resultList => {
+        this.totalRecords = resultList.total
 
-          for (const a of resultList.data) {
-            const abuse = a as ProcessedAbuse
+        this.abuses = []
 
-            abuse.reasonHtml = await this.toHtml(abuse.reason)
+        for (const a of resultList.data) {
+          const abuse = a as ProcessedAbuse
 
-            if (abuse.moderationComment) {
-              abuse.moderationCommentHtml = await this.toHtml(abuse.moderationComment)
-            }
+          abuse.reasonHtml = await this.toHtml(abuse.reason)
 
-            if (abuse.video) {
-              abuse.embedHtml = this.sanitizer.bypassSecurityTrustHtml(this.getVideoEmbed(abuse))
+          if (abuse.moderationComment) {
+            abuse.moderationCommentHtml = await this.toHtml(abuse.moderationComment)
+          }
 
-              if (abuse.video.channel?.ownerAccount) {
-                abuse.video.channel.ownerAccount = new Account(abuse.video.channel.ownerAccount)
-              }
+          if (abuse.video) {
+            if (abuse.video.channel?.ownerAccount) {
+              abuse.video.channel.ownerAccount = new Account(abuse.video.channel.ownerAccount)
             }
+          }
 
-            if (abuse.comment) {
-              if (abuse.comment.deleted) {
-                abuse.truncatedCommentHtml = abuse.commentHtml = this.i18n('Deleted comment')
-              } else {
-                const truncated = truncate(abuse.comment.text, { length: 100 })
-                abuse.truncatedCommentHtml = await this.markdownRenderer.textMarkdownToHTML(truncated, true)
-                abuse.commentHtml = await this.markdownRenderer.textMarkdownToHTML(abuse.comment.text, true)
-              }
+          if (abuse.comment) {
+            if (abuse.comment.deleted) {
+              abuse.truncatedCommentHtml = abuse.commentHtml = $localize`Deleted comment`
+            } else {
+              const truncated = truncate(abuse.comment.text, { length: 100 })
+              abuse.truncatedCommentHtml = await this.markdownRenderer.textMarkdownToHTML(truncated, true)
+              abuse.commentHtml = await this.markdownRenderer.textMarkdownToHTML(abuse.comment.text, true)
             }
+          }
 
-            if (abuse.reporterAccount) {
-              abuse.reporterAccount = new Account(abuse.reporterAccount)
-            }
+          if (abuse.reporterAccount) {
+            abuse.reporterAccount = new Account(abuse.reporterAccount)
+          }
 
-            if (abuse.flaggedAccount) {
-              abuse.flaggedAccount = new Account(abuse.flaggedAccount)
-            }
+          if (abuse.flaggedAccount) {
+            abuse.flaggedAccount = new Account(abuse.flaggedAccount)
+          }
 
-            if (abuse.updatedAt === abuse.createdAt) delete abuse.updatedAt
+          if (abuse.updatedAt === abuse.createdAt) delete abuse.updatedAt
 
-            this.abuses.push(abuse)
-          }
-        },
+          this.abuses.push(abuse)
+        }
+      },
 
-        err => this.notifier.error(err.message)
-      )
+      error: err => this.notifier.error(err.message)
+    })
   }
 
   private buildInternalActions (): DropdownAction<ProcessedAbuse>[] {
     return [
       {
-        label: this.i18n('Internal actions'),
+        label: $localize`Internal actions`,
         isHeader: true
       },
       {
         label: this.isAdminView()
-          ? this.i18n('Messages with reporter')
-          : this.i18n('Messages with moderators'),
+          ? $localize`Messages with reporter`
+          : $localize`Messages with moderators`,
         handler: abuse => this.openAbuseMessagesModal(abuse),
         isDisplayed: abuse => this.isLocalAbuse(abuse)
       },
       {
-        label: this.i18n('Update note'),
+        label: $localize`Update internal note`,
         handler: abuse => this.openModerationCommentModal(abuse),
         isDisplayed: abuse => this.isAdminView() && !!abuse.moderationComment
       },
       {
-        label: this.i18n('Mark as accepted'),
+        label: $localize`Mark as accepted`,
         handler: abuse => this.updateAbuseState(abuse, AbuseState.ACCEPTED),
         isDisplayed: abuse => this.isAdminView() && !this.isAbuseAccepted(abuse)
       },
       {
-        label: this.i18n('Mark as rejected'),
+        label: $localize`Mark as rejected`,
         handler: abuse => this.updateAbuseState(abuse, AbuseState.REJECTED),
         isDisplayed: abuse => this.isAdminView() && !this.isAbuseRejected(abuse)
       },
       {
-        label: this.i18n('Add internal note'),
+        label: $localize`Add internal note`,
         handler: abuse => this.openModerationCommentModal(abuse),
         isDisplayed: abuse => this.isAdminView() && !abuse.moderationComment
       },
       {
-        label: this.i18n('Delete report'),
+        label: $localize`Delete report`,
         handler: abuse => this.isAdminView() && this.removeAbuse(abuse)
       }
     ]
@@ -309,19 +283,19 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV
 
     return [
       {
-        label: this.i18n('Actions for the flagged account'),
+        label: $localize`Actions for the flagged account`,
         isHeader: true,
         isDisplayed: abuse => abuse.flaggedAccount && !abuse.comment && !abuse.video
       },
 
       {
-        label: this.i18n('Mute account'),
+        label: $localize`Mute account`,
         isDisplayed: abuse => abuse.flaggedAccount && !abuse.comment && !abuse.video,
         handler: abuse => this.muteAccountHelper(abuse.flaggedAccount)
       },
 
       {
-        label: this.i18n('Mute server account'),
+        label: $localize`Mute server account`,
         isDisplayed: abuse => abuse.flaggedAccount && !abuse.comment && !abuse.video,
         handler: abuse => this.muteServerHelper(abuse.flaggedAccount.host)
       }
@@ -333,19 +307,19 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV
 
     return [
       {
-        label: this.i18n('Actions for the reporter'),
+        label: $localize`Actions for the reporter`,
         isHeader: true,
         isDisplayed: abuse => !!abuse.reporterAccount
       },
 
       {
-        label: this.i18n('Mute reporter'),
+        label: $localize`Mute reporter`,
         isDisplayed: abuse => !!abuse.reporterAccount,
         handler: abuse => this.muteAccountHelper(abuse.reporterAccount)
       },
 
       {
-        label: this.i18n('Mute server'),
+        label: $localize`Mute server`,
         isDisplayed: abuse => abuse.reporterAccount && !abuse.reporterAccount.userId,
         handler: abuse => this.muteServerHelper(abuse.reporterAccount.host)
       }
@@ -357,62 +331,62 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV
 
     return [
       {
-        label: this.i18n('Actions for the video'),
+        label: $localize`Actions for the video`,
         isHeader: true,
         isDisplayed: abuse => abuse.video && !abuse.video.deleted
       },
       {
-        label: this.i18n('Block video'),
+        label: $localize`Block video`,
         isDisplayed: abuse => abuse.video && !abuse.video.deleted && !abuse.video.blacklisted,
         handler: abuse => {
-          this.videoBlocklistService.blockVideo(abuse.video.id, undefined, true)
-            .subscribe(
-              () => {
-                this.notifier.success(this.i18n('Video blocked.'))
+          this.videoBlocklistService.blockVideo([ { videoId: abuse.video.id, unfederate: abuse.video.channel.isLocal } ])
+            .subscribe({
+              next: () => {
+                this.notifier.success($localize`Video blocked.`)
 
                 this.updateAbuseState(abuse, AbuseState.ACCEPTED)
               },
 
-              err => this.notifier.error(err.message)
-            )
+              error: err => this.notifier.error(err.message)
+            })
         }
       },
       {
-        label: this.i18n('Unblock video'),
+        label: $localize`Unblock video`,
         isDisplayed: abuse => abuse.video && !abuse.video.deleted && abuse.video.blacklisted,
         handler: abuse => {
           this.videoBlocklistService.unblockVideo(abuse.video.id)
-            .subscribe(
-              () => {
-                this.notifier.success(this.i18n('Video unblocked.'))
+            .subscribe({
+              next: () => {
+                this.notifier.success($localize`Video unblocked.`)
 
                 this.updateAbuseState(abuse, AbuseState.ACCEPTED)
               },
 
-              err => this.notifier.error(err.message)
-            )
+              error: err => this.notifier.error(err.message)
+            })
         }
       },
       {
-        label: this.i18n('Delete video'),
+        label: $localize`Delete video`,
         isDisplayed: abuse => abuse.video && !abuse.video.deleted,
         handler: async abuse => {
           const res = await this.confirmService.confirm(
-            this.i18n('Do you really want to delete this video?'),
-            this.i18n('Delete')
+            $localize`Do you really want to delete this video?`,
+            $localize`Delete`
           )
           if (res === false) return
 
           this.videoService.removeVideo(abuse.video.id)
-            .subscribe(
-              () => {
-                this.notifier.success(this.i18n('Video deleted.'))
+            .subscribe({
+              next: () => {
+                this.notifier.success($localize`Video deleted.`)
 
                 this.updateAbuseState(abuse, AbuseState.ACCEPTED)
               },
 
-              err => this.notifier.error(err.message)
-            )
+              error: err => this.notifier.error(err.message)
+            })
         }
       }
     ]
@@ -423,31 +397,31 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV
 
     return [
       {
-        label: this.i18n('Actions for the comment'),
+        label: $localize`Actions for the comment`,
         isHeader: true,
         isDisplayed: abuse => abuse.comment && !abuse.comment.deleted
       },
 
       {
-        label: this.i18n('Delete comment'),
+        label: $localize`Delete comment`,
         isDisplayed: abuse => abuse.comment && !abuse.comment.deleted,
         handler: async abuse => {
           const res = await this.confirmService.confirm(
-            this.i18n('Do you really want to delete this comment?'),
-            this.i18n('Delete')
+            $localize`Do you really want to delete this comment?`,
+            $localize`Delete`
           )
           if (res === false) return
 
           this.commentService.deleteVideoComment(abuse.comment.video.id, abuse.comment.id)
-            .subscribe(
-              () => {
-                this.notifier.success(this.i18n('Comment deleted.'))
+            .subscribe({
+              next: () => {
+                this.notifier.success($localize`Comment deleted.`)
 
                 this.updateAbuseState(abuse, AbuseState.ACCEPTED)
               },
 
-              err => this.notifier.error(err.message)
-            )
+              error: err => this.notifier.error(err.message)
+            })
         }
       }
     ]
@@ -455,30 +429,25 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV
 
   private muteAccountHelper (account: Account) {
     this.blocklistService.blockAccountByInstance(account)
-      .subscribe(
-        () => {
-          this.notifier.success(
-            this.i18n('Account {{nameWithHost}} muted by the instance.', { nameWithHost: account.nameWithHost })
-          )
-
+      .subscribe({
+        next: () => {
+          this.notifier.success($localize`Account ${account.nameWithHost} muted by the instance.`)
           account.mutedByInstance = true
         },
 
-        err => this.notifier.error(err.message)
-      )
+        error: err => this.notifier.error(err.message)
+      })
   }
 
   private muteServerHelper (host: string) {
     this.blocklistService.blockServerByInstance(host)
-      .subscribe(
-        () => {
-          this.notifier.success(
-            this.i18n('Server {{host}} muted by the instance.', { host: host })
-          )
+      .subscribe({
+        next: () => {
+          this.notifier.success($localize`Server ${host} muted by the instance.`)
         },
 
-        err => this.notifier.error(err.message)
-      )
+        error: err => this.notifier.error(err.message)
+      })
   }
 
   private toHtml (text: string) {