diff options
author | Chocobozzz <me@florianbigard.com> | 2021-11-17 11:18:49 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-11-17 11:18:49 +0100 |
commit | 3cfa817672657df18260ece5b354efa0f3b6e317 (patch) | |
tree | 318a7113fac4fcf1e6d0f7888cda1939aeefc500 /client/src/app/shared | |
parent | 4bdff96d77c03e5cce6052188f69a65bf6ea5781 (diff) | |
download | PeerTube-3cfa817672657df18260ece5b354efa0f3b6e317.tar.gz PeerTube-3cfa817672657df18260ece5b354efa0f3b6e317.tar.zst PeerTube-3cfa817672657df18260ece5b354efa0f3b6e317.zip |
Add ability to bulk block videos
Diffstat (limited to 'client/src/app/shared')
7 files changed, 74 insertions, 35 deletions
diff --git a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.html b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.html index d0eef7d4b..0d75a21d7 100644 --- a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.html +++ b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.html | |||
@@ -77,10 +77,6 @@ | |||
77 | 77 | ||
78 | <td *ngIf="abuse.video.deleted" class="c-hand" [pRowToggler]="abuse"> | 78 | <td *ngIf="abuse.video.deleted" class="c-hand" [pRowToggler]="abuse"> |
79 | <div class="table-video" i18n-title title="Video was deleted"> | 79 | <div class="table-video" i18n-title title="Video was deleted"> |
80 | <div class="table-video-image"> | ||
81 | <span i18n>Deleted</span> | ||
82 | </div> | ||
83 | |||
84 | <div class="table-video-text"> | 80 | <div class="table-video-text"> |
85 | <div> | 81 | <div> |
86 | {{ abuse.video.name }} | 82 | {{ abuse.video.name }} |
diff --git a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts index b902726fa..08cf297cc 100644 --- a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts +++ b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts | |||
@@ -338,7 +338,7 @@ export class AbuseListTableComponent extends RestTable implements OnInit { | |||
338 | label: $localize`Block video`, | 338 | label: $localize`Block video`, |
339 | isDisplayed: abuse => abuse.video && !abuse.video.deleted && !abuse.video.blacklisted, | 339 | isDisplayed: abuse => abuse.video && !abuse.video.deleted && !abuse.video.blacklisted, |
340 | handler: abuse => { | 340 | handler: abuse => { |
341 | this.videoBlocklistService.blockVideo(abuse.video.id, undefined, abuse.video.channel.isLocal) | 341 | this.videoBlocklistService.blockVideo([ { videoId: abuse.video.id, unfederate: abuse.video.channel.isLocal } ]) |
342 | .subscribe({ | 342 | .subscribe({ |
343 | next: () => { | 343 | next: () => { |
344 | this.notifier.success($localize`Video blocked.`) | 344 | this.notifier.success($localize`Video blocked.`) |
diff --git a/client/src/app/shared/shared-moderation/video-block.component.html b/client/src/app/shared/shared-moderation/video-block.component.html index 5e9e8493c..e5793f2ca 100644 --- a/client/src/app/shared/shared-moderation/video-block.component.html +++ b/client/src/app/shared/shared-moderation/video-block.component.html | |||
@@ -1,7 +1,14 @@ | |||
1 | <ng-template #modal> | 1 | <ng-template #modal> |
2 | <div class="modal-header"> | 2 | <div class="modal-header"> |
3 | <h4 i18n class="modal-title" *ngIf="!video.isLive">Block video "{{ video.name }}"</h4> | 3 | <ng-container *ngIf="isMultiple()"> |
4 | <h4 i18n class="modal-title" *ngIf="video.isLive">Block live "{{ video.name }}"</h4> | 4 | <h4 i18n class="modal-title">Block {{ videos.length }} videos</h4> |
5 | </ng-container> | ||
6 | |||
7 | <ng-container *ngIf="!isMultiple()"> | ||
8 | <h4 i18n class="modal-title" *ngIf="!getSingleVideo().isLive">Block video "{{ getSingleVideo().name }}"</h4> | ||
9 | <h4 i18n class="modal-title" *ngIf="getSingleVideo().isLive">Block live "{{ getSingleVideo().name }}"</h4> | ||
10 | </ng-container> | ||
11 | |||
5 | <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon> | 12 | <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon> |
6 | </div> | 13 | </div> |
7 | 14 | ||
@@ -18,19 +25,20 @@ | |||
18 | </div> | 25 | </div> |
19 | </div> | 26 | </div> |
20 | 27 | ||
21 | <div class="form-group" *ngIf="video.isLocal"> | 28 | <div class="form-group" *ngIf="hasLocal()"> |
22 | <my-peertube-checkbox | 29 | <my-peertube-checkbox |
23 | inputName="unfederate" formControlName="unfederate" | 30 | inputName="unfederate" formControlName="unfederate" |
24 | i18n-labelText labelText="Unfederate the video" | 31 | i18n-labelText labelText="Unfederate" |
25 | > | 32 | > |
26 | <ng-container ngProjectAs="description"> | 33 | <ng-container ngProjectAs="description"> |
27 | <span i18n>This will ask remote instances to delete it</span> | 34 | <span *ngIf="isMultiple()" i18n>This will ask remote instances to delete local videos</span> |
35 | <span *ngIf="!isMultiple()" i18n>This will ask remote instances to delete this video</span> | ||
28 | </ng-container> | 36 | </ng-container> |
29 | </my-peertube-checkbox> | 37 | </my-peertube-checkbox> |
30 | </div> | 38 | </div> |
31 | 39 | ||
32 | <strong class="live-info" *ngIf="video.isLive" i18n> | 40 | <strong class="live-info" *ngIf="hasLive()" i18n> |
33 | Blocking this live will automatically terminate the live stream. | 41 | Blocking a live will automatically terminate the live stream. |
34 | </strong> | 42 | </strong> |
35 | 43 | ||
36 | <div class="form-group inputs"> | 44 | <div class="form-group inputs"> |
@@ -39,7 +47,7 @@ | |||
39 | (click)="hide()" (key.enter)="hide()" | 47 | (click)="hide()" (key.enter)="hide()" |
40 | > | 48 | > |
41 | 49 | ||
42 | <input type="submit" i18n-value value="Submit" class="peertube-button orange-button" [disabled]="!form.valid" /> | 50 | <input type="submit" i18n-value value="Block" class="peertube-button orange-button" [disabled]="!form.valid" /> |
43 | </div> | 51 | </div> |
44 | </form> | 52 | </form> |
45 | 53 | ||
diff --git a/client/src/app/shared/shared-moderation/video-block.component.ts b/client/src/app/shared/shared-moderation/video-block.component.ts index a6180dd14..400913f02 100644 --- a/client/src/app/shared/shared-moderation/video-block.component.ts +++ b/client/src/app/shared/shared-moderation/video-block.component.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core' | 1 | import { Component, EventEmitter, OnInit, Output, ViewChild } from '@angular/core' |
2 | import { Notifier } from '@app/core' | 2 | import { Notifier } from '@app/core' |
3 | import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' | 3 | import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' |
4 | import { Video } from '@app/shared/shared-main' | 4 | import { Video } from '@app/shared/shared-main' |
@@ -13,12 +13,12 @@ import { VideoBlockService } from './video-block.service' | |||
13 | styleUrls: [ './video-block.component.scss' ] | 13 | styleUrls: [ './video-block.component.scss' ] |
14 | }) | 14 | }) |
15 | export class VideoBlockComponent extends FormReactive implements OnInit { | 15 | export class VideoBlockComponent extends FormReactive implements OnInit { |
16 | @Input() video: Video = null | ||
17 | |||
18 | @ViewChild('modal', { static: true }) modal: NgbModal | 16 | @ViewChild('modal', { static: true }) modal: NgbModal |
19 | 17 | ||
20 | @Output() videoBlocked = new EventEmitter() | 18 | @Output() videoBlocked = new EventEmitter() |
21 | 19 | ||
20 | videos: Video[] | ||
21 | |||
22 | error: string = null | 22 | error: string = null |
23 | 23 | ||
24 | private openedModal: NgbModalRef | 24 | private openedModal: NgbModalRef |
@@ -41,7 +41,25 @@ export class VideoBlockComponent extends FormReactive implements OnInit { | |||
41 | }, defaultValues) | 41 | }, defaultValues) |
42 | } | 42 | } |
43 | 43 | ||
44 | show () { | 44 | isMultiple () { |
45 | return this.videos.length > 1 | ||
46 | } | ||
47 | |||
48 | getSingleVideo () { | ||
49 | return this.videos[0] | ||
50 | } | ||
51 | |||
52 | hasLive () { | ||
53 | return this.videos.some(v => v.isLive) | ||
54 | } | ||
55 | |||
56 | hasLocal () { | ||
57 | return this.videos.some(v => v.isLocal) | ||
58 | } | ||
59 | |||
60 | show (videos: Video[]) { | ||
61 | this.videos = videos | ||
62 | |||
45 | this.openedModal = this.modalService.open(this.modal, { centered: true, keyboard: false }) | 63 | this.openedModal = this.modalService.open(this.modal, { centered: true, keyboard: false }) |
46 | } | 64 | } |
47 | 65 | ||
@@ -51,17 +69,30 @@ export class VideoBlockComponent extends FormReactive implements OnInit { | |||
51 | } | 69 | } |
52 | 70 | ||
53 | block () { | 71 | block () { |
54 | const reason = this.form.value['reason'] || undefined | 72 | const options = this.videos.map(v => ({ |
55 | const unfederate = this.video.isLocal ? this.form.value['unfederate'] : undefined | 73 | videoId: v.id, |
74 | reason: this.form.value['reason'] || undefined, | ||
75 | unfederate: v.isLocal | ||
76 | ? this.form.value['unfederate'] | ||
77 | : undefined | ||
78 | })) | ||
56 | 79 | ||
57 | this.videoBlocklistService.blockVideo(this.video.id, reason, unfederate) | 80 | this.videoBlocklistService.blockVideo(options) |
58 | .subscribe({ | 81 | .subscribe({ |
59 | next: () => { | 82 | next: () => { |
60 | this.notifier.success($localize`Video blocked.`) | 83 | const message = this.isMultiple |
84 | ? $localize`Blocked ${this.videos.length} videos.` | ||
85 | : $localize`Blocked ${this.getSingleVideo().name}` | ||
86 | |||
87 | this.notifier.success(message) | ||
61 | this.hide() | 88 | this.hide() |
62 | 89 | ||
63 | this.video.blacklisted = true | 90 | for (const o of options) { |
64 | this.video.blacklistedReason = reason | 91 | const video = this.videos.find(v => v.id === o.videoId) |
92 | |||
93 | video.blacklisted = true | ||
94 | video.blacklistedReason = o.reason | ||
95 | } | ||
65 | 96 | ||
66 | this.videoBlocked.emit() | 97 | this.videoBlocked.emit() |
67 | }, | 98 | }, |
diff --git a/client/src/app/shared/shared-moderation/video-block.service.ts b/client/src/app/shared/shared-moderation/video-block.service.ts index c22ceefcc..5dfb0d7d4 100644 --- a/client/src/app/shared/shared-moderation/video-block.service.ts +++ b/client/src/app/shared/shared-moderation/video-block.service.ts | |||
@@ -63,16 +63,20 @@ export class VideoBlockService { | |||
63 | ) | 63 | ) |
64 | } | 64 | } |
65 | 65 | ||
66 | blockVideo (videoId: number, reason: string, unfederate: boolean) { | 66 | blockVideo (options: { |
67 | const body = { | 67 | videoId: number |
68 | unfederate, | 68 | reason?: string |
69 | reason | 69 | unfederate: boolean |
70 | } | 70 | }[]) { |
71 | return observableFrom(options) | ||
72 | .pipe( | ||
73 | concatMap(({ videoId, unfederate, reason }) => { | ||
74 | const body = { unfederate, reason } | ||
71 | 75 | ||
72 | return this.authHttp.post(VideoBlockService.BASE_VIDEOS_URL + videoId + '/blacklist', body) | 76 | return this.authHttp.post(VideoBlockService.BASE_VIDEOS_URL + videoId + '/blacklist', body) |
73 | .pipe( | 77 | }), |
74 | map(this.restExtractor.extractDataBool), | 78 | toArray(), |
75 | catchError(res => this.restExtractor.handleError(res)) | 79 | catchError(res => this.restExtractor.handleError(res)) |
76 | ) | 80 | ) |
77 | } | 81 | } |
78 | } | 82 | } |
diff --git a/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.html b/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.html index 7a6394202..3fea2a8a4 100644 --- a/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.html +++ b/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.html | |||
@@ -20,6 +20,6 @@ | |||
20 | 20 | ||
21 | <my-video-download #videoDownloadModal></my-video-download> | 21 | <my-video-download #videoDownloadModal></my-video-download> |
22 | <my-video-report #videoReportModal [video]="video"></my-video-report> | 22 | <my-video-report #videoReportModal [video]="video"></my-video-report> |
23 | <my-video-block #videoBlockModal [video]="video" (videoBlocked)="onVideoBlocked()"></my-video-block> | 23 | <my-video-block #videoBlockModal (videoBlocked)="onVideoBlocked()"></my-video-block> |
24 | <my-live-stream-information #liveStreamInformationModal *ngIf="displayOptions.liveInfo"></my-live-stream-information> | 24 | <my-live-stream-information #liveStreamInformationModal *ngIf="displayOptions.liveInfo"></my-live-stream-information> |
25 | </ng-container> | 25 | </ng-container> |
diff --git a/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts b/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts index 790ae2a5e..eff56b40e 100644 --- a/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts +++ b/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts | |||
@@ -128,7 +128,7 @@ export class VideoActionsDropdownComponent implements OnChanges { | |||
128 | showBlockModal () { | 128 | showBlockModal () { |
129 | this.modalOpened.emit() | 129 | this.modalOpened.emit() |
130 | 130 | ||
131 | this.videoBlockModal.show() | 131 | this.videoBlockModal.show([ this.video ]) |
132 | } | 132 | } |
133 | 133 | ||
134 | showLiveInfoModal (video: Video) { | 134 | showLiveInfoModal (video: Video) { |