mirror of
https://github.com/bitwarden/browser
synced 2025-12-11 22:03:36 +00:00
[PM-18463] [PM-18465] At-risk Password Page Fixes (#13573)
* [PM-18463] Add hyphen and fix description pluralization * [PM-18463] Add spacing between buttons * [PM-18463] Ensure callout does not flash
This commit is contained in:
@@ -2446,8 +2446,17 @@
|
|||||||
"atRiskPasswords": {
|
"atRiskPasswords": {
|
||||||
"message": "At-risk passwords"
|
"message": "At-risk passwords"
|
||||||
},
|
},
|
||||||
"atRiskPasswordsDescSingleOrg": {
|
"atRiskPasswordDescSingleOrg": {
|
||||||
"message": "$ORGANIZATION$ is requesting you change the $COUNT$ passwords because they are at risk.",
|
"message": "$ORGANIZATION$ is requesting you change one password because it is at-risk.",
|
||||||
|
"placeholders": {
|
||||||
|
"organization": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "Acme Corp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"atRiskPasswordsDescSingleOrgPlural": {
|
||||||
|
"message": "$ORGANIZATION$ is requesting you change the $COUNT$ passwords because they are at-risk.",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"organization": {
|
"organization": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
@@ -2459,8 +2468,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"atRiskPasswordsDescMultiOrg": {
|
"atRiskPasswordsDescMultiOrgPlural": {
|
||||||
"message": "Your organizations are requesting you change the $COUNT$ passwords because they are at risk.",
|
"message": "Your organizations are requesting you change the $COUNT$ passwords because they are at-risk.",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {
|
"count": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
</popup-header>
|
</popup-header>
|
||||||
|
|
||||||
<bit-callout
|
<bit-callout
|
||||||
*ngIf="!(inlineAutofillSettingEnabled$ | async) && !(calloutDismissed$ | async)"
|
*ngIf="showAutofillCallout$ | async"
|
||||||
type="info"
|
type="info"
|
||||||
[title]="'changeAtRiskPasswordsFaster' | i18n"
|
[title]="'changeAtRiskPasswordsFaster' | i18n"
|
||||||
data-testid="autofill-callout"
|
data-testid="autofill-callout"
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
buttonType="primary"
|
buttonType="primary"
|
||||||
(click)="activateInlineAutofillMenuVisibility()"
|
(click)="activateInlineAutofillMenuVisibility()"
|
||||||
data-testid="turn-on-autofill-button"
|
data-testid="turn-on-autofill-button"
|
||||||
|
class="tw-mr-2"
|
||||||
>
|
>
|
||||||
{{ "turnOnAutofill" | i18n }}
|
{{ "turnOnAutofill" | i18n }}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -198,8 +198,27 @@ describe("AtRiskPasswordsComponent", () => {
|
|||||||
|
|
||||||
describe("pageDescription$", () => {
|
describe("pageDescription$", () => {
|
||||||
it("should use single org description when tasks belong to one org", async () => {
|
it("should use single org description when tasks belong to one org", async () => {
|
||||||
const description = await firstValueFrom(component["pageDescription$"]);
|
// Single task
|
||||||
expect(description).toBe("atRiskPasswordsDescSingleOrg");
|
let description = await firstValueFrom(component["pageDescription$"]);
|
||||||
|
expect(description).toBe("atRiskPasswordDescSingleOrg");
|
||||||
|
|
||||||
|
// Multiple tasks
|
||||||
|
mockTasks$.next([
|
||||||
|
{
|
||||||
|
id: "task",
|
||||||
|
organizationId: "org",
|
||||||
|
cipherId: "cipher",
|
||||||
|
type: SecurityTaskType.UpdateAtRiskCredential,
|
||||||
|
} as SecurityTask,
|
||||||
|
{
|
||||||
|
id: "task2",
|
||||||
|
organizationId: "org",
|
||||||
|
cipherId: "cipher2",
|
||||||
|
type: SecurityTaskType.UpdateAtRiskCredential,
|
||||||
|
} as SecurityTask,
|
||||||
|
]);
|
||||||
|
description = await firstValueFrom(component["pageDescription$"]);
|
||||||
|
expect(description).toBe("atRiskPasswordsDescSingleOrgPlural");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should use multiple org description when tasks belong to multiple orgs", async () => {
|
it("should use multiple org description when tasks belong to multiple orgs", async () => {
|
||||||
@@ -218,7 +237,7 @@ describe("AtRiskPasswordsComponent", () => {
|
|||||||
} as SecurityTask,
|
} as SecurityTask,
|
||||||
]);
|
]);
|
||||||
const description = await firstValueFrom(component["pageDescription$"]);
|
const description = await firstValueFrom(component["pageDescription$"]);
|
||||||
expect(description).toBe("atRiskPasswordsDescMultiOrg");
|
expect(description).toBe("atRiskPasswordsDescMultiOrgPlural");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -115,14 +115,23 @@ export class AtRiskPasswordsComponent implements OnInit {
|
|||||||
startWith(true),
|
startWith(true),
|
||||||
);
|
);
|
||||||
|
|
||||||
protected calloutDismissed$ = this.activeUserData$.pipe(
|
private calloutDismissed$ = this.activeUserData$.pipe(
|
||||||
switchMap(({ userId }) => this.atRiskPasswordPageService.isCalloutDismissed(userId)),
|
switchMap(({ userId }) => this.atRiskPasswordPageService.isCalloutDismissed(userId)),
|
||||||
);
|
);
|
||||||
|
private inlineAutofillSettingEnabled$ = this.autofillSettingsService.inlineMenuVisibility$.pipe(
|
||||||
protected inlineAutofillSettingEnabled$ = this.autofillSettingsService.inlineMenuVisibility$.pipe(
|
|
||||||
map((setting) => setting !== AutofillOverlayVisibility.Off),
|
map((setting) => setting !== AutofillOverlayVisibility.Off),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
protected showAutofillCallout$ = combineLatest([
|
||||||
|
this.calloutDismissed$,
|
||||||
|
this.inlineAutofillSettingEnabled$,
|
||||||
|
]).pipe(
|
||||||
|
map(([calloutDismissed, inlineAutofillSettingEnabled]) => {
|
||||||
|
return !calloutDismissed && !inlineAutofillSettingEnabled;
|
||||||
|
}),
|
||||||
|
startWith(false),
|
||||||
|
);
|
||||||
|
|
||||||
protected atRiskItems$ = this.activeUserData$.pipe(
|
protected atRiskItems$ = this.activeUserData$.pipe(
|
||||||
map(({ tasks, ciphers }) =>
|
map(({ tasks, ciphers }) =>
|
||||||
tasks
|
tasks
|
||||||
@@ -143,11 +152,19 @@ export class AtRiskPasswordsComponent implements OnInit {
|
|||||||
const [orgId] = orgIds;
|
const [orgId] = orgIds;
|
||||||
return this.organizationService.organizations$(userId).pipe(
|
return this.organizationService.organizations$(userId).pipe(
|
||||||
getOrganizationById(orgId),
|
getOrganizationById(orgId),
|
||||||
map((org) => this.i18nService.t("atRiskPasswordsDescSingleOrg", org?.name, tasks.length)),
|
map((org) =>
|
||||||
|
this.i18nService.t(
|
||||||
|
tasks.length === 1
|
||||||
|
? "atRiskPasswordDescSingleOrg"
|
||||||
|
: "atRiskPasswordsDescSingleOrgPlural",
|
||||||
|
org?.name,
|
||||||
|
tasks.length,
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return of(this.i18nService.t("atRiskPasswordsDescMultiOrg", tasks.length));
|
return of(this.i18nService.t("atRiskPasswordsDescMultiOrgPlural", tasks.length));
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user