rename blacklist to block/blocklist, merge block and auto-block views
authorRigel Kent <sendmemail@rigelk.eu>
Tue, 2 Jun 2020 18:50:42 +0000 (20:50 +0200)
committerRigel Kent <sendmemail@rigelk.eu>
Wed, 10 Jun 2020 19:12:05 +0000 (21:12 +0200)
- also replace whitelist with allowlist
- add advanced filters for video-block-list view
- move icons in video-block-list and video-abuse-list to left side
for visibility
- add robot icon to depict automated nature of a block in
video-block-list

resolves #2790

75 files changed:
client/src/app/+admin/admin.component.ts
client/src/app/+admin/admin.module.ts
client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
client/src/app/+admin/moderation/index.ts
client/src/app/+admin/moderation/moderation.component.html
client/src/app/+admin/moderation/moderation.component.ts
client/src/app/+admin/moderation/moderation.routes.ts
client/src/app/+admin/moderation/video-abuse-list/video-abuse-details.component.html
client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html
client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts
client/src/app/+admin/moderation/video-auto-blacklist-list/index.ts [deleted file]
client/src/app/+admin/moderation/video-auto-blacklist-list/video-auto-blacklist-list.component.html [deleted file]
client/src/app/+admin/moderation/video-auto-blacklist-list/video-auto-blacklist-list.component.scss [deleted file]
client/src/app/+admin/moderation/video-auto-blacklist-list/video-auto-blacklist-list.component.ts [deleted file]
client/src/app/+admin/moderation/video-blacklist-list/index.ts [deleted file]
client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.html [deleted file]
client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.ts [deleted file]
client/src/app/+admin/moderation/video-block-list/index.ts [new file with mode: 0644]
client/src/app/+admin/moderation/video-block-list/video-block-list.component.html [new file with mode: 0644]
client/src/app/+admin/moderation/video-block-list/video-block-list.component.scss [new file with mode: 0644]
client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts [new file with mode: 0644]
client/src/app/+admin/users/user-edit/user-edit.ts
client/src/app/+admin/users/user-edit/user-update.component.ts
client/src/app/+my-account/my-account-history/my-account-history.component.html
client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts
client/src/app/menu/menu.component.ts
client/src/app/search/search.component.html
client/src/app/shared/forms/form-validators/index.ts
client/src/app/shared/forms/form-validators/video-blacklist-validators.service.ts [deleted file]
client/src/app/shared/forms/form-validators/video-block-validators.service.ts [new file with mode: 0644]
client/src/app/shared/images/global-icon.component.ts
client/src/app/shared/index.ts
client/src/app/shared/shared.module.ts
client/src/app/shared/users/user-notification.model.ts
client/src/app/shared/users/user-notifications.component.html
client/src/app/shared/video-blacklist/index.ts [deleted file]
client/src/app/shared/video-blacklist/video-blacklist.service.ts [deleted file]
client/src/app/shared/video-block/index.ts [new file with mode: 0644]
client/src/app/shared/video-block/video-block.service.ts [new file with mode: 0644]
client/src/app/shared/video/abstract-video-list.html
client/src/app/shared/video/modals/video-blacklist.component.html [deleted file]
client/src/app/shared/video/modals/video-blacklist.component.scss [deleted file]
client/src/app/shared/video/modals/video-blacklist.component.ts [deleted file]
client/src/app/shared/video/modals/video-block.component.html [new file with mode: 0644]
client/src/app/shared/video/modals/video-block.component.scss [new file with mode: 0644]
client/src/app/shared/video/modals/video-block.component.ts [new file with mode: 0644]
client/src/app/shared/video/video-actions-dropdown.component.html
client/src/app/shared/video/video-actions-dropdown.component.ts
client/src/app/shared/video/video-miniature.component.html
client/src/app/shared/video/video-miniature.component.scss
client/src/app/shared/video/video-miniature.component.ts
client/src/app/shared/video/video.model.ts
client/src/app/videos/+video-watch/video-watch.component.html
client/src/app/videos/+video-watch/video-watch.component.scss
client/src/app/videos/+video-watch/video-watch.component.ts
client/src/app/videos/recommendations/recommended-videos.component.html
client/src/assets/images/global/robot.svg [new file with mode: 0644]
server/controllers/api/videos/blacklist.ts
server/helpers/custom-validators/video-blacklist.ts
server/initializers/migrations/0350-video-blacklist-type.ts
server/lib/notifier.ts
server/lib/video-blacklist.ts
server/models/account/user.ts
server/models/video/video-blacklist.ts
server/tests/api/check-params/users.ts
server/tests/api/check-params/video-blacklist.ts
server/tests/api/users/users.ts
server/tests/api/videos/video-blacklist.ts
shared/extra-utils/users/user-notifications.ts
shared/extra-utils/videos/video-blacklist.ts
shared/models/users/user-flag.model.ts
shared/models/users/user-notification.model.ts
shared/models/users/user-right.enum.ts
shared/models/users/user-role.ts
shared/models/videos/blacklist/video-blacklist.model.ts

index 9662522dc682db44d84a053622358976c5635edd..4cf3da0e86debdc9dadba6d2b222ae3ae88aa845 100644 (file)
@@ -18,7 +18,7 @@ export class AdminComponent implements OnInit {
   ngOnInit () {
     if (this.hasUsersRight()) this.items.push({ label: this.i18n('Users'), routerLink: '/admin/users' })
     if (this.hasServerFollowRight()) this.items.push({ label: this.i18n('Follows & redundancies'), routerLink: '/admin/follows' })
-    if (this.hasVideoAbusesRight() || this.hasVideoBlacklistRight()) this.items.push({ label: this.i18n('Moderation'), routerLink: '/admin/moderation' })
+    if (this.hasVideoAbusesRight() || this.hasVideoBlocklistRight()) this.items.push({ label: this.i18n('Moderation'), routerLink: '/admin/moderation' })
     if (this.hasConfigRight()) this.items.push({ label: this.i18n('Configuration'), routerLink: '/admin/config' })
     if (this.hasPluginsRight()) this.items.push({ label: this.i18n('Plugins/Themes'), routerLink: '/admin/plugins' })
     if (this.hasJobsRight() || this.hasLogsRight() || this.hasDebugRight()) this.items.push({ label: this.i18n('System'), routerLink: '/admin/system' })
@@ -36,8 +36,8 @@ export class AdminComponent implements OnInit {
     return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_ABUSES)
   }
 
-  hasVideoBlacklistRight () {
-    return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)
+  hasVideoBlocklistRight () {
+    return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_BLOCKS)
   }
 
   hasConfigRight () {
index d04313c0a170d5c7f719817d30f9a8eb0b4e17ff..eb073f70930fd28ff249df20bf834a0aad983e63 100644 (file)
@@ -11,8 +11,7 @@ import { UserCreateComponent, UserListComponent, UserPasswordComponent, UsersCom
 import {
   ModerationCommentModalComponent,
   VideoAbuseListComponent,
-  VideoAutoBlacklistListComponent,
-  VideoBlacklistListComponent
+  VideoBlockListComponent
 } from './moderation'
 import { ModerationComponent } from '@app/+admin/moderation/moderation.component'
 import { RedundancyCheckboxComponent } from '@app/+admin/follows/shared/redundancy-checkbox.component'
@@ -59,10 +58,9 @@ import { VideoAbuseDetailsComponent } from './moderation/video-abuse-list/video-
     UserListComponent,
 
     ModerationComponent,
-    VideoBlacklistListComponent,
+    VideoBlockListComponent,
     VideoAbuseListComponent,
     VideoAbuseDetailsComponent,
-    VideoAutoBlacklistListComponent,
     ModerationCommentModalComponent,
     InstanceServerBlocklistComponent,
     InstanceAccountBlocklistComponent,
index 981b6685fd71320faa0663d2b76c458cb29dd760..52c759fb7e03adb70fe23034c9835adfa6f8bbe2 100644 (file)
                   <div class="form-group">
                     <my-peertube-checkbox
                       inputName="autoBlacklistVideosOfUsersEnabled" formControlName="enabled"
-                      i18n-labelText labelText="Blacklist new videos automatically"
+                      i18n-labelText labelText="Block new videos automatically"
                     >
                     <ng-container ngProjectAs="description">
                       <span i18n>Unless a user is marked as trusted, their videos will stay private until a moderator reviews them.</span>
                 <div class="form-group">
                   <my-peertube-checkbox inputName="servicesTwitterWhitelisted" formControlName="whitelisted">
                     <ng-template ptTemplate="label">
-                      <ng-container i18n>Instance whitelisted by Twitter</ng-container>
+                      <ng-container i18n>Instance allowed by Twitter</ng-container>
                     </ng-template>
 
                     <ng-template ptTemplate="help">
                       <ng-container i18n>
-                        If your instance is whitelisted by Twitter, a video player will be embedded in the Twitter feed on PeerTube video share.<br />
-                        If the instance is not whitelisted, we use an image link card that will redirect on your PeerTube instance.<br /><br />
+                        If your instance is explicitly allowed by Twitter, a video player will be embedded in the Twitter feed on PeerTube video share.<br />
+                        If the instance is not, we use an image link card that will redirect on your PeerTube instance.<br /><br />
                         Check this checkbox, save the configuration and test with a video URL of your instance (https://example.com/videos/watch/blabla) on
                         <a target='_blank' rel='noopener noreferrer' href='https://cards-dev.twitter.com/validator'>https://cards-dev.twitter.com/validator</a>
-                        to see if you instance is whitelisted.
+                        to see if you instance is allowed.
                       </ng-container>
                     </ng-template>
                   </my-peertube-checkbox>
index 3c683a28cc75ee88b1a13db23528b788c2c76150..e99244b745d4d8c3cb875807e00e360cd3c73ef6 100644 (file)
@@ -1,5 +1,4 @@
 export * from './video-abuse-list'
-export * from './video-auto-blacklist-list'
-export * from './video-blacklist-list'
+export * from './video-block-list'
 export * from './moderation.component'
 export * from './moderation.routes'
index b70027957fcf4f79d94ef728a54a11960cf3929e..09f149c0e9218382dd12a1db31737f2af21dc547 100644 (file)
@@ -2,11 +2,9 @@
   <div i18n class="form-sub-title">Moderation</div>
 
   <div class="admin-sub-nav">
-    <a *ngIf="hasVideoAbusesRight()" i18n routerLink="video-abuses/list" routerLinkActive="active">Video abuses</a>
+    <a *ngIf="hasVideoAbusesRight()" i18n routerLink="video-abuses/list" routerLinkActive="active">Video reports</a>
 
-    <a *ngIf="hasVideoBlacklistRight()" i18n routerLink="video-blacklist/list" routerLinkActive="active">{{ autoBlacklistVideosEnabled ? 'Manually blacklisted videos' : 'Blacklisted videos' }}</a>
-
-    <a *ngIf="autoBlacklistVideosEnabled && hasVideoBlacklistRight()" i18n routerLink="video-auto-blacklist/list" routerLinkActive="active">Auto-blacklisted videos</a>
+    <a *ngIf="hasVideoBlocklistRight()" i18n routerLink="video-blocks/list" routerLinkActive="active">Video blocks</a>
 
     <a *ngIf="hasAccountsBlocklistRight()" i18n routerLink="blocklist/accounts" routerLinkActive="active">Muted accounts</a>
 
index 7744deb06ba2d768d6e332dfc7c34fa798627d98..d48305eedf5cf161208103eb3f06e679657396b6 100644 (file)
@@ -7,7 +7,7 @@ import { AuthService, ServerService } from '@app/core'
   styleUrls: [ './moderation.component.scss' ]
 })
 export class ModerationComponent implements OnInit {
-  autoBlacklistVideosEnabled = false
+  autoBlockVideosEnabled = false
 
   constructor (
     private auth: AuthService,
@@ -16,7 +16,7 @@ export class ModerationComponent implements OnInit {
 
   ngOnInit (): void {
     this.serverService.getConfig()
-      .subscribe(config => this.autoBlacklistVideosEnabled = config.autoBlacklist.videos.ofUsers.enabled)
+      .subscribe(config => this.autoBlockVideosEnabled = config.autoBlacklist.videos.ofUsers.enabled)
 
   }
 
@@ -24,8 +24,8 @@ export class ModerationComponent implements OnInit {
     return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_ABUSES)
   }
 
-  hasVideoBlacklistRight () {
-    return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)
+  hasVideoBlocklistRight () {
+    return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_BLOCKS)
   }
 
   hasAccountsBlocklistRight () {
index a024f2bee58f6c40987b3a95ded097da0660cfe0..aeb555c4a89d118a5831a504363a1d1840decedc 100644 (file)
@@ -2,8 +2,7 @@ import { Routes } from '@angular/router'
 import { UserRight } from '../../../../../shared'
 import { UserRightGuard } from '@app/core'
 import { VideoAbuseListComponent } from '@app/+admin/moderation/video-abuse-list'
-import { VideoBlacklistListComponent } from '@app/+admin/moderation/video-blacklist-list'
-import { VideoAutoBlacklistListComponent } from '@app/+admin/moderation/video-auto-blacklist-list'
+import { VideoBlockListComponent } from '@app/+admin/moderation/video-block-list'
 import { ModerationComponent } from '@app/+admin/moderation/moderation.component'
 import { InstanceAccountBlocklistComponent, InstanceServerBlocklistComponent } from '@app/+admin/moderation/instance-blocklist'
 
@@ -22,16 +21,6 @@ export const ModerationRoutes: Routes = [
         redirectTo: 'video-abuses/list',
         pathMatch: 'full'
       },
-      {
-        path: 'video-blacklist',
-        redirectTo: 'video-blacklist/list',
-        pathMatch: 'full'
-      },
-      {
-        path: 'video-auto-blacklist',
-        redirectTo: 'video-auto-blacklist/list',
-        pathMatch: 'full'
-      },
       {
         path: 'video-abuses/list',
         component: VideoAbuseListComponent,
@@ -39,29 +28,38 @@ export const ModerationRoutes: Routes = [
         data: {
           userRight: UserRight.MANAGE_VIDEO_ABUSES,
           meta: {
-            title: 'Video abuses list'
+            title: 'Video reports'
           }
         }
       },
+      {
+        path: 'video-blacklist',
+        redirectTo: 'video-blocks/list',
+        pathMatch: 'full'
+      },
+      {
+        path: 'video-auto-blacklist',
+        redirectTo: 'video-blocks/list',
+        pathMatch: 'full'
+      },
       {
         path: 'video-auto-blacklist/list',
-        component: VideoAutoBlacklistListComponent,
-        canActivate: [ UserRightGuard ],
-        data: {
-          userRight: UserRight.MANAGE_VIDEO_BLACKLIST,
-          meta: {
-            title: 'Auto-blacklisted videos'
-          }
-        }
+        redirectTo: 'video-blocks/list',
+        pathMatch: 'full'
+      },
+      {
+        path: 'video-blacklist',
+        redirectTo: 'video-blocks/list',
+        pathMatch: 'full'
       },
       {
-        path: 'video-blacklist/list',
-        component: VideoBlacklistListComponent,
+        path: 'video-blocks/list',
+        component: VideoBlockListComponent,
         canActivate: [ UserRightGuard ],
         data: {
-          userRight: UserRight.MANAGE_VIDEO_BLACKLIST,
+          userRight: UserRight.MANAGE_VIDEO_BLOCKS,
           meta: {
-            title: 'Blacklisted videos'
+            title: 'Videos blocked'
           }
         }
       },
index 2abcc06695f52d2c474cc214804c8685c722f122..453a282d1c8ed30dda85fcc035f4f9b3f2d84712 100644 (file)
@@ -69,7 +69,7 @@
     <div class="screenratio">
       <div *ngIf="videoAbuse.video.deleted || videoAbuse.video.blacklisted">
         <span i18n *ngIf="videoAbuse.video.deleted">The video was deleted</span>
-        <span i18n *ngIf="!videoAbuse.video.deleted">The video was blacklisted</span>
+        <span i18n *ngIf="!videoAbuse.video.deleted">The video was blocked</span>
       </div>
       <div *ngIf="!videoAbuse.video.deleted && !videoAbuse.video.blacklisted" [innerHTML]="videoAbuse.embedHtml"></div>
     </div>
index d30475794d2b583ff6e0e7f474c467e224663031..df15999ec7365b5daebd88af0c4b522fecbbfc1b 100644 (file)
@@ -19,7 +19,7 @@
               <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'state:pending' }" class="dropdown-item" i18n>Unsolved reports</a>
               <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'state:accepted' }" class="dropdown-item" i18n>Accepted reports</a>
               <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'state:rejected' }" class="dropdown-item" i18n>Refused reports</a>
-              <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'videoIs:blacklisted' }" class="dropdown-item" i18n>Reports with blacklisted videos</a>
+              <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'videoIs:blacklisted' }" class="dropdown-item" i18n>Reports with blocked videos</a>
               <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'videoIs:deleted' }" class="dropdown-item" i18n>Reports with deleted videos</a>
             </div>
           </div>
@@ -84,9 +84,9 @@
             </div>
             <div class="video-table-video-text">
               <div>
-                {{ videoAbuse.video.name }}
                 <span *ngIf="!videoAbuse.video.blacklisted" class="glyphicon glyphicon-new-window"></span>
-                <span *ngIf="videoAbuse.video.blacklisted" i18n-title title="Video was blacklisted" class="glyphicon glyphicon-ban-circle"></span>
+                <span *ngIf="videoAbuse.video.blacklisted" i18n-title title="The video was blocked" class="glyphicon glyphicon-ban-circle"></span>
+                {{ videoAbuse.video.name }}
               </div>
               <div class="text-muted" i18n>by {{ videoAbuse.video.channel?.displayName }} on {{ videoAbuse.video.channel?.host }} </div>
             </div>
index 39f619cc35f2169950d057e809ce4e73670df490..ca37bccf30e975585b346e05ba9338cd68ec9cb8 100644 (file)
@@ -3,7 +3,7 @@ import { Account } from '@app/shared/account/account.model'
 import { Notifier } from '@app/core'
 import { SortMeta } from 'primeng/api'
 import { VideoAbuse, VideoAbuseState } from '../../../../../../shared'
-import { RestPagination, RestTable, VideoAbuseService, VideoBlacklistService } from '../../../shared'
+import { RestPagination, RestTable, VideoAbuseService, VideoBlockService } from '../../../shared'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { DropdownAction } from '../../../shared/buttons/action-dropdown.component'
 import { ConfirmService } from '../../../core/index'
@@ -53,7 +53,7 @@ export class VideoAbuseListComponent extends RestTable implements OnInit, AfterV
     private videoAbuseService: VideoAbuseService,
     private blocklistService: BlocklistService,
     private videoService: VideoService,
-    private videoBlacklistService: VideoBlacklistService,
+    private videoBlocklistService: VideoBlockService,
     private confirmService: ConfirmService,
     private i18n: I18n,
     private markdownRenderer: MarkdownService,
@@ -101,13 +101,13 @@ export class VideoAbuseListComponent extends RestTable implements OnInit, AfterV
           isDisplayed: videoAbuse => !videoAbuse.video.deleted
         },
         {
-          label: this.i18n('Blacklist video'),
+          label: this.i18n('Block video'),
           isDisplayed: videoAbuse => !videoAbuse.video.deleted && !videoAbuse.video.blacklisted,
           handler: videoAbuse => {
-            this.videoBlacklistService.blacklistVideo(videoAbuse.video.id, undefined, true)
+            this.videoBlocklistService.blockVideo(videoAbuse.video.id, undefined, true)
               .subscribe(
                 () => {
-                  this.notifier.success(this.i18n('Video blacklisted.'))
+                  this.notifier.success(this.i18n('Video blocklisted.'))
 
                   this.updateVideoAbuseState(videoAbuse, VideoAbuseState.ACCEPTED)
                 },
@@ -117,13 +117,13 @@ export class VideoAbuseListComponent extends RestTable implements OnInit, AfterV
           }
         },
         {
-          label: this.i18n('Unblacklist video'),
+          label: this.i18n('Unblock video'),
           isDisplayed: videoAbuse => !videoAbuse.video.deleted && videoAbuse.video.blacklisted,
           handler: videoAbuse => {
-            this.videoBlacklistService.removeVideoFromBlacklist(videoAbuse.video.id)
+            this.videoBlocklistService.unblockVideo(videoAbuse.video.id)
               .subscribe(
                 () => {
-                  this.notifier.success(this.i18n('Video unblacklisted.'))
+                  this.notifier.success(this.i18n('Video unblocklisted.'))
 
                   this.updateVideoAbuseState(videoAbuse, VideoAbuseState.ACCEPTED)
                 },
@@ -292,7 +292,6 @@ export class VideoAbuseListComponent extends RestTable implements OnInit, AfterV
 
         err => this.notifier.error(err.message)
       )
-
   }
 
   protected loadData () {
diff --git a/client/src/app/+admin/moderation/video-auto-blacklist-list/index.ts b/client/src/app/+admin/moderation/video-auto-blacklist-list/index.ts
deleted file mode 100644 (file)
index e3522f6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-export * from './video-auto-blacklist-list.component'
diff --git a/client/src/app/+admin/moderation/video-auto-blacklist-list/video-auto-blacklist-list.component.html b/client/src/app/+admin/moderation/video-auto-blacklist-list/video-auto-blacklist-list.component.html
deleted file mode 100644 (file)
index e2193b6..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-<my-videos-selection
-  [pagination]="pagination"
-  [(selection)]="selection"
-  [(videosModel)]="videos"
-  [miniatureDisplayOptions]="miniatureDisplayOptions"
-  [titlePage]="titlePage"
-  [getVideosObservableFunction]="getVideosObservableFunction"
->
-  <ng-template ptTemplate="globalButtons">
-    <span class="action-button action-button-unblacklist-selection" (click)="removeSelectedVideosFromBlacklist()">
-      <my-global-icon iconName="tick"></my-global-icon>
-      <ng-container i18n>Unblacklist</ng-container>
-    </span>
-  </ng-template>
-
-  <ng-template ptTemplate="rowButtons" let-video>
-    <my-button i18n-label label="Unblacklist" icon="tick" (click)="removeVideoFromBlacklist(video)"></my-button>
-  </ng-template>
-
-</my-videos-selection>
diff --git a/client/src/app/+admin/moderation/video-auto-blacklist-list/video-auto-blacklist-list.component.scss b/client/src/app/+admin/moderation/video-auto-blacklist-list/video-auto-blacklist-list.component.scss
deleted file mode 100644 (file)
index 85ebc60..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-@import '_variables';
-@import '_mixins';
-
-.action-button-unblacklist-selection {
-  display: inline-block;
-
-  @include peertube-button;
-  @include orange-button;
-  @include button-with-icon(21px);
-
-  my-global-icon {
-    @include apply-svg-color(#fff);
-  }
-}
diff --git a/client/src/app/+admin/moderation/video-auto-blacklist-list/video-auto-blacklist-list.component.ts b/client/src/app/+admin/moderation/video-auto-blacklist-list/video-auto-blacklist-list.component.ts
deleted file mode 100644 (file)
index fb2962b..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-import { Component } from '@angular/core'
-import { I18n } from '@ngx-translate/i18n-polyfill'
-import { ActivatedRoute, Router } from '@angular/router'
-import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
-import { AuthService, Notifier, ServerService } from '@app/core'
-import { VideoBlacklistService } from '@app/shared'
-import { immutableAssign } from '@app/shared/misc/utils'
-import { ScreenService } from '@app/shared/misc/screen.service'
-import { MiniatureDisplayOptions } from '@app/shared/video/video-miniature.component'
-import { SelectionType } from '@app/shared/video/videos-selection.component'
-import { Video } from '@app/shared/video/video.model'
-
-@Component({
-  selector: 'my-video-auto-blacklist-list',
-  templateUrl: './video-auto-blacklist-list.component.html',
-  styleUrls: [ './video-auto-blacklist-list.component.scss' ]
-})
-export class VideoAutoBlacklistListComponent {
-  titlePage: string
-  selection: SelectionType = {}
-  miniatureDisplayOptions: MiniatureDisplayOptions = {
-    date: true,
-    views: false,
-    by: true,
-    privacyLabel: false,
-    privacyText: true,
-    state: false,
-    blacklistInfo: false,
-    nsfw: true
-  }
-  pagination: ComponentPagination = {
-    currentPage: 1,
-    itemsPerPage: 5,
-    totalItems: null
-  }
-  videos: Video[] = []
-  getVideosObservableFunction = this.getVideosObservable.bind(this)
-
-  constructor (
-    protected router: Router,
-    protected route: ActivatedRoute,
-    protected notifier: Notifier,
-    protected authService: AuthService,
-    protected screenService: ScreenService,
-    protected serverService: ServerService,
-    private i18n: I18n,
-    private videoBlacklistService: VideoBlacklistService
-  ) {
-    this.titlePage = this.i18n('Auto-blacklisted videos')
-  }
-
-  getVideosObservable (page: number) {
-    const newPagination = immutableAssign(this.pagination, { currentPage: page })
-
-    return this.videoBlacklistService.getAutoBlacklistedAsVideoList(newPagination)
-  }
-
-  removeVideoFromBlacklist (entry: Video) {
-    this.videoBlacklistService.removeVideoFromBlacklist(entry.id).subscribe(
-      () => {
-        this.notifier.success(this.i18n('Video {{name}} removed from blacklist.', { name: entry.name }))
-
-        this.videos = this.videos.filter(v => v.id !== entry.id)
-      },
-
-      error => this.notifier.error(error.message)
-    )
-  }
-
-  removeSelectedVideosFromBlacklist () {
-    const toReleaseVideosIds = Object.keys(this.selection)
-                                      .filter(k => this.selection[ k ] === true)
-                                      .map(k => parseInt(k, 10))
-
-    this.videoBlacklistService.removeVideoFromBlacklist(toReleaseVideosIds).subscribe(
-      () => {
-        this.notifier.success(this.i18n('{{num}} videos removed from blacklist.', { num: toReleaseVideosIds.length }))
-
-        this.selection = {}
-        this.videos = this.videos.filter(v => toReleaseVideosIds.includes(v.id) === false)
-      },
-
-      error => this.notifier.error(error.message)
-    )
-  }
-}
diff --git a/client/src/app/+admin/moderation/video-blacklist-list/index.ts b/client/src/app/+admin/moderation/video-blacklist-list/index.ts
deleted file mode 100644 (file)
index 4daf641..0000000
+++ /dev/null
@@ -1 +0,0 @@
-export * from './video-blacklist-list.component'
diff --git a/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.html b/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.html
deleted file mode 100644 (file)
index cfa0451..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-<p-table
-  [value]="blacklist" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
-  [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id"
-  [showCurrentPageReport]="true" i18n-currentPageReportTemplate
-  currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} blacklisted videos"
-  (onPage)="onPage($event)" [expandedRowKeys]="expandedRows"
->
-  <ng-template pTemplate="caption">
-    <div class="caption">
-      <div class="ml-auto has-feedback has-clear">
-        <input
-          type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
-          (keyup)="onSearch($event)"
-        >
-        <a class="glyphicon glyphicon-remove-sign form-control-feedback form-control-clear" (click)="resetSearch()"></a>
-        <span class="sr-only" i18n>Clear filters</span>
-      </div>
-    </div>
-  </ng-template>
-
-  <ng-template pTemplate="header">
-    <tr>
-      <th style="width: 40px"></th>
-      <th i18n pSortableColumn="name">Video <p-sortIcon field="name"></p-sortIcon></th>
-      <th style="width: 100px;" i18n>Sensitive</th>
-      <th style="width: 120px;" i18n>Unfederated</th>
-      <th style="width: 150px;" i18n pSortableColumn="createdAt">Date <p-sortIcon field="createdAt"></p-sortIcon></th>
-      <th style="width: 150px;"></th>
-    </tr>
-  </ng-template>
-
-  <ng-template pTemplate="body" let-videoBlacklist let-expanded="expanded">
-    <tr>
-      <td *ngIf="!videoBlacklist.reason"></td>
-      <td *ngIf="videoBlacklist.reason" class="expand-cell c-hand" [pRowToggler]="videoBlacklist" 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>
-        </span>
-      </td>
-
-      <td>
-        <a [href]="getVideoUrl(videoBlacklist)" class="video-table-video-link" i18n-title title="Open video in a new tab" target="_blank" rel="noopener noreferrer">
-          <div class="video-table-video">
-            <div class="video-table-video-image">
-              <img [src]="videoBlacklist.video.thumbnailPath">
-            </div>
-            <div class="video-table-video-text">
-              <div>
-                {{ videoBlacklist.video.name }}
-                <span i18n-title title="Video was blacklisted" class="glyphicon glyphicon-ban-circle"></span>
-              </div>
-              <div class="text-muted">by {{ videoBlacklist.video.channel?.displayName }} on {{ videoBlacklist.video.channel?.host }} </div>
-            </div>
-          </div>
-        </a>
-      </td>
-
-      <ng-container *ngIf="videoBlacklist.reason">
-        <td class="c-hand" [pRowToggler]="videoBlacklist">{{ booleanToText(videoBlacklist.video.nsfw) }}</td>
-        <td class="c-hand" [pRowToggler]="videoBlacklist">{{ booleanToText(videoBlacklist.unfederated) }}</td>
-        <td class="c-hand" [pRowToggler]="videoBlacklist">{{ videoBlacklist.createdAt | date: 'short' }}</td>
-      </ng-container>
-      <ng-container *ngIf="!videoBlacklist.reason">
-        <td>{{ booleanToText(videoBlacklist.video.nsfw) }}</td>
-        <td>{{ booleanToText(videoBlacklist.unfederated) }}</td>
-        <td>{{ videoBlacklist.createdAt | date: 'short' }}</td>
-      </ng-container>
-
-      <td class="action-cell">
-        <my-action-dropdown
-          [ngClass]="{ 'show': expanded }" placement="bottom-right" container="body"
-          i18n-label label="Actions" [actions]="videoBlacklistActions" [entry]="videoBlacklist"
-        ></my-action-dropdown>
-      </td>
-    </tr>
-  </ng-template>
-
-  <ng-template pTemplate="rowexpansion" let-videoBlacklist>
-    <tr>
-      <td class="expand-cell" colspan="6">
-        <div class="d-flex moderation-expanded">
-          <span class="col-2 moderation-expanded-label" i18n>Blacklist reason:</span>
-          <span class="col-9 moderation-expanded-text" [innerHTML]="videoBlacklist.reasonHtml"></span>
-        </div>
-      </td>
-    </tr>
-  </ng-template>
-
-  <ng-template pTemplate="emptymessage">
-    <tr>
-      <td colspan="6">
-        <div class="empty-table-message">
-          <ng-container *ngIf="search" i18n>No blacklisted video found matching current filters.</ng-container>
-          <ng-container *ngIf="!search" i18n>No blacklisted video found.</ng-container>
-        </div>
-      </td>
-    </tr>
-  </ng-template>
-</p-table>
-
diff --git a/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.ts b/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.ts
deleted file mode 100644 (file)
index 63ecdeb..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-import { Component, OnInit } from '@angular/core'
-import { SortMeta } from 'primeng/api'
-import { Notifier, ServerService } from '@app/core'
-import { ConfirmService } from '../../../core'
-import { RestPagination, RestTable, VideoBlacklistService } from '../../../shared'
-import { VideoBlacklist, VideoBlacklistType } from '../../../../../../shared'
-import { I18n } from '@ngx-translate/i18n-polyfill'
-import { DropdownAction } from '../../../shared/buttons/action-dropdown.component'
-import { Video } from '../../../shared/video/video.model'
-import { MarkdownService } from '@app/shared/renderer'
-
-@Component({
-  selector: 'my-video-blacklist-list',
-  templateUrl: './video-blacklist-list.component.html',
-  styleUrls: [ '../moderation.component.scss' ]
-})
-export class VideoBlacklistListComponent extends RestTable implements OnInit {
-  blacklist: (VideoBlacklist & { reasonHtml?: string })[] = []
-  totalRecords = 0
-  sort: SortMeta = { field: 'createdAt', order: -1 }
-  pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
-  listBlacklistTypeFilter: VideoBlacklistType = undefined
-
-  videoBlacklistActions: DropdownAction<VideoBlacklist>[] = []
-
-  constructor (
-    private notifier: Notifier,
-    private serverService: ServerService,
-    private confirmService: ConfirmService,
-    private videoBlacklistService: VideoBlacklistService,
-    private markdownRenderer: MarkdownService,
-    private i18n: I18n
-  ) {
-    super()
-  }
-
-  ngOnInit () {
-    this.serverService.getConfig()
-        .subscribe(config => {
-          // don't filter if auto-blacklist is not enabled as this will be the only list
-          if (config.autoBlacklist.videos.ofUsers.enabled) {
-            this.listBlacklistTypeFilter = VideoBlacklistType.MANUAL
-          }
-        })
-
-    this.initialize()
-
-    this.videoBlacklistActions = [
-      {
-        label: this.i18n('Unblacklist'),
-        handler: videoBlacklist => this.removeVideoFromBlacklist(videoBlacklist)
-      }
-    ]
-  }
-
-  getIdentifier () {
-    return 'VideoBlacklistListComponent'
-  }
-
-  getVideoUrl (videoBlacklist: VideoBlacklist) {
-    return Video.buildClientUrl(videoBlacklist.video.uuid)
-  }
-
-  booleanToText (value: boolean) {
-    if (value === true) return this.i18n('yes')
-
-    return this.i18n('no')
-  }
-
-  toHtml (text: string) {
-    return this.markdownRenderer.textMarkdownToHTML(text)
-  }
-
-  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.'
-    )
-
-    const res = await this.confirmService.confirm(confirmMessage, this.i18n('Unblacklist'))
-    if (res === false) return
-
-    this.videoBlacklistService.removeVideoFromBlacklist(entry.video.id).subscribe(
-      () => {
-        this.notifier.success(this.i18n('Video {{name}} removed from the blacklist.', { name: entry.video.name }))
-        this.loadData()
-      },
-
-      err => this.notifier.error(err.message)
-    )
-  }
-
-  protected loadData () {
-    this.videoBlacklistService.listBlacklist({
-      pagination: this.pagination,
-      sort: this.sort,
-      search: this.search,
-      type: this.listBlacklistTypeFilter
-    })
-      .subscribe(
-        async resultList => {
-          this.totalRecords = resultList.total
-
-          this.blacklist = resultList.data
-
-          for (const element of this.blacklist) {
-            Object.assign(element, { reasonHtml: await this.toHtml(element.reason) })
-          }
-        },
-
-        err => this.notifier.error(err.message)
-      )
-  }
-}
diff --git a/client/src/app/+admin/moderation/video-block-list/index.ts b/client/src/app/+admin/moderation/video-block-list/index.ts
new file mode 100644 (file)
index 0000000..ec4de8f
--- /dev/null
@@ -0,0 +1 @@
+export * from './video-block-list.component'
diff --git a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.html b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.html
new file mode 100644 (file)
index 0000000..f3ec373
--- /dev/null
@@ -0,0 +1,113 @@
+<p-table
+  [value]="blocklist" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
+  [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id"
+  [showCurrentPageReport]="true" i18n-currentPageReportTemplate
+  currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} blocked videos"
+  (onPage)="onPage($event)" [expandedRowKeys]="expandedRows"
+>
+  <ng-template pTemplate="caption">
+    <div class="caption">
+      <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">
+            <div class="input-group-text" ngbDropdownToggle>
+              <span class="caret" aria-haspopup="menu" role="button"></span>
+            </div>
+
+            <div role="menu" ngbDropdownMenu>
+              <h6 class="dropdown-header" i18n>Advanced block filters</h6>
+              <a [routerLink]="[ '/admin/moderation/video-blocks/list' ]" [queryParams]="{ 'search': 'type:auto' }" class="dropdown-item" i18n>Automatic blocks</a>
+              <a [routerLink]="[ '/admin/moderation/video-blocks/list' ]" [queryParams]="{ 'search': 'type:manual' }" class="dropdown-item" i18n>Manual blocks</a>
+            </div>
+          </div>
+          <input
+            type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
+            (keyup)="onBlockSearch($event)"
+          >
+          <a class="glyphicon glyphicon-remove-sign form-control-feedback form-control-clear" (click)="resetTableFilter()"></a>
+          <span class="sr-only" i18n>Clear filters</span>
+        </div>
+      </div>
+    </div>
+  </ng-template>
+
+  <ng-template pTemplate="header">
+    <tr>
+      <th style="width: 40px"></th>
+      <th i18n pSortableColumn="name">Video <p-sortIcon field="name"></p-sortIcon></th>
+      <th style="width: 100px;" i18n>Sensitive</th>
+      <th style="width: 120px;" i18n>Unfederated</th>
+      <th style="width: 150px;" i18n pSortableColumn="createdAt">Date <p-sortIcon field="createdAt"></p-sortIcon></th>
+      <th style="width: 150px;"></th>
+    </tr>
+  </ng-template>
+
+  <ng-template pTemplate="body" let-videoBlock let-expanded="expanded">
+    <tr>
+      <td *ngIf="!videoBlock.reason"></td>
+      <td *ngIf="videoBlock.reason" class="expand-cell c-hand" [pRowToggler]="videoBlock" 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>
+        </span>
+      </td>
+
+      <td>
+        <a [href]="getVideoUrl(videoBlock)" class="video-table-video-link" i18n-title title="Open video in a new tab" target="_blank" rel="noopener noreferrer">
+          <div class="video-table-video">
+            <div class="video-table-video-image">
+              <img [src]="videoBlock.video.thumbnailPath">
+            </div>
+            <div class="video-table-video-text">
+              <div>
+                <my-global-icon i18n-title title="The video was blocked due to automatic blocking of new videos" *ngIf="videoBlock.type == 2" iconName="robot"></my-global-icon>
+                {{ videoBlock.video.name }}
+              </div>
+              <div class="text-muted">by {{ videoBlock.video.channel?.displayName }} on {{ videoBlock.video.channel?.host }} </div>
+            </div>
+          </div>
+        </a>
+      </td>
+
+      <ng-container *ngIf="videoBlock.reason">
+        <td class="c-hand" [pRowToggler]="videoBlock">{{ booleanToText(videoBlock.video.nsfw) }}</td>
+        <td class="c-hand" [pRowToggler]="videoBlock">{{ booleanToText(videoBlock.unfederated) }}</td>
+        <td class="c-hand" [pRowToggler]="videoBlock">{{ videoBlock.createdAt | date: 'short' }}</td>
+      </ng-container>
+      <ng-container *ngIf="!videoBlock.reason">
+        <td>{{ booleanToText(videoBlock.video.nsfw) }}</td>
+        <td>{{ booleanToText(videoBlock.unfederated) }}</td>
+        <td>{{ videoBlock.createdAt | date: 'short' }}</td>
+      </ng-container>
+
+      <td class="action-cell">
+        <my-action-dropdown
+          [ngClass]="{ 'show': expanded }" placement="bottom-right" container="body"
+          i18n-label label="Actions" [actions]="videoBlocklistActions" [entry]="videoBlock"
+        ></my-action-dropdown>
+      </td>
+    </tr>
+  </ng-template>
+
+  <ng-template pTemplate="rowexpansion" let-videoBlock>
+    <tr>
+      <td class="expand-cell" colspan="6">
+        <div class="d-flex moderation-expanded">
+          <span class="col-2 moderation-expanded-label" i18n>Block reason:</span>
+          <span class="col-9 moderation-expanded-text" [innerHTML]="videoBlock.reasonHtml"></span>
+        </div>
+      </td>
+    </tr>
+  </ng-template>
+
+  <ng-template pTemplate="emptymessage">
+    <tr>
+      <td colspan="6">
+        <div class="empty-table-message">
+          <ng-container *ngIf="search" i18n>No blocked video found matching current filters.</ng-container>
+          <ng-container *ngIf="!search" i18n>No blocked video found.</ng-container>
+        </div>
+      </td>
+    </tr>
+  </ng-template>
+</p-table>
+
diff --git a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.scss b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.scss
new file mode 100644 (file)
index 0000000..43a3656
--- /dev/null
@@ -0,0 +1,18 @@
+@import 'mixins';
+
+my-global-icon {
+  @include apply-svg-color(#7d7d7d);
+
+  width: 12px;
+  height: 12px;
+  position: relative;
+  top: -1px;
+}
+
+.input-group {
+  @include peertube-input-group(300px);
+
+  .dropdown-toggle::after {
+    margin-left: 0;
+  }
+}
diff --git a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts
new file mode 100644 (file)
index 0000000..e72ab53
--- /dev/null
@@ -0,0 +1,196 @@
+import { Component, OnInit } from '@angular/core'
+import { SortMeta } from 'primeng/api'
+import { Notifier, ServerService } from '@app/core'
+import { ConfirmService } from '../../../core'
+import { RestPagination, RestTable, VideoBlockService } from '../../../shared'
+import { VideoBlocklist, VideoBlockType } from '../../../../../../shared'
+import { I18n } from '@ngx-translate/i18n-polyfill'
+import { DropdownAction } from '../../../shared/buttons/action-dropdown.component'
+import { Video } from '../../../shared/video/video.model'
+import { MarkdownService } from '@app/shared/renderer'
+import { Params, ActivatedRoute, Router } from '@angular/router'
+import { filter, switchMap } from 'rxjs/operators'
+import { VideoService } from '@app/shared/video/video.service'
+
+@Component({
+  selector: 'my-video-block-list',
+  templateUrl: './video-block-list.component.html',
+  styleUrls: [ '../moderation.component.scss', './video-block-list.component.scss' ]
+})
+export class VideoBlockListComponent extends RestTable implements OnInit {
+  blocklist: (VideoBlocklist & { reasonHtml?: string })[] = []
+  totalRecords = 0
+  sort: SortMeta = { field: 'createdAt', order: -1 }
+  pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
+  listBlockTypeFilter: VideoBlockType = undefined
+
+  videoBlocklistActions: DropdownAction<VideoBlocklist>[][] = []
+
+  constructor (
+    private notifier: Notifier,
+    private serverService: ServerService,
+    private confirmService: ConfirmService,
+    private videoBlocklistService: VideoBlockService,
+    private markdownRenderer: MarkdownService,
+    private videoService: VideoService,
+    private route: ActivatedRoute,
+    private router: Router,
+    private i18n: I18n
+  ) {
+    super()
+
+    this.videoBlocklistActions = [
+      [
+        {
+          label: this.i18n('Internal actions'),
+          isHeader: true
+        },
+        {
+          label: this.i18n('Switch video block to manual'),
+          handler: videoBlock => {
+            this.videoBlocklistService.unblockVideo(videoBlock.video.id).pipe(
+              switchMap(_ => this.videoBlocklistService.blockVideo(videoBlock.video.id, undefined, true))
+            ).subscribe(
+              () => {
+                this.notifier.success(this.i18n('Video {{name}} switched to manual block.', { name: videoBlock.video.name }))
+                this.loadData()
+              },
+        
+              err => this.notifier.error(err.message)
+            )
+          }
+        }
+      ],
+      [
+        {
+          label: this.i18n('Actions for the video'),
+          isHeader: true,
+        },
+        {
+          label: this.i18n('Unblock video'),
+          handler: videoBlock => this.unblockVideo(videoBlock)
+        },
+
+        {
+          label: this.i18n('Delete video'),
+          handler: async videoBlock => {
+            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(videoBlock.video.id)
+              .subscribe(
+                () => {
+                  this.notifier.success(this.i18n('Video deleted.'))
+                },
+
+                err => this.notifier.error(err.message)
+              )
+          }
+        }
+      ]
+    ]
+  }
+
+  ngOnInit () {
+    this.serverService.getConfig()
+        .subscribe(config => {
+          // don't filter if auto-blacklist is not enabled as this will be the only list
+          if (config.autoBlacklist.videos.ofUsers.enabled) {
+            this.listBlockTypeFilter = VideoBlockType.MANUAL
+          }
+        })
+
+    this.initialize()
+
+    this.route.queryParams
+      .pipe(filter(params => params.search !== undefined && params.search !== null))
+      .subscribe(params => {
+        this.search = params.search
+        this.setTableFilter(params.search)
+        this.loadData()
+      })
+  }
+
+  ngAfterViewInit () {
+    if (this.search) this.setTableFilter(this.search)
+  }
+
+  /* Table filter functions */
+  onBlockSearch (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-blocks/list' ], { queryParams })
+  }
+
+  resetTableFilter () {
+    this.setTableFilter('')
+    this.setQueryParams('')
+    this.resetSearch()
+  }
+  /* END Table filter functions */
+
+  getIdentifier () {
+    return 'VideoBlockListComponent'
+  }
+
+  getVideoUrl (videoBlock: VideoBlocklist) {
+    return Video.buildClientUrl(videoBlock.video.uuid)
+  }
+
+  booleanToText (value: boolean) {
+    if (value === true) return this.i18n('yes')
+
+    return this.i18n('no')
+  }
+
+  toHtml (text: string) {
+    return this.markdownRenderer.textMarkdownToHTML(text)
+  }
+
+  async unblockVideo (entry: VideoBlocklist) {
+    const confirmMessage = this.i18n(
+      'Do you really want to unblock this video? It will be available again in the videos list.'
+    )
+
+    const res = await this.confirmService.confirm(confirmMessage, this.i18n('Unblock'))
+    if (res === false) return
+
+    this.videoBlocklistService.unblockVideo(entry.video.id).subscribe(
+      () => {
+        this.notifier.success(this.i18n('Video {{name}} unblocked.', { name: entry.video.name }))
+        this.loadData()
+      },
+
+      err => this.notifier.error(err.message)
+    )
+  }
+
+  protected loadData () {
+    this.videoBlocklistService.listBlocks({
+      pagination: this.pagination,
+      sort: this.sort,
+      search: this.search,
+    })
+      .subscribe(
+        async resultList => {
+          this.totalRecords = resultList.total
+
+          this.blocklist = resultList.data
+
+          for (const element of this.blocklist) {
+            Object.assign(element, { reasonHtml: await this.toHtml(element.reason) })
+          }
+        },
+
+        err => this.notifier.error(err.message)
+      )
+  }
+}
index 6e2952c44b237ec8c4e9f4aafaf5a71e71f173f9..98249bcc17a74afc581e08f91d4bd3872d35cd17 100644 (file)
@@ -88,7 +88,7 @@ export abstract class UserEdit extends FormReactive implements OnInit {
   }
 
   protected buildAdminFlags (formValue: any) {
-    return formValue.byPassAutoBlacklist ? UserAdminFlag.BY_PASS_VIDEO_AUTO_BLACKLIST : UserAdminFlag.NONE
+    return formValue.byPassAutoBlacklist ? UserAdminFlag.BYPASS_VIDEO_AUTO_BLOCK : UserAdminFlag.NONE
   }
 
   protected buildQuotaOptions () {
index e0e1fbddf43c42088a215e360384327cdc72c051..f2bd8c8ec1e1e6cda20f45a2c28d4c1761dc5344 100644 (file)
@@ -125,7 +125,7 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
       role: userJson.role.toString(),
       videoQuota: userJson.videoQuota,
       videoQuotaDaily: userJson.videoQuotaDaily,
-      byPassAutoBlacklist: userJson.adminFlags & UserAdminFlag.BY_PASS_VIDEO_AUTO_BLACKLIST
+      byPassAutoBlacklist: userJson.adminFlags & UserAdminFlag.BYPASS_VIDEO_AUTO_BLOCK
     })
   }
 }
index d3a329e8f449d5ac5aa2dcdde0d2cd2a45eafa28..817b929febc3e1c1029c077d858a1809828e3856 100644 (file)
@@ -17,6 +17,6 @@
   <div class="video" *ngFor="let video of videos">
     <my-video-miniature
       [video]="video" [displayAsRow]="true"
-      (videoRemoved)="removeVideoFromArray(video)" (videoBlacklisted)="removeVideoFromArray(video)"></my-video-miniature>
+      (videoRemoved)="removeVideoFromArray(video)" (videoBlocked)="removeVideoFromArray(video)"></my-video-miniature>
   </div>
 </div>
index 6ba1a10204d6a83b0b07f21e2f196bef427db6e6..72e26ac2805eed9686d6df918348e7e9aa6c96fb 100644 (file)
@@ -35,8 +35,8 @@ export class MyAccountNotificationPreferencesComponent implements OnInit {
       newVideoFromSubscription: this.i18n('New video from your subscriptions'),
       newCommentOnMyVideo: this.i18n('New comment on your video'),
       videoAbuseAsModerator: this.i18n('New video abuse'),
-      videoAutoBlacklistAsModerator: this.i18n('Video auto-blacklisted waiting review'),
-      blacklistOnMyVideo: this.i18n('One of your video is blacklisted/unblacklisted'),
+      videoAutoBlacklistAsModerator: this.i18n('Video blocked automatically waiting review'),
+      blacklistOnMyVideo: this.i18n('One of your video is blocked/unblocked'),
       myVideoPublished: this.i18n('Video published (after transcoding/scheduled update)'),
       myVideoImportFinished: this.i18n('Video import finished'),
       newUserRegistration: this.i18n('A new user registered on your instance'),
@@ -49,7 +49,7 @@ export class MyAccountNotificationPreferencesComponent implements OnInit {
 
     this.rightNotifications = {
       videoAbuseAsModerator: UserRight.MANAGE_VIDEO_ABUSES,
-      videoAutoBlacklistAsModerator: UserRight.MANAGE_VIDEO_BLACKLIST,
+      videoAutoBlacklistAsModerator: UserRight.MANAGE_VIDEO_BLOCKS,
       newUserRegistration: UserRight.MANAGE_USERS,
       newInstanceFollower: UserRight.MANAGE_SERVER_FOLLOW,
       autoInstanceFollowing: UserRight.MANAGE_CONFIGURATION
index 015c14bce70aee2cb83ffe0a1d2e9c23a53c7058..79bf29e9c72501edbe666a39bc702a972fad7cff 100644 (file)
@@ -33,7 +33,7 @@ export class MenuComponent implements OnInit {
     [UserRight.MANAGE_USERS]: '/admin/users',
     [UserRight.MANAGE_SERVER_FOLLOW]: '/admin/friends',
     [UserRight.MANAGE_VIDEO_ABUSES]: '/admin/moderation/video-abuses',
-    [UserRight.MANAGE_VIDEO_BLACKLIST]: '/admin/moderation/video-blacklist',
+    [UserRight.MANAGE_VIDEO_BLOCKS]: '/admin/moderation/video-blocks',
     [UserRight.MANAGE_JOBS]: '/admin/jobs',
     [UserRight.MANAGE_CONFIGURATION]: '/admin/config'
   }
@@ -131,7 +131,7 @@ export class MenuComponent implements OnInit {
       UserRight.MANAGE_USERS,
       UserRight.MANAGE_SERVER_FOLLOW,
       UserRight.MANAGE_VIDEO_ABUSES,
-      UserRight.MANAGE_VIDEO_BLACKLIST,
+      UserRight.MANAGE_VIDEO_BLOCKS,
       UserRight.MANAGE_JOBS,
       UserRight.MANAGE_CONFIGURATION
     ]
index 3cafc676d9577bc3d0bf683f9a135e7a555d6ac9..d723606db969afeb23c367b915f8b26083303cdf 100644 (file)
@@ -55,7 +55,7 @@
       <my-video-miniature
         [video]="result" [user]="user" [displayAsRow]="true" [displayVideoActions]="!hideActions()"
         [useLazyLoadUrl]="advancedSearch.searchTarget === 'search-index'"
-        (videoBlacklisted)="removeVideoFromArray(result)" (videoRemoved)="removeVideoFromArray(result)"
+        (videoBlocked)="removeVideoFromArray(result)" (videoRemoved)="removeVideoFromArray(result)"
       ></my-video-miniature>
     </div>
   </ng-container>
index e3de3ae13de31b1e552f4e3aae7ec93b8642243d..4a01b1622432a0e43fd5191d6ac67dbb3efcc2f7 100644 (file)
@@ -6,7 +6,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-block-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
deleted file mode 100644 (file)
index 07d1f26..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-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/forms/form-validators/video-block-validators.service.ts b/client/src/app/shared/forms/form-validators/video-block-validators.service.ts
new file mode 100644 (file)
index 0000000..dc82577
--- /dev/null
@@ -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 VideoBlockValidatorsService {
+  readonly VIDEO_BLOCK_REASON: BuildFormValidator
+
+  constructor (private i18n: I18n) {
+    this.VIDEO_BLOCK_REASON = {
+      VALIDATORS: [ Validators.minLength(2), Validators.maxLength(300) ],
+      MESSAGES: {
+        'minlength': this.i18n('Block reason must be at least 2 characters long.'),
+        'maxlength': this.i18n('Block reason cannot be more than 300 characters long.')
+      }
+    }
+  }
+}
index d2700f6c33f876765d2b8a88b8702ff89d36e5ad..169882685b5dfeb89c748069f8d30dd6391b4af9 100644 (file)
@@ -56,7 +56,8 @@ const icons = {
   'refresh': require('!!raw-loader?!../../../assets/images/global/refresh.svg').default,
   'npm': require('!!raw-loader?!../../../assets/images/global/npm.svg').default,
   'fullscreen': require('!!raw-loader?!../../../assets/images/global/fullscreen.svg').default,
-  'exit-fullscreen': require('!!raw-loader?!../../../assets/images/global/exit-fullscreen.svg').default
+  'exit-fullscreen': require('!!raw-loader?!../../../assets/images/global/exit-fullscreen.svg').default,
+  'robot': require('!!raw-loader?!../../../assets/images/global/robot.svg').default
 }
 
 export type GlobalIconName = keyof typeof icons
index 136730c91a36a8b8315f38824b546234ac45cbe1..8be578d9f73af3222cd33155b965ea1b8f55c0cc 100644 (file)
@@ -3,5 +3,5 @@ export * from './forms'
 export * from './rest'
 export * from './users'
 export * from './video-abuse'
-export * from './video-blacklist'
+export * from './video-block'
 export * from './shared.module'
index 813f766723b22ac9ca4f11d4c35792f46b2edf53..2035097d75dd869bda7a4f9da01d6f475725da43 100644 (file)
@@ -35,7 +35,7 @@ import {
   UserValidatorsService,
   VideoAbuseValidatorsService,
   VideoAcceptOwnershipValidatorsService,
-  VideoBlacklistValidatorsService,
+  VideoBlockValidatorsService,
   VideoChangeOwnershipValidatorsService,
   VideoChannelValidatorsService,
   VideoCommentValidatorsService,
@@ -78,7 +78,7 @@ import { VideoPlaylistElementMiniatureComponent } from '@app/shared/video-playli
 import { VideoPlaylistMiniatureComponent } from '@app/shared/video-playlist/video-playlist-miniature.component'
 import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service'
 import { InfiniteScrollerDirective } from '@app/shared/video/infinite-scroller.directive'
-import { VideoBlacklistComponent } from '@app/shared/video/modals/video-blacklist.component'
+import { VideoBlockComponent } from '@app/shared/video/modals/video-block.component'
 import { VideoDownloadComponent } from '@app/shared/video/modals/video-download.component'
 import { VideoReportComponent } from '@app/shared/video/modals/video-report.component'
 import { RedundancyService } from '@app/shared/video/redundancy.service'
@@ -102,7 +102,7 @@ import { LoaderComponent } from './misc/loader.component'
 import { RestExtractor, RestService } from './rest'
 import { UserService } from './users'
 import { VideoAbuseService } from './video-abuse'
-import { VideoBlacklistService } from './video-blacklist'
+import { VideoBlockService } from './video-block'
 import { VideoOwnershipService } from './video-ownership'
 import { FeedComponent } from './video/feed.component'
 import { VideoMiniatureComponent } from './video/video-miniature.component'
@@ -147,7 +147,7 @@ import { VideoService } from './video/video.service'
 
     VideoDownloadComponent,
     VideoReportComponent,
-    VideoBlacklistComponent,
+    VideoBlockComponent,
 
     FeedComponent,
 
@@ -230,7 +230,7 @@ import { VideoService } from './video/video.service'
 
     VideoDownloadComponent,
     VideoReportComponent,
-    VideoBlacklistComponent,
+    VideoBlockComponent,
 
     FeedComponent,
 
@@ -282,7 +282,7 @@ import { VideoService } from './video/video.service'
     RestExtractor,
     RestService,
     VideoAbuseService,
-    VideoBlacklistService,
+    VideoBlockService,
     VideoOwnershipService,
     UserService,
     VideoService,
@@ -305,7 +305,7 @@ import { VideoService } from './video/video.service'
     VideoCommentValidatorsService,
     VideoValidatorsService,
     VideoCaptionsValidatorsService,
-    VideoBlacklistValidatorsService,
+    VideoBlockValidatorsService,
     OverviewService,
     VideoChangeOwnershipValidatorsService,
     VideoAcceptOwnershipValidatorsService,
index 7b8368d872da81ad5c594f68a124471444b1e9b1..bc1861c643697d1530bd8a05fbe7e71c1ba2e89d 100644 (file)
@@ -96,7 +96,7 @@ export class UserNotification implements UserNotificationServer {
           this.videoUrl = this.buildVideoUrl(this.video)
           break
 
-        case UserNotificationType.UNBLACKLIST_ON_MY_VIDEO:
+        case UserNotificationType.UNBLOCK_ON_MY_VIDEO:
           this.videoUrl = this.buildVideoUrl(this.video)
           break
 
@@ -112,7 +112,7 @@ export class UserNotification implements UserNotificationServer {
           this.videoUrl = this.buildVideoUrl(this.videoAbuse.video)
           break
 
-        case UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS:
+        case UserNotificationType.VIDEO_AUTO_BLOCK_FOR_MODERATORS:
           this.videoAutoBlacklistUrl = '/admin/moderation/video-auto-blacklist/list'
           // Backward compatibility where we did not assign videoBlacklist to this type of notification before
           if (!this.videoBlacklist) this.videoBlacklist = { id: null, video: this.video }
@@ -120,7 +120,7 @@ export class UserNotification implements UserNotificationServer {
           this.videoUrl = this.buildVideoUrl(this.videoBlacklist.video)
           break
 
-        case UserNotificationType.BLACKLIST_ON_MY_VIDEO:
+        case UserNotificationType.BLOCK_ON_MY_VIDEO:
           this.videoUrl = this.buildVideoUrl(this.videoBlacklist.video)
           break
 
index 8dbe6e329dd2150d5b9a308f4ef306b92aebcb97..5a102995a2e82e34f4dbca9cccdc776fc30c5836 100644 (file)
         </ng-template>
       </ng-container>
 
-      <ng-container *ngSwitchCase="UserNotificationType.UNBLACKLIST_ON_MY_VIDEO">
+      <ng-container *ngSwitchCase="UserNotificationType.UNBLOCK_ON_MY_VIDEO">
         <my-global-icon iconName="undo"></my-global-icon>
 
         <div class="message" i18n>
-          Your video <a (click)="markAsRead(notification)" [routerLink]="notification.videoUrl">{{ notification.video.name }}</a> has been unblacklisted
+          Your video <a (click)="markAsRead(notification)" [routerLink]="notification.videoUrl">{{ notification.video.name }}</a> has been unblocked
         </div>
       </ng-container>
 
-      <ng-container *ngSwitchCase="UserNotificationType.BLACKLIST_ON_MY_VIDEO">
+      <ng-container *ngSwitchCase="UserNotificationType.BLOCK_ON_MY_VIDEO">
         <my-global-icon iconName="no"></my-global-icon>
 
         <div class="message" i18n>
-          Your video <a (click)="markAsRead(notification)" [routerLink]="notification.videoUrl">{{ notification.videoBlacklist.video.name }}</a> has been blacklisted
+          Your video <a (click)="markAsRead(notification)" [routerLink]="notification.videoUrl">{{ notification.videoBlacklist.video.name }}</a> has been blocked
         </div>
       </ng-container>
 
         </div>
       </ng-container>
 
-      <ng-container *ngSwitchCase="UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS">
+      <ng-container *ngSwitchCase="UserNotificationType.VIDEO_AUTO_BLOCK_FOR_MODERATORS">
         <my-global-icon iconName="no"></my-global-icon>
 
         <div class="message" i18n>
-          The recently added video <a (click)="markAsRead(notification)" [routerLink]="notification.videoUrl">{{ notification.videoBlacklist.video.name }}</a> has been <a (click)="markAsRead(notification)" [routerLink]="notification.videoAutoBlacklistUrl">auto-blacklisted</a>
+          The recently added video <a (click)="markAsRead(notification)" [routerLink]="notification.videoUrl">{{ notification.videoBlacklist.video.name }}</a> has been <a (click)="markAsRead(notification)" [routerLink]="notification.videoAutoBlacklistUrl">auto-blocked</a>
         </div>
       </ng-container>
 
diff --git a/client/src/app/shared/video-blacklist/index.ts b/client/src/app/shared/video-blacklist/index.ts
deleted file mode 100644 (file)
index bfb0264..0000000
+++ /dev/null
@@ -1 +0,0 @@
-export * from './video-blacklist.service'
diff --git a/client/src/app/shared/video-blacklist/video-blacklist.service.ts b/client/src/app/shared/video-blacklist/video-blacklist.service.ts
deleted file mode 100644 (file)
index c0e13a6..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-import { catchError, map, concatMap, toArray } from 'rxjs/operators'
-import { HttpClient, HttpParams } from '@angular/common/http'
-import { Injectable } from '@angular/core'
-import { SortMeta } from 'primeng/api'
-import { from as observableFrom, Observable } from 'rxjs'
-import { VideoBlacklist, VideoBlacklistType, ResultList } from '../../../../../shared'
-import { Video } from '../video/video.model'
-import { environment } from '../../../environments/environment'
-import { RestExtractor, RestPagination, RestService } from '../rest'
-import { ComponentPaginationLight } from '../rest/component-pagination.model'
-
-@Injectable()
-export class VideoBlacklistService {
-  private static BASE_VIDEOS_URL = environment.apiUrl + '/api/v1/videos/'
-
-  constructor (
-    private authHttp: HttpClient,
-    private restService: RestService,
-    private restExtractor: RestExtractor
-  ) {}
-
-  listBlacklist (options: {
-    pagination: RestPagination,
-    sort: SortMeta,
-    search?: string
-    type?: VideoBlacklistType
-  }): Observable<ResultList<VideoBlacklist>> {
-    const { pagination, sort, search, type } = options
-
-    let params = new HttpParams()
-    params = this.restService.addRestGetParams(params, pagination, sort)
-
-    if (search) params = params.append('search', search)
-    if (type) params = params.append('type', type.toString())
-
-    return this.authHttp.get<ResultList<VideoBlacklist>>(VideoBlacklistService.BASE_VIDEOS_URL + 'blacklist', { params })
-               .pipe(
-                 map(res => this.restExtractor.convertResultListDateToHuman(res)),
-                 catchError(res => this.restExtractor.handleError(res))
-               )
-  }
-
-  getAutoBlacklistedAsVideoList (videoPagination: ComponentPaginationLight): Observable<ResultList<Video>> {
-    const pagination = this.restService.componentPaginationToRestPagination(videoPagination)
-
-    // prioritize first created since waiting longest
-    const AUTO_BLACKLIST_SORT = 'createdAt'
-
-    let params = new HttpParams()
-    params = this.restService.addRestGetParams(params, pagination, AUTO_BLACKLIST_SORT)
-
-    params = params.set('type', VideoBlacklistType.AUTO_BEFORE_PUBLISHED.toString())
-
-    return this.authHttp.get<ResultList<VideoBlacklist>>(VideoBlacklistService.BASE_VIDEOS_URL + 'blacklist', { params })
-              .pipe(
-                map(res => {
-                  return {
-                    total: res.total,
-                    data: res.data.map(videoBlacklist => new Video(videoBlacklist.video))
-                  }
-                }),
-                catchError(res => this.restExtractor.handleError(res))
-              )
-  }
-
-  removeVideoFromBlacklist (videoIdArgs: number | number[]) {
-    const videoIds = Array.isArray(videoIdArgs) ? videoIdArgs : [ videoIdArgs ]
-
-    return observableFrom(videoIds)
-      .pipe(
-        concatMap(id => this.authHttp.delete(VideoBlacklistService.BASE_VIDEOS_URL + id + '/blacklist')),
-        toArray(),
-        catchError(err => this.restExtractor.handleError(err))
-      )
-  }
-
-  blacklistVideo (videoId: number, reason: string, unfederate: boolean) {
-    const body = {
-      unfederate,
-      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-block/index.ts b/client/src/app/shared/video-block/index.ts
new file mode 100644 (file)
index 0000000..a99551a
--- /dev/null
@@ -0,0 +1 @@
+export * from './video-block.service'
diff --git a/client/src/app/shared/video-block/video-block.service.ts b/client/src/app/shared/video-block/video-block.service.ts
new file mode 100644 (file)
index 0000000..67ca1d8
--- /dev/null
@@ -0,0 +1,77 @@
+import { catchError, map, concatMap, toArray } from 'rxjs/operators'
+import { HttpClient, HttpParams } from '@angular/common/http'
+import { Injectable } from '@angular/core'
+import { SortMeta } from 'primeng/api'
+import { from as observableFrom, Observable } from 'rxjs'
+import { VideoBlocklist, VideoBlockType, ResultList } from '../../../../../shared'
+import { environment } from '../../../environments/environment'
+import { RestExtractor, RestPagination, RestService } from '../rest'
+
+@Injectable()
+export class VideoBlockService {
+  private static BASE_VIDEOS_URL = environment.apiUrl + '/api/v1/videos/'
+
+  constructor (
+    private authHttp: HttpClient,
+    private restService: RestService,
+    private restExtractor: RestExtractor
+  ) {}
+
+  listBlocks (options: {
+    pagination: RestPagination
+    sort: SortMeta
+    search?: string
+    type?: VideoBlockType
+  }): Observable<ResultList<VideoBlocklist>> {
+    const { pagination, sort, search, type } = options
+
+    let params = new HttpParams()
+    params = this.restService.addRestGetParams(params, pagination, sort)
+
+    if (search) {
+      const filters = this.restService.parseQueryStringFilter(search, {
+        type: {
+          prefix: 'type:',
+          handler: v => {
+            if (v === 'manual') return VideoBlockType.MANUAL
+            if (v === 'auto') return VideoBlockType.AUTO_BEFORE_PUBLISHED
+
+            return undefined
+          }
+        }
+      })
+
+      params = this.restService.addObjectParams(params, filters)
+    }
+
+    return this.authHttp.get<ResultList<VideoBlocklist>>(VideoBlockService.BASE_VIDEOS_URL + 'blacklist', { params })
+               .pipe(
+                 map(res => this.restExtractor.convertResultListDateToHuman(res)),
+                 catchError(res => this.restExtractor.handleError(res))
+               )
+  }
+
+  unblockVideo (videoIdArgs: number | number[]) {
+    const videoIds = Array.isArray(videoIdArgs) ? videoIdArgs : [ videoIdArgs ]
+
+    return observableFrom(videoIds)
+      .pipe(
+        concatMap(id => this.authHttp.delete(VideoBlockService.BASE_VIDEOS_URL + id + '/blacklist')),
+        toArray(),
+        catchError(err => this.restExtractor.handleError(err))
+      )
+  }
+
+  blockVideo (videoId: number, reason: string, unfederate: boolean) {
+    const body = {
+      unfederate,
+      reason
+    }
+
+    return this.authHttp.post(VideoBlockService.BASE_VIDEOS_URL + videoId + '/blacklist', body)
+               .pipe(
+                 map(this.restExtractor.extractDataBool),
+                 catchError(res => this.restExtractor.handleError(res))
+               )
+  }
+}
index cd8a5b840685ee151defe55fa8208f2f1657a2ac..8ce3b25b0245649a572fab4bc7c7a3456a5d8d0a 100644 (file)
@@ -39,7 +39,7 @@
         [fitWidth]="true"
         [video]="video" [user]="user" [ownerDisplayType]="ownerDisplayType"
         [displayVideoActions]="displayVideoActions" [displayOptions]="displayOptions"
-        (videoBlacklisted)="removeVideoFromArray(video)" (videoRemoved)="removeVideoFromArray(video)"
+        (videoBlocked)="removeVideoFromArray(video)" (videoRemoved)="removeVideoFromArray(video)"
       >
       </my-video-miniature>
     </ng-container>
diff --git a/client/src/app/shared/video/modals/video-blacklist.component.html b/client/src/app/shared/video/modals/video-blacklist.component.html
deleted file mode 100644 (file)
index 8f06a6b..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-<ng-template #modal>
-  <div class="modal-header">
-    <h4 i18n class="modal-title">Blacklist video</h4>
-    <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon>
-  </div>
-
-  <div class="modal-body">
-
-    <form novalidate [formGroup]="form" (ngSubmit)="blacklist()">
-      <div class="form-group">
-        <textarea
-          i18n-placeholder placeholder="Reason..." formControlName="reason"
-          [ngClass]="{ 'input-error': formErrors['reason'] }" class="form-control"
-        ></textarea>
-        <div *ngIf="formErrors.reason" class="form-error">
-          {{ formErrors.reason }}
-        </div>
-      </div>
-
-      <div class="form-group" *ngIf="video.isLocal">
-        <my-peertube-checkbox
-          inputName="unfederate" formControlName="unfederate"
-          i18n-labelText labelText="Unfederate the video"
-        >
-          <ng-container ngProjectAs="description">
-            <span i18n>This will ask remote instances to delete it</span>
-          </ng-container>
-        </my-peertube-checkbox>
-      </div>
-
-      <div class="form-group inputs">
-        <input
-          type="button" role="button" i18n-value value="Cancel" class="action-button action-button-cancel"
-          (click)="hide()" (key.enter)="hide()"
-        >
-
-        <input
-          type="submit" i18n-value value="Submit" class="action-button-submit"
-          [disabled]="!form.valid"
-        >
-      </div>
-    </form>
-
-  </div>
-</ng-template>
diff --git a/client/src/app/shared/video/modals/video-blacklist.component.scss b/client/src/app/shared/video/modals/video-blacklist.component.scss
deleted file mode 100644 (file)
index afcdb9a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-@import 'variables';
-@import 'mixins';
-
-textarea {
-  @include peertube-textarea(100%, 100px);
-}
diff --git a/client/src/app/shared/video/modals/video-blacklist.component.ts b/client/src/app/shared/video/modals/video-blacklist.component.ts
deleted file mode 100644 (file)
index 6ef9c25..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'
-import { Notifier, RedirectService } from '@app/core'
-import { VideoBlacklistService } from '../../../shared/video-blacklist'
-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 { FormReactive, VideoBlacklistValidatorsService } from '@app/shared/forms'
-import { Video } from '@app/shared/video/video.model'
-
-@Component({
-  selector: 'my-video-blacklist',
-  templateUrl: './video-blacklist.component.html',
-  styleUrls: [ './video-blacklist.component.scss' ]
-})
-export class VideoBlacklistComponent extends FormReactive implements OnInit {
-  @Input() video: Video = null
-
-  @ViewChild('modal', { static: true }) modal: NgbModal
-
-  @Output() videoBlacklisted = new EventEmitter()
-
-  error: string = null
-
-  private openedModal: NgbModalRef
-
-  constructor (
-    protected formValidatorService: FormValidatorService,
-    private modalService: NgbModal,
-    private videoBlacklistValidatorsService: VideoBlacklistValidatorsService,
-    private videoBlacklistService: VideoBlacklistService,
-    private notifier: Notifier,
-    private redirectService: RedirectService,
-    private i18n: I18n
-  ) {
-    super()
-  }
-
-  ngOnInit () {
-    const defaultValues = { unfederate: 'true' }
-
-    this.buildForm({
-      reason: this.videoBlacklistValidatorsService.VIDEO_BLACKLIST_REASON,
-      unfederate: null
-    }, defaultValues)
-  }
-
-  show () {
-    this.openedModal = this.modalService.open(this.modal, { centered: true, keyboard: false })
-  }
-
-  hide () {
-    this.openedModal.close()
-    this.openedModal = null
-  }
-
-  blacklist () {
-    const reason = this.form.value[ 'reason' ] || undefined
-    const unfederate = this.video.isLocal ? this.form.value[ 'unfederate' ] : undefined
-
-    this.videoBlacklistService.blacklistVideo(this.video.id, reason, unfederate)
-        .subscribe(
-          () => {
-            this.notifier.success(this.i18n('Video blacklisted.'))
-            this.hide()
-
-            this.video.blacklisted = true
-            this.video.blacklistedReason = reason
-
-            this.videoBlacklisted.emit()
-          },
-
-          err => this.notifier.error(err.message)
-        )
-  }
-}
diff --git a/client/src/app/shared/video/modals/video-block.component.html b/client/src/app/shared/video/modals/video-block.component.html
new file mode 100644 (file)
index 0000000..a8dd30b
--- /dev/null
@@ -0,0 +1,45 @@
+<ng-template #modal>
+  <div class="modal-header">
+    <h4 i18n class="modal-title">Blocklist video</h4>
+    <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon>
+  </div>
+
+  <div class="modal-body">
+
+    <form novalidate [formGroup]="form" (ngSubmit)="block()">
+      <div class="form-group">
+        <textarea
+          i18n-placeholder placeholder="Reason..." formControlName="reason"
+          [ngClass]="{ 'input-error': formErrors['reason'] }" class="form-control"
+        ></textarea>
+        <div *ngIf="formErrors.reason" class="form-error">
+          {{ formErrors.reason }}
+        </div>
+      </div>
+
+      <div class="form-group" *ngIf="video.isLocal">
+        <my-peertube-checkbox
+          inputName="unfederate" formControlName="unfederate"
+          i18n-labelText labelText="Unfederate the video"
+        >
+          <ng-container ngProjectAs="description">
+            <span i18n>This will ask remote instances to delete it</span>
+          </ng-container>
+        </my-peertube-checkbox>
+      </div>
+
+      <div class="form-group inputs">
+        <input
+          type="button" role="button" i18n-value value="Cancel" class="action-button action-button-cancel"
+          (click)="hide()" (key.enter)="hide()"
+        >
+
+        <input
+          type="submit" i18n-value value="Submit" class="action-button-submit"
+          [disabled]="!form.valid"
+        >
+      </div>
+    </form>
+
+  </div>
+</ng-template>
diff --git a/client/src/app/shared/video/modals/video-block.component.scss b/client/src/app/shared/video/modals/video-block.component.scss
new file mode 100644 (file)
index 0000000..afcdb9a
--- /dev/null
@@ -0,0 +1,6 @@
+@import 'variables';
+@import 'mixins';
+
+textarea {
+  @include peertube-textarea(100%, 100px);
+}
diff --git a/client/src/app/shared/video/modals/video-block.component.ts b/client/src/app/shared/video/modals/video-block.component.ts
new file mode 100644 (file)
index 0000000..1a25e05
--- /dev/null
@@ -0,0 +1,75 @@
+import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'
+import { Notifier, RedirectService } from '@app/core'
+import { VideoBlockService } from '../../video-block'
+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 { FormReactive, VideoBlockValidatorsService } from '@app/shared/forms'
+import { Video } from '@app/shared/video/video.model'
+
+@Component({
+  selector: 'my-video-block',
+  templateUrl: './video-block.component.html',
+  styleUrls: [ './video-block.component.scss' ]
+})
+export class VideoBlockComponent extends FormReactive implements OnInit {
+  @Input() video: Video = null
+
+  @ViewChild('modal', { static: true }) modal: NgbModal
+
+  @Output() videoBlocked = new EventEmitter()
+
+  error: string = null
+
+  private openedModal: NgbModalRef
+
+  constructor (
+    protected formValidatorService: FormValidatorService,
+    private modalService: NgbModal,
+    private videoBlockValidatorsService: VideoBlockValidatorsService,
+    private videoBlocklistService: VideoBlockService,
+    private notifier: Notifier,
+    private i18n: I18n
+  ) {
+    super()
+  }
+
+  ngOnInit () {
+    const defaultValues = { unfederate: 'true' }
+
+    this.buildForm({
+      reason: this.videoBlockValidatorsService.VIDEO_BLOCK_REASON,
+      unfederate: null
+    }, defaultValues)
+  }
+
+  show () {
+    this.openedModal = this.modalService.open(this.modal, { centered: true, keyboard: false })
+  }
+
+  hide () {
+    this.openedModal.close()
+    this.openedModal = null
+  }
+
+  block () {
+    const reason = this.form.value[ 'reason' ] || undefined
+    const unfederate = this.video.isLocal ? this.form.value[ 'unfederate' ] : undefined
+
+    this.videoBlocklistService.blockVideo(this.video.id, reason, unfederate)
+        .subscribe(
+          () => {
+            this.notifier.success(this.i18n('Video blocked.'))
+            this.hide()
+
+            this.video.blacklisted = true
+            this.video.blockedReason = reason
+
+            this.videoBlocked.emit()
+          },
+
+          err => this.notifier.error(err.message)
+        )
+  }
+}
index ec03fa55d13eb77fbffae7353d3513b7a674c4d1..3c8271b655168cdca732f0a43a669c4c4af72af5 100644 (file)
@@ -17,5 +17,5 @@
 
   <my-video-download #videoDownloadModal></my-video-download>
   <my-video-report #videoReportModal [video]="video"></my-video-report>
-  <my-video-blacklist #videoBlacklistModal [video]="video" (videoBlacklisted)="onVideoBlacklisted()"></my-video-blacklist>
+  <my-video-block #videoBlockModal [video]="video" (videoBlocked)="onVideoBlocked()"></my-video-block>
 </ng-container>
index 4e5fc64762579e50f5a9308c27d95e9a27bd61a5..1f57636108f82594a1370e2dbecbf5db105338c9 100644 (file)
@@ -9,8 +9,8 @@ import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'
 import { VideoAddToPlaylistComponent } from '@app/shared/video-playlist/video-add-to-playlist.component'
 import { VideoDownloadComponent } from '@app/shared/video/modals/video-download.component'
 import { VideoReportComponent } from '@app/shared/video/modals/video-report.component'
-import { VideoBlacklistComponent } from '@app/shared/video/modals/video-blacklist.component'
-import { VideoBlacklistService } from '@app/shared/video-blacklist'
+import { VideoBlockComponent } from '@app/shared/video/modals/video-block.component'
+import { VideoBlockService } from '@app/shared/video-block'
 import { ScreenService } from '@app/shared/misc/screen.service'
 import { VideoCaption } from '@shared/models'
 import { RedundancyService } from '@app/shared/video/redundancy.service'
@@ -36,7 +36,7 @@ export class VideoActionsDropdownComponent implements OnChanges {
 
   @ViewChild('videoDownloadModal') videoDownloadModal: VideoDownloadComponent
   @ViewChild('videoReportModal') videoReportModal: VideoReportComponent
-  @ViewChild('videoBlacklistModal') videoBlacklistModal: VideoBlacklistComponent
+  @ViewChild('videoBlockModal') videoBlockModal: VideoBlockComponent
 
   @Input() video: Video | VideoDetails
   @Input() videoCaptions: VideoCaption[] = []
@@ -59,8 +59,8 @@ export class VideoActionsDropdownComponent implements OnChanges {
   @Input() buttonDirection: DropdownDirection = 'vertical'
 
   @Output() videoRemoved = new EventEmitter()
-  @Output() videoUnblacklisted = new EventEmitter()
-  @Output() videoBlacklisted = new EventEmitter()
+  @Output() videoUnblocked = new EventEmitter()
+  @Output() videoBlocked = new EventEmitter()
   @Output() modalOpened = new EventEmitter()
 
   videoActions: DropdownAction<{ video: Video }>[][] = []
@@ -71,7 +71,7 @@ export class VideoActionsDropdownComponent implements OnChanges {
     private authService: AuthService,
     private notifier: Notifier,
     private confirmService: ConfirmService,
-    private videoBlacklistService: VideoBlacklistService,
+    private videoBlocklistService: VideoBlockService,
     private screenService: ScreenService,
     private videoService: VideoService,
     private redundancyService: RedundancyService,
@@ -117,10 +117,10 @@ export class VideoActionsDropdownComponent implements OnChanges {
     this.videoReportModal.show()
   }
 
-  showBlacklistModal () {
+  showBlockModal () {
     this.modalOpened.emit()
 
-    this.videoBlacklistModal.show()
+    this.videoBlockModal.show()
   }
 
   /* Actions checker */
@@ -133,12 +133,12 @@ export class VideoActionsDropdownComponent implements OnChanges {
     return this.video.isRemovableBy(this.user)
   }
 
-  isVideoBlacklistable () {
-    return this.video.isBlackistableBy(this.user)
+  isVideoBlockable () {
+    return this.video.isBlockableBy(this.user)
   }
 
-  isVideoUnblacklistable () {
-    return this.video.isUnblacklistableBy(this.user)
+  isVideoUnblockable () {
+    return this.video.isUnblockableBy(this.user)
   }
 
   isVideoDownloadable () {
@@ -151,22 +151,22 @@ export class VideoActionsDropdownComponent implements OnChanges {
 
   /* Action handlers */
 
-  async unblacklistVideo () {
+  async unblockVideo () {
     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 unblock this video? It will be available again in the videos list.'
     )
 
-    const res = await this.confirmService.confirm(confirmMessage, this.i18n('Unblacklist'))
+    const res = await this.confirmService.confirm(confirmMessage, this.i18n('Unblock'))
     if (res === false) return
 
-    this.videoBlacklistService.removeVideoFromBlacklist(this.video.id).subscribe(
+    this.videoBlocklistService.unblockVideo(this.video.id).subscribe(
       () => {
-        this.notifier.success(this.i18n('Video {{name}} removed from the blacklist.', { name: this.video.name }))
+        this.notifier.success(this.i18n('Video {{name}} unblocked.', { name: this.video.name }))
 
         this.video.blacklisted = false
-        this.video.blacklistedReason = null
+        this.video.blockedReason = null
 
-        this.videoUnblacklisted.emit()
+        this.videoUnblocked.emit()
       },
 
       err => this.notifier.error(err.message)
@@ -203,8 +203,8 @@ export class VideoActionsDropdownComponent implements OnChanges {
       )
   }
 
-  onVideoBlacklisted () {
-    this.videoBlacklisted.emit()
+  onVideoBlocked () {
+    this.videoBlocked.emit()
   }
 
   getPlaylistDropdownPlacement () {
@@ -239,16 +239,16 @@ export class VideoActionsDropdownComponent implements OnChanges {
           isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.update && this.isVideoUpdatable()
         },
         {
-          label: this.i18n('Blacklist'),
-          handler: () => this.showBlacklistModal(),
+          label: this.i18n('Block'),
+          handler: () => this.showBlockModal(),
           iconName: 'no',
-          isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.blacklist && this.isVideoBlacklistable()
+          isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.blacklist && this.isVideoBlockable()
         },
         {
-          label: this.i18n('Unblacklist'),
-          handler: () => this.unblacklistVideo(),
+          label: this.i18n('Unblock'),
+          handler: () => this.unblockVideo(),
           iconName: 'undo',
-          isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.blacklist && this.isVideoUnblacklistable()
+          isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.blacklist && this.isVideoUnblockable()
         },
         {
           label: this.i18n('Mirror'),
index 3e23cf18c0ffc774cefdab2907533af8a0d6c235..575505f63cb9f3e88fc9b160ef1bd96a181941f5 100644 (file)
@@ -43,9 +43,9 @@
         </div>
       </div>
 
-      <div *ngIf="displayOptions.blacklistInfo && video.blacklisted" class="video-info-blacklisted">
-        <span class="blacklisted-label" i18n>Blacklisted</span>
-        <span class="blacklisted-reason" *ngIf="video.blacklistedReason">{{ video.blacklistedReason }}</span>
+      <div *ngIf="displayOptions.blacklistInfo && video.blacklisted" class="video-info-blocked">
+        <span class="blocked-label" i18n>Blocked</span>
+        <span class="blocked-reason" *ngIf="video.blockedReason">{{ video.blockedReason }}</span>
       </div>
 
       <div i18n *ngIf="displayOptions.nsfw && video.nsfw" class="video-info-nsfw">
@@ -57,7 +57,7 @@
       <!-- FIXME: remove bottom placement when overflow is fixed in bootstrap dropdown: https://github.com/ng-bootstrap/ng-bootstrap/issues/3495 -->
       <my-video-actions-dropdown
         *ngIf="showActions" [video]="video" [displayOptions]="videoActionsDisplayOptions" placement="bottom-left bottom-right left auto"
-        (videoRemoved)="onVideoRemoved()" (videoBlacklisted)="onVideoBlacklisted()" (videoUnblacklisted)="onVideoUnblacklisted()"
+        (videoRemoved)="onVideoRemoved()" (videoBlocked)="onVideoBlocked()" (videoUnblocked)="onVideoUnblocked()"
       ></my-video-actions-dropdown>
     </div>
   </div>
index 849bd54bb0d2df613f8e102e6c8bc68b86945c8f..34f34f2287a8fb08bd998a17a7dbf6b4daff503b 100644 (file)
@@ -45,15 +45,15 @@ $more-margin-right: 15px;
       }
 
       .video-info-privacy,
-      .video-info-blacklisted .blacklisted-label,
+      .video-info-blocked .blocked-label,
       .video-info-nsfw {
         font-weight: $font-semibold;
       }
 
-      .video-info-blacklisted {
+      .video-info-blocked {
         color: red;
 
-        .blacklisted-reason::before {
+        .blocked-reason::before {
           content: ' - ';
         }
       }
@@ -160,7 +160,7 @@ $more-margin-right: 15px;
           margin-top: 5px;
         }
 
-        .video-info-blacklisted {
+        .video-info-blocked {
           margin-top: 3px;
         }
       }
index aa1726ca7b6097a13cdc1ef777be12f6b4bf9449..f0b0992e2ad4eb3056a7390f629f3d6c1ca73613 100644 (file)
@@ -59,8 +59,8 @@ export class VideoMiniatureComponent implements OnInit {
 
   @Input() useLazyLoadUrl = false
 
-  @Output() videoBlacklisted = new EventEmitter()
-  @Output() videoUnblacklisted = new EventEmitter()
+  @Output() videoBlocked = new EventEmitter()
+  @Output() videoUnblocked = new EventEmitter()
   @Output() videoRemoved = new EventEmitter()
 
   videoActionsDisplayOptions: VideoActionsDisplayType = {
@@ -184,12 +184,12 @@ export class VideoMiniatureComponent implements OnInit {
     this.loadWatchLater()
   }
 
-  onVideoBlacklisted () {
-    this.videoBlacklisted.emit()
+  onVideoBlocked () {
+    this.videoBlocked.emit()
   }
 
-  onVideoUnblacklisted () {
-    this.videoUnblacklisted.emit()
+  onVideoUnblocked () {
+    this.videoUnblocked.emit()
   }
 
   onVideoRemoved () {
index 97759f9c1b3f7679d8bafb14c92fa723670bebb3..2b3d915ef9d45b531bcf7bf3658606dadab191bd 100644 (file)
@@ -54,7 +54,7 @@ export class Video implements VideoServerModel {
   state?: VideoConstant<VideoState>
   scheduledUpdate?: VideoScheduleUpdate
   blacklisted?: boolean
-  blacklistedReason?: string
+  blockedReason?: string
 
   account: {
     id: number
@@ -140,7 +140,7 @@ export class Video implements VideoServerModel {
     if (this.state) this.state.label = peertubeTranslate(this.state.label, translations)
 
     this.blacklisted = hash.blacklisted
-    this.blacklistedReason = hash.blacklistedReason
+    this.blockedReason = hash.blacklistedReason
 
     this.userHistory = hash.userHistory
 
@@ -163,12 +163,12 @@ export class Video implements VideoServerModel {
     return user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.REMOVE_ANY_VIDEO))
   }
 
-  isBlackistableBy (user: AuthUser) {
-    return this.blacklisted !== true && user && user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) === true
+  isBlockableBy (user: AuthUser) {
+    return this.blacklisted !== true && user && user.hasRight(UserRight.MANAGE_VIDEO_BLOCKS) === true
   }
 
-  isUnblacklistableBy (user: AuthUser) {
-    return this.blacklisted === true && user && user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) === true
+  isUnblockableBy (user: AuthUser) {
+    return this.blacklisted === true && user && user.hasRight(UserRight.MANAGE_VIDEO_BLOCKS) === true
   }
 
   isUpdatableBy (user: AuthUser) {
index 433543a7bc7c8455c209cdca93afd21db30535e4..63103e2e7e34856e9a0d9bbdac32d15b0ea81314 100644 (file)
@@ -29,8 +29,8 @@
     </div>
 
     <div class="col-md-12 alert alert-danger" *ngIf="video?.blacklisted">
-      <div class="blacklisted-label" i18n>This video is blacklisted.</div>
-      {{ video.blacklistedReason }}
+      <div class="blocked-label" i18n>This video is blocked.</div>
+      {{ video.blockedReason }}
     </div>
   </div>
 
index 8be0bab1d32404c952a426fcfce88ccbe848c3e5..e0d41117a0aabd9e9806778464500a29daca6a75 100644 (file)
@@ -45,7 +45,7 @@ $video-info-margin-left: 44px;
   }
 }
 
-.blacklisted-label {
+.blocked-label {
   font-weight: $font-semibold;
 }
 
index 3790c7f6aa6bdbfb8a8502c18cbaaea15e0dbacf..9f726cf35e37fc4f2e70d735c0fc56f5c56d425d 100644 (file)
@@ -335,7 +335,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
       this.videoCaptionService.listCaptions(videoId)
     ])
       .pipe(
-        // If 401, the video is private or blacklisted so redirect to 404
+        // If 401, the video is private or blocklisted so redirect to 404
         catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [ 400, 401, 403, 404 ]))
       )
       .subscribe(([ video, captionsResult ]) => {
@@ -364,7 +364,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
 
     this.playlistService.getVideoPlaylist(playlistId)
       .pipe(
-        // If 401, the video is private or blacklisted so redirect to 404
+        // If 401, the video is private or blocklisted so redirect to 404
         catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [ 400, 401, 403, 404 ]))
       )
       .subscribe(playlist => {
index c6bdfee4632777f635c90882a0560148ea9b9409..e4568c30952714fcd0f0be13a8cba50e48f4a021 100644 (file)
@@ -13,7 +13,7 @@
     </div>
 
     <div *ngFor="let video of (videos$ | async); let i = index; let length = count">
-      <my-video-miniature [displayOptions]="displayOptions" [video]="video" [user]="user" (videoBlacklisted)="onVideoRemoved()" (videoRemoved)="onVideoRemoved()">
+      <my-video-miniature [displayOptions]="displayOptions" [video]="video" [user]="user" (videoBlocked)="onVideoRemoved()" (videoRemoved)="onVideoRemoved()">
       </my-video-miniature>
       
       <hr *ngIf="!playlist && i == 0 && length > 1" />
diff --git a/client/src/assets/images/global/robot.svg b/client/src/assets/images/global/robot.svg
new file mode 100644 (file)
index 0000000..46db9ba
--- /dev/null
@@ -0,0 +1,11 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" width="24px" viewBox="0 0 24 24">
+  <defs/>
+  <g fill="none" fill-rule="evenodd">
+    <rect width="22" height="14" x="1" y="7" stroke="#000" stroke-width="2" rx="2"/>
+    <path fill="#000" d="M11 3h2v4h-2z"/>
+    <circle cx="12" cy="2" r="2" fill="#000"/>
+    <circle cx="18" cy="12" r="2" fill="#000"/>
+    <circle cx="6" cy="12" r="2" fill="#000"/>
+    <path stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 15c0 1.1.9 2 2 2h0a2 2 0 002-2"/>
+  </g>
+</svg>
index 3b25ceea28bbbfe04e3104999024180a0209eb76..2c6948923d8d652b3f0002b53a7d13b038447a78 100644 (file)
@@ -23,14 +23,14 @@ const blacklistRouter = express.Router()
 
 blacklistRouter.post('/:videoId/blacklist',
   authenticate,
-  ensureUserHasRight(UserRight.MANAGE_VIDEO_BLACKLIST),
+  ensureUserHasRight(UserRight.MANAGE_VIDEO_BLOCKS),
   asyncMiddleware(videosBlacklistAddValidator),
   asyncMiddleware(addVideoToBlacklistController)
 )
 
 blacklistRouter.get('/blacklist',
   authenticate,
-  ensureUserHasRight(UserRight.MANAGE_VIDEO_BLACKLIST),
+  ensureUserHasRight(UserRight.MANAGE_VIDEO_BLOCKS),
   paginationValidator,
   blacklistSortValidator,
   setBlacklistSort,
@@ -41,14 +41,14 @@ blacklistRouter.get('/blacklist',
 
 blacklistRouter.put('/:videoId/blacklist',
   authenticate,
-  ensureUserHasRight(UserRight.MANAGE_VIDEO_BLACKLIST),
+  ensureUserHasRight(UserRight.MANAGE_VIDEO_BLOCKS),
   asyncMiddleware(videosBlacklistUpdateValidator),
   asyncMiddleware(updateVideoBlacklistController)
 )
 
 blacklistRouter.delete('/:videoId/blacklist',
   authenticate,
-  ensureUserHasRight(UserRight.MANAGE_VIDEO_BLACKLIST),
+  ensureUserHasRight(UserRight.MANAGE_VIDEO_BLOCKS),
   asyncMiddleware(videosBlacklistRemoveValidator),
   asyncMiddleware(removeVideoFromBlacklistController)
 )
index 17cb3b00b6b313f62474cb012ddeda3cd290cbea..de6726b8f993226221bcab283d129fb180711aff 100644 (file)
@@ -1,7 +1,7 @@
 import validator from 'validator'
 import { exists } from './misc'
 import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
-import { VideoBlacklistType } from '../../../shared/models/videos'
+import { VideoBlockType } from '../../../shared/models/videos'
 
 const VIDEO_BLACKLIST_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_BLACKLIST
 
@@ -10,7 +10,7 @@ function isVideoBlacklistReasonValid (value: string) {
 }
 
 function isVideoBlacklistTypeValid (value: any) {
-  return exists(value) && validator.isInt('' + value) && VideoBlacklistType[value] !== undefined
+  return exists(value) && validator.isInt('' + value) && VideoBlockType[value] !== undefined
 }
 
 // ---------------------------------------------------------------------------
index f79ae5ec7e6512db4c1960525b330b1a46001033..22c82e431ac16b4b6d9bce470645ce9ae31928e3 100644 (file)
@@ -1,5 +1,5 @@
 import * as Sequelize from 'sequelize'
-import { VideoBlacklistType } from '../../../shared/models/videos'
+import { VideoBlockType } from '../../../shared/models/videos'
 
 async function up (utils: {
   transaction: Sequelize.Transaction
@@ -18,7 +18,7 @@ async function up (utils: {
   }
 
   {
-    const query = 'UPDATE "videoBlacklist" SET "type" = ' + VideoBlacklistType.MANUAL
+    const query = 'UPDATE "videoBlacklist" SET "type" = ' + VideoBlockType.MANUAL
     await utils.sequelize.query(query)
   }
 
index 89f91e0311c6db307f7ff4a1c294c207dfae431f..3e90bb57e8a461a38ae9aa06c4c939f44810c023 100644 (file)
@@ -387,7 +387,7 @@ class Notifier {
   }
 
   private async notifyModeratorsOfVideoAutoBlacklist (videoBlacklist: MVideoBlacklistLightVideo) {
-    const moderators = await UserModel.listWithRight(UserRight.MANAGE_VIDEO_BLACKLIST)
+    const moderators = await UserModel.listWithRight(UserRight.MANAGE_VIDEO_BLOCKS)
     if (moderators.length === 0) return
 
     logger.info('Notifying %s moderators of video auto-blacklist %s.', moderators.length, videoBlacklist.Video.url)
@@ -398,7 +398,7 @@ class Notifier {
 
     async function notificationCreator (user: MUserWithNotificationSetting) {
       const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
-        type: UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS,
+        type: UserNotificationType.VIDEO_AUTO_BLOCK_FOR_MODERATORS,
         userId: user.id,
         videoBlacklistId: videoBlacklist.id
       })
@@ -426,7 +426,7 @@ class Notifier {
 
     async function notificationCreator (user: MUserWithNotificationSetting) {
       const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
-        type: UserNotificationType.BLACKLIST_ON_MY_VIDEO,
+        type: UserNotificationType.BLOCK_ON_MY_VIDEO,
         userId: user.id,
         videoBlacklistId: videoBlacklist.id
       })
@@ -454,7 +454,7 @@ class Notifier {
 
     async function notificationCreator (user: MUserWithNotificationSetting) {
       const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
-        type: UserNotificationType.UNBLACKLIST_ON_MY_VIDEO,
+        type: UserNotificationType.UNBLOCK_ON_MY_VIDEO,
         userId: user.id,
         videoId: video.id
       })
index bd60c6201c93d1cde2ff762b717103f5ef2dc714..f1657e8f1dd509133ad1ea210e47824745b0b075 100644 (file)
@@ -8,7 +8,7 @@ import {
   MVideoFullLight,
   MVideoWithBlacklistLight
 } from '@server/typings/models'
-import { UserRight, VideoBlacklistCreate, VideoBlacklistType } from '../../shared/models'
+import { UserRight, VideoBlacklistCreate, VideoBlockType } from '../../shared/models'
 import { UserAdminFlag } from '../../shared/models/users/user-flag.model'
 import { logger } from '../helpers/logger'
 import { CONFIG } from '../initializers/config'
@@ -39,7 +39,7 @@ async function autoBlacklistVideoIfNeeded (parameters: {
     videoId: video.id,
     unfederated: true,
     reason: 'Auto-blacklisted. Moderator review required.',
-    type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED
+    type: VideoBlockType.AUTO_BEFORE_PUBLISHED
   }
   const [ videoBlacklist ] = await VideoBlacklistModel.findOrCreate<MVideoBlacklistVideo>({
     where: {
@@ -64,7 +64,7 @@ async function blacklistVideo (videoInstance: MVideoAccountLight, options: Video
     videoId: videoInstance.id,
     unfederated: options.unfederate === true,
     reason: options.reason,
-    type: VideoBlacklistType.MANUAL
+    type: VideoBlockType.MANUAL
   }
   )
   blacklist.Video = videoInstance
@@ -94,7 +94,7 @@ async function unblacklistVideo (videoBlacklist: MVideoBlacklist, video: MVideoF
 
   Notifier.Instance.notifyOnVideoUnblacklist(video)
 
-  if (videoBlacklistType === VideoBlacklistType.AUTO_BEFORE_PUBLISHED) {
+  if (videoBlacklistType === VideoBlockType.AUTO_BEFORE_PUBLISHED) {
     Notifier.Instance.notifyOnVideoPublishedAfterRemovedFromAutoBlacklist(video)
 
     // Delete on object so new video notifications will send
@@ -126,7 +126,7 @@ function autoBlacklistNeeded (parameters: {
   if (!CONFIG.AUTO_BLACKLIST.VIDEOS.OF_USERS.ENABLED || !user) return false
   if (isRemote || isNew === false) return false
 
-  if (user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) || user.hasAdminFlag(UserAdminFlag.BY_PASS_VIDEO_AUTO_BLACKLIST)) return false
+  if (user.hasRight(UserRight.MANAGE_VIDEO_BLOCKS) || user.hasAdminFlag(UserAdminFlag.BYPASS_VIDEO_AUTO_BLOCK)) return false
 
   return true
 }
index fbd3080c6a82c5803c716f970bb4ea3d083537b4..4ea175583b66806c98060665483e3ff5c88fe72f 100644 (file)
@@ -739,11 +739,11 @@ export class UserModel extends Model<UserModel> {
     const videoUserId = video.VideoChannel.Account.userId
 
     if (video.isBlacklisted()) {
-      return videoUserId === this.id || this.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)
+      return videoUserId === this.id || this.hasRight(UserRight.MANAGE_VIDEO_BLOCKS)
     }
 
     if (video.privacy === VideoPrivacy.PRIVATE) {
-      return video.VideoChannel && videoUserId === this.id || this.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)
+      return video.VideoChannel && videoUserId === this.id || this.hasRight(UserRight.MANAGE_VIDEO_BLOCKS)
     }
 
     if (video.privacy === VideoPrivacy.INTERNAL) return true
index 8cbfe362e87e87646df9ce4ef312b2c06fa61c63..70a6ecb039e1c769dcc800e37201e51410282e52 100644 (file)
@@ -3,7 +3,7 @@ import { getBlacklistSort, SortType, throwIfNotValid, searchAttribute } from '..
 import { VideoModel } from './video'
 import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from './video-channel'
 import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist'
-import { VideoBlacklist, VideoBlacklistType } from '../../../shared/models/videos'
+import { VideoBlocklist, VideoBlockType } from '../../../shared/models/videos'
 import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
 import { FindOptions } from 'sequelize'
 import { ThumbnailModel } from './thumbnail'
@@ -34,7 +34,7 @@ export class VideoBlacklistModel extends Model<VideoBlacklistModel> {
   @Default(null)
   @Is('VideoBlacklistType', value => throwIfNotValid(value, isVideoBlacklistTypeValid, 'type'))
   @Column
-  type: VideoBlacklistType
+  type: VideoBlockType
 
   @CreatedAt
   createdAt: Date
@@ -59,7 +59,7 @@ export class VideoBlacklistModel extends Model<VideoBlacklistModel> {
     count: number
     sort: SortType
     search?: string
-    type?: VideoBlacklistType
+    type?: VideoBlockType
   }) {
     const { start, count, sort, search, type } = parameters
 
@@ -119,7 +119,7 @@ export class VideoBlacklistModel extends Model<VideoBlacklistModel> {
     return VideoBlacklistModel.findOne(query)
   }
 
-  toFormattedJSON (this: MVideoBlacklistFormattable): VideoBlacklist {
+  toFormattedJSON (this: MVideoBlacklistFormattable): VideoBlocklist {
     return {
       id: this.id,
       createdAt: this.createdAt,
index 6e737af15dcb583137b779163c3f9afe72547ed6..94d47408aa634ff42a9942b8526e76ff4faa45f3 100644 (file)
@@ -188,7 +188,7 @@ describe('Test users API validators', function () {
       videoQuota: -1,
       videoQuotaDaily: -1,
       role: UserRole.USER,
-      adminFlags: UserAdminFlag.BY_PASS_VIDEO_AUTO_BLACKLIST
+      adminFlags: UserAdminFlag.BYPASS_VIDEO_AUTO_BLOCK
     }
 
     it('Should fail with a too small username', async function () {
index 145f43980333144d9efcdacebff12545264c0581..b96c269892900a399aed52e06b4035a9208b3882 100644 (file)
@@ -24,7 +24,7 @@ import {
   checkBadSortPagination,
   checkBadStartPagination
 } from '../../../../shared/extra-utils/requests/check-api-params'
-import { VideoBlacklistType, VideoDetails } from '../../../../shared/models/videos'
+import { VideoBlockType, VideoDetails } from '../../../../shared/models/videos'
 import { expect } from 'chai'
 
 describe('Test video blacklist API validators', function () {
@@ -243,7 +243,7 @@ describe('Test video blacklist API validators', function () {
     })
 
     it('Should succeed with the correct parameters', async function () {
-      await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken, type: VideoBlacklistType.MANUAL })
+      await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken, type: VideoBlockType.MANUAL })
     })
   })
 
index c0cbce36099b0db6ca760d95d3d0981c5cb2f6c8..af5a5fd258d04c383e830b50d8e9891159f9b65f 100644 (file)
@@ -265,7 +265,7 @@ describe('Test users', function () {
         username: user.username,
         password: user.password,
         videoQuota: 2 * 1024 * 1024,
-        adminFlags: UserAdminFlag.BY_PASS_VIDEO_AUTO_BLACKLIST
+        adminFlags: UserAdminFlag.BYPASS_VIDEO_AUTO_BLOCK
       })
     })
 
@@ -292,7 +292,7 @@ describe('Test users', function () {
       }
 
       expect(userMe.adminFlags).to.be.undefined
-      expect(userGet.adminFlags).to.equal(UserAdminFlag.BY_PASS_VIDEO_AUTO_BLACKLIST)
+      expect(userGet.adminFlags).to.equal(UserAdminFlag.BYPASS_VIDEO_AUTO_BLOCK)
 
       expect(userMe.specialPlaylists).to.have.lengthOf(1)
       expect(userMe.specialPlaylists[0].type).to.equal(VideoPlaylistType.WATCH_LATER)
index 67bc0114c93815bffc39ca177953f1ef4b2b8b30..6e15893f3ac59eba04c64db2f48f7727c90591f9 100644 (file)
@@ -25,7 +25,7 @@ import {
 } from '../../../../shared/extra-utils/index'
 import { doubleFollow } from '../../../../shared/extra-utils/server/follows'
 import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { VideoBlacklist, VideoBlacklistType } from '../../../../shared/models/videos'
+import { VideoBlocklist, VideoBlockType } from '../../../../shared/models/videos'
 import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
 import { User, UserRole } from '../../../../shared/models/users'
 import { getMagnetURI, getYoutubeVideoUrl, importVideo } from '../../../../shared/extra-utils/videos/video-imports'
@@ -127,7 +127,7 @@ describe('Test video blacklist', function () {
       const res = await getBlacklistedVideosList({
         url: servers[0].url,
         token: servers[0].accessToken,
-        type: VideoBlacklistType.MANUAL
+        type: VideoBlockType.MANUAL
       })
 
       expect(res.body.total).to.equal(2)
@@ -141,7 +141,7 @@ describe('Test video blacklist', function () {
       const res = await getBlacklistedVideosList({
         url: servers[0].url,
         token: servers[0].accessToken,
-        type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED
+        type: VideoBlockType.AUTO_BEFORE_PUBLISHED
       })
 
       expect(res.body.total).to.equal(0)
@@ -219,7 +219,7 @@ describe('Test video blacklist', function () {
   })
 
   describe('When removing a blacklisted video', function () {
-    let videoToRemove: VideoBlacklist
+    let videoToRemove: VideoBlocklist
     let blacklist = []
 
     it('Should not have any video in videos list on server 1', async function () {
@@ -328,7 +328,7 @@ describe('Test video blacklist', function () {
     it('Should have the correct video blacklist unfederate attribute', async function () {
       const res = await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken, sort: 'createdAt' })
 
-      const blacklistedVideos: VideoBlacklist[] = res.body.data
+      const blacklistedVideos: VideoBlocklist[] = res.body.data
       const video3Blacklisted = blacklistedVideos.find(b => b.video.uuid === video3UUID)
       const video4Blacklisted = blacklistedVideos.find(b => b.video.uuid === video4UUID)
 
@@ -396,7 +396,7 @@ describe('Test video blacklist', function () {
           url: servers[0].url,
           accessToken: servers[0].accessToken,
           username: user.username,
-          adminFlags: UserAdminFlag.BY_PASS_VIDEO_AUTO_BLACKLIST,
+          adminFlags: UserAdminFlag.BYPASS_VIDEO_AUTO_BLOCK,
           password: user.password,
           role: UserRole.USER
         })
@@ -413,7 +413,7 @@ describe('Test video blacklist', function () {
       const res = await getBlacklistedVideosList({
         url: servers[0].url,
         token: servers[0].accessToken,
-        type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED
+        type: VideoBlockType.AUTO_BEFORE_PUBLISHED
       })
 
       expect(res.body.total).to.equal(1)
@@ -434,7 +434,7 @@ describe('Test video blacklist', function () {
         url: servers[0].url,
         token: servers[0].accessToken,
         sort: 'createdAt',
-        type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED
+        type: VideoBlockType.AUTO_BEFORE_PUBLISHED
       })
 
       expect(res.body.total).to.equal(2)
@@ -453,7 +453,7 @@ describe('Test video blacklist', function () {
         url: servers[0].url,
         token: servers[0].accessToken,
         sort: 'createdAt',
-        type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED
+        type: VideoBlockType.AUTO_BEFORE_PUBLISHED
       })
 
       expect(res.body.total).to.equal(3)
@@ -466,7 +466,7 @@ describe('Test video blacklist', function () {
       const res = await getBlacklistedVideosList({
         url: servers[0].url,
         token: servers[0].accessToken,
-        type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED
+        type: VideoBlockType.AUTO_BEFORE_PUBLISHED
       })
 
       expect(res.body.total).to.equal(3)
index bd00894c466b95a0d552f1c59b65d3205c5de56b..6f85bd450c8787b5001c00f4219a69c5b650555a 100644 (file)
@@ -455,7 +455,7 @@ async function checkNewVideoAbuseForModerators (base: CheckerBaseParams, videoUU
 }
 
 async function checkVideoAutoBlacklistForModerators (base: CheckerBaseParams, videoUUID: string, videoName: string, type: CheckerType) {
-  const notificationType = UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS
+  const notificationType = UserNotificationType.VIDEO_AUTO_BLOCK_FOR_MODERATORS
 
   function notificationChecker (notification: UserNotification, type: CheckerType) {
     if (type === 'presence') {
@@ -486,8 +486,8 @@ async function checkNewBlacklistOnMyVideo (
   blacklistType: 'blacklist' | 'unblacklist'
 ) {
   const notificationType = blacklistType === 'blacklist'
-    ? UserNotificationType.BLACKLIST_ON_MY_VIDEO
-    : UserNotificationType.UNBLACKLIST_ON_MY_VIDEO
+    ? UserNotificationType.BLOCK_ON_MY_VIDEO
+    : UserNotificationType.UNBLOCK_ON_MY_VIDEO
 
   function notificationChecker (notification: UserNotification) {
     expect(notification).to.not.be.undefined
index ba139ef95269ad7c682c62772098ccd9954e9f9d..c06b2aa5db74912ce10c3e0689df77323e775f8b 100644 (file)
@@ -1,5 +1,5 @@
 import * as request from 'supertest'
-import { VideoBlacklistType } from '../../models/videos'
+import { VideoBlockType } from '../../models/videos'
 import { makeGetRequest } from '..'
 
 function addVideoToBlacklist (
@@ -45,7 +45,7 @@ function getBlacklistedVideosList (parameters: {
   url: string
   token: string
   sort?: string
-  type?: VideoBlacklistType
+  type?: VideoBlockType
   specialStatus?: number
 }) {
   const { url, token, sort, type, specialStatus = 200 } = parameters
index f5759f18f20d6bd6ed1bcc3a0ca736c592b6df4c..e8b5a5c50a4dc85e667833c6a191c99c7778f581 100644 (file)
@@ -1,4 +1,4 @@
 export enum UserAdminFlag {
   NONE = 0,
-  BY_PASS_VIDEO_AUTO_BLACKLIST = 1 << 0
+  BYPASS_VIDEO_AUTO_BLOCK = 1 << 0
 }
index e9be1ca7fd76c6a7f844f6304dcb6f45c63ad7f8..2329503a8a0a0c8e8a989ee4988e27194594c917 100644 (file)
@@ -5,8 +5,8 @@ export enum UserNotificationType {
   NEW_COMMENT_ON_MY_VIDEO = 2,
   NEW_VIDEO_ABUSE_FOR_MODERATORS = 3,
 
-  BLACKLIST_ON_MY_VIDEO = 4,
-  UNBLACKLIST_ON_MY_VIDEO = 5,
+  BLOCK_ON_MY_VIDEO = 4,
+  UNBLOCK_ON_MY_VIDEO = 5,
 
   MY_VIDEO_PUBLISHED = 6,
 
@@ -17,7 +17,7 @@ export enum UserNotificationType {
   NEW_FOLLOW = 10,
   COMMENT_MENTION = 11,
 
-  VIDEO_AUTO_BLACKLIST_FOR_MODERATORS = 12,
+  VIDEO_AUTO_BLOCK_FOR_MODERATORS = 12,
 
   NEW_INSTANCE_FOLLOWER = 13,
 
index 2f88a65ded827a7c24be60119586bca7f2c9903b..3fb760709fec4c673d9269243dd7924bc7da6c27 100644 (file)
@@ -20,7 +20,7 @@ export enum UserRight {
   MANAGE_ACCOUNTS_BLOCKLIST,
   MANAGE_SERVERS_BLOCKLIST,
 
-  MANAGE_VIDEO_BLACKLIST,
+  MANAGE_VIDEO_BLOCKS,
 
   REMOVE_ANY_VIDEO,
   REMOVE_ANY_VIDEO_CHANNEL,
index 2b08b585029901d17c0e417cba6d381f38c1c845..30ec5edce2440812e92dd2e151aae32eac2b432d 100644 (file)
@@ -19,7 +19,7 @@ const userRoleRights: { [ id in UserRole ]: UserRight[] } = {
   ],
 
   [UserRole.MODERATOR]: [
-    UserRight.MANAGE_VIDEO_BLACKLIST,
+    UserRight.MANAGE_VIDEO_BLOCKS,
     UserRight.MANAGE_VIDEO_ABUSES,
     UserRight.REMOVE_ANY_VIDEO,
     UserRight.REMOVE_ANY_VIDEO_CHANNEL,
index a6e0ef175a59d0dca83ebe3112a311ea48e5af64..e6090b1e93adc631080d6a9ac99f62802d1d794c 100644 (file)
@@ -1,15 +1,15 @@
 import { Video } from '../video.model'
 
-export enum VideoBlacklistType {
+export enum VideoBlockType {
   MANUAL = 1,
   AUTO_BEFORE_PUBLISHED = 2
 }
 
-export interface VideoBlacklist {
+export interface VideoBlocklist {
   id: number
   unfederated: boolean
   reason?: string
-  type: VideoBlacklistType
+  type: VideoBlockType
 
   video: Video