Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Mwpw 155385 personalisation #36

Merged
merged 7 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions edsdme/scripts/personalization.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import {
getCurrentProgramType,
getPartnerDataCookieValue,
isMember,
partnerIsSignedIn,
getPartnerDataCookieObject,
signedInNonMember,
isReseller,
getNodesByXPath
}
from './utils.js';

const PAGE_PERSONALIZATION_PLACEHOLDERS = { firstName: '//*[contains(text(), "$firstName")]' };

const LEVEL_CONDITION = 'partner-level';
const PERSONALIZATION_MARKER = 'partner-personalization';
const PROGRAM = getCurrentProgramType();
const PARTNER_LEVEL = getPartnerDataCookieValue(PROGRAM, 'level');
const COOKIE_OBJECT = getPartnerDataCookieObject(PROGRAM);

const PERSONALIZATION_CONDITIONS = {
'partner-not-member': signedInNonMember(),
'partner-not-signed-in': !partnerIsSignedIn(),
'partner-all-levels': isMember(),
'partner-reseller': isReseller (PARTNER_LEVEL),
'partner-level': (level) => PARTNER_LEVEL === level,
};


function personalizePlaceholders(placeholders, context = document) {
Object.entries(placeholders).forEach(([key, value]) => {
const placeholderValue = COOKIE_OBJECT[key];
getNodesByXPath(value, context).forEach((el) => {
if (!placeholderValue) {
el.remove();
return;
}
el.textContent = el.textContent.replace(`$${key}`, placeholderValue);
});
});
}

function shouldHide(conditions) {
return conditions.every((condition) => {
const conditionLevel = condition.startsWith(LEVEL_CONDITION) ? condition.split('-').pop() : '';
return conditionLevel
? !PERSONALIZATION_CONDITIONS[LEVEL_CONDITION](conditionLevel) : !PERSONALIZATION_CONDITIONS[condition];
});
}

function hideElement(element, conditions) {
if (!element || !conditions?.length) return;
shouldHide(conditions) && element.classList.add('personalization-hide');
}

function hideSections(page) {
const sections = Array.from(page.getElementsByClassName('section-metadata'));
sections.forEach((section) => {
let hide = false;
Array.from(section.children).forEach((child) => {
const col1 = child.firstElementChild;
let col2 = child.lastElementChild;
if (col1?.textContent !== 'style' || !col2?.textContent.includes(PERSONALIZATION_MARKER)) return;
const conditions = col2?.textContent?.split(',').map((text) => text.trim());
hide = shouldHide(conditions);
});
if (!hide) return;
const parent = section.parentElement;
Array.from(parent.children).forEach((el) => {
el.classList.add('personalization-hide');
});
});
}


function personalizePage(page) {
const blocks = Array.from(page.getElementsByClassName(PERSONALIZATION_MARKER));
blocks.forEach((el) => {
const conditions = Object.values(el.classList);
hideElement(el, conditions);
});
hideSections(page);
}

export function applyPagePersonalization() {
const main = document.querySelector('main') ?? document;
personalizePlaceholders(PAGE_PERSONALIZATION_PLACEHOLDERS, main);
personalizePage(main);
}
2 changes: 2 additions & 0 deletions edsdme/scripts/scripts.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { applyPagePersonalization } from './personalization.js';
import { setLibs, redirectLoggedinPartner, updateIMSConfig, preloadResources, getRenewBanner, updateNavigation, updateFooter } from './utils.js';

// Add project-wide style path here.
Expand Down Expand Up @@ -77,6 +78,7 @@ function setUpPage() {
}

(async function loadPage() {
applyPagePersonalization();
setUpPage();
redirectLoggedinPartner();
updateIMSConfig();
Expand Down
34 changes: 34 additions & 0 deletions edsdme/scripts/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@
/**
* The decision engine for where to get Milo's libs from.
*/

export const LEVELS = {
REGISTERED: 'registered',
CERTIFIED: 'certified',
GOLD: 'gold',
PLATINUM: 'platinum',
DISTRIBBUTOR: 'distributor',
};

export const RESSELER_LEVELS = [LEVELS.REGISTERED, LEVELS.CERTIFIED, LEVELS.GOLD, LEVELS.PLATINUM];

export const [setLibs, getLibs] = (() => {
let libs;
return [
Expand Down Expand Up @@ -115,6 +126,18 @@ export function isMember() {
return status === 'MEMBER';
}

export function partnerIsSignedIn() {
return getCookieValue('partner_data');
zagi25 marked this conversation as resolved.
Show resolved Hide resolved
}

export function signedInNonMember() {
return partnerIsSignedIn() && !isMember();
}

export function isReseller (level) {
return RESSELER_LEVELS.includes(level?.toLowerCase());
}

export function getMetadataContent(name) {
return document.querySelector(`meta[name="${name}"]`)?.content;
}
Expand Down Expand Up @@ -373,3 +396,14 @@ export function updateFooter(locales) {
const footerLoggedIn = getMetadataContent('footer-loggedin-source');
footerMeta.content = footerLoggedIn ?? `${prefix}/edsdme/partners-shared/loggedin-footer`;
}

export function getNodesByXPath(query, context = document) {
const nodes = [];
const xpathResult = document.evaluate(query, context);
let current = xpathResult?.iterateNext();
while (current) {
nodes.push(current);
current = xpathResult.iterateNext();
}
return nodes;
}
4 changes: 4 additions & 0 deletions edsdme/styles/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,7 @@
font-size: 16px;
font-weight: bold;
}

.personalization-hide {
display: none;
}
114 changes: 114 additions & 0 deletions test/scripts/mocks/personalization.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<main>
<div>
<div class="marquee">
<div>
<div data-valign="middle">
<picture>
<source type="image/webp" srcset="./media_1b2111891fc6836011dc3d527c6999c59e792ed70.png?width=2000&#x26;format=webply&#x26;optimize=medium" media="(min-width: 600px)">
<source type="image/webp" srcset="./media_1b2111891fc6836011dc3d527c6999c59e792ed70.png?width=750&#x26;format=webply&#x26;optimize=medium">
<source type="image/png" srcset="./media_1b2111891fc6836011dc3d527c6999c59e792ed70.png?width=2000&#x26;format=png&#x26;optimize=medium" media="(min-width: 600px)">
<img loading="lazy" alt="" src="./media_1b2111891fc6836011dc3d527c6999c59e792ed70.png?width=750&#x26;format=png&#x26;optimize=medium" width="750" height="375">
</picture>
</div>
</div>
<div>
<div data-valign="middle">
<p>
<picture>
<source type="image/webp" srcset="./media_14fca9c1d62860abc54e560109211d31d00b7fcd3.png?width=2000&#x26;format=webply&#x26;optimize=medium" media="(min-width: 600px)">
<source type="image/webp" srcset="./media_14fca9c1d62860abc54e560109211d31d00b7fcd3.png?width=750&#x26;format=webply&#x26;optimize=medium">
<source type="image/png" srcset="./media_14fca9c1d62860abc54e560109211d31d00b7fcd3.png?width=2000&#x26;format=png&#x26;optimize=medium" media="(min-width: 600px)">
<img loading="lazy" alt="" src="./media_14fca9c1d62860abc54e560109211d31d00b7fcd3.png?width=750&#x26;format=png&#x26;optimize=medium" width="154" height="150">
</picture>
</p>
<h1 id="heading-xl-marquee-standard-medium-left">Heading XL Marquee standard medium left</h1>
<h4 id="welcome-firstname">Welcome $firstName</h4>
<p>Body M Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation.</p>
<p><em><a href="https://www.adobe.com/">Lorem ipsum</a></em> <strong><a href="https://www.adobe.com/">Learn more</a></strong> <a href="https://www.adobe.com/">Text link</a></p>
</div>
<div data-valign="middle">
<picture>
<source type="image/webp" srcset="./media_1168e12a35e1cecd1eb49bddbdb174ec21ffa152e.png?width=2000&#x26;format=webply&#x26;optimize=medium" media="(min-width: 600px)">
<source type="image/webp" srcset="./media_1168e12a35e1cecd1eb49bddbdb174ec21ffa152e.png?width=750&#x26;format=webply&#x26;optimize=medium">
<source type="image/png" srcset="./media_1168e12a35e1cecd1eb49bddbdb174ec21ffa152e.png?width=2000&#x26;format=png&#x26;optimize=medium" media="(min-width: 600px)">
<img loading="lazy" alt="" src="./media_1168e12a35e1cecd1eb49bddbdb174ec21ffa152e.png?width=750&#x26;format=png&#x26;optimize=medium" width="600" height="300">
</picture>
</div>
</div>
</div>
</div>
<div>
<div class="text full-width partner-personalization partner-not-signed-in">
<div>
<div data-valign="middle">
<h3 id="partner-not-signed-in"><strong>Partner NOT SIGNED IN</strong></h3>
<p>Featuring over 600,000 hand-picked stock photos and graphics, curated from the world’s leading photographers, illustrators, and agencies. Our Premium collection is perfect for organizations looking for authentic, high-quality commercial content, and easy licensing plans.</p>
<p><a href="https://stock.adobe.com/premium">Explore the premium collection</a></p>
<p><strong><a href="http://adobe.com">Join Now</a></strong></p>
</div>
</div>
</div>
<div class="text full-width partner-personalization partner-not-member">
<div>
<div data-valign="middle">
<h3 id="partner-non-member"><strong>Partner NON MEMBER</strong></h3>
<p>Featuring over 600,000 hand-picked stock photos and graphics, curated from the world’s leading photographers, illustrators, and agencies. Our Premium collection is perfect for organizations looking for authentic, high-quality commercial content, and easy licensing plans.</p>
<p><a href="https://stock.adobe.com/premium">Explore the premium collection</a></p>
<p><strong><a href="http://adobe.com">Join Now</a></strong></p>
</div>
</div>
</div>
<div class="text full-width partner-personalization partner-all-levels">
<div>
<div data-valign="middle">
<h3 id="member"><strong>MEMBER</strong></h3>
<p>Featuring over 600,000 hand-picked stock photos and graphics, curated from the world’s leading photographers, illustrators, and agencies. Our Premium collection is perfect for organizations looking for authentic, high-quality commercial content, and easy licensing plans.</p>
</div>
</div>
</div>
</div>
<div>
<div class="text full-width partner-personalization partner-level-gold">
<div>
<div data-valign="middle">
<h3 id="partner-gold"><strong>Partner GOLD</strong></h3>
<p>Featuring over 600,000 hand-picked stock photos and graphics, curated from the world’s leading photographers, illustrators, and agencies. Our Premium collection is perfect for organizations looking for authentic, high-quality commercial content, and easy licensing plans.</p>
</div>
</div>
</div>
</div>
<div>
<div class="text full-width partner-personalization partner-level-platinum">
<div>
<div data-valign="middle">
<h3 id="partner-platinum"><strong>Partner Platinum</strong></h3>
<p>Featuring over 600,000 hand-picked stock photos and graphics, curated from the world’s leading photographers, illustrators, and agencies. Our Premium collection is perfect for organizations looking for authentic, high-quality commercial content, and easy licensing plans.</p>
<p><a href="https://stock.adobe.com/premium">Explore the premium collection</a></p>
</div>
</div>
</div>
<div class="section-metadata">
<div>
<div data-valign="middle">style</div>
<div data-valign="middle">partner-personalization, partner-level-platinum</div>
</div>
</div>
</div>
<div>
<div id="platinum-section" class="text full-width">
<div>
<div data-valign="middle">
<h3 id="partner-platinum-section"><strong>Partner Platinum section</strong></h3>
<p>Featuring over 600,000 hand-picked stock photos and graphics, curated from the world’s leading photographers, illustrators, and agencies. Our Premium collection is perfect for organizations looking for authentic, high-quality commercial content, and easy licensing plans.</p>
<p><a href="https://stock.adobe.com/premium">Explore the premium collection</a></p>
</div>
</div>
</div>
<div class="section-metadata">
<div>
<div data-valign="middle">style</div>
<div data-valign="middle">partner-personalization, partner-level-platinum</div>
</div>
</div>
</div>
</main>
Loading
Loading