src/app/core/admin/user/list-users/admin-list-users.component.html
<section class="page-header mb-3">
<div>
<h1 skipTo>Users</h1>
View and manage user accounts.
</div>
<system-alert />
</section>
<section class="page-body anchored-page-body">
<div class="table-header d-flex align-items-center">
<div class="table-actions d-flex flex-wrap flex-grow-1">
<div class="mb-3 me-5">
<asy-search-input
placeholder="Search..."
[search]="dataSource.searchEvent$.value"
(applySearch)="dataSource.search($event)"
/>
</div>
<div class="mb-3 ms-auto">
<button class="btn btn-outline-primary" type="button" (click)="exportCurrentView()">
<span class="fa-solid fa-download"></span> Export
</button>
<button class="btn btn-primary ms-3" type="button" routerLink="/admin/user">
<span class="fa-solid fa-user-plus"></span> Create User
</button>
<button
class="btn btn-outline-primary font-weight-bold ms-3"
type="button"
ngbTooltip="Set Columns"
(click)="sidebar.toggle()"
>
<span class="fa-solid fa-columns"></span>
</button>
</div>
</div>
</div>
<div class="d-flex overflow-hidden">
<div class="table-content">
<table
class="table table-striped"
asyFilter
asySort
cdk-table
[dataSource]="dataSource"
>
<asy-text-column name="_id" header="ID" />
<ng-container cdkColumnDef="name">
<th cdk-header-cell *cdkHeaderCellDef>
<asy-header-sort>Name</asy-header-sort>
</th>
<td class="text-nowrap" cdk-cell *cdkCellDef="let user">
<a class="btn btn-link p-0" [routerLink]="['/admin/user', user._id]">
{{ user.name }}
</a>
</td>
</ng-container>
<asy-text-column name="username" sortable />
<asy-text-column name="organization" sortable />
<asy-text-column name="email" />
<asy-text-column name="phone" />
<asy-ago-date-column name="acceptedEua" header="EUA" sortable />
<asy-ago-date-column name="lastLogin" header="Last Login" sortable />
<asy-date-column name="created" sortable />
<asy-date-column name="updated" sortable />
<asy-expandable-list-column name="externalRoles" header="External Roles" />
<asy-expandable-list-column name="externalGroups" header="External Groups" />
<ng-container cdkColumnDef="roles">
<th cdk-header-cell *cdkHeaderCellDef>
Roles
<asy-header-filter list-filter user-role-filter />
</th>
<td cdk-cell *cdkCellDef="let user">
@for (role of possibleRoles; track role) {
@if (user.roles?.[role.role]) {
<div
class="user-role text-nowrap"
[ngClass]="{
'user-role-external':
user.localRoles && !user.localRoles[role.role]
}"
>
{{ role.label }}
</div>
}
}
</td>
</ng-container>
<asy-expandable-list-column name="teams">
<ng-template lc-item-tmp let-team="listItem">
<a class="btn btn-link p-0" [routerLink]="['/team', team._id]">
{{ team.team.name }}
</a>
</ng-template>
</asy-expandable-list-column>
<asy-actions-menu-column scope="user" stickyEnd>
<ng-template
actions-menu-tmp
let-item="item"
let-menuId="menuId"
let-triggerId="triggerId"
>
<div
class="dropdown-menu"
[attr.aria-labelledby]="triggerId"
cdkMenu
[id]="menuId"
>
<button
class="dropdown-item"
type="button"
cdkMenuItem
[routerLink]="['/admin/user', item._id]"
>
Edit
</button>
@if (allowDeleteUser()) {
<button
class="dropdown-item"
type="button"
cdkMenuItem
(cdkMenuItemTriggered)="confirmDeleteUser(item)"
>
Delete
</button>
}
</div>
</ng-template>
</asy-actions-menu-column>
<tr cdk-header-row *cdkHeaderRowDef="displayedColumns(); sticky: true"></tr>
<tr cdk-row *cdkRowDef="let team; columns: displayedColumns()"></tr>
</table>
<asy-table-empty-state
emptyText="No users are available."
filteredText="No users matched your search."
[dataSource]="dataSource"
(clearFilters)="clearFilters()"
/>
</div>
<asy-sidebar headerText="Columns" #sidebar>
<asy-column-chooser
[columns]="columns"
[storageKey]="dataSource.storageKey"
(columnsChange)="columnsChanged($event)"
/>
</asy-sidebar>
</div>
<div class="table-footer d-flex align-items-center">
<div class="table-footer-pager ms-auto">
<asy-paginator [dataSource]="dataSource" />
</div>
</div>
</section>