2 <my-global-icon iconName=
"user" aria-hidden=
"true"></my-global-icon>
3 <ng-container i18n
>Users
</ng-container>
7 [value]=
"users" [paginator]=
"totalRecords > 0" [totalRecords]=
"totalRecords" [rows]=
"rowsPerPage" [rowsPerPageOptions]=
"rowsPerPageOptions"
8 [sortField]=
"sort.field" [sortOrder]=
"sort.order" dataKey=
"id" [resizableColumns]=
"true" [(selection)]=
"selectedUsers"
9 [lazy]=
"true" (onLazyLoad)=
"loadLazy($event)" [lazyLoadOnInit]=
"false" [selectionPageOnly]=
"true"
10 [showCurrentPageReport]=
"true" i18n-currentPageReportTemplate
11 currentPageReportTemplate=
"Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} users"
12 [expandedRowKeys]=
"expandedRows"
14 <ng-template pTemplate=
"caption">
16 <div class=
"left-buttons">
18 *
ngIf=
"isInSelectionMode()" i18n-label
label=
"Batch actions" theme=
"orange"
19 [actions]=
"bulkUserActions" [entry]=
"selectedUsers"
23 <a *
ngIf=
"!isInSelectionMode()" class=
"add-button" routerLink=
"/admin/users/create">
24 <my-global-icon iconName=
"user-add" aria-hidden=
"true"></my-global-icon>
25 <ng-container i18n
>Create user
</ng-container>
30 <my-advanced-input-filter [filters]=
"inputFilters" (search)=
"onSearch($event)"></my-advanced-input-filter>
36 <ng-template pTemplate=
"header">
38 <th style=
"width: 40px">
39 <p-tableHeaderCheckbox ariaLabel=
"Select all rows" i18n-ariaLabel
></p-tableHeaderCheckbox>
41 <th style=
"width: 40px"></th>
42 <th style=
"width: 60px;">
43 <div class=
"c-hand column-toggle" ngbDropdown
placement=
"bottom-left auto" container=
"body" autoClose=
"outside">
44 <my-global-icon iconName=
"columns" ngbDropdownToggle
></my-global-icon>
46 <div role=
"menu" class=
"dropdown-menu" ngbDropdownMenu
>
47 <div class=
"dropdown-header" i18n
>Table parameters
</div>
48 <div ngbDropdownItem
class=
"dropdown-item">
51 [availableItems]=
"columns"
52 [selectableGroup]=
"false" [(ngModel)]=
"selectedColumns"
53 i18n-placeholder
placeholder=
"Select columns"
57 <div ngbDropdownItem
class=
"dropdown-item">
58 <my-peertube-checkbox inputName=
"highlightBannedUsers" [(ngModel)]=
"highlightBannedUsers"
59 i18n-labelText
labelText=
"Highlight banned users"></my-peertube-checkbox>
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>
66 <th *
ngIf=
"isSelected('email')">{{ getColumn('email').label }}
</th>
67 <th *
ngIf=
"isSelected('quota')" style=
"width: 160px;" pSortableColumn=
"videoQuotaUsed">{{ getColumn('quota').label }}
<p-sortIcon field=
"videoQuotaUsed"></p-sortIcon></th>
68 <th *
ngIf=
"isSelected('quotaDaily')" style=
"width: 160px;">{{ getColumn('quotaDaily').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>
71 <th *
ngIf=
"isSelected('lastLoginDate')" style=
"width: 150px;" pSortableColumn=
"lastLoginDate">{{ getColumn('lastLoginDate').label }}
<p-sortIcon field=
"lastLoginDate"></p-sortIcon></th>
75 <ng-template pTemplate=
"body" let-expanded=
"expanded" let-user
>
77 <tr [pSelectableRow]=
"user" [ngClass]=
"{ banned: highlightBannedUsers && user.blocked }">
78 <td class=
"checkbox-cell">
79 <p-tableCheckbox [value]=
"user" ariaLabel=
"Select this row" i18n-ariaLabel
></p-tableCheckbox>
82 <td class=
"expand-cell" [ngClass]=
"{ 'empty-cell': !user.blockedReason }" [pRowToggler]=
"user">
83 <my-table-expander-icon *
ngIf=
"user.blockedReason" [expanded]=
"expanded"></my-table-expander-icon>
86 <td class=
"action-cell">
87 <my-user-moderation-dropdown
88 *
ngIf=
"!isInSelectionMode()" [user]=
"user" [account]=
"user.accountMutedStatus" [displayOptions]=
"userModerationDisplayOptions"
89 container=
"body" (userChanged)=
"onUserChanged()" (userDeleted)=
"onUserChanged()">
90 </my-user-moderation-dropdown>
93 <td *
ngIf=
"isSelected('username')">
94 <a i18n-title
title=
"Open account in a new tab" target=
"_blank" rel=
"noopener noreferrer" [routerLink]=
"[ '/a/' + user.username ]">
95 <div class=
"chip two-lines">
96 <my-actor-avatar [account]=
"user?.account" size=
"32"></my-actor-avatar>
98 <span class=
"user-table-primary-text">{{ user.account.displayName }}
</span>
99 <span class=
"muted">{{ user.username }}
</span>
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>
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>
113 <td *
ngIf=
"isSelected('email')" [title]=
"user.email">
114 <ng-container *
ngIf=
"!requiresEmailVerification || user.blocked; else emailWithVerificationStatus">
115 <a class=
"table-email" [href]=
"'mailto:' + user.email">{{ user.email }}
</a>
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>
123 <ng-template #emailVerifiedNotFalse
>
124 <td i18n-title
title=
"User's email is verified / User can login without email verification">
125 ✓ {{ user.email }}
130 <td *
ngIf=
"isSelected('quota')">
131 <div class=
"progress" i18n-title
title=
"Total video quota">
132 <div class=
"progress-bar" role=
"progressbar" [style]=
"{ width: getUserVideoQuotaPercentage(user) + '%' }"
133 [attr.aria-valuenow]=
"user.rawVideoQuotaUsed" aria-valuemin=
"0" [attr.aria-valuemax]=
"user.rawVideoQuota">
135 <span>{{ user.videoQuotaUsed }}
</span>
136 <span>{{ user.videoQuota }}
</span>
140 <td *
ngIf=
"isSelected('quotaDaily')">
141 <div class=
"progress" i18n-title
title=
"Total daily video quota">
142 <div class=
"progress-bar secondary" role=
"progressbar" [style]=
"{ width: getUserVideoQuotaDailyPercentage(user) + '%' }"
143 [attr.aria-valuenow]=
"user.rawVideoQuotaUsedDaily" aria-valuemin=
"0" [attr.aria-valuemax]=
"user.rawVideoQuotaDaily">
145 <span>{{ user.videoQuotaUsedDaily }}
</span>
146 <span>{{ user.videoQuotaDaily }}
</span>
150 <td *
ngIf=
"isSelected('pluginAuth')">
151 <ng-container *
ngIf=
"user.pluginAuth">{{ user.pluginAuth }}
</ng-container>
154 <td *
ngIf=
"isSelected('createdAt')" [title]=
"user.createdAt">{{ user.createdAt | date: 'short' }}
</td>
156 <td *
ngIf=
"isSelected('lastLoginDate')" [title]=
"user.lastLoginDate">{{ user.lastLoginDate | date: 'short' }}
</td>
160 <ng-template pTemplate=
"rowexpansion" let-user
>
161 <tr class=
"user-blocked-reason">
163 <span i18n
class=
"ban-reason-label">Ban reason:
</span>
164 {{ user.blockedReason }}
170 <my-user-ban-modal #userBanModal (userBanned)=
"onUserChanged()"></my-user-ban-modal>