add username generation to generator (#1566)
* add username generation to generator * move bottom buttons into existing containers
This commit is contained in:
parent
42ececbcf5
commit
23b02a770a
|
@ -240,7 +240,7 @@ const routes: Routes = [
|
|||
{
|
||||
path: "generator",
|
||||
component: PasswordGeneratorComponent,
|
||||
data: { titleId: "passwordGenerator" },
|
||||
data: { titleId: "generator" },
|
||||
},
|
||||
{
|
||||
path: "breach-report",
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<li class="list-group-item d-flex" *ngFor="let h of history">
|
||||
<div class="password-row">
|
||||
<div
|
||||
class="text-monospace password-wrapper"
|
||||
class="text-monospace generated-wrapper"
|
||||
[innerHTML]="h.password | colorPassword"
|
||||
appSelectCopy
|
||||
></div>
|
||||
|
|
|
@ -1,32 +1,63 @@
|
|||
<div class="page-header">
|
||||
<h1>{{ "passwordGenerator" | i18n }}</h1>
|
||||
<h1>{{ "generator" | i18n }}</h1>
|
||||
</div>
|
||||
<app-callout type="info" *ngIf="enforcedPasswordPolicyOptions?.inEffect()">
|
||||
<app-callout type="info" *ngIf="enforcedPasswordPolicyOptions?.inEffect() && type === 'password'">
|
||||
{{ "passwordGeneratorPolicyInEffect" | i18n }}
|
||||
</app-callout>
|
||||
<div class="card card-password bg-light my-4">
|
||||
<div class="card card-generated bg-light my-4">
|
||||
<div class="card-body">
|
||||
<div class="password-wrapper" [innerHTML]="password | colorPassword" appSelectCopy></div>
|
||||
<div
|
||||
*ngIf="type === 'password'"
|
||||
class="generated-wrapper"
|
||||
[innerHTML]="password | colorPassword"
|
||||
appSelectCopy
|
||||
></div>
|
||||
<div
|
||||
*ngIf="type === 'username'"
|
||||
class="generated-wrapper"
|
||||
[innerHTML]="username | colorPassword"
|
||||
appSelectCopy
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-check form-check-inline" *ngFor="let o of passTypeOptions">
|
||||
<label class="d-block">{{ "whatWouldYouLikeToGenerate" | i18n }}</label>
|
||||
<div class="form-check form-check-inline" *ngFor="let o of typeOptions">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="radio"
|
||||
[(ngModel)]="passwordOptions.type"
|
||||
[(ngModel)]="type"
|
||||
name="Type_{{ o.value }}"
|
||||
id="type_{{ o.value }}"
|
||||
[value]="o.value"
|
||||
(change)="savePasswordOptions()"
|
||||
[checked]="passwordOptions.type === o.value"
|
||||
(change)="typeChanged()"
|
||||
[checked]="type === o.value"
|
||||
/>
|
||||
<label class="form-check-label" for="type_{{ o.value }}">
|
||||
{{ o.name }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container *ngIf="passwordOptions.type === 'passphrase'">
|
||||
<ng-container *ngIf="type === 'password'">
|
||||
<div class="form-group">
|
||||
<label class="d-block">{{ "passwordType" | i18n }}</label>
|
||||
<div class="form-check form-check-inline" *ngFor="let o of passTypeOptions">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="radio"
|
||||
[(ngModel)]="passwordOptions.type"
|
||||
name="PasswordType_{{ o.value }}"
|
||||
id="passwordType_{{ o.value }}"
|
||||
[value]="o.value"
|
||||
(change)="savePasswordOptions()"
|
||||
[checked]="passwordOptions.type === o.value"
|
||||
/>
|
||||
<label class="form-check-label" for="passwordType_{{ o.value }}">
|
||||
{{ o.name }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container *ngIf="passwordOptions.type === 'passphrase'">
|
||||
<div class="row">
|
||||
<div class="form-group col-4">
|
||||
<label for="num-words">{{ "numWords" | i18n }}</label>
|
||||
|
@ -52,6 +83,7 @@
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<label class="d-block">{{ "options" | i18n }}</label>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input
|
||||
|
@ -76,8 +108,8 @@
|
|||
<label for="include-number" class="form-check-label">{{ "includeNumber" | i18n }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="passwordOptions.type === 'password'">
|
||||
</ng-container>
|
||||
<ng-container *ngIf="passwordOptions.type === 'password'">
|
||||
<div class="row">
|
||||
<div class="form-group col-4">
|
||||
<label for="length">{{ "length" | i18n }}</label>
|
||||
|
@ -119,6 +151,7 @@
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<label class="d-block">{{ "options" | i18n }}</label>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input
|
||||
|
@ -175,8 +208,8 @@
|
|||
<label for="ambiguous" class="form-check-label">{{ "ambiguous" | i18n }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div class="d-flex">
|
||||
</ng-container>
|
||||
<div class="d-flex">
|
||||
<div>
|
||||
<button type="button" class="btn btn-primary" (click)="regenerate()">
|
||||
{{ "regeneratePassword" | i18n }}
|
||||
|
@ -195,5 +228,103 @@
|
|||
<i class="bwi bwi-clock bwi-lg" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="type === 'username'">
|
||||
<div class="form-group">
|
||||
<label class="d-block">{{ "usernameType" | i18n }}</label>
|
||||
<div class="form-check" *ngFor="let o of usernameTypeOptions">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="radio"
|
||||
[(ngModel)]="usernameOptions.type"
|
||||
name="UsernameType_{{ o.value }}"
|
||||
id="usernameType_{{ o.value }}"
|
||||
[value]="o.value"
|
||||
(change)="saveUsernameOptions()"
|
||||
[checked]="usernameOptions.type === o.value"
|
||||
/>
|
||||
<label class="form-check-label" for="usernameType_{{ o.value }}">
|
||||
{{ o.name }}
|
||||
<div class="small text-muted">{{ o.desc }}</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" *ngIf="usernameOptions.type === 'forwarded'">
|
||||
<div class="form-check form-check-inline" *ngFor="let o of forwardOptions">
|
||||
<input
|
||||
class="form-check-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 class="form-check-label" for="forwardtype_{{ o.value }}">
|
||||
{{ o.name }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" *ngIf="usernameOptions.type === 'subaddress'">
|
||||
<div class="form-group col-4">
|
||||
<label for="subaddress-email">{{ "emailAddress" | i18n }}</label>
|
||||
<input
|
||||
id="subaddress-email"
|
||||
class="form-control"
|
||||
type="text"
|
||||
[(ngModel)]="usernameOptions.subaddressEmail"
|
||||
(blur)="saveUsernameOptions()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" *ngIf="usernameOptions.type === 'catchall'">
|
||||
<div class="form-group col-4">
|
||||
<label for="catchall-domain">{{ "domainName" | i18n }}</label>
|
||||
<input
|
||||
id="catchall-domain"
|
||||
class="form-control"
|
||||
type="text"
|
||||
[(ngModel)]="usernameOptions.catchallDomain"
|
||||
(blur)="saveUsernameOptions()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container *ngIf="usernameOptions.type === 'word'">
|
||||
<label class="d-block">{{ "options" | i18n }}</label>
|
||||
<div class="row">
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input
|
||||
id="capitalizeUsername"
|
||||
type="checkbox"
|
||||
(change)="saveUsernameOptions()"
|
||||
[(ngModel)]="usernameOptions.wordCapitalize"
|
||||
/>
|
||||
<label for="capitalizeUsername" class="form-check-label">{{ "capitalize" | i18n }}</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input
|
||||
id="includeNumberUsername"
|
||||
type="checkbox"
|
||||
(change)="saveUsernameOptions()"
|
||||
[(ngModel)]="usernameOptions.wordIncludeNumber"
|
||||
/>
|
||||
<label for="includeNumberUsername" class="form-check-label">{{
|
||||
"includeNumber" | i18n
|
||||
}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div>
|
||||
<button type="button" class="btn btn-primary" (click)="regenerate()">
|
||||
{{ "regenerateUsername" | i18n }}
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="copy()">
|
||||
{{ "copyUsername" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-template #historyTemplate></ng-template>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<div class="card-header">{{ "tools" | i18n }}</div>
|
||||
<div class="list-group list-group-flush">
|
||||
<a routerLink="generator" class="list-group-item" routerLinkActive="active">
|
||||
{{ "passwordGenerator" | i18n }}
|
||||
{{ "generator" | i18n }}
|
||||
</a>
|
||||
<a routerLink="import" class="list-group-item" routerLinkActive="active">
|
||||
{{ "importData" | i18n }}
|
||||
|
|
|
@ -769,7 +769,7 @@
|
|||
<div class="ml-3" *ngIf="viewingPasswordHistory">
|
||||
<div *ngFor="let ph of cipher.passwordHistory">
|
||||
{{ ph.lastUsedDate | date: "short" }} -
|
||||
<span class="password-wrapper text-monospace ml-2">{{ ph.password }}</span>
|
||||
<span class="generated-wrapper text-monospace ml-2">{{ ph.password }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -187,7 +187,12 @@
|
|||
"message": "Edit Folder"
|
||||
},
|
||||
"baseDomain": {
|
||||
"message": "Base domain"
|
||||
"message": "Base domain",
|
||||
"description": "Domain name. Ex. website.com"
|
||||
},
|
||||
"domainName": {
|
||||
"message": "Domain Name",
|
||||
"description": "Domain name. Ex. website.com"
|
||||
},
|
||||
"host": {
|
||||
"message": "Host",
|
||||
|
@ -4826,5 +4831,44 @@
|
|||
"example": "My Org Name"
|
||||
}
|
||||
}
|
||||
},
|
||||
"generator": {
|
||||
"message": "Generator"
|
||||
},
|
||||
"whatWouldYouLikeToGenerate": {
|
||||
"message": "What would you like to generate?"
|
||||
},
|
||||
"passwordType": {
|
||||
"message": "Password Type"
|
||||
},
|
||||
"regenerateUsername": {
|
||||
"message": "Regenerate Username"
|
||||
},
|
||||
"generateUsername": {
|
||||
"message": "Generate Username"
|
||||
},
|
||||
"usernameType": {
|
||||
"message": "Username Type"
|
||||
},
|
||||
"plusAddressedEmail": {
|
||||
"message": "Plus Addressed Email"
|
||||
},
|
||||
"plusAddressedEmailDesc": {
|
||||
"message": "Use your email provider's sub-addressing capabilities."
|
||||
},
|
||||
"catchallEmail": {
|
||||
"message": "Catch-all Email"
|
||||
},
|
||||
"catchallEmailDesc": {
|
||||
"message": "Use your domain's configured catch-all inbox."
|
||||
},
|
||||
"random": {
|
||||
"message": "Random"
|
||||
},
|
||||
"randomWord": {
|
||||
"message": "Random Word"
|
||||
},
|
||||
"service": {
|
||||
"message": "Service"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.password-wrapper {
|
||||
.generated-wrapper {
|
||||
min-width: 0;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
|
@ -114,7 +114,7 @@ app-password-generator {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.card-password {
|
||||
.card-generated {
|
||||
.card-body {
|
||||
@include themify($themes) {
|
||||
background: themed("foregroundColor");
|
||||
|
|
Loading…
Reference in New Issue