From 191764f30b0a812bf3a9dbdc7daf1d5afe25e12a Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 14 Aug 2018 09:08:47 +0200 Subject: Improve blacklist management --- .../video-abuse-list.component.html | 2 +- .../video-abuse-list/video-abuse-list.component.ts | 5 ++++ .../video-blacklist-list.component.html | 11 +++++--- .../video-blacklist-list.component.ts | 13 ++++++--- .../my-account-videos.component.html | 4 +++ .../my-account-videos.component.scss | 17 ++++++++++-- .../+page-not-found/page-not-found.component.scss | 2 +- .../video-blacklist/video-blacklist.service.ts | 6 ++-- client/src/app/shared/video/video-details.model.ts | 6 +++- client/src/app/shared/video/video.model.ts | 9 ++++++ .../videos/+video-watch/video-watch.component.html | 13 +++++++-- .../videos/+video-watch/video-watch.component.scss | 12 ++++++++ .../videos/+video-watch/video-watch.component.ts | 32 +++++++++++++++++++++- 13 files changed, 113 insertions(+), 19 deletions(-) (limited to 'client/src/app') 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 aa0e18c70..f213ab4b0 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 @@ -42,7 +42,7 @@ {{ videoAbuse.createdAt }} - + {{ videoAbuse.video.name }} diff --git a/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.ts b/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.ts index a850c0ec2..377e9c80f 100644 --- a/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.ts +++ b/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.ts @@ -8,6 +8,7 @@ import { I18n } from '@ngx-translate/i18n-polyfill' import { DropdownAction } from '@app/shared/buttons/action-dropdown.component' import { ConfirmService } from '@app/core' import { ModerationCommentModalComponent } from './moderation-comment-modal.component' +import { Video } from '@app/shared/video/video.model' @Component({ selector: 'my-video-abuse-list', @@ -79,6 +80,10 @@ export class VideoAbuseListComponent extends RestTable implements OnInit { return videoAbuse.state.id === VideoAbuseState.REJECTED } + getVideoUrl (videoAbuse: VideoAbuse) { + return Video.buildClientUrl(videoAbuse.video.uuid) + } + async removeVideoAbuse (videoAbuse: VideoAbuse) { const res = await this.confirmService.confirm(this.i18n('Do you really want to delete this abuse?'), this.i18n('Delete')) if (res === false) return 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 78989dc58..05b3a300c 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 @@ -10,8 +10,7 @@ Video name - NSFW - UUID + Sensitive Date @@ -25,9 +24,13 @@ - {{ videoBlacklist.video.name }} + + + {{ videoBlacklist.video.name }} + + + {{ videoBlacklist.video.nsfw }} - {{ videoBlacklist.video.uuid }} {{ videoBlacklist.createdAt }} 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 00b0ac57e..0618252b8 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 @@ -3,9 +3,10 @@ import { SortMeta } from 'primeng/components/common/sortmeta' import { NotificationsService } from 'angular2-notifications' import { ConfirmService } from '../../../core' import { RestPagination, RestTable, VideoBlacklistService } from '../../../shared' -import { BlacklistedVideo } from '../../../../../../shared' +import { VideoBlacklist } from '../../../../../../shared' import { I18n } from '@ngx-translate/i18n-polyfill' import { DropdownAction } from '@app/shared/buttons/action-dropdown.component' +import { Video } from '@app/shared/video/video.model' @Component({ selector: 'my-video-blacklist-list', @@ -13,13 +14,13 @@ import { DropdownAction } from '@app/shared/buttons/action-dropdown.component' styleUrls: [ './video-blacklist-list.component.scss' ] }) export class VideoBlacklistListComponent extends RestTable implements OnInit { - blacklist: BlacklistedVideo[] = [] + blacklist: VideoBlacklist[] = [] totalRecords = 0 rowsPerPage = 10 sort: SortMeta = { field: 'createdAt', order: 1 } pagination: RestPagination = { count: this.rowsPerPage, start: 0 } - videoBlacklistActions: DropdownAction[] = [] + videoBlacklistActions: DropdownAction[] = [] constructor ( private notificationsService: NotificationsService, @@ -41,7 +42,11 @@ export class VideoBlacklistListComponent extends RestTable implements OnInit { this.loadSort() } - async removeVideoFromBlacklist (entry: BlacklistedVideo) { + getVideoUrl (videoBlacklist: VideoBlacklist) { + return Video.buildClientUrl(videoBlacklist.video.uuid) + } + + async removeVideoFromBlacklist (entry: VideoBlacklist) { const confirmMessage = this.i18n( 'Do you really want to remove this video from the blacklist? It will be available again in the videos list.' ) diff --git a/client/src/app/+my-account/my-account-videos/my-account-videos.component.html b/client/src/app/+my-account/my-account-videos/my-account-videos.component.html index 4823e2db9..8a6cb5c32 100644 --- a/client/src/app/+my-account/my-account-videos/my-account-videos.component.html +++ b/client/src/app/+my-account/my-account-videos/my-account-videos.component.html @@ -18,6 +18,10 @@ {{ video.name }} {{ video.createdAt | myFromNow }} - {{ video.views | myNumberFormatter }} views
{{ video.privacy.label }}{{ getStateLabel(video) }}
+
+ Blacklisted + {{ video.blacklistedReason }} +
diff --git a/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss b/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss index 9df28f472..64a04fa20 100644 --- a/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss +++ b/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss @@ -76,12 +76,25 @@ font-weight: $font-semibold; } - .video-info-date-views, .video-info-private { + .video-info-date-views, + .video-info-private, + .video-info-blacklisted { font-size: 13px; - &.video-info-private { + &.video-info-private, + &.video-info-blacklisted .blacklisted-label { font-weight: $font-semibold; } + + &.video-info-blacklisted { + color: red; + + .blacklisted-reason { + &::before { + content: ' - '; + } + } + } } } diff --git a/client/src/app/+page-not-found/page-not-found.component.scss b/client/src/app/+page-not-found/page-not-found.component.scss index 53b6142e1..f3f0354a3 100644 --- a/client/src/app/+page-not-found/page-not-found.component.scss +++ b/client/src/app/+page-not-found/page-not-found.component.scss @@ -2,7 +2,7 @@ div { height: 100%; width: 100%; text-align: center; - margin-top: 150px; + padding-top: 150px; font-size: 32px; } \ No newline at end of file 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 a014260b1..7d39fd4f2 100644 --- a/client/src/app/shared/video-blacklist/video-blacklist.service.ts +++ b/client/src/app/shared/video-blacklist/video-blacklist.service.ts @@ -3,7 +3,7 @@ import { HttpClient, HttpParams } from '@angular/common/http' import { Injectable } from '@angular/core' import { SortMeta } from 'primeng/components/common/sortmeta' import { Observable } from 'rxjs' -import { BlacklistedVideo, ResultList } from '../../../../../shared' +import { VideoBlacklist, ResultList } from '../../../../../shared' import { environment } from '../../../environments/environment' import { RestExtractor, RestPagination, RestService } from '../rest' @@ -17,11 +17,11 @@ export class VideoBlacklistService { private restExtractor: RestExtractor ) {} - listBlacklist (pagination: RestPagination, sort: SortMeta): Observable> { + listBlacklist (pagination: RestPagination, sort: SortMeta): Observable> { let params = new HttpParams() params = this.restService.addRestGetParams(params, pagination, sort) - return this.authHttp.get>(VideoBlacklistService.BASE_VIDEOS_URL + 'blacklist', { params }) + return this.authHttp.get>(VideoBlacklistService.BASE_VIDEOS_URL + 'blacklist', { params }) .pipe( map(res => this.restExtractor.convertResultListDateToHuman(res)), 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 bdcc0bbba..d346f985c 100644 --- a/client/src/app/shared/video/video-details.model.ts +++ b/client/src/app/shared/video/video-details.model.ts @@ -44,7 +44,11 @@ export class VideoDetails extends Video implements VideoDetailsServerModel { } isBlackistableBy (user: AuthUser) { - return user && user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) === true + return this.blacklisted !== true && user && user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) === true + } + + isUnblacklistableBy (user: AuthUser) { + return this.blacklisted === true && user && user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) === true } isUpdatableBy (user: AuthUser) { diff --git a/client/src/app/shared/video/video.model.ts b/client/src/app/shared/video/video.model.ts index 6b1a299ea..ec0afcccb 100644 --- a/client/src/app/shared/video/video.model.ts +++ b/client/src/app/shared/video/video.model.ts @@ -41,6 +41,8 @@ export class Video implements VideoServerModel { waitTranscoding?: boolean state?: VideoConstant scheduledUpdate?: VideoScheduleUpdate + blacklisted?: boolean + blacklistedReason?: string account: { id: number @@ -62,6 +64,10 @@ export class Video implements VideoServerModel { avatar: Avatar } + static buildClientUrl (videoUUID: string) { + return '/videos/watch/' + videoUUID + } + private static createDurationString (duration: number) { const hours = Math.floor(duration / 3600) const minutes = Math.floor((duration % 3600) / 60) @@ -116,6 +122,9 @@ export class Video implements VideoServerModel { this.scheduledUpdate = hash.scheduledUpdate if (this.state) this.state.label = peertubeTranslate(this.state.label, translations) + + this.blacklisted = hash.blacklisted + this.blacklistedReason = hash.blacklistedReason } isVideoNSFWForUser (user: User, serverConfig: ServerConfig) { 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 f82f1c554..8d4a4a5ca 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.html +++ b/client/src/app/videos/+video-watch/video-watch.component.html @@ -1,4 +1,4 @@ -
+
@@ -17,7 +17,12 @@
- This video will be published on {{ video.scheduledUpdate.updateAt | date: 'full' }} + This video will be published on {{ video.scheduledUpdate.updateAt | date: 'full' }}. +
+ +
+
This video is blacklisted.
+ {{ video.blacklistedReason }}
@@ -98,6 +103,10 @@ Blacklist + + Unblacklist + + Delete 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 e63ab7bbd..1354de32e 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.scss +++ b/client/src/app/videos/+video-watch/video-watch.component.scss @@ -1,6 +1,14 @@ @import '_variables'; @import '_mixins'; +.root-row { + flex-direction: column; +} + +.blacklisted-label { + font-weight: $font-semibold; +} + #video-element-wrapper { background-color: #000; display: flex; @@ -259,6 +267,10 @@ background-image: url('../../../assets/images/video/blacklist.svg'); } + &.icon-unblacklist { + background-image: url('../../../assets/images/global/undo.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 878655d4a..bea13ec99 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts @@ -121,7 +121,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy { this.videoCaptionService.listCaptions(uuid) ) .pipe( - catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [ 400, 404 ])) + // If 401, the video is private or blacklisted so redirect to 404 + catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [ 400, 401, 404 ])) ) .subscribe(([ video, captionsResult ]) => { const startTime = this.route.snapshot.queryParams.start @@ -217,6 +218,31 @@ export class VideoWatchComponent implements OnInit, OnDestroy { this.videoBlacklistModal.show() } + async unblacklistVideo (event: Event) { + event.preventDefault() + + const confirmMessage = this.i18n( + '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(this.video.id).subscribe( + () => { + this.notificationsService.success( + this.i18n('Success'), + this.i18n('Video {{name}} removed from the blacklist.', { name: this.video.name }) + ) + + this.video.blacklisted = false + this.video.blacklistedReason = null + }, + + err => this.notificationsService.error(this.i18n('Error'), err.message) + ) + } + isUserLoggedIn () { return this.authService.isLoggedIn() } @@ -229,6 +255,10 @@ export class VideoWatchComponent implements OnInit, OnDestroy { return this.video.isBlackistableBy(this.user) } + isVideoUnblacklistable () { + return this.video.isUnblacklistableBy(this.user) + } + getVideoPoster () { if (!this.video) return '' -- cgit v1.2.3