From 26b7305a232e547709f433a6edf700bf495935d8 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 13 Aug 2018 16:57:13 +0200 Subject: Add blacklist reason field --- .../video-abuse-list.component.html | 2 +- .../video-blacklist-list.component.html | 39 ++++++++----- .../video-blacklist-list.component.scss | 6 ++ .../video-blacklist-list.component.ts | 18 ++++-- .../src/app/shared/forms/form-validators/index.ts | 1 + .../video-blacklist-validators.service.ts | 19 +++++++ client/src/app/shared/shared.module.ts | 5 +- .../video-blacklist/video-blacklist.service.ts | 6 +- client/src/app/shared/video/video-details.model.ts | 2 +- .../modal/video-blacklist.component.html | 31 ++++++++++ .../modal/video-blacklist.component.scss | 6 ++ .../modal/video-blacklist.component.ts | 66 ++++++++++++++++++++++ .../videos/+video-watch/video-watch.component.html | 11 ++-- .../videos/+video-watch/video-watch.component.scss | 4 ++ .../videos/+video-watch/video-watch.component.ts | 27 +++------ .../app/videos/+video-watch/video-watch.module.ts | 2 + client/src/assets/images/global/delete-black.svg | 14 +++++ 17 files changed, 211 insertions(+), 48 deletions(-) create mode 100644 client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.scss create mode 100644 client/src/app/shared/forms/form-validators/video-blacklist-validators.service.ts create mode 100644 client/src/app/videos/+video-watch/modal/video-blacklist.component.html create mode 100644 client/src/app/videos/+video-watch/modal/video-blacklist.component.scss create mode 100644 client/src/app/videos/+video-watch/modal/video-blacklist.component.ts create mode 100644 client/src/assets/images/global/delete-black.svg (limited to 'client/src') diff --git a/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.html b/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.html index 08501d872..aa0e18c70 100644 --- a/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.html +++ b/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.html @@ -9,7 +9,7 @@ - State + State Reason Reporter Created diff --git a/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.html b/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.html index 04f0e3b5c..78989dc58 100644 --- a/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.html +++ b/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.html @@ -4,30 +4,43 @@ - Name - Description - Views + + Video name NSFW UUID - Created - + Date + - + - {{ videoBlacklist.name }} - {{ videoBlacklist.description }} - {{ videoBlacklist.views }} - {{ videoBlacklist.nsfw }} - {{ videoBlacklist.uuid }} + + + + + + + {{ videoBlacklist.video.name }} + {{ videoBlacklist.video.nsfw }} + {{ videoBlacklist.video.uuid }} {{ videoBlacklist.createdAt }} + - + + + + + + + + + Blacklist reason: + {{ videoBlacklist.reason }} diff --git a/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.scss b/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.scss new file mode 100644 index 000000000..5265536ca --- /dev/null +++ b/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.scss @@ -0,0 +1,6 @@ +@import '_variables'; +@import '_mixins'; + +.blacklist-reason-label { + font-weight: $font-semibold; +} \ No newline at end of file diff --git a/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.ts b/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.ts index 143ec8406..00b0ac57e 100644 --- a/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.ts +++ b/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.ts @@ -5,11 +5,12 @@ import { ConfirmService } from '../../../core' import { RestPagination, RestTable, VideoBlacklistService } from '../../../shared' import { BlacklistedVideo } from '../../../../../../shared' import { I18n } from '@ngx-translate/i18n-polyfill' +import { DropdownAction } from '@app/shared/buttons/action-dropdown.component' @Component({ selector: 'my-video-blacklist-list', templateUrl: './video-blacklist-list.component.html', - styleUrls: [] + styleUrls: [ './video-blacklist-list.component.scss' ] }) export class VideoBlacklistListComponent extends RestTable implements OnInit { blacklist: BlacklistedVideo[] = [] @@ -18,6 +19,8 @@ export class VideoBlacklistListComponent extends RestTable implements OnInit { sort: SortMeta = { field: 'createdAt', order: 1 } pagination: RestPagination = { count: this.rowsPerPage, start: 0 } + videoBlacklistActions: DropdownAction[] = [] + constructor ( private notificationsService: NotificationsService, private confirmService: ConfirmService, @@ -25,6 +28,13 @@ export class VideoBlacklistListComponent extends RestTable implements OnInit { private i18n: I18n ) { super() + + this.videoBlacklistActions = [ + { + label: this.i18n('Unblacklist'), + handler: videoBlacklist => this.removeVideoFromBlacklist(videoBlacklist) + } + ] } ngOnInit () { @@ -33,17 +43,17 @@ export class VideoBlacklistListComponent extends RestTable implements OnInit { async removeVideoFromBlacklist (entry: BlacklistedVideo) { const confirmMessage = this.i18n( - 'Do you really want to remove this video from the blacklist ? It will be available again in the videos list.' + 'Do you really want to remove this video from the blacklist? It will be available again in the videos list.' ) const res = await this.confirmService.confirm(confirmMessage, this.i18n('Unblacklist')) if (res === false) return - this.videoBlacklistService.removeVideoFromBlacklist(entry.videoId).subscribe( + this.videoBlacklistService.removeVideoFromBlacklist(entry.video.id).subscribe( () => { this.notificationsService.success( this.i18n('Success'), - this.i18n('Video {{name}} removed from the blacklist.', { name: entry.name }) + this.i18n('Video {{name}} removed from the blacklist.', { name: entry.video.name }) ) this.loadData() }, diff --git a/client/src/app/shared/forms/form-validators/index.ts b/client/src/app/shared/forms/form-validators/index.ts index 60d735ef7..9bc7615ca 100644 --- a/client/src/app/shared/forms/form-validators/index.ts +++ b/client/src/app/shared/forms/form-validators/index.ts @@ -5,6 +5,7 @@ export * from './login-validators.service' export * from './reset-password-validators.service' export * from './user-validators.service' export * from './video-abuse-validators.service' +export * from './video-blacklist-validators.service' export * from './video-channel-validators.service' export * from './video-comment-validators.service' export * from './video-validators.service' diff --git a/client/src/app/shared/forms/form-validators/video-blacklist-validators.service.ts b/client/src/app/shared/forms/form-validators/video-blacklist-validators.service.ts new file mode 100644 index 000000000..07d1f264a --- /dev/null +++ b/client/src/app/shared/forms/form-validators/video-blacklist-validators.service.ts @@ -0,0 +1,19 @@ +import { I18n } from '@ngx-translate/i18n-polyfill' +import { Validators } from '@angular/forms' +import { Injectable } from '@angular/core' +import { BuildFormValidator } from '@app/shared' + +@Injectable() +export class VideoBlacklistValidatorsService { + readonly VIDEO_BLACKLIST_REASON: BuildFormValidator + + constructor (private i18n: I18n) { + this.VIDEO_BLACKLIST_REASON = { + VALIDATORS: [ Validators.minLength(2), Validators.maxLength(300) ], + MESSAGES: { + 'minlength': this.i18n('Blacklist reason must be at least 2 characters long.'), + 'maxlength': this.i18n('Blacklist reason cannot be more than 300 characters long.') + } + } + } +} diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts index ea7f2c887..722415a06 100644 --- a/client/src/app/shared/shared.module.ts +++ b/client/src/app/shared/shared.module.ts @@ -36,7 +36,7 @@ import { ReactiveFileComponent, ResetPasswordValidatorsService, UserValidatorsService, - VideoAbuseValidatorsService, + VideoAbuseValidatorsService, VideoBlacklistValidatorsService, VideoChannelValidatorsService, VideoCommentValidatorsService, VideoValidatorsService @@ -133,6 +133,7 @@ import { NgbDropdownModule, NgbModalModule, NgbPopoverModule, NgbTabsetModule, N MarkdownService, VideoChannelService, VideoCaptionService, + VideoImportService, FormValidatorService, CustomConfigValidatorsService, @@ -144,7 +145,7 @@ import { NgbDropdownModule, NgbModalModule, NgbPopoverModule, NgbTabsetModule, N VideoCommentValidatorsService, VideoValidatorsService, VideoCaptionsValidatorsService, - VideoImportService, + VideoBlacklistValidatorsService, I18nPrimengCalendarService, ScreenService, diff --git a/client/src/app/shared/video-blacklist/video-blacklist.service.ts b/client/src/app/shared/video-blacklist/video-blacklist.service.ts index 040d82c9a..a014260b1 100644 --- a/client/src/app/shared/video-blacklist/video-blacklist.service.ts +++ b/client/src/app/shared/video-blacklist/video-blacklist.service.ts @@ -36,8 +36,10 @@ export class VideoBlacklistService { ) } - blacklistVideo (videoId: number) { - return this.authHttp.post(VideoBlacklistService.BASE_VIDEOS_URL + videoId + '/blacklist', {}) + blacklistVideo (videoId: number, reason?: string) { + const body = reason ? { reason } : {} + + return this.authHttp.post(VideoBlacklistService.BASE_VIDEOS_URL + videoId + '/blacklist', body) .pipe( map(this.restExtractor.extractDataBool), catchError(res => this.restExtractor.handleError(res)) diff --git a/client/src/app/shared/video/video-details.model.ts b/client/src/app/shared/video/video-details.model.ts index e500ad6fc..bdcc0bbba 100644 --- a/client/src/app/shared/video/video-details.model.ts +++ b/client/src/app/shared/video/video-details.model.ts @@ -44,7 +44,7 @@ export class VideoDetails extends Video implements VideoDetailsServerModel { } isBlackistableBy (user: AuthUser) { - return user && user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) === true && this.isLocal === false + return user && user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) === true } isUpdatableBy (user: AuthUser) { diff --git a/client/src/app/videos/+video-watch/modal/video-blacklist.component.html b/client/src/app/videos/+video-watch/modal/video-blacklist.component.html new file mode 100644 index 000000000..c436501b4 --- /dev/null +++ b/client/src/app/videos/+video-watch/modal/video-blacklist.component.html @@ -0,0 +1,31 @@ + + + + + diff --git a/client/src/app/videos/+video-watch/modal/video-blacklist.component.scss b/client/src/app/videos/+video-watch/modal/video-blacklist.component.scss new file mode 100644 index 000000000..afcdb9a16 --- /dev/null +++ b/client/src/app/videos/+video-watch/modal/video-blacklist.component.scss @@ -0,0 +1,6 @@ +@import 'variables'; +@import 'mixins'; + +textarea { + @include peertube-textarea(100%, 100px); +} diff --git a/client/src/app/videos/+video-watch/modal/video-blacklist.component.ts b/client/src/app/videos/+video-watch/modal/video-blacklist.component.ts new file mode 100644 index 000000000..2c123ebed --- /dev/null +++ b/client/src/app/videos/+video-watch/modal/video-blacklist.component.ts @@ -0,0 +1,66 @@ +import { Component, Input, OnInit, ViewChild } from '@angular/core' +import { NotificationsService } from 'angular2-notifications' +import { FormReactive, VideoBlacklistService, VideoBlacklistValidatorsService } from '../../../shared/index' +import { VideoDetails } from '../../../shared/video/video-details.model' +import { I18n } from '@ngx-translate/i18n-polyfill' +import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' +import { NgbModal } from '@ng-bootstrap/ng-bootstrap' +import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref' +import { RedirectService } from '@app/core' + +@Component({ + selector: 'my-video-blacklist', + templateUrl: './video-blacklist.component.html', + styleUrls: [ './video-blacklist.component.scss' ] +}) +export class VideoBlacklistComponent extends FormReactive implements OnInit { + @Input() video: VideoDetails = null + + @ViewChild('modal') modal: NgbModal + + error: string = null + + private openedModal: NgbModalRef + + constructor ( + protected formValidatorService: FormValidatorService, + private modalService: NgbModal, + private videoBlacklistValidatorsService: VideoBlacklistValidatorsService, + private videoBlacklistService: VideoBlacklistService, + private notificationsService: NotificationsService, + private redirectService: RedirectService, + private i18n: I18n + ) { + super() + } + + ngOnInit () { + this.buildForm({ + reason: this.videoBlacklistValidatorsService.VIDEO_BLACKLIST_REASON + }) + } + + show () { + this.openedModal = this.modalService.open(this.modal, { keyboard: false }) + } + + hide () { + this.openedModal.close() + this.openedModal = null + } + + blacklist () { + const reason = this.form.value[ 'reason' ] || undefined + + this.videoBlacklistService.blacklistVideo(this.video.id, reason) + .subscribe( + () => { + this.notificationsService.success(this.i18n('Success'), this.i18n('Video blacklisted.')) + this.hide() + this.redirectService.redirectToHomepage() + }, + + err => this.notificationsService.error(this.i18n('Error'), err.message) + ) + } +} diff --git a/client/src/app/videos/+video-watch/video-watch.component.html b/client/src/app/videos/+video-watch/video-watch.component.html index dd0d628bd..f82f1c554 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.html +++ b/client/src/app/videos/+video-watch/video-watch.component.html @@ -90,16 +90,16 @@ Report - - Blacklist - - Update + + Blacklist + + - Delete + Delete @@ -205,4 +205,5 @@ + diff --git a/client/src/app/videos/+video-watch/video-watch.component.scss b/client/src/app/videos/+video-watch/video-watch.component.scss index 7d269b31f..e63ab7bbd 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.scss +++ b/client/src/app/videos/+video-watch/video-watch.component.scss @@ -258,6 +258,10 @@ &.icon-blacklist { background-image: url('../../../assets/images/video/blacklist.svg'); } + + &.icon-delete { + background-image: url('../../../assets/images/global/delete-black.svg'); + } } } } diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts index 04bcc6cd1..878655d4a 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts @@ -21,6 +21,7 @@ import { MarkdownService } from '../shared' import { VideoDownloadComponent } from './modal/video-download.component' import { VideoReportComponent } from './modal/video-report.component' import { VideoShareComponent } from './modal/video-share.component' +import { VideoBlacklistComponent } from './modal/video-blacklist.component' import { addContextMenu, getVideojsOptions, loadLocale } from '../../../assets/player/peertube-player' import { ServerService } from '@app/core' import { I18n } from '@ngx-translate/i18n-polyfill' @@ -41,6 +42,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { @ViewChild('videoShareModal') videoShareModal: VideoShareComponent @ViewChild('videoReportModal') videoReportModal: VideoReportComponent @ViewChild('videoSupportModal') videoSupportModal: VideoSupportComponent + @ViewChild('videoBlacklistModal') videoBlacklistModal: VideoBlacklistComponent otherVideosDisplayed: Video[] = [] @@ -156,26 +158,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy { } } - async blacklistVideo (event: Event) { - event.preventDefault() - - const res = await this.confirmService.confirm(this.i18n('Do you really want to blacklist this video?'), this.i18n('Blacklist')) - if (res === false) return - - this.videoBlacklistService.blacklistVideo(this.video.id) - .subscribe( - () => { - this.notificationsService.success( - this.i18n('Success'), - this.i18n('Video {{videoName}} had been blacklisted.', { videoName: this.video.name }) - ) - this.redirectService.redirectToHomepage() - }, - - error => this.notificationsService.error(this.i18n('Error'), error.message) - ) - } - showMoreDescription () { if (this.completeVideoDescription === undefined) { return this.loadCompleteDescription() @@ -230,6 +212,11 @@ export class VideoWatchComponent implements OnInit, OnDestroy { this.videoDownloadModal.show() } + showBlacklistModal (event: Event) { + event.preventDefault() + this.videoBlacklistModal.show() + } + isUserLoggedIn () { return this.authService.isLoggedIn() } diff --git a/client/src/app/videos/+video-watch/video-watch.module.ts b/client/src/app/videos/+video-watch/video-watch.module.ts index 09d5133e4..7730919fe 100644 --- a/client/src/app/videos/+video-watch/video-watch.module.ts +++ b/client/src/app/videos/+video-watch/video-watch.module.ts @@ -15,6 +15,7 @@ import { VideoWatchRoutingModule } from './video-watch-routing.module' import { VideoWatchComponent } from './video-watch.component' import { NgxQRCodeModule } from 'ngx-qrcode2' import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap' +import { VideoBlacklistComponent } from '@app/videos/+video-watch/modal/video-blacklist.component' @NgModule({ imports: [ @@ -31,6 +32,7 @@ import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap' VideoDownloadComponent, VideoShareComponent, VideoReportComponent, + VideoBlacklistComponent, VideoSupportComponent, VideoCommentsComponent, VideoCommentAddComponent, diff --git a/client/src/assets/images/global/delete-black.svg b/client/src/assets/images/global/delete-black.svg new file mode 100644 index 000000000..04ddc23aa --- /dev/null +++ b/client/src/assets/images/global/delete-black.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + -- cgit v1.2.3