diff --git a/libs/blocks/global-navigation/features/profile/dropdown.js b/libs/blocks/global-navigation/features/profile/dropdown.js index 6c41fb5eec..d6f0a19ee0 100644 --- a/libs/blocks/global-navigation/features/profile/dropdown.js +++ b/libs/blocks/global-navigation/features/profile/dropdown.js @@ -78,8 +78,6 @@ class ProfileDropdown { this.placeholders.manageEnterprise, this.placeholders.profileAvatar, ], - // TODO: sanity checks if the user is logged in and mandatory properties are set. - // If not, add logs providing guidance for developers { displayName: this.profileData.displayName, email: this.profileData.email }, ] = await Promise.all([ replaceKeyArray( diff --git a/libs/blocks/global-navigation/features/search/gnav-search.js b/libs/blocks/global-navigation/features/search/gnav-search.js index 993084774d..38a886116a 100644 --- a/libs/blocks/global-navigation/features/search/gnav-search.js +++ b/libs/blocks/global-navigation/features/search/gnav-search.js @@ -129,8 +129,6 @@ class Search { this.isDesktop.addEventListener('change', () => { closeAllDropdowns(); }); - - // TODO: search menu should close on scroll, but this should happen from the general Menu logic } getSuggestions(query = this.query) { diff --git a/libs/blocks/global-navigation/global-navigation.js b/libs/blocks/global-navigation/global-navigation.js index d1a164f75a..cc848b111b 100644 --- a/libs/blocks/global-navigation/global-navigation.js +++ b/libs/blocks/global-navigation/global-navigation.js @@ -256,14 +256,11 @@ class Gnav { }; loadIMS = () => { - const { locale, imsClientId, env } = getConfig(); + const { locale, imsClientId, imsScope, env } = getConfig(); if (!imsClientId) return null; - // TODO-1 scopes should be defineable by the consumers - // We didn't have a use-case for that so far - // TODO-2 we should emit an event after the onReady callback window.adobeid = { client_id: imsClientId, - scope: 'AdobeID,openid,gnav', + scope: imsScope, locale: locale?.ietf?.replace('-', '_') || 'en_US', autoValidateToken: true, environment: env.ims, @@ -337,7 +334,6 @@ class Gnav { }; decorateAppLauncher = () => { - // TODO: review App Launcher component // const appLauncherBlock = this.body.querySelector('.app-launcher'); // if (appLauncherBlock) { // await this.loadDelayed(); @@ -633,7 +629,7 @@ class Gnav { export default async function init(header) { const { locale } = getConfig(); - // TODO locale.contentRoot is not the fallback we want + // TODO locale.contentRoot is not the fallback we want if we implement centralized content const url = getMetadata('gnav-source') || `${locale.contentRoot}/gnav`; const resp = await fetch(`${url}.plain.html`); const html = await resp.text(); diff --git a/libs/blocks/global-navigation/utilities/getUserEntitlements.js b/libs/blocks/global-navigation/utilities/getUserEntitlements.js index 9e70635dcc..d322dc2d02 100644 --- a/libs/blocks/global-navigation/utilities/getUserEntitlements.js +++ b/libs/blocks/global-navigation/utilities/getUserEntitlements.js @@ -4,19 +4,11 @@ import { getConfig } from '../../../utils/utils.js'; const API_WAIT_TIMEOUT = 10000; const entitlements = {}; -const getAcceptLanguage = (locale) => { - let languages = []; - if (!locale || Object.keys(locale).length === 0) { - return languages; - } - - languages = [ - `${locale.language}-${locale.country.toUpperCase()}`, - `${locale.language};q=0.9`, - 'en;q=0.8', - ]; - return languages; -}; +const getAcceptLanguage = (locale = 'en-US') => [ + `${locale}`, + `${locale.split('-')[0]};q=0.9`, + 'en;q=0.8', +].join(','); const getQueryParameters = (params) => { const query = []; @@ -94,9 +86,10 @@ const mapSubscriptionCodes = (offers) => { }; }; -const getSubscriptions = async ({ queryParams, locale }) => { +const getSubscriptions = async ({ queryParams }) => { + const config = getConfig(); const profile = await window.adobeIMS.getProfile(); - const apiUrl = getConfig().env.name === 'prod' + const apiUrl = config.env.name === 'prod' ? `https://www.adobe.com/aos-api/users/${profile.userId}/subscriptions` : `https://www.stage.adobe.com/aos-api/users/${profile.userId}/subscriptions`; const res = await fetch(`${apiUrl}${queryParams}`, { @@ -107,7 +100,7 @@ const getSubscriptions = async ({ queryParams, locale }) => { headers: { Authorization: `Bearer ${window.adobeIMS.getAccessToken().token}`, 'X-Api-Key': window.adobeIMS.adobeIdData.client_id, - 'Accept-Language': getAcceptLanguage(locale).join(','), + 'Accept-Language': getAcceptLanguage(config.locale.ietf), }, }) .then((response) => (response.status === 200 ? response.json() : emptyEntitlements)); @@ -118,12 +111,10 @@ const getSubscriptions = async ({ queryParams, locale }) => { * @description Return the JIL User Entitlements * @param {object} object required params * @param {array} object.params array of name value query parameters [{name: 'Q', value: 'PARAM'}] - * @param {object} object.locale {country: 'CH', language: 'de'} * @param {string} object.format format function, raw or default * @returns {object} JIL Entitlements */ -// TODO the locale could use the milo format, currently that's an AEM relic. -const getUserEntitlements = async ({ params, locale, format } = {}) => { +const getUserEntitlements = async ({ params, format } = {}) => { if (!window.adobeIMS?.isSignedInUser()) return Promise.resolve(emptyEntitlements); const queryParams = getQueryParameters(params); @@ -137,8 +128,7 @@ const getUserEntitlements = async ({ params, locale, format } = {}) => { entitlements[queryParams] = entitlements[queryParams] || new Promise((resolve) => { - // TODO we might need to format data for analytics - getSubscriptions({ queryParams, locale }) + getSubscriptions({ queryParams }) .then((data) => resolve(data)) .catch(() => resolve(emptyEntitlements)); }); diff --git a/libs/blocks/global-navigation/utilities/keyboard/mainNav.js b/libs/blocks/global-navigation/utilities/keyboard/mainNav.js index 2793e64254..6791e4ddaa 100644 --- a/libs/blocks/global-navigation/utilities/keyboard/mainNav.js +++ b/libs/blocks/global-navigation/utilities/keyboard/mainNav.js @@ -39,7 +39,6 @@ class MainNavItem { closeAllDropdowns(); break; } - // TODO popup navigation logic. case 'ArrowLeft': { if (document.dir !== 'rtl') { if (this.prev === -1) break; diff --git a/libs/blocks/global-navigation/utilities/onImsReady.js b/libs/blocks/global-navigation/utilities/onImsReady.js new file mode 100644 index 0000000000..3e9122e432 --- /dev/null +++ b/libs/blocks/global-navigation/utilities/onImsReady.js @@ -0,0 +1,31 @@ +let ready = false; +let existingCall = null; +const onInstance = 'onImsLibInstance'; + +const onImsReady = (timeout = 3000) => { + existingCall = existingCall || new Promise((resolve, reject) => { + const onFail = () => { + if (!ready) reject(); + }; + const waitTimeout = setTimeout(onFail, timeout); + const onSuccess = (data) => { + const instance = data?.detail?.instance; + if (!instance) { + reject(); + return; + } + + ready = true; + window.removeEventListener(onInstance, onSuccess); + clearTimeout(waitTimeout); + resolve(instance); + }; + + window.addEventListener(onInstance, onSuccess); + window.dispatchEvent(new window.CustomEvent('getImsLibInstance')); + }); + + return existingCall; +}; + +export default onImsReady; diff --git a/libs/blocks/global-navigation/utilities/utilities.js b/libs/blocks/global-navigation/utilities/utilities.js index e8b72eb687..06fa2f99a6 100644 --- a/libs/blocks/global-navigation/utilities/utilities.js +++ b/libs/blocks/global-navigation/utilities/utilities.js @@ -123,7 +123,7 @@ export function closeAllDropdowns({ e } = {}) { el.setAttribute('daa-lh', 'header|Open'); } }); - // TODO the curtain will be refactored + document.querySelector(selectors.curtain)?.classList.remove('is-open'); } diff --git a/libs/scripts/scripts.js b/libs/scripts/scripts.js index ad61af61e8..b1943f074f 100644 --- a/libs/scripts/scripts.js +++ b/libs/scripts/scripts.js @@ -109,6 +109,7 @@ const config = { fallbackRouting: 'on', links: 'on', imsClientId: 'milo', + imsScope: 'AdobeID,openid,gnav', codeRoot: '/libs', locales, prodDomains,