diff options
Diffstat (limited to 'client/src/app')
7 files changed, 140 insertions, 17 deletions
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 075be8498..19b33a0f5 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 | |||
@@ -23,7 +23,12 @@ | |||
23 | 23 | ||
24 | <ng-template pTemplate="body" let-serverBlock> | 24 | <ng-template pTemplate="body" let-serverBlock> |
25 | <tr> | 25 | <tr> |
26 | <td>{{ serverBlock.blockedServer.host }}</td> | 26 | <td> |
27 | <a [href]="'https://' + serverBlock.blockedServer.host" i18n-title title="Open instance in a new tab" target="_blank" rel="noopener noreferrer"> | ||
28 | {{ serverBlock.blockedServer.host }} | ||
29 | <span class="glyphicon glyphicon-new-window"></span> | ||
30 | </a> | ||
31 | </td> | ||
27 | <td>{{ serverBlock.createdAt }}</td> | 32 | <td>{{ serverBlock.createdAt }}</td> |
28 | <td class="action-cell"> | 33 | <td class="action-cell"> |
29 | <button class="unblock-button" (click)="unblockServer(serverBlock)" i18n>Unmute</button> | 34 | <button class="unblock-button" (click)="unblockServer(serverBlock)" i18n>Unmute</button> |
diff --git a/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.scss b/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.scss index 9d3bedd80..c6c71587f 100644 --- a/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.scss +++ b/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.scss | |||
@@ -1,6 +1,20 @@ | |||
1 | @import '_variables'; | 1 | @import '_variables'; |
2 | @import '_mixins'; | 2 | @import '_mixins'; |
3 | 3 | ||
4 | a { | ||
5 | @include disable-default-a-behaviour; | ||
6 | display: inline-block; | ||
7 | |||
8 | &, &:hover { | ||
9 | color: var(--mainForegroundColor); | ||
10 | } | ||
11 | |||
12 | span { | ||
13 | font-size: 80%; | ||
14 | color: var(--inputPlaceholderColor); | ||
15 | } | ||
16 | } | ||
17 | |||
4 | .unblock-button { | 18 | .unblock-button { |
5 | @include peertube-button; | 19 | @include peertube-button; |
6 | @include grey-button; | 20 | @include grey-button; |
diff --git a/client/src/app/+admin/moderation/moderation.component.scss b/client/src/app/+admin/moderation/moderation.component.scss index a015b6d85..9ceff1161 100644 --- a/client/src/app/+admin/moderation/moderation.component.scss +++ b/client/src/app/+admin/moderation/moderation.component.scss | |||
@@ -29,10 +29,6 @@ | |||
29 | } | 29 | } |
30 | } | 30 | } |
31 | 31 | ||
32 | .glyphicon-trash { | ||
33 | font-size: 80%; | ||
34 | } | ||
35 | |||
36 | .screenratio { | 32 | .screenratio { |
37 | position: relative; | 33 | position: relative; |
38 | width: 100%; | 34 | width: 100%; |
@@ -47,6 +43,7 @@ | |||
47 | display: inline-flex; | 43 | display: inline-flex; |
48 | justify-content: center; | 44 | justify-content: center; |
49 | align-items: center; | 45 | align-items: center; |
46 | color: var(--inputPlaceholderColor); | ||
50 | } | 47 | } |
51 | 48 | ||
52 | ::ng-deep iframe { | 49 | ::ng-deep iframe { |
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 204cb209e..2204bb371 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 | |||
@@ -41,9 +41,22 @@ | |||
41 | </td> | 41 | </td> |
42 | 42 | ||
43 | <td> | 43 | <td> |
44 | <span *ngIf="videoAbuse.video.deleted" i18n-title title="Video was deleted" class="glyphicon glyphicon-trash"></span> | 44 | <a [href]="getVideoUrl(videoAbuse)" class="video-abuse-video-link" 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"> | 45 | <div class="video-abuse-video"> |
46 | {{ videoAbuse.video.name }} | 46 | <div class="video-abuse-video-image"> |
47 | <img *ngIf="!videoAbuse.video.deleted" [src]="videoAbuse.video.thumbnailPath"> | ||
48 | <span *ngIf="videoAbuse.video.deleted" i18n>Deleted</span> | ||
49 | </div> | ||
50 | <div class="video-abuse-video-text"> | ||
51 | <div> | ||
52 | {{ videoAbuse.video.name }} | ||
53 | <span *ngIf="!videoAbuse.video.deleted && !videoAbuse.video.blacklisted" class="glyphicon glyphicon-new-window"></span> | ||
54 | <span *ngIf="videoAbuse.video.deleted" i18n-title title="Video was deleted" class="glyphicon glyphicon-trash"></span> | ||
55 | <span *ngIf="videoAbuse.video.blacklisted" i18n-title title="Video was blacklisted" class="glyphicon glyphicon-ban-circle"></span> | ||
56 | </div> | ||
57 | <div class="text-muted">by {{ videoAbuse.video.channel?.displayName }} on {{ videoAbuse.video.channel?.host }} </div> | ||
58 | </div> | ||
59 | </div> | ||
47 | </a> | 60 | </a> |
48 | </td> | 61 | </td> |
49 | 62 | ||
@@ -78,10 +91,10 @@ | |||
78 | 91 | ||
79 | <div class="col-4"> | 92 | <div class="col-4"> |
80 | <div class="screenratio"> | 93 | <div class="screenratio"> |
81 | <div *ngIf="videoAbuse.video.deleted"> | 94 | <div *ngIf="videoAbuse.video.deleted || videoAbuse.video.blacklisted"> |
82 | <span i18n>The video was {{ videoAbuse.video.deleted ? 'deleted' : 'blacklisted' }}</span> | 95 | <span i18n>The video was {{ videoAbuse.video.deleted ? 'deleted' : 'blacklisted' }}</span> |
83 | </div> | 96 | </div> |
84 | <div *ngIf="!videoAbuse.video.deleted" [innerHTML]="videoAbuse.embedHtml"></div> | 97 | <div *ngIf="!videoAbuse.video.deleted && !videoAbuse.video.blacklisted" [innerHTML]="videoAbuse.embedHtml"></div> |
85 | </div> | 98 | </div> |
86 | </div> | 99 | </div> |
87 | </div> | 100 | </div> |
diff --git a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.scss b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.scss new file mode 100644 index 000000000..09402fda7 --- /dev/null +++ b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.scss | |||
@@ -0,0 +1,57 @@ | |||
1 | @import 'mixins'; | ||
2 | @import 'miniature'; | ||
3 | |||
4 | .video-abuse-video-link { | ||
5 | @include disable-outline; | ||
6 | position: relative; | ||
7 | top: 3px; | ||
8 | } | ||
9 | |||
10 | .video-abuse-video { | ||
11 | display: inline-flex; | ||
12 | |||
13 | .video-abuse-video-image { | ||
14 | @include miniature-thumbnail; | ||
15 | |||
16 | $image-height: 45px; | ||
17 | |||
18 | height: $image-height; | ||
19 | width: #{(16/9) * $image-height}; | ||
20 | margin-right: 0.5rem; | ||
21 | border-radius: 2px; | ||
22 | border: none; | ||
23 | background: transparent; | ||
24 | display: inline-flex; | ||
25 | justify-content: center; | ||
26 | align-items: center; | ||
27 | |||
28 | img { | ||
29 | height: 100%; | ||
30 | width: 100%; | ||
31 | border-radius: 2px; | ||
32 | } | ||
33 | |||
34 | span { | ||
35 | color: var(--inputPlaceholderColor); | ||
36 | } | ||
37 | } | ||
38 | |||
39 | .video-abuse-video-text { | ||
40 | display: inline-flex; | ||
41 | flex-direction: column; | ||
42 | justify-content: center; | ||
43 | font-size: 90%; | ||
44 | color: var(--mainForegroundColor); | ||
45 | line-height: 1rem; | ||
46 | |||
47 | div .glyphicon { | ||
48 | font-size: 80%; | ||
49 | color: gray; | ||
50 | margin-left: 0.1rem; | ||
51 | } | ||
52 | |||
53 | div + div { | ||
54 | font-size: 80%; | ||
55 | } | ||
56 | } | ||
57 | } | ||
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 9858cbce2..cc5014ae8 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 | |||
@@ -20,14 +20,14 @@ import { VideoService } from '@app/shared/video/video.service' | |||
20 | @Component({ | 20 | @Component({ |
21 | selector: 'my-video-abuse-list', | 21 | selector: 'my-video-abuse-list', |
22 | templateUrl: './video-abuse-list.component.html', | 22 | templateUrl: './video-abuse-list.component.html', |
23 | styleUrls: [ '../moderation.component.scss'] | 23 | styleUrls: [ '../moderation.component.scss', './video-abuse-list.component.scss' ] |
24 | }) | 24 | }) |
25 | export class VideoAbuseListComponent extends RestTable implements OnInit { | 25 | export class VideoAbuseListComponent extends RestTable implements OnInit { |
26 | @ViewChild('moderationCommentModal', { static: true }) moderationCommentModal: ModerationCommentModalComponent | 26 | @ViewChild('moderationCommentModal', { static: true }) moderationCommentModal: ModerationCommentModalComponent |
27 | 27 | ||
28 | videoAbuses: (VideoAbuse & { moderationCommentHtml?: string, reasonHtml?: string })[] = [] | 28 | videoAbuses: (VideoAbuse & { moderationCommentHtml?: string, reasonHtml?: string })[] = [] |
29 | totalRecords = 0 | 29 | totalRecords = 0 |
30 | rowsPerPageOptions = [ 20, 50, 100 ] | 30 | rowsPerPageOptions = [ 20, 50, 100 ] |
31 | rowsPerPage = this.rowsPerPageOptions[0] | 31 | rowsPerPage = this.rowsPerPageOptions[0] |
32 | sort: SortMeta = { field: 'createdAt', order: 1 } | 32 | sort: SortMeta = { field: 'createdAt', order: 1 } |
33 | pagination: RestPagination = { count: this.rowsPerPage, start: 0 } | 33 | pagination: RestPagination = { count: this.rowsPerPage, start: 0 } |
@@ -86,7 +86,7 @@ export class VideoAbuseListComponent extends RestTable implements OnInit { | |||
86 | }, | 86 | }, |
87 | { | 87 | { |
88 | label: this.i18n('Blacklist video'), | 88 | label: this.i18n('Blacklist video'), |
89 | isDisplayed: videoAbuse => !videoAbuse.video.deleted, | 89 | isDisplayed: videoAbuse => !videoAbuse.video.deleted && !videoAbuse.video.blacklisted, |
90 | handler: videoAbuse => { | 90 | handler: videoAbuse => { |
91 | this.videoBlacklistService.blacklistVideo(videoAbuse.video.id, undefined, true) | 91 | this.videoBlacklistService.blacklistVideo(videoAbuse.video.id, undefined, true) |
92 | .subscribe( | 92 | .subscribe( |
@@ -101,10 +101,29 @@ export class VideoAbuseListComponent extends RestTable implements OnInit { | |||
101 | } | 101 | } |
102 | }, | 102 | }, |
103 | { | 103 | { |
104 | label: this.i18n('Unblacklist video'), | ||
105 | isDisplayed: videoAbuse => !videoAbuse.video.deleted && videoAbuse.video.blacklisted, | ||
106 | handler: videoAbuse => { | ||
107 | this.videoBlacklistService.removeVideoFromBlacklist(videoAbuse.video.id) | ||
108 | .subscribe( | ||
109 | () => { | ||
110 | this.notifier.success(this.i18n('Video unblacklisted.')) | ||
111 | |||
112 | this.updateVideoAbuseState(videoAbuse, VideoAbuseState.ACCEPTED) | ||
113 | }, | ||
114 | |||
115 | err => this.notifier.error(err.message) | ||
116 | ) | ||
117 | } | ||
118 | }, | ||
119 | { | ||
104 | label: this.i18n('Delete video'), | 120 | label: this.i18n('Delete video'), |
105 | isDisplayed: videoAbuse => !videoAbuse.video.deleted, | 121 | isDisplayed: videoAbuse => !videoAbuse.video.deleted, |
106 | handler: async videoAbuse => { | 122 | handler: async videoAbuse => { |
107 | const res = await this.confirmService.confirm(this.i18n('Do you really want to delete this video?'), this.i18n('Delete')) | 123 | const res = await this.confirmService.confirm( |
124 | this.i18n('Do you really want to delete this video?'), | ||
125 | this.i18n('Delete') | ||
126 | ) | ||
108 | if (res === false) return | 127 | if (res === false) return |
109 | 128 | ||
110 | this.videoService.removeVideo(videoAbuse.video.id) | 129 | this.videoService.removeVideo(videoAbuse.video.id) |
@@ -126,14 +145,16 @@ export class VideoAbuseListComponent extends RestTable implements OnInit { | |||
126 | isHeader: true | 145 | isHeader: true |
127 | }, | 146 | }, |
128 | { | 147 | { |
129 | label: this.i18n('Mute reporter'), | 148 | label: this.i18n('Mute reporter'), |
130 | handler: async videoAbuse => { | 149 | handler: async videoAbuse => { |
131 | const account = videoAbuse.reporterAccount as Account | 150 | const account = videoAbuse.reporterAccount as Account |
132 | 151 | ||
133 | this.blocklistService.blockAccountByInstance(account) | 152 | this.blocklistService.blockAccountByInstance(account) |
134 | .subscribe( | 153 | .subscribe( |
135 | () => { | 154 | () => { |
136 | this.notifier.success(this.i18n('Account {{nameWithHost}} muted by the instance.', { nameWithHost: account.nameWithHost })) | 155 | this.notifier.success( |
156 | this.i18n('Account {{nameWithHost}} muted by the instance.', { nameWithHost: account.nameWithHost }) | ||
157 | ) | ||
137 | 158 | ||
138 | account.mutedByInstance = true | 159 | account.mutedByInstance = true |
139 | }, | 160 | }, |
@@ -141,6 +162,22 @@ export class VideoAbuseListComponent extends RestTable implements OnInit { | |||
141 | err => this.notifier.error(err.message) | 162 | err => this.notifier.error(err.message) |
142 | ) | 163 | ) |
143 | } | 164 | } |
165 | }, | ||
166 | { | ||
167 | label: this.i18n('Mute server'), | ||
168 | isDisplayed: videoAbuse => !videoAbuse.reporterAccount.userId, | ||
169 | handler: async videoAbuse => { | ||
170 | this.blocklistService.blockServerByInstance(videoAbuse.reporterAccount.host) | ||
171 | .subscribe( | ||
172 | () => { | ||
173 | this.notifier.success( | ||
174 | this.i18n('Server {{host}} muted by the instance.', { host: videoAbuse.reporterAccount.host }) | ||
175 | ) | ||
176 | }, | ||
177 | |||
178 | err => this.notifier.error(err.message) | ||
179 | ) | ||
180 | } | ||
144 | } | 181 | } |
145 | ] | 182 | ] |
146 | ] | 183 | ] |
diff --git a/client/src/app/+admin/users/user-edit/user-update.component.ts b/client/src/app/+admin/users/user-edit/user-update.component.ts index fbe3d6950..e0e1fbddf 100644 --- a/client/src/app/+admin/users/user-edit/user-update.component.ts +++ b/client/src/app/+admin/users/user-edit/user-update.component.ts | |||
@@ -85,7 +85,7 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy { | |||
85 | 85 | ||
86 | this.userService.updateUser(this.user.id, userUpdate).subscribe( | 86 | this.userService.updateUser(this.user.id, userUpdate).subscribe( |
87 | () => { | 87 | () => { |
88 | this.notifier.success(this.i18n('User {{user.username}} updated.', { username: this.user.username })) | 88 | this.notifier.success(this.i18n('User {{username}} updated.', { username: this.user.username })) |
89 | this.router.navigate([ '/admin/users/list' ]) | 89 | this.router.navigate([ '/admin/users/list' ]) |
90 | }, | 90 | }, |
91 | 91 | ||