aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html2
-rw-r--r--client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.html2
-rw-r--r--client/src/app/+admin/moderation/moderation.component.scss4
-rw-r--r--client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html15
-rw-r--r--client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts54
-rw-r--r--client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.html2
-rw-r--r--client/src/app/shared/buttons/action-dropdown.component.html2
-rw-r--r--client/src/app/shared/buttons/action-dropdown.component.ts1
-rw-r--r--client/src/sass/primeng-custom.scss10
9 files changed, 78 insertions, 14 deletions
diff --git a/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html b/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html
index e40c29abf..6d77c8290 100644
--- a/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html
+++ b/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html
@@ -8,7 +8,7 @@
8 <ng-template pTemplate="header"> 8 <ng-template pTemplate="header">
9 <tr> 9 <tr>
10 <th i18n>Account</th> 10 <th i18n>Account</th>
11 <th style="width: 200px;" i18n pSortableColumn="createdAt">Muted at <p-sortIcon field="createdAt"></p-sortIcon></th> 11 <th style="width: 190px;" i18n pSortableColumn="createdAt">Muted at <p-sortIcon field="createdAt"></p-sortIcon></th>
12 <th style="width: 100px;"></th> <!-- column for action buttons --> 12 <th style="width: 100px;"></th> <!-- column for action buttons -->
13 </tr> 13 </tr>
14 </ng-template> 14 </ng-template>
diff --git a/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.html b/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.html
index bf5c00918..075be8498 100644
--- a/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.html
+++ b/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.html
@@ -16,7 +16,7 @@
16 <ng-template pTemplate="header"> 16 <ng-template pTemplate="header">
17 <tr> 17 <tr>
18 <th i18n>Instance</th> 18 <th i18n>Instance</th>
19 <th style="width: 200px;" i18n pSortableColumn="createdAt">Muted at <p-sortIcon field="createdAt"></p-sortIcon></th> 19 <th style="width: 190px;" i18n pSortableColumn="createdAt">Muted at <p-sortIcon field="createdAt"></p-sortIcon></th>
20 <th style="width: 100px;"></th> <!-- column for action buttons --> 20 <th style="width: 100px;"></th> <!-- column for action buttons -->
21 </tr> 21 </tr>
22 </ng-template> 22 </ng-template>
diff --git a/client/src/app/+admin/moderation/moderation.component.scss b/client/src/app/+admin/moderation/moderation.component.scss
index 9af76d2dd..a015b6d85 100644
--- a/client/src/app/+admin/moderation/moderation.component.scss
+++ b/client/src/app/+admin/moderation/moderation.component.scss
@@ -29,6 +29,10 @@
29 } 29 }
30} 30}
31 31
32.glyphicon-trash {
33 font-size: 80%;
34}
35
32.screenratio { 36.screenratio {
33 position: relative; 37 position: relative;
34 width: 100%; 38 width: 100%;
diff --git a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html
index 3d356dc7c..204cb209e 100644
--- a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html
+++ b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html
@@ -1,15 +1,15 @@
1<p-table 1<p-table
2 [value]="videoAbuses" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" 2 [value]="videoAbuses" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
3 [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id" 3 [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id" [resizableColumns]="true"
4 [showCurrentPageReport]="true" i18n-currentPageReportTemplate 4 [showCurrentPageReport]="true" i18n-currentPageReportTemplate
5 currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} reports" 5 currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} reports"
6> 6>
7 <ng-template pTemplate="header"> 7 <ng-template pTemplate="header">
8 <tr> <!-- header --> 8 <tr> <!-- header -->
9 <th style="width: 40px;"></th> 9 <th style="width: 40px;"></th>
10 <th i18n>Reporter</th> 10 <th style="width: 20%;" pResizableColumn i18n>Reporter</th>
11 <th style="width: 200px;" i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
12 <th i18n>Video</th> 11 <th i18n>Video</th>
12 <th style="width:190px;" i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
13 <th i18n pSortableColumn="state" style="width: 80px;">State <p-sortIcon field="state"></p-sortIcon></th> 13 <th i18n pSortableColumn="state" style="width: 80px;">State <p-sortIcon field="state"></p-sortIcon></th>
14 <th style="width: 120px;"></th> 14 <th style="width: 120px;"></th>
15 </tr> 15 </tr>
@@ -40,14 +40,15 @@
40 </a> 40 </a>
41 </td> 41 </td>
42 42
43 <td>{{ videoAbuse.createdAt }}</td>
44
45 <td> 43 <td>
44 <span *ngIf="videoAbuse.video.deleted" i18n-title title="Video was deleted" class="glyphicon glyphicon-trash"></span>
46 <a [href]="getVideoUrl(videoAbuse)" i18n-title title="Open video in a new tab" target="_blank" rel="noopener noreferrer"> 45 <a [href]="getVideoUrl(videoAbuse)" i18n-title title="Open video in a new tab" target="_blank" rel="noopener noreferrer">
47 {{ videoAbuse.video.name }} 46 {{ videoAbuse.video.name }}
48 </a> 47 </a>
49 </td> 48 </td>
50 49
50 <td>{{ videoAbuse.createdAt }}</td>
51
51 <td class="c-hand video-abuse-states" [pRowToggler]="videoAbuse"> 52 <td class="c-hand video-abuse-states" [pRowToggler]="videoAbuse">
52 <span *ngIf="isVideoAbuseAccepted(videoAbuse)" [title]="videoAbuse.state.label" class="glyphicon glyphicon-ok"></span> 53 <span *ngIf="isVideoAbuseAccepted(videoAbuse)" [title]="videoAbuse.state.label" class="glyphicon glyphicon-ok"></span>
53 <span *ngIf="isVideoAbuseRejected(videoAbuse)" [title]="videoAbuse.state.label" class="glyphicon glyphicon-remove"></span> 54 <span *ngIf="isVideoAbuseRejected(videoAbuse)" [title]="videoAbuse.state.label" class="glyphicon glyphicon-remove"></span>
@@ -55,7 +56,7 @@
55 </td> 56 </td>
56 57
57 <td class="action-cell"> 58 <td class="action-cell">
58 <my-action-dropdown placement="bottom-right auto" i18n-label label="Actions" [actions]="videoAbuseActions" [entry]="videoAbuse"></my-action-dropdown> 59 <my-action-dropdown placement="bottom-right auto" container="body" i18n-label label="Actions" [actions]="videoAbuseActions" [entry]="videoAbuse"></my-action-dropdown>
59 </td> 60 </td>
60 </tr> 61 </tr>
61 </ng-template> 62 </ng-template>
diff --git a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts
index 5e48cf24f..9858cbce2 100644
--- a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts
+++ b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts
@@ -15,6 +15,7 @@ import { buildVideoLink, buildVideoEmbed } from 'src/assets/player/utils'
15import { getAbsoluteAPIUrl } from '@app/shared/misc/utils' 15import { getAbsoluteAPIUrl } from '@app/shared/misc/utils'
16import { DomSanitizer } from '@angular/platform-browser' 16import { DomSanitizer } from '@angular/platform-browser'
17import { BlocklistService } from '@app/shared/blocklist' 17import { BlocklistService } from '@app/shared/blocklist'
18import { VideoService } from '@app/shared/video/video.service'
18 19
19@Component({ 20@Component({
20 selector: 'my-video-abuse-list', 21 selector: 'my-video-abuse-list',
@@ -26,7 +27,8 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
26 27
27 videoAbuses: (VideoAbuse & { moderationCommentHtml?: string, reasonHtml?: string })[] = [] 28 videoAbuses: (VideoAbuse & { moderationCommentHtml?: string, reasonHtml?: string })[] = []
28 totalRecords = 0 29 totalRecords = 0
29 rowsPerPage = 10 30 rowsPerPageOptions = [ 20, 50, 100 ]
31 rowsPerPage = this.rowsPerPageOptions[0]
30 sort: SortMeta = { field: 'createdAt', order: 1 } 32 sort: SortMeta = { field: 'createdAt', order: 1 }
31 pagination: RestPagination = { count: this.rowsPerPage, start: 0 } 33 pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
32 34
@@ -36,6 +38,7 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
36 private notifier: Notifier, 38 private notifier: Notifier,
37 private videoAbuseService: VideoAbuseService, 39 private videoAbuseService: VideoAbuseService,
38 private blocklistService: BlocklistService, 40 private blocklistService: BlocklistService,
41 private videoService: VideoService,
39 private videoBlacklistService: VideoBlacklistService, 42 private videoBlacklistService: VideoBlacklistService,
40 private confirmService: ConfirmService, 43 private confirmService: ConfirmService,
41 private i18n: I18n, 44 private i18n: I18n,
@@ -78,10 +81,12 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
78 [ 81 [
79 { 82 {
80 label: this.i18n('Actions for the video'), 83 label: this.i18n('Actions for the video'),
81 isHeader: true 84 isHeader: true,
85 isDisplayed: videoAbuse => !videoAbuse.video.deleted
82 }, 86 },
83 { 87 {
84 label: this.i18n('Blacklist video'), 88 label: this.i18n('Blacklist video'),
89 isDisplayed: videoAbuse => !videoAbuse.video.deleted,
85 handler: videoAbuse => { 90 handler: videoAbuse => {
86 this.videoBlacklistService.blacklistVideo(videoAbuse.video.id, undefined, true) 91 this.videoBlacklistService.blacklistVideo(videoAbuse.video.id, undefined, true)
87 .subscribe( 92 .subscribe(
@@ -94,6 +99,48 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
94 err => this.notifier.error(err.message) 99 err => this.notifier.error(err.message)
95 ) 100 )
96 } 101 }
102 },
103 {
104 label: this.i18n('Delete video'),
105 isDisplayed: videoAbuse => !videoAbuse.video.deleted,
106 handler: async videoAbuse => {
107 const res = await this.confirmService.confirm(this.i18n('Do you really want to delete this video?'), this.i18n('Delete'))
108 if (res === false) return
109
110 this.videoService.removeVideo(videoAbuse.video.id)
111 .subscribe(
112 () => {
113 this.notifier.success(this.i18n('Video deleted.'))
114
115 this.updateVideoAbuseState(videoAbuse, VideoAbuseState.ACCEPTED)
116 },
117
118 err => this.notifier.error(err.message)
119 )
120 }
121 }
122 ],
123 [
124 {
125 label: this.i18n('Actions for the reporter'),
126 isHeader: true
127 },
128 {
129 label: this.i18n('Mute reporter'),
130 handler: async videoAbuse => {
131 const account = videoAbuse.reporterAccount as Account
132
133 this.blocklistService.blockAccountByInstance(account)
134 .subscribe(
135 () => {
136 this.notifier.success(this.i18n('Account {{nameWithHost}} muted by the instance.', { nameWithHost: account.nameWithHost }))
137
138 account.mutedByInstance = true
139 },
140
141 err => this.notifier.error(err.message)
142 )
143 }
97 } 144 }
98 ] 145 ]
99 ] 146 ]
@@ -180,7 +227,8 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
180 Object.assign(abuse, { 227 Object.assign(abuse, {
181 reasonHtml: await this.toHtml(abuse.reason), 228 reasonHtml: await this.toHtml(abuse.reason),
182 moderationCommentHtml: await this.toHtml(abuse.moderationComment), 229 moderationCommentHtml: await this.toHtml(abuse.moderationComment),
183 embedHtml: this.sanitizer.bypassSecurityTrustHtml(this.getVideoEmbed(abuse)) 230 embedHtml: this.sanitizer.bypassSecurityTrustHtml(this.getVideoEmbed(abuse)),
231 reporterAccount: new Account(abuse.reporterAccount)
184 }) 232 })
185 } 233 }
186 234
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
index 023f4e7b7..2f9fc8ba4 100644
--- 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
@@ -10,7 +10,7 @@
10 <th i18n pSortableColumn="name">Video <p-sortIcon field="name"></p-sortIcon></th> 10 <th i18n pSortableColumn="name">Video <p-sortIcon field="name"></p-sortIcon></th>
11 <th style="width: 120px;" i18n>Sensitive</th> 11 <th style="width: 120px;" i18n>Sensitive</th>
12 <th style="width: 120px;" i18n>Unfederated</th> 12 <th style="width: 120px;" i18n>Unfederated</th>
13 <th style="width: 200px;" i18n pSortableColumn="createdAt">Date <p-sortIcon field="createdAt"></p-sortIcon></th> 13 <th style="width: 190px;" i18n pSortableColumn="createdAt">Date <p-sortIcon field="createdAt"></p-sortIcon></th>
14 <th style="width: 120px;"></th> 14 <th style="width: 120px;"></th>
15 </tr> 15 </tr>
16 </ng-template> 16 </ng-template>
diff --git a/client/src/app/shared/buttons/action-dropdown.component.html b/client/src/app/shared/buttons/action-dropdown.component.html
index 0efc01d38..952b3b6f8 100644
--- a/client/src/app/shared/buttons/action-dropdown.component.html
+++ b/client/src/app/shared/buttons/action-dropdown.component.html
@@ -1,4 +1,4 @@
1<div class="dropdown-root" ngbDropdown [placement]="placement" container="body" *ngIf="areActionsDisplayed(actions, entry)"> 1<div class="dropdown-root" ngbDropdown [placement]="placement" [container]="container" *ngIf="areActionsDisplayed(actions, entry)">
2 <div 2 <div
3 class="action-button" [ngClass]="{ small: buttonSize === 'small', grey: theme === 'grey', orange: theme === 'orange', 'button-styled': buttonStyled }" 3 class="action-button" [ngClass]="{ small: buttonSize === 'small', grey: theme === 'grey', orange: theme === 'orange', 'button-styled': buttonStyled }"
4 ngbDropdownToggle role="button" 4 ngbDropdownToggle role="button"
diff --git a/client/src/app/shared/buttons/action-dropdown.component.ts b/client/src/app/shared/buttons/action-dropdown.component.ts
index 8fcaa38b9..15f9556dc 100644
--- a/client/src/app/shared/buttons/action-dropdown.component.ts
+++ b/client/src/app/shared/buttons/action-dropdown.component.ts
@@ -27,6 +27,7 @@ export class ActionDropdownComponent<T> {
27 @Input() entry: T 27 @Input() entry: T
28 28
29 @Input() placement = 'bottom-left auto' 29 @Input() placement = 'bottom-left auto'
30 @Input() container: null | 'body'
30 31
31 @Input() buttonSize: DropdownButtonSize = 'normal' 32 @Input() buttonSize: DropdownButtonSize = 'normal'
32 @Input() buttonDirection: DropdownDirection = 'horizontal' 33 @Input() buttonDirection: DropdownDirection = 'horizontal'
diff --git a/client/src/sass/primeng-custom.scss b/client/src/sass/primeng-custom.scss
index b8e685aba..9c9a6197d 100644
--- a/client/src/sass/primeng-custom.scss
+++ b/client/src/sass/primeng-custom.scss
@@ -191,12 +191,22 @@ p-table {
191 191
192 .ui-dropdown { 192 .ui-dropdown {
193 position: absolute; 193 position: absolute;
194 top: 3px;
194 left: 0; 195 left: 0;
196
197 &.ui-state-focus {
198 box-shadow: #{$focus-box-shadow-form} var(--mainColorLightest);
199 }
200
201 .ui-dropdown-label {
202 color: var(--inputPlaceholderColor);
203 }
195 } 204 }
196 205
197 .ui-paginator-current { 206 .ui-paginator-current {
198 position: absolute; 207 position: absolute;
199 right: 0; 208 right: 0;
209 color: var(--inputPlaceholderColor);
200 } 210 }
201 211
202 .ui-paginator-first, 212 .ui-paginator-first,