add boundary help text to credential settings

This commit is contained in:
✨ Audrey ✨ 2024-10-28 14:37:16 -04:00
parent 2a47b9b06a
commit ab49dc57ec
No known key found for this signature in database
GPG Key ID: 0CF8B4C0D9088B97
7 changed files with 76 additions and 2 deletions

View File

@ -2877,6 +2877,20 @@
"generateEmail": {
"message": "Generate email"
},
"generatorBoundariesHint": {
"message": "Value must be between $MIN$ and $MAX$",
"description": "Explains spin box minimum and maximum values to the user",
"placeholders": {
"min": {
"content": "$1",
"example": "8"
},
"max": {
"content": "$2",
"example": "128"
}
}
},
"usernameType": {
"message": "Username type"
},

View File

@ -2393,6 +2393,20 @@
"generateEmail": {
"message": "Generate email"
},
"generatorBoundariesHint": {
"message": "Value must be between $MIN$ and $MAX$",
"description": "Explains spin box minimum and maximum values to the user",
"placeholders": {
"min": {
"content": "$1",
"example": "8"
},
"max": {
"content": "$2",
"example": "128"
}
}
},
"usernameType": {
"message": "Username type"
},

View File

@ -6412,6 +6412,20 @@
"generateEmail": {
"message": "Generate email"
},
"generatorBoundariesHint": {
"message": "Value must be between $MIN$ and $MAX$",
"description": "Explains spin box minimum and maximum values to the user",
"placeholders": {
"min": {
"content": "$1",
"example": "8"
},
"max": {
"content": "$2",
"example": "128"
}
}
},
"usernameType": {
"message": "Username type"
},

View File

@ -8,6 +8,7 @@
<bit-form-field disableMargin>
<bit-label>{{ "numWords" | i18n }}</bit-label>
<input bitInput formControlName="numWords" id="num-words" type="number" />
<bit-hint>{{ numWordsBoundariesHint$ | async }}</bit-hint>
</bit-form-field>
</bit-card>
</div>

View File

@ -1,9 +1,10 @@
import { coerceBooleanProperty } from "@angular/cdk/coercion";
import { OnInit, Input, Output, EventEmitter, Component, OnDestroy } from "@angular/core";
import { FormBuilder } from "@angular/forms";
import { BehaviorSubject, skip, takeUntil, Subject } from "rxjs";
import { BehaviorSubject, skip, takeUntil, Subject, ReplaySubject } from "rxjs";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { UserId } from "@bitwarden/common/types/guid";
import {
Generators,
@ -29,11 +30,13 @@ export class PassphraseSettingsComponent implements OnInit, OnDestroy {
/** Instantiates the component
* @param accountService queries user availability
* @param generatorService settings and policy logic
* @param i18nService localize hints
* @param formBuilder reactive form controls
*/
constructor(
private formBuilder: FormBuilder,
private generatorService: CredentialGeneratorService,
private i18nService: I18nService,
private accountService: AccountService,
) {}
@ -97,6 +100,13 @@ export class PassphraseSettingsComponent implements OnInit, OnDestroy {
this.toggleEnabled(Controls.capitalize, !constraints.capitalize?.readonly);
this.toggleEnabled(Controls.includeNumber, !constraints.includeNumber?.readonly);
const boundariesHint = this.i18nService.t(
"generatorBoundariesHint",
constraints.numWords.min,
constraints.numWords.max,
);
this.numWordsBoundariesHint.next(boundariesHint);
});
// now that outputs are set up, connect inputs
@ -106,6 +116,11 @@ export class PassphraseSettingsComponent implements OnInit, OnDestroy {
/** display binding for enterprise policy notice */
protected policyInEffect: boolean;
private numWordsBoundariesHint = new ReplaySubject<string>(1);
/** display binding for min/max constraints of `numWords` */
protected numWordsBoundariesHint$ = this.numWordsBoundariesHint.asObservable();
private toggleEnabled(setting: keyof typeof Controls, enabled: boolean) {
if (enabled) {
this.settings.get(setting).enable({ emitEvent: false });

View File

@ -8,6 +8,7 @@
<bit-form-field disableMargin>
<bit-label>{{ "length" | i18n }}</bit-label>
<input bitInput formControlName="length" type="number" />
<bit-hint>{{ lengthBoundariesHint$ | async }}</bit-hint>
</bit-form-field>
</bit-card>
</div>

View File

@ -1,9 +1,10 @@
import { coerceBooleanProperty } from "@angular/cdk/coercion";
import { OnInit, Input, Output, EventEmitter, Component, OnDestroy } from "@angular/core";
import { FormBuilder } from "@angular/forms";
import { BehaviorSubject, takeUntil, Subject, map, filter, tap, skip } from "rxjs";
import { BehaviorSubject, takeUntil, Subject, map, filter, tap, skip, ReplaySubject } from "rxjs";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { UserId } from "@bitwarden/common/types/guid";
import {
Generators,
@ -33,11 +34,13 @@ export class PasswordSettingsComponent implements OnInit, OnDestroy {
/** Instantiates the component
* @param accountService queries user availability
* @param generatorService settings and policy logic
* @param i18nService localize hints
* @param formBuilder reactive form controls
*/
constructor(
private formBuilder: FormBuilder,
private generatorService: CredentialGeneratorService,
private i18nService: I18nService,
private accountService: AccountService,
) {}
@ -147,6 +150,13 @@ export class PasswordSettingsComponent implements OnInit, OnDestroy {
for (const [control, enabled] of toggles) {
this.toggleEnabled(control, enabled);
}
const boundariesHint = this.i18nService.t(
"generatorBoundariesHint",
constraints.length.min,
constraints.length.max,
);
this.lengthBoundariesHint.next(boundariesHint);
});
// cascade selections between checkboxes and spinboxes
@ -208,6 +218,11 @@ export class PasswordSettingsComponent implements OnInit, OnDestroy {
/** display binding for enterprise policy notice */
protected policyInEffect: boolean;
private lengthBoundariesHint = new ReplaySubject<string>(1);
/** display binding for min/max constraints of `length` */
protected lengthBoundariesHint$ = this.lengthBoundariesHint.asObservable();
private toggleEnabled(setting: keyof typeof Controls, enabled: boolean) {
if (enabled) {
this.settings.get(setting).enable({ emitEvent: false });