1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-11-14 10:26:19 +01:00

[PM-10437][PM-10438] Copy toast message (#10366)

* add option to include a label for copy success message

* add label text to copy success messages for all cipher types
This commit is contained in:
Nick Krantz 2024-08-05 13:00:29 -05:00 committed by GitHub
parent cecfbaeaad
commit 8fcf717ec4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 50 additions and 2 deletions

View File

@ -12,12 +12,14 @@ import { CopyClickDirective } from "./copy-click.directive";
<button appCopyClick="no toast shown" #noToast></button> <button appCopyClick="no toast shown" #noToast></button>
<button appCopyClick="info toast shown" showToast="info" #infoToast></button> <button appCopyClick="info toast shown" showToast="info" #infoToast></button>
<button appCopyClick="success toast shown" showToast #successToast></button> <button appCopyClick="success toast shown" showToast #successToast></button>
<button appCopyClick="toast with label" showToast valueLabel="Content" #toastWithLabel></button>
`, `,
}) })
class TestCopyClickComponent { class TestCopyClickComponent {
@ViewChild("noToast") noToastButton: ElementRef<HTMLButtonElement>; @ViewChild("noToast") noToastButton: ElementRef<HTMLButtonElement>;
@ViewChild("infoToast") infoToastButton: ElementRef<HTMLButtonElement>; @ViewChild("infoToast") infoToastButton: ElementRef<HTMLButtonElement>;
@ViewChild("successToast") successToastButton: ElementRef<HTMLButtonElement>; @ViewChild("successToast") successToastButton: ElementRef<HTMLButtonElement>;
@ViewChild("toastWithLabel") toastWithLabelButton: ElementRef<HTMLButtonElement>;
} }
describe("CopyClickDirective", () => { describe("CopyClickDirective", () => {
@ -32,7 +34,17 @@ describe("CopyClickDirective", () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [CopyClickDirective, TestCopyClickComponent], declarations: [CopyClickDirective, TestCopyClickComponent],
providers: [ providers: [
{ provide: I18nService, useValue: { t: (key: string) => key } }, {
provide: I18nService,
useValue: {
t: (key: string, ...rest: string[]) => {
if (rest?.length) {
return `${key} ${rest.join("")}`;
}
return key;
},
},
},
{ provide: PlatformUtilsService, useValue: { copyToClipboard } }, { provide: PlatformUtilsService, useValue: { copyToClipboard } },
{ provide: ToastService, useValue: { showToast } }, { provide: ToastService, useValue: { showToast } },
], ],
@ -87,4 +99,16 @@ describe("CopyClickDirective", () => {
variant: "info", variant: "info",
}); });
}); });
it('includes label in toast message when "copyLabel" is set', () => {
const toastWithLabelButton = fixture.componentInstance.toastWithLabelButton.nativeElement;
toastWithLabelButton.click();
expect(showToast).toHaveBeenCalledWith({
message: "valueCopied Content",
title: null,
variant: "success",
});
});
}); });

View File

@ -20,6 +20,12 @@ export class CopyClickDirective {
@Input("appCopyClick") valueToCopy = ""; @Input("appCopyClick") valueToCopy = "";
/**
* When set, the toast displayed will show `<valueLabel> copied`
* instead of the default messaging.
*/
@Input() valueLabel: string;
/** /**
* When set without a value, a success toast will be shown when the value is copied * When set without a value, a success toast will be shown when the value is copied
* @example * @example
@ -47,10 +53,14 @@ export class CopyClickDirective {
this.platformUtilsService.copyToClipboard(this.valueToCopy); this.platformUtilsService.copyToClipboard(this.valueToCopy);
if (this._showToast) { if (this._showToast) {
const message = this.valueLabel
? this.i18nService.t("valueCopied", this.valueLabel)
: this.i18nService.t("copySuccessful");
this.toastService.showToast({ this.toastService.showToast({
variant: this.toastVariant, variant: this.toastVariant,
title: null, title: null,
message: this.i18nService.t("copySuccessful"), message,
}); });
} }
} }

View File

@ -13,6 +13,7 @@
type="button" type="button"
[appCopyClick]="notes" [appCopyClick]="notes"
showToast showToast
[valueLabel]="'note' | i18n"
[appA11yTitle]="'copyValue' | i18n" [appA11yTitle]="'copyValue' | i18n"
></button> ></button>
</bit-form-field> </bit-form-field>

View File

@ -37,6 +37,7 @@
type="button" type="button"
[appCopyClick]="card.number" [appCopyClick]="card.number"
showToast showToast
[valueLabel]="'number' | i18n"
[appA11yTitle]="'copyValue' | i18n" [appA11yTitle]="'copyValue' | i18n"
data-testid="copy-number" data-testid="copy-number"
></button> ></button>
@ -75,6 +76,7 @@
type="button" type="button"
[appCopyClick]="card.code" [appCopyClick]="card.code"
showToast showToast
[valueLabel]="'securityCode' | i18n"
[appA11yTitle]="'copyValue' | i18n" [appA11yTitle]="'copyValue' | i18n"
data-testid="copy-code" data-testid="copy-code"
></button> ></button>

View File

@ -17,6 +17,7 @@
type="button" type="button"
[appCopyClick]="field.value" [appCopyClick]="field.value"
showToast showToast
[valueLabel]="field.name"
[appA11yTitle]="'copyValue' | i18n" [appA11yTitle]="'copyValue' | i18n"
></button> ></button>
</bit-form-field> </bit-form-field>
@ -30,6 +31,7 @@
type="button" type="button"
[appCopyClick]="field.value" [appCopyClick]="field.value"
showToast showToast
[valueLabel]="field.name"
[appA11yTitle]="'copyValue' | i18n" [appA11yTitle]="'copyValue' | i18n"
></button> ></button>
</bit-form-field> </bit-form-field>

View File

@ -14,6 +14,7 @@
[appA11yTitle]="'copyName' | i18n" [appA11yTitle]="'copyName' | i18n"
[appCopyClick]="cipher.identity.fullName" [appCopyClick]="cipher.identity.fullName"
showToast showToast
[valueLabel]="'name' | i18n"
></button> ></button>
</bit-form-field> </bit-form-field>
<bit-form-field *ngIf="cipher.identity.username"> <bit-form-field *ngIf="cipher.identity.username">
@ -26,6 +27,7 @@
[appA11yTitle]="'copyUsername' | i18n" [appA11yTitle]="'copyUsername' | i18n"
[appCopyClick]="cipher.identity.username" [appCopyClick]="cipher.identity.username"
showToast showToast
[valueLabel]="'username' | i18n"
></button> ></button>
</bit-form-field> </bit-form-field>
<bit-form-field *ngIf="cipher.identity.company"> <bit-form-field *ngIf="cipher.identity.company">
@ -38,6 +40,7 @@
[appA11yTitle]="'copyCompany' | i18n" [appA11yTitle]="'copyCompany' | i18n"
[appCopyClick]="cipher.identity.company" [appCopyClick]="cipher.identity.company"
showToast showToast
[valueLabel]="'company' | i18n"
></button> ></button>
</bit-form-field> </bit-form-field>
</bit-card> </bit-card>
@ -66,6 +69,7 @@
[appA11yTitle]="'copySSN' | i18n" [appA11yTitle]="'copySSN' | i18n"
[appCopyClick]="cipher.identity.ssn" [appCopyClick]="cipher.identity.ssn"
showToast showToast
[valueLabel]="'ssn' | i18n"
></button> ></button>
</bit-form-field> </bit-form-field>
<bit-form-field *ngIf="cipher.identity.passportNumber"> <bit-form-field *ngIf="cipher.identity.passportNumber">
@ -91,6 +95,7 @@
[appA11yTitle]="'copyPassportNumber' | i18n" [appA11yTitle]="'copyPassportNumber' | i18n"
[appCopyClick]="cipher.identity.passportNumber" [appCopyClick]="cipher.identity.passportNumber"
showToast showToast
[valueLabel]="'passportNumber' | i18n"
></button> ></button>
</bit-form-field> </bit-form-field>
<bit-form-field *ngIf="cipher.identity.licenseNumber"> <bit-form-field *ngIf="cipher.identity.licenseNumber">
@ -103,6 +108,7 @@
[appA11yTitle]="'copyLicenseNumber' | i18n" [appA11yTitle]="'copyLicenseNumber' | i18n"
[appCopyClick]="cipher.identity.licenseNumber" [appCopyClick]="cipher.identity.licenseNumber"
showToast showToast
[valueLabel]="'licenseNumber' | i18n"
></button> ></button>
</bit-form-field> </bit-form-field>
</bit-card> </bit-card>
@ -124,6 +130,7 @@
[appA11yTitle]="'copyEmail' | i18n" [appA11yTitle]="'copyEmail' | i18n"
[appCopyClick]="cipher.identity.email" [appCopyClick]="cipher.identity.email"
showToast showToast
[valueLabel]="'email' | i18n"
></button> ></button>
</bit-form-field> </bit-form-field>
<bit-form-field *ngIf="cipher.identity.phone"> <bit-form-field *ngIf="cipher.identity.phone">
@ -136,6 +143,7 @@
[appA11yTitle]="'copyPhone' | i18n" [appA11yTitle]="'copyPhone' | i18n"
[appCopyClick]="cipher.identity.phone" [appCopyClick]="cipher.identity.phone"
showToast showToast
[valueLabel]="'phone' | i18n"
></button> ></button>
</bit-form-field> </bit-form-field>
<bit-form-field *ngIf="addressFields"> <bit-form-field *ngIf="addressFields">
@ -155,6 +163,7 @@
[appA11yTitle]="'copyAddress' | i18n" [appA11yTitle]="'copyAddress' | i18n"
[appCopyClick]="addressFields" [appCopyClick]="addressFields"
showToast showToast
[valueLabel]="'address' | i18n"
></button> ></button>
</bit-form-field> </bit-form-field>
</bit-card> </bit-card>