From e29bed7d8555dc4c5d3da3b778d137feb4f6ebcd Mon Sep 17 00:00:00 2001 From: echen-adobe Date: Tue, 11 Mar 2025 09:19:17 -0700 Subject: [PATCH 01/16] Update frictionless-quick-action.js --- .../frictionless-quick-action.js | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js index 5b31439c..140cae93 100644 --- a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js +++ b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js @@ -43,11 +43,6 @@ const QA_CONFIGS = { }, }; -const EXPERIMENTAL_VARIANTS = [ - 'qa-in-product-variant1', - 'qa-in-product-variant2', -]; - function fade(element, action) { if (action === 'in') { element.classList.remove('hidden'); @@ -159,23 +154,29 @@ export function runQuickAction(quickAction, data, block) { ccEverywhere.quickAction.resizeImage(docConfig, appConfig, exportConfig, contConfig); break; case 'remove-background': - if (appConfig?.metaData?.variant - && EXPERIMENTAL_VARIANTS.includes(appConfig.metaData.variant)) { - document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; - ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { - ...contConfig, - mode: 'modal', - metaData: { - isFrictionlessQa: 'true', - }, - }); - } else { - ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); - } + ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); break; case 'generate-qr-code': ccEverywhere.quickAction.generateQRCode({}, appConfig, exportConfig, contConfig); break; + case 'qa-in-product-variant1': + document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; + ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { + ...contConfig, + mode: 'modal', + metaData: { + isFrictionlessQa: 'true', + }, + }); + case 'qa-in-product-variant2': + document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; + ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { + ...contConfig, + mode: 'modal', + metaData: { + isFrictionlessQa: 'true', + }, + }); default: break; } } @@ -271,8 +272,8 @@ async function startSDKWithUnconvertedFile(file, quickAction, block) { export default async function decorate(block) { const [utils, gNavUtils] = await Promise.all([import(`${getLibs()}/utils/utils.js`), - import(`${getLibs()}/blocks/global-navigation/utilities/utilities.js`), - decorateButtonsDeprecated(block)]); + import(`${getLibs()}/blocks/global-navigation/utilities/utilities.js`), + decorateButtonsDeprecated(block)]); ({ createTag, getMetadata, loadScript, getConfig } = utils); globalNavSelector = gNavUtils?.selectors.globalNav; From 7e2c192837aa8fb40be5fb9df484430247e514b9 Mon Sep 17 00:00:00 2001 From: echen-adobe Date: Tue, 11 Mar 2025 09:22:45 -0700 Subject: [PATCH 02/16] Update frictionless-quick-action.js --- .../frictionless-quick-action/frictionless-quick-action.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js index 140cae93..6894d00b 100644 --- a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js +++ b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js @@ -41,6 +41,8 @@ const QA_CONFIGS = { ...getBaseImgCfg(JPG, JPEG, PNG), input_check: () => true, }, + 'qa-in-product-variant1': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + 'qa-in-product-variant2': { ...getBaseImgCfg(JPG, JPEG, PNG) }, }; function fade(element, action) { From 4baf77be7a33cebc861ef9801b3e2ef4b594b525 Mon Sep 17 00:00:00 2001 From: echen-adobe Date: Tue, 11 Mar 2025 09:48:50 -0700 Subject: [PATCH 03/16] Update frictionless-quick-action.js --- .../frictionless-quick-action/frictionless-quick-action.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js index 6894d00b..cfe71bc1 100644 --- a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js +++ b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js @@ -274,8 +274,8 @@ async function startSDKWithUnconvertedFile(file, quickAction, block) { export default async function decorate(block) { const [utils, gNavUtils] = await Promise.all([import(`${getLibs()}/utils/utils.js`), - import(`${getLibs()}/blocks/global-navigation/utilities/utilities.js`), - decorateButtonsDeprecated(block)]); + import(`${getLibs()}/blocks/global-navigation/utilities/utilities.js`), + decorateButtonsDeprecated(block)]); ({ createTag, getMetadata, loadScript, getConfig } = utils); globalNavSelector = gNavUtils?.selectors.globalNav; From 9f5d1af61fd6088301f3f54e9ecfd3fc7c8c1dd8 Mon Sep 17 00:00:00 2001 From: echen-adobe Date: Tue, 11 Mar 2025 09:50:36 -0700 Subject: [PATCH 04/16] Update frictionless-quick-action.js --- .../frictionless-quick-action/frictionless-quick-action.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js index cfe71bc1..0328ba32 100644 --- a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js +++ b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js @@ -170,6 +170,7 @@ export function runQuickAction(quickAction, data, block) { isFrictionlessQa: 'true', }, }); + break; case 'qa-in-product-variant2': document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { @@ -179,6 +180,7 @@ export function runQuickAction(quickAction, data, block) { isFrictionlessQa: 'true', }, }); + break; default: break; } } From 4441c4142bd3598819bf08ba639fb05efe258f50 Mon Sep 17 00:00:00 2001 From: echen-adobe Date: Tue, 11 Mar 2025 10:30:33 -0700 Subject: [PATCH 05/16] reverted base frictionless quick action file added new file as an experiment --- .../frictionless-quick-action.js | 41 +- .../frictionless-quick-action.css | 196 +++++++++ .../frictionless-quick-action.js | 394 ++++++++++++++++++ 3 files changed, 596 insertions(+), 35 deletions(-) create mode 100644 express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.css create mode 100644 express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js diff --git a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js index 0328ba32..29f1b0d1 100644 --- a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js +++ b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js @@ -7,8 +7,7 @@ import { buildFreePlanWidget } from '../../scripts/widgets/free-plan.js'; import { sendFrictionlessEventToAdobeAnaltics } from '../../scripts/instrument.js'; let createTag; let getConfig; -let getMetadata; -let loadScript; let globalNavSelector; +let loadScript; let getMetadata; let ccEverywhere; let quickActionContainer; @@ -41,8 +40,6 @@ const QA_CONFIGS = { ...getBaseImgCfg(JPG, JPEG, PNG), input_check: () => true, }, - 'qa-in-product-variant1': { ...getBaseImgCfg(JPG, JPEG, PNG) }, - 'qa-in-product-variant2': { ...getBaseImgCfg(JPG, JPEG, PNG) }, }; function fade(element, action) { @@ -104,7 +101,6 @@ export function runQuickAction(quickAction, data, block) { parentElementId: `${quickAction}-container`, backgroundColor: 'transparent', hideCloseButton: true, - padding: 0, }; const docConfig = { @@ -114,9 +110,8 @@ export function runQuickAction(quickAction, data, block) { type: 'image', }, }; - const variant = new URLSearchParams(window.location.search).get('variant'); const appConfig = { - metaData: { isFrictionlessQa: 'true', variant, entryPoint: 'seo-quickaction-image-upload' }, + metaData: { isFrictionlessQa: 'true' }, receiveQuickActionErrors: false, callbacks: { onIntentChange: () => { @@ -161,26 +156,6 @@ export function runQuickAction(quickAction, data, block) { case 'generate-qr-code': ccEverywhere.quickAction.generateQRCode({}, appConfig, exportConfig, contConfig); break; - case 'qa-in-product-variant1': - document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; - ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { - ...contConfig, - mode: 'modal', - metaData: { - isFrictionlessQa: 'true', - }, - }); - break; - case 'qa-in-product-variant2': - document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; - ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { - ...contConfig, - mode: 'modal', - metaData: { - isFrictionlessQa: 'true', - }, - }); - break; default: break; } } @@ -212,7 +187,6 @@ async function startSDK(data = '', quickAction, block) { if (ietf === 'zh-Hant-TW') ietf = 'tw-TW'; else if (ietf === 'zh-Hans-CN') ietf = 'cn-CN'; - const baseQA = new URLSearchParams(window.location.search).get('base-qa'); const ccEverywhereConfig = { hostInfo: { clientId, @@ -221,7 +195,6 @@ async function startSDK(data = '', quickAction, block) { configParams: { locale: ietf?.replace('-', '_'), env: urlParams.get('hzenv') === 'stage' ? 'stage' : 'prod', - urlOverride: baseQA, }, authOption: () => ({ mode: 'delayed' }), }; @@ -275,12 +248,9 @@ async function startSDKWithUnconvertedFile(file, quickAction, block) { } export default async function decorate(block) { - const [utils, gNavUtils] = await Promise.all([import(`${getLibs()}/utils/utils.js`), - import(`${getLibs()}/blocks/global-navigation/utilities/utilities.js`), - decorateButtonsDeprecated(block)]); - ({ createTag, getMetadata, loadScript, getConfig } = utils); - globalNavSelector = gNavUtils?.selectors.globalNav; - + await Promise.all([import(`${getLibs()}/utils/utils.js`), decorateButtonsDeprecated(block)]).then(([utils]) => { + ({ createTag, getConfig, loadScript, getMetadata } = utils); + }); const rows = Array.from(block.children); rows[1].classList.add('fqa-container'); const quickActionRow = rows.filter((r) => r.children && r.children[0].textContent.toLowerCase().trim() === 'quick-action'); @@ -365,6 +335,7 @@ export default async function decorate(block) { const freePlanTags = await buildFreePlanWidget({ typeKey: 'branded', checkmarks: true }); dropzone.append(freePlanTags); + window.addEventListener('popstate', (e) => { const editorModal = selectElementByTagPrefix('cc-everywhere-container-'); const correctState = e.state?.hideFrictionlessQa; diff --git a/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.css b/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.css new file mode 100644 index 00000000..d3137342 --- /dev/null +++ b/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.css @@ -0,0 +1,196 @@ +.frictionless-quick-action { + padding: 40px 20px; + max-width: none; + text-align: center; +} + +.section .frictionless-quick-action h1 { + font-size: 2.8125rem; + margin: 0; +} + +.frictionless-quick-action .express-logo { + width: initial; + height: 30px; +} + +.frictionless-quick-action h1+p { + margin: 16px 0 24px; + font-size: 1rem; +} + +.frictionless-quick-action input { + display: none; +} + +.frictionless-quick-action .quick-action-container { + padding: 40px 0; + min-height: 697px; + max-width: 1440px; + width: 100%; + margin: auto; + transition: opacity 0.2s; +} + +.frictionless-quick-action h1 em { + background: linear-gradient(320deg, #7C84F3, #FF4DD2, #FF993B, #FF4DD2, #7C84F3, #FF4DD2, #FF993B); + background-size: 400% 400%; + -webkit-animation: quickActionGradient 45s ease infinite; + -moz-animation: quickActionGradient 45s ease infinite; + animation: quickActionGradient 45s ease infinite; + -webkit-background-clip: text; + background-clip: text; + font-style: normal; + -webkit-text-fill-color: transparent; +} + +.frictionless-quick-action .fqa-container { + display: flex; + align-items: center; + justify-content: center; + transition: opacity 0.2s; + flex-wrap: wrap; +} + +.frictionless-quick-action .fqa-container > div:nth-child(2) { + margin-top: 26px; +} + +.frictionless-quick-action video, +.frictionless-quick-action img:not(.icon) { + max-width: 444px; +} + +.frictionless-quick-action .dropzone-container { + cursor: pointer; + padding: 24px 0; + border-radius: 20px; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3); + width: 630px; + height: 284px; +} + +.frictionless-quick-action .dropzone-bg { + position: absolute; + width: 100%; + height: 100%; + left: 0px; + background: url("/express/code/icons/dash-rectangle.svg") center center / 91% no-repeat; +} + +.frictionless-quick-action .dropzone-container.highlight .dropzone-bg { + filter: invert(0%) sepia(0%) saturate(7500%) hue-rotate(327deg) brightness(6%) contrast(104%); + transition: 0.3s ease-in-out; +} + +.frictionless-quick-action .dropzone-container:hover, .frictionless-quick-action .dropzone-container.highlight { + background-color: rgb(211, 211, 211, 0.2); +} + +.frictionless-quick-action .dropzone { + height: 100%; + width: 100%; + position: relative; +} + +.frictionless-quick-action .dropzone-bg + p { + margin: 0; + padding: 39px 24px 0 24px; + font-size: var(--heading-font-size-m); + font-weight: var(--heading-font-weight); + line-height: var(--heading-line-height); +} + +.frictionless-quick-action .dropzone-bg + p em { + font-style: normal; + color: var(--color-info-accent); +} + +.frictionless-quick-action .dropzone p:last-of-type { + font-size: .6875rem; + margin: 0; +} + +.frictionless-quick-action .dropzone .button { + margin-bottom: 0; +} + +.frictionless-quick-action .fqa-container > div:nth-child(2) > p:last-of-type { + margin: 15px 0 0; + font-size: 0.75rem; +} + +.frictionless-quick-action .free-plan-widget { + background-color: unset; + flex-direction: row; + padding: unset; + margin: 16px auto 0 auto; + gap: 8px; +} + +.frictionless-quick-action .free-plan-widget > div { + margin: 10px; +} + +main .section .frictionless-quick-action .free-plan-widget img.icon.icon-checkmark { + background-color: #f06dad; +} +.frictionless-quick-action .quick-action-container { + height: 667px; +} + +.frictionless-quick-action .quick-action-container > * { + height: 100%; +} + +.frictionless-quick-action .quick-action-container#resize-image-container { + height: 1080px; +} + +.frictionless-quick-action > div.hidden { + visibility: hidden; + position: absolute; +} + +.frictionless-quick-action > div.transparent { + opacity: 0; +} + +.frictionless-quick-action .error-toast { + position: fixed; + bottom: 100px; + left: 50%; + transform: translateX(-50%); + opacity: 1; + transition: opacity 1s; + z-index: 10; + margin: 0 auto; + color: white; + background-color: #d31510; + padding: 10px 16px; + display: flex; + align-items: center; + gap: 10px; + font-size: var(--body-font-size-s); + width: fit-content; + border-radius: 50px; +} + +.frictionless-quick-action .error-toast.hide { + opacity: 0; +} + +.frictionless-quick-action .error-toast button { + background-color: unset; + border: unset; + padding: unset; + display: flex; + align-items: center; + cursor: pointer; +} + +@media (min-width: 1200) { + .frictionless-quick-action .quick-action-container#resize-image-container { + height: 1000px; + } +} diff --git a/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js b/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js new file mode 100644 index 00000000..7386ca85 --- /dev/null +++ b/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js @@ -0,0 +1,394 @@ +import { + addAnimationToggle, + transformLinkToAnimation, + } from '../../../../media.js' + import { getLibs, getIconElementDeprecated, decorateButtonsDeprecated } from '../../../../utils.js'; + import { buildFreePlanWidget } from '../../../../free-plan.js'; + import { sendFrictionlessEventToAdobeAnaltics } from '../../../../instrument.js'; + + let createTag; let getConfig; + let getMetadata; + let loadScript; let globalNavSelector; + + let ccEverywhere; + let quickActionContainer; + let uploadContainer; + + const JPG = 'jpg'; + const JPEG = 'jpeg'; + const PNG = 'png'; + const WEBP = 'webp'; + export const getBaseImgCfg = (...types) => ({ + group: 'image', + max_size: 40 * 1024 * 1024, + accept: types.map((type) => `.${type}`).join(', '), + input_check: (input) => types.map((type) => `image/${type}`).includes(input), + }); + export const getBaseVideoCfg = (...types) => ({ + group: 'video', + max_size: 1024 * 1024 * 1024, + accept: types.map((type) => `.${type}`).join(', '), + input_check: (input) => types.map((type) => `video/${type}`).includes(input), + }); + const QA_CONFIGS = { + 'convert-to-jpg': { ...getBaseImgCfg(PNG, WEBP) }, + 'convert-to-png': { ...getBaseImgCfg(JPG, JPEG, WEBP) }, + 'convert-to-svg': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + 'crop-image': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + 'resize-image': { ...getBaseImgCfg(JPG, JPEG, PNG, WEBP) }, + 'remove-background': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + 'generate-qr-code': { + ...getBaseImgCfg(JPG, JPEG, PNG), + input_check: () => true, + }, + 'qa-in-product-variant1': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + 'qa-in-product-variant2': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + }; + + function fade(element, action) { + if (action === 'in') { + element.classList.remove('hidden'); + setTimeout(() => { + element.classList.remove('transparent'); + }, 10); + } else if (action === 'out') { + element.classList.add('transparent'); + setTimeout(() => { + element.classList.add('hidden'); + }, 200); + } + } + + function selectElementByTagPrefix(p) { + const allEls = document.body.querySelectorAll(':scope > *'); + return Array.from(allEls).find((e) => e.tagName.toLowerCase().startsWith(p.toLowerCase())); + } + + // eslint-disable-next-line default-param-last + export function runQuickAction(quickAction, data, block) { + // TODO: need the button labels from the placeholders sheet if the SDK default doens't work. + const exportConfig = [ + { + id: 'download-button', + // label: 'Download', + action: { target: 'download' }, + style: { uiType: 'button' }, + buttonStyle: { + variant: 'secondary', + treatment: 'fill', + size: 'xl', + }, + }, + { + id: 'edit-in-express', + // label: 'Edit in Adobe Express for free', + action: { target: 'express' }, + style: { uiType: 'button' }, + buttonStyle: { + variant: 'primary', + treatment: 'fill', + size: 'xl', + }, + }, + ]; + + const id = `${quickAction}-container`; + quickActionContainer = createTag('div', { id, class: 'quick-action-container' }); + block.append(quickActionContainer); + const divs = block.querySelectorAll(':scope > div'); + if (divs[1]) [, uploadContainer] = divs; + fade(uploadContainer, 'out'); + + const contConfig = { + mode: 'inline', + parentElementId: `${quickAction}-container`, + backgroundColor: 'transparent', + hideCloseButton: true, + padding: 0, + }; + + const docConfig = { + asset: { + data, + dataType: 'base64', + type: 'image', + }, + }; + const variant = new URLSearchParams(window.location.search).get('variant'); + const appConfig = { + metaData: { isFrictionlessQa: 'true', variant, entryPoint: 'seo-quickaction-image-upload' }, + receiveQuickActionErrors: false, + callbacks: { + onIntentChange: () => { + quickActionContainer?.remove(); + fade(uploadContainer, 'in'); + document.body.classList.add('editor-modal-loaded'); + window.history.pushState({ hideFrictionlessQa: true }, '', ''); + return { + containerConfig: { + mode: 'modal', + zIndex: 999, + }, + }; + }, + onCancel: () => { + window.history.back(); + }, + }, + }; + + if (!ccEverywhere) return; + switch (quickAction) { + case 'convert-to-jpg': + ccEverywhere.quickAction.convertToJPEG(docConfig, appConfig, exportConfig, contConfig); + break; + case 'convert-to-png': + ccEverywhere.quickAction.convertToPNG(docConfig, appConfig, exportConfig, contConfig); + break; + case 'convert-to-svg': + exportConfig.pop(); + ccEverywhere.quickAction.convertToSVG(docConfig, appConfig, exportConfig, contConfig); + break; + case 'crop-image': + ccEverywhere.quickAction.cropImage(docConfig, appConfig, exportConfig, contConfig); + break; + case 'resize-image': + ccEverywhere.quickAction.resizeImage(docConfig, appConfig, exportConfig, contConfig); + break; + case 'remove-background': + ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); + break; + case 'generate-qr-code': + ccEverywhere.quickAction.generateQRCode({}, appConfig, exportConfig, contConfig); + break; + case 'qa-in-product-variant1': + document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; + ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { + ...contConfig, + mode: 'modal', + metaData: { + isFrictionlessQa: 'true', + }, + }); + break; + case 'qa-in-product-variant2': + document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; + ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { + ...contConfig, + mode: 'modal', + metaData: { + isFrictionlessQa: 'true', + }, + }); + break; + default: break; + } + } + + // eslint-disable-next-line default-param-last + async function startSDK(data = '', quickAction, block) { + const urlParams = new URLSearchParams(window.location.search); + const urlOverride = urlParams.get('sdk-override'); + let valid = false; + if (urlOverride) { + try { + if (new URL(urlOverride).host === 'dev.cc-embed.adobe.com') valid = true; + } catch (e) { + window.lana.log('Invalid SDK URL'); + } + } + const CDN_URL = valid ? urlOverride : 'https://cc-embed.adobe.com/sdk/1p/v4/CCEverywhere.js'; + const clientId = 'AdobeExpressWeb'; + + await loadScript(CDN_URL); + if (!window.CCEverywhere) { + return; + } + + if (!ccEverywhere) { + let { ietf } = getConfig().locale; + const country = urlParams.get('country'); + if (country) ietf = getConfig().locales[country]?.ietf; + if (ietf === 'zh-Hant-TW') ietf = 'tw-TW'; + else if (ietf === 'zh-Hans-CN') ietf = 'cn-CN'; + + const baseQA = new URLSearchParams(window.location.search).get('base-qa'); + const ccEverywhereConfig = { + hostInfo: { + clientId, + appName: 'express', + }, + configParams: { + locale: ietf?.replace('-', '_'), + env: urlParams.get('hzenv') === 'stage' ? 'stage' : 'prod', + urlOverride: baseQA, + }, + authOption: () => ({ mode: 'delayed' }), + }; + + ccEverywhere = await window.CCEverywhere.initialize(...Object.values(ccEverywhereConfig)); + } + + runQuickAction(quickAction, data, block); + } + + let timeoutId = null; + function showErrorToast(block, msg) { + let toast = block.querySelector('.error-toast'); + const hideToast = () => toast.classList.add('hide'); + if (!toast) { + toast = createTag('div', { class: 'error-toast hide' }); + toast.prepend(getIconElementDeprecated('error')); + const close = createTag('button', {}, getIconElementDeprecated('close-white')); + close.addEventListener('click', hideToast); + toast.append(close); + block.append(toast); + } + toast.textContent = msg; + toast.classList.remove('hide'); + clearTimeout(timeoutId); + timeoutId = setTimeout(hideToast, 6000); + } + + async function startSDKWithUnconvertedFile(file, quickAction, block) { + if (!file) return; + const maxSize = QA_CONFIGS[quickAction].max_size ?? 40 * 1024 * 1024; + if (QA_CONFIGS[quickAction].input_check(file.type) && file.size <= maxSize) { + const reader = new FileReader(); + reader.onloadend = () => { + window.history.pushState({ hideFrictionlessQa: true }, '', ''); + startSDK(reader.result, quickAction, block); + }; + + // Read the file as a data URL (Base64) + reader.readAsDataURL(file); + return; + } + const { replaceKey } = await import(`${getLibs()}/features/placeholders.js`); + let msg; + if (!QA_CONFIGS[quickAction].input_check(file.type)) { + msg = await replaceKey('file-type-not-supported', getConfig()); + } else { + msg = await replaceKey('file-size-not-supported', getConfig()); + } + showErrorToast(block, msg); + } + + export default async function decorate(block) { + const [utils, gNavUtils] = await Promise.all([import(`${getLibs()}/utils/utils.js`), + import(`${getLibs()}/blocks/global-navigation/utilities/utilities.js`), + decorateButtonsDeprecated(block)]); + ({ createTag, getMetadata, loadScript, getConfig } = utils); + globalNavSelector = gNavUtils?.selectors.globalNav; + + const rows = Array.from(block.children); + rows[1].classList.add('fqa-container'); + const quickActionRow = rows.filter((r) => r.children && r.children[0].textContent.toLowerCase().trim() === 'quick-action'); + const quickAction = quickActionRow?.[0].children[1]?.textContent; + if (!quickAction) { + throw new Error('Invalid Quick Action Type.'); + } + quickActionRow[0].remove(); + + const actionAndAnimationRow = rows[1].children; + const animationContainer = actionAndAnimationRow[0]; + const animation = animationContainer.querySelector('a'); + const dropzone = actionAndAnimationRow[1]; + const dropzoneBackground = createTag('div', { class: 'dropzone-bg' }); + const cta = dropzone.querySelector('a.button, a.con-button'); + const gtcText = dropzone.querySelector('p:last-child'); + const actionColumn = createTag('div'); + const dropzoneContainer = createTag('div', { class: 'dropzone-container' }); + + if (animation && animation.href.includes('.mp4')) { + transformLinkToAnimation(animation); + addAnimationToggle(animationContainer); + } + if (cta) cta.classList.add('xlarge'); + dropzone.classList.add('dropzone'); + + dropzone.prepend(dropzoneBackground); + dropzone.before(actionColumn); + dropzoneContainer.append(dropzone); + actionColumn.append(dropzoneContainer, gtcText); + const inputElement = createTag('input', { type: 'file', accept: QA_CONFIGS[quickAction].accept }); + inputElement.onchange = () => { + const file = inputElement.files[0]; + startSDKWithUnconvertedFile(file, quickAction, block); + }; + block.append(inputElement); + + dropzoneContainer.addEventListener('click', (e) => { + e.preventDefault(); + if (quickAction === 'generate-qr-code') { + startSDK('', quickAction, block); + } else { + inputElement.click(); + } + document.body.dataset.suppressfloatingcta = 'true'; + }); + + function preventDefaults(e) { + e.preventDefault(); + e.stopPropagation(); + } + + function highlight() { + dropzoneContainer.classList.add('highlight'); + } + + function unhighlight() { + dropzoneContainer.classList.remove('highlight'); + } + + ['dragenter', 'dragover'].forEach((eventName) => { + dropzoneContainer.addEventListener(eventName, highlight, false); + }); + + ['dragenter', 'dragover', 'dragleave', 'drop'].forEach((eventName) => { + dropzoneContainer.addEventListener(eventName, preventDefaults, false); + }); + + ['dragleave', 'drop'].forEach((eventName) => { + dropzoneContainer.addEventListener(eventName, unhighlight, false); + }); + + dropzoneContainer.addEventListener('drop', async (e) => { + const dt = e.dataTransfer; + const { files } = dt; + + await Promise.all( + [...files].map((file) => startSDKWithUnconvertedFile(file, quickAction, block)), + ); + document.body.dataset.suppressfloatingcta = 'true'; + }, false); + + const freePlanTags = await buildFreePlanWidget({ typeKey: 'branded', checkmarks: true }); + dropzone.append(freePlanTags); + window.addEventListener('popstate', (e) => { + const editorModal = selectElementByTagPrefix('cc-everywhere-container-'); + const correctState = e.state?.hideFrictionlessQa; + const embedElsFound = quickActionContainer || editorModal; + window.history.pushState({ hideFrictionlessQa: true }, '', ''); + if (correctState || embedElsFound) { + quickActionContainer?.remove(); + editorModal?.remove(); + document.body.classList.remove('editor-modal-loaded'); + inputElement.value = ''; + fade(uploadContainer, 'in'); + document.body.dataset.suppressfloatingcta = 'false'; + } + }, { passive: true }); + + block.dataset.frictionlesstype = quickAction; + block.dataset.frictionlessgroup = QA_CONFIGS[quickAction].group ?? 'image'; + + if (['on', 'yes'].includes(getMetadata('marquee-inject-logo')?.toLowerCase())) { + const logo = getIconElementDeprecated('adobe-express-logo'); + logo.classList.add('express-logo'); + block.prepend(logo); + } + + sendFrictionlessEventToAdobeAnaltics(block); + } + \ No newline at end of file From 57f419ab348c7fc920e2e6ad3d82161a231bad5d Mon Sep 17 00:00:00 2001 From: echen-adobe Date: Tue, 11 Mar 2025 11:03:37 -0700 Subject: [PATCH 06/16] Update frictionless-quick-action.js --- .../frictionless-quick-action.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js b/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js index 7386ca85..a07eafe0 100644 --- a/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js +++ b/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js @@ -166,19 +166,13 @@ import { ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { ...contConfig, mode: 'modal', - metaData: { - isFrictionlessQa: 'true', - }, }); break; case 'qa-in-product-variant2': document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { ...contConfig, - mode: 'modal', - metaData: { - isFrictionlessQa: 'true', - }, + mode: 'modal', }); break; default: break; From f67f952a79c45daa128b6407120f3bb57d21f57a Mon Sep 17 00:00:00 2001 From: echen-adobe Date: Tue, 11 Mar 2025 11:30:08 -0700 Subject: [PATCH 07/16] Update frictionless-quick-action.js --- .../frictionless-quick-action/frictionless-quick-action.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js b/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js index a07eafe0..ade6ce58 100644 --- a/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js +++ b/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js @@ -161,6 +161,12 @@ import { case 'generate-qr-code': ccEverywhere.quickAction.generateQRCode({}, appConfig, exportConfig, contConfig); break; + case 'qa-nbs': + ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); + break; + case 'qa-in-product-control': + ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); + break; case 'qa-in-product-variant1': document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { From 74849ae619a75622dcf558c1f817c4532e800ebf Mon Sep 17 00:00:00 2001 From: echen-adobe Date: Tue, 11 Mar 2025 11:31:37 -0700 Subject: [PATCH 08/16] Update frictionless-quick-action.js --- .../frictionless-quick-action/frictionless-quick-action.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js b/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js index ade6ce58..2008ed4c 100644 --- a/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js +++ b/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js @@ -43,6 +43,9 @@ import { }, 'qa-in-product-variant1': { ...getBaseImgCfg(JPG, JPEG, PNG) }, 'qa-in-product-variant2': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + 'qa-in-product-control': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + 'qa-nbs': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + }; function fade(element, action) { From 88bba62908333c59aa4b614e6b98e5f7948b688f Mon Sep 17 00:00:00 2001 From: echen-adobe Date: Tue, 11 Mar 2025 12:04:49 -0700 Subject: [PATCH 09/16] Update frictionless-quick-action.js --- .../frictionless-quick-action.js | 755 +++++++++--------- 1 file changed, 377 insertions(+), 378 deletions(-) diff --git a/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js b/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js index 2008ed4c..19ee6fbe 100644 --- a/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js +++ b/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js @@ -1,397 +1,396 @@ import { - addAnimationToggle, - transformLinkToAnimation, - } from '../../../../media.js' - import { getLibs, getIconElementDeprecated, decorateButtonsDeprecated } from '../../../../utils.js'; - import { buildFreePlanWidget } from '../../../../free-plan.js'; - import { sendFrictionlessEventToAdobeAnaltics } from '../../../../instrument.js'; - - let createTag; let getConfig; - let getMetadata; - let loadScript; let globalNavSelector; - - let ccEverywhere; - let quickActionContainer; - let uploadContainer; - - const JPG = 'jpg'; - const JPEG = 'jpeg'; - const PNG = 'png'; - const WEBP = 'webp'; - export const getBaseImgCfg = (...types) => ({ - group: 'image', - max_size: 40 * 1024 * 1024, - accept: types.map((type) => `.${type}`).join(', '), - input_check: (input) => types.map((type) => `image/${type}`).includes(input), - }); - export const getBaseVideoCfg = (...types) => ({ - group: 'video', - max_size: 1024 * 1024 * 1024, - accept: types.map((type) => `.${type}`).join(', '), - input_check: (input) => types.map((type) => `video/${type}`).includes(input), - }); - const QA_CONFIGS = { - 'convert-to-jpg': { ...getBaseImgCfg(PNG, WEBP) }, - 'convert-to-png': { ...getBaseImgCfg(JPG, JPEG, WEBP) }, - 'convert-to-svg': { ...getBaseImgCfg(JPG, JPEG, PNG) }, - 'crop-image': { ...getBaseImgCfg(JPG, JPEG, PNG) }, - 'resize-image': { ...getBaseImgCfg(JPG, JPEG, PNG, WEBP) }, - 'remove-background': { ...getBaseImgCfg(JPG, JPEG, PNG) }, - 'generate-qr-code': { - ...getBaseImgCfg(JPG, JPEG, PNG), - input_check: () => true, + addAnimationToggle, + transformLinkToAnimation, +} from '../../../../scripts/utils/media.js' +import { getLibs, getIconElementDeprecated, decorateButtonsDeprecated } from '../../../../scripts/utils/utils.js'; +import { buildFreePlanWidget } from '../../../../scripts/utils/free-plan.js'; +import { sendFrictionlessEventToAdobeAnaltics } from '../../../../scripts/utils/instrument.js'; + +let createTag; let getConfig; +let getMetadata; +let loadScript; let globalNavSelector; + +let ccEverywhere; +let quickActionContainer; +let uploadContainer; + +const JPG = 'jpg'; +const JPEG = 'jpeg'; +const PNG = 'png'; +const WEBP = 'webp'; +export const getBaseImgCfg = (...types) => ({ + group: 'image', + max_size: 40 * 1024 * 1024, + accept: types.map((type) => `.${type}`).join(', '), + input_check: (input) => types.map((type) => `image/${type}`).includes(input), +}); +export const getBaseVideoCfg = (...types) => ({ + group: 'video', + max_size: 1024 * 1024 * 1024, + accept: types.map((type) => `.${type}`).join(', '), + input_check: (input) => types.map((type) => `video/${type}`).includes(input), +}); +const QA_CONFIGS = { + 'convert-to-jpg': { ...getBaseImgCfg(PNG, WEBP) }, + 'convert-to-png': { ...getBaseImgCfg(JPG, JPEG, WEBP) }, + 'convert-to-svg': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + 'crop-image': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + 'resize-image': { ...getBaseImgCfg(JPG, JPEG, PNG, WEBP) }, + 'remove-background': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + 'generate-qr-code': { + ...getBaseImgCfg(JPG, JPEG, PNG), + input_check: () => true, + }, + 'qa-in-product-variant1': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + 'qa-in-product-variant2': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + 'qa-in-product-control': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + 'qa-nbs': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + +}; + +function fade(element, action) { + if (action === 'in') { + element.classList.remove('hidden'); + setTimeout(() => { + element.classList.remove('transparent'); + }, 10); + } else if (action === 'out') { + element.classList.add('transparent'); + setTimeout(() => { + element.classList.add('hidden'); + }, 200); + } +} + +function selectElementByTagPrefix(p) { + const allEls = document.body.querySelectorAll(':scope > *'); + return Array.from(allEls).find((e) => e.tagName.toLowerCase().startsWith(p.toLowerCase())); +} + +// eslint-disable-next-line default-param-last +export function runQuickAction(quickAction, data, block) { + // TODO: need the button labels from the placeholders sheet if the SDK default doens't work. + const exportConfig = [ + { + id: 'download-button', + // label: 'Download', + action: { target: 'download' }, + style: { uiType: 'button' }, + buttonStyle: { + variant: 'secondary', + treatment: 'fill', + size: 'xl', + }, }, - 'qa-in-product-variant1': { ...getBaseImgCfg(JPG, JPEG, PNG) }, - 'qa-in-product-variant2': { ...getBaseImgCfg(JPG, JPEG, PNG) }, - 'qa-in-product-control': { ...getBaseImgCfg(JPG, JPEG, PNG) }, - 'qa-nbs': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + { + id: 'edit-in-express', + // label: 'Edit in Adobe Express for free', + action: { target: 'express' }, + style: { uiType: 'button' }, + buttonStyle: { + variant: 'primary', + treatment: 'fill', + size: 'xl', + }, + }, + ]; + + const id = `${quickAction}-container`; + quickActionContainer = createTag('div', { id, class: 'quick-action-container' }); + block.append(quickActionContainer); + const divs = block.querySelectorAll(':scope > div'); + if (divs[1]) [, uploadContainer] = divs; + fade(uploadContainer, 'out'); + + const contConfig = { + mode: 'inline', + parentElementId: `${quickAction}-container`, + backgroundColor: 'transparent', + hideCloseButton: true, + padding: 0, + }; + const docConfig = { + asset: { + data, + dataType: 'base64', + type: 'image', + }, + }; + const variant = new URLSearchParams(window.location.search).get('variant'); + const appConfig = { + metaData: { isFrictionlessQa: 'true', variant, entryPoint: 'seo-quickaction-image-upload' }, + receiveQuickActionErrors: false, + callbacks: { + onIntentChange: () => { + quickActionContainer?.remove(); + fade(uploadContainer, 'in'); + document.body.classList.add('editor-modal-loaded'); + window.history.pushState({ hideFrictionlessQa: true }, '', ''); + return { + containerConfig: { + mode: 'modal', + zIndex: 999, + }, + }; + }, + onCancel: () => { + window.history.back(); + }, + }, }; - - function fade(element, action) { - if (action === 'in') { - element.classList.remove('hidden'); - setTimeout(() => { - element.classList.remove('transparent'); - }, 10); - } else if (action === 'out') { - element.classList.add('transparent'); - setTimeout(() => { - element.classList.add('hidden'); - }, 200); + + if (!ccEverywhere) return; + switch (quickAction) { + case 'convert-to-jpg': + ccEverywhere.quickAction.convertToJPEG(docConfig, appConfig, exportConfig, contConfig); + break; + case 'convert-to-png': + ccEverywhere.quickAction.convertToPNG(docConfig, appConfig, exportConfig, contConfig); + break; + case 'convert-to-svg': + exportConfig.pop(); + ccEverywhere.quickAction.convertToSVG(docConfig, appConfig, exportConfig, contConfig); + break; + case 'crop-image': + ccEverywhere.quickAction.cropImage(docConfig, appConfig, exportConfig, contConfig); + break; + case 'resize-image': + ccEverywhere.quickAction.resizeImage(docConfig, appConfig, exportConfig, contConfig); + break; + case 'remove-background': + ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); + break; + case 'generate-qr-code': + ccEverywhere.quickAction.generateQRCode({}, appConfig, exportConfig, contConfig); + break; + case 'qa-nbs': + ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); + break; + case 'qa-in-product-control': + ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); + break; + case 'qa-in-product-variant1': + document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; + ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { + ...contConfig, + mode: 'modal', + }); + break; + case 'qa-in-product-variant2': + document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; + ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { + ...contConfig, + mode: 'modal', + }); + break; + default: break; + } +} + +// eslint-disable-next-line default-param-last +async function startSDK(data = '', quickAction, block) { + const urlParams = new URLSearchParams(window.location.search); + const urlOverride = urlParams.get('sdk-override'); + let valid = false; + if (urlOverride) { + try { + if (new URL(urlOverride).host === 'dev.cc-embed.adobe.com') valid = true; + } catch (e) { + window.lana.log('Invalid SDK URL'); } } - - function selectElementByTagPrefix(p) { - const allEls = document.body.querySelectorAll(':scope > *'); - return Array.from(allEls).find((e) => e.tagName.toLowerCase().startsWith(p.toLowerCase())); + const CDN_URL = valid ? urlOverride : 'https://cc-embed.adobe.com/sdk/1p/v4/CCEverywhere.js'; + const clientId = 'AdobeExpressWeb'; + + await loadScript(CDN_URL); + if (!window.CCEverywhere) { + return; } - - // eslint-disable-next-line default-param-last - export function runQuickAction(quickAction, data, block) { - // TODO: need the button labels from the placeholders sheet if the SDK default doens't work. - const exportConfig = [ - { - id: 'download-button', - // label: 'Download', - action: { target: 'download' }, - style: { uiType: 'button' }, - buttonStyle: { - variant: 'secondary', - treatment: 'fill', - size: 'xl', - }, - }, - { - id: 'edit-in-express', - // label: 'Edit in Adobe Express for free', - action: { target: 'express' }, - style: { uiType: 'button' }, - buttonStyle: { - variant: 'primary', - treatment: 'fill', - size: 'xl', - }, + + if (!ccEverywhere) { + let { ietf } = getConfig().locale; + const country = urlParams.get('country'); + if (country) ietf = getConfig().locales[country]?.ietf; + if (ietf === 'zh-Hant-TW') ietf = 'tw-TW'; + else if (ietf === 'zh-Hans-CN') ietf = 'cn-CN'; + + const baseQA = new URLSearchParams(window.location.search).get('base-qa'); + const ccEverywhereConfig = { + hostInfo: { + clientId, + appName: 'express', }, - ]; - - const id = `${quickAction}-container`; - quickActionContainer = createTag('div', { id, class: 'quick-action-container' }); - block.append(quickActionContainer); - const divs = block.querySelectorAll(':scope > div'); - if (divs[1]) [, uploadContainer] = divs; - fade(uploadContainer, 'out'); - - const contConfig = { - mode: 'inline', - parentElementId: `${quickAction}-container`, - backgroundColor: 'transparent', - hideCloseButton: true, - padding: 0, - }; - - const docConfig = { - asset: { - data, - dataType: 'base64', - type: 'image', + configParams: { + locale: ietf?.replace('-', '_'), + env: urlParams.get('hzenv') === 'stage' ? 'stage' : 'prod', + urlOverride: baseQA, }, + authOption: () => ({ mode: 'delayed' }), }; - const variant = new URLSearchParams(window.location.search).get('variant'); - const appConfig = { - metaData: { isFrictionlessQa: 'true', variant, entryPoint: 'seo-quickaction-image-upload' }, - receiveQuickActionErrors: false, - callbacks: { - onIntentChange: () => { - quickActionContainer?.remove(); - fade(uploadContainer, 'in'); - document.body.classList.add('editor-modal-loaded'); - window.history.pushState({ hideFrictionlessQa: true }, '', ''); - return { - containerConfig: { - mode: 'modal', - zIndex: 999, - }, - }; - }, - onCancel: () => { - window.history.back(); - }, - }, + + ccEverywhere = await window.CCEverywhere.initialize(...Object.values(ccEverywhereConfig)); + } + + runQuickAction(quickAction, data, block); +} + +let timeoutId = null; +function showErrorToast(block, msg) { + let toast = block.querySelector('.error-toast'); + const hideToast = () => toast.classList.add('hide'); + if (!toast) { + toast = createTag('div', { class: 'error-toast hide' }); + toast.prepend(getIconElementDeprecated('error')); + const close = createTag('button', {}, getIconElementDeprecated('close-white')); + close.addEventListener('click', hideToast); + toast.append(close); + block.append(toast); + } + toast.textContent = msg; + toast.classList.remove('hide'); + clearTimeout(timeoutId); + timeoutId = setTimeout(hideToast, 6000); +} + +async function startSDKWithUnconvertedFile(file, quickAction, block) { + if (!file) return; + const maxSize = QA_CONFIGS[quickAction].max_size ?? 40 * 1024 * 1024; + if (QA_CONFIGS[quickAction].input_check(file.type) && file.size <= maxSize) { + const reader = new FileReader(); + reader.onloadend = () => { + window.history.pushState({ hideFrictionlessQa: true }, '', ''); + startSDK(reader.result, quickAction, block); }; - - if (!ccEverywhere) return; - switch (quickAction) { - case 'convert-to-jpg': - ccEverywhere.quickAction.convertToJPEG(docConfig, appConfig, exportConfig, contConfig); - break; - case 'convert-to-png': - ccEverywhere.quickAction.convertToPNG(docConfig, appConfig, exportConfig, contConfig); - break; - case 'convert-to-svg': - exportConfig.pop(); - ccEverywhere.quickAction.convertToSVG(docConfig, appConfig, exportConfig, contConfig); - break; - case 'crop-image': - ccEverywhere.quickAction.cropImage(docConfig, appConfig, exportConfig, contConfig); - break; - case 'resize-image': - ccEverywhere.quickAction.resizeImage(docConfig, appConfig, exportConfig, contConfig); - break; - case 'remove-background': - ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); - break; - case 'generate-qr-code': - ccEverywhere.quickAction.generateQRCode({}, appConfig, exportConfig, contConfig); - break; - case 'qa-nbs': - ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); - break; - case 'qa-in-product-control': - ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); - break; - case 'qa-in-product-variant1': - document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; - ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { - ...contConfig, - mode: 'modal', - }); - break; - case 'qa-in-product-variant2': - document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; - ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { - ...contConfig, - mode: 'modal', - }); - break; - default: break; - } + + // Read the file as a data URL (Base64) + reader.readAsDataURL(file); + return; } - - // eslint-disable-next-line default-param-last - async function startSDK(data = '', quickAction, block) { - const urlParams = new URLSearchParams(window.location.search); - const urlOverride = urlParams.get('sdk-override'); - let valid = false; - if (urlOverride) { - try { - if (new URL(urlOverride).host === 'dev.cc-embed.adobe.com') valid = true; - } catch (e) { - window.lana.log('Invalid SDK URL'); - } - } - const CDN_URL = valid ? urlOverride : 'https://cc-embed.adobe.com/sdk/1p/v4/CCEverywhere.js'; - const clientId = 'AdobeExpressWeb'; - - await loadScript(CDN_URL); - if (!window.CCEverywhere) { - return; - } - - if (!ccEverywhere) { - let { ietf } = getConfig().locale; - const country = urlParams.get('country'); - if (country) ietf = getConfig().locales[country]?.ietf; - if (ietf === 'zh-Hant-TW') ietf = 'tw-TW'; - else if (ietf === 'zh-Hans-CN') ietf = 'cn-CN'; - - const baseQA = new URLSearchParams(window.location.search).get('base-qa'); - const ccEverywhereConfig = { - hostInfo: { - clientId, - appName: 'express', - }, - configParams: { - locale: ietf?.replace('-', '_'), - env: urlParams.get('hzenv') === 'stage' ? 'stage' : 'prod', - urlOverride: baseQA, - }, - authOption: () => ({ mode: 'delayed' }), - }; - - ccEverywhere = await window.CCEverywhere.initialize(...Object.values(ccEverywhereConfig)); - } - - runQuickAction(quickAction, data, block); + const { replaceKey } = await import(`${getLibs()}/features/placeholders.js`); + let msg; + if (!QA_CONFIGS[quickAction].input_check(file.type)) { + msg = await replaceKey('file-type-not-supported', getConfig()); + } else { + msg = await replaceKey('file-size-not-supported', getConfig()); } - - let timeoutId = null; - function showErrorToast(block, msg) { - let toast = block.querySelector('.error-toast'); - const hideToast = () => toast.classList.add('hide'); - if (!toast) { - toast = createTag('div', { class: 'error-toast hide' }); - toast.prepend(getIconElementDeprecated('error')); - const close = createTag('button', {}, getIconElementDeprecated('close-white')); - close.addEventListener('click', hideToast); - toast.append(close); - block.append(toast); - } - toast.textContent = msg; - toast.classList.remove('hide'); - clearTimeout(timeoutId); - timeoutId = setTimeout(hideToast, 6000); + showErrorToast(block, msg); +} + +export default async function decorate(block) { + const [utils, gNavUtils] = await Promise.all([import(`${getLibs()}/utils/utils.js`), + import(`${getLibs()}/blocks/global-navigation/utilities/utilities.js`), + decorateButtonsDeprecated(block)]); + ({ createTag, getMetadata, loadScript, getConfig } = utils); + globalNavSelector = gNavUtils?.selectors.globalNav; + + const rows = Array.from(block.children); + rows[1].classList.add('fqa-container'); + const quickActionRow = rows.filter((r) => r.children && r.children[0].textContent.toLowerCase().trim() === 'quick-action'); + const quickAction = quickActionRow?.[0].children[1]?.textContent; + if (!quickAction) { + throw new Error('Invalid Quick Action Type.'); } - - async function startSDKWithUnconvertedFile(file, quickAction, block) { - if (!file) return; - const maxSize = QA_CONFIGS[quickAction].max_size ?? 40 * 1024 * 1024; - if (QA_CONFIGS[quickAction].input_check(file.type) && file.size <= maxSize) { - const reader = new FileReader(); - reader.onloadend = () => { - window.history.pushState({ hideFrictionlessQa: true }, '', ''); - startSDK(reader.result, quickAction, block); - }; - - // Read the file as a data URL (Base64) - reader.readAsDataURL(file); - return; - } - const { replaceKey } = await import(`${getLibs()}/features/placeholders.js`); - let msg; - if (!QA_CONFIGS[quickAction].input_check(file.type)) { - msg = await replaceKey('file-type-not-supported', getConfig()); + quickActionRow[0].remove(); + + const actionAndAnimationRow = rows[1].children; + const animationContainer = actionAndAnimationRow[0]; + const animation = animationContainer.querySelector('a'); + const dropzone = actionAndAnimationRow[1]; + const dropzoneBackground = createTag('div', { class: 'dropzone-bg' }); + const cta = dropzone.querySelector('a.button, a.con-button'); + const gtcText = dropzone.querySelector('p:last-child'); + const actionColumn = createTag('div'); + const dropzoneContainer = createTag('div', { class: 'dropzone-container' }); + + if (animation && animation.href.includes('.mp4')) { + transformLinkToAnimation(animation); + addAnimationToggle(animationContainer); + } + if (cta) cta.classList.add('xlarge'); + dropzone.classList.add('dropzone'); + + dropzone.prepend(dropzoneBackground); + dropzone.before(actionColumn); + dropzoneContainer.append(dropzone); + actionColumn.append(dropzoneContainer, gtcText); + const inputElement = createTag('input', { type: 'file', accept: QA_CONFIGS[quickAction].accept }); + inputElement.onchange = () => { + const file = inputElement.files[0]; + startSDKWithUnconvertedFile(file, quickAction, block); + }; + block.append(inputElement); + + dropzoneContainer.addEventListener('click', (e) => { + e.preventDefault(); + if (quickAction === 'generate-qr-code') { + startSDK('', quickAction, block); } else { - msg = await replaceKey('file-size-not-supported', getConfig()); + inputElement.click(); } - showErrorToast(block, msg); + document.body.dataset.suppressfloatingcta = 'true'; + }); + + function preventDefaults(e) { + e.preventDefault(); + e.stopPropagation(); } - - export default async function decorate(block) { - const [utils, gNavUtils] = await Promise.all([import(`${getLibs()}/utils/utils.js`), - import(`${getLibs()}/blocks/global-navigation/utilities/utilities.js`), - decorateButtonsDeprecated(block)]); - ({ createTag, getMetadata, loadScript, getConfig } = utils); - globalNavSelector = gNavUtils?.selectors.globalNav; - - const rows = Array.from(block.children); - rows[1].classList.add('fqa-container'); - const quickActionRow = rows.filter((r) => r.children && r.children[0].textContent.toLowerCase().trim() === 'quick-action'); - const quickAction = quickActionRow?.[0].children[1]?.textContent; - if (!quickAction) { - throw new Error('Invalid Quick Action Type.'); - } - quickActionRow[0].remove(); - - const actionAndAnimationRow = rows[1].children; - const animationContainer = actionAndAnimationRow[0]; - const animation = animationContainer.querySelector('a'); - const dropzone = actionAndAnimationRow[1]; - const dropzoneBackground = createTag('div', { class: 'dropzone-bg' }); - const cta = dropzone.querySelector('a.button, a.con-button'); - const gtcText = dropzone.querySelector('p:last-child'); - const actionColumn = createTag('div'); - const dropzoneContainer = createTag('div', { class: 'dropzone-container' }); - - if (animation && animation.href.includes('.mp4')) { - transformLinkToAnimation(animation); - addAnimationToggle(animationContainer); - } - if (cta) cta.classList.add('xlarge'); - dropzone.classList.add('dropzone'); - - dropzone.prepend(dropzoneBackground); - dropzone.before(actionColumn); - dropzoneContainer.append(dropzone); - actionColumn.append(dropzoneContainer, gtcText); - const inputElement = createTag('input', { type: 'file', accept: QA_CONFIGS[quickAction].accept }); - inputElement.onchange = () => { - const file = inputElement.files[0]; - startSDKWithUnconvertedFile(file, quickAction, block); - }; - block.append(inputElement); - - dropzoneContainer.addEventListener('click', (e) => { - e.preventDefault(); - if (quickAction === 'generate-qr-code') { - startSDK('', quickAction, block); - } else { - inputElement.click(); - } - document.body.dataset.suppressfloatingcta = 'true'; - }); - - function preventDefaults(e) { - e.preventDefault(); - e.stopPropagation(); - } - - function highlight() { - dropzoneContainer.classList.add('highlight'); - } - - function unhighlight() { - dropzoneContainer.classList.remove('highlight'); - } - - ['dragenter', 'dragover'].forEach((eventName) => { - dropzoneContainer.addEventListener(eventName, highlight, false); - }); - - ['dragenter', 'dragover', 'dragleave', 'drop'].forEach((eventName) => { - dropzoneContainer.addEventListener(eventName, preventDefaults, false); - }); - - ['dragleave', 'drop'].forEach((eventName) => { - dropzoneContainer.addEventListener(eventName, unhighlight, false); - }); - - dropzoneContainer.addEventListener('drop', async (e) => { - const dt = e.dataTransfer; - const { files } = dt; - - await Promise.all( - [...files].map((file) => startSDKWithUnconvertedFile(file, quickAction, block)), - ); - document.body.dataset.suppressfloatingcta = 'true'; - }, false); - - const freePlanTags = await buildFreePlanWidget({ typeKey: 'branded', checkmarks: true }); - dropzone.append(freePlanTags); - window.addEventListener('popstate', (e) => { - const editorModal = selectElementByTagPrefix('cc-everywhere-container-'); - const correctState = e.state?.hideFrictionlessQa; - const embedElsFound = quickActionContainer || editorModal; - window.history.pushState({ hideFrictionlessQa: true }, '', ''); - if (correctState || embedElsFound) { - quickActionContainer?.remove(); - editorModal?.remove(); - document.body.classList.remove('editor-modal-loaded'); - inputElement.value = ''; - fade(uploadContainer, 'in'); - document.body.dataset.suppressfloatingcta = 'false'; - } - }, { passive: true }); - - block.dataset.frictionlesstype = quickAction; - block.dataset.frictionlessgroup = QA_CONFIGS[quickAction].group ?? 'image'; - - if (['on', 'yes'].includes(getMetadata('marquee-inject-logo')?.toLowerCase())) { - const logo = getIconElementDeprecated('adobe-express-logo'); - logo.classList.add('express-logo'); - block.prepend(logo); + + function highlight() { + dropzoneContainer.classList.add('highlight'); + } + + function unhighlight() { + dropzoneContainer.classList.remove('highlight'); + } + + ['dragenter', 'dragover'].forEach((eventName) => { + dropzoneContainer.addEventListener(eventName, highlight, false); + }); + + ['dragenter', 'dragover', 'dragleave', 'drop'].forEach((eventName) => { + dropzoneContainer.addEventListener(eventName, preventDefaults, false); + }); + + ['dragleave', 'drop'].forEach((eventName) => { + dropzoneContainer.addEventListener(eventName, unhighlight, false); + }); + + dropzoneContainer.addEventListener('drop', async (e) => { + const dt = e.dataTransfer; + const { files } = dt; + + await Promise.all( + [...files].map((file) => startSDKWithUnconvertedFile(file, quickAction, block)), + ); + document.body.dataset.suppressfloatingcta = 'true'; + }, false); + + const freePlanTags = await buildFreePlanWidget({ typeKey: 'branded', checkmarks: true }); + dropzone.append(freePlanTags); + window.addEventListener('popstate', (e) => { + const editorModal = selectElementByTagPrefix('cc-everywhere-container-'); + const correctState = e.state?.hideFrictionlessQa; + const embedElsFound = quickActionContainer || editorModal; + window.history.pushState({ hideFrictionlessQa: true }, '', ''); + if (correctState || embedElsFound) { + quickActionContainer?.remove(); + editorModal?.remove(); + document.body.classList.remove('editor-modal-loaded'); + inputElement.value = ''; + fade(uploadContainer, 'in'); + document.body.dataset.suppressfloatingcta = 'false'; } - - sendFrictionlessEventToAdobeAnaltics(block); + }, { passive: true }); + + block.dataset.frictionlesstype = quickAction; + block.dataset.frictionlessgroup = QA_CONFIGS[quickAction].group ?? 'image'; + + if (['on', 'yes'].includes(getMetadata('marquee-inject-logo')?.toLowerCase())) { + const logo = getIconElementDeprecated('adobe-express-logo'); + logo.classList.add('express-logo'); + block.prepend(logo); } - \ No newline at end of file + + sendFrictionlessEventToAdobeAnaltics(block); +} From 13f3cd480d8b96163556c5202829cee89bca581b Mon Sep 17 00:00:00 2001 From: echen-adobe Date: Tue, 11 Mar 2025 12:27:04 -0700 Subject: [PATCH 10/16] moved to main block --- .../frictionless-quick-action.js | 46 +- .../frictionless-quick-action.css | 196 --------- .../frictionless-quick-action.js | 396 ------------------ 3 files changed, 39 insertions(+), 599 deletions(-) delete mode 100644 express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.css delete mode 100644 express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js diff --git a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js index 29f1b0d1..3986099e 100644 --- a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js +++ b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js @@ -4,10 +4,11 @@ import { } from '../../scripts/utils/media.js'; import { getLibs, getIconElementDeprecated, decorateButtonsDeprecated } from '../../scripts/utils.js'; import { buildFreePlanWidget } from '../../scripts/widgets/free-plan.js'; -import { sendFrictionlessEventToAdobeAnaltics } from '../../scripts/instrument.js'; +import { sendFrictionlessEventToAdobeAnaltics } from '../../scripts/instrument.js' let createTag; let getConfig; -let loadScript; let getMetadata; +let getMetadata; +let loadScript; let globalNavSelector; let ccEverywhere; let quickActionContainer; @@ -40,6 +41,11 @@ const QA_CONFIGS = { ...getBaseImgCfg(JPG, JPEG, PNG), input_check: () => true, }, + 'qa-in-product-variant1': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + 'qa-in-product-variant2': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + 'qa-in-product-control': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + 'qa-nbs': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + }; function fade(element, action) { @@ -101,6 +107,7 @@ export function runQuickAction(quickAction, data, block) { parentElementId: `${quickAction}-container`, backgroundColor: 'transparent', hideCloseButton: true, + padding: 0, }; const docConfig = { @@ -110,8 +117,9 @@ export function runQuickAction(quickAction, data, block) { type: 'image', }, }; + const variant = new URLSearchParams(window.location.search).get('variant'); const appConfig = { - metaData: { isFrictionlessQa: 'true' }, + metaData: { isFrictionlessQa: 'true', variant, entryPoint: 'seo-quickaction-image-upload' }, receiveQuickActionErrors: false, callbacks: { onIntentChange: () => { @@ -156,6 +164,26 @@ export function runQuickAction(quickAction, data, block) { case 'generate-qr-code': ccEverywhere.quickAction.generateQRCode({}, appConfig, exportConfig, contConfig); break; + case 'qa-nbs': + ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); + break; + case 'qa-in-product-control': + ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); + break; + case 'qa-in-product-variant1': + document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; + ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { + ...contConfig, + mode: 'modal', + }); + break; + case 'qa-in-product-variant2': + document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; + ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { + ...contConfig, + mode: 'modal', + }); + break; default: break; } } @@ -187,6 +215,7 @@ async function startSDK(data = '', quickAction, block) { if (ietf === 'zh-Hant-TW') ietf = 'tw-TW'; else if (ietf === 'zh-Hans-CN') ietf = 'cn-CN'; + const baseQA = new URLSearchParams(window.location.search).get('base-qa'); const ccEverywhereConfig = { hostInfo: { clientId, @@ -195,6 +224,7 @@ async function startSDK(data = '', quickAction, block) { configParams: { locale: ietf?.replace('-', '_'), env: urlParams.get('hzenv') === 'stage' ? 'stage' : 'prod', + urlOverride: baseQA, }, authOption: () => ({ mode: 'delayed' }), }; @@ -248,9 +278,12 @@ async function startSDKWithUnconvertedFile(file, quickAction, block) { } export default async function decorate(block) { - await Promise.all([import(`${getLibs()}/utils/utils.js`), decorateButtonsDeprecated(block)]).then(([utils]) => { - ({ createTag, getConfig, loadScript, getMetadata } = utils); - }); + const [utils, gNavUtils] = await Promise.all([import(`${getLibs()}/utils/utils.js`), + import(`${getLibs()}/blocks/global-navigation/utilities/utilities.js`), + decorateButtonsDeprecated(block)]); + ({ createTag, getMetadata, loadScript, getConfig } = utils); + globalNavSelector = gNavUtils?.selectors.globalNav; + const rows = Array.from(block.children); rows[1].classList.add('fqa-container'); const quickActionRow = rows.filter((r) => r.children && r.children[0].textContent.toLowerCase().trim() === 'quick-action'); @@ -335,7 +368,6 @@ export default async function decorate(block) { const freePlanTags = await buildFreePlanWidget({ typeKey: 'branded', checkmarks: true }); dropzone.append(freePlanTags); - window.addEventListener('popstate', (e) => { const editorModal = selectElementByTagPrefix('cc-everywhere-container-'); const correctState = e.state?.hideFrictionlessQa; diff --git a/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.css b/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.css deleted file mode 100644 index d3137342..00000000 --- a/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.css +++ /dev/null @@ -1,196 +0,0 @@ -.frictionless-quick-action { - padding: 40px 20px; - max-width: none; - text-align: center; -} - -.section .frictionless-quick-action h1 { - font-size: 2.8125rem; - margin: 0; -} - -.frictionless-quick-action .express-logo { - width: initial; - height: 30px; -} - -.frictionless-quick-action h1+p { - margin: 16px 0 24px; - font-size: 1rem; -} - -.frictionless-quick-action input { - display: none; -} - -.frictionless-quick-action .quick-action-container { - padding: 40px 0; - min-height: 697px; - max-width: 1440px; - width: 100%; - margin: auto; - transition: opacity 0.2s; -} - -.frictionless-quick-action h1 em { - background: linear-gradient(320deg, #7C84F3, #FF4DD2, #FF993B, #FF4DD2, #7C84F3, #FF4DD2, #FF993B); - background-size: 400% 400%; - -webkit-animation: quickActionGradient 45s ease infinite; - -moz-animation: quickActionGradient 45s ease infinite; - animation: quickActionGradient 45s ease infinite; - -webkit-background-clip: text; - background-clip: text; - font-style: normal; - -webkit-text-fill-color: transparent; -} - -.frictionless-quick-action .fqa-container { - display: flex; - align-items: center; - justify-content: center; - transition: opacity 0.2s; - flex-wrap: wrap; -} - -.frictionless-quick-action .fqa-container > div:nth-child(2) { - margin-top: 26px; -} - -.frictionless-quick-action video, -.frictionless-quick-action img:not(.icon) { - max-width: 444px; -} - -.frictionless-quick-action .dropzone-container { - cursor: pointer; - padding: 24px 0; - border-radius: 20px; - box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3); - width: 630px; - height: 284px; -} - -.frictionless-quick-action .dropzone-bg { - position: absolute; - width: 100%; - height: 100%; - left: 0px; - background: url("/express/code/icons/dash-rectangle.svg") center center / 91% no-repeat; -} - -.frictionless-quick-action .dropzone-container.highlight .dropzone-bg { - filter: invert(0%) sepia(0%) saturate(7500%) hue-rotate(327deg) brightness(6%) contrast(104%); - transition: 0.3s ease-in-out; -} - -.frictionless-quick-action .dropzone-container:hover, .frictionless-quick-action .dropzone-container.highlight { - background-color: rgb(211, 211, 211, 0.2); -} - -.frictionless-quick-action .dropzone { - height: 100%; - width: 100%; - position: relative; -} - -.frictionless-quick-action .dropzone-bg + p { - margin: 0; - padding: 39px 24px 0 24px; - font-size: var(--heading-font-size-m); - font-weight: var(--heading-font-weight); - line-height: var(--heading-line-height); -} - -.frictionless-quick-action .dropzone-bg + p em { - font-style: normal; - color: var(--color-info-accent); -} - -.frictionless-quick-action .dropzone p:last-of-type { - font-size: .6875rem; - margin: 0; -} - -.frictionless-quick-action .dropzone .button { - margin-bottom: 0; -} - -.frictionless-quick-action .fqa-container > div:nth-child(2) > p:last-of-type { - margin: 15px 0 0; - font-size: 0.75rem; -} - -.frictionless-quick-action .free-plan-widget { - background-color: unset; - flex-direction: row; - padding: unset; - margin: 16px auto 0 auto; - gap: 8px; -} - -.frictionless-quick-action .free-plan-widget > div { - margin: 10px; -} - -main .section .frictionless-quick-action .free-plan-widget img.icon.icon-checkmark { - background-color: #f06dad; -} -.frictionless-quick-action .quick-action-container { - height: 667px; -} - -.frictionless-quick-action .quick-action-container > * { - height: 100%; -} - -.frictionless-quick-action .quick-action-container#resize-image-container { - height: 1080px; -} - -.frictionless-quick-action > div.hidden { - visibility: hidden; - position: absolute; -} - -.frictionless-quick-action > div.transparent { - opacity: 0; -} - -.frictionless-quick-action .error-toast { - position: fixed; - bottom: 100px; - left: 50%; - transform: translateX(-50%); - opacity: 1; - transition: opacity 1s; - z-index: 10; - margin: 0 auto; - color: white; - background-color: #d31510; - padding: 10px 16px; - display: flex; - align-items: center; - gap: 10px; - font-size: var(--body-font-size-s); - width: fit-content; - border-radius: 50px; -} - -.frictionless-quick-action .error-toast.hide { - opacity: 0; -} - -.frictionless-quick-action .error-toast button { - background-color: unset; - border: unset; - padding: unset; - display: flex; - align-items: center; - cursor: pointer; -} - -@media (min-width: 1200) { - .frictionless-quick-action .quick-action-container#resize-image-container { - height: 1000px; - } -} diff --git a/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js b/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js deleted file mode 100644 index 19ee6fbe..00000000 --- a/express/code/scripts/mep/aexg5201/frictionless-quick-action/frictionless-quick-action.js +++ /dev/null @@ -1,396 +0,0 @@ -import { - addAnimationToggle, - transformLinkToAnimation, -} from '../../../../scripts/utils/media.js' -import { getLibs, getIconElementDeprecated, decorateButtonsDeprecated } from '../../../../scripts/utils/utils.js'; -import { buildFreePlanWidget } from '../../../../scripts/utils/free-plan.js'; -import { sendFrictionlessEventToAdobeAnaltics } from '../../../../scripts/utils/instrument.js'; - -let createTag; let getConfig; -let getMetadata; -let loadScript; let globalNavSelector; - -let ccEverywhere; -let quickActionContainer; -let uploadContainer; - -const JPG = 'jpg'; -const JPEG = 'jpeg'; -const PNG = 'png'; -const WEBP = 'webp'; -export const getBaseImgCfg = (...types) => ({ - group: 'image', - max_size: 40 * 1024 * 1024, - accept: types.map((type) => `.${type}`).join(', '), - input_check: (input) => types.map((type) => `image/${type}`).includes(input), -}); -export const getBaseVideoCfg = (...types) => ({ - group: 'video', - max_size: 1024 * 1024 * 1024, - accept: types.map((type) => `.${type}`).join(', '), - input_check: (input) => types.map((type) => `video/${type}`).includes(input), -}); -const QA_CONFIGS = { - 'convert-to-jpg': { ...getBaseImgCfg(PNG, WEBP) }, - 'convert-to-png': { ...getBaseImgCfg(JPG, JPEG, WEBP) }, - 'convert-to-svg': { ...getBaseImgCfg(JPG, JPEG, PNG) }, - 'crop-image': { ...getBaseImgCfg(JPG, JPEG, PNG) }, - 'resize-image': { ...getBaseImgCfg(JPG, JPEG, PNG, WEBP) }, - 'remove-background': { ...getBaseImgCfg(JPG, JPEG, PNG) }, - 'generate-qr-code': { - ...getBaseImgCfg(JPG, JPEG, PNG), - input_check: () => true, - }, - 'qa-in-product-variant1': { ...getBaseImgCfg(JPG, JPEG, PNG) }, - 'qa-in-product-variant2': { ...getBaseImgCfg(JPG, JPEG, PNG) }, - 'qa-in-product-control': { ...getBaseImgCfg(JPG, JPEG, PNG) }, - 'qa-nbs': { ...getBaseImgCfg(JPG, JPEG, PNG) }, - -}; - -function fade(element, action) { - if (action === 'in') { - element.classList.remove('hidden'); - setTimeout(() => { - element.classList.remove('transparent'); - }, 10); - } else if (action === 'out') { - element.classList.add('transparent'); - setTimeout(() => { - element.classList.add('hidden'); - }, 200); - } -} - -function selectElementByTagPrefix(p) { - const allEls = document.body.querySelectorAll(':scope > *'); - return Array.from(allEls).find((e) => e.tagName.toLowerCase().startsWith(p.toLowerCase())); -} - -// eslint-disable-next-line default-param-last -export function runQuickAction(quickAction, data, block) { - // TODO: need the button labels from the placeholders sheet if the SDK default doens't work. - const exportConfig = [ - { - id: 'download-button', - // label: 'Download', - action: { target: 'download' }, - style: { uiType: 'button' }, - buttonStyle: { - variant: 'secondary', - treatment: 'fill', - size: 'xl', - }, - }, - { - id: 'edit-in-express', - // label: 'Edit in Adobe Express for free', - action: { target: 'express' }, - style: { uiType: 'button' }, - buttonStyle: { - variant: 'primary', - treatment: 'fill', - size: 'xl', - }, - }, - ]; - - const id = `${quickAction}-container`; - quickActionContainer = createTag('div', { id, class: 'quick-action-container' }); - block.append(quickActionContainer); - const divs = block.querySelectorAll(':scope > div'); - if (divs[1]) [, uploadContainer] = divs; - fade(uploadContainer, 'out'); - - const contConfig = { - mode: 'inline', - parentElementId: `${quickAction}-container`, - backgroundColor: 'transparent', - hideCloseButton: true, - padding: 0, - }; - - const docConfig = { - asset: { - data, - dataType: 'base64', - type: 'image', - }, - }; - const variant = new URLSearchParams(window.location.search).get('variant'); - const appConfig = { - metaData: { isFrictionlessQa: 'true', variant, entryPoint: 'seo-quickaction-image-upload' }, - receiveQuickActionErrors: false, - callbacks: { - onIntentChange: () => { - quickActionContainer?.remove(); - fade(uploadContainer, 'in'); - document.body.classList.add('editor-modal-loaded'); - window.history.pushState({ hideFrictionlessQa: true }, '', ''); - return { - containerConfig: { - mode: 'modal', - zIndex: 999, - }, - }; - }, - onCancel: () => { - window.history.back(); - }, - }, - }; - - if (!ccEverywhere) return; - switch (quickAction) { - case 'convert-to-jpg': - ccEverywhere.quickAction.convertToJPEG(docConfig, appConfig, exportConfig, contConfig); - break; - case 'convert-to-png': - ccEverywhere.quickAction.convertToPNG(docConfig, appConfig, exportConfig, contConfig); - break; - case 'convert-to-svg': - exportConfig.pop(); - ccEverywhere.quickAction.convertToSVG(docConfig, appConfig, exportConfig, contConfig); - break; - case 'crop-image': - ccEverywhere.quickAction.cropImage(docConfig, appConfig, exportConfig, contConfig); - break; - case 'resize-image': - ccEverywhere.quickAction.resizeImage(docConfig, appConfig, exportConfig, contConfig); - break; - case 'remove-background': - ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); - break; - case 'generate-qr-code': - ccEverywhere.quickAction.generateQRCode({}, appConfig, exportConfig, contConfig); - break; - case 'qa-nbs': - ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); - break; - case 'qa-in-product-control': - ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); - break; - case 'qa-in-product-variant1': - document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; - ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { - ...contConfig, - mode: 'modal', - }); - break; - case 'qa-in-product-variant2': - document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; - ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { - ...contConfig, - mode: 'modal', - }); - break; - default: break; - } -} - -// eslint-disable-next-line default-param-last -async function startSDK(data = '', quickAction, block) { - const urlParams = new URLSearchParams(window.location.search); - const urlOverride = urlParams.get('sdk-override'); - let valid = false; - if (urlOverride) { - try { - if (new URL(urlOverride).host === 'dev.cc-embed.adobe.com') valid = true; - } catch (e) { - window.lana.log('Invalid SDK URL'); - } - } - const CDN_URL = valid ? urlOverride : 'https://cc-embed.adobe.com/sdk/1p/v4/CCEverywhere.js'; - const clientId = 'AdobeExpressWeb'; - - await loadScript(CDN_URL); - if (!window.CCEverywhere) { - return; - } - - if (!ccEverywhere) { - let { ietf } = getConfig().locale; - const country = urlParams.get('country'); - if (country) ietf = getConfig().locales[country]?.ietf; - if (ietf === 'zh-Hant-TW') ietf = 'tw-TW'; - else if (ietf === 'zh-Hans-CN') ietf = 'cn-CN'; - - const baseQA = new URLSearchParams(window.location.search).get('base-qa'); - const ccEverywhereConfig = { - hostInfo: { - clientId, - appName: 'express', - }, - configParams: { - locale: ietf?.replace('-', '_'), - env: urlParams.get('hzenv') === 'stage' ? 'stage' : 'prod', - urlOverride: baseQA, - }, - authOption: () => ({ mode: 'delayed' }), - }; - - ccEverywhere = await window.CCEverywhere.initialize(...Object.values(ccEverywhereConfig)); - } - - runQuickAction(quickAction, data, block); -} - -let timeoutId = null; -function showErrorToast(block, msg) { - let toast = block.querySelector('.error-toast'); - const hideToast = () => toast.classList.add('hide'); - if (!toast) { - toast = createTag('div', { class: 'error-toast hide' }); - toast.prepend(getIconElementDeprecated('error')); - const close = createTag('button', {}, getIconElementDeprecated('close-white')); - close.addEventListener('click', hideToast); - toast.append(close); - block.append(toast); - } - toast.textContent = msg; - toast.classList.remove('hide'); - clearTimeout(timeoutId); - timeoutId = setTimeout(hideToast, 6000); -} - -async function startSDKWithUnconvertedFile(file, quickAction, block) { - if (!file) return; - const maxSize = QA_CONFIGS[quickAction].max_size ?? 40 * 1024 * 1024; - if (QA_CONFIGS[quickAction].input_check(file.type) && file.size <= maxSize) { - const reader = new FileReader(); - reader.onloadend = () => { - window.history.pushState({ hideFrictionlessQa: true }, '', ''); - startSDK(reader.result, quickAction, block); - }; - - // Read the file as a data URL (Base64) - reader.readAsDataURL(file); - return; - } - const { replaceKey } = await import(`${getLibs()}/features/placeholders.js`); - let msg; - if (!QA_CONFIGS[quickAction].input_check(file.type)) { - msg = await replaceKey('file-type-not-supported', getConfig()); - } else { - msg = await replaceKey('file-size-not-supported', getConfig()); - } - showErrorToast(block, msg); -} - -export default async function decorate(block) { - const [utils, gNavUtils] = await Promise.all([import(`${getLibs()}/utils/utils.js`), - import(`${getLibs()}/blocks/global-navigation/utilities/utilities.js`), - decorateButtonsDeprecated(block)]); - ({ createTag, getMetadata, loadScript, getConfig } = utils); - globalNavSelector = gNavUtils?.selectors.globalNav; - - const rows = Array.from(block.children); - rows[1].classList.add('fqa-container'); - const quickActionRow = rows.filter((r) => r.children && r.children[0].textContent.toLowerCase().trim() === 'quick-action'); - const quickAction = quickActionRow?.[0].children[1]?.textContent; - if (!quickAction) { - throw new Error('Invalid Quick Action Type.'); - } - quickActionRow[0].remove(); - - const actionAndAnimationRow = rows[1].children; - const animationContainer = actionAndAnimationRow[0]; - const animation = animationContainer.querySelector('a'); - const dropzone = actionAndAnimationRow[1]; - const dropzoneBackground = createTag('div', { class: 'dropzone-bg' }); - const cta = dropzone.querySelector('a.button, a.con-button'); - const gtcText = dropzone.querySelector('p:last-child'); - const actionColumn = createTag('div'); - const dropzoneContainer = createTag('div', { class: 'dropzone-container' }); - - if (animation && animation.href.includes('.mp4')) { - transformLinkToAnimation(animation); - addAnimationToggle(animationContainer); - } - if (cta) cta.classList.add('xlarge'); - dropzone.classList.add('dropzone'); - - dropzone.prepend(dropzoneBackground); - dropzone.before(actionColumn); - dropzoneContainer.append(dropzone); - actionColumn.append(dropzoneContainer, gtcText); - const inputElement = createTag('input', { type: 'file', accept: QA_CONFIGS[quickAction].accept }); - inputElement.onchange = () => { - const file = inputElement.files[0]; - startSDKWithUnconvertedFile(file, quickAction, block); - }; - block.append(inputElement); - - dropzoneContainer.addEventListener('click', (e) => { - e.preventDefault(); - if (quickAction === 'generate-qr-code') { - startSDK('', quickAction, block); - } else { - inputElement.click(); - } - document.body.dataset.suppressfloatingcta = 'true'; - }); - - function preventDefaults(e) { - e.preventDefault(); - e.stopPropagation(); - } - - function highlight() { - dropzoneContainer.classList.add('highlight'); - } - - function unhighlight() { - dropzoneContainer.classList.remove('highlight'); - } - - ['dragenter', 'dragover'].forEach((eventName) => { - dropzoneContainer.addEventListener(eventName, highlight, false); - }); - - ['dragenter', 'dragover', 'dragleave', 'drop'].forEach((eventName) => { - dropzoneContainer.addEventListener(eventName, preventDefaults, false); - }); - - ['dragleave', 'drop'].forEach((eventName) => { - dropzoneContainer.addEventListener(eventName, unhighlight, false); - }); - - dropzoneContainer.addEventListener('drop', async (e) => { - const dt = e.dataTransfer; - const { files } = dt; - - await Promise.all( - [...files].map((file) => startSDKWithUnconvertedFile(file, quickAction, block)), - ); - document.body.dataset.suppressfloatingcta = 'true'; - }, false); - - const freePlanTags = await buildFreePlanWidget({ typeKey: 'branded', checkmarks: true }); - dropzone.append(freePlanTags); - window.addEventListener('popstate', (e) => { - const editorModal = selectElementByTagPrefix('cc-everywhere-container-'); - const correctState = e.state?.hideFrictionlessQa; - const embedElsFound = quickActionContainer || editorModal; - window.history.pushState({ hideFrictionlessQa: true }, '', ''); - if (correctState || embedElsFound) { - quickActionContainer?.remove(); - editorModal?.remove(); - document.body.classList.remove('editor-modal-loaded'); - inputElement.value = ''; - fade(uploadContainer, 'in'); - document.body.dataset.suppressfloatingcta = 'false'; - } - }, { passive: true }); - - block.dataset.frictionlesstype = quickAction; - block.dataset.frictionlessgroup = QA_CONFIGS[quickAction].group ?? 'image'; - - if (['on', 'yes'].includes(getMetadata('marquee-inject-logo')?.toLowerCase())) { - const logo = getIconElementDeprecated('adobe-express-logo'); - logo.classList.add('express-logo'); - block.prepend(logo); - } - - sendFrictionlessEventToAdobeAnaltics(block); -} From 699bf303dfc2488c7ff015b863440bbb7a8ca216 Mon Sep 17 00:00:00 2001 From: echen-adobe Date: Tue, 11 Mar 2025 13:32:02 -0700 Subject: [PATCH 11/16] Update frictionless-quick-action.js --- .../frictionless-quick-action/frictionless-quick-action.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js index 3986099e..698832e4 100644 --- a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js +++ b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js @@ -44,7 +44,7 @@ const QA_CONFIGS = { 'qa-in-product-variant1': { ...getBaseImgCfg(JPG, JPEG, PNG) }, 'qa-in-product-variant2': { ...getBaseImgCfg(JPG, JPEG, PNG) }, 'qa-in-product-control': { ...getBaseImgCfg(JPG, JPEG, PNG) }, - 'qa-nbs': { ...getBaseImgCfg(JPG, JPEG, PNG) }, + 'qa-nba': { ...getBaseImgCfg(JPG, JPEG, PNG) }, }; @@ -164,7 +164,7 @@ export function runQuickAction(quickAction, data, block) { case 'generate-qr-code': ccEverywhere.quickAction.generateQRCode({}, appConfig, exportConfig, contConfig); break; - case 'qa-nbs': + case 'qa-nba': ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); break; case 'qa-in-product-control': From 42ffad5154d8e6a271151651f3b4c91df5caee5c Mon Sep 17 00:00:00 2001 From: echen-adobe Date: Wed, 12 Mar 2025 08:46:42 -0700 Subject: [PATCH 12/16] Squashed commit of the following: commit 3e2d3ef0e392f0a636333c7722d885b6955fffbe Author: echen-adobe Date: Wed Mar 12 08:37:24 2025 -0700 Update frictionless-quick-action.js commit 14e8d85e17d5c9ddd776da96bb5a54288165234b Author: echen-adobe Date: Wed Mar 12 08:36:17 2025 -0700 Update frictionless-quick-action.js commit 67b2bbf8ee98c8383f18305fc85598c3f77198df Author: echen-adobe Date: Wed Mar 12 08:34:53 2025 -0700 Update frictionless-quick-action.js commit 6429bfa67f79073bcbc40a8a03f2d151b6d303c1 Author: echen-adobe Date: Wed Mar 12 08:30:49 2025 -0700 Update frictionless-quick-action.js commit e8f1b52a56ba6c5d9eeaf7c8348ab4eff2dd3462 Author: echen-adobe Date: Tue Mar 11 13:50:29 2025 -0700 Update frictionless-quick-action.js commit 3625016406199252047d78925b930b089b426991 Author: echen-adobe Date: Tue Mar 11 13:48:54 2025 -0700 Update frictionless-quick-action.js commit 5b8315c769d2a47e6f5296eda6a8f462ad27a6b9 Author: echen-adobe Date: Tue Mar 11 13:43:08 2025 -0700 Update frictionless-quick-action.js commit ed0361f5579f24820dabb7b5cf98d5dd1a594540 Author: echen-adobe Date: Tue Mar 11 13:42:04 2025 -0700 Update frictionless-quick-action.js commit 809f0e8812a32eb01fa3aff121557ea3f0709a78 Author: echen-adobe Date: Tue Mar 11 13:39:52 2025 -0700 Update frictionless-quick-action.js commit 10a003096e8383bcd764ec860e1c8320142fd02e Author: echen-adobe Date: Tue Mar 11 13:38:03 2025 -0700 Update frictionless-quick-action.js --- .../frictionless-quick-action/frictionless-quick-action.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js index 698832e4..e2b14fa5 100644 --- a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js +++ b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js @@ -117,7 +117,8 @@ export function runQuickAction(quickAction, data, block) { type: 'image', }, }; - const variant = new URLSearchParams(window.location.search).get('variant'); + const urlParams = new URLSearchParams(window.location.search) + const variant = (urlParams.get('hzenv') === 'stage' && urlParams.get('variant')) || quickAction; const appConfig = { metaData: { isFrictionlessQa: 'true', variant, entryPoint: 'seo-quickaction-image-upload' }, receiveQuickActionErrors: false, @@ -171,13 +172,15 @@ export function runQuickAction(quickAction, data, block) { ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); break; case 'qa-in-product-variant1': + appConfig.metaData.isFrictionlessQa = false document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { ...contConfig, mode: 'modal', - }); + }) break; case 'qa-in-product-variant2': + appConfig.metaData.isFrictionlessQa = false document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { ...contConfig, From 66f797c103188d6b0f3593c97195394a0efe174c Mon Sep 17 00:00:00 2001 From: echen-adobe Date: Wed, 12 Mar 2025 08:57:12 -0700 Subject: [PATCH 13/16] Update frictionless-quick-action.js --- .../frictionless-quick-action/frictionless-quick-action.js | 1 + 1 file changed, 1 insertion(+) diff --git a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js index e2b14fa5..cc2b4840 100644 --- a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js +++ b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js @@ -119,6 +119,7 @@ export function runQuickAction(quickAction, data, block) { }; const urlParams = new URLSearchParams(window.location.search) const variant = (urlParams.get('hzenv') === 'stage' && urlParams.get('variant')) || quickAction; + const appConfig = { metaData: { isFrictionlessQa: 'true', variant, entryPoint: 'seo-quickaction-image-upload' }, receiveQuickActionErrors: false, From b2567c73efb2d0f372e638e6354a875a22cdb597 Mon Sep 17 00:00:00 2001 From: echen-adobe Date: Wed, 12 Mar 2025 09:01:50 -0700 Subject: [PATCH 14/16] Update frictionless-quick-action.js --- .../frictionless-quick-action.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js index 6327c9fe..4d2bfa14 100644 --- a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js +++ b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js @@ -7,7 +7,8 @@ import { buildFreePlanWidget } from '../../scripts/widgets/free-plan.js'; import { sendFrictionlessEventToAdobeAnaltics } from '../../scripts/instrument.js' let createTag; let getConfig; -let loadScript; let getMetadata; +let getMetadata; +let loadScript; let globalNavSelector; let ccEverywhere; let quickActionContainer; @@ -105,6 +106,7 @@ export function runQuickAction(quickAction, data, block) { parentElementId: `${quickAction}-container`, backgroundColor: 'transparent', hideCloseButton: true, + padding: 0, }; const docConfig = { @@ -215,7 +217,7 @@ async function startSDK(data = '', quickAction, block) { if (country) ietf = getConfig().locales[country]?.ietf; if (ietf === 'zh-Hant-TW') ietf = 'tw-TW'; else if (ietf === 'zh-Hans-CN') ietf = 'cn-CN'; - + const baseQA = new URLSearchParams(window.location.search).get('base-qa'); const ccEverywhereConfig = { hostInfo: { clientId, @@ -224,6 +226,7 @@ async function startSDK(data = '', quickAction, block) { configParams: { locale: ietf?.replace('-', '_'), env: urlParams.get('hzenv') === 'stage' ? 'stage' : 'prod', + urlOverride: baseQA, }, authOption: () => ({ mode: 'delayed' }), }; @@ -277,9 +280,12 @@ async function startSDKWithUnconvertedFile(file, quickAction, block) { } export default async function decorate(block) { - await Promise.all([import(`${getLibs()}/utils/utils.js`), decorateButtonsDeprecated(block)]).then(([utils]) => { - ({ createTag, getConfig, loadScript, getMetadata } = utils); - }); + const [utils, gNavUtils] = await Promise.all([import(`${getLibs()}/utils/utils.js`), + import(`${getLibs()}/blocks/global-navigation/utilities/utilities.js`), + decorateButtonsDeprecated(block)]); + ({ createTag, getMetadata, loadScript, getConfig } = utils); + globalNavSelector = gNavUtils?.selectors.globalNav; + const rows = Array.from(block.children); rows[1].classList.add('fqa-container'); const quickActionRow = rows.filter((r) => r.children && r.children[0].textContent.toLowerCase().trim() === 'quick-action'); From a445b9aad4b401b936d852f6b31e3e5b53b7e549 Mon Sep 17 00:00:00 2001 From: echen-adobe Date: Wed, 12 Mar 2025 11:14:21 -0700 Subject: [PATCH 15/16] Squashed commit of the following: commit 3681f6416fd813246ba2d3472e59ec8172990f68 Author: echen-adobe Date: Wed Mar 12 11:12:24 2025 -0700 Update frictionless-quick-action.js commit af5e4e2c8f2f33754bdac445fd6c85798e460395 Author: echen-adobe Date: Wed Mar 12 11:04:22 2025 -0700 Update frictionless-quick-action.js commit 911c8c856b2b21a9382710a8f7bae19ef7384df1 Author: echen-adobe Date: Wed Mar 12 11:04:00 2025 -0700 Update frictionless-quick-action.js commit 412c55bc0ddc8abfa618db396d926711fc15c0b7 Author: echen-adobe Date: Wed Mar 12 09:20:14 2025 -0700 Update frictionless-quick-action.js commit fba3a52cc57169611cc8aa213f683aeb4585a0f7 Author: echen-adobe Date: Wed Mar 12 09:14:08 2025 -0700 Update frictionless-quick-action.js commit 4e371695608fff686eae15e13cdb08a355890816 Author: echen-adobe Date: Wed Mar 12 09:11:40 2025 -0700 Update frictionless-quick-action.js --- .../frictionless-quick-action.js | 80 ++++++++++++++----- 1 file changed, 58 insertions(+), 22 deletions(-) diff --git a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js index 4d2bfa14..9656e68a 100644 --- a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js +++ b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js @@ -4,7 +4,7 @@ import { } from '../../scripts/utils/media.js'; import { getLibs, getIconElementDeprecated, decorateButtonsDeprecated } from '../../scripts/utils.js'; import { buildFreePlanWidget } from '../../scripts/widgets/free-plan.js'; -import { sendFrictionlessEventToAdobeAnaltics } from '../../scripts/instrument.js' +import { sendFrictionlessEventToAdobeAnaltics } from '../../scripts/instrument.js'; let createTag; let getConfig; let getMetadata; @@ -66,6 +66,40 @@ function selectElementByTagPrefix(p) { return Array.from(allEls).find((e) => e.tagName.toLowerCase().startsWith(p.toLowerCase())); } +function frictionlessQAExperiment(quickAction, docConfig, appConfig, exportConfig, contConfig) { + const urlParams = new URLSearchParams(window.location.search); + const urlVariant = urlParams.get('variant'); + const isStage = urlParams.get('hzenv') === 'stage'; + const variant = isStage && urlVariant ? urlVariant : quickAction; + appConfig.metaData.variant = variant; + switch (variant) { + case 'qa-nba': + ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); + break; + case 'qa-in-product-control': + ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); + break; + case 'qa-in-product-variant1': + appConfig.metaData.isFrictionlessQa = false; + document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; + ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { + ...contConfig, + mode: 'modal', + }); + break; + case 'qa-in-product-variant2': + appConfig.metaData.isFrictionlessQa = false; + document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; + ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { + ...contConfig, + mode: 'modal', + }); + break; + default: + break; + } +} + // eslint-disable-next-line default-param-last export function runQuickAction(quickAction, data, block) { // TODO: need the button labels from the placeholders sheet if the SDK default doens't work. @@ -116,11 +150,9 @@ export function runQuickAction(quickAction, data, block) { type: 'image', }, }; - const urlParams = new URLSearchParams(window.location.search) - const variant = (urlParams.get('hzenv') === 'stage' && urlParams.get('variant')) || quickAction; - + const appConfig = { - metaData: { isFrictionlessQa: 'true' , variant }, + metaData: { isFrictionlessQa: 'true' }, receiveQuickActionErrors: false, callbacks: { onIntentChange: () => { @@ -141,6 +173,10 @@ export function runQuickAction(quickAction, data, block) { }, }; + const urlParams = new URLSearchParams(window.location.search); + const variant = urlParams.get('variant'); + const isStage = urlParams.get('hzenv') === 'stage'; + if (!ccEverywhere) return; switch (quickAction) { case 'convert-to-jpg': @@ -160,32 +196,29 @@ export function runQuickAction(quickAction, data, block) { ccEverywhere.quickAction.resizeImage(docConfig, appConfig, exportConfig, contConfig); break; case 'remove-background': + + if (variant && isStage) { + frictionlessQAExperiment(variant, docConfig, appConfig, exportConfig, contConfig); + break; + } + ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); break; case 'generate-qr-code': ccEverywhere.quickAction.generateQRCode({}, appConfig, exportConfig, contConfig); break; + // Experiment code, remove after done case 'qa-nba': - ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); + frictionlessQAExperiment(quickAction, docConfig, appConfig, exportConfig, contConfig); break; case 'qa-in-product-control': - ccEverywhere.quickAction.removeBackground(docConfig, appConfig, exportConfig, contConfig); + frictionlessQAExperiment(quickAction, docConfig, appConfig, exportConfig, contConfig); break; case 'qa-in-product-variant1': - appConfig.metaData.isFrictionlessQa = false - document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; - ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { - ...contConfig, - mode: 'modal', - }) + frictionlessQAExperiment(quickAction, docConfig, appConfig, exportConfig, contConfig); break; case 'qa-in-product-variant2': - appConfig.metaData.isFrictionlessQa = false - document.querySelector(`${globalNavSelector}.ready`).style.display = 'none'; - ccEverywhere.editor.createWithAsset(docConfig, appConfig, exportConfig, { - ...contConfig, - mode: 'modal', - }); + frictionlessQAExperiment(quickAction, docConfig, appConfig, exportConfig, contConfig); break; default: break; } @@ -217,6 +250,9 @@ async function startSDK(data = '', quickAction, block) { if (country) ietf = getConfig().locales[country]?.ietf; if (ietf === 'zh-Hant-TW') ietf = 'tw-TW'; else if (ietf === 'zh-Hans-CN') ietf = 'cn-CN'; + // query parameter URL for overriding the cc everywhere + // iframe source URL, used for testing new experiences + const isStageEnv = urlParams.get('hzenv') === 'stage'; const baseQA = new URLSearchParams(window.location.search).get('base-qa'); const ccEverywhereConfig = { hostInfo: { @@ -225,8 +261,8 @@ async function startSDK(data = '', quickAction, block) { }, configParams: { locale: ietf?.replace('-', '_'), - env: urlParams.get('hzenv') === 'stage' ? 'stage' : 'prod', - urlOverride: baseQA, + env: isStageEnv ? 'stage' : 'prod', + urlOverride: isStageEnv ? baseQA : undefined, }, authOption: () => ({ mode: 'delayed' }), }; @@ -285,7 +321,7 @@ export default async function decorate(block) { decorateButtonsDeprecated(block)]); ({ createTag, getMetadata, loadScript, getConfig } = utils); globalNavSelector = gNavUtils?.selectors.globalNav; - + const rows = Array.from(block.children); rows[1].classList.add('fqa-container'); const quickActionRow = rows.filter((r) => r.children && r.children[0].textContent.toLowerCase().trim() === 'quick-action'); From 0be496ffa213f2175385c51be868c88a23957193 Mon Sep 17 00:00:00 2001 From: echen-adobe Date: Wed, 12 Mar 2025 11:16:49 -0700 Subject: [PATCH 16/16] Update frictionless-quick-action.js --- .../frictionless-quick-action/frictionless-quick-action.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js index 9656e68a..7efb10c2 100644 --- a/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js +++ b/express/code/blocks/frictionless-quick-action/frictionless-quick-action.js @@ -250,7 +250,7 @@ async function startSDK(data = '', quickAction, block) { if (country) ietf = getConfig().locales[country]?.ietf; if (ietf === 'zh-Hant-TW') ietf = 'tw-TW'; else if (ietf === 'zh-Hans-CN') ietf = 'cn-CN'; - // query parameter URL for overriding the cc everywhere + // query parameter URL for overriding the cc everywhere // iframe source URL, used for testing new experiences const isStageEnv = urlParams.get('hzenv') === 'stage'; const baseQA = new URLSearchParams(window.location.search).get('base-qa');