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

Feature/cdd-2405: Date prefix #577

Merged
merged 7 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
}
},
"timestamp": {
"value": "Up to and including {{value, dateShort}}"
"value": "{{prefix}} {{value, dateShortest}}"
},
"table": {
"toggle": "View data in a tabular format",
Expand Down
61 changes: 26 additions & 35 deletions src/api/models/cms/Page/Body.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,69 +19,60 @@ 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(),
type: z.literal('column'),
value: z.object({
title: z.string(),
date_prefix: z.string(),
rows: Blocks,
}),
})
),
})

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(),
date_prefix: z.string(),
})

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,
}),
})

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, date_prefix: true }),
})

export const ChartSchemas = z.discriminatedUnion('type', [
export const ChartCardSchemas = z.discriminatedUnion('type', [
WithChartHeadlineAndTrendCard,
WithChartCard,
WithSimplifiedChartCardAndLink,
Expand Down
5 changes: 5 additions & 0 deletions src/app/components/cms/Chart/Chart.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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: [],
}
Expand Down Expand Up @@ -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: [],
}
Expand Down Expand Up @@ -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: [],
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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: [],
}
Expand Down
4 changes: 2 additions & 2 deletions src/app/components/cms/Chart/Chart.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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<typeof ChartSchemas>['value']
data: z.infer<typeof ChartCardSchemas>['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'
Expand Down
1 change: 1 addition & 0 deletions src/app/components/cms/Download/Download.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const props: ComponentProps<typeof Download> = {
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',
Expand Down
8 changes: 4 additions & 4 deletions src/app/components/cms/Headline/Headline.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand All @@ -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')
})
})
Expand All @@ -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()
})
Expand Down
5 changes: 3 additions & 2 deletions src/app/components/cms/Headline/Headline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<typeof HeadlineNumber>['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)
Expand All @@ -23,7 +24,7 @@ export async function Headline({ data: { body: heading, ...requestParams } }: He
<div>
<div>{t('cms.blocks.headline.heading', { heading })}</div>
<div className="govuk-body-xs govuk-!-margin-bottom-1 text-dark-grey [.ukhsa-chart-card_&]:hidden">
{t('cms.blocks.headline.date', { value: date })}
{t('cms.blocks.timestamp.value', { prefix: datePrefix, value: date })}
</div>
<div className="govuk-body-l govuk-!-margin-bottom-0">{t('cms.blocks.headline.value', { value })}</div>
</div>
Expand Down
10 changes: 5 additions & 5 deletions src/app/components/cms/Percentage/Percentage.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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%')

Expand All @@ -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')
})
Expand All @@ -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()
})
Expand Down
5 changes: 3 additions & 2 deletions src/app/components/cms/Percentage/Percentage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<typeof HeadlineNumber>['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)
Expand All @@ -23,7 +24,7 @@ export async function Percentage({ data: { body: heading, ...requestParams } }:
<div>
<div>{t('cms.blocks.percentage.heading', { heading })}</div>
<div className="govuk-body-xs govuk-!-margin-bottom-1 text-dark-grey [.ukhsa-chart-card_&]:hidden">
{t('cms.blocks.headline.date', { value: date })}
{t('cms.blocks.timestamp.value', { prefix: datePrefix, value: date })}
</div>
<div className="govuk-body-l govuk-!-margin-bottom-0">{t('cms.blocks.percentage.value', { value })}</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/app/components/cms/Table/Table.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ const mockData: ComponentProps<typeof Table>['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',
Expand Down
2 changes: 2 additions & 0 deletions src/app/components/cms/Timestamp/Timestamp.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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: [],
Expand Down Expand Up @@ -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: [],
Expand Down
4 changes: 2 additions & 2 deletions src/app/components/cms/Timestamp/Timestamp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -40,7 +40,7 @@ export async function Timestamp({ data, size }: TimestampProps) {

return (
<h4 className="govuk-body-s govuk-!-margin-bottom-0 text-dark-grey">
{t('cms.blocks.timestamp.value', { value: lastUpdated })}
{t('cms.blocks.timestamp.value', { prefix: datePrefix, value: lastUpdated })}
</h4>
)
}
Expand Down
16 changes: 8 additions & 8 deletions src/app/components/cms/Trend/Trend.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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()
})
Expand All @@ -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()
})
Expand All @@ -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()
})
Expand All @@ -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()
})
Expand All @@ -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()
})
Expand All @@ -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.')
Expand All @@ -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')
})
Expand All @@ -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()
})
Expand Down
Loading
Loading