bitwarden-estensione-browser/apps/web/src/app/vault/add-edit.component.html

852 lines
33 KiB
HTML

<div class="modal fade" role="dialog" aria-modal="true" aria-labelledby="cipherAddEditTitle">
<div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
<form
class="modal-content"
#form
(ngSubmit)="submit()"
[appApiAction]="formPromise"
ngNativeValidate
autocomplete="off"
>
<div class="modal-header">
<h2 class="modal-title" id="cipherAddEditTitle">{{ title }}</h2>
<button
type="button"
class="close"
data-dismiss="modal"
appA11yTitle="{{ 'close' | i18n }}"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body" *ngIf="cipher">
<app-callout type="info" *ngIf="allowOwnershipAssignment() && !allowPersonal">
{{ "personalOwnershipPolicyInEffect" | i18n }}
</app-callout>
<div class="row" *ngIf="!editMode && !viewOnly">
<div class="col-6 form-group">
<label for="type">{{ "whatTypeOfItem" | i18n }}</label>
<select
id="type"
name="Type"
[(ngModel)]="cipher.type"
class="form-control"
[disabled]="cipher.isDeleted"
appAutofocus
>
<option *ngFor="let o of typeOptions" [ngValue]="o.value">{{ o.name }}</option>
</select>
</div>
</div>
<div class="row">
<div class="col-6 form-group">
<label for="name">{{ "name" | i18n }}</label>
<input
id="name"
class="form-control"
type="text"
name="Name"
[(ngModel)]="cipher.name"
required
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
<div class="col-6 form-group" *ngIf="!organization">
<label for="folder">{{ "folder" | i18n }}</label>
<select
id="folder"
name="FolderId"
[(ngModel)]="cipher.folderId"
class="form-control"
[disabled]="cipher.isDeleted || viewOnly"
>
<option *ngFor="let f of folders" [ngValue]="f.id">{{ f.name }}</option>
</select>
</div>
</div>
<!-- Login -->
<ng-container *ngIf="cipher.type === cipherType.Login">
<div class="row">
<div class="col-6 form-group">
<label for="loginUsername">{{ "username" | i18n }}</label>
<div class="input-group">
<input
id="loginUsername"
class="form-control"
type="text"
name="Login.Username"
[(ngModel)]="cipher.login.username"
appInputVerbatim
[disabled]="cipher.isDeleted || viewOnly"
/>
<div class="input-group-append" *ngIf="!cipher.isDeleted">
<button
type="button"
class="btn btn-outline-secondary"
appA11yTitle="{{ 'copyUsername' | i18n }}"
(click)="copy(cipher.login.username, 'username', 'Username')"
>
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
<div class="col-6 form-group">
<div class="d-flex">
<label for="loginPassword">{{ "password" | i18n }}</label>
<div class="ml-auto d-flex" *ngIf="!cipher.isDeleted && !viewOnly">
<a
href="#"
class="d-block mr-2 bwi-icon-above-input"
appStopClick
appA11yTitle="{{ 'generatePassword' | i18n }}"
(click)="generatePassword()"
*ngIf="cipher.viewPassword"
>
<i class="bwi bwi-lg bwi-fw bwi-generate" aria-hidden="true"></i>
</a>
<a
href="#"
class="d-block bwi-icon-above-input"
#checkPasswordBtn
appStopClick
appA11yTitle="{{ 'checkPassword' | i18n }}"
(click)="checkPassword()"
[appApiAction]="checkPasswordPromise"
>
<i
class="bwi bwi-lg bwi-fw bwi-check-circle"
[hidden]="checkPasswordBtn.loading"
aria-hidden="true"
></i>
<i
class="bwi bwi-lg bwi-fw bwi-spinner bwi-spin"
aria-hidden="true"
[hidden]="!checkPasswordBtn.loading"
title="{{ 'loading' | i18n }}"
></i>
</a>
</div>
</div>
<div class="input-group">
<input
id="loginPassword"
class="form-control text-monospace"
type="{{ showPassword ? 'text' : 'password' }}"
name="Login.Password"
[(ngModel)]="cipher.login.password"
appInputVerbatim
autocomplete="new-password"
[disabled]="cipher.isDeleted || !cipher.viewPassword || viewOnly"
/>
<div class="input-group-append">
<button
type="button"
class="btn btn-outline-secondary"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
(click)="togglePassword()"
[disabled]="!cipher.viewPassword"
>
<i
class="bwi bwi-lg"
aria-hidden="true"
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
></i>
</button>
<button
type="button"
class="btn btn-outline-secondary"
appA11yTitle="{{ 'copyPassword' | i18n }}"
(click)="copy(cipher.login.password, 'password', 'Password')"
[disabled]="!cipher.viewPassword"
>
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-6 form-group">
<label for="loginTotp">{{ "authenticatorKeyTotp" | i18n }}</label>
<input
id="loginTotp"
type="{{ cipher.viewPassword ? 'text' : 'password' }}"
name="Login.Totp"
class="form-control text-monospace"
[(ngModel)]="cipher.login.totp"
appInputVerbatim
[disabled]="cipher.isDeleted || !cipher.viewPassword || viewOnly"
/>
</div>
<div class="col-6 form-group totp d-flex align-items-end" [ngClass]="{ low: totpLow }">
<div *ngIf="!cipher.login.totp || !totpCode">
<img
src="../../images/totp-countdown.png"
id="totpImage"
title="{{ 'verificationCodeTotp' | i18n }}"
class="ml-2"
/>
<app-premium-badge
*ngIf="!organization && !cipher.organizationId"
class="ml-3"
></app-premium-badge>
<a
href="#"
appStopClick
class="badge badge-primary ml-3"
(click)="upgradeOrganization()"
*ngIf="
(organization && !organization.useTotp) ||
(!organization &&
!canAccessPremium &&
cipher.organizationId &&
!cipher.organizationUseTotp)
"
>
{{ "upgrade" | i18n }}
</a>
</div>
<div *ngIf="cipher.login.totp && totpCode" class="d-flex align-items-center">
<span class="totp-countdown mr-3 ml-2">
<span class="totp-sec">{{ totpSec }}</span>
<svg>
<g>
<circle
class="totp-circle inner"
r="12.6"
cy="16"
cx="16"
[ngStyle]="{ 'stroke-dashoffset.px': totpDash }"
></circle>
<circle class="totp-circle outer" r="14" cy="16" cx="16"></circle>
</g>
</svg>
</span>
<span class="totp-code mr-2" title="{{ 'verificationCodeTotp' | i18n }}">{{
totpCodeFormatted
}}</span>
<button
type="button"
class="btn btn-link"
appA11yTitle="{{ 'copyVerificationCode' | i18n }}"
(click)="copy(totpCode, 'verificationCodeTotp', 'TOTP')"
>
<i class="bwi bwi-clone" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
<ng-container *ngIf="cipher.login.hasUris">
<div
class="row"
*ngFor="let u of cipher.login.uris; let i = index; trackBy: trackByFunction"
>
<div class="col-7 form-group">
<label for="loginUri{{ i }}">{{ "uriPosition" | i18n: i + 1 }}</label>
<div class="input-group">
<input
class="form-control"
id="loginUri{{ i }}"
type="text"
name="Login.Uris[{{ i }}].Uri"
[(ngModel)]="u.uri"
[disabled]="cipher.isDeleted || viewOnly"
placeholder="{{ 'ex' | i18n }} https://google.com"
appInputVerbatim
/>
<div class="input-group-append">
<button
type="button"
class="btn btn-outline-secondary"
appA11yTitle="{{ 'launch' | i18n }}"
(click)="launch(u)"
[disabled]="!u.canLaunch"
>
<i class="bwi bwi-lg bwi-share-square" aria-hidden="true"></i>
</button>
<button
type="button"
class="btn btn-outline-secondary"
appA11yTitle="{{ 'copyUri' | i18n }}"
(click)="copy(u.uri, 'uri', 'URI')"
>
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
<div class="col-5 form-group">
<div class="d-flex">
<label for="loginUriMatch{{ i }}">
{{ "matchDetection" | i18n }}
</label>
<a
class="ml-auto"
href="https://bitwarden.com/help/uri-match-detection/"
target="_blank"
rel="noopener"
appA11yTitle="{{ 'learnMore' | i18n }}"
>
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
</a>
</div>
<div class="d-flex">
<select
class="form-control overflow-hidden"
id="loginUriMatch{{ i }}"
name="Login.Uris[{{ i }}].Match"
[(ngModel)]="u.match"
(change)="loginUriMatchChanged(u)"
[disabled]="cipher.isDeleted || viewOnly"
>
<option *ngFor="let o of uriMatchOptions" [ngValue]="o.value">
{{ o.name }}
</option>
</select>
<button
type="button"
class="btn btn-link text-danger ml-2"
(click)="removeUri(u)"
appA11yTitle="{{ 'remove' | i18n }}"
*ngIf="!cipher.isDeleted && !viewOnly"
>
<i class="bwi bwi-minus-circle bwi-lg" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
</ng-container>
<a
href="#"
appStopClick
(click)="addUri()"
class="d-inline-block mb-3"
*ngIf="!cipher.isDeleted && !viewOnly"
>
<i class="bwi bwi-plus-circle bwi-fw" aria-hidden="true"></i> {{ "newUri" | i18n }}
</a>
</ng-container>
<!-- Card -->
<ng-container *ngIf="cipher.type === cipherType.Card">
<div class="row">
<div class="col-6 form-group">
<label for="cardCardholderName">{{ "cardholderName" | i18n }}</label>
<input
id="cardCardholderName"
class="form-control"
type="text"
name="Card.CardCardholderName"
[(ngModel)]="cipher.card.cardholderName"
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
<div class="col-6 form-group">
<label for="cardBrand">{{ "brand" | i18n }}</label>
<select
id="cardBrand"
class="form-control"
name="Card.Brand"
[(ngModel)]="cipher.card.brand"
[disabled]="cipher.isDeleted || viewOnly"
>
<option *ngFor="let o of cardBrandOptions" [ngValue]="o.value">{{ o.name }}</option>
</select>
</div>
</div>
<div class="row">
<div class="col-6 form-group">
<label for="cardNumber">{{ "number" | i18n }}</label>
<div class="input-group">
<input
id="cardNumber"
class="form-control text-monospace"
type="{{ showCardNumber ? 'text' : 'password' }}"
name="Card.Number"
[(ngModel)]="cipher.card.number"
appInputVerbatim
autocomplete="new-password"
[disabled]="cipher.isDeleted || viewOnly"
/>
<div class="input-group-append">
<button
type="button"
class="btn btn-outline-secondary"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
(click)="toggleCardNumber()"
>
<i
class="bwi bwi-lg"
aria-hidden="true"
[ngClass]="{
'bwi-eye': !showCardNumber,
'bwi-eye-slash': showCardNumber
}"
></i>
</button>
<button
type="button"
class="btn btn-outline-secondary"
appA11yTitle="{{ 'copyNumber' | i18n }}"
(click)="copy(cipher.card.number, 'number', 'Number')"
>
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
<div class="col form-group">
<label for="cardExpMonth">{{ "expirationMonth" | i18n }}</label>
<select
id="cardExpMonth"
class="form-control"
name="Card.ExpMonth"
[(ngModel)]="cipher.card.expMonth"
[disabled]="cipher.isDeleted || viewOnly"
>
<option *ngFor="let o of cardExpMonthOptions" [ngValue]="o.value">
{{ o.name }}
</option>
</select>
</div>
<div class="col form-group">
<label for="cardExpYear">{{ "expirationYear" | i18n }}</label>
<input
id="cardExpYear"
class="form-control"
type="text"
name="Card.ExpYear"
[(ngModel)]="cipher.card.expYear"
placeholder="{{ 'ex' | i18n }} 2019"
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
</div>
<div class="row">
<div class="col-6 form-group">
<label for="cardCode">{{ "securityCode" | i18n }}</label>
<div class="input-group">
<input
id="cardCode"
class="form-control text-monospace"
type="{{ showCardCode ? 'text' : 'password' }}"
name="Card.Code"
[(ngModel)]="cipher.card.code"
appInputVerbatim
autocomplete="new-password"
[disabled]="cipher.isDeleted || viewOnly"
/>
<div class="input-group-append">
<button
type="button"
class="btn btn-outline-secondary"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
(click)="toggleCardCode()"
>
<i
class="bwi bwi-lg"
aria-hidden="true"
[ngClass]="{ 'bwi-eye': !showCardCode, 'bwi-eye-slash': showCardCode }"
></i>
</button>
<button
type="button"
class="btn btn-outline-secondary"
appA11yTitle="{{ 'securityCode' | i18n }}"
(click)="copy(cipher.card.code, 'securityCode', 'Security Code')"
>
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
</div>
</ng-container>
<!-- Identity -->
<ng-container *ngIf="cipher.type === cipherType.Identity">
<div class="row">
<div class="col-4 form-group">
<label for="idTitle">{{ "title" | i18n }}</label>
<select
id="idTitle"
class="form-control"
name="Identity.Title"
[(ngModel)]="cipher.identity.title"
[disabled]="cipher.isDeleted || viewOnly"
>
<option *ngFor="let o of identityTitleOptions" [ngValue]="o.value">
{{ o.name }}
</option>
</select>
</div>
</div>
<div class="row">
<div class="col-4 form-group">
<label for="idFirstName">{{ "firstName" | i18n }}</label>
<input
id="idFirstName"
class="form-control"
type="text"
name="Identity.FirstName"
[(ngModel)]="cipher.identity.firstName"
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
<div class="col-4 form-group">
<label for="idMiddleName">{{ "middleName" | i18n }}</label>
<input
id="idMiddleName"
class="form-control"
type="text"
name="Identity.MiddleName"
[(ngModel)]="cipher.identity.middleName"
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
<div class="col-4 form-group">
<label for="idLastName">{{ "lastName" | i18n }}</label>
<input
id="idLastName"
class="form-control"
type="text"
name="Identity.LastName"
[(ngModel)]="cipher.identity.lastName"
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
</div>
<div class="row">
<div class="col-4 form-group">
<label for="idUsername">{{ "username" | i18n }}</label>
<input
id="idUsername"
class="form-control"
type="text"
name="Identity.Username"
[(ngModel)]="cipher.identity.username"
appInputVerbatim
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
<div class="col-4 form-group">
<label for="idCompany">{{ "company" | i18n }}</label>
<input
id="idCompany"
class="form-control"
type="text"
name="Identity.Company"
[(ngModel)]="cipher.identity.company"
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
</div>
<div class="row">
<div class="col-4 form-group">
<label for="idSsn">{{ "ssn" | i18n }}</label>
<input
id="idSsn"
class="form-control"
type="text"
name="Identity.SSN"
[(ngModel)]="cipher.identity.ssn"
appInputVerbatim
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
<div class="col-4 form-group">
<label for="idPassportNumber">{{ "passportNumber" | i18n }}</label>
<input
id="idPassportNumber"
class="form-control"
type="text"
name="Identity.PassportNumber"
[(ngModel)]="cipher.identity.passportNumber"
appInputVerbatim
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
<div class="col-4 form-group">
<label for="idLicenseNumber">{{ "licenseNumber" | i18n }}</label>
<input
id="idLicenseNumber"
class="form-control"
type="text"
name="Identity.LicenseNumber"
[(ngModel)]="cipher.identity.licenseNumber"
appInputVerbatim
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
</div>
<div class="row">
<div class="col-6 form-group">
<label for="idEmail">{{ "email" | i18n }}</label>
<input
id="idEmail"
class="form-control"
type="text"
inputmode="email"
name="Identity.Email"
[(ngModel)]="cipher.identity.email"
appInputVerbatim
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
<div class="col-6 form-group">
<label for="idPhone">{{ "phone" | i18n }}</label>
<input
id="idPhone"
class="form-control"
type="text"
inputmode="tel"
name="Identity.Phone"
[(ngModel)]="cipher.identity.phone"
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
</div>
<div class="row">
<div class="col-6 form-group">
<label for="idAddress1">{{ "address1" | i18n }}</label>
<input
id="idAddress1"
class="form-control"
type="text"
name="Identity.Address1"
[(ngModel)]="cipher.identity.address1"
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
<div class="col-6 form-group">
<label for="idAddress2">{{ "address2" | i18n }}</label>
<input
id="idAddress2"
class="form-control"
type="text"
name="Identity.Address2"
[(ngModel)]="cipher.identity.address2"
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
</div>
<div class="row">
<div class="col-6 form-group">
<label for="idAddress3">{{ "address3" | i18n }}</label>
<input
id="idAddress3"
class="form-control"
type="text"
name="Identity.Address3"
[(ngModel)]="cipher.identity.address3"
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
<div class="col-6 form-group">
<label for="idCity">{{ "cityTown" | i18n }}</label>
<input
id="idCity"
class="form-control"
type="text"
name="Identity.City"
[(ngModel)]="cipher.identity.city"
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
</div>
<div class="row">
<div class="col-6 form-group">
<label for="idState">{{ "stateProvince" | i18n }}</label>
<input
id="idState"
class="form-control"
type="text"
name="Identity.State"
[(ngModel)]="cipher.identity.state"
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
<div class="col-6 form-group">
<label for="idPostalCode">{{ "zipPostalCode" | i18n }}</label>
<input
id="idPostalCode"
class="form-control"
type="text"
name="Identity.PostalCode"
[(ngModel)]="cipher.identity.postalCode"
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
</div>
<div class="row">
<div class="col-6 form-group">
<label for="idCountry">{{ "country" | i18n }}</label>
<input
id="idCountry"
class="form-control"
type="text"
name="Identity.Country"
[(ngModel)]="cipher.identity.country"
[disabled]="cipher.isDeleted || viewOnly"
/>
</div>
</div>
</ng-container>
<div class="form-group">
<label for="notes">{{ "notes" | i18n }}</label>
<textarea
id="notes"
name="Notes"
rows="6"
[(ngModel)]="cipher.notes"
[disabled]="cipher.isDeleted || viewOnly"
class="form-control"
></textarea>
</div>
<app-vault-add-edit-custom-fields
[cipher]="cipher"
[thisCipherType]="cipher.type"
[viewOnly]="viewOnly"
[copy]="copy.bind(this)"
></app-vault-add-edit-custom-fields>
<ng-container *ngIf="allowOwnershipAssignment()">
<h3 class="mt-4">{{ "ownership" | i18n }}</h3>
<div class="row">
<div class="col-5">
<label for="organizationId">{{ "whoOwnsThisItem" | i18n }}</label>
<select
id="organizationId"
class="form-control"
name="OrganizationId"
[(ngModel)]="cipher.organizationId"
(change)="organizationChanged()"
[disabled]="cipher.isDeleted || viewOnly"
>
<option *ngFor="let o of ownershipOptions" [ngValue]="o.value">{{ o.name }}</option>
</select>
</div>
</div>
</ng-container>
<ng-container *ngIf="(!editMode || cloneMode) && cipher.organizationId">
<h3 class="mt-4">{{ "collections" | i18n }}</h3>
<div *ngIf="!collections || !collections.length">
{{ "noCollectionsInList" | i18n }}
</div>
<ng-container *ngIf="collections && collections.length">
<div class="form-check" *ngFor="let c of collections; let i = index">
<input
class="form-check-input"
type="checkbox"
[(ngModel)]="c.checked"
id="collection-{{ i }}"
name="Collection[{{ i }}].Checked"
[disabled]="cipher.isDeleted || viewOnly"
/>
<label class="form-check-label" for="collection-{{ i }}">{{ c.name }}</label>
</div>
</ng-container>
</ng-container>
<ng-container *ngIf="editMode">
<div class="small text-muted mt-4">
<div>
<b class="font-weight-semibold">{{ "dateUpdated" | i18n }}:</b>
{{ cipher.revisionDate | date: "medium" }}
</div>
<div *ngIf="showRevisionDate">
<b class="font-weight-semibold">{{ "datePasswordUpdated" | i18n }}:</b>
{{ cipher.passwordRevisionDisplayDate | date: "medium" }}
</div>
<div *ngIf="hasPasswordHistory">
<b class="font-weight-semibold">{{ "passwordHistory" | i18n }}:</b>
<a href="#" appStopClick (click)="viewHistory()" title="{{ 'view' | i18n }}">
{{ cipher.passwordHistory.length }}
</a>
</div>
<div class="ml-3" *ngIf="viewingPasswordHistory">
<div *ngFor="let ph of cipher.passwordHistory">
{{ ph.lastUsedDate | date: "short" }} -
<span class="generated-wrapper text-monospace ml-2">{{ ph.password }}</span>
</div>
</div>
</div>
</ng-container>
<ng-container *ngIf="canUseReprompt">
<h3 class="mt-4">{{ "options" | i18n }}</h3>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
[ngModel]="reprompt"
(change)="repromptChanged()"
id="passwordPrompt"
name="passwordPrompt"
[disabled]="cipher.isDeleted || viewOnly"
/>
<label class="form-check-label" for="passwordPrompt">{{
"passwordPrompt" | i18n
}}</label>
<a
target="_blank"
rel="noopener"
appA11yTitle="{{ 'learnMore' | i18n }}"
href="https://bitwarden.com/help/managing-items/#protect-individual-items"
>
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
</a>
</div>
</ng-container>
</div>
<div class="modal-footer">
<button
type="submit"
class="btn btn-primary btn-submit"
[disabled]="form.loading"
*ngIf="!viewOnly"
>
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
<span>{{ (cipher?.isDeleted ? "restore" : "save") | i18n }}</span>
</button>
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">
{{ (viewOnly ? "close" : "cancel") | i18n }}
</button>
<div class="ml-auto" *ngIf="cipher && !viewOnly">
<button
*ngIf="!organization && !cipher.isDeleted"
type="button"
(click)="toggleFavorite()"
class="btn btn-link"
appA11yTitle="{{ (cipher.favorite ? 'unfavorite' : 'favorite') | i18n }}"
>
<i
class="bwi bwi-lg"
[ngClass]="{ 'bwi-star-f': cipher.favorite, 'bwi-star': !cipher.favorite }"
aria-hidden="true"
></i>
</button>
<button
#deleteBtn
type="button"
(click)="delete()"
class="btn btn-outline-danger"
appA11yTitle="{{ (cipher.isDeleted ? 'permanentlyDelete' : 'delete') | i18n }}"
*ngIf="editMode && !cloneMode"
[disabled]="deleteBtn.loading"
[appApiAction]="deletePromise"
>
<i
class="bwi bwi-trash bwi-lg bwi-fw"
[hidden]="deleteBtn.loading"
aria-hidden="true"
></i>
<i
class="bwi bwi-spinner bwi-spin bwi-lg bwi-fw"
[hidden]="!deleteBtn.loading"
title="{{ 'loading' | i18n }}"
aria-hidden="true"
></i>
</button>
</div>
</div>
</form>
</div>
</div>