1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

Full headers (#16184)

Co-authored-by: Daniel James Smith <2670567+djsmith85@users.noreply.github.com>
This commit is contained in:
Konrad
2025-09-16 16:53:36 +02:00
committed by GitHub
parent 59396f0262
commit d06d47e26a
12 changed files with 231 additions and 163 deletions

View File

@@ -1934,32 +1934,81 @@
"typeNote": {
"message": "Note"
},
"newItemHeader": {
"message": "New $TYPE$",
"placeholders": {
"type": {
"content": "$1",
"example": "Login"
}
}
"newItemHeaderLogin": {
"message": "New Login",
"description": "Header for new login item type"
},
"editItemHeader": {
"message": "Edit $TYPE$",
"placeholders": {
"type": {
"content": "$1",
"example": "Login"
}
}
"newItemHeaderCard": {
"message": "New Card",
"description": "Header for new card item type"
},
"viewItemHeader": {
"message": "View $TYPE$",
"placeholders": {
"type": {
"content": "$1",
"example": "Login"
}
}
"newItemHeaderIdentity": {
"message": "New Identity",
"description": "Header for new identity item type"
},
"newItemHeaderNote": {
"message": "New Note",
"description": "Header for new note item type"
},
"newItemHeaderSshKey": {
"message": "New SSH key",
"description": "Header for new SSH key item type"
},
"newItemHeaderTextSend": {
"message": "New Text Send",
"description": "Header for new text send"
},
"newItemHeaderFileSend": {
"message": "New File Send",
"description": "Header for new file send"
},
"editItemHeaderLogin": {
"message": "Edit Login",
"description": "Header for edit login item type"
},
"editItemHeaderCard": {
"message": "Edit Card",
"description": "Header for edit card item type"
},
"editItemHeaderIdentity": {
"message": "Edit Identity",
"description": "Header for edit identity item type"
},
"editItemHeaderNote": {
"message": "Edit Note",
"description": "Header for edit note item type"
},
"editItemHeaderSshKey": {
"message": "Edit SSH key",
"description": "Header for edit SSH key item type"
},
"editItemHeaderTextSend": {
"message": "Edit Text Send",
"description": "Header for edit text send"
},
"editItemHeaderFileSend": {
"message": "Edit File Send",
"description": "Header for edit file send"
},
"viewItemHeaderLogin": {
"message": "View Login",
"description": "Header for view login item type"
},
"viewItemHeaderCard": {
"message": "View Card",
"description": "Header for view card item type"
},
"viewItemHeaderIdentity": {
"message": "View Identity",
"description": "Header for view identity item type"
},
"viewItemHeaderNote": {
"message": "View Note",
"description": "Header for view note item type"
},
"viewItemHeaderSshKey": {
"message": "View SSH key",
"description": "Header for view SSH key item type"
},
"passwordHistory": {
"message": "Password history"
@@ -5092,15 +5141,9 @@
"itemLocation": {
"message": "Item Location"
},
"fileSend": {
"message": "File Send"
},
"fileSends": {
"message": "File Sends"
},
"textSend": {
"message": "Text Send"
},
"textSends": {
"message": "Text Sends"
},

View File

@@ -188,14 +188,11 @@ export class SendAddEditComponent {
* @returns The header text.
*/
private getHeaderText(mode: SendFormMode, type: SendType) {
const headerKey =
mode === "edit" || mode === "partial-edit" ? "editItemHeader" : "newItemHeader";
switch (type) {
case SendType.Text:
return this.i18nService.t(headerKey, this.i18nService.t("textSend"));
case SendType.File:
return this.i18nService.t(headerKey, this.i18nService.t("fileSend"));
}
const isEditMode = mode === "edit" || mode === "partial-edit";
const translation = {
[SendType.Text]: isEditMode ? "editItemHeaderTextSend" : "newItemHeaderTextSend",
[SendType.File]: isEditMode ? "editItemHeaderFileSend" : "newItemHeaderFileSend",
};
return this.i18nService.t(translation[type]);
}
}

View File

@@ -368,20 +368,15 @@ export class AddEditV2Component implements OnInit {
}
setHeader(mode: CipherFormMode, type: CipherType) {
const partOne = mode === "edit" || mode === "partial-edit" ? "editItemHeader" : "newItemHeader";
switch (type) {
case CipherType.Login:
return this.i18nService.t(partOne, this.i18nService.t("typeLogin"));
case CipherType.Card:
return this.i18nService.t(partOne, this.i18nService.t("typeCard"));
case CipherType.Identity:
return this.i18nService.t(partOne, this.i18nService.t("typeIdentity"));
case CipherType.SecureNote:
return this.i18nService.t(partOne, this.i18nService.t("note"));
case CipherType.SshKey:
return this.i18nService.t(partOne, this.i18nService.t("typeSshKey"));
}
const isEditMode = mode === "edit" || mode === "partial-edit";
const translation = {
[CipherType.Login]: isEditMode ? "editItemHeaderLogin" : "newItemHeaderLogin",
[CipherType.Card]: isEditMode ? "editItemHeaderCard" : "newItemHeaderCard",
[CipherType.Identity]: isEditMode ? "editItemHeaderIdentity" : "newItemHeaderIdentity",
[CipherType.SecureNote]: isEditMode ? "editItemHeaderNote" : "newItemHeaderNote",
[CipherType.SshKey]: isEditMode ? "editItemHeaderSshKey" : "newItemHeaderSshKey",
};
return this.i18nService.t(translation[type]);
}
delete = async () => {

View File

@@ -172,28 +172,28 @@ describe("ViewV2Component", () => {
params$.next({ cipherId: mockCipher.id });
flush(); // Resolve all promises
expect(component.headerText).toEqual("viewItemHeader typeLogin");
expect(component.headerText).toEqual("viewItemHeaderLogin");
// Set header text for a card
mockCipher.type = CipherType.Card;
params$.next({ cipherId: mockCipher.id });
flush(); // Resolve all promises
expect(component.headerText).toEqual("viewItemHeader typeCard");
expect(component.headerText).toEqual("viewItemHeaderCard");
// Set header text for an identity
mockCipher.type = CipherType.Identity;
params$.next({ cipherId: mockCipher.id });
flush(); // Resolve all promises
expect(component.headerText).toEqual("viewItemHeader typeIdentity");
expect(component.headerText).toEqual("viewItemHeaderIdentity");
// Set header text for a secure note
mockCipher.type = CipherType.SecureNote;
params$.next({ cipherId: mockCipher.id });
flush(); // Resolve all promises
expect(component.headerText).toEqual("viewItemHeader note");
expect(component.headerText).toEqual("viewItemHeaderNote");
}));
it("sends viewed event", fakeAsync(() => {

View File

@@ -194,18 +194,14 @@ export class ViewV2Component {
}
setHeader(type: CipherType) {
switch (type) {
case CipherType.Login:
return this.i18nService.t("viewItemHeader", this.i18nService.t("typeLogin"));
case CipherType.Card:
return this.i18nService.t("viewItemHeader", this.i18nService.t("typeCard"));
case CipherType.Identity:
return this.i18nService.t("viewItemHeader", this.i18nService.t("typeIdentity"));
case CipherType.SecureNote:
return this.i18nService.t("viewItemHeader", this.i18nService.t("note"));
case CipherType.SshKey:
return this.i18nService.t("viewItemHeader", this.i18nService.t("typeSshkey"));
}
const translation = {
[CipherType.Login]: "viewItemHeaderLogin",
[CipherType.Card]: "viewItemHeaderCard",
[CipherType.Identity]: "viewItemHeaderIdentity",
[CipherType.SecureNote]: "viewItemHeaderNote",
[CipherType.SshKey]: "viewItemHeaderSshKey",
};
return this.i18nService.t(translation[type]);
}
async getCipherData(id: string, userId: UserId) {

View File

@@ -134,7 +134,7 @@ describe("EmergencyViewDialogComponent", () => {
component["updateTitle"]();
expect(component["title"]).toBe("viewItemType typelogin");
expect(component["title"]).toBe("viewItemHeaderLogin");
});
it("sets card title", () => {
@@ -142,7 +142,7 @@ describe("EmergencyViewDialogComponent", () => {
component["updateTitle"]();
expect(component["title"]).toBe("viewItemType typecard");
expect(component["title"]).toBe("viewItemHeaderCard");
});
it("sets identity title", () => {
@@ -150,7 +150,7 @@ describe("EmergencyViewDialogComponent", () => {
component["updateTitle"]();
expect(component["title"]).toBe("viewItemType typeidentity");
expect(component["title"]).toBe("viewItemHeaderIdentity");
});
it("sets note title", () => {
@@ -158,7 +158,7 @@ describe("EmergencyViewDialogComponent", () => {
component["updateTitle"]();
expect(component["title"]).toBe("viewItemType note");
expect(component["title"]).toBe("viewItemHeaderNote");
});
});
});

View File

@@ -73,22 +73,20 @@ export class EmergencyViewDialogComponent {
};
private updateTitle() {
const partOne = "viewItemType";
const type = this.cipher.type;
switch (type) {
case CipherType.Login:
this.title = this.i18nService.t(partOne, this.i18nService.t("typeLogin").toLowerCase());
this.title = this.i18nService.t("viewItemHeaderLogin");
break;
case CipherType.Card:
this.title = this.i18nService.t(partOne, this.i18nService.t("typeCard").toLowerCase());
this.title = this.i18nService.t("viewItemHeaderCard");
break;
case CipherType.Identity:
this.title = this.i18nService.t(partOne, this.i18nService.t("typeIdentity").toLowerCase());
this.title = this.i18nService.t("viewItemHeaderIdentity");
break;
case CipherType.SecureNote:
this.title = this.i18nService.t(partOne, this.i18nService.t("note").toLowerCase());
this.title = this.i18nService.t("viewItemHeaderNote");
break;
}
}

View File

@@ -521,36 +521,39 @@ export class VaultItemDialogComponent implements OnInit, OnDestroy {
return await this.cipherService.decrypt(config.originalCipher, activeUserId);
}
private updateTitle() {
let partOne: string;
private updateTitle(): void {
const mode = this.formConfig.mode || this.params.mode;
const type = this.cipher?.type ?? this.formConfig.cipherType;
const translation: { [key: string]: { [key: number]: string } } = {
view: {
[CipherType.Login]: "viewItemHeaderLogin",
[CipherType.Card]: "viewItemHeaderCard",
[CipherType.Identity]: "viewItemHeaderIdentity",
[CipherType.SecureNote]: "viewItemHeaderNote",
[CipherType.SshKey]: "viewItemHeaderSshKey",
},
new: {
[CipherType.Login]: "newItemHeaderLogin",
[CipherType.Card]: "newItemHeaderCard",
[CipherType.Identity]: "newItemHeaderIdentity",
[CipherType.SecureNote]: "newItemHeaderNote",
[CipherType.SshKey]: "newItemHeaderSshKey",
},
edit: {
[CipherType.Login]: "editItemHeaderLogin",
[CipherType.Card]: "editItemHeaderCard",
[CipherType.Identity]: "editItemHeaderIdentity",
[CipherType.SecureNote]: "editItemHeaderNote",
[CipherType.SshKey]: "editItemHeaderSshKey",
},
};
if (this.params.mode === "view") {
partOne = "viewItemType";
} else if (this.formConfig.mode === "edit" || this.formConfig.mode === "partial-edit") {
partOne = "editItemHeader";
} else {
partOne = "newItemHeader";
}
const effectiveMode =
mode === "partial-edit" || mode === "edit" ? "edit" : translation[mode] ? mode : "new";
const type = this.cipher?.type ?? this.formConfig.cipherType ?? CipherType.Login;
const fullTranslation = translation[effectiveMode][type];
switch (type) {
case CipherType.Login:
this.title = this.i18nService.t(partOne, this.i18nService.t("typeLogin"));
break;
case CipherType.Card:
this.title = this.i18nService.t(partOne, this.i18nService.t("typeCard"));
break;
case CipherType.Identity:
this.title = this.i18nService.t(partOne, this.i18nService.t("typeIdentity"));
break;
case CipherType.SecureNote:
this.title = this.i18nService.t(partOne, this.i18nService.t("note"));
break;
case CipherType.SshKey:
this.title = this.i18nService.t(partOne, this.i18nService.t("typeSshKey"));
break;
}
this.title = this.i18nService.t(fullTranslation);
}
/**

View File

@@ -138,19 +138,15 @@ export class AddEditComponentV2 implements OnInit {
* @returns The header text.
*/
setHeader(mode: CipherFormMode, type: CipherType) {
const partOne = mode === "edit" || mode === "partial-edit" ? "editItemHeader" : "newItemHeader";
switch (type) {
case CipherType.Login:
return this.i18nService.t(partOne, this.i18nService.t("typeLogin").toLowerCase());
case CipherType.Card:
return this.i18nService.t(partOne, this.i18nService.t("typeCard").toLowerCase());
case CipherType.Identity:
return this.i18nService.t(partOne, this.i18nService.t("typeIdentity").toLowerCase());
case CipherType.SecureNote:
return this.i18nService.t(partOne, this.i18nService.t("note").toLowerCase());
case CipherType.SshKey:
return this.i18nService.t(partOne, this.i18nService.t("typeSshKey").toLowerCase());
}
const isEditMode = mode === "edit" || mode === "partial-edit";
const translation = {
[CipherType.Login]: isEditMode ? "editItemHeaderLogin" : "newItemHeaderLogin",
[CipherType.Card]: isEditMode ? "editItemHeaderCard" : "newItemHeaderCard",
[CipherType.Identity]: isEditMode ? "editItemHeaderIdentity" : "newItemHeaderIdentity",
[CipherType.SecureNote]: isEditMode ? "editItemHeaderNote" : "newItemHeaderNote",
[CipherType.SshKey]: isEditMode ? "editItemHeaderSshKey" : "newItemHeaderSshKey",
};
return this.i18nService.t(translation[type]);
}
/**

View File

@@ -194,15 +194,15 @@ export class ViewComponent implements OnInit {
switch (this.cipher.type) {
case CipherType.Login:
return this.i18nService.t("viewItemType", this.i18nService.t("typeLogin").toLowerCase());
return this.i18nService.t("viewItemHeaderLogin");
case CipherType.SecureNote:
return this.i18nService.t("viewItemType", this.i18nService.t("note").toLowerCase());
return this.i18nService.t("viewItemHeaderCard");
case CipherType.Card:
return this.i18nService.t("viewItemType", this.i18nService.t("typeCard").toLowerCase());
return this.i18nService.t("viewItemHeaderIdentity");
case CipherType.Identity:
return this.i18nService.t("viewItemType", this.i18nService.t("typeIdentity").toLowerCase());
return this.i18nService.t("viewItemHeaderNote");
case CipherType.SshKey:
return this.i18nService.t("viewItemType", this.i18nService.t("typeSshKey").toLowerCase());
return this.i18nService.t("viewItemHeaderSshKey");
default:
return null;
}

View File

@@ -734,32 +734,81 @@
"viewItem": {
"message": "View item"
},
"newItemHeader": {
"message": "New $TYPE$",
"placeholders": {
"type": {
"content": "$1",
"example": "login"
}
}
"newItemHeaderLogin": {
"message": "New Login",
"description": "Header for new login item type"
},
"editItemHeader": {
"message": "Edit $TYPE$",
"placeholders": {
"type": {
"content": "$1",
"example": "login"
}
}
"newItemHeaderCard": {
"message": "New Card",
"description": "Header for new card item type"
},
"viewItemType": {
"message": "View $ITEMTYPE$",
"placeholders": {
"itemtype": {
"content": "$1",
"example": "login"
}
}
"newItemHeaderIdentity": {
"message": "New Identity",
"description": "Header for new identity item type"
},
"newItemHeaderNote": {
"message": "New Note",
"description": "Header for new note item type"
},
"newItemHeaderSshKey": {
"message": "New SSH key",
"description": "Header for new SSH key item type"
},
"newItemHeaderTextSend": {
"message": "New Text Send",
"description": "Header for new text send"
},
"newItemHeaderFileSend": {
"message": "New File Send",
"description": "Header for new file send"
},
"editItemHeaderLogin": {
"message": "Edit Login",
"description": "Header for edit login item type"
},
"editItemHeaderCard": {
"message": "Edit Card",
"description": "Header for edit card item type"
},
"editItemHeaderIdentity": {
"message": "Edit Identity",
"description": "Header for edit identity item type"
},
"editItemHeaderNote": {
"message": "Edit Note",
"description": "Header for edit note item type"
},
"editItemHeaderSshKey": {
"message": "Edit SSH key",
"description": "Header for edit SSH key item type"
},
"editItemHeaderTextSend": {
"message": "Edit Text Send",
"description": "Header for edit text send"
},
"editItemHeaderFileSend": {
"message": "Edit File Send",
"description": "Header for edit file send"
},
"viewItemHeaderLogin": {
"message": "View Login",
"description": "Header for view login item type"
},
"viewItemHeaderCard": {
"message": "View Card",
"description": "Header for view card item type"
},
"viewItemHeaderIdentity": {
"message": "View Identity",
"description": "Header for view identity item type"
},
"viewItemHeaderNote": {
"message": "View Note",
"description": "Header for view note item type"
},
"viewItemHeaderSshKey": {
"message": "View SSH key",
"description": "Header for view SSH key item type"
},
"new": {
"message": "New",
@@ -10217,15 +10266,9 @@
"learnMoreAboutApi": {
"message": "Learn more about Bitwarden's API"
},
"fileSend": {
"message": "File Send"
},
"fileSends": {
"message": "File Sends"
},
"textSend": {
"message": "Text Send"
},
"textSends": {
"message": "Text Sends"
},