116 lines
5.3 KiB
HTML
116 lines
5.3 KiB
HTML
<ng-container *transloco="let t; read: 'manage-users'">
|
|
<div class="position-relative">
|
|
<button class="btn btn-outline-primary position-absolute custom-position" (click)="inviteUser()">
|
|
<i class="fa fa-plus" aria-hidden="true"></i><span class="phone-hidden"> {{t('invite')}}</span>
|
|
</button>
|
|
</div>
|
|
|
|
|
|
|
|
<table class="table table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th scope="col"></th>
|
|
<th scope="col">{{t('name-header')}}</th>
|
|
<th scope="col">{{t('last-active-header')}}</th>
|
|
<th scope="col">{{t('sharing-header')}}</th>
|
|
<th scope="col">{{t('roles-header')}}</th>
|
|
<th scope="col">{{t('actions-header')}}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for(member of members; track member.username + member.lastActiveUtc + member.roles.length; let idx = $index) {
|
|
<tr>
|
|
<td>
|
|
<div class="-flex flex-row justify-content-center align-items-center">
|
|
<app-owner-icon [owner]="member.owner" />
|
|
</div>
|
|
</td>
|
|
<td id="username--{{idx}}">
|
|
<span class="member-name" id="member-name--{{idx}}" [ngClass]="{'highlight': member.username === loggedInUsername}">{{member.username | titlecase}}</span>
|
|
@if (member.isPending) {
|
|
<span class="badge bg-secondary text-dark ms-1 pending-badge" [ngbTooltip]="t('pending-tooltip')">{{t('pending-title')}}</span>
|
|
}
|
|
</td>
|
|
<td>
|
|
<span [ngbTooltip]="member.lastActiveUtc | utcToLocalTime | defaultDate">
|
|
@if ((messageHub.onlineUsers$ | async)?.includes(member.username)) {
|
|
{{t('online-now-tooltip')}}
|
|
} @else {
|
|
{{member.lastActiveUtc | utcToLocaleDate | timeAgo | sentenceCase | defaultDate}}
|
|
}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
@if (member.libraries.length > 0) {
|
|
@if (hasAdminRole(member) || member.libraries.length === libraryCount) {
|
|
{{t('all-libraries')}}
|
|
} @else {
|
|
@if (member.libraries.length > 5) {
|
|
{{t('too-many-libraries')}}
|
|
}
|
|
@else {
|
|
@for(lib of member.libraries; track lib.name) {
|
|
<app-tag-badge class="col-auto">{{lib.name}}</app-tag-badge>
|
|
}
|
|
}
|
|
}
|
|
} @else {
|
|
{{null | defaultValue}}
|
|
}
|
|
</td>
|
|
<td>
|
|
@if (getRoles(member); as roles) {
|
|
<div>
|
|
@if (roles.length === 0) {
|
|
<span>{{null | defaultValue}}</span>
|
|
} @else {
|
|
@if (hasAdminRole(member)) {
|
|
<app-tag-badge class="col-auto">{{Role.Admin | roleLocalized}}</app-tag-badge>
|
|
} @else {
|
|
@for (role of roles; track role) {
|
|
<app-tag-badge class="col-auto">{{role | roleLocalized}}</app-tag-badge>
|
|
}
|
|
}
|
|
}
|
|
</div>
|
|
} @else {
|
|
{{null | defaultValue}}
|
|
}
|
|
</td>
|
|
<td>
|
|
<div class="btn-container">
|
|
@if (canEditMember(member)) {
|
|
<button class="btn btn-danger btn-sm me-2 mb-2" (click)="deleteUser(member)"
|
|
placement="top" [ngbTooltip]="t('delete-user-tooltip')" [attr.aria-label]="t('delete-user-alt', {user: member.username | titlecase})">
|
|
<i class="fa fa-trash" aria-hidden="true"></i>
|
|
</button>
|
|
<button class="btn btn-primary btn-sm me-2 mb-2" (click)="openEditUser(member)"
|
|
placement="top" [ngbTooltip]="t('edit-user-tooltip')" [attr.aria-label]="t('edit-user-alt', {user: member.username | titlecase})">
|
|
<i class="fa fa-pen" aria-hidden="true"></i>
|
|
</button>
|
|
|
|
@if (member.isPending) {
|
|
<button class="btn btn-secondary btn-sm me-2 mb-2" (click)="resendEmail(member)"
|
|
placement="top" [ngbTooltip]="t('resend-invite-tooltip')" [attr.aria-label]="t('resend-invite-alt', {user: member.username | titlecase})"><i class="fa-solid fa-share-from-square" aria-hidden="true"></i></button>
|
|
<button class="btn btn-secondary btn-sm me-2 mb-2" (click)="setup(member)"
|
|
placement="top" [ngbTooltip]="t('setup-user-tooltip')" [attr.aria-label]="t('setup-user-alt', {user: member.username | titlecase})"><i class="fa-solid fa-sliders" aria-hidden="true"></i></button>
|
|
} @else {
|
|
<button class="btn btn-secondary btn-sm me-2 mb-2" (click)="updatePassword(member)"
|
|
placement="top" [ngbTooltip]="t('change-password-tooltip')" [attr.aria-label]="t('change-password-alt', {user: member.username | titlecase})"><i class="fa fa-key" aria-hidden="true"></i></button>
|
|
}
|
|
}
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
}
|
|
@empty {
|
|
@if (loadingMembers) {
|
|
<tr><td colspan="4" style="text-align: center;"><app-loading [loading]="loadingMembers"></app-loading></td></tr>
|
|
} @else {
|
|
<tr><td colspan="4" style="text-align: center;">{{t('no-data')}}</td></tr>
|
|
}
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</ng-container>
|