Merge branch 'blacklist' into 'develop'
rename blacklist to block/blocklist, merge block and auto-block views See merge request framasoft/peertube/PeerTube!30
This commit is contained in:
commit
fa58a19819
|
@ -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,7 +36,7 @@ export class AdminComponent implements OnInit {
|
|||
return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_ABUSES)
|
||||
}
|
||||
|
||||
hasVideoBlacklistRight () {
|
||||
hasVideoBlocklistRight () {
|
||||
return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -430,7 +430,7 @@
|
|||
<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>
|
||||
|
@ -671,16 +671,16 @@
|
|||
<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>
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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,7 +24,7 @@ export class ModerationComponent implements OnInit {
|
|||
return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_ABUSES)
|
||||
}
|
||||
|
||||
hasVideoBlacklistRight () {
|
||||
hasVideoBlocklistRight () {
|
||||
return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)
|
||||
}
|
||||
|
||||
|
|
|
@ -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/list',
|
||||
component: VideoBlacklistListComponent,
|
||||
path: 'video-blacklist',
|
||||
redirectTo: 'video-blocks/list',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
{
|
||||
path: 'video-blocks/list',
|
||||
component: VideoBlockListComponent,
|
||||
canActivate: [ UserRightGuard ],
|
||||
data: {
|
||||
userRight: UserRight.MANAGE_VIDEO_BLACKLIST,
|
||||
meta: {
|
||||
title: 'Blacklisted videos'
|
||||
title: 'Videos blocked'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 blocked.'))
|
||||
|
||||
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 unblocked.'))
|
||||
|
||||
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 () {
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
export * from './video-auto-blacklist-list.component'
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
export * from './video-blacklist-list.component'
|
|
@ -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>
|
||||
|
|
@ -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)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './video-block-list.component'
|
|
@ -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>
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 { 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'
|
||||
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: (VideoBlacklist & { reasonHtml?: string })[] = []
|
||||
totalRecords = 0
|
||||
sort: SortMeta = { field: 'createdAt', order: -1 }
|
||||
pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
|
||||
blocklistTypeFilter: VideoBlacklistType = undefined
|
||||
|
||||
videoBlocklistActions: DropdownAction<VideoBlacklist>[][] = []
|
||||
|
||||
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.blocklistTypeFilter = VideoBlacklistType.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: VideoBlacklist) {
|
||||
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: VideoBlacklist) {
|
||||
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)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -52,7 +52,7 @@ export class UserCreateComponent extends UserEdit implements OnInit {
|
|||
role: this.userValidatorsService.USER_ROLE,
|
||||
videoQuota: this.userValidatorsService.USER_VIDEO_QUOTA,
|
||||
videoQuotaDaily: this.userValidatorsService.USER_VIDEO_QUOTA_DAILY,
|
||||
byPassAutoBlacklist: null
|
||||
byPassAutoBlock: null
|
||||
}, defaultValues)
|
||||
}
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@
|
|||
|
||||
<div class="form-group">
|
||||
<my-peertube-checkbox
|
||||
inputName="byPassAutoBlacklist" formControlName="byPassAutoBlacklist"
|
||||
inputName="byPassAutoBlock" formControlName="byPassAutoBlock"
|
||||
i18n-labelText labelText="Doesn't need review before a video goes public"
|
||||
></my-peertube-checkbox>
|
||||
</div>
|
||||
|
|
|
@ -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.byPassAutoBlock ? UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST : UserAdminFlag.NONE
|
||||
}
|
||||
|
||||
protected buildQuotaOptions () {
|
||||
|
|
|
@ -56,7 +56,7 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
|
|||
role: this.userValidatorsService.USER_ROLE,
|
||||
videoQuota: this.userValidatorsService.USER_VIDEO_QUOTA,
|
||||
videoQuotaDaily: this.userValidatorsService.USER_VIDEO_QUOTA_DAILY,
|
||||
byPassAutoBlacklist: null
|
||||
byPassAutoBlock: null
|
||||
}, defaultValues)
|
||||
|
||||
this.paramsSub = this.route.params.subscribe(routeParams => {
|
||||
|
@ -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
|
||||
byPassAutoBlock: userJson.adminFlags & UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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'),
|
||||
|
|
|
@ -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_BLACKLIST]: '/admin/moderation/video-blocks',
|
||||
[UserRight.MANAGE_JOBS]: '/admin/jobs',
|
||||
[UserRight.MANAGE_CONFIGURATION]: '/admin/config'
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -4,15 +4,15 @@ import { Injectable } from '@angular/core'
|
|||
import { BuildFormValidator } from '@app/shared'
|
||||
|
||||
@Injectable()
|
||||
export class VideoBlacklistValidatorsService {
|
||||
readonly VIDEO_BLACKLIST_REASON: BuildFormValidator
|
||||
export class VideoBlockValidatorsService {
|
||||
readonly VIDEO_BLOCK_REASON: BuildFormValidator
|
||||
|
||||
constructor (private i18n: I18n) {
|
||||
this.VIDEO_BLACKLIST_REASON = {
|
||||
this.VIDEO_BLOCK_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.')
|
||||
'minlength': this.i18n('Block reason must be at least 2 characters long.'),
|
||||
'maxlength': this.i18n('Block reason cannot be more than 300 characters long.')
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<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>
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
|||
<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>
|
||||
|
||||
|
@ -54,7 +54,7 @@
|
|||
<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">automatically blocked</a>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
export * from './video-blacklist.service'
|
|
@ -0,0 +1 @@
|
|||
export * from './video-block.service'
|
|
@ -4,13 +4,11 @@ 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 {
|
||||
export class VideoBlockService {
|
||||
private static BASE_VIDEOS_URL = environment.apiUrl + '/api/v1/videos/'
|
||||
|
||||
constructor (
|
||||
|
@ -19,9 +17,9 @@ export class VideoBlacklistService {
|
|||
private restExtractor: RestExtractor
|
||||
) {}
|
||||
|
||||
listBlacklist (options: {
|
||||
pagination: RestPagination,
|
||||
sort: SortMeta,
|
||||
listBlocks (options: {
|
||||
pagination: RestPagination
|
||||
sort: SortMeta
|
||||
search?: string
|
||||
type?: VideoBlacklistType
|
||||
}): Observable<ResultList<VideoBlacklist>> {
|
||||
|
@ -30,57 +28,48 @@ export class VideoBlacklistService {
|
|||
let params = new HttpParams()
|
||||
params = this.restService.addRestGetParams(params, pagination, sort)
|
||||
|
||||
if (search) params = params.append('search', search)
|
||||
if (search) {
|
||||
const filters = this.restService.parseQueryStringFilter(search, {
|
||||
type: {
|
||||
prefix: 'type:',
|
||||
handler: v => {
|
||||
if (v === 'manual') return VideoBlacklistType.MANUAL
|
||||
if (v === 'auto') return VideoBlacklistType.AUTO_BEFORE_PUBLISHED
|
||||
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
params = this.restService.addObjectParams(params, filters)
|
||||
}
|
||||
if (type) params = params.append('type', type.toString())
|
||||
|
||||
return this.authHttp.get<ResultList<VideoBlacklist>>(VideoBlacklistService.BASE_VIDEOS_URL + 'blacklist', { params })
|
||||
return this.authHttp.get<ResultList<VideoBlacklist>>(VideoBlockService.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[]) {
|
||||
unblockVideo (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')),
|
||||
concatMap(id => this.authHttp.delete(VideoBlockService.BASE_VIDEOS_URL + id + '/blacklist')),
|
||||
toArray(),
|
||||
catchError(err => this.restExtractor.handleError(err))
|
||||
)
|
||||
}
|
||||
|
||||
blacklistVideo (videoId: number, reason: string, unfederate: boolean) {
|
||||
blockVideo (videoId: number, reason: string, unfederate: boolean) {
|
||||
const body = {
|
||||
unfederate,
|
||||
reason
|
||||
}
|
||||
|
||||
return this.authHttp.post(VideoBlacklistService.BASE_VIDEOS_URL + videoId + '/blacklist', body)
|
||||
return this.authHttp.post(VideoBlockService.BASE_VIDEOS_URL + videoId + '/blacklist', body)
|
||||
.pipe(
|
||||
map(this.restExtractor.extractDataBool),
|
||||
catchError(res => this.restExtractor.handleError(res))
|
|
@ -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>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<ng-template #modal>
|
||||
<div class="modal-header">
|
||||
<h4 i18n class="modal-title">Blacklist video</h4>
|
||||
<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)="blacklist()">
|
||||
<form novalidate [formGroup]="form" (ngSubmit)="block()">
|
||||
<div class="form-group">
|
||||
<textarea
|
||||
i18n-placeholder placeholder="Reason..." formControlName="reason"
|
|
@ -1,24 +1,24 @@
|
|||
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'
|
||||
import { Notifier, RedirectService } from '@app/core'
|
||||
import { VideoBlacklistService } from '../../../shared/video-blacklist'
|
||||
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, VideoBlacklistValidatorsService } from '@app/shared/forms'
|
||||
import { FormReactive, VideoBlockValidatorsService } 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' ]
|
||||
selector: 'my-video-block',
|
||||
templateUrl: './video-block.component.html',
|
||||
styleUrls: [ './video-block.component.scss' ]
|
||||
})
|
||||
export class VideoBlacklistComponent extends FormReactive implements OnInit {
|
||||
export class VideoBlockComponent extends FormReactive implements OnInit {
|
||||
@Input() video: Video = null
|
||||
|
||||
@ViewChild('modal', { static: true }) modal: NgbModal
|
||||
|
||||
@Output() videoBlacklisted = new EventEmitter()
|
||||
@Output() videoBlocked = new EventEmitter()
|
||||
|
||||
error: string = null
|
||||
|
||||
|
@ -27,10 +27,9 @@ export class VideoBlacklistComponent extends FormReactive implements OnInit {
|
|||
constructor (
|
||||
protected formValidatorService: FormValidatorService,
|
||||
private modalService: NgbModal,
|
||||
private videoBlacklistValidatorsService: VideoBlacklistValidatorsService,
|
||||
private videoBlacklistService: VideoBlacklistService,
|
||||
private videoBlockValidatorsService: VideoBlockValidatorsService,
|
||||
private videoBlocklistService: VideoBlockService,
|
||||
private notifier: Notifier,
|
||||
private redirectService: RedirectService,
|
||||
private i18n: I18n
|
||||
) {
|
||||
super()
|
||||
|
@ -40,7 +39,7 @@ export class VideoBlacklistComponent extends FormReactive implements OnInit {
|
|||
const defaultValues = { unfederate: 'true' }
|
||||
|
||||
this.buildForm({
|
||||
reason: this.videoBlacklistValidatorsService.VIDEO_BLACKLIST_REASON,
|
||||
reason: this.videoBlockValidatorsService.VIDEO_BLOCK_REASON,
|
||||
unfederate: null
|
||||
}, defaultValues)
|
||||
}
|
||||
|
@ -54,20 +53,20 @@ export class VideoBlacklistComponent extends FormReactive implements OnInit {
|
|||
this.openedModal = null
|
||||
}
|
||||
|
||||
blacklist () {
|
||||
block () {
|
||||
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)
|
||||
this.videoBlocklistService.blockVideo(this.video.id, reason, unfederate)
|
||||
.subscribe(
|
||||
() => {
|
||||
this.notifier.success(this.i18n('Video blacklisted.'))
|
||||
this.notifier.success(this.i18n('Video blocked.'))
|
||||
this.hide()
|
||||
|
||||
this.video.blacklisted = true
|
||||
this.video.blacklistedReason = reason
|
||||
this.video.blockedReason = reason
|
||||
|
||||
this.videoBlacklisted.emit()
|
||||
this.videoBlocked.emit()
|
||||
},
|
||||
|
||||
err => this.notifier.error(err.message)
|
|
@ -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>
|
||||
|
|
|
@ -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'),
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 () {
|
||||
|
|
|
@ -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,11 +163,11 @@ export class Video implements VideoServerModel {
|
|||
return user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.REMOVE_ANY_VIDEO))
|
||||
}
|
||||
|
||||
isBlackistableBy (user: AuthUser) {
|
||||
isBlockableBy (user: AuthUser) {
|
||||
return this.blacklisted !== true && user && user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) === true
|
||||
}
|
||||
|
||||
isUnblacklistableBy (user: AuthUser) {
|
||||
isUnblockableBy (user: AuthUser) {
|
||||
return this.blacklisted === true && user && user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) === true
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ $video-info-margin-left: 44px;
|
|||
}
|
||||
}
|
||||
|
||||
.blacklisted-label {
|
||||
.blocked-label {
|
||||
font-weight: $font-semibold;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 blocked 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 blocked so redirect to 404
|
||||
catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [ 400, 401, 403, 404 ]))
|
||||
)
|
||||
.subscribe(playlist => {
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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>
|
After Width: | Height: | Size: 548 B |
|
@ -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_BLACKLIST) || user.hasAdminFlag(UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -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_BLACKLIST
|
||||
}
|
||||
|
||||
it('Should fail with a too small username', async function () {
|
||||
|
|
|
@ -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_BLACKLIST
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -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_BLACKLIST)
|
||||
|
||||
expect(userMe.specialPlaylists).to.have.lengthOf(1)
|
||||
expect(userMe.specialPlaylists[0].type).to.equal(VideoPlaylistType.WATCH_LATER)
|
||||
|
|
|
@ -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_BLACKLIST,
|
||||
password: user.password,
|
||||
role: UserRole.USER
|
||||
})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export enum UserAdminFlag {
|
||||
NONE = 0,
|
||||
BY_PASS_VIDEO_AUTO_BLACKLIST = 1 << 0
|
||||
BYPASS_VIDEO_AUTO_BLACKLIST = 1 << 0
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue