From 893a37356d86593cd36b33182340612fdbe54cf2 Mon Sep 17 00:00:00 2001 From: Rhys Date: Fri, 24 Jan 2025 10:06:08 +0000 Subject: [PATCH 1/3] Updating body schema's with shared data --- src/api/models/cms/Page/Body.ts | 59 +++++++++++--------------- src/app/components/cms/Chart/Chart.tsx | 4 +- 2 files changed, 26 insertions(+), 37 deletions(-) diff --git a/src/api/models/cms/Page/Body.ts b/src/api/models/cms/Page/Body.ts index 8fd1478e4..facc51d5d 100644 --- a/src/api/models/cms/Page/Body.ts +++ b/src/api/models/cms/Page/Body.ts @@ -19,7 +19,7 @@ export const WithWeatherHealthAlertCard = z.object({ alert_type: HealthAlertTypes, }) -export const WithHeadlineNumbersRowCard = z.object({ +const WithHeadlineNumbersRowCard = z.object({ columns: z.array( z.object({ id: z.string(), @@ -32,16 +32,23 @@ export const WithHeadlineNumbersRowCard = z.object({ ), }) +const chartCardValues = z.object({ + title: z.string(), + chart: Chart, + body: z.string(), + tag_manager_event_id: z.string().nullable(), + x_axis: z.string().nullable(), + y_axis: z.string().nullable(), + x_axis_title: z.string().optional(), + y_axis_title: z.string().optional(), + y_axis_minimum_value: z.number().nullable().optional(), + y_axis_maximum_value: z.number().nullable().optional(), +}) + export const WithChartHeadlineAndTrendCard = z.object({ - type: z.literal('chart_with_headline_and_trend_card'), id: z.string(), - value: z.object({ - title: z.string(), - body: z.string(), - chart: Chart, - tag_manager_event_id: z.string().nullable(), - x_axis: z.string().nullable(), - y_axis: z.string().nullable(), + type: z.literal('chart_with_headline_and_trend_card'), + value: chartCardValues.extend({ headline_number_columns: Blocks, }), }) @@ -49,39 +56,21 @@ export const WithChartHeadlineAndTrendCard = z.object({ export const WithChartCard = z.object({ id: z.string(), type: z.enum(['chart_card', 'headline_chart_card']), - value: z.object({ - title: z.string(), - body: z.string(), - chart: Chart, - tag_manager_event_id: z.string().nullable(), - x_axis: z.string().nullable(), - y_axis: z.string().nullable(), - x_axis_title: z.string().optional(), - y_axis_title: z.string().optional(), - y_axis_minimum_value: z.number().nullable().optional(), - y_axis_maximum_value: z.number().nullable().optional(), - }), + value: chartCardValues, }) export const WithSimplifiedChartCardAndLink = z.object({ id: z.string(), type: z.enum(['simplified_chart_with_link']), - value: z.object({ - title: z.string(), - sub_title: z.string(), - tag_manager_event_id: z.string().nullable(), - topic_page: z.string(), - x_axis: z.string().nullable(), - x_axis_title: z.string().optional(), - y_axis_title: z.string().optional(), - y_axis: z.string().nullable(), - y_axis_minimum_value: z.number().nullable().optional(), - y_axis_maximum_value: z.number().nullable().optional(), - chart: Chart, - }), + value: chartCardValues + .extend({ + sub_title: z.string(), + topic_page: z.string(), + }) + .omit({ body: true }), }) -export const ChartSchemas = z.discriminatedUnion('type', [ +export const ChartCardSchemas = z.discriminatedUnion('type', [ WithChartHeadlineAndTrendCard, WithChartCard, WithSimplifiedChartCardAndLink, diff --git a/src/app/components/cms/Chart/Chart.tsx b/src/app/components/cms/Chart/Chart.tsx index f9b908831..abf837b60 100644 --- a/src/app/components/cms/Chart/Chart.tsx +++ b/src/app/components/cms/Chart/Chart.tsx @@ -1,6 +1,6 @@ import { z } from 'zod' -import { ChartSchemas } from '@/api/models/cms/Page' +import { ChartCardSchemas } from '@/api/models/cms/Page' import { getCharts } from '@/api/requests/charts/getCharts' import { getAreaSelector } from '@/app/hooks/getAreaSelector' import { getPathname } from '@/app/hooks/getPathname' @@ -12,7 +12,7 @@ import { ChartEmpty } from '../ChartEmpty/ChartEmpty' interface ChartProps { /* Request metadata from the CMS required to fetch from the headlines api */ - data: z.infer['value'] + data: z.infer['value'] /* Size of chart based on whether the chart is displayed in a 1 or 2 column layout, or half/third layouts for landiing page */ size: 'narrow' | 'wide' | 'half' | 'third' From 68d12b4a8cff45aa3a4656bc0ce6a44feb7b848b Mon Sep 17 00:00:00 2001 From: Rhys Date: Fri, 24 Jan 2025 12:51:19 +0000 Subject: [PATCH 2/3] Additional date_prefix locations --- public/locales/en/common.json | 2 +- src/api/models/cms/Page/Body.ts | 3 ++- src/app/components/cms/Chart/Chart.spec.tsx | 5 +++++ src/app/components/cms/Download/Download.spec.tsx | 1 + src/app/components/cms/Table/Table.spec.tsx | 1 + .../components/cms/Timestamp/Timestamp.spec.tsx | 2 ++ src/app/components/cms/Timestamp/Timestamp.tsx | 4 ++-- .../handlers/cms/pages/fixtures/page/covid-19.ts | 14 ++++++++++++++ .../handlers/cms/pages/fixtures/page/dashboard.ts | 4 ++++ .../handlers/cms/pages/fixtures/page/influenza.ts | 6 ++++++ .../fixtures/page/other-respiratory-viruses.ts | 13 +++++++++++++ 11 files changed, 51 insertions(+), 4 deletions(-) diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 6b0fbfb45..a19af247b 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -58,7 +58,7 @@ } }, "timestamp": { - "value": "Up to and including {{value, dateShort}}" + "value": "{{prefix}} {{value, dateShortest}}" }, "table": { "toggle": "View data in a tabular format", diff --git a/src/api/models/cms/Page/Body.ts b/src/api/models/cms/Page/Body.ts index facc51d5d..6dcb02cc7 100644 --- a/src/api/models/cms/Page/Body.ts +++ b/src/api/models/cms/Page/Body.ts @@ -43,6 +43,7 @@ const chartCardValues = z.object({ y_axis_title: z.string().optional(), y_axis_minimum_value: z.number().nullable().optional(), y_axis_maximum_value: z.number().nullable().optional(), + date_prefix: z.string(), }) export const WithChartHeadlineAndTrendCard = z.object({ @@ -67,7 +68,7 @@ export const WithSimplifiedChartCardAndLink = z.object({ sub_title: z.string(), topic_page: z.string(), }) - .omit({ body: true }), + .omit({ body: true, date_prefix: true }), }) export const ChartCardSchemas = z.discriminatedUnion('type', [ diff --git a/src/app/components/cms/Chart/Chart.spec.tsx b/src/app/components/cms/Chart/Chart.spec.tsx index 6102e9c2a..71c0d9f9b 100644 --- a/src/app/components/cms/Chart/Chart.spec.tsx +++ b/src/app/components/cms/Chart/Chart.spec.tsx @@ -64,6 +64,7 @@ test('renders the chart correctly when successful', async () => { ], body: 'COVID-19 chart description.', tag_manager_event_id: '', + date_prefix: 'Up to', title: '', headline_number_columns: [], } @@ -133,6 +134,7 @@ test('renders the chart by geography and geography type when both are present in ], body: 'COVID-19 chart description.', tag_manager_event_id: '', + date_prefix: 'Up to', title: '', headline_number_columns: [], } @@ -191,6 +193,7 @@ test('full width charts should also have an acompanying narrow version for mobil chart: [], body: 'COVID-19 chart description.', tag_manager_event_id: '', + date_prefix: 'Up to', title: '', headline_number_columns: [], } @@ -231,6 +234,7 @@ test('renders a fallback message when the chart requests fail', async () => { title: 'Cases by specimen date', headline_number_columns: [], tag_manager_event_id: '', + date_prefix: 'Up to', } const { getByText, getByRole } = render((await Chart({ data, size: 'narrow' })) as ReactElement) @@ -267,6 +271,7 @@ test('Fallback message with escaped characters', async () => { chart: [], body: 'COVID-19 chart description.', tag_manager_event_id: '', + date_prefix: 'Up to', title: 'Cases by specimen date', headline_number_columns: [], } diff --git a/src/app/components/cms/Download/Download.spec.tsx b/src/app/components/cms/Download/Download.spec.tsx index b19a46410..3ed6e7872 100644 --- a/src/app/components/cms/Download/Download.spec.tsx +++ b/src/app/components/cms/Download/Download.spec.tsx @@ -65,6 +65,7 @@ const props: ComponentProps = { y_axis: 'y-axis', x_axis: 'x-axis', tag_manager_event_id: '', + date_prefix: 'Up to', headline_number_columns: [], title: 'Table Title', body: 'Table Body', diff --git a/src/app/components/cms/Table/Table.spec.tsx b/src/app/components/cms/Table/Table.spec.tsx index 6a5d58fd4..ad6590a30 100644 --- a/src/app/components/cms/Table/Table.spec.tsx +++ b/src/app/components/cms/Table/Table.spec.tsx @@ -117,6 +117,7 @@ const mockData: ComponentProps['data'] = { y_axis: 'y-axis', x_axis: 'x-axis', tag_manager_event_id: '', + date_prefix: 'Up to and including', headline_number_columns: [], title: 'Table Title ABC/XYZ', body: 'Table Body', diff --git a/src/app/components/cms/Timestamp/Timestamp.spec.tsx b/src/app/components/cms/Timestamp/Timestamp.spec.tsx index d2f9b2074..41a1111f9 100644 --- a/src/app/components/cms/Timestamp/Timestamp.spec.tsx +++ b/src/app/components/cms/Timestamp/Timestamp.spec.tsx @@ -25,6 +25,7 @@ test('renders the timestamp correctly when successful', async () => { y_axis: null, chart: [], tag_manager_event_id: '', + date_prefix: 'Up to and including', body: '', title: '', headline_number_columns: [], @@ -53,6 +54,7 @@ test('renders null when the timestamp request fails', async () => { y_axis: null, chart: [], tag_manager_event_id: '', + date_prefix: '', body: '', title: '', headline_number_columns: [], diff --git a/src/app/components/cms/Timestamp/Timestamp.tsx b/src/app/components/cms/Timestamp/Timestamp.tsx index 6ff6be9cd..b35d1c685 100644 --- a/src/app/components/cms/Timestamp/Timestamp.tsx +++ b/src/app/components/cms/Timestamp/Timestamp.tsx @@ -21,7 +21,7 @@ interface TimestampProps { export async function Timestamp({ data, size }: TimestampProps) { const { t } = await getServerTranslation('common') - const { chart, x_axis, y_axis } = data + const { chart, x_axis, y_axis, date_prefix: datePrefix } = data const plots = chart.map((plot) => plot.value) @@ -40,7 +40,7 @@ export async function Timestamp({ data, size }: TimestampProps) { return (

- {t('cms.blocks.timestamp.value', { value: lastUpdated })} + {t('cms.blocks.timestamp.value', { prefix: datePrefix, value: lastUpdated })}

) } diff --git a/src/mock-server/handlers/cms/pages/fixtures/page/covid-19.ts b/src/mock-server/handlers/cms/pages/fixtures/page/covid-19.ts index ff1d021f6..814398f7f 100644 --- a/src/mock-server/handlers/cms/pages/fixtures/page/covid-19.ts +++ b/src/mock-server/handlers/cms/pages/fixtures/page/covid-19.ts @@ -47,6 +47,7 @@ export const covid19PageMock: PageResponse = { title: 'Cases by specimen date', body: 'Number of cases by specimen date. Data for the last 5 days, highlighted in grey, are incomplete.', tag_manager_event_id: 'cases_by_specimen_date', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -87,6 +88,7 @@ export const covid19PageMock: PageResponse = { title: '7-day case rates by specimen date', body: 'Rate of cases per 100,000 people in the rolling 7-day period ending on the dates shown.', tag_manager_event_id: '7day_case_rates_by_specimen_date', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -119,6 +121,7 @@ export const covid19PageMock: PageResponse = { title: 'Case rates by age', body: 'Rates per 100,000 people of the total number of cases since the start of the pandemic, by age.', tag_manager_event_id: 'case_rates_by_age', + date_prefix: 'Up to', x_axis: 'stratum', y_axis: 'metric', chart: [ @@ -168,6 +171,7 @@ export const covid19PageMock: PageResponse = { title: 'Daily deaths with COVID-19 on the death certificate by date of death', body: 'Daily numbers of deaths of people whose death certificate mentioned COVID-19 as one of the causes, and 7-day rolling average. Because of the time it takes for deaths to be registered, there is a lag in reporting of at least 11 days, and data are not shown for the 14 days before the most recent reported date as they are considered incomplete. Data are shown by date of death.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -236,6 +240,7 @@ export const covid19PageMock: PageResponse = { title: 'Bar chart with overlaying line comparing patients \r\nadmitted to hospital with COVID-19', body: 'Daily and total numbers of COVID-19 patients admitted to hospital. The overlaying line shows the 7-day average.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -268,6 +273,7 @@ export const covid19PageMock: PageResponse = { title: 'Patients in hospital', body: 'Daily count of confirmed COVID-19 patients in hospital at 8am. The overlaying line shows the 7-day average.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -308,6 +314,7 @@ export const covid19PageMock: PageResponse = { title: 'Admissions rate by age', body: 'Age breakdown of people admitted to hospital, shown as the rate per 100,000 people, since the start of the pandemic. There are fewer people in the oldest age group so the rates show the relative impact on different age groups.', tag_manager_event_id: 'admissions_rate_by_age', + date_prefix: 'Up to', x_axis: 'stratum', y_axis: 'metric', chart: [ @@ -340,6 +347,7 @@ export const covid19PageMock: PageResponse = { title: 'Patients in mechanical ventilation beds', body: 'Daily count of COVID-19 patients in mechanical ventilation beds, and 7-day rolling average. Data are not updated every day.', tag_manager_event_id: null, + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -389,6 +397,7 @@ export const covid19PageMock: PageResponse = { title: 'Total daily number of PCR tests reported', body: 'The daily number of new polymerase chain reaction (PCR) tests reported. Data is shown by specimen date (the date the sample was collected from the person).', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -421,6 +430,7 @@ export const covid19PageMock: PageResponse = { title: 'Weekly positivity of people receiving a PCR test', body: 'The percentage positivity of people who received a polymerase chain reaction (PCR) and had at least one positive COVID-19 PCR test result in the same 7 days. Data is shown by specimen date (the date the sample was collected). People tested more than once in the period are only counted once in the denominator. People with more than one positive result in the period are only included once in the numerator.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -470,6 +480,7 @@ export const covid19PageMock: PageResponse = { title: 'People aged 50 and over who have received autumn booster vaccinations, by vaccination date', body: 'The number of people aged 50 and over who have received an autumn booster COVID-19 vaccination. Data for the latest 2 days, marked in grey, are incomplete. Data are shown by date of vaccination.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -502,6 +513,7 @@ export const covid19PageMock: PageResponse = { title: 'Autumn booster vaccination uptake (50+), by vaccination date', body: 'The percentage of people aged 50 and over who have received an autumn booster COVID-19 vaccination. The denominator is the number of people aged 50 and over on the National Immunisation Management Service (NIMS) database.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -694,6 +706,7 @@ export const covid19PageMock: PageResponse = { title: 'People aged 75 and over who have received spring booster vaccinations, by vaccination date', body: 'The number of people aged 75 and over who have received a spring booster COVID-19 vaccination. Data for the latest 2 days, marked in grey, are incomplete. Data are shown by date of vaccination.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -726,6 +739,7 @@ export const covid19PageMock: PageResponse = { title: 'Spring booster vaccination uptake (75+), by vaccination date', body: 'The percentage of people aged 75 and over who have received a spring booster COVID-19 vaccination. The denominator is the number of people aged 75 and over on the National Immunisation Management Service (NIMS) database.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ diff --git a/src/mock-server/handlers/cms/pages/fixtures/page/dashboard.ts b/src/mock-server/handlers/cms/pages/fixtures/page/dashboard.ts index 0e072fedf..3abbec60a 100644 --- a/src/mock-server/handlers/cms/pages/fixtures/page/dashboard.ts +++ b/src/mock-server/handlers/cms/pages/fixtures/page/dashboard.ts @@ -179,6 +179,7 @@ export const dashboardMock: PageResponse = { title: 'Cases', body: 'Positive tests reported in England', tag_manager_event_id: 'positive_tests_reported_in_england', + date_prefix: 'Up to', x_axis: '', y_axis: '', chart: [ @@ -232,6 +233,7 @@ export const dashboardMock: PageResponse = { title: 'Deaths', body: 'Deaths with COVID-19 on the death certificate in England', tag_manager_event_id: 'deaths_with_covid-19_on_death_certificate', + date_prefix: 'Up to', x_axis: '', y_axis: '', chart: [ @@ -353,6 +355,7 @@ export const dashboardMock: PageResponse = { title: 'Healthcare', body: 'Weekly hospital admission rates for Influenza', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: '', y_axis: '', chart: [ @@ -396,6 +399,7 @@ export const dashboardMock: PageResponse = { title: 'Testing', body: 'Weekly positivity', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: '', y_axis: '', chart: [ diff --git a/src/mock-server/handlers/cms/pages/fixtures/page/influenza.ts b/src/mock-server/handlers/cms/pages/fixtures/page/influenza.ts index 3e1364814..66c563dd2 100644 --- a/src/mock-server/handlers/cms/pages/fixtures/page/influenza.ts +++ b/src/mock-server/handlers/cms/pages/fixtures/page/influenza.ts @@ -48,6 +48,7 @@ export const influenzaPageMock: PageResponse = { 'Line chart with overlaying line comparing hospital admission rates of patients admitted to hospital with Influenza', body: 'Weekly admissions rates of patients admitted to hospital with Influenza as a weekly time series, shown as the rate per 100,000 people.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -80,6 +81,7 @@ export const influenzaPageMock: PageResponse = { title: 'Line chart comparing Influenza hospital admission rates by age', body: 'Age breakdown of people admitted to hospital, shown as the rate per 100,000 people.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -254,6 +256,7 @@ export const influenzaPageMock: PageResponse = { 'Line chart with overlaying line comparing ICU admission rates of patients admitted to hospital with Influenza', body: 'Weekly admissions rates of patients admitted to ICU with Influenza as a weekly time series, shown as the rate per 100,000 people.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -286,6 +289,7 @@ export const influenzaPageMock: PageResponse = { title: 'Line chart comparing Influenza ICU admission rates by age', body: 'Age breakdown of people admitted to ICU, shown as the rate per 100,000 people.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -468,6 +472,7 @@ export const influenzaPageMock: PageResponse = { title: 'Bar chart with overlaying line comparing positivity for Influenza tests', body: 'Weekly admissions rates of patients admitted to hospital with Influenza as a weekly time series, shown as the rate per 100,000 people.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -500,6 +505,7 @@ export const influenzaPageMock: PageResponse = { title: 'Line chart comparing weekly positivity for Influenza \r\ntests by age', body: 'Weekly time series of positivity for people testing positive for Influenza broken down by age.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ diff --git a/src/mock-server/handlers/cms/pages/fixtures/page/other-respiratory-viruses.ts b/src/mock-server/handlers/cms/pages/fixtures/page/other-respiratory-viruses.ts index 39cbae92a..0a64760dc 100644 --- a/src/mock-server/handlers/cms/pages/fixtures/page/other-respiratory-viruses.ts +++ b/src/mock-server/handlers/cms/pages/fixtures/page/other-respiratory-viruses.ts @@ -48,6 +48,7 @@ export const otherRespiratoryVirusesPageMock: PageResponse = { 'Line chart comparing RSV hospital (ICU or HDU) admission rates of positive cases per 100,000 population reported through SARI Watch, England', body: 'RSV SARI Watch surveillance has run from week 40 to week 20. In the 2022 to 2023 season onwards this was extended to run throughout the year, to allow for surveillance of out-of-season trends.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -88,6 +89,7 @@ export const otherRespiratoryVirusesPageMock: PageResponse = { title: 'Bar chart comparing RSV hospital admissions count by week', body: 'Weekly admissions rates of patients admitted to hospital with RSV as a weekly time series.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -120,6 +122,7 @@ export const otherRespiratoryVirusesPageMock: PageResponse = { title: 'Bar chart comparing weekly RSV ICU/HDU admissions count by week', body: 'Weekly admission rates of patients admitted to ICU/HDU with RSV as a weekly time series.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -169,6 +172,7 @@ export const otherRespiratoryVirusesPageMock: PageResponse = { title: 'Line chart comparing Adenovirus test positivity count by week', body: 'Weekly admissions rates of patients admitted to hospital with Adenovirus as a weekly time series.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -201,6 +205,7 @@ export const otherRespiratoryVirusesPageMock: PageResponse = { title: 'Line chart comparing Adenovirus test positivity count by week broken down by age', body: 'Age breakdown of people testing positive for Adenovirus per 100,000 people.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -317,6 +322,7 @@ export const otherRespiratoryVirusesPageMock: PageResponse = { title: 'Line chart comparing hMPV test positivity count by week', body: 'Weekly admissions rates of patients admitted to hospital with hMPV as a weekly time series.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -349,6 +355,7 @@ export const otherRespiratoryVirusesPageMock: PageResponse = { title: 'Line chart comparing hMPV test positivity count by week broken down by age', body: 'Age breakdown of people testing positive for hMPV per 100,000 people.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -465,6 +472,7 @@ export const otherRespiratoryVirusesPageMock: PageResponse = { title: 'Line chart comparing Parainfluenza test positivity count by week', body: 'Weekly admissions rates of patients admitted to hospital with Parainfluenza as a weekly time series.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -497,6 +505,7 @@ export const otherRespiratoryVirusesPageMock: PageResponse = { title: 'Line chart comparing Parainfluenza test positivity count by week broken down by age', body: 'Age breakdown of people testing positive for Parainfluenza per 100,000 people.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -613,6 +622,7 @@ export const otherRespiratoryVirusesPageMock: PageResponse = { title: 'Line chart comparing Rhinovirus test positivity count by week', body: 'Weekly admissions rates of patients admitted to hospital with Rhinovirus as a weekly time series.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -645,6 +655,7 @@ export const otherRespiratoryVirusesPageMock: PageResponse = { title: 'Line chart comparing Rhinovirus test positivity count by week broken down by age', body: 'Age breakdown of people testing positive for Rhinovirus per 100,000 people.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -761,6 +772,7 @@ export const otherRespiratoryVirusesPageMock: PageResponse = { title: 'Line chart comparing RSV test positivity count by week', body: 'Weekly admissions rates of patients admitted to hospital with RSV as a weekly time series.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ @@ -793,6 +805,7 @@ export const otherRespiratoryVirusesPageMock: PageResponse = { title: 'Line chart comparing RSV test positivity count by week broken down by age', body: 'Age breakdown of people testing positive for Rhinovirus per 100,000 people.', tag_manager_event_id: '', + date_prefix: 'Up to', x_axis: null, y_axis: null, chart: [ From 97663f40d5d03fe6ff03f789e9e3c54dbe75e71b Mon Sep 17 00:00:00 2001 From: Rhys Date: Fri, 24 Jan 2025 17:32:38 +0000 Subject: [PATCH 3/3] CDD-2405: Headline, Percentage and Trend components --- src/api/models/cms/Page/Body.ts | 1 + .../components/cms/Headline/Headline.spec.tsx | 8 +- src/app/components/cms/Headline/Headline.tsx | 5 +- .../cms/Percentage/Percentage.spec.tsx | 10 +- .../components/cms/Percentage/Percentage.tsx | 5 +- src/app/components/cms/Trend/Trend.spec.tsx | 16 +- src/app/components/cms/Trend/Trend.tsx | 5 +- src/app/utils/__mocks__/cms.ts | 6 + src/app/utils/cms.utils.spec.tsx | 3 + src/app/utils/cms.utils.tsx | 21 ++- .../cms/pages/fixtures/page/dashboard.ts | 168 +----------------- 11 files changed, 53 insertions(+), 195 deletions(-) diff --git a/src/api/models/cms/Page/Body.ts b/src/api/models/cms/Page/Body.ts index 6dcb02cc7..3ba8a1350 100644 --- a/src/api/models/cms/Page/Body.ts +++ b/src/api/models/cms/Page/Body.ts @@ -26,6 +26,7 @@ const WithHeadlineNumbersRowCard = z.object({ type: z.literal('column'), value: z.object({ title: z.string(), + date_prefix: z.string(), rows: Blocks, }), }) diff --git a/src/app/components/cms/Headline/Headline.spec.tsx b/src/app/components/cms/Headline/Headline.spec.tsx index 9f55c3336..efbfcf953 100644 --- a/src/app/components/cms/Headline/Headline.spec.tsx +++ b/src/app/components/cms/Headline/Headline.spec.tsx @@ -19,7 +19,7 @@ describe('Data request is successful', () => { } test('renders a heading, date and number', async () => { - const { getByText } = render((await Headline({ data })) as ReactElement) + const { getByText } = render((await Headline({ data, datePrefix: 'Up to' })) as ReactElement) const headingElement = getByText('Test Heading') const dateElement = getByText('Up to 3 Nov 2023') const valueElement = getByText('24,000') @@ -30,8 +30,8 @@ describe('Data request is successful', () => { }) test('hides the date within chart cards', async () => { - const { getByText } = render((await Headline({ data })) as ReactElement) - const dateElement = getByText('Up to 3 Nov 2023') + const { getByText } = render((await Headline({ data, datePrefix: 'Headline prefix' })) as ReactElement) + const dateElement = getByText('Headline prefix 3 Nov 2023') expect(dateElement).toHaveClass('[.ukhsa-chart-card_&]:hidden') }) }) @@ -57,7 +57,7 @@ describe('Data request is unsuccessful', () => { body: 'Test Heading', } - const { container } = render((await Headline({ data })) as ReactElement) + const { container } = render((await Headline({ data, datePrefix: '' })) as ReactElement) expect(container.firstChild).toBeNull() }) diff --git a/src/app/components/cms/Headline/Headline.tsx b/src/app/components/cms/Headline/Headline.tsx index 5c743e01c..53180a690 100644 --- a/src/app/components/cms/Headline/Headline.tsx +++ b/src/app/components/cms/Headline/Headline.tsx @@ -7,9 +7,10 @@ import { getServerTranslation } from '@/app/i18n' interface HeadlineProps { /* Request metadata from the CMS required to fetch from the headlines api */ data: z.infer['value'] + datePrefix: string } -export async function Headline({ data: { body: heading, ...requestParams } }: HeadlineProps) { +export async function Headline({ data: { body: heading, ...requestParams }, datePrefix }: HeadlineProps) { const { t } = await getServerTranslation('common') const headline = await getHeadlines(requestParams) @@ -23,7 +24,7 @@ export async function Headline({ data: { body: heading, ...requestParams } }: He
{t('cms.blocks.headline.heading', { heading })}
- {t('cms.blocks.headline.date', { value: date })} + {t('cms.blocks.timestamp.value', { prefix: datePrefix, value: date })}
{t('cms.blocks.headline.value', { value })}
diff --git a/src/app/components/cms/Percentage/Percentage.spec.tsx b/src/app/components/cms/Percentage/Percentage.spec.tsx index a6ef72b01..c08203448 100644 --- a/src/app/components/cms/Percentage/Percentage.spec.tsx +++ b/src/app/components/cms/Percentage/Percentage.spec.tsx @@ -20,9 +20,9 @@ describe('Data request is successful', () => { test('renders a heading, date and percentage', async () => { getHeadlinesMock.mockResolvedValueOnce({ success: true, data: { value: 50.5, period_end: '2023-11-03' } }) - const { getByText } = render((await Percentage({ data })) as ReactElement) + const { getByText } = render((await Percentage({ data, datePrefix: 'Date prefix test' })) as ReactElement) const headingElement = getByText('Test Heading') - const dateElement = getByText('Up to 3 Nov 2023') + const dateElement = getByText('Date prefix test 3 Nov 2023') const valueElement = getByText('50.5%') expect(headingElement).toBeInTheDocument() @@ -33,7 +33,7 @@ describe('Data request is successful', () => { test('formats the percentage to two decimal places', async () => { getHeadlinesMock.mockResolvedValueOnce({ success: true, data: { value: 55.3846, period_end: '2023-11-03' } }) - const { getByText } = render((await Percentage({ data })) as ReactElement) + const { getByText } = render((await Percentage({ data, datePrefix: '' })) as ReactElement) const headingElement = getByText('Test Heading') const valueElement = getByText('55.38%') @@ -44,7 +44,7 @@ describe('Data request is successful', () => { test('hides the date within chart cards', async () => { getHeadlinesMock.mockResolvedValueOnce({ success: true, data: { value: 50.5, period_end: '2023-11-03' } }) - const { getByText } = render((await Percentage({ data })) as ReactElement) + const { getByText } = render((await Percentage({ data, datePrefix: 'Up to' })) as ReactElement) const dateElement = getByText('Up to 3 Nov 2023') expect(dateElement).toHaveClass('[.ukhsa-chart-card_&]:hidden') }) @@ -71,7 +71,7 @@ describe('Data request is unsuccessful', () => { body: 'Test Heading', } - const { container } = render((await Percentage({ data })) as ReactElement) + const { container } = render((await Percentage({ data, datePrefix: '' })) as ReactElement) expect(container.firstChild).toBeNull() }) diff --git a/src/app/components/cms/Percentage/Percentage.tsx b/src/app/components/cms/Percentage/Percentage.tsx index 9d5738951..d9320eb5a 100644 --- a/src/app/components/cms/Percentage/Percentage.tsx +++ b/src/app/components/cms/Percentage/Percentage.tsx @@ -7,9 +7,10 @@ import { getServerTranslation } from '@/app/i18n' interface PercentageProps { /* Request metadata from the CMS required to fetch from the headlines api */ data: z.infer['value'] + datePrefix: string } -export async function Percentage({ data: { body: heading, ...requestParams } }: PercentageProps) { +export async function Percentage({ data: { body: heading, ...requestParams }, datePrefix }: PercentageProps) { const { t } = await getServerTranslation('common') const headline = await getHeadlines(requestParams) @@ -23,7 +24,7 @@ export async function Percentage({ data: { body: heading, ...requestParams } }:
{t('cms.blocks.percentage.heading', { heading })}
- {t('cms.blocks.headline.date', { value: date })} + {t('cms.blocks.timestamp.value', { prefix: datePrefix, value: date })}
{t('cms.blocks.percentage.value', { value })}
diff --git a/src/app/components/cms/Trend/Trend.spec.tsx b/src/app/components/cms/Trend/Trend.spec.tsx index 37b02d3cd..cdb2ce25c 100644 --- a/src/app/components/cms/Trend/Trend.spec.tsx +++ b/src/app/components/cms/Trend/Trend.spec.tsx @@ -32,7 +32,7 @@ describe('Data request is successful', () => { }, }) - const { getByText } = render((await Trend({ data: mockRequestData })) as ReactElement) + const { getByText } = render((await Trend({ data: mockRequestData, datePrefix: '' })) as ReactElement) expect(getByText('There has been an increase of 592 (3%) compared to the previous 7 days.')).toBeInTheDocument() }) @@ -52,7 +52,7 @@ describe('Data request is successful', () => { }, }) - const { getByText } = render((await Trend({ data: mockRequestData })) as ReactElement) + const { getByText } = render((await Trend({ data: mockRequestData, datePrefix: '' })) as ReactElement) expect(getByText('There has been a decrease of -592 (-3%) compared to the previous 7 days.')).toBeInTheDocument() }) @@ -72,7 +72,7 @@ describe('Data request is successful', () => { }, }) - const { getByText } = render((await Trend({ data: mockRequestData })) as ReactElement) + const { getByText } = render((await Trend({ data: mockRequestData, datePrefix: '' })) as ReactElement) expect(getByText('There has been an increase of 592 (3%) compared to the previous 7 days.')).toBeInTheDocument() }) @@ -92,7 +92,7 @@ describe('Data request is successful', () => { }, }) - const { getByText } = render((await Trend({ data: mockRequestData })) as ReactElement) + const { getByText } = render((await Trend({ data: mockRequestData, datePrefix: '' })) as ReactElement) expect(getByText('There has been an decrease of -592 (-3%) compared to the previous 7 days.')).toBeInTheDocument() }) @@ -112,7 +112,7 @@ describe('Data request is successful', () => { }, }) - const { getByText } = render((await Trend({ data: mockRequestData })) as ReactElement) + const { getByText } = render((await Trend({ data: mockRequestData, datePrefix: '' })) as ReactElement) expect(getByText('There has been no change compared to the previous 7 days.')).toBeInTheDocument() }) @@ -132,7 +132,7 @@ describe('Data request is successful', () => { }, }) - const { getByText } = render((await Trend({ data: mockRequestData })) as ReactElement) + const { getByText } = render((await Trend({ data: mockRequestData, datePrefix: '' })) as ReactElement) expect( getByText('There has been an decrease of -592.12 (3.68%) compared to the previous 7 days.') @@ -153,7 +153,7 @@ describe('Data request is successful', () => { direction: 'down', }, }) - const { getByText } = render((await Trend({ data: mockRequestData })) as ReactElement) + const { getByText } = render((await Trend({ data: mockRequestData, datePrefix: 'Up to' })) as ReactElement) const dateElement = getByText('Up to 3 Nov 2023') expect(dateElement).toHaveClass('[.ukhsa-chart-card_&]:hidden') }) @@ -174,7 +174,7 @@ describe('Data request is unsuccessful', () => { ]), }) - const { container } = render((await Trend({ data: mockRequestData })) as ReactElement) + const { container } = render((await Trend({ data: mockRequestData, datePrefix: '' })) as ReactElement) expect(container.firstChild).toBeNull() }) diff --git a/src/app/components/cms/Trend/Trend.tsx b/src/app/components/cms/Trend/Trend.tsx index 7031886e0..ebfd91294 100644 --- a/src/app/components/cms/Trend/Trend.tsx +++ b/src/app/components/cms/Trend/Trend.tsx @@ -8,9 +8,10 @@ import { getServerTranslation } from '@/app/i18n' interface TrendProps { /* Request metadata from the CMS required to fetch from the headlines api */ data: z.infer['value'] + datePrefix: string } -export async function Trend({ data: { body: heading, ...requestParams } }: TrendProps) { +export async function Trend({ data: { body: heading, ...requestParams }, datePrefix }: TrendProps) { const { t } = await getServerTranslation('common') const trend = await getTrends(requestParams) @@ -28,7 +29,7 @@ export async function Trend({ data: { body: heading, ...requestParams } }: Trend <>
{t('cms.blocks.percentage.heading', { heading: heading || '\u00A0' })}
- {t('cms.blocks.headline.date', { value: date })} + {t('cms.blocks.timestamp.value', { prefix: datePrefix, value: date })}
({ type: 'column', value: { title: 'Cases', + date_prefix: 'Up to', rows: [ { type: 'headline_number', @@ -94,6 +95,7 @@ export const mockHeadlineNumbersRowCard = Mock.of({ type: 'column', value: { title: 'Deaths', + date_prefix: 'Up to', rows: [ { type: 'headline_number', @@ -122,6 +124,7 @@ export const mockHeadlineNumbersRowCard = Mock.of({ type: 'column', value: { title: 'Healthcare', + date_prefix: 'Up to', rows: [ { type: 'headline_number', @@ -150,6 +153,7 @@ export const mockHeadlineNumbersRowCard = Mock.of({ type: 'column', value: { title: 'Vaccines', + date_prefix: 'Up to', rows: [ { type: 'headline_number', @@ -168,6 +172,7 @@ export const mockHeadlineNumbersRowCard = Mock.of({ type: 'column', value: { title: 'Testing', + date_prefix: 'Up to', rows: [ { type: 'percentage_number', @@ -195,6 +200,7 @@ export const mockHeadlineNumbersRowCardWithOneColumn = Mock.of({ type: 'column', value: { title: 'Cases', + date_prefix: 'Up to', rows: [ { type: 'headline_number', diff --git a/src/app/utils/cms.utils.spec.tsx b/src/app/utils/cms.utils.spec.tsx index ff2d5f52a..bf7f4164b 100644 --- a/src/app/utils/cms.utils.spec.tsx +++ b/src/app/utils/cms.utils.spec.tsx @@ -197,6 +197,7 @@ describe('Metrics', () => { body: 'Virus tests positivity', }, id: '36746bcd-1dce-4e5e-81f8-60c8b9994540', + date_prefix: '', }) ) expect(screen.getByText('Mocked percentage number')).toBeInTheDocument() @@ -212,6 +213,7 @@ describe('Metrics', () => { body: 'Autumn booster', }, id: 'ae3344f7-5b23-4977-bea9-2e1ccd84eb50', + date_prefix: '', }) ) expect(screen.getByText('Mocked headline number')).toBeInTheDocument() @@ -228,6 +230,7 @@ describe('Metrics', () => { percentage_metric: 'COVID-19_headline_newcases_7daypercentchange', }, id: '8c42a86e-f675-41d0-a65a-633c20ac98e3', + date_prefix: '', }) ) expect(screen.getByText('Mocked trend number')).toBeInTheDocument() diff --git a/src/app/utils/cms.utils.tsx b/src/app/utils/cms.utils.tsx index 198f618e2..5963507d0 100644 --- a/src/app/utils/cms.utils.tsx +++ b/src/app/utils/cms.utils.tsx @@ -84,7 +84,9 @@ export const renderCard = ( {value.columns.map((column) => (

{column.value.title}

-
{column.value.rows.map(renderBlock)}
+
+ {column.value.rows.map((row) => renderBlock({ ...row, date_prefix: column.value.date_prefix }))} +
))}
@@ -149,7 +151,9 @@ export const renderCard = ( <>
- {column.value.headline_number_columns.map(renderBlock)} + {column.value.headline_number_columns.map((headline_number_columns) => + renderBlock({ ...headline_number_columns, date_prefix: column.value.date_prefix }) + )}
@@ -243,11 +247,16 @@ export const renderCard = ( ) -export const renderBlock = ({ id, type, value }: z.infer[number]) => ( +export const renderBlock = ({ + id, + type, + value, + date_prefix, +}: z.infer[number] & { date_prefix: string }) => (
- {type === 'percentage_number' && } - {type === 'headline_number' && } - {type === 'trend_number' && } + {type === 'percentage_number' && } + {type === 'headline_number' && } + {type === 'trend_number' && }
) diff --git a/src/mock-server/handlers/cms/pages/fixtures/page/dashboard.ts b/src/mock-server/handlers/cms/pages/fixtures/page/dashboard.ts index 3abbec60a..fb3463817 100644 --- a/src/mock-server/handlers/cms/pages/fixtures/page/dashboard.ts +++ b/src/mock-server/handlers/cms/pages/fixtures/page/dashboard.ts @@ -44,128 +44,7 @@ export const dashboardMock: PageResponse = { { type: 'headline_numbers_row_card', value: { - columns: [ - { - type: 'column', - value: { - title: 'Cases', - rows: [ - { - type: 'headline_number', - value: { - topic: 'COVID-19', - metric: 'COVID-19_headline_newcases_7daytotals', - body: 'Weekly', - }, - id: 'eff08341-7bfa-4a3b-b013-527e7b954ce8', - }, - { - type: 'trend_number', - value: { - topic: 'COVID-19', - metric: 'COVID-19_headline_newcases_7daychange', - body: 'Last 7 days', - percentage_metric: 'COVID-19_headline_newcases_7daypercentchange', - }, - id: 'a57a4ad5-6b52-45a6-acfd-2fe208cb5617', - }, - ], - }, - id: 'ff081d2a-e235-4bc2-9b09-220f8fe20494', - }, - { - type: 'column', - value: { - title: 'Deaths', - rows: [ - { - type: 'headline_number', - value: { - topic: 'COVID-19', - metric: 'COVID-19_headline_ONSdeaths_7daytotals', - body: 'Weekly', - }, - id: '2e403485-030c-4122-86be-5827a095f30d', - }, - { - type: 'trend_number', - value: { - topic: 'COVID-19', - metric: 'COVID-19_headline_ONSdeaths_7daychange', - body: 'Last 7 days', - percentage_metric: 'COVID-19_headline_ONSdeaths_7daypercentchange', - }, - id: 'ea8603ca-7b4d-4ef5-a8b1-f27a565938b5', - }, - ], - }, - id: '530cf367-092c-40d1-9129-c2274c7836b9', - }, - { - type: 'column', - value: { - title: 'Healthcare', - rows: [ - { - type: 'headline_number', - value: { - topic: 'COVID-19', - metric: 'COVID-19_headline_7DayAdmissions', - body: 'Patients admitted', - }, - id: '2f49a215-02e7-4ded-94b1-1a0c2933708b', - }, - { - type: 'trend_number', - value: { - topic: 'COVID-19', - metric: 'COVID-19_headline_7DayAdmisionsChange', - body: 'Last 7 days', - percentage_metric: 'COVID-19_headline_7DayAdmissionsPercentChange', - }, - id: '6c09d01e-82c5-425f-aa07-1bdd22d1eaa8', - }, - ], - }, - id: 'fad2e89a-8a65-44a8-b962-9df59169c0af', - }, - { - type: 'column', - value: { - title: 'Vaccines', - rows: [ - { - type: 'headline_number', - value: { - topic: 'COVID-19', - metric: 'COVID-19_headline_totalvaccines_spring23', - body: 'Autumn booster', - }, - id: 'ae3344f7-5b23-4977-bea9-2e1ccd84eb50', - }, - ], - }, - id: '93b6367b-fbb3-47e8-96db-f724d947fa00', - }, - { - type: 'column', - value: { - title: 'Testing', - rows: [ - { - type: 'percentage_number', - value: { - topic: 'COVID-19', - metric: 'COVID-19_headline_positivity_latest', - body: 'Virus tests positivity', - }, - id: '36746bcd-1dce-4e5e-81f8-60c8b9994540', - }, - ], - }, - id: '1e3bf214-88e4-4cf4-9b78-3ad7eabb2eaa', - }, - ], + columns: [], }, id: 'e285caf4-ae79-4c76-bcb7-426d6e66cb8a', }, @@ -301,50 +180,7 @@ export const dashboardMock: PageResponse = { }, id: '53fcc358-f10d-411d-9bd0-9acb3c4d3aae', }, - { - type: 'headline_numbers_row_card', - value: { - columns: [ - { - type: 'column', - value: { - title: 'Healthcare', - rows: [ - { - type: 'headline_number', - value: { - topic: 'Influenza', - metric: 'influenza_headline_ICUHDUadmissionrateLatest', - body: 'Hospital admission rate (per 100,000)', - }, - id: '0520e9d6-794f-4616-b217-f5ec884a86d8', - }, - ], - }, - id: '0da002a7-d985-417c-b75c-9a4c8a77fa8e', - }, - { - type: 'column', - value: { - title: 'Testing', - rows: [ - { - type: 'percentage_number', - value: { - topic: 'Influenza', - metric: 'influenza_headline_positivityLatest', - body: 'Virus tests positivity', - }, - id: '36ec8822-56e2-4513-ac8f-969e84f0d5e8', - }, - ], - }, - id: 'e57ed33f-658a-40be-bfdb-6fa12ee62512', - }, - ], - }, - id: '06e1f087-dc2c-42ea-873f-0b1fb1f1b12e', - }, + { type: 'chart_row_card', value: {