mirror of
https://github.com/bitwarden/browser
synced 2026-02-23 16:13:21 +00:00
* [CL-571] Update icons to new fileset and metaphors (#14163) * [CL-518] Convert icons docs to stories (#14299) * [CL-574] Update inline autofill icons (#14379) --------- Co-authored-by: William Martin <contact@willmartian.com>
378 lines
14 KiB
HTML
378 lines
14 KiB
HTML
<app-header>
|
|
<bit-search
|
|
class="tw-grow"
|
|
[formControl]="searchControl"
|
|
[placeholder]="'searchMembers' | i18n"
|
|
></bit-search>
|
|
|
|
<button type="button" bitButton buttonType="primary" (click)="invite()" [disabled]="!firstLoaded">
|
|
<i class="bwi bwi-plus bwi-fw" aria-hidden="true"></i>
|
|
{{ "inviteMember" | i18n }}
|
|
</button>
|
|
</app-header>
|
|
|
|
<div class="tw-mb-4 tw-flex tw-flex-col tw-space-y-4">
|
|
<bit-toggle-group
|
|
[selected]="status"
|
|
(selectedChange)="statusToggle.next($event)"
|
|
[attr.aria-label]="'memberStatusFilter' | i18n"
|
|
>
|
|
<bit-toggle [value]="null">
|
|
{{ "all" | i18n }}
|
|
<span bitBadge variant="info" *ngIf="dataSource.activeUserCount as allCount">{{
|
|
allCount
|
|
}}</span>
|
|
</bit-toggle>
|
|
|
|
<bit-toggle [value]="userStatusType.Invited">
|
|
{{ "invited" | i18n }}
|
|
<span bitBadge variant="info" *ngIf="dataSource.invitedUserCount as invitedCount">{{
|
|
invitedCount
|
|
}}</span>
|
|
</bit-toggle>
|
|
|
|
<bit-toggle [value]="userStatusType.Accepted">
|
|
{{ "needsConfirmation" | i18n }}
|
|
<span bitBadge variant="info" *ngIf="dataSource.acceptedUserCount as acceptedUserCount">{{
|
|
acceptedUserCount
|
|
}}</span>
|
|
</bit-toggle>
|
|
|
|
<bit-toggle [value]="userStatusType.Revoked">
|
|
{{ "revoked" | i18n }}
|
|
<span bitBadge variant="info" *ngIf="dataSource.revokedUserCount as revokedCount">{{
|
|
revokedCount
|
|
}}</span>
|
|
</bit-toggle>
|
|
</bit-toggle-group>
|
|
</div>
|
|
<ng-container *ngIf="!firstLoaded">
|
|
<i
|
|
class="bwi bwi-spinner bwi-spin tw-text-muted"
|
|
title="{{ 'loading' | i18n }}"
|
|
aria-hidden="true"
|
|
></i>
|
|
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
|
|
</ng-container>
|
|
<ng-container *ngIf="firstLoaded">
|
|
<p *ngIf="!dataSource.filteredData.length">{{ "noMembersInList" | i18n }}</p>
|
|
<ng-container *ngIf="dataSource.filteredData.length">
|
|
<bit-callout
|
|
type="info"
|
|
title="{{ 'confirmUsers' | i18n }}"
|
|
icon="bwi-check-circle"
|
|
*ngIf="showConfirmUsers"
|
|
>
|
|
{{ "usersNeedConfirmed" | i18n }}
|
|
</bit-callout>
|
|
<!-- The padding on the bottom of the cdk-virtual-scroll-viewport element is required to prevent table row content
|
|
from overflowing the <main> element. -->
|
|
<cdk-virtual-scroll-viewport scrollWindow [itemSize]="rowHeight" class="tw-pb-8">
|
|
<bit-table [dataSource]="dataSource">
|
|
<ng-container header>
|
|
<tr>
|
|
<th bitCell class="tw-w-20">
|
|
<input
|
|
type="checkbox"
|
|
bitCheckbox
|
|
class="tw-mr-1"
|
|
(change)="dataSource.checkAllFilteredUsers($any($event.target).checked)"
|
|
id="selectAll"
|
|
/>
|
|
<label class="tw-mb-0 !tw-font-bold !tw-text-muted" for="selectAll">{{
|
|
"all" | i18n
|
|
}}</label>
|
|
</th>
|
|
<th bitCell bitSortable="email" default>{{ "name" | i18n }}</th>
|
|
<th bitCell>{{ (organization.useGroups ? "groups" : "collections") | i18n }}</th>
|
|
<th bitCell bitSortable="type">{{ "role" | i18n }}</th>
|
|
<th bitCell>{{ "policies" | i18n }}</th>
|
|
<th bitCell class="tw-w-10">
|
|
<button
|
|
[bitMenuTriggerFor]="headerMenu"
|
|
type="button"
|
|
bitIconButton="bwi-ellipsis-v"
|
|
size="small"
|
|
appA11yTitle="{{ 'options' | i18n }}"
|
|
></button>
|
|
|
|
<bit-menu #headerMenu>
|
|
<ng-container *ngIf="canUseSecretsManager$ | async">
|
|
<button type="button" bitMenuItem (click)="bulkEnableSM()">
|
|
{{ "activateSecretsManager" | i18n }}
|
|
</button>
|
|
<bit-menu-divider></bit-menu-divider>
|
|
</ng-container>
|
|
<button
|
|
type="button"
|
|
bitMenuItem
|
|
(click)="bulkReinvite()"
|
|
*ngIf="showBulkReinviteUsers"
|
|
>
|
|
<i class="bwi bwi-fw bwi-envelope" aria-hidden="true"></i>
|
|
{{ "reinviteSelected" | i18n }}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
bitMenuItem
|
|
(click)="bulkConfirm()"
|
|
*ngIf="showBulkConfirmUsers"
|
|
>
|
|
<span class="tw-text-success">
|
|
<i class="bwi bwi-fw bwi-check" aria-hidden="true"></i>
|
|
{{ "confirmSelected" | i18n }}
|
|
</span>
|
|
</button>
|
|
<button
|
|
type="button"
|
|
bitMenuItem
|
|
(click)="bulkRestore()"
|
|
*ngIf="showBulkRestoreUsers"
|
|
>
|
|
<i class="bwi bwi-fw bwi-plus-circle" aria-hidden="true"></i>
|
|
{{ "restoreAccess" | i18n }}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
bitMenuItem
|
|
(click)="bulkRevoke()"
|
|
*ngIf="showBulkRevokeUsers"
|
|
>
|
|
<i class="bwi bwi-fw bwi-minus-circle" aria-hidden="true"></i>
|
|
{{ "revokeAccess" | i18n }}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
bitMenuItem
|
|
(click)="bulkRemove()"
|
|
*ngIf="showBulkRemoveUsers"
|
|
>
|
|
<span class="tw-text-danger">
|
|
<i aria-hidden="true" class="bwi bwi-fw bwi-close"></i>
|
|
{{ "remove" | i18n }}
|
|
</span>
|
|
</button>
|
|
<button
|
|
type="button"
|
|
bitMenuItem
|
|
(click)="bulkDelete()"
|
|
*ngIf="showBulkDeleteUsers"
|
|
>
|
|
<span class="tw-text-danger">
|
|
<i aria-hidden="true" class="bwi bwi-fw bwi-trash"></i>
|
|
{{ "delete" | i18n }}
|
|
</span>
|
|
</button>
|
|
</bit-menu>
|
|
</th>
|
|
</tr>
|
|
</ng-container>
|
|
<ng-template body let-rows$>
|
|
<tr
|
|
bitRow
|
|
*cdkVirtualFor="let u of rows$"
|
|
alignContent="middle"
|
|
[ngClass]="rowHeightClass"
|
|
>
|
|
<td bitCell (click)="dataSource.checkUser(u)">
|
|
<input type="checkbox" bitCheckbox [(ngModel)]="$any(u).checked" />
|
|
</td>
|
|
<td bitCell (click)="edit(u)" class="tw-cursor-pointer">
|
|
<div class="tw-flex tw-items-center">
|
|
<bit-avatar
|
|
size="small"
|
|
[text]="u | userName"
|
|
[id]="u.userId"
|
|
[color]="u.avatarColor"
|
|
class="tw-mr-3"
|
|
></bit-avatar>
|
|
<div class="tw-flex tw-flex-col">
|
|
<div class="tw-flex tw-flex-row tw-gap-2">
|
|
<button type="button" bitLink>
|
|
{{ u.name ?? u.email }}
|
|
</button>
|
|
<span
|
|
bitBadge
|
|
class="tw-text-xs"
|
|
variant="secondary"
|
|
*ngIf="u.status === userStatusType.Invited"
|
|
>
|
|
{{ "invited" | i18n }}
|
|
</span>
|
|
<span
|
|
bitBadge
|
|
class="tw-text-xs"
|
|
variant="warning"
|
|
*ngIf="u.status === userStatusType.Accepted"
|
|
>
|
|
{{ "needsConfirmation" | i18n }}
|
|
</span>
|
|
<span
|
|
bitBadge
|
|
class="tw-text-xs"
|
|
variant="secondary"
|
|
*ngIf="u.status === userStatusType.Revoked"
|
|
>
|
|
{{ "revoked" | i18n }}
|
|
</span>
|
|
</div>
|
|
<div class="tw-text-sm tw-text-muted" *ngIf="u.name">
|
|
{{ u.email }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
|
|
<td
|
|
bitCell
|
|
(click)="edit(u, organization.useGroups ? memberTab.Groups : memberTab.Collections)"
|
|
class="tw-cursor-pointer"
|
|
>
|
|
<bit-badge-list
|
|
[items]="organization.useGroups ? u.groupNames : u.collectionNames"
|
|
[maxItems]="3"
|
|
variant="secondary"
|
|
></bit-badge-list>
|
|
</td>
|
|
|
|
<td
|
|
bitCell
|
|
(click)="edit(u, memberTab.Role)"
|
|
class="tw-cursor-pointer tw-text-sm tw-text-muted"
|
|
>
|
|
{{ u.type | userType }}
|
|
</td>
|
|
|
|
<td bitCell class="tw-text-muted">
|
|
<ng-container *ngIf="u.twoFactorEnabled">
|
|
<i
|
|
class="bwi bwi-lock"
|
|
title="{{ 'userUsingTwoStep' | i18n }}"
|
|
aria-hidden="true"
|
|
></i>
|
|
<span class="tw-sr-only">{{ "userUsingTwoStep" | i18n }}</span>
|
|
</ng-container>
|
|
<ng-container *ngIf="showEnrolledStatus($any(u))">
|
|
<i
|
|
class="bwi bwi-key"
|
|
title="{{ 'enrolledAccountRecovery' | i18n }}"
|
|
aria-hidden="true"
|
|
></i>
|
|
<span class="tw-sr-only">{{ "enrolledAccountRecovery" | i18n }}</span>
|
|
</ng-container>
|
|
</td>
|
|
<td bitCell>
|
|
<button
|
|
[bitMenuTriggerFor]="rowMenu"
|
|
type="button"
|
|
bitIconButton="bwi-ellipsis-v"
|
|
size="small"
|
|
appA11yTitle="{{ 'options' | i18n }}"
|
|
></button>
|
|
|
|
<bit-menu #rowMenu>
|
|
<button
|
|
type="button"
|
|
bitMenuItem
|
|
(click)="reinvite(u)"
|
|
*ngIf="u.status === userStatusType.Invited"
|
|
>
|
|
<i aria-hidden="true" class="bwi bwi-envelope"></i>
|
|
{{ "resendInvitation" | i18n }}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
bitMenuItem
|
|
(click)="confirm(u)"
|
|
*ngIf="u.status === userStatusType.Accepted"
|
|
>
|
|
<span class="tw-text-success">
|
|
<i aria-hidden="true" class="bwi bwi-check"></i> {{ "confirm" | i18n }}
|
|
</span>
|
|
</button>
|
|
<bit-menu-divider
|
|
*ngIf="
|
|
u.status === userStatusType.Accepted || u.status === userStatusType.Invited
|
|
"
|
|
></bit-menu-divider>
|
|
<button type="button" bitMenuItem (click)="edit(u, memberTab.Role)">
|
|
<i aria-hidden="true" class="bwi bwi-user"></i> {{ "memberRole" | i18n }}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
bitMenuItem
|
|
(click)="edit(u, memberTab.Groups)"
|
|
*ngIf="organization.useGroups"
|
|
>
|
|
<i aria-hidden="true" class="bwi bwi-users"></i> {{ "groups" | i18n }}
|
|
</button>
|
|
<button type="button" bitMenuItem (click)="edit(u, memberTab.Collections)">
|
|
<i aria-hidden="true" class="bwi bwi-collection-shared"></i>
|
|
{{ "collections" | i18n }}
|
|
</button>
|
|
<bit-menu-divider></bit-menu-divider>
|
|
<button
|
|
type="button"
|
|
bitMenuItem
|
|
(click)="openEventsDialog(u)"
|
|
*ngIf="organization.useEvents && u.status === userStatusType.Confirmed"
|
|
>
|
|
<i aria-hidden="true" class="bwi bwi-file-text"></i> {{ "eventLogs" | i18n }}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
bitMenuItem
|
|
(click)="resetPassword(u)"
|
|
*ngIf="allowResetPassword(u)"
|
|
>
|
|
<i aria-hidden="true" class="bwi bwi-key"></i> {{ "recoverAccount" | i18n }}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
bitMenuItem
|
|
(click)="restore(u)"
|
|
*ngIf="u.status === userStatusType.Revoked"
|
|
>
|
|
<i aria-hidden="true" class="bwi bwi-plus-circle"></i>
|
|
{{ "restoreAccess" | i18n }}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
bitMenuItem
|
|
(click)="revoke(u)"
|
|
*ngIf="u.status !== userStatusType.Revoked"
|
|
>
|
|
<i aria-hidden="true" class="bwi bwi-minus-circle"></i>
|
|
{{ "revokeAccess" | i18n }}
|
|
</button>
|
|
<button
|
|
*ngIf="!u.managedByOrganization"
|
|
type="button"
|
|
bitMenuItem
|
|
(click)="remove(u)"
|
|
>
|
|
<span class="tw-text-danger">
|
|
<i aria-hidden="true" class="bwi bwi-close"></i> {{ "remove" | i18n }}
|
|
</span>
|
|
</button>
|
|
<button
|
|
*ngIf="u.managedByOrganization"
|
|
type="button"
|
|
bitMenuItem
|
|
(click)="deleteUser(u)"
|
|
>
|
|
<span class="tw-text-danger">
|
|
<i class="bwi bwi-trash" aria-hidden="true"></i>
|
|
{{ "delete" | i18n }}
|
|
</span>
|
|
</button>
|
|
</bit-menu>
|
|
</td>
|
|
</tr>
|
|
</ng-template>
|
|
</bit-table>
|
|
</cdk-virtual-scroll-viewport>
|
|
</ng-container>
|
|
</ng-container>
|
|
<ng-template #resetPasswordTemplate></ng-template>
|