diff --git a/apps/browser/src/autofill/background/abstractions/overlay.background.ts b/apps/browser/src/autofill/background/abstractions/overlay.background.ts index 67eafdb0af83c..954e0698ae50c 100644 --- a/apps/browser/src/autofill/background/abstractions/overlay.background.ts +++ b/apps/browser/src/autofill/background/abstractions/overlay.background.ts @@ -260,6 +260,10 @@ export type InlineMenuListPortMessageHandlers = { message, port, }: PortOnMessageHandlerParams) => void; + fillAutofillInlineMenuCipherWithPaperField: ({ + message, + port, + }: PortOnMessageHandlerParams) => void; inlineMenuSearchContact: ({ message, port }: PortOnMessageHandlerParams) => void; saveFieldToCozyDoctype: ({ message, port }: PortOnMessageHandlerParams) => void; // Cozy customization end diff --git a/apps/browser/src/autofill/background/overlay.background.ts b/apps/browser/src/autofill/background/overlay.background.ts index 6c3f73f7d16b3..7600206df6a82 100644 --- a/apps/browser/src/autofill/background/overlay.background.ts +++ b/apps/browser/src/autofill/background/overlay.background.ts @@ -171,6 +171,8 @@ export class OverlayBackground implements OverlayBackgroundInterface { saveFieldToCozyDoctype: ({ message, port }) => this.saveFieldToCozyDoctype(message, port), fillAutofillInlineMenuCipherWithAmbiguousField: ({ message, port }) => this.fillAutofillInlineMenuCipherWithAmbiguousField(message, port), + fillAutofillInlineMenuCipherWithPaperField: ({ message, port }) => + this.fillAutofillInlineMenuCipherWithPaperField(message, port), inlineMenuSearchContact: ({ message }) => this.searchContacts(message), redirectToCozy: ({ message }) => this.redirectToCozy(message), handleMenuListUpdate: ({ message, port }) => this.handleMenuListUpdate(message, port), @@ -936,6 +938,15 @@ export class OverlayBackground implements OverlayBackgroundInterface { this.fillInlineMenuCipher(message, port, cozyAutofillOptions, fieldHtmlIDToFill); } + private async fillAutofillInlineMenuCipherWithPaperField( + message: OverlayPortMessage, + port: chrome.runtime.Port, + ) { + const { cozyAutofillOptions } = message; + + this.fillInlineMenuCipher(message, port, cozyAutofillOptions); + } + /** * @param inlineMenuCipherId - Cipher ID corresponding to the inlineMenuCiphers map. Does not correspond to the actual cipher's ID. * @param sender - The sender of the port message diff --git a/apps/browser/src/autofill/overlay/inline-menu/pages/list/autofill-inline-menu-list.ts b/apps/browser/src/autofill/overlay/inline-menu/pages/list/autofill-inline-menu-list.ts index b1bdf3bb1f78b..b40e0f273061d 100644 --- a/apps/browser/src/autofill/overlay/inline-menu/pages/list/autofill-inline-menu-list.ts +++ b/apps/browser/src/autofill/overlay/inline-menu/pages/list/autofill-inline-menu-list.ts @@ -544,13 +544,17 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement { const div = document.createElement("div"); div.classList.add("cipher-container"); + const cozyAutofillOptions = { + value, + }; + const fillButton = document.createElement("button"); fillButton.setAttribute("tabindex", "-1"); fillButton.classList.add("fill-cipher-button", "inline-menu-list-action"); fillButton.setAttribute("aria-label", contactName); fillButton.addEventListener( EVENTS.CLICK, - () => {}, // TODO + this.handleFillCipherPaperClickEvent(inlineMenuCipherId, cozyAutofillOptions, uniqueId()), ); const radio = document.createElement("input"); @@ -880,6 +884,27 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement { ); }; + /** + * @param inlineMenuCipherId + * @param cozyAutofillOptions + * @param UID + */ + private handleFillCipherPaperClickEvent = ( + inlineMenuCipherId: string, + cozyAutofillOptions: CozyAutofillOptions, + UID: string, + ) => { + return this.useEventHandlersMemo( + () => + this.postMessageToParent({ + command: "fillAutofillInlineMenuCipherWithPaperField", + inlineMenuCipherId, + cozyAutofillOptions, + }), + `${UID}-fill-cipher-button-click-handler`, + ); + }; + /** * Inline menu view that is presented when no ciphers are found for a given page. * Facilitates the ability to add a new vault item from the inline menu. diff --git a/apps/browser/src/autofill/services/autofill.service.ts b/apps/browser/src/autofill/services/autofill.service.ts index 5c8b7cca07d91..9402aef10a90f 100644 --- a/apps/browser/src/autofill/services/autofill.service.ts +++ b/apps/browser/src/autofill/services/autofill.service.ts @@ -1725,6 +1725,7 @@ export default class AutofillService implements AutofillServiceInterface { client, contactId: options.cipher.id, fieldQualifier: "paperIdentityCardNumber", + cozyAutofillOptions: options.cozyAutofillOptions, }); this.makeScriptActionWithValue( fillScript, @@ -1739,6 +1740,7 @@ export default class AutofillService implements AutofillServiceInterface { client, contactId: options.cipher.id, fieldQualifier: "paperPassportNumber", + cozyAutofillOptions: options.cozyAutofillOptions, }); this.makeScriptActionWithValue( fillScript, @@ -1753,6 +1755,7 @@ export default class AutofillService implements AutofillServiceInterface { client, contactId: options.cipher.id, fieldQualifier: "paperSocialSecurityNumber", + cozyAutofillOptions: options.cozyAutofillOptions, }); this.makeScriptActionWithValue( fillScript, @@ -1767,6 +1770,7 @@ export default class AutofillService implements AutofillServiceInterface { client, contactId: options.cipher.id, fieldQualifier: "paperResidencePermitNumber", + cozyAutofillOptions: options.cozyAutofillOptions, }); this.makeScriptActionWithValue( fillScript, @@ -1781,6 +1785,7 @@ export default class AutofillService implements AutofillServiceInterface { client, contactId: options.cipher.id, fieldQualifier: "paperDrivingLicenseNumber", + cozyAutofillOptions: options.cozyAutofillOptions, }); this.makeScriptActionWithValue( fillScript, @@ -1795,6 +1800,7 @@ export default class AutofillService implements AutofillServiceInterface { client, contactId: options.cipher.id, fieldQualifier: "paperVehicleRegistrationNumber", + cozyAutofillOptions: options.cozyAutofillOptions, }); this.makeScriptActionWithValue( fillScript, @@ -1809,6 +1815,7 @@ export default class AutofillService implements AutofillServiceInterface { client, contactId: options.cipher.id, fieldQualifier: "paperVehicleRegistrationConfidentialCode", + cozyAutofillOptions: options.cozyAutofillOptions, }); this.makeScriptActionWithValue( fillScript, @@ -1823,6 +1830,7 @@ export default class AutofillService implements AutofillServiceInterface { client, contactId: options.cipher.id, fieldQualifier: "paperVehicleRegistrationLicensePlateNumber", + cozyAutofillOptions: options.cozyAutofillOptions, }); this.makeScriptActionWithValue( fillScript, @@ -1837,6 +1845,7 @@ export default class AutofillService implements AutofillServiceInterface { client, contactId: options.cipher.id, fieldQualifier: "paperBankIbanNumber", + cozyAutofillOptions: options.cozyAutofillOptions, }); this.makeScriptActionWithValue( fillScript, @@ -1851,6 +1860,7 @@ export default class AutofillService implements AutofillServiceInterface { client, contactId: options.cipher.id, fieldQualifier: "paperBankBicNumber", + cozyAutofillOptions: options.cozyAutofillOptions, }); this.makeScriptActionWithValue( fillScript, @@ -1865,6 +1875,7 @@ export default class AutofillService implements AutofillServiceInterface { client, contactId: options.cipher.id, fieldQualifier: "paperGrossSalaryAmount", + cozyAutofillOptions: options.cozyAutofillOptions, }); this.makeScriptActionWithValue( fillScript, @@ -1879,6 +1890,7 @@ export default class AutofillService implements AutofillServiceInterface { client, contactId: options.cipher.id, fieldQualifier: "paperNetSalaryAmount", + cozyAutofillOptions: options.cozyAutofillOptions, }); this.makeScriptActionWithValue( fillScript, @@ -1893,6 +1905,7 @@ export default class AutofillService implements AutofillServiceInterface { client, contactId: options.cipher.id, fieldQualifier: "paperTaxNoticeNumber", + cozyAutofillOptions: options.cozyAutofillOptions, }); this.makeScriptActionWithValue( fillScript, @@ -1911,6 +1924,7 @@ export default class AutofillService implements AutofillServiceInterface { me: options.cipher.contact.me, field: paperTaxNoticeRefTaxIncomeFillField, fieldQualifier: "paperTaxNoticeRefTaxIncome", + cozyAutofillOptions: options.cozyAutofillOptions, filterName: "yearFilter", }); this.makeScriptActionWithValue( diff --git a/libs/cozy/getCozyValue.spec.ts b/libs/cozy/getCozyValue.spec.ts index d3524f4b7e405..3538edcbd1865 100644 --- a/libs/cozy/getCozyValue.spec.ts +++ b/libs/cozy/getCozyValue.spec.ts @@ -1,6 +1,8 @@ +import { IOCozyFile } from "cozy-client/types/types"; + import { CozyAutofillOptions } from "../../apps/browser/src/autofill/services/abstractions/autofill.service"; -import { selectDataWithCozyProfile } from "./getCozyValue"; +import { selectPaper, selectDataWithCozyProfile } from "./getCozyValue"; // PROFILES @@ -129,3 +131,66 @@ describe("getCozyValue", () => { }); }); }); + +const RIB1 = { + _id: "b4698ba56c7d0ae2faeb9571d4e0ce60", + _type: "io.cozy.files", + name: "RIB 1 - Bob John Doe.pdf", + metadata: { + bicNumber: "BIC99999999", + datetime: "2024-09-12T09:24:59.000Z", + datetimeLabel: "datetime", + number: "FR9999999999999999999999999", + qualification: { + icon: "bank-check", + label: "bank_details", + purpose: "attestation", + sourceCategory: "bank", + subjects: ["bank_account"], + }, + }, +} as unknown as IOCozyFile; + +const RIB2 = { + _id: "6bfca732cd8f258cde5b012f3b48dd67", + _type: "io.cozy.files", + name: "RIB 2 - Bob John Doe.pdf", + metadata: { + bicNumber: "BIC11111111", + datetime: "2024-07-25T10:13:17.000Z", + datetimeLabel: "datetime", + number: "FR1111111111111111111111111", + qualification: { + icon: "bank-check", + label: "bank_details", + purpose: "attestation", + sourceCategory: "bank", + subjects: ["bank_account"], + }, + }, +} as unknown as IOCozyFile; + +describe("getCozyValue", () => { + describe("selectPaper", () => { + it("should return the corresponding paper if it exists", () => { + const selectedPaper = selectPaper({ + papers: [RIB1, RIB2], + cozyAutofillOptions: { + value: "FR1111111111111111111111111", + }, + }); + + // Add your assertions here + expect(selectedPaper).toEqual(RIB2); + }); + + it("should return the first paper if no corresponding paper exists", () => { + const selectedPaper = selectPaper({ + papers: [RIB1, RIB2], + cozyAutofillOptions: { value: "non-existing-value" }, + }); + + expect(selectedPaper).toEqual(RIB1); + }); + }); +}); diff --git a/libs/cozy/getCozyValue.ts b/libs/cozy/getCozyValue.ts index c2789b93d3b2c..45d928c18aca4 100644 --- a/libs/cozy/getCozyValue.ts +++ b/libs/cozy/getCozyValue.ts @@ -1,6 +1,6 @@ import CozyClient, { Q } from "cozy-client"; import { IOCozyFile } from "cozy-client/types/types"; -import _ from "lodash"; +import * as _ from "lodash"; import { AutofillFieldQualifierType } from "../../apps/browser/src/autofill/enums/autofill-field.enums"; import AutofillField from "../../apps/browser/src/autofill/models/autofill-field"; @@ -98,6 +98,7 @@ const getCozyValueInPaper = async ({ contactEmail, me, cozyAttributeModel, + cozyAutofillOptions, field, filterName, }: GetCozyValueInDataType) => { @@ -115,7 +116,40 @@ const getCozyValueInPaper = async ({ filteredPapers = filteredPapers.filter(yearFilterFunction); } - return _.get(filteredPapers[0], cozyAttributeModel.path); + // Select the paper corresponding to the cozyAutofillOptions or the first one + const selectedPaper = selectPaper({ + papers: filteredPapers, + cozyAutofillOptions, + }); + + return _.get(selectedPaper, cozyAttributeModel.path); +}; + +export const selectPaper = ({ + papers, + cozyAutofillOptions, +}: { + papers: IOCozyFile[]; + cozyAutofillOptions?: CozyAutofillOptions; +}) => { + const papersModels = Object.values(COZY_ATTRIBUTES_MAPPING).filter( + (model) => model.doctype === "io.cozy.files", + ); + + // Example: If we click on a BIC of value "BIC111111", we look in the papers + // for the paper that have "BIC111111" as a value so that we can also + // find the IBAN corresponding to the BIC + const correspondingPaper = papers.find((paper) => { + for (const paperModel of papersModels) { + if (_.get(paper, paperModel.path) === cozyAutofillOptions?.value) { + return true; + } + } + + return false; + }); + + return correspondingPaper || papers[0]; }; export const getAllPapersFromContact = async ({