From e741cf7b09093938bce79200d59568c742b60225 Mon Sep 17 00:00:00 2001
From: mdickson-adbe <95774602+mdickson-adbe@users.noreply.github.com>
Date: Fri, 5 Apr 2024 16:44:43 -0400
Subject: [PATCH 1/2] Assets 98990 - Dynamic campaign list (#61)
* initial commit, new blocks/files
* rename files, start implementing
* continuing to implement/adjust styling
* numerous changes
- finish building bones of list component
- build bones of pagination/footer
- add icons for products (will likely need more)
- build javascript for pagination (cleanup needed)
- build javascript for sorting list
* finish pagination
* Updates to css/js to better align to mockup
---
.../gmo-campaign-list/gmo-campaign-list.css | 24 +-
blocks/gmo-campaign-list/gmo-campaign-list.js | 297 ++-
icons/AEM.svg | 2 +-
icons/Acrobat.svg | 23 +-
icons/Creative-Cloud.svg | 749 ++++++
icons/Express.svg | 2373 ++++++++++++++++-
icons/Illustrator.svg | 6 +-
icons/Lightroom.svg | 37 +-
icons/Photoshop.svg | 38 +-
9 files changed, 3291 insertions(+), 258 deletions(-)
create mode 100644 icons/Creative-Cloud.svg
diff --git a/blocks/gmo-campaign-list/gmo-campaign-list.css b/blocks/gmo-campaign-list/gmo-campaign-list.css
index aa8f3af1..b36a1804 100644
--- a/blocks/gmo-campaign-list/gmo-campaign-list.css
+++ b/blocks/gmo-campaign-list/gmo-campaign-list.css
@@ -58,6 +58,7 @@ body {
display: flex;
font-size: 14px;
margin-bottom: 20px;
+ height: 80px;
}
.campaign-info-wrapper {
display: flex;
@@ -67,6 +68,11 @@ body {
width: 80px;
height: 80px;
margin-right: 14px;
+ background: #e2e2e2;
+ border-radius: 18px;
+}
+.campaign-name-wrapper {
+ width: 220px;
}
.campaign-name-label {
font-weight: bold;
@@ -74,9 +80,14 @@ body {
.campaign-name {
color: #959595;
}
-.campaign-description {
+.campaign-description-wrapper {
color: #505050;
}
+.campaign-description {
+ line-height:20px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
.campaign-launch-date {
color: black;
font-weight: bold;
@@ -177,11 +188,11 @@ select {
border-radius: 4px;
}
.column-1 {
- width: 21%;
+ width: 28%;
margin-right: 1%;
}
.column-2 {
- width: 26%;
+ width: 40%;
margin-right: 1%;
}
.column-3 {
@@ -189,7 +200,7 @@ select {
margin-right: 1%;
}
.column-4 {
- width: 13%;
+ width: 16%;
margin-right: 1%;
}
.column-5 {
@@ -217,4 +228,9 @@ select {
.status.yellow {
background-color: rgb(248, 243, 181);
color: rgba(150, 138, 4, 0.945);
+}
+.vertical-center {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
}
\ No newline at end of file
diff --git a/blocks/gmo-campaign-list/gmo-campaign-list.js b/blocks/gmo-campaign-list/gmo-campaign-list.js
index 252b892e..593cf745 100644
--- a/blocks/gmo-campaign-list/gmo-campaign-list.js
+++ b/blocks/gmo-campaign-list/gmo-campaign-list.js
@@ -1,5 +1,6 @@
import { readBlockConfig } from '../../scripts/lib-franklin.js';
import { decorateIcons } from '../../scripts/lib-franklin.js';
+import { graphqlAllCampaigns } from '../../scripts/graphql.js';
const icon = 'https://delivery-p108396-e1046543.adobeaemcloud.com/adobe/assets/deliver/urn:aaid:aem:acdaa42f-00ae-42f4-97e5-8309c42d9076/marketing-hub-102023-lockup-video.png'
const testCampaigns = [
@@ -96,7 +97,7 @@ const testCampaigns = [
]
const testConfig = [
{
- 'name': 'Campaign',
+ 'name': 'Marketing Moments',
'attribute': 'campaign',
'sortable': 'true'
},
@@ -115,11 +116,6 @@ const testConfig = [
'name': 'Products',
'attribute': 'products'
},
- {
- 'name': 'Language',
- 'attribute': 'language',
- 'type': 'string'
- },
{
'name': 'Status',
'attribute': 'status',
@@ -130,25 +126,20 @@ const testConfig = [
export default async function decorate(block) {
//const config = readBlockConfig(block); // this will be for final implementation
- const numPerPage = 2;
- const campaignCount = testCampaigns.length;
+ const campaignResponse = await graphqlAllCampaigns();
+ const campaigns = campaignResponse.data.campaignList.items;
+ console.log(campaignResponse.data.campaignList.items);
+ //console.log(testCampaigns);
+ const numPerPage = 4;
+ const campaignCount = campaigns.length;
const config = testConfig;
const listHeaders = buildListHeaders(config);
- const listItems = buildCampaignList(testCampaigns, numPerPage);
+ const listItems = buildCampaignList(campaigns, numPerPage);
const listFooter = buildListFooter(campaignCount, numPerPage);
- //paginate(listItems);
block.innerHTML = `
`
-
- /*
-
-
-
- */
const listContainer = block.querySelector('.list-container');
listContainer.appendChild(listHeaders);
listContainer.appendChild(listItems);
@@ -159,6 +150,7 @@ export default async function decorate(block) {
function buildCampaignList(campaigns, numPerPage) {
const listWrapper = document.createElement('div');
listWrapper.classList.add('list-items');
+ listWrapper.dataset.totalresults = campaigns.length;
campaigns.forEach((campaign, index) => {
const campaignRow = document.createElement('div');
@@ -168,41 +160,47 @@ function buildCampaignList(campaigns, numPerPage) {
campaignInfoWrapper.classList.add('campaign-info-wrapper','column-1');
const campaignIcon = document.createElement('div');
campaignIcon.classList.add('campaign-icon');
- campaignIcon.innerHTML = ``;
+ //campaignIcon.innerHTML = ``;
const campaignName = document.createElement('div');
- campaignName.classList.add('campaign-name-wrapper');
+ campaignName.classList.add('campaign-name-wrapper', 'vertical-center');
campaignName.innerHTML = `
- Campaign Name
- ${campaign.name}
+ ${checkBlankString(campaign.campaignName)}
+ ${checkBlankString(campaign.programName)}
`
campaignInfoWrapper.appendChild(campaignIcon);
campaignInfoWrapper.appendChild(campaignName);
+ const campaignOverviewWrapper = document.createElement('div');
+ campaignOverviewWrapper.classList.add('column-2', 'campaign-description-wrapper','vertical-center');
const campaignOverview = document.createElement('div');
- campaignOverview.textContent = campaign.description;
- campaignOverview.classList.add('column-2', 'campaign-description');
+ campaignOverview.textContent = checkBlankString(campaign.marketingGoal.plaintext);
+ campaignOverview.classList.add('campaign-description');
campaignOverview.dataset.property = 'description';
+ campaignOverviewWrapper.appendChild(campaignOverview);
const campaignLaunch = document.createElement('div');
- campaignLaunch.textContent = campaign.launch;
- campaignLaunch.classList.add('column-3', 'campaign-launch-date');
+ campaignLaunch.textContent = checkBlankString(campaign.launchDate);
+ campaignLaunch.classList.add('column-3', 'campaign-launch-date', 'vertical-center');
campaignLaunch.dataset.property = 'launch';
- const campaignProducts = buildProducts(campaign.products);
- campaignProducts.classList.add('column-4');
+ const campaignProducts = buildProductsList(checkBlankString(campaign.productOffering));
+ campaignProducts.classList.add('column-4', 'vertical-center');
+ /*
const campaignLanguage = document.createElement('div');
campaignLanguage.textContent = campaign.languages;
campaignLanguage.classList.add('column-5');
+ */
const campaignStatusWrapper = document.createElement('div');
- campaignStatusWrapper.classList.add('status-wrapper', 'column-6');
+ campaignStatusWrapper.classList.add('status-wrapper', 'column-6','vertical-center');
const campaignStatus = document.createElement('div');
- campaignStatus.textContent = campaign.status;
- campaignStatus.classList.add(determineStatusColor(campaign.status)); // this will need additional processing
+ const statusString = checkBlankString(campaign.status);
+ campaignStatus.textContent = statusString;
+ campaignStatus.classList.add(determineStatusColor(statusString));
campaignStatus.classList.add('status');
campaignStatus.dataset.property = 'status';
campaignStatusWrapper.appendChild(campaignStatus);
campaignRow.appendChild(campaignInfoWrapper);
- campaignRow.appendChild(campaignOverview);
+ campaignRow.appendChild(campaignOverviewWrapper);
campaignRow.appendChild(campaignLaunch);
campaignRow.appendChild(campaignProducts);
- campaignRow.appendChild(campaignLanguage);
+ //campaignRow.appendChild(campaignLanguage);
campaignRow.appendChild(campaignStatusWrapper);
listWrapper.appendChild(campaignRow);
@@ -210,35 +208,42 @@ function buildCampaignList(campaigns, numPerPage) {
return listWrapper;
}
-function buildProducts(products) {
+function buildProductsList(productList) {
const campaignProducts = document.createElement('div');
- if (products.length > 1) {
- products.forEach((product) => {
- console.log(product);
- const productEl = document.createElement('div');
- productEl.classList.add('product-entry');
- productEl.innerHTML = `
-
- ${product}
- `
+ //structure of the data for this is different than expected.
+ //may need to break strings up on some delimiter
+ /*if (productList.length > 1) {
+ productList.forEach((product) => {
+ const productEl = buildProduct(product);
campaignProducts.appendChild(productEl);
})
- } else {
-
- }
+ } else {*/
+ const productEl = buildProduct(productList);
+ campaignProducts.appendChild(productEl);
+ //}
- //campaignProducts.textContent = products; // this will need additional processing
return campaignProducts;
}
+function buildProduct(product) {
+ const productEl = document.createElement('div');
+ let productIcon = product;
+ if (product == null) product = 'None';
+ if (product == 'Not Available') productIcon = "gear";
+ productEl.classList.add('product-entry');
+ productEl.innerHTML = `
+
+ ${product}
+ `
+ return productEl;
+}
+
function buildListHeaders(headerConfig) {
- //console.log(headerConfig);
const config = headerConfig;
const listHeaders = document.createElement('div');
listHeaders.classList.add('list-header');
let columnCounter = 1;
config.forEach((column) => {
- //console.log(column);
const columnWrapper = document.createElement('div');
columnWrapper.classList.add('column-header-wrapper');
columnWrapper.classList.add(`column-${columnCounter}`);
@@ -256,20 +261,15 @@ function buildListHeaders(headerConfig) {
const columnSort = document.createElement('div');
columnSort.classList.add('column-sort-wrapper');
const columnSortAsc = document.createElement('span');
- //
columnSortAsc.classList.add('column-sort-asc', 'icon', 'icon-chevronUp');
- //columnSortAsc.dataset.property = column.attribute;
columnSortAsc.addEventListener('click', () => {
sortColumn('asc', column.attribute);
})
- //columnSortAsc.textContent = "^";
const columnSortDesc = document.createElement('span');
columnSortDesc.classList.add('column-sort-desc', 'icon', 'icon-chevronDown');
- //columnSortDesc.dataset.property = column.attribute;
columnSortDesc.addEventListener('click', () => {
sortColumn('desc', column.attribute);
})
- //columnSortDesc.textContent = "v";
columnSort.appendChild(columnSortAsc);
columnSort.appendChild(columnSortDesc);
columnWrapper.appendChild(columnSort);
@@ -284,11 +284,11 @@ function buildListFooter(rows, rowsPerPage) {
const pages = Math.ceil(rows / rowsPerPage);
const footerWrapper = document.createElement('div');
footerWrapper.classList.add('list-footer', 'footer-wrapper');
- console.log('calculated num of pages: ' + pages);
footerWrapper.dataset.pages = pages;
const footerTotal = document.createElement('div');
footerTotal.textContent = `Page 1 of ${pages} -- ${rows} total results`;
footerTotal.classList.add('footer-total');
+
// pagination
const footerPagination = document.createElement('div');
footerPagination.classList.add('footer-pagination');
@@ -298,26 +298,13 @@ function buildListFooter(rows, rowsPerPage) {
footerPrev.addEventListener('click', (event) => {
prevPage(event.target);
})
+
const footerPageBtnsWrapper = document.createElement('div');
footerPageBtnsWrapper.classList.add('footer-pages-wrapper');
- const footerPageBtn = document.createElement('div');
- footerPageBtn.classList.add('footer-pagination-pages', 'currentpage');
- footerPageBtn.id = "current-page";
- footerPageBtn.textContent = '1';
- footerPageBtn.dataset.pagenumber = 1;
- footerPageBtnsWrapper.appendChild(footerPageBtn);
const footerNext = document.createElement('div');
footerNext.classList.add('footer-pagination-button', 'next');
- if (pages > 1) {
- footerNext.classList.add('active');
- for (let i = 2; i <= pages; i++) {
- const footerPageBtns = document.createElement('div');
- footerPageBtns.classList.add('footer-pagination-pages');
- footerPageBtns.textContent = i;
- footerPageBtns.dataset.pagenumber = i;
- footerPageBtnsWrapper.appendChild(footerPageBtns);
- }
- }
+ buildPageSelector(pages, footerPageBtnsWrapper, footerNext);
+
footerNext.addEventListener('click', (event) => {
nextPage(event.target);
})
@@ -333,10 +320,10 @@ function buildListFooter(rows, rowsPerPage) {
const footerPerPageLabel = document.createElement('div');
footerPerPageLabel.textContent = 'Per Page';
footerPerPageLabel.classList.add('footer-perPage-label');
- const footerPerPageDropdown = document.createElement('div');
+ const footerPerPageDropdownWrapper = document.createElement('div');
+ const footerPerPageDropdown = document.createElement('select');
+ footerPerPageDropdown.id = 'per-page';
footerPerPageDropdown.innerHTML = `
-
- `
- footerPerPageDropdown.classList.add('footer-perPage-dropdown');
+ `;
+ footerPerPageDropdown.addEventListener('change', (event) => {
+ repaginate(event.target);
+ });
+ footerPerPageDropdownWrapper.appendChild(footerPerPageDropdown);
+ footerPerPageDropdownWrapper.classList.add('footer-perPage-dropdown');
footerPerPage.appendChild(footerPerPageLabel);
- footerPerPage.appendChild(footerPerPageDropdown);
+ footerPerPage.appendChild(footerPerPageDropdownWrapper);
// end per-page controls
footerWrapper.appendChild(footerTotal);
@@ -357,20 +347,71 @@ function buildListFooter(rows, rowsPerPage) {
return footerWrapper;
}
-function paginate(listItems) {
-
+function buildPageSelector(pageCount, footerPageSelectorWrapper, footerNext) {
+ const footerPageBtn = document.createElement('div');
+ footerPageBtn.classList.add('footer-pagination-pages', 'currentpage');
+ footerPageBtn.id = "current-page";
+ footerPageBtn.textContent = '1';
+ footerPageBtn.dataset.pagenumber = 1;
+ footerPageBtn.addEventListener('click', (event) => {
+ changePage(event.target.dataset.pagenumber);
+ })
+ footerPageSelectorWrapper.appendChild(footerPageBtn);
+ if (pageCount > 1) {
+ footerNext.classList.add('active');
+ for (let i = 2; i <= pageCount; i++) {
+ const footerPageBtns = document.createElement('div');
+ footerPageBtns.classList.add('footer-pagination-pages');
+ footerPageBtns.textContent = i;
+ footerPageBtns.dataset.pagenumber = i;
+ footerPageBtns.addEventListener('click', (event) => {
+ changePage(event.target.dataset.pagenumber);
+ })
+ footerPageSelectorWrapper.appendChild(footerPageBtns);
+ }
+ } else {
+ footerNext.classList.remove('active');
+ }
}
-function nextPage(nextBtn) {
- if (!(nextBtn.classList.contains('active'))) {
- return;
+function repaginate(dropdown) {
+ const numPerPage = dropdown.value;
+ const listItems = document.querySelectorAll('.campaign-row');
+ if (listItems.length > 1 ) {
+ listItems.forEach((row, index) => {
+ row.classList.remove('hidden');
+ if ((index + 1) > numPerPage) row.classList.add('hidden');
+ })
}
+ const totalResults = parseInt(document.querySelector('.list-items').dataset.totalresults);
+ const pageCount = Math.ceil(totalResults / numPerPage);
+ document.querySelector('.list-footer.footer-wrapper').dataset.pages = pageCount;
+
+ const pagesText = `Page 1 of ${pageCount} -- ${totalResults} total results`;
+ document.querySelector('.footer-total').textContent = pagesText;
+
+ const footerPageSelectorWrapper = document.querySelector('.footer-pages-wrapper');
+ footerPageSelectorWrapper.replaceChildren();
+
+ const footerNext = document.querySelector('.footer-pagination-button.next');
+ const footerPrev = document.querySelector('.footer-pagination-button.prev');
+ footerPrev.classList.remove('active');
+ buildPageSelector(pageCount, footerPageSelectorWrapper, footerNext);
+}
+
+function changePage(targetPage) {
+ // if targetPage = currentPage, do nothing
+ const nextBtn = document.querySelector('.footer-pagination-button.next');
const prevBtn = document.querySelector('.footer-pagination-button.prev');
const currentPageBtn = document.querySelector('#current-page');
- const currentPageValue = parseInt(currentPageBtn.dataset.pagenumber);
- const targetPage = (currentPageValue + 1);
- const nextSelector = "[data-pagenumber='" + (targetPage) + "']";
- const nextPageBtn = document.querySelector(nextSelector);
+ const currentPage = parseInt(currentPageBtn.dataset.pagenumber);
+
+ if (currentPage == targetPage) {
+ return;
+ }
+
+ const newPageSelector = "[data-pagenumber='" + (targetPage) + "']";
+ const newPageBtn = document.querySelector(newPageSelector);
const itemsPerPage = document.querySelector('#per-page').value;
const listItems = document.querySelectorAll('.campaign-row');
@@ -378,21 +419,43 @@ function nextPage(nextBtn) {
const upperBound = (targetPage * itemsPerPage);
listItems.forEach((row, index) => {
- //if ((index + 1) <= (currentPageValue * itemsPerPage) || (index + 1) > (targetPage * itemsPerPage)) {
if ((index + 1) <= (lowerBound) || (index + 1) > (upperBound)) {
row.classList.add('hidden');
} else {
row.classList.remove('hidden');
}
})
- //increment page counter
- prevBtn.classList.add('active');
- const totalPages = parseInt(document.querySelector('.list-footer.footer-wrapper').dataset.pages);
- if (totalPages == targetPage) nextBtn.classList.remove('active');
+ const totalPages = document.querySelector('.list-footer.footer-wrapper').dataset.pages;
+ const totalResults = document.querySelector('.list-items').dataset.totalresults;
+ const pagesText = `Page ${targetPage} of ${totalPages} -- ${totalResults} total results`;
+ document.querySelector('.footer-total').textContent = pagesText;
+ if (totalPages == targetPage) {
+ nextBtn.classList.remove('active')
+ } else {
+ nextBtn.classList.add('active');
+ }
+ if (targetPage == "1") {
+ prevBtn.classList.remove('active')
+ } else {
+ prevBtn.classList.add('active');
+ }
currentPageBtn.id = '';
currentPageBtn.classList.remove('currentpage');
- nextPageBtn.id = 'current-page';
- nextPageBtn.classList.add('currentpage');
+ newPageBtn.id = 'current-page';
+ newPageBtn.classList.add('currentpage');
+ // update next and prev according to which page we're on
+}
+
+function nextPage(nextBtn) {
+ if (!(nextBtn.classList.contains('active'))) {
+ return;
+ }
+ const prevBtn = document.querySelector('.footer-pagination-button.prev');
+ const currentPageBtn = document.querySelector('#current-page');
+ const currentPageValue = parseInt(currentPageBtn.dataset.pagenumber);
+ const targetPage = (currentPageValue + 1);
+ changePage(targetPage);
+ prevBtn.classList.add('active');
}
function prevPage(prevBtn) {
@@ -403,36 +466,11 @@ function prevPage(prevBtn) {
const currentPageBtn = document.querySelector('#current-page');
const currentPageValue = parseInt(currentPageBtn.dataset.pagenumber);
const targetPage = (currentPageValue - 1);
- const prevSelector = "[data-pagenumber='" + (targetPage) + "']";
- const prevPageBtn = document.querySelector(prevSelector);
- const itemsPerPage = document.querySelector('#per-page').value;
- const listItems = document.querySelectorAll('.campaign-row');
-
- const lowerBound = ((targetPage * itemsPerPage) - itemsPerPage);
- //console.log('test lower bound: ' + lowerBound);
- const upperBound = (targetPage * itemsPerPage);
- //console.log('test upper bound: ' + upperBound);
-
- listItems.forEach((row, index) => {
- //if ((index + 1) <= (currentPageValue * itemsPerPage) || (index + 1) > (targetPage * itemsPerPage)) {
- if ((index + 1) < (lowerBound) || (index + 1) > (upperBound)) {
- row.classList.add('hidden');
- } else {
- row.classList.remove('hidden');
- }
- })
+ changePage(targetPage)
nextBtn.classList.add('active');
- //const totalPages = parseInt(document.querySelector('.list-footer.footer-wrapper').dataset.pages);
- if (targetPage == 1) prevBtn.classList.remove('active');
- currentPageBtn.id = '';
- currentPageBtn.classList.remove('currentpage');
- prevPageBtn.id = 'current-page';
- prevPageBtn.classList.add('currentpage');
}
function sortColumn(dir, property) {
- // need to handle dates
- console.log('clicked sort: ' + dir + ', ' + property);
const container = document.querySelector('.list-items');
if (!container) {
console.error("Could not locate list container.");
@@ -440,22 +478,15 @@ function sortColumn(dir, property) {
}
const selector = '[data-property="' + property + '"]';
- console.log(selector)
const divs = document.querySelectorAll(selector);
- console.log(divs.length);
- //document.querySelectorAll('[data-property="description"]')
const sortArray = [];
- // Retrieve text content of each div and store it in an array
divs.forEach(div => {
const textContent = div.textContent.trim();
- //const row = div.parentElement; // need to make this more general
const row = div.closest('.campaign-row');
- console.log(row);
sortArray.push({ textContent, row });
});
- // Sort the divs based on their text content
if (property == 'launch') {
if (dir == 'asc') {
sortArray.sort((a,b) => {
@@ -478,7 +509,6 @@ function sortColumn(dir, property) {
}
}
- // Update the container with the sorted divs
sortArray.forEach(({ row }, index) => {
container.appendChild(row);
});
@@ -486,7 +516,7 @@ function sortColumn(dir, property) {
function determineStatusColor(status) {
switch(status) {
- case 'On Track':
+ case 'Current':
return 'green';
case 'Delayed':
return 'yellow';
@@ -495,4 +525,13 @@ function determineStatusColor(status) {
default:
return 'red';
}
+}
+
+// supply dummy data if none present
+function checkBlankString(string) {
+ if (string == undefined || string == '' ) {
+ return 'Not Available';
+ } else {
+ return string;
+ }
}
\ No newline at end of file
diff --git a/icons/AEM.svg b/icons/AEM.svg
index a608289e..8f15e819 100644
--- a/icons/AEM.svg
+++ b/icons/AEM.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/icons/Acrobat.svg b/icons/Acrobat.svg
index 84cfe515..2d8d6ad2 100644
--- a/icons/Acrobat.svg
+++ b/icons/Acrobat.svg
@@ -1,4 +1,21 @@
-