From 01f830da50cc6c8ae41be27cee13f36589b955be Mon Sep 17 00:00:00 2001 From: Nick Sayre Date: Tue, 5 Nov 2024 17:36:50 -0600 Subject: [PATCH] 1255 - use different data and pdf templates based on feature flag value --- .../ProofOfVeteranStatus.jsx | 60 +++- .../personalization/profile/mocks/server.js | 4 +- src/platform/pdf/templates/index.js | 4 + .../pdf/templates/veteran_status_new.js | 318 ++++++++++++++++++ .../fixtures/veteran_status.json | 8 +- .../veteran_status.unit.spec.js | 65 +--- .../img/design/logo/seal-black-and-white.png | Bin 0 -> 12095 bytes src/site/assets/img/scissors-black.png | Bin 0 -> 5540 bytes 8 files changed, 394 insertions(+), 65 deletions(-) create mode 100644 src/platform/pdf/templates/veteran_status_new.js create mode 100644 src/site/assets/img/design/logo/seal-black-and-white.png create mode 100644 src/site/assets/img/scissors-black.png diff --git a/src/applications/personalization/profile/components/proof-of-veteran-status/ProofOfVeteranStatus.jsx b/src/applications/personalization/profile/components/proof-of-veteran-status/ProofOfVeteranStatus.jsx index ad98ce52c9093..63a25ecf99e87 100644 --- a/src/applications/personalization/profile/components/proof-of-veteran-status/ProofOfVeteranStatus.jsx +++ b/src/applications/personalization/profile/components/proof-of-veteran-status/ProofOfVeteranStatus.jsx @@ -6,6 +6,7 @@ import { generatePdf } from '~/platform/pdf'; import { focusElement } from '~/platform/utilities/ui'; import { captureError } from '~/platform/user/profile/vap-svc/util/analytics'; import { CONTACTS } from '@department-of-veterans-affairs/component-library/contacts'; +import { useFeatureToggle } from '~/platform/utilities/feature-toggles'; import { formatFullName } from '../../../common/helpers'; import { getServiceBranchDisplayName } from '../../helpers'; @@ -32,7 +33,7 @@ const ProofOfVeteranStatus = ({ (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) || /android/i.test(userAgent); - const pdfData = { + const pdfDataOld = { title: `Veteran status card for ${formatFullName({ first, middle, @@ -60,6 +61,53 @@ const ProofOfVeteranStatus = ({ }, }, }; + const pdfDataNew = { + title: `Veteran status card for ${formatFullName({ + first, + middle, + last, + suffix, + })}`, + details: { + fullName: formatFullName({ + first, + middle, + last, + suffix, + }), + serviceHistory: serviceHistory.map(item => { + return { + ...item, + branchOfService: getServiceBranchDisplayName(item.branchOfService), + }; + }), + totalDisabilityRating, + edipi, + image: { + title: 'V-A logo', + url: '/img/design/logo/logo-black-and-white.png', + }, + seal: { + title: 'V-A Seal', + url: '/img/design/logo/seal-black-and-white.png', + }, + scissors: { + title: 'Scissors icon', + url: '/img/scissors-black.png', + }, + }, + }; + + const { + TOGGLE_NAMES, + useToggleValue, + useToggleLoadingValue, + } = useFeatureToggle(); + + const isLoadingFeatureFlags = useToggleLoadingValue(); + const showNewPdf = useToggleValue( + TOGGLE_NAMES.veteranStatusCardUseLighthouse, + ); useEffect( () => { @@ -75,9 +123,11 @@ const ProofOfVeteranStatus = ({ try { await generatePdf( - 'veteranStatus', + isLoadingFeatureFlags || !showNewPdf + ? 'veteranStatus' + : 'veteranStatusNew', 'Veteran status card', - pdfData, + isLoadingFeatureFlags || !showNewPdf ? pdfDataOld : pdfDataNew, !isMobile, ); } catch (error) { @@ -115,6 +165,10 @@ const ProofOfVeteranStatus = ({ ); }); + if (isLoadingFeatureFlags) { + return null; + } + return ( <>
diff --git a/src/applications/personalization/profile/mocks/server.js b/src/applications/personalization/profile/mocks/server.js index 32bd593dd618a..9177f471ca1d9 100644 --- a/src/applications/personalization/profile/mocks/server.js +++ b/src/applications/personalization/profile/mocks/server.js @@ -106,6 +106,7 @@ const responses = { profileUseExperimental: false, profileShowPrivacyPolicy: true, veteranOnboardingContactInfoFlow: true, + veteranStatusCardUseLighthouse: true, }), ), secondsOfDelay, @@ -236,7 +237,8 @@ const responses = { // .json(serviceHistory.generateServiceHistoryError('403')); }, 'GET /v0/disability_compensation_form/rating_info': (_req, res) => { - return res.status(200).json(ratingInfo.success); + // return res.status(200).json(ratingInfo.success.serviceConnected0); + return res.status(200).json(ratingInfo.success.serviceConnected40); // return res.status(500).json(genericErrors.error500); }, diff --git a/src/platform/pdf/templates/index.js b/src/platform/pdf/templates/index.js index c4fe728396384..301f1d98377af 100644 --- a/src/platform/pdf/templates/index.js +++ b/src/platform/pdf/templates/index.js @@ -16,4 +16,8 @@ templates.veteranStatus = () => { return require('./veteran_status'); }; +templates.veteranStatusNew = () => { + return require('./veteran_status_new'); +}; + export { templates }; diff --git a/src/platform/pdf/templates/veteran_status_new.js b/src/platform/pdf/templates/veteran_status_new.js new file mode 100644 index 0000000000000..790b0160c72ba --- /dev/null +++ b/src/platform/pdf/templates/veteran_status_new.js @@ -0,0 +1,318 @@ +/** + * Proof of Veteran Status PDF template. + * + * NB: The order in which items are added to the document is important, + * and thus PDFKit requires performing operations synchronously. + */ +/* eslint-disable no-await-in-loop */ + +import { MissingFieldsException } from '../utils/exceptions/MissingFieldsException'; +import { + createAccessibleDoc, + createHeading, + registerVaGovFonts, +} from './utils'; + +const config = { + margins: { + top: 30, + bottom: 40, + left: 40, + right: 40, + }, + headings: { + H1: { + font: 'Bitter-Bold', + size: 20, + }, + H2: { + font: 'SourceSansPro-Bold', + size: 13, + }, + }, + paragraph: { + font: 'SourceSansPro-Regular', + size: 16, + }, + text: { + boldFont: 'SourceSansPro-Bold', + font: 'SourceSansPro-Regular', + size: 9, + }, + disclaimer: { + font: 'SourceSansPro-Regular', + size: 9, + }, + instruction: { + font: 'SourceSansPro-Regular', + size: 12, + }, +}; + +// Reusable function to fetch and return an image as a base64 data URL +const fetchImage = async url => { + const fetchedImage = await fetch(url); + const contentType = fetchedImage.headers.get('Content-type'); + const base64Data = Buffer.from(await fetchedImage.arrayBuffer()).toString( + 'base64', + ); + return `data:${contentType};base64,${base64Data}`; +}; + +const validate = data => { + const requiredFields = ['fullName', 'serviceHistory']; // If there is no serviceHistory, there is also no DOD ID + + const missingFields = requiredFields.filter(field => !data[field]); + if (missingFields.length) { + throw new MissingFieldsException(missingFields); + } +}; + +const generate = async data => { + validate(data.details); + + const doc = createAccessibleDoc(data, config); + + await registerVaGovFonts(doc); + + doc.addPage({ margins: config.margins }); + + const wrapper = doc.struct('Document'); + doc.addStructure(wrapper); + + // VA logo + if (data.details.image) { + const logoGraphic = await fetchImage(data.details.image.url); + + const logoImage = doc.image( + logoGraphic, + doc.page.margins.left, + doc.page.margins.top, + { width: 155, alt: data.details.image.title }, + ); + + const logo = doc.struct('Figure', { alt: data.details.image.title }, [ + () => logoImage, + ]); + + wrapper.add(logo); + } + + doc.moveDown(0.5); + + // Heading + const heading = createHeading( + doc, + 'H1', + config, + 'Proof of Veteran status card', + { + x: doc.page.margins.left, + paragraphGap: 10, + }, + ); + wrapper.add(heading); + + // description + wrapper.add( + doc.struct('P', () => { + doc + .font(config.paragraph.font) + .fontSize(config.paragraph.size) + .text( + 'You can use your Veteran status card to get discounts for at many stores, businesses, and restaurants. Additionally, you’ll be able to use your Veteran status card to checkout at the commissaries and exchanges on base.', + doc.page.margins.left, + doc.y, + { + lineGap: 4, + width: 450, + }, + ); + }), + ); + + // veteran status card + // Add content synchronously to ensure that reading order + // is left intact for screen reader users. + + doc.moveDown(0.5); + const cardSection = doc.struct('Sect'); + wrapper.add(cardSection); + + const cardYPosition = doc.y; + const cardXPosition = doc.x; + const cardWidth = 252; // roughly results in a 2 x 3.5 inch rectangle + const cardHeight = 144; + const cardPadding = 12; + + // Add a dotted line to indicate where the card should be cut out + const cardWrapper = doc.struct('Artifact', () => { + doc + .lineWidth(0.5) + .roundedRect(doc.page.margins.left, doc.y, cardWidth, cardHeight, 8) + .dash(3.5, { space: 3.5 }) + .stroke(); + }); + + cardSection.add(cardWrapper); + + // Card title + doc.moveDown(0.5); + const cardHeading = doc.struct('H2', () => { + doc + .font(config.headings.H2.font) + .fontSize(config.headings.H2.size) + .text( + 'Proof of Veteran Status', + doc.page.margins.left + cardPadding, + doc.y, + ); + }); + cardSection.add(cardHeading); + + // VA seal + if (data.details.seal) { + const sealGraphic = await fetchImage(data.details.seal.url); + const sealWidth = 40; + const sealImage = doc.image( + sealGraphic, + cardXPosition + cardWidth - cardPadding - sealWidth, // positioned relative to top-right corner + cardYPosition + cardPadding, + { width: sealWidth, alt: data.details.image.title }, + ); + const seal = doc.struct('Figure', { alt: data.details.seal.title }, [ + () => sealImage, + ]); + cardSection.add(seal); + } + + // Generate content for latest period of service + const latestService = data.details.serviceHistory[0]; + const serviceStartYear = latestService.beginDate + ? latestService.beginDate.substring(0, 4) + : ''; + const serviceEndYear = latestService.endDate + ? latestService.endDate.substring(0, 4) + : ''; + const dateRange = + serviceStartYear.length || serviceEndYear.length + ? `${serviceStartYear}–${serviceEndYear}` + : ''; + + // First column of info items + doc.moveDown(0.25); + const infoItems = [ + { + heading: 'Name', + content: data.details.fullName, + }, + { + heading: 'Latest period of service', + content: `${latestService.branchOfService} • ${dateRange}`, + }, + { + heading: 'DoD ID Number', + content: data.details.edipi, + }, + ]; + + let lastHeaderY; + infoItems.forEach(item => { + lastHeaderY = doc.y; + const header = doc.struct('H2', () => { + doc + .font(config.text.boldFont) + .fontSize(config.text.size) + .text(`${item.heading}`); + }); + const content = doc.struct('P', () => { + doc + .font(config.text.font) + .fontSize(config.text.size) + .text(item.content) + .moveDown(0.5); + }); + cardSection.add(header); + cardSection.add(content); + }); + + // Second column of info items + const infoItems2 = [ + { + heading: 'VA disability rating', + content: `${data.details.totalDisabilityRating?.toString()}%`, + condition: data.details.totalDisabilityRating, + }, + ]; + infoItems2.forEach(item => { + if (item.condition) { + const header = doc.struct('H2', () => { + doc + .font(config.text.boldFont) + .fontSize(config.text.size) + .text(`${item.heading}`, doc.page.margins.left + 130, lastHeaderY); + }); + const content = doc.struct('P', () => { + doc + .font(config.text.font) + .fontSize(config.text.size) + .text(item.content) + .moveDown(0.5); + }); + cardSection.add(header); + cardSection.add(content); + } + }); + + doc.moveDown(0.5); + + // Disclaimer text + const disclaimerText = doc.struct('P', () => { + doc + .font(config.disclaimer.font) + .fontSize(config.disclaimer.size) + .text( + "This card doesn't entitle you to any VA benefits.", + doc.page.margins.left + cardPadding, + cardYPosition + cardHeight - cardPadding - config.disclaimer.size, // position this text relative to the bottom of the card + ); + }); + cardSection.add(disclaimerText); + + // Instructions + doc.moveDown(3); + const scissorsWidth = 10; + if (data.details.scissors) { + const scissorsGraphic = await fetchImage(data.details.scissors.url); + const scissorsImage = doc.image( + scissorsGraphic, + doc.page.margins.left, + doc.y, + { width: scissorsWidth }, + ); + const scissors = doc.struct( + 'Figure', + { alt: data.details.scissors.title }, + [() => scissorsImage], + ); + wrapper.add(scissors); + } + + const instructionText = doc.struct('P', () => { + doc + .font(config.instruction.font) + .fontSize(config.instruction.size) + .text( + 'Cut this card out and keep in your wallet.', + doc.page.margins.left + scissorsWidth + 4, + doc.y - scissorsWidth - 3, // position this text relative to the bottom of the card + ); + }); + wrapper.add(instructionText); + + wrapper.end(); + doc.flushPages(); + return doc; +}; + +export { generate }; diff --git a/src/platform/pdf/test/templates/veteran_status/fixtures/veteran_status.json b/src/platform/pdf/test/templates/veteran_status/fixtures/veteran_status.json index 46a041d05944c..53f0816c2c8ef 100644 --- a/src/platform/pdf/test/templates/veteran_status/fixtures/veteran_status.json +++ b/src/platform/pdf/test/templates/veteran_status/fixtures/veteran_status.json @@ -1,24 +1,24 @@ { - "title": "Veteran Status", + "title": "Proof of Veteran status card", "details": { "fullName": "John H. Doe", "serviceHistory": [ { - "branchOfService": "Air Force", + "branchOfService": "United States Air Force", "beginDate": "2009-04-12", "endDate": "2013-04-11", "personnelCategoryTypeCode": "V", "characterOfDischargeCode": "A" }, { - "branchOfService": "Army", + "branchOfService": "United States Army", "beginDate": "2005-04-12", "endDate": "2009-04-11", "personnelCategoryTypeCode": "A", "characterOfDischargeCode": "A" }, { - "branchOfService": "Navy", + "branchOfService": "United States Navy", "beginDate": "2003-04-12", "endDate": "2005-04-11", "personnelCategoryTypeCode": "A", diff --git a/src/platform/pdf/test/templates/veteran_status/veteran_status.unit.spec.js b/src/platform/pdf/test/templates/veteran_status/veteran_status.unit.spec.js index 63ef0c2948b0b..6b11121ad03d1 100644 --- a/src/platform/pdf/test/templates/veteran_status/veteran_status.unit.spec.js +++ b/src/platform/pdf/test/templates/veteran_status/veteran_status.unit.spec.js @@ -31,7 +31,7 @@ describe('Veteran Status PDF template', () => { }; describe('PDF Semantics', () => { - it('places the name in an H1', async () => { + it('places the page title in an H1', async () => { const data = require('./fixtures/veteran_status.json'); const { pdf } = await generateAndParsePdf(data); @@ -41,9 +41,7 @@ describe('Veteran Status PDF template', () => { const content = await page.getTextContent({ includeMarkedContent: true }); expect(content.items.filter(item => item.tag === 'H1').length).to.eq(1); - expect(content.items[3].str).to.eq(data.details.fullName); - // H1 in this case is set to 14 px - expect(content.items[3].height).to.eq(10.5); + expect(content.items[3].str).to.eq(data.details.title); }); it('All sections are contained by a root level Document element', async () => { @@ -63,7 +61,7 @@ describe('Veteran Status PDF template', () => { }); describe('Document section customization', () => { - it('Shows service details', async () => { + it('Shows latest service details', async () => { const data = require('./fixtures/veteran_status.json'); const { pdf } = await generateAndParsePdf(data); @@ -73,39 +71,13 @@ describe('Veteran Status PDF template', () => { const content = await page.getTextContent({ includeMarkedContent: true }); const listContent = content.items.filter( - item => item.str === 'Period of service', + item => item.str === 'Latest period of service', ); expect(listContent.length).to.eq(1); const airForceText = content.items.filter( - item => - item.str === `${data.details.serviceHistory[0].branchOfService}`, + item => item.str === 'United States Air Force • 2009–2013', ); expect(airForceText.length).to.eq(1); - const armyText = content.items.filter( - item => - item.str === `${data.details.serviceHistory[1].branchOfService}`, - ); - expect(armyText.length).to.eq(1); - }); - - it('Should only show the 2 most recent periods of service', async () => { - const data = require('./fixtures/veteran_status.json'); - const { pdf } = await generateAndParsePdf(data); - - // Fetch the first page - const pageNumber = 1; - const page = await pdf.getPage(pageNumber); - - const content = await page.getTextContent({ includeMarkedContent: true }); - - const listItems = content.items.filter(item => item.tag === 'Lbl'); - expect(listItems.length).to.eq(2); - - const navyService = content.items.filter( - item => - item.str === `${data.details.serviceHistory[2].branchOfService}`, - ); - expect(navyService.length).to.eq(0); }); it('Shows disability rating details', async () => { @@ -118,13 +90,12 @@ describe('Veteran Status PDF template', () => { const content = await page.getTextContent({ includeMarkedContent: true }); const ratingText = content.items.filter( - item => item.str === 'Disability rating:', + item => item.str === 'VA disability rating', ); expect(ratingText.length).to.eq(1); const ratingContent = content.items.filter( item => - item.str === - `${data.details.totalDisabilityRating.toString()}% service connected`, + item.str === `${data.details.totalDisabilityRating.toString()}%`, ); expect(ratingContent.length).to.eq(1); }); @@ -139,7 +110,7 @@ describe('Veteran Status PDF template', () => { const content = await page.getTextContent({ includeMarkedContent: true }); const dodIdTitle = content.items.filter( - item => item.str === 'DoD ID Number:', + item => item.str === 'DoD ID Number', ); expect(dodIdTitle.length).to.eq(1); const dodId = content.items.filter( @@ -148,26 +119,6 @@ describe('Veteran Status PDF template', () => { expect(dodId.length).to.eq(1); }); - it("Doesn't show DoD ID Number if it is unavailable", async () => { - const data = require('./fixtures/veteran_status.json'); - data.details.edipi = null; - const { pdf } = await generateAndParsePdf(data); - - // Fetch the first page - const pageNumber = 1; - const page = await pdf.getPage(pageNumber); - - const content = await page.getTextContent({ includeMarkedContent: true }); - const dodIdTitle = content.items.filter( - item => item.str === 'DoD ID Number:', - ); - expect(dodIdTitle.length).to.eq(0); - const dodId = content.items.filter( - item => item.str === data.details.edipi, - ); - expect(dodId.length).to.eq(0); - }); - it('Has a default language (english)', async () => { const data = require('./fixtures/veteran_status.json'); const { metadata } = await generateAndParsePdf(data); diff --git a/src/site/assets/img/design/logo/seal-black-and-white.png b/src/site/assets/img/design/logo/seal-black-and-white.png new file mode 100644 index 0000000000000000000000000000000000000000..45a5fec2c1c3da21294ac89be28557e4948be7a0 GIT binary patch literal 12095 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 m