aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/+admin
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/+admin')
-rw-r--r--client/src/app/+admin/admin.component.ts16
-rw-r--r--client/src/app/+admin/admin.module.ts2
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts3
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.html25
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.ts9
-rw-r--r--client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html56
-rw-r--r--client/src/app/+admin/moderation/moderation.routes.ts12
-rw-r--r--client/src/app/+admin/overview/comments/index.ts (renamed from client/src/app/+admin/moderation/video-comment-list/index.ts)1
-rw-r--r--client/src/app/+admin/overview/comments/video-comment-list.component.html (renamed from client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.html)6
-rw-r--r--client/src/app/+admin/overview/comments/video-comment-list.component.scss (renamed from client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.scss)8
-rw-r--r--client/src/app/+admin/overview/comments/video-comment-list.component.ts (renamed from client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.ts)2
-rw-r--r--client/src/app/+admin/overview/comments/video-comment.routes.ts30
-rw-r--r--client/src/app/+admin/overview/index.ts1
-rw-r--r--client/src/app/+admin/overview/overview.routes.ts10
-rw-r--r--client/src/app/+admin/overview/users/user-list/user-list.component.html20
-rw-r--r--client/src/app/+admin/overview/users/user-list/user-list.component.scss4
-rw-r--r--client/src/app/+admin/overview/users/user-list/user-list.component.ts42
-rw-r--r--client/src/app/+admin/overview/users/users.routes.ts2
-rw-r--r--client/src/app/+admin/overview/videos/video-list.component.html4
-rw-r--r--client/src/app/+admin/overview/videos/video-list.component.scss2
-rw-r--r--client/src/app/+admin/overview/videos/video.routes.ts2
21 files changed, 157 insertions, 100 deletions
diff --git a/client/src/app/+admin/admin.component.ts b/client/src/app/+admin/admin.component.ts
index b8a957d1c..746549555 100644
--- a/client/src/app/+admin/admin.component.ts
+++ b/client/src/app/+admin/admin.component.ts
@@ -52,6 +52,14 @@ export class AdminComponent implements OnInit {
52 }) 52 })
53 } 53 }
54 54
55 if (this.hasVideoCommentsRight()) {
56 overviewItems.children.push({
57 label: $localize`Comments`,
58 routerLink: '/admin/comments',
59 iconName: 'message-circle'
60 })
61 }
62
55 if (overviewItems.children.length !== 0) { 63 if (overviewItems.children.length !== 0) {
56 this.menuEntries.push(overviewItems) 64 this.menuEntries.push(overviewItems)
57 } 65 }
@@ -104,14 +112,6 @@ export class AdminComponent implements OnInit {
104 }) 112 })
105 } 113 }
106 114
107 if (this.hasVideoCommentsRight()) {
108 moderationItems.children.push({
109 label: $localize`Video comments`,
110 routerLink: '/admin/moderation/video-comments/list',
111 iconName: 'message-circle'
112 })
113 }
114
115 if (this.hasAccountsBlocklistRight()) { 115 if (this.hasAccountsBlocklistRight()) {
116 moderationItems.children.push({ 116 moderationItems.children.push({
117 label: $localize`Muted accounts`, 117 label: $localize`Muted accounts`,
diff --git a/client/src/app/+admin/admin.module.ts b/client/src/app/+admin/admin.module.ts
index c672fa280..366e29883 100644
--- a/client/src/app/+admin/admin.module.ts
+++ b/client/src/app/+admin/admin.module.ts
@@ -32,13 +32,13 @@ import { RedundancyCheckboxComponent } from './follows/shared/redundancy-checkbo
32import { VideoRedundancyInformationComponent } from './follows/video-redundancies-list/video-redundancy-information.component' 32import { VideoRedundancyInformationComponent } from './follows/video-redundancies-list/video-redundancy-information.component'
33import { AbuseListComponent, VideoBlockListComponent } from './moderation' 33import { AbuseListComponent, VideoBlockListComponent } from './moderation'
34import { InstanceAccountBlocklistComponent, InstanceServerBlocklistComponent } from './moderation/instance-blocklist' 34import { InstanceAccountBlocklistComponent, InstanceServerBlocklistComponent } from './moderation/instance-blocklist'
35import { VideoCommentListComponent } from './moderation/video-comment-list'
36import { 35import {
37 UserCreateComponent, 36 UserCreateComponent,
38 UserListComponent, 37 UserListComponent,
39 UserPasswordComponent, 38 UserPasswordComponent,
40 UserUpdateComponent, 39 UserUpdateComponent,
41 VideoAdminService, 40 VideoAdminService,
41 VideoCommentListComponent,
42 VideoListComponent 42 VideoListComponent
43} from './overview' 43} from './overview'
44import { 44import {
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
index f2eaa3033..e3b6f8305 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
+++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
@@ -197,6 +197,9 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
197 resolutions: {} 197 resolutions: {}
198 } 198 }
199 }, 199 },
200 videoEditor: {
201 enabled: null
202 },
200 autoBlacklist: { 203 autoBlacklist: {
201 videos: { 204 videos: {
202 ofUsers: { 205 ofUsers: {
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.html b/client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.html
index 1158f027b..2be855756 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.html
+++ b/client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.html
@@ -192,4 +192,29 @@
192 192
193 </div> 193 </div>
194 </div> 194 </div>
195
196 <div class="form-row mt-2"> <!-- video editor grid -->
197 <div class="form-group col-12 col-lg-4 col-xl-3">
198 <div i18n class="inner-form-title">VIDEO EDITOR</div>
199 <div i18n class="inner-form-description">
200 Allows your users to edit their video (cut, add intro/outro, add a watermark etc)
201 </div>
202 </div>
203
204 <div class="form-group form-group-right col-12 col-lg-8 col-xl-9">
205
206 <ng-container formGroupName="videoEditor">
207 <div class="form-group" [ngClass]="getTranscodingDisabledClass()">
208 <my-peertube-checkbox
209 inputName="videoEditorEnabled" formControlName="enabled"
210 i18n-labelText labelText="Enable video editor"
211 >
212 <ng-container ngProjectAs="description" *ngIf="!isTranscodingEnabled()">
213 <span i18n>⚠️ You need to enable transcoding first to enable video editor</span>
214 </ng-container>
215 </my-peertube-checkbox>
216 </div>
217 </ng-container>
218 </div>
219 </div>
195</ng-container> 220</ng-container>
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.ts b/client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.ts
index 3397c3dbd..948c10b69 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.ts
+++ b/client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.ts
@@ -71,6 +71,8 @@ export class EditVODTranscodingComponent implements OnInit, OnChanges {
71 } 71 }
72 72
73 private checkTranscodingFields () { 73 private checkTranscodingFields () {
74 const transcodingControl = this.form.get('transcoding.enabled')
75 const videoEditorControl = this.form.get('videoEditor.enabled')
74 const hlsControl = this.form.get('transcoding.hls.enabled') 76 const hlsControl = this.form.get('transcoding.hls.enabled')
75 const webtorrentControl = this.form.get('transcoding.webtorrent.enabled') 77 const webtorrentControl = this.form.get('transcoding.webtorrent.enabled')
76 78
@@ -95,5 +97,12 @@ export class EditVODTranscodingComponent implements OnInit, OnChanges {
95 webtorrentControl.enable() 97 webtorrentControl.enable()
96 } 98 }
97 }) 99 })
100
101 transcodingControl.valueChanges
102 .subscribe(newValue => {
103 if (newValue === false) {
104 videoEditorControl.setValue(false)
105 }
106 })
98 } 107 }
99} 108}
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
deleted file mode 100644
index feade0c26..000000000
--- a/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html
+++ /dev/null
@@ -1,56 +0,0 @@
1<p-table
2 [value]="blockedAccounts" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
3 [sortField]="sort.field" [sortOrder]="sort.order"
4 [lazy]="true" (onLazyLoad)="loadLazy($event)" [lazyLoadOnInit]="false"
5 [showCurrentPageReport]="true" i18n-currentPageReportTemplate
6 currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} muted accounts"
7>
8 <ng-template pTemplate="caption">
9 <div class="caption">
10 <div class="ml-auto">
11 <my-advanced-input-filter (search)="onSearch($event)"></my-advanced-input-filter>
12 </div>
13 </div>
14 </ng-template>
15
16 <ng-template pTemplate="header">
17 <tr>
18 <th style="width: 150px;">Action</th> <!-- column for action buttons -->
19 <th style="width: calc(100% - 300px);" i18n>Account</th>
20 <th style="width: 150px;" i18n pSortableColumn="createdAt">Muted at <p-sortIcon field="createdAt"></p-sortIcon></th>
21 </tr>
22 </ng-template>
23
24 <ng-template pTemplate="body" let-accountBlock>
25 <tr>
26 <td class="action-cell">
27 <button class="unblock-button" (click)="unblockAccount(accountBlock)" i18n>Unmute</button>
28 </td>
29
30 <td>
31 <a [href]="accountBlock.blockedAccount.url" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer">
32 <div class="chip two-lines">
33 <my-actor-avatar [account]="accountBlock.blockedAccount"></my-actor-avatar>
34 <div>
35 {{ accountBlock.blockedAccount.displayName }}
36 <span class="text-muted">{{ accountBlock.blockedAccount.nameWithHost }}</span>
37 </div>
38 </div>
39 </a>
40 </td>
41
42 <td>{{ accountBlock.createdAt | date: 'short' }}</td>
43 </tr>
44 </ng-template>
45
46 <ng-template pTemplate="emptymessage">
47 <tr>
48 <td colspan="6">
49 <div class="no-results">
50 <ng-container *ngIf="search" i18n>No account found matching current filters.</ng-container>
51 <ng-container *ngIf="!search" i18n>No account found.</ng-container>
52 </div>
53 </td>
54 </tr>
55 </ng-template>
56</p-table>
diff --git a/client/src/app/+admin/moderation/moderation.routes.ts b/client/src/app/+admin/moderation/moderation.routes.ts
index 5c39ff366..1ad301039 100644
--- a/client/src/app/+admin/moderation/moderation.routes.ts
+++ b/client/src/app/+admin/moderation/moderation.routes.ts
@@ -2,7 +2,6 @@ import { Routes } from '@angular/router'
2import { AbuseListComponent } from '@app/+admin/moderation/abuse-list' 2import { AbuseListComponent } from '@app/+admin/moderation/abuse-list'
3import { InstanceAccountBlocklistComponent, InstanceServerBlocklistComponent } from '@app/+admin/moderation/instance-blocklist' 3import { InstanceAccountBlocklistComponent, InstanceServerBlocklistComponent } from '@app/+admin/moderation/instance-blocklist'
4import { VideoBlockListComponent } from '@app/+admin/moderation/video-block-list' 4import { VideoBlockListComponent } from '@app/+admin/moderation/video-block-list'
5import { VideoCommentListComponent } from './video-comment-list'
6import { UserRightGuard } from '@app/core' 5import { UserRightGuard } from '@app/core'
7import { UserRight } from '@shared/models' 6import { UserRight } from '@shared/models'
8 7
@@ -69,6 +68,7 @@ export const ModerationRoutes: Routes = [
69 } 68 }
70 }, 69 },
71 70
71 // We move this component in admin overview pages
72 { 72 {
73 path: 'video-comments', 73 path: 'video-comments',
74 redirectTo: 'video-comments/list', 74 redirectTo: 'video-comments/list',
@@ -76,14 +76,8 @@ export const ModerationRoutes: Routes = [
76 }, 76 },
77 { 77 {
78 path: 'video-comments/list', 78 path: 'video-comments/list',
79 component: VideoCommentListComponent, 79 redirectTo: '/admin/comments/list',
80 canActivate: [ UserRightGuard ], 80 pathMatch: 'full'
81 data: {
82 userRight: UserRight.SEE_ALL_COMMENTS,
83 meta: {
84 title: $localize`Video comments`
85 }
86 }
87 }, 81 },
88 82
89 { 83 {
diff --git a/client/src/app/+admin/moderation/video-comment-list/index.ts b/client/src/app/+admin/overview/comments/index.ts
index eb08b4177..c487f7a81 100644
--- a/client/src/app/+admin/moderation/video-comment-list/index.ts
+++ b/client/src/app/+admin/overview/comments/index.ts
@@ -1 +1,2 @@
1export * from './video-comment-list.component' 1export * from './video-comment-list.component'
2export * from './video-comment.routes'
diff --git a/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.html b/client/src/app/+admin/overview/comments/video-comment-list.component.html
index 9bf23c21a..27a5d82ff 100644
--- a/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.html
+++ b/client/src/app/+admin/overview/comments/video-comment-list.component.html
@@ -25,8 +25,10 @@
25 </my-action-dropdown> 25 </my-action-dropdown>
26 </div> 26 </div>
27 27
28 <div class="ml-auto"> 28 <div class="ml-auto right-form">
29 <my-advanced-input-filter [filters]="inputFilters" (search)="onSearch($event)"></my-advanced-input-filter> 29 <my-advanced-input-filter [filters]="inputFilters" (search)="onSearch($event)"></my-advanced-input-filter>
30
31 <my-button i18n-label label="Refresh" icon="refresh" (click)="reloadData()"></my-button>
30 </div> 32 </div>
31 </div> 33 </div>
32 </ng-template> 34 </ng-template>
@@ -66,7 +68,7 @@
66 <td> 68 <td>
67 <a [href]="videoComment.account.localUrl" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer"> 69 <a [href]="videoComment.account.localUrl" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer">
68 <div class="chip two-lines"> 70 <div class="chip two-lines">
69 <my-actor-avatar [account]="videoComment.account"></my-actor-avatar> 71 <my-actor-avatar [account]="videoComment.account" size="32"></my-actor-avatar>
70 <div> 72 <div>
71 {{ videoComment.account.displayName }} 73 {{ videoComment.account.displayName }}
72 <span>{{ videoComment.by }}</span> 74 <span>{{ videoComment.by }}</span>
diff --git a/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.scss b/client/src/app/+admin/overview/comments/video-comment-list.component.scss
index 3cf7b8db6..d7eb02142 100644
--- a/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.scss
+++ b/client/src/app/+admin/overview/comments/video-comment-list.component.scss
@@ -45,6 +45,14 @@ my-global-icon {
45 } 45 }
46} 46}
47 47
48.right-form {
49 display: flex;
50
51 > *:not(:last-child) {
52 @include margin-right(10px);
53 }
54}
55
48@media screen and (max-width: $primeng-breakpoint) { 56@media screen and (max-width: $primeng-breakpoint) {
49 .video { 57 .video {
50 align-items: flex-start !important; 58 align-items: flex-start !important;
diff --git a/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.ts b/client/src/app/+admin/overview/comments/video-comment-list.component.ts
index 25fe65133..f3f43a900 100644
--- a/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.ts
+++ b/client/src/app/+admin/overview/comments/video-comment-list.component.ts
@@ -117,7 +117,7 @@ export class VideoCommentListComponent extends RestTable implements OnInit {
117 return this.selectedComments.length !== 0 117 return this.selectedComments.length !== 0
118 } 118 }
119 119
120 protected reloadData () { 120 reloadData () {
121 this.videoCommentService.getAdminVideoComments({ 121 this.videoCommentService.getAdminVideoComments({
122 pagination: this.pagination, 122 pagination: this.pagination,
123 sort: this.sort, 123 sort: this.sort,
diff --git a/client/src/app/+admin/overview/comments/video-comment.routes.ts b/client/src/app/+admin/overview/comments/video-comment.routes.ts
new file mode 100644
index 000000000..f0bd440ad
--- /dev/null
+++ b/client/src/app/+admin/overview/comments/video-comment.routes.ts
@@ -0,0 +1,30 @@
1import { Routes } from '@angular/router'
2import { UserRightGuard } from '@app/core'
3import { UserRight } from '@shared/models'
4import { VideoCommentListComponent } from './video-comment-list.component'
5
6export const commentRoutes: Routes = [
7 {
8 path: 'comments',
9 canActivate: [ UserRightGuard ],
10 data: {
11 userRight: UserRight.SEE_ALL_COMMENTS
12 },
13 children: [
14 {
15 path: '',
16 redirectTo: 'list',
17 pathMatch: 'full'
18 },
19 {
20 path: 'list',
21 component: VideoCommentListComponent,
22 data: {
23 meta: {
24 title: $localize`Comments list`
25 }
26 }
27 }
28 ]
29 }
30]
diff --git a/client/src/app/+admin/overview/index.ts b/client/src/app/+admin/overview/index.ts
index a9c46893f..111360734 100644
--- a/client/src/app/+admin/overview/index.ts
+++ b/client/src/app/+admin/overview/index.ts
@@ -1,3 +1,4 @@
1export * from './comments'
1export * from './users' 2export * from './users'
2export * from './videos' 3export * from './videos'
3export * from './overview.routes' 4export * from './overview.routes'
diff --git a/client/src/app/+admin/overview/overview.routes.ts b/client/src/app/+admin/overview/overview.routes.ts
index 1e6686d16..72d6835d7 100644
--- a/client/src/app/+admin/overview/overview.routes.ts
+++ b/client/src/app/+admin/overview/overview.routes.ts
@@ -1,8 +1,10 @@
1import { Routes } from '@angular/router' 1import { Routes } from '@angular/router'
2import { UsersRoutes } from './users' 2import { commentRoutes } from './comments'
3import { VideosRoutes } from './videos' 3import { usersRoutes } from './users'
4import { videosRoutes } from './videos'
4 5
5export const OverviewRoutes: Routes = [ 6export const OverviewRoutes: Routes = [
6 ...UsersRoutes, 7 ...commentRoutes,
7 ...VideosRoutes 8 ...usersRoutes,
9 ...videosRoutes
8] 10]
diff --git a/client/src/app/+admin/overview/users/user-list/user-list.component.html b/client/src/app/+admin/overview/users/user-list/user-list.component.html
index 7eb89fea1..0662e3ac3 100644
--- a/client/src/app/+admin/overview/users/user-list/user-list.component.html
+++ b/client/src/app/+admin/overview/users/user-list/user-list.component.html
@@ -62,10 +62,10 @@
62 </div> 62 </div>
63 </th> 63 </th>
64 <th *ngIf="isSelected('username')" pResizableColumn pSortableColumn="username">{{ getColumn('username').label }} <p-sortIcon field="username"></p-sortIcon></th> 64 <th *ngIf="isSelected('username')" pResizableColumn pSortableColumn="username">{{ getColumn('username').label }} <p-sortIcon field="username"></p-sortIcon></th>
65 <th *ngIf="isSelected('role')" style="width: 120px;" pSortableColumn="role">{{ getColumn('role').label }} <p-sortIcon field="role"></p-sortIcon></th>
65 <th *ngIf="isSelected('email')">{{ getColumn('email').label }}</th> 66 <th *ngIf="isSelected('email')">{{ getColumn('email').label }}</th>
66 <th *ngIf="isSelected('quota')" style="width: 160px;" pSortableColumn="videoQuotaUsed">{{ getColumn('quota').label }} <p-sortIcon field="videoQuotaUsed"></p-sortIcon></th> 67 <th *ngIf="isSelected('quota')" style="width: 160px;" pSortableColumn="videoQuotaUsed">{{ getColumn('quota').label }} <p-sortIcon field="videoQuotaUsed"></p-sortIcon></th>
67 <th *ngIf="isSelected('quotaDaily')" style="width: 160px;">{{ getColumn('quotaDaily').label }}</th> 68 <th *ngIf="isSelected('quotaDaily')" style="width: 160px;">{{ getColumn('quotaDaily').label }}</th>
68 <th *ngIf="isSelected('role')" style="width: 120px;" pSortableColumn="role">{{ getColumn('role').label }} <p-sortIcon field="role"></p-sortIcon></th>
69 <th *ngIf="isSelected('pluginAuth')" style="width: 140px;" pResizableColumn >{{ getColumn('pluginAuth').label }}</th> 69 <th *ngIf="isSelected('pluginAuth')" style="width: 140px;" pResizableColumn >{{ getColumn('pluginAuth').label }}</th>
70 <th *ngIf="isSelected('createdAt')" style="width: 150px;" pSortableColumn="createdAt">{{ getColumn('createdAt').label }} <p-sortIcon field="createdAt"></p-sortIcon></th> 70 <th *ngIf="isSelected('createdAt')" style="width: 150px;" pSortableColumn="createdAt">{{ getColumn('createdAt').label }} <p-sortIcon field="createdAt"></p-sortIcon></th>
71 <th *ngIf="isSelected('lastLoginDate')" style="width: 150px;" pSortableColumn="lastLoginDate">{{ getColumn('lastLoginDate').label }} <p-sortIcon field="lastLoginDate"></p-sortIcon></th> 71 <th *ngIf="isSelected('lastLoginDate')" style="width: 150px;" pSortableColumn="lastLoginDate">{{ getColumn('lastLoginDate').label }} <p-sortIcon field="lastLoginDate"></p-sortIcon></th>
@@ -84,8 +84,9 @@
84 </td> 84 </td>
85 85
86 <td class="action-cell"> 86 <td class="action-cell">
87 <my-user-moderation-dropdown *ngIf="!isInSelectionMode()" [user]="user" container="body" 87 <my-user-moderation-dropdown
88 (userChanged)="onUserChanged()" (userDeleted)="onUserChanged()"> 88 *ngIf="!isInSelectionMode()" [user]="user" [account]="user.accountMutedStatus" [displayOptions]="userModerationDisplayOptions"
89 container="body" (userChanged)="onUserChanged()" (userDeleted)="onUserChanged()">
89 </my-user-moderation-dropdown> 90 </my-user-moderation-dropdown>
90 </td> 91 </td>
91 92
@@ -99,6 +100,14 @@
99 </div> 100 </div>
100 </div> 101 </div>
101 </a> 102 </a>
103
104 <div *ngIf="user.accountMutedStatus.mutedByInstance" class="badges-username badge badge-red" i18n>Muted</div>
105 <div *ngIf="user.blocked" class="badges-username badge badge-red" i18n>Banned</div>
106 </td>
107
108 <td *ngIf="isSelected('role')">
109 <span *ngIf="user.blocked" class="badge badge-banned" i18n-title title="The user was banned">{{ user.roleLabel }}</span>
110 <span *ngIf="!user.blocked" class="badge" [ngClass]="getRoleClass(user.role)">{{ user.roleLabel }}</span>
102 </td> 111 </td>
103 112
104 <td *ngIf="isSelected('email')" [title]="user.email"> 113 <td *ngIf="isSelected('email')" [title]="user.email">
@@ -138,11 +147,6 @@
138 </div> 147 </div>
139 </td> 148 </td>
140 149
141 <td *ngIf="isSelected('role')">
142 <span *ngIf="user.blocked" class="badge badge-banned" i18n-title title="The user was banned">{{ user.roleLabel }}</span>
143 <span *ngIf="!user.blocked" class="badge" [ngClass]="getRoleClass(user.role)">{{ user.roleLabel }}</span>
144 </td>
145
146 <td *ngIf="isSelected('pluginAuth')"> 150 <td *ngIf="isSelected('pluginAuth')">
147 <ng-container *ngIf="user.pluginAuth">{{ user.pluginAuth }}</ng-container> 151 <ng-container *ngIf="user.pluginAuth">{{ user.pluginAuth }}</ng-container>
148 </td> 152 </td>
diff --git a/client/src/app/+admin/overview/users/user-list/user-list.component.scss b/client/src/app/+admin/overview/users/user-list/user-list.component.scss
index 335bd2995..8160703f0 100644
--- a/client/src/app/+admin/overview/users/user-list/user-list.component.scss
+++ b/client/src/app/+admin/overview/users/user-list/user-list.component.scss
@@ -23,6 +23,10 @@ tr.banned > td {
23 font-weight: $font-semibold; 23 font-weight: $font-semibold;
24} 24}
25 25
26.badges-username {
27 margin-left: 15px;
28}
29
26.user-table-primary-text .glyphicon { 30.user-table-primary-text .glyphicon {
27 @include margin-left(0.1rem); 31 @include margin-left(0.1rem);
28 32
diff --git a/client/src/app/+admin/overview/users/user-list/user-list.component.ts b/client/src/app/+admin/overview/users/user-list/user-list.component.ts
index 9a9d0f5c6..d22e1355e 100644
--- a/client/src/app/+admin/overview/users/user-list/user-list.component.ts
+++ b/client/src/app/+admin/overview/users/user-list/user-list.component.ts
@@ -2,9 +2,10 @@ import { SortMeta } from 'primeng/api'
2import { Component, OnInit, ViewChild } from '@angular/core' 2import { Component, OnInit, ViewChild } from '@angular/core'
3import { ActivatedRoute, Router } from '@angular/router' 3import { ActivatedRoute, Router } from '@angular/router'
4import { AuthService, ConfirmService, Notifier, RestPagination, RestTable, ServerService } from '@app/core' 4import { AuthService, ConfirmService, Notifier, RestPagination, RestTable, ServerService } from '@app/core'
5import { getAPIHost } from '@app/helpers'
5import { AdvancedInputFilter } from '@app/shared/shared-forms' 6import { AdvancedInputFilter } from '@app/shared/shared-forms'
6import { DropdownAction } from '@app/shared/shared-main' 7import { Actor, DropdownAction } from '@app/shared/shared-main'
7import { UserBanModalComponent } from '@app/shared/shared-moderation' 8import { AccountMutedStatus, BlocklistService, UserBanModalComponent, UserModerationDisplayType } from '@app/shared/shared-moderation'
8import { UserAdminService } from '@app/shared/shared-users' 9import { UserAdminService } from '@app/shared/shared-users'
9import { User, UserRole } from '@shared/models' 10import { User, UserRole } from '@shared/models'
10 11
@@ -23,7 +24,7 @@ type UserForList = User & {
23export class UserListComponent extends RestTable implements OnInit { 24export class UserListComponent extends RestTable implements OnInit {
24 @ViewChild('userBanModal', { static: true }) userBanModal: UserBanModalComponent 25 @ViewChild('userBanModal', { static: true }) userBanModal: UserBanModalComponent
25 26
26 users: User[] = [] 27 users: (User & { accountMutedStatus: AccountMutedStatus })[] = []
27 28
28 totalRecords = 0 29 totalRecords = 0
29 sort: SortMeta = { field: 'createdAt', order: 1 } 30 sort: SortMeta = { field: 'createdAt', order: 1 }
@@ -47,6 +48,12 @@ export class UserListComponent extends RestTable implements OnInit {
47 } 48 }
48 ] 49 ]
49 50
51 userModerationDisplayOptions: UserModerationDisplayType = {
52 instanceAccount: true,
53 instanceUser: true,
54 myAccount: false
55 }
56
50 requiresEmailVerification = false 57 requiresEmailVerification = false
51 58
52 private _selectedColumns: string[] 59 private _selectedColumns: string[]
@@ -58,6 +65,7 @@ export class UserListComponent extends RestTable implements OnInit {
58 private confirmService: ConfirmService, 65 private confirmService: ConfirmService,
59 private serverService: ServerService, 66 private serverService: ServerService,
60 private auth: AuthService, 67 private auth: AuthService,
68 private blocklist: BlocklistService,
61 private userAdminService: UserAdminService 69 private userAdminService: UserAdminService
62 ) { 70 ) {
63 super() 71 super()
@@ -115,9 +123,9 @@ export class UserListComponent extends RestTable implements OnInit {
115 123
116 this.columns = [ 124 this.columns = [
117 { id: 'username', label: $localize`Username` }, 125 { id: 'username', label: $localize`Username` },
126 { id: 'role', label: $localize`Role` },
118 { id: 'email', label: $localize`Email` }, 127 { id: 'email', label: $localize`Email` },
119 { id: 'quota', label: $localize`Video quota` }, 128 { id: 'quota', label: $localize`Video quota` },
120 { id: 'role', label: $localize`Role` },
121 { id: 'createdAt', label: $localize`Created` } 129 { id: 'createdAt', label: $localize`Created` }
122 ] 130 ]
123 131
@@ -237,11 +245,35 @@ export class UserListComponent extends RestTable implements OnInit {
237 search: this.search 245 search: this.search
238 }).subscribe({ 246 }).subscribe({
239 next: resultList => { 247 next: resultList => {
240 this.users = resultList.data 248 this.users = resultList.data.map(u => ({
249 ...u,
250
251 accountMutedStatus: {
252 ...u.account,
253
254 nameWithHost: Actor.CREATE_BY_STRING(u.account.name, u.account.host),
255
256 mutedByInstance: false,
257 mutedByUser: false,
258 mutedServerByInstance: false,
259 mutedServerByUser: false
260 }
261 }))
241 this.totalRecords = resultList.total 262 this.totalRecords = resultList.total
263
264 this.loadMutedStatus()
242 }, 265 },
243 266
244 error: err => this.notifier.error(err.message) 267 error: err => this.notifier.error(err.message)
245 }) 268 })
246 } 269 }
270
271 private loadMutedStatus () {
272 this.blocklist.getStatus({ accounts: this.users.map(u => u.username + '@' + getAPIHost()) })
273 .subscribe(blockStatus => {
274 for (const user of this.users) {
275 user.accountMutedStatus.mutedByInstance = blockStatus.accounts[user.username + '@' + getAPIHost()].blockedByServer
276 }
277 })
278 }
247} 279}
diff --git a/client/src/app/+admin/overview/users/users.routes.ts b/client/src/app/+admin/overview/users/users.routes.ts
index 8b63f5bc7..c9724e5fb 100644
--- a/client/src/app/+admin/overview/users/users.routes.ts
+++ b/client/src/app/+admin/overview/users/users.routes.ts
@@ -4,7 +4,7 @@ import { UserRight } from '@shared/models'
4import { UserCreateComponent, UserUpdateComponent } from './user-edit' 4import { UserCreateComponent, UserUpdateComponent } from './user-edit'
5import { UserListComponent } from './user-list' 5import { UserListComponent } from './user-list'
6 6
7export const UsersRoutes: Routes = [ 7export const usersRoutes: Routes = [
8 { 8 {
9 path: 'users', 9 path: 'users',
10 canActivate: [ UserRightGuard ], 10 canActivate: [ UserRightGuard ],
diff --git a/client/src/app/+admin/overview/videos/video-list.component.html b/client/src/app/+admin/overview/videos/video-list.component.html
index 974912b32..75d9be5f1 100644
--- a/client/src/app/+admin/overview/videos/video-list.component.html
+++ b/client/src/app/+admin/overview/videos/video-list.component.html
@@ -24,9 +24,7 @@
24 <div class="ml-auto right-form"> 24 <div class="ml-auto right-form">
25 <my-advanced-input-filter [filters]="inputFilters" (search)="onSearch($event)"></my-advanced-input-filter> 25 <my-advanced-input-filter [filters]="inputFilters" (search)="onSearch($event)"></my-advanced-input-filter>
26 26
27 <div class="button-filter-block"> 27 <my-button i18n-label label="Refresh" icon="refresh" (click)="reloadData()"></my-button>
28 <my-button i18n-label label="Refresh" icon="refresh" (click)="reloadData()"></my-button>
29 </div>
30 </div> 28 </div>
31 29
32 </div> 30 </div>
diff --git a/client/src/app/+admin/overview/videos/video-list.component.scss b/client/src/app/+admin/overview/videos/video-list.component.scss
index 543cb433c..cb47b6548 100644
--- a/client/src/app/+admin/overview/videos/video-list.component.scss
+++ b/client/src/app/+admin/overview/videos/video-list.component.scss
@@ -1,5 +1,6 @@
1@use '_variables' as *; 1@use '_variables' as *;
2@use '_mixins' as *; 2@use '_mixins' as *;
3
3my-embed { 4my-embed {
4 display: block; 5 display: block;
5 max-width: 500px; 6 max-width: 500px;
@@ -27,4 +28,3 @@ my-embed {
27 @include margin-right(10px); 28 @include margin-right(10px);
28 } 29 }
29} 30}
30
diff --git a/client/src/app/+admin/overview/videos/video.routes.ts b/client/src/app/+admin/overview/videos/video.routes.ts
index 984df7b82..01cb5b497 100644
--- a/client/src/app/+admin/overview/videos/video.routes.ts
+++ b/client/src/app/+admin/overview/videos/video.routes.ts
@@ -3,7 +3,7 @@ import { UserRightGuard } from '@app/core'
3import { UserRight } from '@shared/models' 3import { UserRight } from '@shared/models'
4import { VideoListComponent } from './video-list.component' 4import { VideoListComponent } from './video-list.component'
5 5
6export const VideosRoutes: Routes = [ 6export const videosRoutes: Routes = [
7 { 7 {
8 path: 'videos', 8 path: 'videos',
9 canActivate: [ UserRightGuard ], 9 canActivate: [ UserRightGuard ],