Skip to content

Commit

Permalink
feat: Create and autofill address fields in inline-menu
Browse files Browse the repository at this point in the history
WIP
  • Loading branch information
Merkur39 committed Sep 27, 2024
1 parent d36e4a5 commit aff3adb
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 61 deletions.
30 changes: 25 additions & 5 deletions apps/browser/src/autofill/background/overlay.background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ import { createOrUpdateCozyDoctype } from "../../../../../libs/cozy/createOrUpda
import { getCozyValue, getAllPapersFromContact } from "../../../../../libs/cozy/getCozyValue";
import _ from "lodash";
import { FILES_DOCTYPE } from "../../../../../libs/cozy/constants";
import { cleanFormattedAddress } from "../../../../../libs/cozy/contact.helper";
/* eslint-enable */
/* end Cozy imports */

Expand Down Expand Up @@ -1021,7 +1022,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
}

private async saveFieldToCozyDoctype(message: OverlayPortMessage, port: chrome.runtime.Port) {
const { inlineMenuCipherId, fieldQualifier, newAutofillValue, fieldHtmlIDToFill } = message;
const { inlineMenuCipherId, fieldQualifier, data, fieldHtmlIDToFill } = message;

if (inlineMenuCipherId) {
const client = await this.cozyClientService.getClientInstance();
Expand All @@ -1030,13 +1031,32 @@ export class OverlayBackground implements OverlayBackgroundInterface {
await createOrUpdateCozyDoctype({
client,
cipher,
fieldQualifier,
newAutofillValue,
data,
i18nService: this.i18nService,
logService: this.logService,
});

const isAddressData = Object.keys(data).includes("street");

this.fillInlineMenuCipher(message, port, {
...newAutofillValue,
fillOnlyThisFieldHtmlID: fieldHtmlIDToFill,
value: isAddressData
? cleanFormattedAddress(data)
: data[COZY_ATTRIBUTES_MAPPING[fieldQualifier].name],
type: data.type,
label: data.label,
...(fieldQualifier ? data : {}),
...(fieldHtmlIDToFill ? { fillOnlyThisFieldHtmlID: fieldHtmlIDToFill } : {}),
...(!fieldQualifier
? {
fillOnlyTheseFieldQualifiers: [
"identityAddress1",
"identityCity",
"identityCountry",
"identityPostalCode",
"identityState",
],
}
: {}),
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { AutofillInlineMenuPageElement } from "../shared/autofill-inline-menu-pa
/* start Cozy imports */
/* eslint-disable */
import uniqueId from "lodash/uniqueId";
import set from "lodash/set";
import { AutofillFieldQualifierType } from "src/autofill/enums/autofill-field.enums";
import {
AmbiguousContactFields,
Expand Down Expand Up @@ -148,6 +149,7 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement {
iconElement.classList.add("contact-edit-icon");
inputTextContainer.appendChild(iconElement);

const allData = [];
for (const field of addressFieldsPrimary) {
const labelGroup = document.createElement("div");
labelGroup.classList.add("contact-edit-input-label-group");
Expand All @@ -163,6 +165,8 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement {

labelGroup.appendChild(inputText);
inputTextContainer.appendChild(labelGroup);

allData.push({ [field]: inputText });
}
editContainer.appendChild(inputTextContainer);

Expand Down Expand Up @@ -204,6 +208,8 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement {

labelGroup.appendChild(inputText);
inputTextContainer2.appendChild(labelGroup);

allData.push({ [subField]: inputText });
}
editContainer.appendChild(inputTextContainer2);

Expand All @@ -220,7 +226,13 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement {
divider.classList.add("contact-edit-divider");

// TODO - Add the buttons
// const buttons = this.editContactButtons(inlineMenuCipherId);
const buttons = this.editContactButtons(
inlineMenuCipherId,
undefined,
undefined,
selectElement,
allData,
);

// Necessary for the bottom margin of “buttons” to be interpreted
const necessaryStyleElement = document.createElement("div");
Expand All @@ -230,7 +242,7 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement {
this.inlineMenuListContainer.appendChild(editContainer);
this.inlineMenuListContainer.appendChild(divider);
// TODO - Add the buttons
// this.inlineMenuListContainer.appendChild(buttons);
this.inlineMenuListContainer.appendChild(buttons);
this.inlineMenuListContainer.appendChild(necessaryStyleElement);
}

Expand Down Expand Up @@ -296,8 +308,9 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement {
const buttons = this.editContactButtons(
inlineMenuCipherId,
fieldHtmlIDToFill,
inputText,
this.fieldQualifier,
selectElement,
[{ [COZY_ATTRIBUTES_MAPPING[this.fieldQualifier].name]: inputText }],
);

// Necessary for the bottom margin of “buttons” to be interpreted
Expand All @@ -320,9 +333,10 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement {

private editContactButtons(
inlineMenuCipherId: string,
fieldHtmlIDToFill: string,
inputText?: HTMLInputElement,
fieldHtmlIDToFill?: string,
fieldQualifier?: string,
selectElement?: HTMLSelectElement | null,
allData?: { [key: string]: HTMLInputElement }[],
) {
const buttonContainer = document.createElement("div");
buttonContainer.classList.add("contact-edit-buttons");
Expand All @@ -338,18 +352,29 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement {
saveButton.textContent = this.getTranslation("save");
saveButton.classList.add("contact-edit-button", "contact-edit-button-save");
saveButton.addEventListener(EVENTS.CLICK, () => {
if (!inputText?.value) {
const hasValue = allData?.some((data) => Object.values(data).some((d) => d?.value));
if (!hasValue) {
return;
}
const newAutofillValue: AutofillValue = {
value: inputText.value,
...(selectElement && JSON.parse(selectElement.value)),
};

let newData = allData.reduce((acc, data) => {
const key = Object.keys(data)[0];
set(acc, key, data[key].value);
return acc;
}, {});

if (selectElement) {
newData = {
...newData,
...(selectElement && JSON.parse(selectElement.value)),
};
}

this.handleSaveContactCipherEvent(
inlineMenuCipherId,
fieldHtmlIDToFill,
this.fieldQualifier,
newAutofillValue,
fieldQualifier,
newData,
);
});

Expand All @@ -363,13 +388,13 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement {
inlineMenuCipherId: string,
fieldHtmlIDToFill: string,
fieldQualifier: string,
newAutofillValue: AutofillValue,
data: any,
) => {
return this.postMessageToParent({
command: "saveFieldToCozyDoctype",
inlineMenuCipherId,
fieldQualifier,
newAutofillValue,
data,
fieldHtmlIDToFill,
});
};
Expand Down
68 changes: 68 additions & 0 deletions libs/cozy/contact.helper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import CozyClient, { models } from "cozy-client";
import { IOCozyContact } from "cozy-client/types/types";
import get from "lodash/get";
import set from "lodash/set";

import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
Expand Down Expand Up @@ -141,3 +143,69 @@ export const generateIdentityViewFromContactId = async (

return identity;
};

export const cleanFormattedAddress = (address: { [key: string]: string }) => {
const formattedAddress = `${address.number} ${address.street}, ${address.code} ${address.city}, ${address.country}`;
// Replace all spaces by one space, to fix cases where there are multiple spaces
// Replace commas that have a space before
// And remove all spaces before & after the string
let formattedAddressClean = formattedAddress.replace(/\s+/g, " ").replace(/\s,/g, "").trim();

// Case where a comma is the last character
if (formattedAddressClean.lastIndexOf(",") === formattedAddressClean.length - 1) {
formattedAddressClean = formattedAddressClean.slice(0, formattedAddressClean.length - 1);
}

// Case where a comma is the first character
if (formattedAddressClean.indexOf(",") === 0) {
formattedAddressClean = formattedAddressClean.slice(1);
}

return formattedAddressClean;
};

export const hasExtendedAddress = (addressField: any) => {
// TODO typer addressField
if (!addressField) {
return false;
}
const extendedAddressKeys = ["locality", "building", "stairs", "floor", "apartment", "entrycode"];
return Object.keys(addressField).some((ext) => extendedAddressKeys.includes(ext));
};

export const createOrUpdateCozyContactAddress = (
contact: IOCozyContact,
path: string,
data: any,
) => {
const arrayData = get(contact, path) || [];
const formattedAddress = cleanFormattedAddress(data);

const cozyAddress = {
primary: !arrayData.length,
formattedAddress,
...(data.number && { number: data.number }),
...(data.street && { street: data.street }),
...(data.code && { code: data.code }),
...(data.city && { city: data.city }),
...(data.region && { region: data.region }),
...(data.country && { country: data.country }),
...(data.label && { label: data.label }),
...(data.type && { type: data.type }),
...(hasExtendedAddress(data) && {
extendedAddress: {
...(data.locality && { locality: data.locality }),
...(data.building && { building: data.building }),
...(data.stairs && { stairs: data.stairs }),
...(data.floor && { floor: data.floor }),
...(data.apartment && { apartment: data.apartment }),
...(data.entrycode && { entrycode: data.entrycode }),
},
}),
};
arrayData.push(cozyAddress);

set(contact, path, arrayData);

return contact;
};
Loading

0 comments on commit aff3adb

Please sign in to comment.