Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MWPW-164660: [3-in-1][Milo] Implement a link converter for CTAs using an iFrame #3564

Open
wants to merge 8 commits into
base: stage
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
trigger,
closeAllDropdowns,
logErrorFor,
lanaLog,
} from '../../utilities/utilities.js';
import { replaceKeyArray } from '../../../../features/placeholders.js';
import { getConfig } from '../../../../utils/utils.js';
Expand All @@ -31,12 +30,11 @@ class Search {
this.icon = config.icon;
this.trigger = config.trigger;
this.parent = this.trigger.closest('.feds-nav-wrapper');
lanaLog({ message: `Search integrated on URL : ${window.location.href}`, tags: 'gnav-search', errorType: 'info' });
const observer = new MutationObserver(() => {
this.clearSearchForm();
});
observer.observe(this.trigger, { attributeFilter: ['aria-expanded'] });
logErrorFor(this.init.bind(this), 'Search init has failed', 'gnav-search', 'error');
logErrorFor(this.init.bind(this), 'Search init has failed', 'errorType=error,module=gnav-search');
}

async init() {
Expand Down
20 changes: 20 additions & 0 deletions libs/blocks/merch/merch.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,26 @@ a[is='checkout-link'].con-button > span {
content: "\00a0";
}

.three-in-one {
display: flex;
height: 100%;
}

.three-in-one .loading iframe {
visibility: hidden;
}

.three-in-one sp-theme {
height: 100%;
width: 100%;
align-content: center;
}

.three-in-one sp-theme sp-progress-circle {
inset-inline-start: 50%;
transform: translate(-50%);
}

@media (max-width: 1199px) {
#checkout-link-modal {
height: 100vh;
Expand Down
31 changes: 11 additions & 20 deletions libs/blocks/merch/merch.js
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ async function openExternalModal(url, getModal, extraOptions) {

const isInternalModal = (url) => /\/fragments\//.test(url);

export async function openModal(e, url, offerType, hash, extraOptions) {
export async function openModal(e, url, offerType, hash, extraOptions, el) {
e.preventDefault();
e.stopImmediatePropagation();
const { getModal } = await import('../modal/modal.js');
Expand All @@ -489,14 +489,18 @@ export async function openModal(e, url, offerType, hash, extraOptions) {
const prevHash = window.location.hash.replace('#', '') === hash ? '' : window.location.hash;
window.location.hash = hash;
window.addEventListener('milo:modal:closed', () => {
window.history.pushState({}, document.title, `#${prevHash}`);
window.history.pushState({}, document.title, prevHash !== '' ? `#${prevHash}` : `${window.location.pathname}${window.location.search}`);
}, { once: true });
}
if (isInternalModal(url)) {
const fragmentPath = url.split(/(hlx|aem).(page|live)/).pop();
modal = await openFragmentModal(fragmentPath, getModal);
} else if (el?.opens3in1Modal) {
const { default: openThreeInOneModal, handle3in1IFrameEvents } = await import('./three-in-one.js');
window.addEventListener('message', handle3in1IFrameEvents);
modal = await openThreeInOneModal(el);
} else {
modal = await openExternalModal(url, getModal, extraOptions);
modal = await openExternalModal(url, getModal, extraOptions, el);
}
if (modal) {
modal.classList.add(offerTypeClass);
Expand Down Expand Up @@ -539,7 +543,10 @@ export async function getModalAction(offers, options, el) {
if (!url) return undefined;
url = isInternalModal(url) || isProdModal(url)
? localizeLink(checkoutLinkConfig[columnName]) : checkoutLinkConfig[columnName];
return { url, handler: (e) => openModal(e, url, offerType, hash, options.extraOptions) };
return {
url,
handler: (e) => openModal(e, url, offerType, hash, options.extraOptions, el),
};
}

export async function getCheckoutAction(offers, options, imsSignedInPromise, el) {
Expand Down Expand Up @@ -760,19 +767,3 @@ export default async function init(el) {
log.warn('Failed to get context:', { el });
return null;
}

export async function handleHashChange() {
const modalDialog = document.querySelector('.dialog-modal');
if (window.location.hash) {
const modalId = window.location.hash.replace('#', '');
const cta = document.querySelector(`.con-button[data-modal-id="${modalId}"]`);
if (!modalDialog) {
reopenModal(cta);
}
} else if (modalDialog) {
const { closeModal } = await import('../modal/modal.js');
closeModal(modalDialog);
}
}

window.addEventListener('hashchange', handleHashChange);
82 changes: 82 additions & 0 deletions libs/blocks/merch/three-in-one.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/* eslint-disable import/no-relative-packages */
import { createTag } from '../../utils/utils.js';
import { MODAL_TYPE_3_IN_1 } from '../../deps/mas/constants.js';
import '../../features/spectrum-web-components/dist/theme.js';
import '../../features/spectrum-web-components/dist/progress-circle.js';

export const MSG_SUBTYPE = {
AppLoaded: 'AppLoaded',
EXTERNAL: 'EXTERNAL',
SWITCH: 'SWITCH',
RETURN_BACK: 'RETURN_BACK',
OrderComplete: 'OrderComplete',
Error: 'Error',
Close: 'Close',
};

export const LANA_OPTIONS = {
clientId: 'merch-at-scale',
sampleRate: 10,
tags: 'three-in-one',
};

export const handle3in1IFrameEvents = ({ data: msgData }) => {
let parsedMsg = null;
try {
parsedMsg = JSON.parse(msgData);
} catch (error) {
return;
}
const { app, subType, data } = parsedMsg || {};
if (app !== 'ucv3') return;
window.lana?.log(`3-in-1 modal: ${subType}`, LANA_OPTIONS);
const threeInOne = document.querySelector('.three-in-one');
const closeBtn = threeInOne?.querySelector('.dialog-close');
if (!threeInOne) return;
switch (subType) {
case MSG_SUBTYPE.AppLoaded:
threeInOne.querySelector('iframe')?.classList.remove('loading');
threeInOne.querySelector('sp-theme')?.remove();
if (closeBtn) {
closeBtn.setAttribute('aria-hidden', 'true');
closeBtn.style.opacity = '0';
}
break;
case MSG_SUBTYPE.EXTERNAL:
case MSG_SUBTYPE.SWITCH:
case MSG_SUBTYPE.RETURN_BACK:
if (data?.externalUrl && data.target) {
window.open(data.externalUrl, data.target);
}
break;
case MSG_SUBTYPE.Close:
document.querySelector('.dialog-modal.three-in-one')?.dispatchEvent(new Event('closeModal'));
window.removeEventListener('message', handle3in1IFrameEvents);
break;
default:
break;
}
};

export async function createContent(iframeUrl, modalType) {
const content = createTag('div', { class: 'milo-iframe' });
content.innerHTML = `<sp-theme system="light" color="light" scale="medium" dir="ltr">
<sp-progress-circle label="progress circle" indeterminate="" size="l" dir="ltr" role="progressbar" aria-label="progress circle"></sp-progress-circle>
</sp-theme>
<iframe src="${iframeUrl}" title="${modalType === MODAL_TYPE_3_IN_1.CRM ? 'Single App' : modalType}" frameborder="0" marginwidth="0" marginheight="0" allowfullscreen="true" loading="lazy" class="loading" style="height: 100%;"></iframe>`;
Comment on lines +63 to +66

Check warning

Code scanning / CodeQL

DOM text reinterpreted as HTML Medium

DOM text
is reinterpreted as HTML without escaping meta-characters.
return content;
}

export default async function openThreeInOneModal(el) {
const iframeUrl = el?.href;
const modalType = el?.getAttribute('data-modal-type');
if (!modalType || !iframeUrl) return undefined;
const { getModal } = await import('../modal/modal.js');
const content = await createContent(iframeUrl, modalType);
return getModal(null, {
id: 'three-in-one',
content,
closeEvent: 'closeModal',
class: 'three-in-one',
});
}
59 changes: 38 additions & 21 deletions libs/blocks/modal/modal.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,31 @@
z-index: 102;
}

.dialog-modal.upgrade-flow-modal,
.dialog-modal.three-in-one {
height: 100%;
width: 100%;
max-height: 100%;
max-width: 100%;
overflow: hidden;
}

.upgrade-flow-modal .dialog-close {
display: none;
}

.upgrade-flow-modal .upgrade-flow-iframe,
.three-in-one .milo-iframe {
overflow: hidden;
height: 100%;
width: 100%;
box-sizing: border-box;
}

.three-in-one iframe {
width: 100%;
}

#locale-modal-v2 .dialog-close,
#locale-modal-v2 .georouting-wrapper {
display: block;
Expand Down Expand Up @@ -72,25 +97,6 @@
}
}

.dialog-modal.upgrade-flow-modal {
height: 100%;
width: 100%;
max-height: 100%;
max-width: 100%;
overflow: hidden;
}

.upgrade-flow-modal .dialog-close {
display: none;
}

.upgrade-flow-modal .upgrade-flow-iframe {
overflow: hidden;
height: 100%;
width: 100%;
box-sizing: border-box;
}

.modal-curtain.is-open {
position: fixed;
top: 0;
Expand Down Expand Up @@ -238,6 +244,10 @@
width: fit-content;
}

.dialog-modal.three-in-one {
width: 100%;
}

.dialog-modal .embed-vimeo {
min-width: 80vw;
}
Expand Down Expand Up @@ -282,7 +292,7 @@
max-width: 100%;
max-height: 100%;
}

.dialog-modal.upgrade-flow-modal {
border-radius: 0;
}
Expand Down Expand Up @@ -355,14 +365,21 @@
.dialog-modal.commerce-frame .milo-iframe iframe {
height: 0%;
}

.dialog-modal.upgrade-flow-modal {
height: 820px;
max-width: 1100px;
overflow: hidden;
width: 80%;
}

.dialog-modal.three-in-one {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see .dialog-modal.upgrade-flow-modal has the exact properties, can we combine them somehow?

height: 820px;
width: 80%;
max-width: 1100px;
overflow: hidden;
}

.dialog-modal.tall-video,
.dialog-modal.tall-video .milo-video {
--modal-width-var: 35vw;
Expand Down
4 changes: 2 additions & 2 deletions libs/deps/mas/commerce.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions libs/deps/mas/constants.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

132 changes: 66 additions & 66 deletions libs/deps/mas/mas.js

Large diffs are not rendered by default.

Loading
Loading