diff --git a/creativecloud/blocks/sidenav/sidenav.js b/creativecloud/blocks/sidenav/sidenav.js
index ac16ca7c6..b3e388d5d 100644
--- a/creativecloud/blocks/sidenav/sidenav.js
+++ b/creativecloud/blocks/sidenav/sidenav.js
@@ -2,31 +2,43 @@ import { createTag, getLibs } from '../../scripts/utils.js';
import '../../deps/merch-sidenav.js';
-const CATEGORY_TYPE = 'Categories';
-const TYPE_TYPE = 'Types';
-const getValueFromLabel = (content) => content
- .trim()
- .toLowerCase()
- .replace(/( and )/g, ' ')
- .replace(/-/g, '')
- .replace(/\s+/g, '-');
+const CATEGORY_ID_PREFIX = 'categories/';
+const TYPE_ID_PREFIX = 'types/';
-const getCategories = (arrayCategories) => {
- const tag = createTag('sp-sidenav', { variant: 'multilevel', manageTabIndex: true });
+const getIdLeaf = (id) => (id?.substring(id.lastIndexOf('/') + 1) || id);
+
+const getCategories = (items, isMultilevel, mapCategories) => {
+ const configuration = { manageTabIndex: true };
+ if (isMultilevel) {
+ configuration.variant = 'multilevel';
+ }
+ const mapParents = [];
+ const tag = createTag('sp-sidenav', configuration);
const merchTag = createTag('merch-sidenav-list', { deeplink: 'category' });
merchTag.append(tag);
- const mapParents = {};
- arrayCategories.forEach((item) => {
- if (item.Name?.length > 0) {
- const parentName = item.Name.split('|')[0].trim();
- if (!mapParents[parentName]) {
- mapParents[parentName] = createTag('sp-sidenav-item', { label: parentName, value: getValueFromLabel(parentName) });
- tag.append(mapParents[parentName]);
- }
- const childName = item.Name.split('|')[1]?.trim();
- if (childName) {
- const childNode = createTag('sp-sidenav-item', { label: childName, value: getValueFromLabel(childName) });
- mapParents[parentName].append(childNode);
+ items.forEach((item) => {
+ if (item) {
+ let parent = tag;
+ const value = getIdLeaf(item.id);
+ // first token is type, second is parent category
+ const isParent = item.id.split('/').length <= 2;
+ const itemTag = createTag('sp-sidenav-item', { label: item.name, value });
+ if (isParent) {
+ mapParents[value] = itemTag;
+ tag.append(itemTag);
+ } else {
+ const parentId = getIdLeaf(item.id.substring(0, item.id.lastIndexOf('/')));
+ if (isMultilevel) {
+ if (!mapParents[parentId]) {
+ const parentItem = mapCategories[parentId];
+ if (parentItem) {
+ mapParents[parentId] = createTag('sp-sidenav-item', { label: parentItem.name, parentId });
+ tag.append(mapParents[parentId]);
+ }
+ }
+ parent = mapParents[parentId];
+ }
+ parent?.append(itemTag);
}
}
});
@@ -36,28 +48,52 @@ const getCategories = (arrayCategories) => {
const getTypes = (arrayTypes) => {
const tag = createTag('merch-sidenav-checkbox-group', { title: 'Types', deeplink: 'types' });
arrayTypes.forEach((item) => {
- if (item.Name?.length > 0) {
- const checkbox = createTag('sp-checkbox', { emphasized: '', name: getValueFromLabel(item.Name) });
- checkbox.append(document.createTextNode(item.Name));
+ if (item.name?.length > 0) {
+ const checkbox = createTag('sp-checkbox', {
+ emphasized: '',
+ name: getIdLeaf(item.id),
+ });
+ checkbox.append(item.name);
tag.append(checkbox);
}
});
return tag;
};
-const appendFilters = async (root, link) => {
+const appendFilters = async (root, link, explicitCategoriesElt) => {
const payload = link.textContent.trim();
try {
const resp = await fetch(payload);
if (resp.ok) {
const json = await resp.json();
- const arrayCategories = json.data.filter((item) => item.Type === CATEGORY_TYPE);
- if (arrayCategories.length > 0) {
- root.append(getCategories(arrayCategories));
+ const mapCategories = {};
+ let categoryValues = [];
+ const types = [];
+ json.data.forEach((item) => {
+ if (item.id?.startsWith(CATEGORY_ID_PREFIX)) {
+ const value = getIdLeaf(item.id);
+ mapCategories[value] = item;
+ categoryValues.push(value);
+ } else if (item.id?.startsWith(TYPE_ID_PREFIX)) {
+ types.push(item);
+ }
+ });
+ if (explicitCategoriesElt) {
+ categoryValues = Array.from(explicitCategoriesElt.querySelectorAll('li'))
+ .map((item) => item.textContent.trim().toLowerCase());
+ }
+ let shallowCategories = true;
+ if (categoryValues.length > 0) {
+ const items = categoryValues.map((value) => mapCategories[value]);
+ const parentValues = new Set(items.map((value) => value?.id.split('/')[1]));
+ // all parent will always be here without children,
+ // so shallow is considered below 2 parents
+ shallowCategories = parentValues.size <= 2;
+ const categoryTags = getCategories(items, !shallowCategories, mapCategories);
+ root.append(categoryTags);
}
- const arrayTypes = json.data.filter((item) => item.Type === TYPE_TYPE);
- if (arrayTypes.length > 0) {
- root.append(getTypes(arrayTypes));
+ if (!shallowCategories && types.length > 0) {
+ root.append(getTypes(types));
}
}
} catch (e) {
@@ -104,10 +140,11 @@ export default async function init(el) {
const title = el.querySelector('h2')?.textContent.trim();
const rootNav = createTag('merch-sidenav', { title });
- const searchText = el.querySelector('p')?.textContent.trim();
+ const searchText = el.querySelector('p > strong')?.textContent.trim();
appendSearch(rootNav, searchText);
const links = el.querySelectorAll('a');
- await appendFilters(rootNav, links[0]);
+ const explicitCategories = el.querySelector('ul');
+ await appendFilters(rootNav, links[0], explicitCategories);
if (links.length > 1) {
appendResources(rootNav, links[1]);
}
diff --git a/test/blocks/sidenav/mocks/sidenav.html b/test/blocks/sidenav/mocks/sidenav.html
index 21b4f21e2..f3712df3f 100644
--- a/test/blocks/sidenav/mocks/sidenav.html
+++ b/test/blocks/sidenav/mocks/sidenav.html
@@ -14,17 +14,55 @@
SIDE NAV testing
+
+
+
+
REFINE YOUR RESULTS
+
Search all your products
+
https://www.adobe.com/some/taxonomy.json
+
+ - all
+ - Graphic-design
+ - Photo
+ - Illustration
+ - Social-media
+ - Pdf
+ - Esignatures
+ - Coldfusion
+ - Elearning
+ - Print-imaging
+ - Technical-communication
+ - Insight-audiences
+ - Content-journeys
+ - Channel-engagement
+ - Commerce-conversions
+ - Optimization-scale
+
+
RESOURCES: Special Offers
+
+
+
diff --git a/test/blocks/sidenav/mocks/taxonomy.json b/test/blocks/sidenav/mocks/taxonomy.json
index deffe42e6..4941c4a3a 100644
--- a/test/blocks/sidenav/mocks/taxonomy.json
+++ b/test/blocks/sidenav/mocks/taxonomy.json
@@ -1,169 +1,111 @@
{
- "total": 27,
+ "total": 26,
"offset": 0,
- "limit": 27,
+ "limit": 26,
"data": [
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "",
- "Name": ""
+ "name": "All",
+ "id": "categories/all"
},
{
- "Type": "Categories",
- "Level 1": "All",
- "Level 2": "",
- "Name": "All"
+ "name": "Creativity and Design",
+ "id": "categories/creativity-design"
},
{
- "Type": "Categories",
- "Level 1": "Creativity and Design",
- "Level 2": "",
- "Name": "Creativity and Design"
+ "name": "Photo",
+ "id": "categories/creativity-design/photo"
},
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "Photo",
- "Name": "Creativity and Design | Photo"
+ "name": "Graphic Design",
+ "id": "categories/creativity-design/graphic-design"
},
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "Graphic Design",
- "Name": "Creativity and Design | Graphic Design"
+ "name": "Video",
+ "id": "categories/creativity-design/video"
},
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "Video",
- "Name": "Creativity and Design | Video"
+ "name": "Illustration",
+ "id": "categories/creativity-design/illustration"
},
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "Illustration",
- "Name": "Creativity and Design | Illustration"
+ "name": "Acrobat and PDF",
+ "id": "categories/creativity-design/acrobat-pdf"
},
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "Acrobat and PDF",
- "Name": "Creativity and Design | Acrobat and PDF"
+ "name": "3D and AR",
+ "id": "categories/creativity-design/3d-ar"
},
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "3D and AR",
- "Name": "Creativity and Design | 3D and AR"
+ "name": "Social Media",
+ "id": "categories/creativity-design/social-media"
},
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "Social Media",
- "Name": "Creativity and Design | Social Media"
+ "name": "PDF and E-signatures",
+ "id": "categories/pdf-esignatures"
},
{
- "Type": "Categories",
- "Level 1": "PDF and E-signatures",
- "Level 2": "",
- "Name": "PDF and E-signatures"
+ "name": "PDF",
+ "id": "categories/pdf-esignatures/pdf"
},
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "PDF",
- "Name": "PDF and E-signatures | PDF"
+ "name": "E-signatures",
+ "id": "categories/pdf-esignatures/esignatures"
},
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "E-signatures",
- "Name": "PDF and E-signatures | E-signatures"
+ "name": "Marketing and Commerce",
+ "id": "categories/marketing-commerce"
},
{
- "Type": "Categories",
- "Level 1": "Marketing and Commerce",
- "Level 2": "",
- "Name": "Marketing and Commerce"
+ "name": "Insights and Audiences",
+ "id": "categories/marketing-commerce/insights-audiences"
},
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "Insights and Audiences",
- "Name": "Marketing and Commerce | Insights and Audiences"
+ "name": "Content and Journeys",
+ "id": "categories/marketing-commerce/content-journeys"
},
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "Content and Journeys",
- "Name": "Marketing and Commerce | Content and Journeys"
+ "name": "Channels and Engagement",
+ "id": "categories/marketing-commerce/channels-engagement"
},
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "Channels and Engagement",
- "Name": "Marketing and Commerce | Channels and Engagement"
+ "name": "Commerce and Conversions",
+ "id": "categories/marketing-commerce/commerce-conversions"
},
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "Commerce and Conversions",
- "Name": "Marketing and Commerce | Commerce and Conversions"
+ "name": "Optimization and Scale",
+ "id": "categories/marketing-commerce/optimization-scale"
},
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "Optimization and Scale",
- "Name": "Marketing and Commerce | Optimization and Scale"
+ "name": "Additional Solutions",
+ "id": "categories/additional-solutions"
},
{
- "Type": "Categories",
- "Level 1": "Additional Solutions",
- "Level 2": "",
- "Name": "Additional Solutions"
+ "name": "ColdFusion",
+ "id": "categories/additional-solutions/coldFusion"
},
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "ColdFusion",
- "Name": "Additional Solutions | ColdFusion"
+ "name": "eLearning",
+ "id": "categories/additional-solutions/eLearning"
},
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "eLearning",
- "Name": "Additional Solutions | eLearning"
+ "name": "Print Imaging",
+ "id": "categories/additional-solutions/print-imaging"
},
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "Print Imaging",
- "Name": "Additional Solutions | Print Imaging"
+ "name": "Technical Communication",
+ "id": "categories/additional-solutions/technical-communication"
},
{
- "Type": "Categories",
- "Level 1": "",
- "Level 2": "Technical Communication",
- "Name": "Additional Solutions | Technical Communication"
+ "name": "Desktop",
+ "id": "types/desktop"
},
{
- "Type": "Types",
- "Level 1": "Desktop",
- "Level 2": "",
- "Name": "Desktop"
+ "name": "Mobile",
+ "id": "types/mobile"
},
{
- "Type": "Types",
- "Level 1": "Mobile",
- "Level 2": "",
- "Name": "Mobile"
- },
- {
- "Type": "Types",
- "Level 1": "Web",
- "Level 2": "",
- "Name": "Web"
+ "name": "Web",
+ "id": "types/web"
}
],
":type": "sheet"
diff --git a/test/blocks/sidenav/sidenav.test.js b/test/blocks/sidenav/sidenav.test.js
index 5577a5f92..0f97b9ec3 100644
--- a/test/blocks/sidenav/sidenav.test.js
+++ b/test/blocks/sidenav/sidenav.test.js
@@ -27,16 +27,37 @@ describe('Sidenav', () => {
window.fetch = sinon.stub().callsFake(() => mockedTaxonomy());
});
- it('does create nice categories sidenav', async () => {
- const sidenavEl = document.querySelector('.sidenav.categories');
- await init(sidenavEl);
- const newRoot = document.querySelector('merch-sidenav');
- expect(newRoot.title).to.equal("REFINE YOUR RESULTS");
+ const testCategorySidenav = async (selector, expectedItemCount, expectedChildItemCount) => {
+ const sidenavEl = document.querySelector(selector);
+ const newRoot = await init(sidenavEl);
+ expect(newRoot.tagName).to.equal('MERCH-SIDENAV');
+ expect(newRoot.title).to.equal('REFINE YOUR RESULTS');
const items = newRoot.querySelectorAll('sp-sidenav-item');
- expect(items.length).to.equal(24);
+ expect(items.length).to.equal(expectedItemCount);
const search = newRoot.querySelector('sp-search');
expect(search.getAttribute('placeholder')).to.equal('Search all your products');
expect(newRoot.querySelectorAll('sp-checkbox').length).to.equal(3);
+ const nestedItems = newRoot.querySelectorAll('sp-sidenav-item > sp-sidenav-item');
+ expect(nestedItems.length).to.equal(expectedChildItemCount);
expect(newRoot.querySelector('sp-checkbox').textContent.trim()).to.equal('Desktop');
+ };
+
+ it('does create nice categories default sidenav', async () => {
+ await testCategorySidenav('.categories', 24, 18);
+ });
+
+ it('does create nice reordered categories sidenav', async () => {
+ await testCategorySidenav('.reordered-categories', 17, 11);
+ });
+
+ it('does create nice plans sidenav', async () => {
+ const sidenavEl = document.querySelector('.plans');
+ const newRoot = await init(sidenavEl);
+ expect(newRoot.tagName).to.equal('MERCH-SIDENAV');
+ expect(newRoot.title).to.equal('REFINE YOUR RESULTS');
+ const search = newRoot.querySelector('sp-search');
+ expect(search).to.be.null;
+ const nestedItems = newRoot.querySelectorAll('sp-sidenav-item > sp-sidenav-item');
+ expect(nestedItems.length).to.equal(0);
});
});