1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-26 05:03:33 +00:00
Files
browser/apps/web/src/app/auth/settings/emergency-access/emergency-access.component.html
Conner Turnbull b99153a016 [AC-2156] Billing State Provider Migration (#8133)
* Added billing account profile state service

* Update usages after removing state service functions

* Added migrator

* Updated bw.ts and main.background.ts

* Removed comment

* Updated state service dependencies to include billing service

* Added missing mv3 factory and updated MainContextMenuHandler

* updated autofill service and tests

* Updated the remaining extensions usages

* Updated desktop

* Removed subjects where they weren't needed

* Refactored billing service to have a single setter to avoid unecessary emissions

* Refactored has premium guard to return an observable

* Renamed services to match ADR

f633f2cdd8/docs/architecture/clients/presentation/angular.md (abstract--default-implementations)

* Updated property names to be a smidgen more descriptive and added jsdocs

* Updated setting of canAccessPremium to automatically update when the underlying observable emits

* Fixed build error after merge conflicts

* Another build error from conflict

* Removed autofill unit test changes from conflict

* Updated login strategy to not set premium field using state service

* Updated CLI to use billing state provider

* Shortened names a bit

* Fixed build
2024-03-15 14:53:05 -05:00

279 lines
10 KiB
HTML

<app-header></app-header>
<bit-container>
<bit-section>
<p bitTypography="body1">
<span class="tw-text-main">{{ "emergencyAccessDesc" | i18n }}</span>
<a
bitLink
href="https://bitwarden.com/help/emergency-access/"
target="_blank"
rel="noreferrer"
>
{{ "learnMore" | i18n }}.
</a>
</p>
<bit-callout *ngIf="isOrganizationOwner" type="warning" title="{{ 'warning' | i18n }}">{{
"emergencyAccessOwnerWarning" | i18n
}}</bit-callout>
</bit-section>
<bit-section>
<div class="tw-flex tw-items-center tw-gap-2 tw-mb-2">
<h2 bitTypography="h2" noMargin class="tw-mb-0">
{{ "trustedEmergencyContacts" | i18n }}
</h2>
<app-premium-badge></app-premium-badge>
<div class="tw-ml-auto tw-flex">
<button
type="button"
bitButton
buttonType="primary"
[bitAction]="invite"
[disabled]="!(canAccessPremium$ | async)"
>
<i aria-hidden="true" class="bwi bwi-plus bwi-fw"></i>
{{ "addEmergencyContact" | i18n }}
</button>
</div>
</div>
<bit-table *ngIf="trustedContacts && trustedContacts.length">
<ng-container header>
<tr>
<th bitCell>{{ "name" | i18n }}</th>
<th bitCell>{{ "accessLevel" | i18n }}</th>
<th bitCell class="tw-text-right">{{ "options" | i18n }}</th>
</tr>
</ng-container>
<ng-template body>
<tr bitRow *ngFor="let c of trustedContacts; let i = index">
<td bitCell class="tw-flex tw-items-center tw-gap-4">
<bit-avatar
[text]="c | userName"
[id]="c.granteeId"
[color]="c.avatarColor"
size="small"
></bit-avatar>
<span>
<a bitLink href="#" appStopClick (click)="edit(c)">{{ c.email }}</a>
<span
bitBadge
variant="secondary"
*ngIf="c.status === emergencyAccessStatusType.Invited"
>{{ "invited" | i18n }}</span
>
<span
bitBadge
variant="warning"
*ngIf="c.status === emergencyAccessStatusType.Accepted"
>{{ "accepted" | i18n }}</span
>
<span
bitBadge
variant="warning"
*ngIf="c.status === emergencyAccessStatusType.RecoveryInitiated"
>{{ "emergencyAccessRecoveryInitiated" | i18n }}</span
>
<span bitBadge *ngIf="c.status === emergencyAccessStatusType.RecoveryApproved">{{
"emergencyAccessRecoveryApproved" | i18n
}}</span>
<small class="tw-text-muted tw-block" *ngIf="c.name">{{ c.name }}</small>
</span>
</td>
<td bitCell>
<span bitBadge *ngIf="c.type === emergencyAccessType.View">{{ "view" | i18n }}</span>
<span bitBadge *ngIf="c.type === emergencyAccessType.Takeover">{{
"takeover" | i18n
}}</span>
</td>
<td bitCell class="tw-text-right">
<button
[bitMenuTriggerFor]="trustedContactOptions"
type="button"
appA11yTitle="{{ 'options' | i18n }}"
bitIconButton="bwi-ellipsis-v"
buttonType="main"
></button>
<bit-menu #trustedContactOptions>
<button
type="button"
bitMenuItem
*ngIf="c.status === emergencyAccessStatusType.Invited"
(click)="reinvite(c)"
>
<i class="bwi bwi-fw bwi-envelope" aria-hidden="true"></i>
{{ "resendInvitation" | i18n }}
</button>
<button
type="button"
bitMenuItem
*ngIf="c.status === emergencyAccessStatusType.Accepted"
(click)="confirm(c)"
>
<i class="bwi bwi-fw bwi-check" aria-hidden="true"></i>
{{ "confirm" | i18n }}
</button>
<button
type="button"
bitMenuItem
*ngIf="c.status === emergencyAccessStatusType.RecoveryInitiated"
(click)="approve(c)"
>
<i class="bwi bwi-fw bwi-check" aria-hidden="true"></i>
{{ "approve" | i18n }}
</button>
<button
type="button"
bitMenuItem
*ngIf="
c.status === emergencyAccessStatusType.RecoveryInitiated ||
c.status === emergencyAccessStatusType.RecoveryApproved
"
(click)="reject(c)"
>
<i class="bwi bwi-fw bwi-close" aria-hidden="true"></i>
{{ "reject" | i18n }}
</button>
<button type="button" bitMenuItem (click)="remove(c)">
<i class="bwi bwi-fw bwi-close" aria-hidden="true"></i>
{{ "remove" | i18n }}
</button>
</bit-menu>
</td>
</tr>
</ng-template>
</bit-table>
<ng-container *ngIf="!trustedContacts || !trustedContacts.length">
<p bitTypography="body1" class="tw-mt-2" *ngIf="loaded">{{ "noTrustedContacts" | i18n }}</p>
<ng-container *ngIf="!loaded">
<i
class="bwi bwi-spinner bwi-spin text-muted"
title="{{ 'loading' | i18n }}"
aria-hidden="true"
></i>
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
</ng-container>
</ng-container>
</bit-section>
<bit-section>
<h2 bitTypography="h2">{{ "designatedEmergencyContacts" | i18n }}</h2>
<bit-table *ngIf="grantedContacts && grantedContacts.length">
<ng-container header>
<tr>
<th bitCell>{{ "name" | i18n }}</th>
<th bitCell>{{ "accessLevel" | i18n }}</th>
<th bitCell class="tw-text-right">{{ "options" | i18n }}</th>
</tr>
</ng-container>
<ng-template body>
<tr bitRow *ngFor="let c of grantedContacts; let i = index">
<td bitCell class="tw-flex tw-items-center tw-gap-4">
<bit-avatar
[text]="c | userName"
[id]="c.grantorId"
[color]="c.avatarColor"
size="small"
></bit-avatar>
<span>
<span>{{ c.email }}</span>
<span bitBadge *ngIf="c.status === emergencyAccessStatusType.Invited">{{
"invited" | i18n
}}</span>
<span
bitBadge
variant="warning"
*ngIf="c.status === emergencyAccessStatusType.Accepted"
>{{ "accepted" | i18n }}</span
>
<span
bitBadge
variant="warning"
*ngIf="c.status === emergencyAccessStatusType.RecoveryInitiated"
>{{ "emergencyAccessRecoveryInitiated" | i18n }}</span
>
<span
bitBadge
variant="success"
*ngIf="c.status === emergencyAccessStatusType.RecoveryApproved"
>{{ "emergencyAccessRecoveryApproved" | i18n }}</span
>
<small class="tw-text-muted tw-block" *ngIf="c.name">{{ c.name }}</small>
</span>
</td>
<td bitCell>
<span bitBadge *ngIf="c.type === emergencyAccessType.View">{{ "view" | i18n }}</span>
<span bitBadge *ngIf="c.type === emergencyAccessType.Takeover">{{
"takeover" | i18n
}}</span>
</td>
<td bitCell class="tw-text-right">
<button
[bitMenuTriggerFor]="grantedContactOptions"
type="button"
appA11yTitle="{{ 'options' | i18n }}"
bitIconButton="bwi-ellipsis-v"
buttonType="main"
></button>
<bit-menu #grantedContactOptions>
<button
type="button"
bitMenuItem
*ngIf="c.status === emergencyAccessStatusType.Confirmed"
(click)="requestAccess(c)"
>
<i class="bwi bwi-fw bwi-envelope" aria-hidden="true"></i>
{{ "requestAccess" | i18n }}
</button>
<button
type="button"
bitMenuItem
*ngIf="
c.status === emergencyAccessStatusType.RecoveryApproved &&
c.type === emergencyAccessType.Takeover
"
(click)="takeover(c)"
>
<i class="bwi bwi-fw bwi-key" aria-hidden="true"></i>
{{ "takeover" | i18n }}
</button>
<button
type="button"
bitMenuItem
*ngIf="
c.status === emergencyAccessStatusType.RecoveryApproved &&
c.type === emergencyAccessType.View
"
[routerLink]="c.id"
>
<i class="bwi bwi-fw bwi-eye" aria-hidden="true"></i>
{{ "view" | i18n }}
</button>
<button type="button" bitMenuItem (click)="remove(c)">
<i class="bwi bwi-fw bwi-close" aria-hidden="true"></i>
{{ "remove" | i18n }}
</button>
</bit-menu>
</td>
</tr>
</ng-template>
</bit-table>
<ng-container *ngIf="!grantedContacts || !grantedContacts.length">
<p bitTypography="body1" *ngIf="loaded">{{ "noGrantedAccess" | i18n }}</p>
<ng-container *ngIf="!loaded">
<i
class="bwi bwi-spinner bwi-spin text-muted"
title="{{ 'loading' | i18n }}"
aria-hidden="true"
></i>
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
</ng-container>
</ng-container>
</bit-section>
</bit-container>
<ng-template #addEdit></ng-template>
<ng-template #takeoverTemplate></ng-template>
<ng-template #confirmTemplate></ng-template>