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

ASSETS-88922 : Review the Deliverable page load time #130

Merged
merged 10 commits into from
Jun 28, 2024
132 changes: 82 additions & 50 deletions blocks/gmo-program-details/gmo-program-details.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,47 @@ const platformMappings = getMappingArray('platforms');
export default async function decorate(block) {
const encodedSemi = encodeURIComponent(';');
const encodedProgram = encodeURIComponent(programName);

blockConfig = readBlockConfig(block);

const programQueryString = `getProgramDetails${encodedSemi}programName=${encodedProgram}${encodedSemi}programID=${encodeURIComponent(programID)}`;
const deliverableQueryString = `getProgramDeliverables${encodedSemi}programName=${encodedProgram}${encodedSemi}programID=${encodeURIComponent(programID)}`;

// Immediately render a placeholder header
block.innerHTML = `
<div class="back-button">
<span class="icon icon-back"></span>
<span class="back-label">Back</span>
</div>
<div class="main-body-wrapper">
<div class="placeholder-header">Loading program details...</div>
</div>
`;

// Wait for program data to render the actual header
const programData = await executeQuery(programQueryString);
const program = programData.data.programList.items[0];
blockConfig = readBlockConfig(block);
const header = buildHeader(program, queryVars).outerHTML;
if (!program) {

// Update the header with the actual data
block.querySelector('.placeholder-header').outerHTML = header;

let imageObject = null;
let totalassets = 0;
if (program) {
try {
imageObject = await searchAsset(program.programName, program.campaignName);
if (imageObject) {
insertImageIntoCampaignImg(block, imageObject);
totalassets = imageObject.assetCount;
}
} catch (error) {
console.error("Failed to load campaign image:", error);
}
decorateIcons(block);
}
else
{
block.innerHTML = `
<div class="back-button">
<span class="icon icon-back"></span>
Expand All @@ -35,30 +70,15 @@ export default async function decorate(block) {
return;
}

const deliverableQueryString = `getProgramDeliverables${encodedSemi}programName=${encodedProgram}${encodedSemi}programID=${encodeURIComponent(programID)}`;
const deliverables = await executeQuery(deliverableQueryString);

const p0TargetMarketArea = program.p0TargetMarketArea;
const p1TargetMarketArea = program.p1TargetMarketArea;

// Extract unique deliverable types
const uniqueDeliverableTypes = getUniqueItems(programData.data.deliverableList.items, 'deliverableType');
// Extract unique platforms (flattened from arrays within each item)
const uniquePlatforms = getUniqueItems(programData.data.deliverableList.items, 'platforms');
const kpis = buildKPIList(program).outerHTML;

const targetMarketAreas = buildTargetMarketAreaList(p0TargetMarketArea,p1TargetMarketArea).outerHTML;

const audiences = buildAudienceList(program).outerHTML;
const artifactLinks = buildArtifactLinks(program).outerHTML;

block.innerHTML = `
<div class="back-button">
<span class="icon icon-back"></span>
<span class="back-label">Back</span>
</div>
<div class="main-body-wrapper">
${header}

// Inject the additional HTML content
block.querySelector('.main-body-wrapper').innerHTML += `
<div class="tab-wrapper">
<div id="tab1toggle" data-target="tab1" class="tabBtn active">Overview</div>
<div id="tab2toggle" data-target="tab2" class="tabBtn">Deliverables</div>
Expand Down Expand Up @@ -127,7 +147,7 @@ export default async function decorate(block) {
${artifactLinks}
<div class="total-assets total-assets-tooltip">
<div class="h3">Total Approved Assets</div>
<span id="totalassets" class="description"></span>
<span id="totalassets" class="description">${totalassets}</span>
<span class="tooltiptext">To view the assets, go to the "All Asset" search page and use Program and Campaign name facet to filter the assets</span>
</div>
</div>
Expand All @@ -146,26 +166,43 @@ export default async function decorate(block) {
</div>
</div>
</div>
</div>
`;

// Wait for deliverables data
const deliverables = await executeQuery(deliverableQueryString);

const uniqueDeliverableTypes = getUniqueItems(programData.data.deliverableList.items, 'deliverableType');
const uniquePlatforms = getUniqueItems(programData.data.deliverableList.items, 'platforms');

buildProductCard(program);
try {
const imageObject = await searchAsset(program.programName, program.campaignName);
if (imageObject){
insertImageIntoCampaignImg(block,imageObject);
document.getElementById('totalassets').textContent = imageObject.assetCount;
}
else
{
document.getElementById('totalassets').textContent = 0;
}
} catch (error) {
console.error("Failed to load campaign image:", error);
}
buildFieldScopes('deliverable-type', uniqueDeliverableTypes, block);
buildFieldScopes('platforms', uniquePlatforms, block);

const table = await buildTable(await deliverables).then(async (rows) => {
return rows;
});

block.querySelector('.tab-wrapper').addEventListener('click', (event) => {
// Batch Dom Updates
const tableRoot = block.querySelector('.table-content');
const fragment = document.createDocumentFragment();
fragment.appendChild(table);
tableRoot.appendChild(fragment);

buildStatus(program.status);

// Optimize Event Listeners: Added debouncing to event listeners to prevent performance issues.
const debounce = (func, delay) => {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), delay);
};
};

block.querySelector('.tab-wrapper').addEventListener('click', debounce((event) => {
switchTab(event.target);
})
}, 300));

enableBackBtn(block, blockConfig);
block.querySelectorAll('.read-more').forEach((button) => {
button.addEventListener('click', (event) => {
Expand All @@ -175,14 +212,7 @@ export default async function decorate(block) {
});
});
decorateIcons(block);
buildFieldScopes('deliverable-type',uniqueDeliverableTypes, block);
buildFieldScopes('platforms',uniquePlatforms, block);
const table = await buildTable(await deliverables).then(async (rows) => {
return rows;
})
const tableRoot = block.querySelector('.table-content');
tableRoot.appendChild(table);
buildStatus(program.status);

}

function enableBackBtn(block, blockConfig) {
Expand Down Expand Up @@ -248,9 +278,11 @@ function getUniqueItems(items, property) {
)];
}

function insertImageIntoCampaignImg(block,imageObject) {
function insertImageIntoCampaignImg(block, imageObject) {
const campaignImgDiv = block.querySelector('.campaign-img');
const imgElement = document.createElement('img');
//Lazy load images
imgElement.loading = 'lazy';
imgElement.src = imageObject.imageUrl;
imgElement.alt = imageObject.imageAltText;
campaignImgDiv.appendChild(imgElement);
Expand All @@ -259,7 +291,7 @@ function insertImageIntoCampaignImg(block,imageObject) {
function switchTab(tab) {
if (tab.classList.contains('active') || tab.classList.contains('tab-wrapper')) {
return;
}
}
document.querySelector('.tabBtn.active').classList.toggle('active');
document.querySelector(`.tab:not(.inactive)`).classList.toggle('inactive');
const targetTab = tab.dataset.target;
Expand Down Expand Up @@ -412,7 +444,7 @@ function formatDate(dateString) {

// Formatting the date into mm/dd/yyyy format
const formattedDate = mm + '/' + dd + '/' + yyyy;

return formattedDate;
}

Expand Down Expand Up @@ -502,7 +534,7 @@ async function buildHeaderRow(category, headerType, isInactive, matchCount) {
const headerRow = document.createElement('div');
headerRow.classList.add('row', 'collapsible', 'header');
let divopen;
if (headerType === 'subcategory') {
if (headerType === 'subcategory') {
headerRow.classList.add('subheader');
divopen = '<div class="heading-wrapper subheading">';
} else {
Expand Down Expand Up @@ -579,7 +611,7 @@ function sortRows(rows) {
nodes.sort((a, b) => {
var classA = a.classList ? a.classList.contains('datarow') : false;
var classB = b.classList ? b.classList.contains('datarow') : false;

if (classA && !classB) {
return 1;
} else if (!classA && classB) {
Expand Down
Loading