Skip to content

Commit

Permalink
Edit profile, account management links
Browse files Browse the repository at this point in the history
  • Loading branch information
dejanpreradovic committed Aug 26, 2024
1 parent fc009d5 commit 3781055
Show file tree
Hide file tree
Showing 4 changed files with 339 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
:root {
--feds-color-profile-heading: #707070;
--feds-color-profile: #4b4b4b;
--feds-color-profile--emphasis: #2c2c2c;
--feds-border-profile: 1px solid #e1e1e1;
}

.feds-profile-menu {
position: absolute;
width: 320px;
right: 0;
top: 100%;
border: var(--feds-border-profile);
border-radius: 0 0 4px 4px;
background: var(--color-white);
overflow: hidden;
box-shadow: 0 2px 6px -1px rgb(0 0 0 / 10%);
display: none;
line-height: 1;
white-space: nowrap;
z-index: 1;
transform: translate3d(0,0,0); /* Fix Safari issues w/ position: sticky */
}

[dir = "rtl"] .feds-profile-menu {
right: initial;
left: 0;
}

.feds-profile-button[aria-expanded = "true"] + .feds-profile-menu {
display: block;
}

.feds-profile-header {
padding: 20px;
display: flex;
flex-direction: row;
outline-offset: -3px;
column-gap: 15px;
}

.feds-profile-header .feds-profile-img {
max-height: 64px;
max-width: 64px;
}

.feds-profile-details {
overflow: hidden;
line-height: 1.25;
}

.feds-profile-name,
.feds-profile-email {
text-overflow: ellipsis;
overflow: hidden;
}

.feds-profile-name {
margin: 0;
font-size: 18px;
font-weight: 700;
color: var(--feds-color-profile--emphasis);
}

.feds-profile-email {
margin: 0 0 6px;
font-size: 14px;
color: var(--feds-color-profile-heading);
}

.feds-profile-account {
margin: 0;
font-size: 14px;
text-decoration: underline;
color: var(--feds-color-profile);
}

.feds-local-menu {
border-top: var(--feds-border-profile);
padding: 6px 0;
}

.feds-local-menu h5 {
margin: 0;
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 {
padding: 6px 20px;
line-height: 1.4;
outline-offset: -1px;
}

.feds-profile-actions {
margin: 0;
padding: 0;
}

.feds-profile-action {
padding: 14px 20px;
border-top: var(--feds-border-profile);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import { getLibs } from '../../../../scripts/utils.js';

import { getConfig } from '../../../utils/utils.js';

const miloLibs = getLibs();

const { toFragment, getFedsPlaceholderConfig, trigger, closeAllDropdowns, logErrorFor } = await import(`${miloLibs}/blocks/global-navigation/utilities/utilities.js`);

const { replaceKeyArray } = await import(`${miloLibs}/features/placeholders.js`);

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 decorateEditProfileLink = () => {
const { env } = getConfig();
if (env.name === 'prod') {
return 'https://channelpartners.adobe.com/s/manageprofile/?appid=mp';
}
return 'https://channelpartners.stage2.adobe.com/s/manageprofile/?appid=mp';
};

const decorateAction = (label, path) => toFragment`<li><a class="feds-profile-action" href="${decorateProfileLink('adminconsole', path)}">${label}</a></li>`;

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;
logErrorFor(this.init.bind(this), 'ProfileDropdown.init()', 'errorType=error,module=gnav-profile');
}

async init() {
await this.getData();
this.setButtonLabel();
this.dropdown = this.decorateDropdown();
this.addEventListeners();

if (this.openOnInit) trigger({ element: this.buttonElem });

this.decoratedElem.append(this.dropdown);
}

async getData() {
[
[
this.placeholders.profileButton,
this.placeholders.signOut,
this.placeholders.viewAccount,
this.placeholders.manageTeams,
this.placeholders.manageEnterprise,
this.placeholders.profileAvatar,
],
[
this.placeholders.editProfile,
],
{ displayName: this.profileData.displayName, email: this.profileData.email },
] = await Promise.all([
replaceKeyArray(
['profile-button', 'sign-out', 'view-account', 'manage-teams', 'manage-enterprise', 'profile-avatar'],
getFedsPlaceholderConfig(),
),
replaceKeyArray(
['edit-profile'],
getConfig(),
),
window.adobeIMS.getProfile(),
]);
}

setButtonLabel() {
if (this.buttonElem) this.buttonElem.setAttribute('aria-label', this.profileData.displayName);
}

decorateDropdown() {
// 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...")
this.avatarElem = toFragment`<img
class="feds-profile-img"
src="${this.avatar}"
tabindex="0"
alt="${this.placeholders.profileAvatar}"
data-url="${decorateEditProfileLink()}"></img>`;
return toFragment`
<div id="feds-profile-menu" class="feds-profile-menu">
<a
href="${decorateEditProfileLink()}"
target="_blank"
class="feds-profile-header"
daa-ll="${this.placeholders.editProfile}"
aria-label="${this.placeholders.editProfile}"
>
${this.avatarElem}
<div class="feds-profile-details">
<p class="feds-profile-name">${this.profileData.displayName}</p>
<p class="feds-profile-email">${this.decorateEmail(this.profileData.email)}</p>
<p class="feds-profile-account">${this.placeholders.editProfile}</p>
</div>
</a>
${this.localMenu ? this.decorateLocalMenu() : ''}
<ul class="feds-profile-actions">
${this.sections?.manage?.items?.team?.id ? decorateAction(this.placeholders.manageTeams, '/team') : ''}
${this.sections?.manage?.items?.enterprise?.id ? decorateAction(this.placeholders.manageEnterprise) : ''}
${this.decorateSignOut()}
</ul>
</div>
`;
}

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`
<li>
<a href="#" class="feds-profile-action" daa-ll="${this.placeholders.signOut}">${this.placeholders.signOut}</a>
</li>
`;

signOutLink.addEventListener('click', (e) => {
e.preventDefault();
window.dispatchEvent(new Event('feds:signOut'));
window.adobeIMS.signOut();
});

return signOutLink;
}

addEventListeners() {
this.buttonElem.addEventListener('click', (e) => trigger({ element: this.buttonElem, event: e }));
this.buttonElem.addEventListener('keydown', (e) => e.code === 'Escape' && closeAllDropdowns());
this.dropdown.addEventListener('keydown', (e) => e.code === 'Escape' && closeAllDropdowns());
this.avatarElem.addEventListener('click', (e) => {
e.preventDefault();
window.location.assign(this.avatarElem.dataset?.url);
});
}
}

export default ProfileDropdown;
8 changes: 4 additions & 4 deletions edsdme/blocks/partners-navigation/partners-navigation.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable no-async-promise-executor */
import { getLibs } from '../../scripts/utils.js';
import { applyGnavPersonalization } from '../../scripts/personalization.js';
import ProfileDropdown from './features/profile/partners-dropdown.js';

const miloLibs = getLibs();
const {
Expand All @@ -9,6 +10,7 @@ const {
loadIms,
decorateLinks,
loadScript,
loadStyle,
} = await import(`${miloLibs}/utils/utils.js`);
const {
closeAllDropdowns,
Expand Down Expand Up @@ -420,10 +422,8 @@ class Gnav {
}

if (!this.useUniversalNav) {
const [ProfileDropdown] = await Promise.all([
loadBlock('../features/profile/dropdown.js'),
loadStyles(rootPath('features/profile/dropdown.css')),
]);
// use this code when performing Milo code sync
loadStyle('/edsdme/blocks/partners-navigation/features/profile/partners-dropdown.css');
this.ProfileDropdown = ProfileDropdown;
}

Expand Down
Loading

0 comments on commit 3781055

Please sign in to comment.