diff --git a/blocks/gmo-campaign-details/gmo-campaign-details.css b/blocks/gmo-campaign-details/gmo-campaign-details.css index 2b5f2a06..1005d4a1 100644 --- a/blocks/gmo-campaign-details/gmo-campaign-details.css +++ b/blocks/gmo-campaign-details/gmo-campaign-details.css @@ -33,6 +33,9 @@ body { & .h3 { font: normal normal bold 14px/21px Adobe Clean; } + & .subtitle { + font: normal normal normal 14px/21px Adobe Clean; + } & > .main-body-wrapper { display: flex; flex-direction: column; @@ -51,6 +54,7 @@ body { margin-left: 20px; display: flex; flex-direction: column; + justify-content: space-evenly; & .icon-calendar { width: 17px; } @@ -68,12 +72,15 @@ body { & .header-row2 { display: flex; align-items: center; - margin-top: 20px; + } + & .header-row3 { + display: flex; + align-items: center; } & .campaign-status { - background-color: #EEF8F5; border-radius: 4px; - color: #33AB84; + color: black; + filter: saturate(0.5); font: normal normal normal 12px/15px Adobe Clean; height: 24px; line-height: 24px; @@ -265,21 +272,25 @@ body { } } } -} -.artifacts-wrapper { - display: flex; - flex-direction: column; - width: 400px; - margin-right: 100px; - & .links { + .links-wrapper { display: flex; - justify-content: space-between; - margin-top: 10px; - } - & .campaign-link { - font: normal normal normal 14px/21px Adobe Clean; - letter-spacing: 0px; - color: #0D66D0; + flex-direction: column; + max-width: 90%; + margin-right: 100px; + margin-top: unset; + & .links { + display: flex; + justify-content: space-between; + margin-top: 10px; + } + & .campaign-link { + font: normal normal normal 14px/21px Adobe Clean; + letter-spacing: 0px; + color: #0D66D0; + &:not(:last-child) { + margin-right: 30px; + } + } } } .table-wrapper { @@ -321,6 +332,18 @@ body { text-overflow: ellipsis; line-height: 16px; } + & .date-wrapper { + display: flex; + flex-direction: column; + justify-content:center; + & > .completion-date, .revised-date { + line-height: 21px; + } + & > .revised-date { + color: #959595; + font: italic normal normal 11px/21px Adobe Clean; + } + } } &.collapsible.header { height: unset; @@ -360,6 +383,7 @@ body { border-top: 2px solid #F4F4F4; } } + .status-wrapper { height: 56px; display: flex; @@ -397,6 +421,22 @@ body { } } +.header-row3:hover .date-tooltip { + visibility: visible; + opacity: 1; +} +.date-tooltip { + background-color: #D3D3D3; + border-radius: 2px; + visibility: hidden; + z-index: 1; + position: absolute; + text-align: center; + width: 100px; + padding: 2px 0; + font: normal normal normal 12px/17px Adobe Clean; + margin-left: 100px; +} .column1 { margin-left: 45px; } @@ -416,7 +456,7 @@ body { width: 170px; } .column8 { - width: 100px; + width: 120px; } .column9 { width: 150px; diff --git a/blocks/gmo-campaign-details/gmo-campaign-details.js b/blocks/gmo-campaign-details/gmo-campaign-details.js index ef22138e..7fc5a2f7 100644 --- a/blocks/gmo-campaign-details/gmo-campaign-details.js +++ b/blocks/gmo-campaign-details/gmo-campaign-details.js @@ -2,22 +2,22 @@ import { decorateIcons, readBlockConfig } from '../../scripts/lib-franklin.js'; import { getQueryVariable } from '../../scripts/shared.js'; import { getProgramInfo } from '../../scripts/graphql.js'; import { checkBlankString } from '../gmo-campaign-list/gmo-campaign-list.js' -import { statusMappings, productMappings } from '../../scripts/shared-campaigns.js'; +import { statusMappings, productMappings, typeMappings } from '../../scripts/shared-campaigns.js'; import { getBaseConfigPath } from '../../scripts/site-config.js'; import { searchAsset } from '../../scripts/assets.js'; let blockConfig; +const programName = getQueryVariable('programName'); export default async function decorate(block) { - const programName = getQueryVariable('programName'); - const programData = await getProgramInfo(programName, "program"); - const deliverables = getProgramInfo(programName, "deliverables"); + const programData = await getProgramInfo(programName, "getProgramDetails"); + const deliverables = getProgramInfo(programName, "getProgramDeliverables"); const program = programData.data.programList.items[0]; const kpis = buildKPIList(program).outerHTML; const products = buildProductList(program).outerHTML; const audiences = buildAudienceList(program).outerHTML; const date = formatDate(program.launchDate); - const status = buildStatus(program.status).outerHTML; + const artifactLinks = buildArtifactLinks(program).outerHTML; blockConfig = readBlockConfig(block); block.innerHTML = `
@@ -33,8 +33,10 @@ export default async function decorate(block) { ${program.programName} ${status}
-
+ ${program.campaignName ? '
' + program.campaignName + '
': ""} +
+ Launch date ${date}
@@ -79,6 +81,7 @@ export default async function decorate(block) {
+ ${artifactLinks} `; const listContainer = block.querySelector('.list-container'); listContainer.appendChild(listHeaders); listContainer.appendChild(listItems); @@ -187,10 +183,9 @@ async function buildCampaignList(campaigns, numPerPage) { const campaignName = document.createElement('div'); campaignName.classList.add('campaign-name-wrapper', 'vertical-center'); campaignName.innerHTML = ` -
${checkBlankString(campaign.node.campaignName)}
-
${checkBlankString(campaign.node.programName)}
- `; - +
${checkBlankString(campaign.node.programName)}
+
${checkBlankString(campaign.node.campaignName)}
+ ` campaignInfoWrapper.appendChild(campaignIconLink); campaignInfoWrapper.appendChild(campaignName); @@ -211,18 +206,9 @@ async function buildCampaignList(campaigns, numPerPage) { const campaignProducts = buildProductsList(checkBlankString(campaign.node.productOffering)); campaignProducts.classList.add('column-4', 'vertical-center'); - const campaignStatusWrapper = document.createElement('div'); + var campaignStatusWrapper = document.createElement('div'); campaignStatusWrapper.classList.add('status-wrapper', 'column-6', 'vertical-center'); - - const campaignStatus = document.createElement('div'); - const statusStr = checkBlankString(campaign.node.status); - const statusString = statusMappings[statusStr].label; - campaignStatus.textContent = statusString; - campaignStatus.classList.add(statusMappings[statusStr].color); - campaignStatus.classList.add('status'); - campaignStatus.dataset.property = 'status'; - campaignStatusWrapper.appendChild(campaignStatus); - + campaignStatusWrapper = buildStatus(campaignStatusWrapper, campaign); campaignRow.appendChild(campaignInfoWrapper); campaignRow.appendChild(campaignOverviewWrapper); campaignRow.appendChild(campaignLaunch); @@ -234,6 +220,20 @@ async function buildCampaignList(campaigns, numPerPage) { return listWrapper; } +function buildStatus(statusWrapper, campaign) { + const campaignStatus = document.createElement('div'); + const statusStr = checkBlankString(campaign.node.status); + const statusArray = statusMapping.data.jsonByPath.item.json.options; + const statusMatch = statusArray.filter(item => item.value === statusStr); + const statusText = statusMatch.length > 0 ? statusMatch[0].text : statusStr; + campaignStatus.textContent = statusText; + campaignStatus.style.backgroundColor = "#" + statusMatch[0]["color-code"]; + campaignStatus.classList.add('status'); + campaignStatus.dataset.property = 'status'; + statusWrapper.appendChild(campaignStatus); + return statusWrapper; +} + function buildProductsList(productList) { const campaignProducts = document.createElement('div'); const productEl = buildProduct(productList); diff --git a/scripts/assets.js b/scripts/assets.js index a1f140c0..9eb62894 100644 --- a/scripts/assets.js +++ b/scripts/assets.js @@ -88,8 +88,9 @@ export async function searchAsset(programName, campaignName, imageWidth = 80) { // Asset retrieved successfully const responseBody = await response.json(); const assetData = responseBody.results[0].hits[0]; + const totalAssets = responseBody.results[0].nbHits; const thumbnailURL = await getOptimizedDeliveryUrl(assetData.assetId, assetData['repo-name'], imageWidth); - return {imageUrl : thumbnailURL, imageAltText: assetData['repo-name']}; + return {imageUrl : thumbnailURL, imageAltText: assetData['repo-name'], assetCount: totalAssets}; } // Handle other response codes throw new Error(`Failed to search asset: ${response.status} ${response.statusText}`); diff --git a/scripts/graphql.js b/scripts/graphql.js index a35a4cc3..8db1d8b4 100644 --- a/scripts/graphql.js +++ b/scripts/graphql.js @@ -226,11 +226,11 @@ export function generateFilterJSON(filterParams) { export async function getProgramInfo(programName, queryType) { const baseApiUrl = `${await getGraphqlEndpoint()}/graphql/execute.json`; const projectId = 'gmo'; - const queryName = (queryType == "deliverables") ? "getProgramDeliverables" : "getProgramDetails"; + //const queryName = (queryType == "deliverables") ? "getProgramDeliverables" : "getProgramDetails"; const encodedProgramName = encodeURIComponent(programName); const encodedSemiColon = encodeURIComponent(';'); //persisted query URLs have to be encoded together with the first semicolon - const graphqlEndpoint = `${baseApiUrl}/${projectId}/${queryName}${encodedSemiColon}programName=${encodedProgramName}`; + const graphqlEndpoint = `${baseApiUrl}/${projectId}/${queryType}${encodedSemiColon}programName=${encodedProgramName}`; const jwtToken = await getBearerToken(); // Return the fetch promise chain so that it can be awaited outside @@ -251,3 +251,29 @@ export async function getProgramInfo(programName, queryType) { throw error; // Rethrow or handle error as appropriate }); } + +export async function getMappingInfo(queryType) { + const baseApiUrl = `${await getGraphqlEndpoint()}/graphql/execute.json`; + const projectId = 'gmo'; + //persisted query URLs have to be encoded together with the first semicolon + const graphqlEndpoint = `${baseApiUrl}/${projectId}/${queryType}`; + const jwtToken = await getBearerToken(); + + // Return the fetch promise chain so that it can be awaited outside + return fetch(graphqlEndpoint, { + method: 'GET', + headers: { + Authorization: jwtToken, + }, + }).then(response => { + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + return response.json(); + }).then(data => { + return data; // Make sure to return the data so that the promise resolves with it + }).catch(error => { + console.error('Error fetching data: ', error); + throw error; // Rethrow or handle error as appropriate + }); +} \ No newline at end of file diff --git a/scripts/shared-campaigns.js b/scripts/shared-campaigns.js index 51993236..a20f0215 100644 --- a/scripts/shared-campaigns.js +++ b/scripts/shared-campaigns.js @@ -18,6 +18,10 @@ export const productMappings = { "name": "Acrobat Pro", "icon": "acro-icon" }, + "acrobat-export-pdf": { + "name": "Acrobat Export PDF", + "icon": "acro-icon" + }, "lightroom": { "name": "Lightroom", "icon": "lr-icon", @@ -34,4 +38,34 @@ export const productMappings = { "name": "Not Available", "icon": "gear" } +} + +export const typeMappings = { + "email": { + "name": "E-Mail" + }, + "adobe-com": { + "name": "Adobe.com" + }, + "other": { + "name": "Other" + }, + "in-app": { + "name": "In-App" + }, + "paid-media-static": { + "name": "Paid Media: Static" + }, + "paid-media-video": { + "name": "Paid Media: Video" + }, + "owned-social": { + "name": "Owned Social" + }, + "discover": { + "name": "Discover" + }, + null: { + "name": "Not Available" + } } \ No newline at end of file