Skip to content

Commit

Permalink
[Release] Stage to Main (#2722)
Browse files Browse the repository at this point in the history
  • Loading branch information
milo-pr-merge[bot] authored Aug 13, 2024
2 parents 3abbe4d + 60cb005 commit 0b80fa1
Show file tree
Hide file tree
Showing 12 changed files with 407 additions and 126 deletions.
93 changes: 55 additions & 38 deletions libs/blocks/marketo/marketo.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,20 @@ const ROOT_MARGIN = 1000;
const FORM_ID = 'form id';
const BASE_URL = 'marketo host';
const MUNCHKIN_ID = 'marketo munckin';
const SUCCESS_TYPE = 'form.success.type';
const SUCCESS_CONTENT = 'form.success.content';
const SUCCESS_SECTION = 'form.success.section';
const FORM_MAP = {
'destination-url': 'form.success.content',
'success-type': SUCCESS_TYPE,
'destination-type': SUCCESS_TYPE,
'success-content': SUCCESS_CONTENT,
'destination-url': SUCCESS_CONTENT,
'success-section': SUCCESS_SECTION,
'co-partner-names': 'program.copartnernames',
'sfdc-campaign-id': 'program.campaignids.sfdc',
};

export const formValidate = (form) => {
const formEl = form.getFormElem().get(0);
export const formValidate = (formEl) => {
formEl.classList.remove('hide-errors');
formEl.classList.add('show-warnings');
};
Expand Down Expand Up @@ -61,9 +67,24 @@ export const decorateURL = (destination, baseURL = window.location) => {
return null;
};

export const formSuccess = (form) => {
const formEl = form.getFormElem().get(0);
const parentModal = formEl.closest('.dialog-modal');
const setPreference = (key = '', value = '') => {
if (!value || !key.includes('.')) return;
const keyParts = key.split('.');
const lastKey = keyParts.pop();
const formDataObject = keyParts.reduce((obj, part) => {
obj[part] = obj[part] || {};
return obj[part];
}, window.mcz_marketoForm_pref);
formDataObject[lastKey] = value;
};

export const setPreferences = (formData) => {
window.mcz_marketoForm_pref = window.mcz_marketoForm_pref || {};
Object.entries(formData).forEach(([key, value]) => setPreference(key, value));
};

export const formSuccess = (formEl, formData) => {
const parentModal = formEl?.closest('.dialog-modal');
const mktoSubmit = new Event('mktoSubmit');

window.dispatchEvent(mktoSubmit);
Expand All @@ -76,10 +97,23 @@ export const formSuccess = (form) => {
return false;
}

return true;
if (formData?.[SUCCESS_TYPE] !== 'section') return true;

try {
const section = formData[SUCCESS_SECTION].toLowerCase().replaceAll(' ', '-');
const success = document.querySelector(`.section.${section}`);
success.classList.remove('hide-block');
success.scrollIntoView({ behavior: 'smooth' });
setPreference(SUCCESS_TYPE, 'message');
} catch (e) {
/* c8 ignore next 2 */
window.lana?.log('Error showing Marketo success section', { tags: 'errorType=warn,module=marketo' });
}

return false;
};

const readyForm = (form) => {
const readyForm = (form, formData) => {
const formEl = form.getFormElem().get(0);
const isDesktop = matchMedia('(min-width: 900px)');

Expand All @@ -95,58 +129,42 @@ const readyForm = (form) => {
const offsetPosition = targetPosition + window.pageYOffset - pageTop - window.innerHeight / 2;
window.scrollTo(0, offsetPosition);
}, true);
form.onValidate(() => formValidate(form));
form.onSuccess(() => formSuccess(form));
};

const setPreference = (key, value) => {
if (value && key?.includes('.')) {
const keyParts = key.split('.');
const lastKey = keyParts.pop();
const formDataObject = keyParts.reduce((obj, part) => {
obj[part] = obj[part] || {};
return obj[part];
}, window.mcz_marketoForm_pref);
formDataObject[lastKey] = value;
}
};

export const setPreferences = (formData) => {
window.mcz_marketoForm_pref = window.mcz_marketoForm_pref || {};
Object.entries(formData).forEach(([key, value]) => setPreference(key, value));
form.onValidate(() => formValidate(formEl));
form.onSuccess(() => formSuccess(formEl, formData));
};

export const loadMarketo = (el, formData) => {
const baseURL = formData[BASE_URL];
const munchkinID = formData[MUNCHKIN_ID];
const formID = formData[FORM_ID];

loadScript(`https://${baseURL}/js/forms2/js/forms2.min.js`)
.then(() => {
const { MktoForms2 } = window;
if (!MktoForms2) throw new Error('Marketo forms not loaded');

MktoForms2.loadForm(`//${baseURL}`, formData[MUNCHKIN_ID], formData[FORM_ID]);
MktoForms2.loadForm(`//${baseURL}`, munchkinID, formID);
MktoForms2.whenReady((form) => { readyForm(form, formData); });
})
.catch(() => {
/* c8 ignore next */
/* c8 ignore next 2 */
el.style.display = 'none';
window.lana?.log(`Error loading Marketo form for ${munchkinID}_${formID}`, { tags: 'errorType=error,module=marketo' });
});
};

export default function init(el) {
const children = Array.from(el.querySelectorAll(':scope > div'));
const encodedConfigDiv = children.shift();
const link = encodedConfigDiv.querySelector('a');
let formData = {};

if (!link?.href) {
el.style.display = 'none';
return;
}

const encodedConfig = link.href.split('#')[1];

formData = parseEncodedConfig(encodedConfig);
const formData = parseEncodedConfig(encodedConfig);

children.forEach((element) => {
const key = element.children[0]?.textContent.trim().toLowerCase().replaceAll(' ', '-');
Expand All @@ -168,13 +186,12 @@ export default function init(el) {
return;
}

if (formData['form.success.content']) {
const destinationUrl = decorateURL(formData['form.success.content']);
formData[SUCCESS_TYPE] = formData[SUCCESS_TYPE] || 'redirect';

if (destinationUrl) {
formData['form.success.type'] = 'redirect';
formData['form.success.content'] = destinationUrl;
}
if (formData[SUCCESS_TYPE] === 'redirect') {
const destinationUrl = decorateURL(formData[SUCCESS_CONTENT]);

if (destinationUrl) formData[SUCCESS_CONTENT] = destinationUrl;
}

setPreferences(formData);
Expand Down
60 changes: 48 additions & 12 deletions libs/blocks/merch/merch.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,28 +192,48 @@ export async function fetchCheckoutLinkConfigs(base = '') {
?? fetch(`${base}${CHECKOUT_LINK_CONFIG_PATH}`).catch((e) => {
log?.error('Failed to fetch checkout link configs', e);
}).then((mappings) => {
if (!mappings?.ok) return undefined;
if (!mappings?.ok) return { data: [] };
return mappings.json();
});
return fetchCheckoutLinkConfigs.promise;
}

export async function getCheckoutLinkConfig(productFamily) {
export async function getCheckoutLinkConfig(productFamily, productCode, paCode) {
let { base } = getConfig();
if (/\.page$/.test(document.location.origin)) {
/* c8 ignore next 2 */
base = base.replace('.live', '.page');
}
const checkoutLinkConfigs = await fetchCheckoutLinkConfigs(base);
if (!checkoutLinkConfigs.data.length) return undefined;
const { locale: { region } } = getConfig();
const productFamilyConfigs = checkoutLinkConfigs.data?.filter(
({ [NAME_PRODUCT_FAMILY]: mappingProductFamily }) => mappingProductFamily === productFamily,
);
if (productFamilyConfigs.length === 0) return undefined;
const checkoutLinkConfig = productFamilyConfigs.find(

const {
paCodeConfigs,
productCodeConfigs,
productFamilyConfigs,
} = checkoutLinkConfigs.data.reduce((acc, config) => {
if (config[NAME_PRODUCT_FAMILY] === paCode) {
acc.paCodeConfigs.push(config);
} else if (config[NAME_PRODUCT_FAMILY] === productCode) {
acc.productCodeConfigs.push(config);
} else if (config[NAME_PRODUCT_FAMILY] === productFamily) {
acc.productFamilyConfigs.push(config);
}
return acc;
}, { paCodeConfigs: [], productCodeConfigs: [], productFamilyConfigs: [] });

// helps to fallback to product family config
// if no locale specific config is found below.
const productCheckoutLinkConfigs = [
...paCodeConfigs, ...productCodeConfigs, ...productFamilyConfigs,
];

if (!productCheckoutLinkConfigs.length) return undefined;
const checkoutLinkConfig = productCheckoutLinkConfigs.find(
({ [NAME_LOCALE]: locale }) => locale === '',
);
const checkoutLinkConfigOverride = productFamilyConfigs.find(
const checkoutLinkConfigOverride = productCheckoutLinkConfigs.find(
({ [NAME_LOCALE]: locale }) => locale === region,
) ?? {};
const overrides = Object.fromEntries(
Expand All @@ -231,14 +251,22 @@ export async function getCheckoutLinkConfig(productFamily) {
export async function getDownloadAction(
options,
imsSignedInPromise,
[{ offerType, productArrangement: { productFamily: offerFamily } = {} }],
[{
offerType,
productArrangementCode,
productArrangement: { productCode, productFamily: offerFamily } = {},
}],
) {
if (options.entitlement !== true) return undefined;
const loggedIn = await imsSignedInPromise;
if (!loggedIn) return undefined;
const entitlements = await fetchEntitlements();
if (!entitlements?.length) return undefined;
const checkoutLinkConfig = await getCheckoutLinkConfig(offerFamily);
const checkoutLinkConfig = await getCheckoutLinkConfig(
offerFamily,
productCode,
productArrangementCode,
);
if (!checkoutLinkConfig?.DOWNLOAD_URL) return undefined;
const offer = entitlements.find((
{ offer: { product_arrangement: { family: subscriptionFamily } } },
Expand Down Expand Up @@ -355,9 +383,17 @@ export async function openModal(e, url, offerType) {
}

export async function getModalAction(offers, options) {
const [{ offerType, productArrangement: { productFamily: offerFamily } = {} }] = offers ?? [{}];
const [{
offerType,
productArrangementCode,
productArrangement: { productCode, productFamily: offerFamily } = {},
}] = offers ?? [{}];
if (options.modal !== true) return undefined;
const checkoutLinkConfig = await getCheckoutLinkConfig(offerFamily);
const checkoutLinkConfig = await getCheckoutLinkConfig(
offerFamily,
productCode,
productArrangementCode,
);
if (!checkoutLinkConfig) return undefined;
const columnName = (offerType === OFFER_TYPE_TRIAL) ? FREE_TRIAL_PATH : BUY_NOW_PATH;
let url = checkoutLinkConfig[columnName];
Expand Down
43 changes: 24 additions & 19 deletions libs/features/personalization/personalization.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,21 +169,19 @@ const fetchData = async (url, type = DATA_TYPE.JSON) => {
return null;
};

const getBlockProps = (fVal) => {
const getBlockProps = (fVal, miloLibs, origin) => {
let val = fVal;
if (val?.includes('\\')) val = val?.split('\\').join('/');
if (!val?.startsWith('/')) val = `/${val}`;
const blockSelector = val?.split('/').pop();
const { origin } = PAGE_URL;
if (origin.includes('.hlx.') || origin.includes('localhost')) {
if (val.startsWith('/libs/')) {
/* c8 ignore next 2 */
const { miloLibs, codeRoot } = getConfig();
val = `${miloLibs || codeRoot}${val.replace('/libs', '')}`;
} else {
val = `${origin}${val}`;
}

if (val.startsWith('/libs/')) {
/* c8 ignore next 1 */
val = `${miloLibs}${val.replace('/libs', '')}`;
} else {
val = `${origin}${val}`;
}

return { blockSelector, blockTarget: val };
};

Expand Down Expand Up @@ -457,6 +455,7 @@ const getVariantInfo = (line, variantNames, variants, manifestPath, manifestOver
if (pageFilter && !matchGlob(pageFilter, new URL(window.location).pathname)) return;

if (!config.mep?.preview) manifestId = false;
const { origin } = PAGE_URL;
variantNames.forEach((vn) => {
const targetManifestId = vn.startsWith(TARGET_EXP_PREFIX) ? targetId : false;
if (!line[vn] || line[vn].toLowerCase() === 'false') return;
Expand All @@ -483,7 +482,7 @@ const getVariantInfo = (line, variantNames, variants, manifestPath, manifestOver
variants[vn][action] = variants[vn][action] || [];

if (action === 'useblockcode') {
const { blockSelector, blockTarget } = getBlockProps(line[vn]);
const { blockSelector, blockTarget } = getBlockProps(line[vn], config.miloLibs, origin);
variants[vn][action].push({
selector: blockSelector,
val: blockTarget,
Expand Down Expand Up @@ -578,20 +577,26 @@ const checkForParamMatch = (paramStr) => {
return false;
};

function trimNames(arr) {
return arr.map((v) => v.trim()).filter(Boolean);
}
export function buildVariantInfo(variantNames) {
return variantNames.reduce((acc, name) => {
let nameArr = [name];
if (!name.startsWith(TARGET_EXP_PREFIX)) nameArr = name.split(',');
acc[name] = trimNames(nameArr);
acc.allNames = [...acc.allNames, ...trimNames(name.split(/[,&]|\bnot\b/))];
return acc;
}, { allNames: [] });
}

async function getPersonalizationVariant(manifestPath, variantNames = [], variantLabel = null) {
const config = getConfig();
if (config.mep?.variantOverride?.[manifestPath]) {
return config.mep.variantOverride[manifestPath];
}

const variantInfo = variantNames.reduce((acc, name) => {
let nameArr = [name];
if (!name.startsWith(TARGET_EXP_PREFIX)) nameArr = name.split(',');
const vNames = nameArr.map((v) => v.trim()).filter(Boolean);
acc[name] = vNames;
acc.allNames = [...acc.allNames, ...vNames];
return acc;
}, { allNames: [] });
const variantInfo = buildVariantInfo(variantNames);

const entitlementKeys = Object.values(await getEntitlementMap());
const hasEntitlementTag = entitlementKeys.some((tag) => variantInfo.allNames.includes(tag));
Expand Down
Loading

0 comments on commit 0b80fa1

Please sign in to comment.