diff --git a/libs/blocks/global-navigation/blocks/appLauncher/appLauncher.js b/libs/blocks/global-navigation/blocks/appLauncher/appLauncher.js
index 43a7ebc473f..e54e2ca1e70 100644
--- a/libs/blocks/global-navigation/blocks/appLauncher/appLauncher.js
+++ b/libs/blocks/global-navigation/blocks/appLauncher/appLauncher.js
@@ -47,9 +47,6 @@ function decorateAppsMenu(profileEl, appsDom, toggle) {
}
async function appLauncher(profileEl, appLauncherBlock, toggle) {
- const gnav = profileEl.closest('nav.gnav');
- gnav.classList.add('has-apps');
-
const appsLink = appLauncherBlock.querySelector('a');
appsLink.href = localizeLink(appsLink.href);
diff --git a/libs/blocks/global-navigation/blocks/navDropdown/dropdown.css b/libs/blocks/global-navigation/blocks/navDropdown/dropdown.css
index 26674686206..f1ad317b631 100644
--- a/libs/blocks/global-navigation/blocks/navDropdown/dropdown.css
+++ b/libs/blocks/global-navigation/blocks/navDropdown/dropdown.css
@@ -120,6 +120,7 @@
left: 0;
padding: 0;
z-index: 1;
+ box-shadow: 0 3px 3px 0 rgb(0 0 0 / 20%);
}
[dir = "rtl"] .feds-popup {
diff --git a/libs/blocks/global-navigation/blocks/profile/milo-wrapper.css b/libs/blocks/global-navigation/blocks/profile/button.css
similarity index 100%
rename from libs/blocks/global-navigation/blocks/profile/milo-wrapper.css
rename to libs/blocks/global-navigation/blocks/profile/button.css
diff --git a/libs/blocks/global-navigation/blocks/profile/button.js b/libs/blocks/global-navigation/blocks/profile/button.js
new file mode 100644
index 00000000000..bb0fd430688
--- /dev/null
+++ b/libs/blocks/global-navigation/blocks/profile/button.js
@@ -0,0 +1,26 @@
+import { toFragment, getFedsPlaceholderConfig } from '../../utilities/utilities.js';
+import { replaceKey } from '../../../../features/placeholders.js';
+
+const decorateButton = async ({ avatar }) => {
+ const label = await replaceKey(
+ 'profile-button',
+ getFedsPlaceholderConfig(),
+ );
+
+ const buttonElem = toFragment`
+
+
+
+ `;
+
+ return buttonElem;
+};
+
+export default decorateButton;
diff --git a/libs/blocks/global-navigation/blocks/profile/profile.css b/libs/blocks/global-navigation/blocks/profile/dropdown.css
similarity index 67%
rename from libs/blocks/global-navigation/blocks/profile/profile.css
rename to libs/blocks/global-navigation/blocks/profile/dropdown.css
index 5d72a9008b7..a380b4d43e3 100644
--- a/libs/blocks/global-navigation/blocks/profile/profile.css
+++ b/libs/blocks/global-navigation/blocks/profile/dropdown.css
@@ -1,7 +1,7 @@
:root {
--feds-color-profile-heading: #707070;
--feds-color-profile: #4b4b4b;
- --feds-color-profile-emphasis: #2c2c2c;
+ --feds-color-profile--emphasis: #2c2c2c;
--feds-border-profile: 1px solid #e1e1e1;
}
@@ -18,32 +18,18 @@
display: none;
line-height: 1;
white-space: nowrap;
+ z-index: 1;
}
-[dir='rtl'] .feds-profile-menu {
+[dir = "rtl"] .feds-profile-menu {
right: initial;
left: 0;
}
-.feds-profile.is-open .feds-profile-menu {
+.feds-profile-button[aria-expanded = "true"] + .feds-profile-menu {
display: block;
}
-.feds-profile li a {
- color: inherit;
- overflow: hidden;
- text-overflow: ellipsis;
- display: block;
-}
-
-/* TODO be removable with refactoring the menu CSS */
-.feds-profile.gnav-navitem.has-menu.is-open .gnav-navitem-menu {
- position: absolute;
- top: 100%;
- left: auto;
- margin-top: 0;
-}
-
.feds-profile-header {
padding: 20px;
display: flex;
@@ -61,22 +47,23 @@
overflow: hidden;
}
+.feds-profile-name,
+.feds-profile-email {
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+
.feds-profile-name {
- margin: 0;
- padding: 0 0 4px;
+ margin: 0 0 4px;
font-size: 18px;
font-weight: 700;
- text-overflow: ellipsis;
- overflow: hidden;
- color: var(--feds-color-profile-emphasis);
+ color: var(--feds-color-profile--emphasis);
}
.feds-profile-email {
margin: 0 0 12px;
font-size: 14px;
color: var(--feds-color-profile-heading);
- text-overflow: ellipsis;
- overflow: hidden;
}
.feds-profile-account {
@@ -91,24 +78,35 @@
padding: 6px 0;
}
-.feds-local-menu ul {
- margin: 0;
- padding: 0;
-}
-
.feds-local-menu h5 {
margin: 0;
- padding: 5px 20px;
+ padding: 8px 20px;
color: var(--feds-color-profile-heading);
font-size: 11px;
font-weight: 600;
+ line-height: 1.5;
text-transform: uppercase;
}
+.feds-local-menu p {
+ margin: 0;
+}
+
+.feds-local-menu a,
+.feds-profile-actions a {
+ display: block;
+ color: var(--feds-color-link--light);
+}
+
+.feds-local-menu a:hover,
+.feds-profile-actions a:hover {
+ color: var(--feds-color-link--hover--light);
+ background-color: var(--feds-background-link--hover--light);
+}
+
.feds-local-menu a {
- font-size: 14px;
- padding: 9px 18px;
- color: var(--feds-color-profile);
+ padding: 6px 20px;
+ line-height: 1.4;
outline-offset: -1px;
}
@@ -121,8 +119,3 @@
padding: 14px 20px;
border-top: var(--feds-border-profile);
}
-
-.feds-profile-menu li:hover {
- color: var(--feds-color-profile-emphasis);
- background-color: #f5f5f5;
-}
diff --git a/libs/blocks/global-navigation/blocks/profile/dropdown.js b/libs/blocks/global-navigation/blocks/profile/dropdown.js
new file mode 100644
index 00000000000..9da56e9cfdd
--- /dev/null
+++ b/libs/blocks/global-navigation/blocks/profile/dropdown.js
@@ -0,0 +1,188 @@
+import { getConfig } from '../../../../utils/utils.js';
+import { toFragment, getFedsPlaceholderConfig } from '../../utilities/utilities.js';
+import { replaceKeyArray } from '../../../../features/placeholders.js';
+
+const getLanguage = (ietfLocale) => {
+ if (!ietfLocale.length) return 'en';
+
+ const nonStandardLocaleMap = { 'no-NO': 'nb' };
+
+ if (nonStandardLocaleMap[ietfLocale]) {
+ return nonStandardLocaleMap[ietfLocale];
+ }
+
+ return ietfLocale.split('-')[0];
+};
+
+const decorateProfileLink = (service, path = '') => {
+ const defaultServiceUrls = {
+ adminconsole: 'https://adminconsole.adobe.com',
+ account: 'https://account.adobe.com',
+ };
+
+ if (!service.length || !defaultServiceUrls[service]) return '';
+
+ let serviceUrl;
+ const { env } = getConfig();
+
+ if (!env?.[service]) {
+ serviceUrl = defaultServiceUrls[service];
+ } else {
+ serviceUrl = new URL(defaultServiceUrls[service]);
+ serviceUrl.hostname = env[service];
+ }
+
+ return `${serviceUrl}${path}`;
+};
+
+const decorateAction = (label, path) => toFragment`
${label} `;
+
+class ProfileDropdown {
+ constructor({
+ rawElem,
+ decoratedElem,
+ avatar,
+ sections,
+ buttonElem,
+ openOnInit,
+ } = {}) {
+ this.placeholders = {};
+ this.profileData = {};
+ this.avatar = avatar;
+ this.buttonElem = buttonElem;
+ this.decoratedElem = decoratedElem;
+ this.sections = sections;
+ this.openOnInit = openOnInit;
+ this.localMenu = rawElem.querySelector('h5')?.parentElement;
+ this.init();
+ }
+
+ async init() {
+ await this.getData();
+ this.setButtonLabel();
+ this.dropdown = this.decorateDropdown();
+ this.addEventListeners();
+
+ if (this.openOnInit) this.toggleDropdown();
+
+ this.decoratedElem.append(this.dropdown);
+ }
+
+ async getData() {
+ [
+ [
+ this.placeholders.profileButton,
+ this.placeholders.signOut,
+ this.placeholders.viewAccount,
+ this.placeholders.manageTeams,
+ this.placeholders.manageEnterprise,
+ ],
+ // 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(
+ ['profile-button', 'sign-out', 'view-account', 'manage-teams', 'manage-enterprise'],
+ getFedsPlaceholderConfig(),
+ ),
+ window.adobeIMS.getProfile(),
+ ]);
+ }
+
+ setButtonLabel() {
+ if (this.buttonElem) this.buttonElem.setAttribute('aria-label', this.profileData.displayName);
+ }
+
+ decorateDropdown() {
+ const { locale } = getConfig();
+ const lang = getLanguage(locale.ietf);
+
+ // TODO: the account name and email might need a bit of adaptive behavior;
+ // historically we shrunk the font size and displayed the account name on two lines;
+ // the email had some special logic as well;
+ // for MVP, we took a simpler approach ("Some very long name, very l...")
+ // TODO: historically, clicking the avatar lead to '/profile',
+ // but clicking the 'View account link' let to the account page;
+ // we need to check whether this is still needed
+ return toFragment`
+
+ `;
+ }
+
+ decorateEmail() {
+ const maxCharacters = 12;
+ const emailParts = this.profileData.email.split('@');
+ const username = emailParts[0].length <= maxCharacters
+ ? emailParts[0]
+ : `${emailParts[0].slice(0, maxCharacters)}…`;
+ const domainArr = emailParts[1].split('.');
+ const tld = domainArr.pop();
+ let domain = domainArr.join('.');
+ domain = domain.length <= maxCharacters
+ ? domain
+ : `${domain.slice(0, maxCharacters)}…`;
+
+ return `${username}@${domain}.${tld}`;
+ }
+
+ decorateLocalMenu() {
+ if (this.localMenu) this.localMenu.classList.add('feds-local-menu');
+
+ return this.localMenu;
+ }
+
+ decorateSignOut() {
+ const signOutLink = toFragment`
+
+ ${this.placeholders.signOut}
+
+ `;
+
+ // TODO consumers might want to execute their own logic before a sign out
+ // we might want to provide them a way to do so here
+ signOutLink.addEventListener('click', (e) => {
+ e.preventDefault();
+ window.adobeIMS.signOut();
+ });
+
+ return signOutLink;
+ }
+
+ addEventListeners() {
+ this.buttonElem.addEventListener('click', () => {
+ this.toggleDropdown();
+ });
+ }
+
+ toggleDropdown() {
+ const isOpen = this.buttonElem.getAttribute('aria-expanded') === 'true';
+
+ if (isOpen) {
+ this.buttonElem.setAttribute('aria-expanded', 'false');
+ } else {
+ this.buttonElem.setAttribute('aria-expanded', 'true');
+ }
+ }
+}
+
+export default ProfileDropdown;
diff --git a/libs/blocks/global-navigation/blocks/profile/milo-wrapper.js b/libs/blocks/global-navigation/blocks/profile/milo-wrapper.js
deleted file mode 100644
index 599dafa27a5..00000000000
--- a/libs/blocks/global-navigation/blocks/profile/milo-wrapper.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import { toFragment, getFedsPlaceholderConfig } from '../../utilities/utilities.js';
-import {
- replaceKey,
- replaceKeyArray,
-} from '../../../../features/placeholders.js';
-
-const initProfileButton = async ({ blockEl, decoratedEl, avatar }) => {
- const profileButtonLabel = await replaceKey(
- 'profile-button',
- getFedsPlaceholderConfig(),
- );
- if (blockEl.children.length > 1) decoratedEl.classList.add('has-menu');
- decoratedEl.closest('nav.gnav')?.classList.add('signed-in');
-
- const profileButtonEl = toFragment`
-
-
-
- `;
- profileButtonEl.addEventListener('click', () => window.dispatchEvent(new Event('feds:profileButton:clicked')));
- return profileButtonEl;
-};
-
-const initProfileMenu = async ({ blockEl, ProfileClass, ...rest }) => {
- const placeholders = {};
- [
- placeholders.profileButton,
- placeholders.signOut,
- placeholders.viewAccount,
- placeholders.manageTeams,
- placeholders.manageEnterprise,
- ] = await replaceKeyArray(
- [
- 'profile-button',
- 'sign-out',
- 'view-account',
- 'manage-teams',
- 'manage-enterprise',
- ],
- getFedsPlaceholderConfig(),
- );
- const profile = new ProfileClass({
- localMenu: blockEl.querySelector('h5')?.parentElement,
- placeholders,
- ...rest,
- });
- return profile;
-};
-
-export default { initProfileButton, initProfileMenu };
diff --git a/libs/blocks/global-navigation/blocks/profile/profile.js b/libs/blocks/global-navigation/blocks/profile/profile.js
deleted file mode 100644
index 05d04e508ec..00000000000
--- a/libs/blocks/global-navigation/blocks/profile/profile.js
+++ /dev/null
@@ -1,103 +0,0 @@
-import { getConfig } from '../../../../utils/utils.js';
-import { toFragment } from '../../utilities/utilities.js';
-
-const decorateEmail = (email) => {
- const MAX_CHAR = 12;
- const emailParts = email.split('@');
- const username = emailParts[0].length <= MAX_CHAR ? emailParts[0] : `${emailParts[0].slice(0, MAX_CHAR)}…`;
- const domainArr = emailParts[1].split('.');
- const tld = domainArr.pop();
- let domain = domainArr.join('.');
- domain = domain.length <= MAX_CHAR ? domain : `${domain.slice(0, MAX_CHAR)}…`;
- return `${username}@${domain}.${tld}`;
-};
-
-const decorateProfileLink = (href, service) => {
- const env = getConfig();
- const name = env.name || 'prod';
- if (name === 'prod') return href;
- const url = new URL(href);
- url.hostname = env[service];
- return url.href;
-};
-
-const decorateAction = (label, href) => toFragment`${label} `;
-
-class Profile {
- constructor({
- decoratedEl,
- avatar,
- sections,
- profileButtonEl,
- localMenu,
- placeholders,
- }) {
- this.sections = sections;
- this.avatar = avatar;
- this.profileButtonEl = profileButtonEl;
- this.decoratedEl = decoratedEl;
- this.localMenu = localMenu;
- this.placeholders = placeholders;
- if (localMenu) {
- localMenu.classList.add('feds-local-menu');
- }
- this.init();
- }
-
- async init() {
- // TODO do some sanity checks if the user is logged in, the mandatory properties are set.
- // If not there should be helpful logs providing guidance for developers
- const { displayName, email } = await window.adobeIMS.getProfile();
- if (this.profileButtonEl) this.profileButtonEl.setAttribute('aria-label', displayName);
- this.displayName = displayName;
- this.email = email;
- this.decoratedEl.append(this.menu());
- }
-
- decorateSignOut() {
- const signOutLink = toFragment`
-
- ${this.placeholders.signOut}
-
- `;
-
- // TODO consumers might want to execute their own logic before a sign out
- // we might want to provide them a way to do so here
- signOutLink.addEventListener('click', (e) => {
- e.preventDefault();
- window.adobeIMS.signOut();
- });
- return signOutLink;
- }
-
- menu() {
- // TODO the account name and email might need a bit of adaptive behaviour
- // historically we shrunk the fontsize and displayed the account name on two lines
- // the email had some special logic as well
- // we took a simpler approach ("Some very long name, very l...") for MVP
- return toFragment`
-
- `;
- }
-}
-export default Profile;
diff --git a/libs/blocks/global-navigation/blocks/profile/signIn.css b/libs/blocks/global-navigation/blocks/profile/signIn.css
index 2a74e94709d..6ab21a57a8f 100644
--- a/libs/blocks/global-navigation/blocks/profile/signIn.css
+++ b/libs/blocks/global-navigation/blocks/profile/signIn.css
@@ -1,11 +1,11 @@
-.feds-signin {
+.feds-signIn {
padding: 11px var(--feds-spacing-utilityNav);
border-radius: var(--feds-radius-utilityIcon);
color: #4B4B4B;
white-space: nowrap;
}
-.feds-signin-dropdown {
+.feds-signIn-dropdown {
position: absolute;
display: none;
right: 0;
@@ -17,31 +17,30 @@
box-shadow: 0 2px 6px -1px rgb(0 0 0 / 10%);
line-height: 1.4;
white-space: nowrap;
+ z-index: 1;
}
-.feds-profile.is-open .feds-signin-dropdown {
+.feds-signIn[aria-expanded = "true"] + .feds-signIn-dropdown {
display: block;
}
-[dir='rtl'] .feds-signin-dropdown {
+[dir = "rtl"] .feds-signIn-dropdown {
right: initial;
left: 0;
}
-.feds-signin-dropdown a {
- color: inherit;
-}
-
-.feds-signin-dropdown ul {
+.feds-signIn-dropdown ul {
margin: 0;
padding: 12px 0;
}
-.feds-signin-dropdown li {
- padding: 4px 32px;
+.feds-signIn-dropdown li > a {
+ display: block;
+ color: var(--feds-color-link--light);
+ padding: 6px 32px;
}
-.feds-signin-dropdown li:hover {
- color: var(--link-color);
- background-color: #f5f5f5;
+.feds-signIn-dropdown li > a:hover {
+ color: var(--feds-color-link--hover--light);
+ background-color: var(--feds-background-link--hover--light);;
}
diff --git a/libs/blocks/global-navigation/blocks/profile/signIn.js b/libs/blocks/global-navigation/blocks/profile/signIn.js
index e8a54c38f7c..0193c8b1371 100644
--- a/libs/blocks/global-navigation/blocks/profile/signIn.js
+++ b/libs/blocks/global-navigation/blocks/profile/signIn.js
@@ -1,35 +1,49 @@
import { toFragment, getFedsPlaceholderConfig } from '../../utilities/utilities.js';
import { replaceKey } from '../../../../features/placeholders.js';
-const decorateSignIn = async ({ blockEl, decoratedEl }) => {
- const dropDown = blockEl.querySelector(':scope > div:nth-child(2)');
+const decorateSignIn = async ({ rawElem, decoratedElem }) => {
+ const dropdownElem = rawElem.querySelector(':scope > div:nth-child(2)');
const signInLabel = await replaceKey('sign-in', getFedsPlaceholderConfig());
- if (!dropDown) {
- const signIn = toFragment`${signInLabel} `;
- signIn.addEventListener('click', (e) => {
+ let signInElem;
+
+ if (!dropdownElem) {
+ signInElem = toFragment`${signInLabel} `;
+
+ signInElem.addEventListener('click', (e) => {
e.preventDefault();
// TODO confirm adobeIMS is always set
// e.g. when it's consumed as NPM package or when we are on a consumer page
window.adobeIMS.signIn();
});
- return signIn;
- }
+ } else {
+ signInElem = toFragment`${signInLabel} `;
- const signInWithDropDown = toFragment`${signInLabel} `;
- dropDown.classList.add('feds-signin-dropdown');
- decoratedEl.insertAdjacentElement('beforeend', dropDown);
+ signInElem.addEventListener('click', () => {
+ const isOpen = signInElem.getAttribute('aria-expanded') === 'true';
- // TODO we don't have a good way of adding attributes to links
- const dropDownSignIn = dropDown.querySelector('[href="https://adobe.com?sign-in=true"]');
- if (dropDownSignIn) {
- dropDownSignIn.addEventListener('click', (e) => {
- e.preventDefault();
- window.adobeIMS.signIn();
+ if (isOpen) {
+ signInElem.setAttribute('aria-expanded', 'false');
+ } else {
+ signInElem.setAttribute('aria-expanded', 'true');
+ }
});
+
+ dropdownElem.classList.add('feds-signIn-dropdown');
+
+ // TODO we don't have a good way of adding attributes to links
+ const dropdownSignIn = dropdownElem.querySelector('[href="https://adobe.com?sign-in=true"]');
+
+ if (dropdownSignIn) {
+ dropdownSignIn.addEventListener('click', (e) => {
+ e.preventDefault();
+ window.adobeIMS.signIn();
+ });
+ }
+
+ decoratedElem.append(dropdownElem);
}
- signInWithDropDown.addEventListener('click', () => window.dispatchEvent(new Event('feds:profileSignIn:clicked')));
- return signInWithDropDown;
+ decoratedElem.prepend(signInElem);
};
export default decorateSignIn;
diff --git a/libs/blocks/global-navigation/blocks/profile/standalone-wrapper.css b/libs/blocks/global-navigation/blocks/profile/standalone-wrapper.css
index 10983927f94..425ab157cd3 100644
--- a/libs/blocks/global-navigation/blocks/profile/standalone-wrapper.css
+++ b/libs/blocks/global-navigation/blocks/profile/standalone-wrapper.css
@@ -8,7 +8,7 @@
justify-content: end;
}
-.feds-signin {
+.feds-signIn {
padding: 4px var(--feds-spacing-utilityNav);
border-radius: var(--feds-radius-utilityIcon);
}
diff --git a/libs/blocks/global-navigation/blocks/search/gnav-search.js b/libs/blocks/global-navigation/blocks/search/gnav-search.js
index bf2a2178440..2facaf79fa0 100644
--- a/libs/blocks/global-navigation/blocks/search/gnav-search.js
+++ b/libs/blocks/global-navigation/blocks/search/gnav-search.js
@@ -281,4 +281,4 @@ class Search {
}
}
-export default { Search };
+export default Search;
diff --git a/libs/blocks/global-navigation/global-navigation.css b/libs/blocks/global-navigation/global-navigation.css
index a2df65cdb2a..06cc3939b65 100644
--- a/libs/blocks/global-navigation/global-navigation.css
+++ b/libs/blocks/global-navigation/global-navigation.css
@@ -76,6 +76,11 @@
background-color: var(--feds-background-nav--light);
}
+[dir = "rtl"] .feds-nav-wrapper {
+ left: 20px;
+ right: 0;
+}
+
.global-navigation.is-open .feds-nav-wrapper {
display: flex;
}
@@ -426,6 +431,7 @@
right: 0;
justify-content: center;
border-bottom: unset;
+ box-shadow: 0 3px 2px rgb(142 142 142 / 30%);
}
.feds-breadcrumbs {
diff --git a/libs/blocks/global-navigation/global-navigation.js b/libs/blocks/global-navigation/global-navigation.js
index f35640e8d79..f26a2a5f57d 100644
--- a/libs/blocks/global-navigation/global-navigation.js
+++ b/libs/blocks/global-navigation/global-navigation.js
@@ -39,9 +39,8 @@ class Gnav {
constructor(body, el) {
this.blocks = {
profile: {
- blockEl: body.querySelector('.profile'),
- decoratedEl: toFragment`
`,
- config: {},
+ rawElem: body.querySelector('.profile'),
+ decoratedElem: toFragment`
`,
},
search: { config: { icon: CONFIG.icons.search } },
};
@@ -74,7 +73,7 @@ class Gnav {
${this.decorateBrand()}
${this.elements.navWrapper}
- ${this.blocks.profile.blockEl && this.blocks.profile.decoratedEl}
+ ${this.blocks.profile.rawElem ? this.blocks.profile.decoratedElem : ''}
${this.decorateLogo()}
`;
@@ -127,22 +126,22 @@ class Gnav {
{ MenuControls },
decorateDropdown,
{ appLauncher },
- Profile,
- { Search },
+ ProfileDropdown,
+ Search,
] = await Promise.all([
loadBlock('./utilities/delayed-utilities.js'),
loadBlock('./blocks/navDropdown/dropdown.js'),
loadBlock('./blocks/appLauncher/appLauncher.js'),
- loadBlock('./blocks/profile/profile.js'),
+ loadBlock('./blocks/profile/dropdown.js'),
loadBlock('./blocks/search/gnav-search.js'),
- loadStyles('./blocks/profile/profile.css'),
+ loadStyles('./blocks/profile/dropdown.css'),
loadStyles('./blocks/navDropdown/dropdown.css'),
loadStyles('./blocks/search/gnav-search.css'),
]);
this.menuControls = new MenuControls(this.curtain);
this.decorateDropdown = decorateDropdown;
+ this.ProfileDropdown = ProfileDropdown;
this.appLauncher = appLauncher;
- this.blocks.profile.ProfileClass = Profile;
this.Search = Search;
resolve();
});
@@ -162,7 +161,10 @@ class Gnav {
autoValidateToken: true,
environment: env.ims,
useLocalStorage: false,
- onReady: () => this.decorateProfile(),
+ onReady: () => {
+ this.decorateProfile();
+ this.decorateAppLauncher();
+ },
};
const imsScript = document.querySelector('script[src$="/imslib.min.js"]') instanceof HTMLElement;
if (!imsScript && !window.adobeIMS) {
@@ -172,57 +174,78 @@ class Gnav {
};
decorateProfile = async () => {
- const { blockEl, decoratedEl } = this.blocks.profile;
- if (!blockEl) return;
+ const { rawElem, decoratedElem } = this.blocks.profile;
+ if (!rawElem) return;
- const accessToken = window.adobeIMS.getAccessToken();
- const { env } = getConfig();
- this.blocks.profile.profileRes = accessToken
- ? await fetch(`https://${env.adobeIO}/profile`, { headers: new Headers({ Authorization: `Bearer ${accessToken.token}` }) })
- : {};
+ const isSignedInUser = window.adobeIMS.isSignedInUser();
- if (this.blocks.profile.profileRes.status !== 200) {
+ // If user is not signed in, decorate the 'Sign In' element
+ if (!isSignedInUser) {
const [decorateSignIn] = await Promise.all([
loadBlock('./blocks/profile/signIn.js'),
loadStyles('./blocks/profile/signIn.css'),
]);
- const signInEl = await decorateSignIn({ blockEl, decoratedEl });
- decoratedEl.append(signInEl);
- window.addEventListener('feds:profileSignIn:clicked', async () => {
- await this.loadDelayed();
- this.menuControls.toggleMenu(decoratedEl);
- });
+
+ decorateSignIn({ rawElem, decoratedElem });
+
+ return;
+ }
+
+ // If user is signed in, decorate the profile avatar
+ const accessToken = window.adobeIMS.getAccessToken();
+ const { env } = getConfig();
+ const headers = new Headers({ Authorization: `Bearer ${accessToken.token}` });
+ const profileData = await fetch(`https://${env.adobeIO}/profile`, { headers });
+
+ if (profileData.status !== 200) {
return;
}
const [
{ sections, user: { avatar } },
- { initProfileButton, initProfileMenu },
+ decorateButton,
] = await Promise.all([
- this.blocks.profile.profileRes.json(),
- loadBlock('./blocks/profile/milo-wrapper.js'),
- loadStyles('./blocks/profile/milo-wrapper.css'),
+ profileData.json(),
+ loadBlock('./blocks/profile/button.js'),
+ loadStyles('./blocks/profile/button.css'),
]);
- this.blocks.profile.sections = sections;
- this.blocks.profile.avatar = avatar;
- const profileButtonEl = await initProfileButton(this.blocks.profile);
- decoratedEl.append(profileButtonEl);
- window.addEventListener('feds:profileButton:clicked', async () => {
- if (!this.blocks.profile.menu) {
- await this.loadDelayed();
- this.blocks.profile.menu = initProfileMenu(this.blocks.profile);
- const appLauncherBlock = this.body.querySelector('.app-launcher');
- if (appLauncherBlock) {
- this.appLauncher(
- decoratedEl,
- appLauncherBlock,
- this.menuControls.toggleMenu,
- );
- }
- }
- this.menuControls.toggleMenu(decoratedEl);
- });
+ this.blocks.profile.buttonElem = await decorateButton({ avatar });
+ decoratedElem.append(this.blocks.profile.buttonElem);
+
+ // Decorate the profile dropdown
+ // after user interacts with button or after 3s have passed
+ let decorationTimeout;
+
+ const decorateDropdown = async (e) => {
+ this.blocks.profile.buttonElem.removeEventListener('click', decorateDropdown);
+ clearTimeout(decorationTimeout);
+ await this.loadDelayed();
+ this.blocks.profile.dropdownInstance = new this.ProfileDropdown({
+ rawElem,
+ decoratedElem,
+ avatar,
+ sections,
+ buttonElem: this.blocks.profile.buttonElem,
+ // If the dropdown has been decorated due to a click, open it
+ openOnInit: e instanceof Event,
+ });
+ };
+
+ this.blocks.profile.buttonElem.addEventListener('click', decorateDropdown);
+ decorationTimeout = setTimeout(decorateDropdown, 3000);
+ };
+
+ decorateAppLauncher = () => {
+ // TODO: review App Launcher component
+ // const appLauncherBlock = this.body.querySelector('.app-launcher');
+ // if (appLauncherBlock) {
+ // await this.loadDelayed();
+ // this.appLauncher(
+ // decoratedElem,
+ // appLauncherBlock,
+ // );
+ // }
};
loadSearch = () => {