diff options
Diffstat (limited to 'client/src/app/+admin/overview')
7 files changed, 38 insertions, 81 deletions
diff --git a/client/src/app/+admin/overview/comments/video-comment-list.component.html b/client/src/app/+admin/overview/comments/video-comment-list.component.html index d2ca5f700..b0d8131bf 100644 --- a/client/src/app/+admin/overview/comments/video-comment-list.component.html +++ b/client/src/app/+admin/overview/comments/video-comment-list.component.html | |||
@@ -13,14 +13,14 @@ | |||
13 | [lazy]="true" (onLazyLoad)="loadLazy($event)" [lazyLoadOnInit]="false" [selectionPageOnly]="true" | 13 | [lazy]="true" (onLazyLoad)="loadLazy($event)" [lazyLoadOnInit]="false" [selectionPageOnly]="true" |
14 | [showCurrentPageReport]="true" i18n-currentPageReportTemplate | 14 | [showCurrentPageReport]="true" i18n-currentPageReportTemplate |
15 | currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} comments" | 15 | currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} comments" |
16 | [expandedRowKeys]="expandedRows" [(selection)]="selectedComments" | 16 | [expandedRowKeys]="expandedRows" [(selection)]="selectedRows" |
17 | > | 17 | > |
18 | <ng-template pTemplate="caption"> | 18 | <ng-template pTemplate="caption"> |
19 | <div class="caption"> | 19 | <div class="caption"> |
20 | <div> | 20 | <div> |
21 | <my-action-dropdown | 21 | <my-action-dropdown |
22 | *ngIf="isInSelectionMode()" i18n-label label="Batch actions" theme="orange" | 22 | *ngIf="isInSelectionMode()" i18n-label label="Batch actions" theme="orange" |
23 | [actions]="bulkCommentActions" [entry]="selectedComments" | 23 | [actions]="bulkActions" [entry]="selectedRows" |
24 | > | 24 | > |
25 | </my-action-dropdown> | 25 | </my-action-dropdown> |
26 | </div> | 26 | </div> |
diff --git a/client/src/app/+admin/overview/comments/video-comment-list.component.ts b/client/src/app/+admin/overview/comments/video-comment-list.component.ts index c95d2ffeb..28efdc076 100644 --- a/client/src/app/+admin/overview/comments/video-comment-list.component.ts +++ b/client/src/app/+admin/overview/comments/video-comment-list.component.ts | |||
@@ -14,7 +14,7 @@ import { prepareIcu } from '@app/helpers' | |||
14 | templateUrl: './video-comment-list.component.html', | 14 | templateUrl: './video-comment-list.component.html', |
15 | styleUrls: [ '../../../shared/shared-moderation/moderation.scss', './video-comment-list.component.scss' ] | 15 | styleUrls: [ '../../../shared/shared-moderation/moderation.scss', './video-comment-list.component.scss' ] |
16 | }) | 16 | }) |
17 | export class VideoCommentListComponent extends RestTable implements OnInit { | 17 | export class VideoCommentListComponent extends RestTable <VideoCommentAdmin> implements OnInit { |
18 | comments: VideoCommentAdmin[] | 18 | comments: VideoCommentAdmin[] |
19 | totalRecords = 0 | 19 | totalRecords = 0 |
20 | sort: SortMeta = { field: 'createdAt', order: -1 } | 20 | sort: SortMeta = { field: 'createdAt', order: -1 } |
@@ -40,8 +40,7 @@ export class VideoCommentListComponent extends RestTable implements OnInit { | |||
40 | } | 40 | } |
41 | ] | 41 | ] |
42 | 42 | ||
43 | selectedComments: VideoCommentAdmin[] = [] | 43 | bulkActions: DropdownAction<VideoCommentAdmin[]>[] = [] |
44 | bulkCommentActions: DropdownAction<VideoCommentAdmin[]>[] = [] | ||
45 | 44 | ||
46 | inputFilters: AdvancedInputFilter[] = [ | 45 | inputFilters: AdvancedInputFilter[] = [ |
47 | { | 46 | { |
@@ -100,7 +99,7 @@ export class VideoCommentListComponent extends RestTable implements OnInit { | |||
100 | ngOnInit () { | 99 | ngOnInit () { |
101 | this.initialize() | 100 | this.initialize() |
102 | 101 | ||
103 | this.bulkCommentActions = [ | 102 | this.bulkActions = [ |
104 | { | 103 | { |
105 | label: $localize`Delete`, | 104 | label: $localize`Delete`, |
106 | handler: comments => this.removeComments(comments), | 105 | handler: comments => this.removeComments(comments), |
@@ -118,11 +117,7 @@ export class VideoCommentListComponent extends RestTable implements OnInit { | |||
118 | return this.markdownRenderer.textMarkdownToHTML({ markdown: text, withHtml: true, withEmoji: true }) | 117 | return this.markdownRenderer.textMarkdownToHTML({ markdown: text, withHtml: true, withEmoji: true }) |
119 | } | 118 | } |
120 | 119 | ||
121 | isInSelectionMode () { | 120 | protected reloadDataInternal () { |
122 | return this.selectedComments.length !== 0 | ||
123 | } | ||
124 | |||
125 | reloadData () { | ||
126 | this.videoCommentService.getAdminVideoComments({ | 121 | this.videoCommentService.getAdminVideoComments({ |
127 | pagination: this.pagination, | 122 | pagination: this.pagination, |
128 | sort: this.sort, | 123 | sort: this.sort, |
@@ -162,7 +157,7 @@ export class VideoCommentListComponent extends RestTable implements OnInit { | |||
162 | 157 | ||
163 | error: err => this.notifier.error(err.message), | 158 | error: err => this.notifier.error(err.message), |
164 | 159 | ||
165 | complete: () => this.selectedComments = [] | 160 | complete: () => this.selectedRows = [] |
166 | }) | 161 | }) |
167 | } | 162 | } |
168 | 163 | ||
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 a96ce561c..7eb5e0fc7 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 | |||
@@ -6,7 +6,7 @@ | |||
6 | <p-table | 6 | <p-table |
7 | [value]="users" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [first]="pagination.start" | 7 | [value]="users" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [first]="pagination.start" |
8 | [rowsPerPageOptions]="rowsPerPageOptions" [sortField]="sort.field" [sortOrder]="sort.order" dataKey="id" [resizableColumns]="true" | 8 | [rowsPerPageOptions]="rowsPerPageOptions" [sortField]="sort.field" [sortOrder]="sort.order" dataKey="id" [resizableColumns]="true" |
9 | [(selection)]="selectedUsers" [lazy]="true" (onLazyLoad)="loadLazy($event)" [lazyLoadOnInit]="false" [selectionPageOnly]="true" | 9 | [(selection)]="selectedRows" [lazy]="true" (onLazyLoad)="loadLazy($event)" [lazyLoadOnInit]="false" [selectionPageOnly]="true" |
10 | [showCurrentPageReport]="true" i18n-currentPageReportTemplate | 10 | [showCurrentPageReport]="true" i18n-currentPageReportTemplate |
11 | currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} users" | 11 | currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} users" |
12 | [expandedRowKeys]="expandedRows" | 12 | [expandedRowKeys]="expandedRows" |
@@ -16,7 +16,7 @@ | |||
16 | <div class="left-buttons"> | 16 | <div class="left-buttons"> |
17 | <my-action-dropdown | 17 | <my-action-dropdown |
18 | *ngIf="isInSelectionMode()" i18n-label label="Batch actions" theme="orange" | 18 | *ngIf="isInSelectionMode()" i18n-label label="Batch actions" theme="orange" |
19 | [actions]="bulkUserActions" [entry]="selectedUsers" | 19 | [actions]="bulkActions" [entry]="selectedRows" |
20 | > | 20 | > |
21 | </my-action-dropdown> | 21 | </my-action-dropdown> |
22 | 22 | ||
@@ -95,7 +95,7 @@ | |||
95 | <div class="chip two-lines"> | 95 | <div class="chip two-lines"> |
96 | <my-actor-avatar [actor]="user?.account" actorType="account" size="32"></my-actor-avatar> | 96 | <my-actor-avatar [actor]="user?.account" actorType="account" size="32"></my-actor-avatar> |
97 | <div> | 97 | <div> |
98 | <span class="user-table-primary-text">{{ user.account.displayName }}</span> | 98 | <span>{{ user.account.displayName }}</span> |
99 | <span class="muted">{{ user.username }}</span> | 99 | <span class="muted">{{ user.username }}</span> |
100 | </div> | 100 | </div> |
101 | </div> | 101 | </div> |
@@ -110,23 +110,10 @@ | |||
110 | <span *ngIf="!user.blocked" class="pt-badge" [ngClass]="getRoleClass(user.role.id)">{{ user.role.label }}</span> | 110 | <span *ngIf="!user.blocked" class="pt-badge" [ngClass]="getRoleClass(user.role.id)">{{ user.role.label }}</span> |
111 | </td> | 111 | </td> |
112 | 112 | ||
113 | <td *ngIf="isSelected('email')" [title]="user.email"> | 113 | <td *ngIf="isSelected('email')"> |
114 | <ng-container *ngIf="!requiresEmailVerification || user.blocked; else emailWithVerificationStatus"> | 114 | <my-user-email-info [entry]="user" [requiresEmailVerification]="requiresEmailVerification"></my-user-email-info> |
115 | <a class="table-email" [href]="'mailto:' + user.email">{{ user.email }}</a> | ||
116 | </ng-container> | ||
117 | </td> | 115 | </td> |
118 | 116 | ||
119 | <ng-template #emailWithVerificationStatus> | ||
120 | <td *ngIf="user.emailVerified === false; else emailVerifiedNotFalse" i18n-title title="User's email must be verified to login"> | ||
121 | <em>? {{ user.email }}</em> | ||
122 | </td> | ||
123 | <ng-template #emailVerifiedNotFalse> | ||
124 | <td i18n-title title="User's email is verified / User can login without email verification"> | ||
125 | ✓ {{ user.email }} | ||
126 | </td> | ||
127 | </ng-template> | ||
128 | </ng-template> | ||
129 | |||
130 | <td *ngIf="isSelected('quota')"> | 117 | <td *ngIf="isSelected('quota')"> |
131 | <div class="progress" i18n-title title="Total video quota"> | 118 | <div class="progress" i18n-title title="Total video quota"> |
132 | <div class="progress-bar" role="progressbar" [style]="{ width: getUserVideoQuotaPercentage(user) + '%' }" | 119 | <div class="progress-bar" role="progressbar" [style]="{ width: getUserVideoQuotaPercentage(user) + '%' }" |
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 23e0d29ee..2a3b955d2 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 | |||
@@ -10,12 +10,6 @@ tr.banned > td { | |||
10 | background-color: lighten($color: $red, $amount: 40) !important; | 10 | background-color: lighten($color: $red, $amount: 40) !important; |
11 | } | 11 | } |
12 | 12 | ||
13 | .table-email { | ||
14 | @include disable-default-a-behaviour; | ||
15 | |||
16 | color: pvar(--mainForegroundColor); | ||
17 | } | ||
18 | |||
19 | .banned-info { | 13 | .banned-info { |
20 | font-style: italic; | 14 | font-style: italic; |
21 | } | 15 | } |
@@ -37,10 +31,6 @@ my-global-icon { | |||
37 | width: 18px; | 31 | width: 18px; |
38 | } | 32 | } |
39 | 33 | ||
40 | .chip { | ||
41 | @include chip; | ||
42 | } | ||
43 | |||
44 | .progress { | 34 | .progress { |
45 | @include progressbar($small: true); | 35 | @include progressbar($small: true); |
46 | 36 | ||
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 99987fdff..19420b748 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 | |||
@@ -22,7 +22,7 @@ type UserForList = User & { | |||
22 | templateUrl: './user-list.component.html', | 22 | templateUrl: './user-list.component.html', |
23 | styleUrls: [ './user-list.component.scss' ] | 23 | styleUrls: [ './user-list.component.scss' ] |
24 | }) | 24 | }) |
25 | export class UserListComponent extends RestTable implements OnInit { | 25 | export class UserListComponent extends RestTable <User> implements OnInit { |
26 | private static readonly LOCAL_STORAGE_SELECTED_COLUMNS_KEY = 'admin-user-list-selected-columns' | 26 | private static readonly LOCAL_STORAGE_SELECTED_COLUMNS_KEY = 'admin-user-list-selected-columns' |
27 | 27 | ||
28 | @ViewChild('userBanModal', { static: true }) userBanModal: UserBanModalComponent | 28 | @ViewChild('userBanModal', { static: true }) userBanModal: UserBanModalComponent |
@@ -35,8 +35,7 @@ export class UserListComponent extends RestTable implements OnInit { | |||
35 | 35 | ||
36 | highlightBannedUsers = false | 36 | highlightBannedUsers = false |
37 | 37 | ||
38 | selectedUsers: User[] = [] | 38 | bulkActions: DropdownAction<User[]>[][] = [] |
39 | bulkUserActions: DropdownAction<User[]>[][] = [] | ||
40 | columns: { id: string, label: string }[] | 39 | columns: { id: string, label: string }[] |
41 | 40 | ||
42 | inputFilters: AdvancedInputFilter[] = [ | 41 | inputFilters: AdvancedInputFilter[] = [ |
@@ -95,7 +94,7 @@ export class UserListComponent extends RestTable implements OnInit { | |||
95 | 94 | ||
96 | this.initialize() | 95 | this.initialize() |
97 | 96 | ||
98 | this.bulkUserActions = [ | 97 | this.bulkActions = [ |
99 | [ | 98 | [ |
100 | { | 99 | { |
101 | label: $localize`Delete`, | 100 | label: $localize`Delete`, |
@@ -249,7 +248,7 @@ export class UserListComponent extends RestTable implements OnInit { | |||
249 | const res = await this.confirmService.confirm(message, $localize`Delete`) | 248 | const res = await this.confirmService.confirm(message, $localize`Delete`) |
250 | if (res === false) return | 249 | if (res === false) return |
251 | 250 | ||
252 | this.userAdminService.removeUser(users) | 251 | this.userAdminService.removeUsers(users) |
253 | .subscribe({ | 252 | .subscribe({ |
254 | next: () => { | 253 | next: () => { |
255 | this.notifier.success( | 254 | this.notifier.success( |
@@ -284,13 +283,7 @@ export class UserListComponent extends RestTable implements OnInit { | |||
284 | }) | 283 | }) |
285 | } | 284 | } |
286 | 285 | ||
287 | isInSelectionMode () { | 286 | protected reloadDataInternal () { |
288 | return this.selectedUsers.length !== 0 | ||
289 | } | ||
290 | |||
291 | protected reloadData () { | ||
292 | this.selectedUsers = [] | ||
293 | |||
294 | this.userAdminService.getUsers({ | 287 | this.userAdminService.getUsers({ |
295 | pagination: this.pagination, | 288 | pagination: this.pagination, |
296 | sort: this.sort, | 289 | sort: this.sort, |
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 a6cd2e257..5b8405ad9 100644 --- a/client/src/app/+admin/overview/videos/video-list.component.html +++ b/client/src/app/+admin/overview/videos/video-list.component.html | |||
@@ -6,7 +6,7 @@ | |||
6 | <p-table | 6 | <p-table |
7 | [value]="videos" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [first]="pagination.start" | 7 | [value]="videos" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [first]="pagination.start" |
8 | [rowsPerPageOptions]="rowsPerPageOptions" [sortField]="sort.field" [sortOrder]="sort.order" dataKey="id" [resizableColumns]="true" | 8 | [rowsPerPageOptions]="rowsPerPageOptions" [sortField]="sort.field" [sortOrder]="sort.order" dataKey="id" [resizableColumns]="true" |
9 | [(selection)]="selectedVideos" [lazy]="true" (onLazyLoad)="loadLazy($event)" [lazyLoadOnInit]="false" [selectionPageOnly]="true" | 9 | [(selection)]="selectedRows" [lazy]="true" (onLazyLoad)="loadLazy($event)" [lazyLoadOnInit]="false" [selectionPageOnly]="true" |
10 | [showCurrentPageReport]="true" i18n-currentPageReportTemplate | 10 | [showCurrentPageReport]="true" i18n-currentPageReportTemplate |
11 | currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} videos" | 11 | currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} videos" |
12 | [expandedRowKeys]="expandedRows" [ngClass]="{ loading: loading }" | 12 | [expandedRowKeys]="expandedRows" [ngClass]="{ loading: loading }" |
@@ -16,7 +16,7 @@ | |||
16 | <div class="left-buttons"> | 16 | <div class="left-buttons"> |
17 | <my-action-dropdown | 17 | <my-action-dropdown |
18 | *ngIf="isInSelectionMode()" i18n-label label="Batch actions" theme="orange" | 18 | *ngIf="isInSelectionMode()" i18n-label label="Batch actions" theme="orange" |
19 | [actions]="bulkVideoActions" [entry]="selectedVideos" | 19 | [actions]="bulkActions" [entry]="selectedRows" |
20 | > | 20 | > |
21 | </my-action-dropdown> | 21 | </my-action-dropdown> |
22 | </div> | 22 | </div> |
diff --git a/client/src/app/+admin/overview/videos/video-list.component.ts b/client/src/app/+admin/overview/videos/video-list.component.ts index 4d3e9873c..1ea295499 100644 --- a/client/src/app/+admin/overview/videos/video-list.component.ts +++ b/client/src/app/+admin/overview/videos/video-list.component.ts | |||
@@ -17,7 +17,7 @@ import { VideoAdminService } from './video-admin.service' | |||
17 | templateUrl: './video-list.component.html', | 17 | templateUrl: './video-list.component.html', |
18 | styleUrls: [ './video-list.component.scss' ] | 18 | styleUrls: [ './video-list.component.scss' ] |
19 | }) | 19 | }) |
20 | export class VideoListComponent extends RestTable implements OnInit { | 20 | export class VideoListComponent extends RestTable <Video> implements OnInit { |
21 | @ViewChild('videoBlockModal') videoBlockModal: VideoBlockComponent | 21 | @ViewChild('videoBlockModal') videoBlockModal: VideoBlockComponent |
22 | 22 | ||
23 | videos: Video[] = [] | 23 | videos: Video[] = [] |
@@ -26,9 +26,7 @@ export class VideoListComponent extends RestTable implements OnInit { | |||
26 | sort: SortMeta = { field: 'publishedAt', order: -1 } | 26 | sort: SortMeta = { field: 'publishedAt', order: -1 } |
27 | pagination: RestPagination = { count: this.rowsPerPage, start: 0 } | 27 | pagination: RestPagination = { count: this.rowsPerPage, start: 0 } |
28 | 28 | ||
29 | bulkVideoActions: DropdownAction<Video[]>[][] = [] | 29 | bulkActions: DropdownAction<Video[]>[][] = [] |
30 | |||
31 | selectedVideos: Video[] = [] | ||
32 | 30 | ||
33 | inputFilters: AdvancedInputFilter[] | 31 | inputFilters: AdvancedInputFilter[] |
34 | 32 | ||
@@ -72,7 +70,7 @@ export class VideoListComponent extends RestTable implements OnInit { | |||
72 | 70 | ||
73 | this.inputFilters = this.videoAdminService.buildAdminInputFilter() | 71 | this.inputFilters = this.videoAdminService.buildAdminInputFilter() |
74 | 72 | ||
75 | this.bulkVideoActions = [ | 73 | this.bulkActions = [ |
76 | [ | 74 | [ |
77 | { | 75 | { |
78 | label: $localize`Delete`, | 76 | label: $localize`Delete`, |
@@ -126,10 +124,6 @@ export class VideoListComponent extends RestTable implements OnInit { | |||
126 | return 'VideoListComponent' | 124 | return 'VideoListComponent' |
127 | } | 125 | } |
128 | 126 | ||
129 | isInSelectionMode () { | ||
130 | return this.selectedVideos.length !== 0 | ||
131 | } | ||
132 | |||
133 | getPrivacyBadgeClass (video: Video) { | 127 | getPrivacyBadgeClass (video: Video) { |
134 | if (video.privacy.id === VideoPrivacy.PUBLIC) return 'badge-green' | 128 | if (video.privacy.id === VideoPrivacy.PUBLIC) return 'badge-green' |
135 | 129 | ||
@@ -189,9 +183,23 @@ export class VideoListComponent extends RestTable implements OnInit { | |||
189 | return files.reduce((p, f) => p += f.size, 0) | 183 | return files.reduce((p, f) => p += f.size, 0) |
190 | } | 184 | } |
191 | 185 | ||
192 | reloadData () { | 186 | async removeVideoFile (video: Video, file: VideoFile, type: 'hls' | 'webtorrent') { |
193 | this.selectedVideos = [] | 187 | const message = $localize`Are you sure you want to delete this ${file.resolution.label} file?` |
188 | const res = await this.confirmService.confirm(message, $localize`Delete file`) | ||
189 | if (res === false) return | ||
190 | |||
191 | this.videoService.removeFile(video.uuid, file.id, type) | ||
192 | .subscribe({ | ||
193 | next: () => { | ||
194 | this.notifier.success($localize`File removed.`) | ||
195 | this.reloadData() | ||
196 | }, | ||
197 | |||
198 | error: err => this.notifier.error(err.message) | ||
199 | }) | ||
200 | } | ||
194 | 201 | ||
202 | protected reloadDataInternal () { | ||
195 | this.loading = true | 203 | this.loading = true |
196 | 204 | ||
197 | this.videoAdminService.getAdminVideos({ | 205 | this.videoAdminService.getAdminVideos({ |
@@ -209,22 +217,6 @@ export class VideoListComponent extends RestTable implements OnInit { | |||
209 | }) | 217 | }) |
210 | } | 218 | } |
211 | 219 | ||
212 | async removeVideoFile (video: Video, file: VideoFile, type: 'hls' | 'webtorrent') { | ||
213 | const message = $localize`Are you sure you want to delete this ${file.resolution.label} file?` | ||
214 | const res = await this.confirmService.confirm(message, $localize`Delete file`) | ||
215 | if (res === false) return | ||
216 | |||
217 | this.videoService.removeFile(video.uuid, file.id, type) | ||
218 | .subscribe({ | ||
219 | next: () => { | ||
220 | this.notifier.success($localize`File removed.`) | ||
221 | this.reloadData() | ||
222 | }, | ||
223 | |||
224 | error: err => this.notifier.error(err.message) | ||
225 | }) | ||
226 | } | ||
227 | |||
228 | private async removeVideos (videos: Video[]) { | 220 | private async removeVideos (videos: Video[]) { |
229 | const message = prepareIcu($localize`Are you sure you want to delete {count, plural, =1 {this video} other {these {count} videos}}?`)( | 221 | const message = prepareIcu($localize`Are you sure you want to delete {count, plural, =1 {this video} other {these {count} videos}}?`)( |
230 | { count: videos.length }, | 222 | { count: videos.length }, |