bitwarden-desktop/src/app/vault/generator.component.html

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

482 lines
19 KiB
HTML
Raw Normal View History

<div
class="modal fade"
role="dialog"
aria-modal="true"
attr.aria-label="{{ 'generatePassword' | i18n }}"
>
<div class="modal-dialog modal-md" role="document">
2018-01-29 15:33:43 +01:00
<div class="modal-content">
<div class="modal-body">
<div class="modal-title">
{{ "generator" | i18n }}
</div>
<app-callout
type="info"
*ngIf="enforcedPasswordPolicyOptions?.inEffect() && type === 'password'"
>
2019-04-02 05:08:54 +02:00
{{ "passwordGeneratorPolicyInEffect" | i18n }}
2018-01-29 22:13:37 +01:00
</app-callout>
<div class="generated-block" *ngIf="type === 'password'">
<div class="generated-wrapper" [innerHTML]="password | colorPassword" appSelectCopy></div>
<div class="action-buttons">
<button
type="button"
class="icon-btn primary"
appStopClick
appA11yTitle="{{ 'copyPassword' | i18n }}"
(click)="copy()"
>
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
</button>
<button
type="button"
class="icon-btn primary"
appStopClick
appA11yTitle="{{ 'regeneratePassword' | i18n }}"
(click)="regenerate()"
>
<i class="bwi bwi-lg bwi-generate" aria-hidden="true"></i>
</button>
</div>
</div>
<div class="generated-block" *ngIf="type === 'username'">
<div class="generated-wrapper" [innerHTML]="username | colorPassword" appSelectCopy></div>
<div class="action-buttons">
<button
type="button"
class="icon-btn primary"
appStopClick
appA11yTitle="{{ 'copyUsername' | i18n }}"
(click)="copy()"
>
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
</button>
<button
type="button"
class="icon-btn primary"
appStopClick
appA11yTitle="{{ 'regenerateUsername' | i18n }}"
(click)="regenerate()"
>
<i class="bwi bwi-lg bwi-generate" aria-hidden="true"></i>
</button>
</div>
</div>
<div class="box">
<div class="box-content condensed">
2018-10-09 15:13:22 +02:00
<div class="box-content-row box-content-row-radio">
<label class="radio-header">{{ "whatWouldYouLikeToGenerate" | i18n }}</label>
2021-12-20 15:47:17 +01:00
<div
class="radio-group text-default"
2018-01-30 20:33:06 +01:00
appBoxRow
name="TypeOptions"
*ngFor="let o of typeOptions"
2021-12-20 15:47:17 +01:00
>
2018-10-09 15:13:22 +02:00
<input
type="radio"
class="radio"
[(ngModel)]="type"
2018-10-09 15:13:22 +02:00
name="Type_{{ o.value }}"
id="type_{{ o.value }}"
[value]="o.value"
(change)="typeChanged()"
[checked]="type === o.value"
2022-04-20 17:46:12 +02:00
[disabled]="comingFromAddEdit && type !== o.value"
2018-10-09 15:13:22 +02:00
/>
<label class="unstyled" for="type_{{ o.value }}">
2021-12-20 15:47:17 +01:00
{{ o.name }}
2018-10-09 15:13:22 +02:00
</label>
</div>
2018-10-09 15:13:22 +02:00
</div>
</div>
</div>
<ng-container *ngIf="type === 'password'">
<div class="box">
<div class="box-header">
<button
type="button"
(click)="toggleOptions()"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-expanded]="showOptions"
>
<i class="bwi bwi-plus-square" aria-hidden="true" [hidden]="showOptions"></i>
<i class="bwi bwi-minus-square" aria-hidden="true" [hidden]="!showOptions"></i>
{{ "options" | i18n }}
</button>
2021-12-20 15:47:17 +01:00
</div>
<div class="box-content condensed" [hidden]="!showOptions">
<div class="box-content-row box-content-row-radio">
<label class="radio-header">{{ "passwordType" | i18n }}</label>
<div
class="radio-group text-default"
appBoxRow
name="PassTypeOptions"
*ngFor="let o of passTypeOptions"
>
<input
type="radio"
class="radio"
[(ngModel)]="passwordOptions.type"
name="PasswordType_{{ o.value }}"
id="passwordType_{{ o.value }}"
[value]="o.value"
(change)="savePasswordOptions()"
[checked]="passwordOptions.type === o.value"
/>
<label class="unstyled" for="passwordType_{{ o.value }}">
{{ o.name }}
</label>
</div>
</div>
2021-12-20 15:47:17 +01:00
</div>
</div>
<div class="box" [hidden]="!showOptions" *ngIf="passwordOptions.type === 'passphrase'">
2018-10-09 15:13:22 +02:00
<div class="box-content condensed">
<div class="box-content-row box-content-row-input" appBoxRow>
<label for="num-words">{{ "numWords" | i18n }}</label>
2021-12-20 15:47:17 +01:00
<input
id="num-words"
type="number"
min="3"
max="20"
(blur)="savePasswordOptions()"
[(ngModel)]="passwordOptions.numWords"
2021-12-20 15:47:17 +01:00
/>
</div>
<div class="box-content-row box-content-row-input" appBoxRow>
<label for="word-separator">{{ "wordSeparator" | i18n }}</label>
2021-12-20 15:47:17 +01:00
<input
id="word-separator"
type="text"
maxlength="1"
(input)="savePasswordOptions()"
[(ngModel)]="passwordOptions.wordSeparator"
2021-12-20 15:47:17 +01:00
/>
</div>
2018-10-09 15:13:22 +02:00
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="capitalize">{{ "capitalize" | i18n }}</label>
2021-12-20 15:47:17 +01:00
<input
id="capitalize"
2018-10-09 15:13:22 +02:00
type="checkbox"
(change)="savePasswordOptions()"
[(ngModel)]="passwordOptions.capitalize"
[disabled]="enforcedPasswordPolicyOptions?.capitalize"
2021-12-20 15:47:17 +01:00
/>
</div>
2018-10-09 15:13:22 +02:00
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="include-number">{{ "includeNumber" | i18n }}</label>
2021-12-20 15:47:17 +01:00
<input
id="include-number"
2018-10-09 15:13:22 +02:00
type="checkbox"
(change)="savePasswordOptions()"
[(ngModel)]="passwordOptions.includeNumber"
[disabled]="enforcedPasswordPolicyOptions?.includeNumber"
2021-12-20 15:47:17 +01:00
/>
</div>
</div>
</div>
<ng-container *ngIf="passwordOptions.type === 'password'">
<div class="box" [hidden]="!showOptions">
<div class="box-content condensed">
<div class="box-content-row box-content-row-slider" appBoxRow>
<label for="length">{{ "length" | i18n }}</label>
<input
id="length"
type="number"
min="5"
max="128"
[(ngModel)]="passwordOptions.length"
(blur)="savePasswordOptions()"
/>
<input
id="lengthRange"
type="range"
min="5"
max="128"
step="1"
[(ngModel)]="passwordOptions.length"
(change)="sliderChanged()"
(input)="sliderInput()"
attr.aria-label="{{ 'length' | i18n }}"
tabindex="-1"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="uppercase">A-Z</label>
<input
id="uppercase"
type="checkbox"
(change)="savePasswordOptions()"
[disabled]="enforcedPasswordPolicyOptions?.useUppercase"
[(ngModel)]="passwordOptions.uppercase"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="lowercase">a-z</label>
<input
id="lowercase"
type="checkbox"
(change)="savePasswordOptions()"
[disabled]="enforcedPasswordPolicyOptions?.useLowercase"
[(ngModel)]="passwordOptions.lowercase"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="numbers">0-9</label>
<input
id="numbers"
type="checkbox"
(change)="savePasswordOptions()"
[disabled]="enforcedPasswordPolicyOptions?.useNumbers"
[(ngModel)]="passwordOptions.number"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="special">!@#$%^&*</label>
<input
id="special"
type="checkbox"
(change)="savePasswordOptions()"
[disabled]="enforcedPasswordPolicyOptions?.useSpecial"
[(ngModel)]="passwordOptions.special"
/>
</div>
</div>
</div>
<div class="box" [hidden]="!showOptions">
<div class="box-content condensed">
<div class="box-content-row box-content-row-input" appBoxRow>
<label for="min-number">{{ "minNumbers" | i18n }}</label>
<input
id="min-number"
type="number"
min="0"
max="9"
(blur)="savePasswordOptions()"
[(ngModel)]="passwordOptions.minNumber"
/>
</div>
<div class="box-content-row box-content-row-input" appBoxRow>
<label for="min-special">{{ "minSpecial" | i18n }}</label>
<input
id="min-special"
type="number"
min="0"
max="9"
(blur)="savePasswordOptions()"
[(ngModel)]="passwordOptions.minSpecial"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="ambiguous">{{ "ambiguous" | i18n }}</label>
<input
id="ambiguous"
type="checkbox"
(change)="savePasswordOptions()"
[(ngModel)]="avoidAmbiguous"
/>
</div>
</div>
</div>
</ng-container>
</ng-container>
<ng-container *ngIf="type === 'username'">
<div class="box">
<div class="box-header">
<button
type="button"
(click)="toggleOptions()"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-expanded]="showOptions"
>
<i class="bwi bwi-plus-square" aria-hidden="true" [hidden]="showOptions"></i>
<i class="bwi bwi-minus-square" aria-hidden="true" [hidden]="!showOptions"></i>
{{ "options" | i18n }}
</button>
</div>
<div class="box-content condensed" [hidden]="!showOptions">
<div class="box-content-row box-content-row-radio">
<label class="radio-header">
{{ "usernameType" | i18n }}
<a
href="#"
appStopClick
appBlurClick
(click)="usernameTypesLearnMore()"
appA11yTitle="{{ 'learnMore' | i18n }}"
>
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
</a>
</label>
<div
class="radio-group align-start text-default"
appBoxRow
name="UsernameTypeOptions"
*ngFor="let o of usernameTypeOptions"
>
<input
type="radio"
class="radio"
[(ngModel)]="usernameOptions.type"
name="UsernameType_{{ o.value }}"
id="usernameType_{{ o.value }}"
[value]="o.value"
(change)="saveUsernameOptions()"
[checked]="usernameOptions.type === o.value"
/>
<label class="unstyled" for="usernameType_{{ o.value }}">
{{ o.name }}
<div class="small text-muted" *ngIf="o.desc">{{ o.desc }}</div>
</label>
</div>
</div>
</div>
</div>
<div class="box" *ngIf="usernameOptions.type === 'forwarded'" [hidden]="!showOptions">
<div class="box-content condensed">
<div class="box-content-row">
<label class="radio-header">{{ "service" | i18n }}</label>
<div class="radio-group text-default" appBoxRow *ngFor="let o of forwardOptions">
<input
type="radio"
[(ngModel)]="usernameOptions.forwardedService"
name="ForwardType_{{ o.value }}"
id="forwardtype_{{ o.value }}"
[value]="o.value"
(change)="saveUsernameOptions()"
[checked]="usernameOptions.forwardedService === o.value"
/>
<label for="forwardtype_{{ o.value }}">
{{ o.name }}
</label>
</div>
</div>
</div>
</div>
<div class="box" *ngIf="usernameOptions.type === 'subaddress'" [hidden]="!showOptions">
<div class="box-content condensed">
<div class="box-content-row" appBoxRow>
<label for="subaddress-email">{{ "emailAddress" | i18n }}</label>
2021-12-20 15:47:17 +01:00
<input
id="subaddress-email"
type="text"
name="SubaddressEmail"
[(ngModel)]="usernameOptions.subaddressEmail"
(blur)="saveUsernameOptions()"
2021-12-20 15:47:17 +01:00
/>
</div>
<div class="box-content-row" *ngIf="subaddressOptions.length > 1">
<label class="radio-header">{{ "type" | i18n }}</label>
<div class="radio-group text-default" appBoxRow *ngFor="let o of subaddressOptions">
<input
type="radio"
[(ngModel)]="usernameOptions.subaddressType"
name="SubaddressType_{{ o.value }}"
id="subaddresstype_{{ o.value }}"
[value]="o.value"
(change)="saveUsernameOptions()"
[checked]="usernameOptions.subaddressType === o.value"
/>
<label for="subaddresstype_{{ o.value }}">
{{ o.name }}
</label>
</div>
</div>
<div class="box-content-row" appBoxRow *ngIf="usernameWebsite">
<label for="subaddress-website">{{ "website" | i18n }}</label>
2021-12-20 15:47:17 +01:00
<input
id="subaddress-website"
type="text"
name="SubaddressWebsite"
[value]="usernameOptions.website"
disabled
readonly
2021-12-20 15:47:17 +01:00
/>
</div>
</div>
</div>
<div class="box" *ngIf="usernameOptions.type === 'catchall'" [hidden]="!showOptions">
2018-10-09 15:13:22 +02:00
<div class="box-content condensed">
<div class="box-content-row" appBoxRow>
<label for="catchall-domain">{{ "domainName" | i18n }}</label>
2021-12-20 15:47:17 +01:00
<input
id="catchall-domain"
type="text"
name="CatchallDomain"
[(ngModel)]="usernameOptions.catchallDomain"
(blur)="saveUsernameOptions()"
2021-12-20 15:47:17 +01:00
/>
</div>
<div class="box-content-row" *ngIf="catchallOptions.length > 1">
<label class="radio-header">{{ "type" | i18n }}</label>
<div class="radio-group text-default" appBoxRow *ngFor="let o of catchallOptions">
<input
type="radio"
[(ngModel)]="usernameOptions.catchallType"
name="CatchallType_{{ o.value }}"
id="catchalltype_{{ o.value }}"
[value]="o.value"
(change)="saveUsernameOptions()"
[checked]="usernameOptions.catchallType === o.value"
/>
<label for="catchalltype_{{ o.value }}">
{{ o.name }}
</label>
</div>
</div>
<div class="box-content-row" appBoxRow *ngIf="usernameWebsite">
<label for="catchall-website">{{ "website" | i18n }}</label>
2021-12-20 15:47:17 +01:00
<input
id="catchall-website"
type="text"
name="CatchallWebsite"
[value]="usernameOptions.website"
disabled
readonly
2021-12-20 15:47:17 +01:00
/>
</div>
</div>
</div>
<div class="box" *ngIf="usernameOptions.type === 'word'" [hidden]="!showOptions">
<div class="box-content condensed">
2018-10-09 15:13:22 +02:00
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="capitalize">{{ "capitalize" | i18n }}</label>
2021-12-20 15:47:17 +01:00
<input
id="capitalize"
2018-10-09 15:13:22 +02:00
type="checkbox"
(change)="saveUsernameOptions()"
[(ngModel)]="usernameOptions.wordCapitalize"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="include-number">{{ "includeNumber" | i18n }}</label>
<input
id="include-number"
type="checkbox"
(change)="saveUsernameOptions()"
[(ngModel)]="usernameOptions.wordIncludeNumber"
2021-12-20 15:47:17 +01:00
/>
</div>
</div>
</div>
2018-10-09 15:13:22 +02:00
</ng-container>
2021-12-20 15:47:17 +01:00
</div>
2018-01-29 18:14:19 +01:00
<div class="modal-footer">
2021-12-20 15:47:17 +01:00
<button
2019-04-02 05:08:54 +02:00
type="button"
2018-02-01 03:13:42 +01:00
class="primary"
2019-02-21 22:53:32 +01:00
appBlurClick
*ngIf="comingFromAddEdit"
2018-02-01 03:13:42 +01:00
(click)="select()"
2019-04-02 04:43:42 +02:00
appA11yTitle="{{ 'select' | i18n }}"
2021-12-20 15:47:17 +01:00
>
<i class="bwi bwi-lg bwi-fw bwi-check" aria-hidden="true"></i>
2018-01-29 22:13:37 +01:00
</button>
2019-04-02 05:08:54 +02:00
<button type="button" data-dismiss="modal">
{{ (comingFromAddEdit ? "cancel" : "close") | i18n }}
2018-01-29 22:13:37 +01:00
</button>
2021-12-20 15:47:17 +01:00
</div>
2018-01-29 15:33:43 +01:00
</div>
2021-12-20 15:47:17 +01:00
</div>
2018-01-29 15:33:43 +01:00
</div>