From d95d15598847c7f020aa056e7e6e0c02d2bbf732 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 1 Jul 2020 16:05:30 +0200 Subject: Use 3 tables to represent abuses --- .../+admin/moderation/video-abuse-list/index.ts | 2 - .../moderation-comment-modal.component.html | 38 --- .../moderation-comment-modal.component.scss | 6 - .../moderation-comment-modal.component.ts | 70 ----- .../video-abuse-details.component.html | 93 ------ .../video-abuse-details.component.ts | 52 ---- .../video-abuse-list.component.html | 149 ---------- .../video-abuse-list.component.scss | 23 -- .../video-abuse-list/video-abuse-list.component.ts | 328 --------------------- 9 files changed, 761 deletions(-) delete mode 100644 client/src/app/+admin/moderation/video-abuse-list/index.ts delete mode 100644 client/src/app/+admin/moderation/video-abuse-list/moderation-comment-modal.component.html delete mode 100644 client/src/app/+admin/moderation/video-abuse-list/moderation-comment-modal.component.scss delete mode 100644 client/src/app/+admin/moderation/video-abuse-list/moderation-comment-modal.component.ts delete mode 100644 client/src/app/+admin/moderation/video-abuse-list/video-abuse-details.component.html delete mode 100644 client/src/app/+admin/moderation/video-abuse-list/video-abuse-details.component.ts delete mode 100644 client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html delete mode 100644 client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.scss delete mode 100644 client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts (limited to 'client/src/app/+admin/moderation/video-abuse-list') diff --git a/client/src/app/+admin/moderation/video-abuse-list/index.ts b/client/src/app/+admin/moderation/video-abuse-list/index.ts deleted file mode 100644 index da7176e52..000000000 --- a/client/src/app/+admin/moderation/video-abuse-list/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './video-abuse-list.component' -export * from './moderation-comment-modal.component' diff --git a/client/src/app/+admin/moderation/video-abuse-list/moderation-comment-modal.component.html b/client/src/app/+admin/moderation/video-abuse-list/moderation-comment-modal.component.html deleted file mode 100644 index 8082e93f4..000000000 --- a/client/src/app/+admin/moderation/video-abuse-list/moderation-comment-modal.component.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - diff --git a/client/src/app/+admin/moderation/video-abuse-list/moderation-comment-modal.component.scss b/client/src/app/+admin/moderation/video-abuse-list/moderation-comment-modal.component.scss deleted file mode 100644 index afcdb9a16..000000000 --- a/client/src/app/+admin/moderation/video-abuse-list/moderation-comment-modal.component.scss +++ /dev/null @@ -1,6 +0,0 @@ -@import 'variables'; -@import 'mixins'; - -textarea { - @include peertube-textarea(100%, 100px); -} diff --git a/client/src/app/+admin/moderation/video-abuse-list/moderation-comment-modal.component.ts b/client/src/app/+admin/moderation/video-abuse-list/moderation-comment-modal.component.ts deleted file mode 100644 index 3cd763ca4..000000000 --- a/client/src/app/+admin/moderation/video-abuse-list/moderation-comment-modal.component.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { Component, EventEmitter, OnInit, Output, ViewChild } from '@angular/core' -import { Notifier } from '@app/core' -import { FormReactive, FormValidatorService, VideoAbuseValidatorsService } from '@app/shared/shared-forms' -import { VideoAbuseService } from '@app/shared/shared-moderation' -import { NgbModal } from '@ng-bootstrap/ng-bootstrap' -import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { VideoAbuse } from '@shared/models' - -@Component({ - selector: 'my-moderation-comment-modal', - templateUrl: './moderation-comment-modal.component.html', - styleUrls: [ './moderation-comment-modal.component.scss' ] -}) -export class ModerationCommentModalComponent extends FormReactive implements OnInit { - @ViewChild('modal', { static: true }) modal: NgbModal - @Output() commentUpdated = new EventEmitter() - - private abuseToComment: VideoAbuse - private openedModal: NgbModalRef - - constructor ( - protected formValidatorService: FormValidatorService, - private modalService: NgbModal, - private notifier: Notifier, - private videoAbuseService: VideoAbuseService, - private videoAbuseValidatorsService: VideoAbuseValidatorsService, - private i18n: I18n - ) { - super() - } - - ngOnInit () { - this.buildForm({ - moderationComment: this.videoAbuseValidatorsService.VIDEO_ABUSE_MODERATION_COMMENT - }) - } - - openModal (abuseToComment: VideoAbuse) { - this.abuseToComment = abuseToComment - this.openedModal = this.modalService.open(this.modal, { centered: true }) - - this.form.patchValue({ - moderationComment: this.abuseToComment.moderationComment - }) - } - - hide () { - this.abuseToComment = undefined - this.openedModal.close() - this.form.reset() - } - - async banUser () { - const moderationComment: string = this.form.value[ 'moderationComment' ] - - this.videoAbuseService.updateVideoAbuse(this.abuseToComment, { moderationComment }) - .subscribe( - () => { - this.notifier.success(this.i18n('Comment updated.')) - - this.commentUpdated.emit(moderationComment) - this.hide() - }, - - err => this.notifier.error(err.message) - ) - } - -} diff --git a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-details.component.html b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-details.component.html deleted file mode 100644 index ec808cdb8..000000000 --- a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-details.component.html +++ /dev/null @@ -1,93 +0,0 @@ - diff --git a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-details.component.ts b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-details.component.ts deleted file mode 100644 index 5db2887fa..000000000 --- a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-details.component.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Component, Input } from '@angular/core' -import { Actor } from '@app/shared/shared-main' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { VideoAbusePredefinedReasonsString } from '../../../../../../shared/models/videos/abuse/video-abuse-reason.model' -import { ProcessedVideoAbuse } from './video-abuse-list.component' -import { durationToString } from '@app/helpers' - -@Component({ - selector: 'my-video-abuse-details', - templateUrl: './video-abuse-details.component.html', - styleUrls: [ '../moderation.component.scss' ] -}) -export class VideoAbuseDetailsComponent { - @Input() videoAbuse: ProcessedVideoAbuse - - private predefinedReasonsTranslations: { [key in VideoAbusePredefinedReasonsString]: string } - - constructor ( - private i18n: I18n - ) { - this.predefinedReasonsTranslations = { - violentOrRepulsive: this.i18n('Violent or Repulsive'), - hatefulOrAbusive: this.i18n('Hateful or Abusive'), - spamOrMisleading: this.i18n('Spam or Misleading'), - privacy: this.i18n('Privacy'), - rights: this.i18n('Rights'), - serverRules: this.i18n('Server rules'), - thumbnails: this.i18n('Thumbnails'), - captions: this.i18n('Captions') - } - } - - get startAt () { - return durationToString(this.videoAbuse.startAt) - } - - get endAt () { - return durationToString(this.videoAbuse.endAt) - } - - getPredefinedReasons () { - if (!this.videoAbuse.predefinedReasons) return [] - return this.videoAbuse.predefinedReasons.map(r => ({ - id: r, - label: this.predefinedReasonsTranslations[r] - })) - } - - switchToDefaultAvatar ($event: Event) { - ($event.target as HTMLImageElement).src = Actor.GET_DEFAULT_AVATAR_URL() - } -} diff --git a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html deleted file mode 100644 index 64641b28a..000000000 --- a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html +++ /dev/null @@ -1,149 +0,0 @@ - - -
-
-
- - - - Clear filters -
-
-
-
- - - - - Reporter - Video - Created - State - - - - - - - - - - - - - - -
- Avatar -
- {{ videoAbuse.reporterAccount.displayName }} - {{ videoAbuse.reporterAccount.nameWithHost }} -
-
-
- - - - -
-
- - - {{ videoAbuse.nth }}/{{ videoAbuse.count }} - -
-
-
- - - {{ videoAbuse.video.name }} -
-
by {{ videoAbuse.video.channel?.displayName }} on {{ videoAbuse.video.channel?.host }}
-
-
-
- - - -
-
- Deleted -
-
-
- {{ videoAbuse.video.name }} - -
-
by {{ videoAbuse.video.channel?.displayName }} on {{ videoAbuse.video.channel?.host }}
-
-
- - - {{ videoAbuse.createdAt | date: 'short' }} - - - - - - - - - - - -
- - - - - - - - - - - - -
- No video abuses found matching current filters. - No video abuses found. -
- - -
-
- - diff --git a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.scss b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.scss deleted file mode 100644 index 8eee15b64..000000000 --- a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.scss +++ /dev/null @@ -1,23 +0,0 @@ -@import 'mixins'; -@import 'miniature'; - -.video-details-date-updated { - font-size: 90%; - margin-top: .1rem; -} - -.video-details-links { - @include disable-default-a-behaviour; -} - -.video-abuse-states .glyphicon-comment { - margin-left: 0.5rem; -} - -.input-group { - @include peertube-input-group(300px); - - .dropdown-toggle::after { - margin-left: 0; - } -} diff --git a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts deleted file mode 100644 index 409dd42c7..000000000 --- a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts +++ /dev/null @@ -1,328 +0,0 @@ -import { SortMeta } from 'primeng/api' -import { filter } from 'rxjs/operators' -import { buildVideoEmbed, buildVideoLink } from 'src/assets/player/utils' -import { environment } from 'src/environments/environment' -import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core' -import { DomSanitizer } from '@angular/platform-browser' -import { ActivatedRoute, Params, 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 { BlocklistService, VideoAbuseService, VideoBlockService } from '@app/shared/shared-moderation' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { VideoAbuse, VideoAbuseState } from '@shared/models' -import { ModerationCommentModalComponent } from './moderation-comment-modal.component' - -export type ProcessedVideoAbuse = VideoAbuse & { - moderationCommentHtml?: string, - reasonHtml?: string - embedHtml?: string - updatedAt?: Date - // override bare server-side definitions with rich client-side definitions - reporterAccount: Account - video: VideoAbuse['video'] & { - channel: VideoAbuse['video']['channel'] & { - ownerAccount: Account - } - } -} - -@Component({ - selector: 'my-video-abuse-list', - templateUrl: './video-abuse-list.component.html', - styleUrls: [ '../moderation.component.scss', './video-abuse-list.component.scss' ] -}) -export class VideoAbuseListComponent extends RestTable implements OnInit, AfterViewInit { - @ViewChild('moderationCommentModal', { static: true }) moderationCommentModal: ModerationCommentModalComponent - - videoAbuses: ProcessedVideoAbuse[] = [] - totalRecords = 0 - sort: SortMeta = { field: 'createdAt', order: 1 } - pagination: RestPagination = { count: this.rowsPerPage, start: 0 } - - videoAbuseActions: DropdownAction[][] = [] - - constructor ( - private notifier: Notifier, - private videoAbuseService: VideoAbuseService, - private blocklistService: BlocklistService, - private videoService: VideoService, - private videoBlocklistService: VideoBlockService, - private confirmService: ConfirmService, - private i18n: I18n, - private markdownRenderer: MarkdownService, - private sanitizer: DomSanitizer, - private route: ActivatedRoute, - private router: Router - ) { - super() - - this.videoAbuseActions = [ - [ - { - label: this.i18n('Internal actions'), - isHeader: true - }, - { - label: this.i18n('Delete report'), - handler: videoAbuse => this.removeVideoAbuse(videoAbuse) - }, - { - label: this.i18n('Add note'), - handler: videoAbuse => this.openModerationCommentModal(videoAbuse), - isDisplayed: videoAbuse => !videoAbuse.moderationComment - }, - { - label: this.i18n('Update note'), - handler: videoAbuse => this.openModerationCommentModal(videoAbuse), - isDisplayed: videoAbuse => !!videoAbuse.moderationComment - }, - { - label: this.i18n('Mark as accepted'), - handler: videoAbuse => this.updateVideoAbuseState(videoAbuse, VideoAbuseState.ACCEPTED), - isDisplayed: videoAbuse => !this.isVideoAbuseAccepted(videoAbuse) - }, - { - label: this.i18n('Mark as rejected'), - handler: videoAbuse => this.updateVideoAbuseState(videoAbuse, VideoAbuseState.REJECTED), - isDisplayed: videoAbuse => !this.isVideoAbuseRejected(videoAbuse) - } - ], - [ - { - label: this.i18n('Actions for the video'), - isHeader: true, - isDisplayed: videoAbuse => !videoAbuse.video.deleted - }, - { - label: this.i18n('Block video'), - isDisplayed: videoAbuse => !videoAbuse.video.deleted && !videoAbuse.video.blacklisted, - handler: videoAbuse => { - this.videoBlocklistService.blockVideo(videoAbuse.video.id, undefined, true) - .subscribe( - () => { - this.notifier.success(this.i18n('Video blocked.')) - - this.updateVideoAbuseState(videoAbuse, VideoAbuseState.ACCEPTED) - }, - - err => this.notifier.error(err.message) - ) - } - }, - { - label: this.i18n('Unblock video'), - isDisplayed: videoAbuse => !videoAbuse.video.deleted && videoAbuse.video.blacklisted, - handler: videoAbuse => { - this.videoBlocklistService.unblockVideo(videoAbuse.video.id) - .subscribe( - () => { - this.notifier.success(this.i18n('Video unblocked.')) - - this.updateVideoAbuseState(videoAbuse, VideoAbuseState.ACCEPTED) - }, - - err => this.notifier.error(err.message) - ) - } - }, - { - label: this.i18n('Delete video'), - isDisplayed: videoAbuse => !videoAbuse.video.deleted, - handler: async videoAbuse => { - const res = await this.confirmService.confirm( - this.i18n('Do you really want to delete this video?'), - this.i18n('Delete') - ) - if (res === false) return - - this.videoService.removeVideo(videoAbuse.video.id) - .subscribe( - () => { - this.notifier.success(this.i18n('Video deleted.')) - - this.updateVideoAbuseState(videoAbuse, VideoAbuseState.ACCEPTED) - }, - - err => this.notifier.error(err.message) - ) - } - } - ], - [ - { - label: this.i18n('Actions for the reporter'), - isHeader: true - }, - { - label: this.i18n('Mute reporter'), - handler: async videoAbuse => { - const account = videoAbuse.reporterAccount as Account - - this.blocklistService.blockAccountByInstance(account) - .subscribe( - () => { - this.notifier.success( - this.i18n('Account {{nameWithHost}} muted by the instance.', { nameWithHost: account.nameWithHost }) - ) - - account.mutedByInstance = true - }, - - err => this.notifier.error(err.message) - ) - } - }, - { - label: this.i18n('Mute server'), - isDisplayed: videoAbuse => !videoAbuse.reporterAccount.userId, - handler: async videoAbuse => { - this.blocklistService.blockServerByInstance(videoAbuse.reporterAccount.host) - .subscribe( - () => { - this.notifier.success( - this.i18n('Server {{host}} muted by the instance.', { host: videoAbuse.reporterAccount.host }) - ) - }, - - err => this.notifier.error(err.message) - ) - } - } - ] - ] - } - - ngOnInit () { - this.initialize() - - this.route.queryParams - .subscribe(params => { - this.search = params.search || '' - - this.setTableFilter(this.search) - this.loadData() - }) - } - - ngAfterViewInit () { - if (this.search) this.setTableFilter(this.search) - } - - getIdentifier () { - return 'VideoAbuseListComponent' - } - - openModerationCommentModal (videoAbuse: VideoAbuse) { - this.moderationCommentModal.openModal(videoAbuse) - } - - 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([ '/admin/moderation/video-abuses/list' ], { queryParams }) - } - - resetTableFilter () { - this.setTableFilter('') - this.setQueryParams('') - this.resetSearch() - } - /* END Table filter functions */ - - isVideoAbuseAccepted (videoAbuse: VideoAbuse) { - return videoAbuse.state.id === VideoAbuseState.ACCEPTED - } - - isVideoAbuseRejected (videoAbuse: VideoAbuse) { - return videoAbuse.state.id === VideoAbuseState.REJECTED - } - - getVideoUrl (videoAbuse: VideoAbuse) { - return Video.buildClientUrl(videoAbuse.video.uuid) - } - - getVideoEmbed (videoAbuse: VideoAbuse) { - return buildVideoEmbed( - buildVideoLink({ - baseUrl: `${environment.embedUrl}/videos/embed/${videoAbuse.video.uuid}`, - title: false, - warningTitle: false, - startTime: videoAbuse.startAt, - stopTime: videoAbuse.endAt - }) - ) - } - - switchToDefaultAvatar ($event: Event) { - ($event.target as HTMLImageElement).src = Actor.GET_DEFAULT_AVATAR_URL() - } - - async removeVideoAbuse (videoAbuse: VideoAbuse) { - const res = await this.confirmService.confirm(this.i18n('Do you really want to delete this abuse report?'), this.i18n('Delete')) - if (res === false) return - - this.videoAbuseService.removeVideoAbuse(videoAbuse).subscribe( - () => { - this.notifier.success(this.i18n('Abuse deleted.')) - this.loadData() - }, - - err => this.notifier.error(err.message) - ) - } - - updateVideoAbuseState (videoAbuse: VideoAbuse, state: VideoAbuseState) { - this.videoAbuseService.updateVideoAbuse(videoAbuse, { state }) - .subscribe( - () => this.loadData(), - - err => this.notifier.error(err.message) - ) - } - - protected loadData () { - return this.videoAbuseService.getVideoAbuses({ - pagination: this.pagination, - sort: this.sort, - search: this.search - }).subscribe( - async resultList => { - this.totalRecords = resultList.total - const videoAbuses = [] - - for (const abuse of resultList.data) { - Object.assign(abuse, { - reasonHtml: await this.toHtml(abuse.reason), - moderationCommentHtml: await this.toHtml(abuse.moderationComment), - embedHtml: this.sanitizer.bypassSecurityTrustHtml(this.getVideoEmbed(abuse)), - reporterAccount: new Account(abuse.reporterAccount) - }) - - if (abuse.video.channel?.ownerAccount) abuse.video.channel.ownerAccount = new Account(abuse.video.channel.ownerAccount) - if (abuse.updatedAt === abuse.createdAt) delete abuse.updatedAt - - videoAbuses.push(abuse as ProcessedVideoAbuse) - } - - this.videoAbuses = videoAbuses - }, - - err => this.notifier.error(err.message) - ) - } - - private toHtml (text: string) { - return this.markdownRenderer.textMarkdownToHTML(text) - } -} -- cgit v1.2.3