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/config/edit-custom-config/edit-custom-config.component.html22
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss4
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts33
-rw-r--r--client/src/app/+admin/users/user-list/user-list.component.html44
-rw-r--r--client/src/app/+admin/users/user-list/user-list.component.scss1
-rw-r--r--client/src/app/+admin/users/user-list/user-list.component.ts34
6 files changed, 70 insertions, 68 deletions
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
index 8fdced1c7..b82281c6c 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
+++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
@@ -48,11 +48,12 @@
48 <label i18n for="instanceCategories">Main instance categories</label> 48 <label i18n for="instanceCategories">Main instance categories</label>
49 49
50 <div> 50 <div>
51 <p-multiSelect 51 <my-select-checkbox
52 inputId="instanceCategories" [options]="categoryItems" formControlName="categories" [showToggleAll]="false" 52 id="instanceCategories"
53 [defaultLabel]="getDefaultCategoryLabel()" [selectedItemsLabel]="getSelectedCategoryLabel()" 53 formControlName="categories" [availableItems]="categoryItems"
54 emptyFilterMessage="No results found" i18n-emptyFilterMessage 54 [selectableGroup]="false"
55 ></p-multiSelect> 55 >
56 </my-select-checkbox>
56 </div> 57 </div>
57 </div> 58 </div>
58 59
@@ -60,11 +61,12 @@
60 <label i18n for="instanceLanguages">Main languages you/your moderators speak</label> 61 <label i18n for="instanceLanguages">Main languages you/your moderators speak</label>
61 62
62 <div> 63 <div>
63 <p-multiSelect 64 <my-select-checkbox
64 inputId="instanceLanguages" [options]="languageItems" formControlName="languages" [showToggleAll]="false" 65 id="instanceLanguages"
65 [defaultLabel]="getDefaultLanguageLabel()" [selectedItemsLabel]="getSelectedLanguageLabel()" 66 formControlName="languages" [availableItems]="languageItems"
66 emptyFilterMessage="No results found" i18n-emptyFilterMessage 67 [selectableGroup]="false"
67 ></p-multiSelect> 68 >
69 </my-select-checkbox>
68 </div> 70 </div>
69 </div> 71 </div>
70 72
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss
index 9618100b5..f8f2d5fdc 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss
+++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss
@@ -30,6 +30,10 @@ input[type=checkbox] {
30 @include peertube-select-container($form-base-input-width); 30 @include peertube-select-container($form-base-input-width);
31} 31}
32 32
33my-select-checkbox {
34 @include ng-select($form-base-input-width);
35}
36
33input[type=submit] { 37input[type=submit] {
34 @include peertube-button; 38 @include peertube-button;
35 @include orange-button; 39 @include orange-button;
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 69629770f..00a0bfad2 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
@@ -1,11 +1,16 @@
1import { SelectItem } from 'primeng/api'
2import { forkJoin } from 'rxjs' 1import { forkJoin } from 'rxjs'
3import { ViewportScroller } from '@angular/common' 2import { ViewportScroller } from '@angular/common'
4import { AfterViewChecked, Component, OnInit, ViewChild } from '@angular/core' 3import { AfterViewChecked, Component, OnInit, ViewChild } from '@angular/core'
5import { ConfigService } from '@app/+admin/config/shared/config.service' 4import { ConfigService } from '@app/+admin/config/shared/config.service'
6import { Notifier } from '@app/core' 5import { Notifier } from '@app/core'
7import { ServerService } from '@app/core/server/server.service' 6import { ServerService } from '@app/core/server/server.service'
8import { CustomConfigValidatorsService, FormReactive, FormValidatorService, UserValidatorsService } from '@app/shared/shared-forms' 7import {
8 CustomConfigValidatorsService,
9 FormReactive,
10 FormValidatorService,
11 SelectOptionsItem,
12 UserValidatorsService
13} from '@app/shared/shared-forms'
9import { NgbNav } from '@ng-bootstrap/ng-bootstrap' 14import { NgbNav } from '@ng-bootstrap/ng-bootstrap'
10import { I18n } from '@ngx-translate/i18n-polyfill' 15import { I18n } from '@ngx-translate/i18n-polyfill'
11import { CustomConfig, ServerConfig } from '@shared/models' 16import { CustomConfig, ServerConfig } from '@shared/models'
@@ -25,8 +30,8 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit, A
25 resolutions: { id: string, label: string, description?: string }[] = [] 30 resolutions: { id: string, label: string, description?: string }[] = []
26 transcodingThreadOptions: { label: string, value: number }[] = [] 31 transcodingThreadOptions: { label: string, value: number }[] = []
27 32
28 languageItems: SelectItem[] = [] 33 languageItems: SelectOptionsItem[] = []
29 categoryItems: SelectItem[] = [] 34 categoryItems: SelectOptionsItem[] = []
30 35
31 private serverConfig: ServerConfig 36 private serverConfig: ServerConfig
32 37
@@ -290,22 +295,6 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit, A
290 ) 295 )
291 } 296 }
292 297
293 getSelectedLanguageLabel () {
294 return this.i18n('{{\'{0} languages selected')
295 }
296
297 getDefaultLanguageLabel () {
298 return this.i18n('No language')
299 }
300
301 getSelectedCategoryLabel () {
302 return this.i18n('{{\'{0} categories selected')
303 }
304
305 getDefaultCategoryLabel () {
306 return this.i18n('No category')
307 }
308
309 gotoAnchor () { 298 gotoAnchor () {
310 const hashToNav = { 299 const hashToNav = {
311 'customizations': 'advanced-configuration' 300 'customizations': 'advanced-configuration'
@@ -331,8 +320,8 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit, A
331 ([ config, languages, categories ]) => { 320 ([ config, languages, categories ]) => {
332 this.customConfig = config 321 this.customConfig = config
333 322
334 this.languageItems = languages.map(l => ({ label: l.label, value: l.id })) 323 this.languageItems = languages.map(l => ({ label: l.label, id: l.id }))
335 this.categoryItems = categories.map(l => ({ label: l.label, value: l.id })) 324 this.categoryItems = categories.map(l => ({ label: l.label, id: l.id + '' }))
336 325
337 this.updateForm() 326 this.updateForm()
338 // Force form validation 327 // Force form validation
diff --git a/client/src/app/+admin/users/user-list/user-list.component.html b/client/src/app/+admin/users/user-list/user-list.component.html
index 3090247e5..d02f6526f 100644
--- a/client/src/app/+admin/users/user-list/user-list.component.html
+++ b/client/src/app/+admin/users/user-list/user-list.component.html
@@ -57,12 +57,12 @@
57 <div role="menu" class="dropdown-menu" ngbDropdownMenu> 57 <div role="menu" class="dropdown-menu" ngbDropdownMenu>
58 <div class="dropdown-header" i18n>Table parameters</div> 58 <div class="dropdown-header" i18n>Table parameters</div>
59 <div ngbDropdownItem class="dropdown-item"> 59 <div ngbDropdownItem class="dropdown-item">
60 <p-multiSelect 60 <my-select-checkbox
61 [options]="columns" [showToggleAll]="true" [(ngModel)]="selectedColumns" optionLabel="label" 61 name="columns"
62 emptyFilterMessage="No matching column found" i18n-emptyFilterMessage [filter]="false" 62 [availableItems]="columns"
63 selectedItemsLabel="{0} columns displayed" i18n-emptyFilterMessage [showHeader]="false" 63 [selectableGroup]="false" [(ngModel)]="selectedColumns"
64 [maxSelectedLabels]="4" 64 >
65 ></p-multiSelect> 65 </my-select-checkbox>
66 </div> 66 </div>
67 <div ngbDropdownItem class="dropdown-item"> 67 <div ngbDropdownItem class="dropdown-item">
68 <my-peertube-checkbox inputName="highlightBannedUsers" [(ngModel)]="highlightBannedUsers" 68 <my-peertube-checkbox inputName="highlightBannedUsers" [(ngModel)]="highlightBannedUsers"
@@ -71,14 +71,14 @@
71 </div> 71 </div>
72 </div> 72 </div>
73 </th> 73 </th>
74 <th *ngIf="getColumn('username')" pResizableColumn i18n pSortableColumn="username">{{ getColumn('username').label }} <p-sortIcon field="username"></p-sortIcon></th> 74 <th *ngIf="isSelected('username')" pResizableColumn i18n pSortableColumn="username">{{ getColumn('username').label }} <p-sortIcon field="username"></p-sortIcon></th>
75 <th *ngIf="getColumn('email')" i18n>{{ getColumn('email').label }}</th> 75 <th *ngIf="isSelected('email')" i18n>{{ getColumn('email').label }}</th>
76 <th *ngIf="getColumn('quota')" style="width: 160px;" i18n pSortableColumn="videoQuotaUsed">{{ getColumn('quota').label }} <p-sortIcon field="videoQuotaUsed"></p-sortIcon></th> 76 <th *ngIf="isSelected('quota')" style="width: 160px;" i18n pSortableColumn="videoQuotaUsed">{{ getColumn('quota').label }} <p-sortIcon field="videoQuotaUsed"></p-sortIcon></th>
77 <th *ngIf="getColumn('quotaDaily')" style="width: 160px;" i18n>{{ getColumn('quotaDaily').label }}</th> 77 <th *ngIf="isSelected('quotaDaily')" style="width: 160px;" i18n>{{ getColumn('quotaDaily').label }}</th>
78 <th *ngIf="getColumn('role')" style="width: 120px;" i18n pSortableColumn="role">{{ getColumn('role').label }} <p-sortIcon field="role"></p-sortIcon></th> 78 <th *ngIf="isSelected('role')" style="width: 120px;" i18n pSortableColumn="role">{{ getColumn('role').label }} <p-sortIcon field="role"></p-sortIcon></th>
79 <th *ngIf="getColumn('pluginAuth')" style="width: 140px;" pResizableColumn i18n>{{ getColumn('pluginAuth').label }}</th> 79 <th *ngIf="isSelected('pluginAuth')" style="width: 140px;" pResizableColumn i18n>{{ getColumn('pluginAuth').label }}</th>
80 <th *ngIf="getColumn('createdAt')" style="width: 150px;" i18n pSortableColumn="createdAt">{{ getColumn('createdAt').label }} <p-sortIcon field="createdAt"></p-sortIcon></th> 80 <th *ngIf="isSelected('createdAt')" style="width: 150px;" i18n pSortableColumn="createdAt">{{ getColumn('createdAt').label }} <p-sortIcon field="createdAt"></p-sortIcon></th>
81 <th *ngIf="getColumn('lastLoginDate')" style="width: 150px;" i18n pSortableColumn="lastLoginDate">{{ getColumn('lastLoginDate').label }} <p-sortIcon field="lastLoginDate"></p-sortIcon></th> 81 <th *ngIf="isSelected('lastLoginDate')" style="width: 150px;" i18n pSortableColumn="lastLoginDate">{{ getColumn('lastLoginDate').label }} <p-sortIcon field="lastLoginDate"></p-sortIcon></th>
82 </tr> 82 </tr>
83 </ng-template> 83 </ng-template>
84 84
@@ -101,7 +101,7 @@
101 </my-user-moderation-dropdown> 101 </my-user-moderation-dropdown>
102 </td> 102 </td>
103 103
104 <td *ngIf="getColumn('username')"> 104 <td *ngIf="isSelected('username')">
105 <a i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer" [routerLink]="[ '/accounts/' + user.username ]"> 105 <a i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer" [routerLink]="[ '/accounts/' + user.username ]">
106 <div class="chip two-lines"> 106 <div class="chip two-lines">
107 <img 107 <img
@@ -118,7 +118,7 @@
118 </a> 118 </a>
119 </td> 119 </td>
120 120
121 <td *ngIf="getColumn('email')" [title]="user.email"> 121 <td *ngIf="isSelected('email')" [title]="user.email">
122 <ng-container *ngIf="!requiresEmailVerification || user.blocked; else emailWithVerificationStatus"> 122 <ng-container *ngIf="!requiresEmailVerification || user.blocked; else emailWithVerificationStatus">
123 <a class="table-email" [href]="'mailto:' + user.email">{{ user.email }}</a> 123 <a class="table-email" [href]="'mailto:' + user.email">{{ user.email }}</a>
124 </ng-container> 124 </ng-container>
@@ -135,7 +135,7 @@
135 </ng-template> 135 </ng-template>
136 </ng-template> 136 </ng-template>
137 137
138 <td *ngIf="getColumn('quota')"> 138 <td *ngIf="isSelected('quota')">
139 <div class="progress" i18n-title title="Total video quota"> 139 <div class="progress" i18n-title title="Total video quota">
140 <div class="progress-bar" role="progressbar" [style]="{ width: getUserVideoQuotaPercentage(user) + '%' }" 140 <div class="progress-bar" role="progressbar" [style]="{ width: getUserVideoQuotaPercentage(user) + '%' }"
141 [attr.aria-valuenow]="user.rawVideoQuotaUsed" aria-valuemin="0" [attr.aria-valuemax]="user.rawVideoQuota"> 141 [attr.aria-valuenow]="user.rawVideoQuotaUsed" aria-valuemin="0" [attr.aria-valuemax]="user.rawVideoQuota">
@@ -145,7 +145,7 @@
145 </div> 145 </div>
146 </td> 146 </td>
147 147
148 <td *ngIf="getColumn('quotaDaily')"> 148 <td *ngIf="isSelected('quotaDaily')">
149 <div class="progress" i18n-title title="Total daily video quota"> 149 <div class="progress" i18n-title title="Total daily video quota">
150 <div class="progress-bar secondary" role="progressbar" [style]="{ width: getUserVideoQuotaDailyPercentage(user) + '%' }" 150 <div class="progress-bar secondary" role="progressbar" [style]="{ width: getUserVideoQuotaDailyPercentage(user) + '%' }"
151 [attr.aria-valuenow]="user.rawVideoQuotaUsedDaily" aria-valuemin="0" [attr.aria-valuemax]="user.rawVideoQuotaDaily"> 151 [attr.aria-valuenow]="user.rawVideoQuotaUsedDaily" aria-valuemin="0" [attr.aria-valuemax]="user.rawVideoQuotaDaily">
@@ -155,18 +155,18 @@
155 </div> 155 </div>
156 </td> 156 </td>
157 157
158 <td *ngIf="getColumn('role')"> 158 <td *ngIf="isSelected('role')">
159 <span *ngIf="user.blocked" class="badge badge-banned" i18n-title title="The user was banned">{{ user.roleLabel }}</span> 159 <span *ngIf="user.blocked" class="badge badge-banned" i18n-title title="The user was banned">{{ user.roleLabel }}</span>
160 <span *ngIf="!user.blocked" class="badge" [ngClass]="getRoleClass(user.role)">{{ user.roleLabel }}</span> 160 <span *ngIf="!user.blocked" class="badge" [ngClass]="getRoleClass(user.role)">{{ user.roleLabel }}</span>
161 </td> 161 </td>
162 162
163 <td *ngIf="getColumn('pluginAuth')"> 163 <td *ngIf="isSelected('pluginAuth')">
164 <ng-container *ngIf="user.pluginAuth">{{ user.pluginAuth }}</ng-container> 164 <ng-container *ngIf="user.pluginAuth">{{ user.pluginAuth }}</ng-container>
165 </td> 165 </td>
166 166
167 <td *ngIf="getColumn('createdAt')" [title]="user.createdAt">{{ user.createdAt | date: 'short' }}</td> 167 <td *ngIf="isSelected('createdAt')" [title]="user.createdAt">{{ user.createdAt | date: 'short' }}</td>
168 168
169 <td *ngIf="getColumn('lastLoginDate')" [title]="user.lastLoginDate">{{ user.lastLoginDate | date: 'short' }}</td> 169 <td *ngIf="isSelected('lastLoginDate')" [title]="user.lastLoginDate">{{ user.lastLoginDate | date: 'short' }}</td>
170 </tr> 170 </tr>
171 </ng-template> 171 </ng-template>
172 172
diff --git a/client/src/app/+admin/users/user-list/user-list.component.scss b/client/src/app/+admin/users/user-list/user-list.component.scss
index 98fc4d027..50080bad6 100644
--- a/client/src/app/+admin/users/user-list/user-list.component.scss
+++ b/client/src/app/+admin/users/user-list/user-list.component.scss
@@ -61,6 +61,7 @@ my-global-icon {
61 61
62.input-group { 62.input-group {
63 @include peertube-input-group(300px); 63 @include peertube-input-group(300px);
64
64 input { 65 input {
65 flex: 1; 66 flex: 1;
66 } 67 }
diff --git a/client/src/app/+admin/users/user-list/user-list.component.ts b/client/src/app/+admin/users/user-list/user-list.component.ts
index 699b2a6da..69d4e917d 100644
--- a/client/src/app/+admin/users/user-list/user-list.component.ts
+++ b/client/src/app/+admin/users/user-list/user-list.component.ts
@@ -30,9 +30,9 @@ export class UserListComponent extends RestTable implements OnInit {
30 30
31 selectedUsers: User[] = [] 31 selectedUsers: User[] = []
32 bulkUserActions: DropdownAction<User[]>[][] = [] 32 bulkUserActions: DropdownAction<User[]>[][] = []
33 columns: { key: string, label: string }[] 33 columns: { id: string, label: string }[]
34 34
35 private _selectedColumns: { key: string, label: string }[] 35 private _selectedColumns: string[]
36 private serverConfig: ServerConfig 36 private serverConfig: ServerConfig
37 37
38 constructor ( 38 constructor (
@@ -60,7 +60,7 @@ export class UserListComponent extends RestTable implements OnInit {
60 return this._selectedColumns 60 return this._selectedColumns
61 } 61 }
62 62
63 set selectedColumns (val) { 63 set selectedColumns (val: string[]) {
64 this._selectedColumns = val 64 this._selectedColumns = val
65 } 65 }
66 66
@@ -112,16 +112,18 @@ export class UserListComponent extends RestTable implements OnInit {
112 ] 112 ]
113 113
114 this.columns = [ 114 this.columns = [
115 { key: 'username', label: 'Username' }, 115 { id: 'username', label: 'Username' },
116 { key: 'email', label: 'Email' }, 116 { id: 'email', label: 'Email' },
117 { key: 'quota', label: 'Video quota' }, 117 { id: 'quota', label: 'Video quota' },
118 { key: 'role', label: 'Role' }, 118 { id: 'role', label: 'Role' },
119 { key: 'createdAt', label: 'Created' } 119 { id: 'createdAt', label: 'Created' }
120 ] 120 ]
121 this.selectedColumns = [ ...this.columns ] // make a full copy of the array 121
122 this.columns.push({ key: 'quotaDaily', label: 'Daily quota' }) 122 this.selectedColumns = this.columns.map(c => c.id)
123 this.columns.push({ key: 'pluginAuth', label: 'Auth plugin' }) 123
124 this.columns.push({ key: 'lastLoginDate', label: 'Last login' }) 124 this.columns.push({ id: 'quotaDaily', label: 'Daily quota' })
125 this.columns.push({ id: 'pluginAuth', label: 'Auth plugin' })
126 this.columns.push({ id: 'lastLoginDate', label: 'Last login' })
125 } 127 }
126 128
127 getIdentifier () { 129 getIdentifier () {
@@ -139,8 +141,12 @@ export class UserListComponent extends RestTable implements OnInit {
139 } 141 }
140 } 142 }
141 143
142 getColumn (key: string) { 144 isSelected (id: string) {
143 return this.selectedColumns.find((col: { key: string }) => col.key === key) 145 return this.selectedColumns.find(c => c === id)
146 }
147
148 getColumn (id: string) {
149 return this.columns.find(c => c.id === id)
144 } 150 }
145 151
146 getUserVideoQuotaPercentage (user: UserForList) { 152 getUserVideoQuotaPercentage (user: UserForList) {