Skip to content
This repository has been archived by the owner on Nov 4, 2024. It is now read-only.

feature/COR-1953_non-archived-graphs-adjustments #5005

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
10 changes: 5 additions & 5 deletions packages/app/src/components/chart-tile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,28 @@ import { Heading } from './typography';

interface ChartTileProps {
children: ReactNode;
title: string;
description?: string;
disableFullscreen?: boolean;
id?: string;
metadata?: MetadataProps;
onSelectTimeframe?: (timeframe: TimeframeOption) => void;
timeframeInitialValue?: TimeframeOption;
timeframeOptions?: TimeframeOption[];
title: string;
toggle?: ChartTileToggleProps;
onSelectTimeframe?: (timeframe: TimeframeOption) => void;
}

export const ChartTile = ({
children,
title,
description,
disableFullscreen,
id,
metadata,
onSelectTimeframe,
timeframeInitialValue,
toggle,
timeframeOptions,
onSelectTimeframe,
title,
toggle,
}: ChartTileProps) => {
const [timeframe, setTimeframe] = useState<TimeframeOption>(timeframeInitialValue || TimeframeOption.ALL);

Expand Down
55 changes: 23 additions & 32 deletions packages/app/src/components/metadata.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { MarginBottomProps } from 'styled-system';
import { ExternalLink } from '~/components/external-link';
import { useIntl } from '~/intl';
import { space } from '~/style/theme';
import { replaceVariablesInText } from '~/utils/replace-variables-in-text';
import { Box } from './base';
import { Calendar, Clock, Database, External as ExternalLinkIcon } from '@corona-dashboard/icons';
import { colors } from '@corona-dashboard/common';
import { ExternalLink } from '~/components/external-link';
import { InlineText, Text } from './typography';
import { MarginBottomProps } from 'styled-system';
import { Markdown } from '~/components/markdown';
import { Calendar, Clock, Database, External as ExternalLinkIcon } from '@corona-dashboard/icons';
import { replaceVariablesInText } from '~/utils/replace-variables-in-text';
import { space } from '~/style/theme';
import { useIntl } from '~/intl';
import css from '@styled-system/css';
import React from 'react';
import styled from 'styled-components';
import { colors } from '@corona-dashboard/common';
import css from '@styled-system/css';

type source = {
text: string;
Expand Down Expand Up @@ -40,18 +40,18 @@ export interface MetadataProps extends MarginBottomProps {
}

export function Metadata({
dataSources,
date,
source,
obtainedAt,
isTileFooter,
dateOfInsertion,
datePeriod,
datumsText,
marginBottom,
dataSources,
intervalCount,
disclaimer,
datePeriod,
dateOfInsertion,
intervalCount,
isArchivedGraph = false,
isTileFooter,
marginBottom,
obtainedAt,
source,
}: MetadataProps) {
const { commonTexts, formatDateFromSeconds } = useIntl();

Expand Down Expand Up @@ -117,26 +117,17 @@ export function Metadata({
</Box>
)}

{dateOfInsertion && !isArchivedGraph && (
<Box display="flex" alignItems="flex-start" color="gray7" paddingY={space[2]}>
{dateOfInsertion && (
<Box display="flex" alignItems="flex-start" color="gray7" marginY={space[1]}>
<Icon>
<Clock aria-hidden color={colors.gray7} />
</Icon>
<Text variant="label1">
{replaceVariablesInText(commonTexts.common.metadata.last_insertion_date, { dateOfInsertion: formatDateFromSeconds(dateOfInsertion, 'weekday-long') })}
</Text>
</Box>
)}

{dateOfInsertion && isArchivedGraph && (
<Box display="flex" alignItems="flex-start" color="gray7">
<Icon>
<Clock aria-hidden color={colors.gray7} />
</Icon>
<Text variant="label1">
{replaceVariablesInText(commonTexts.common.metadata.last_insertion_date_archived, {
dateOfInsertion: formatDateFromSeconds(dateOfInsertion, 'weekday-long'),
})}
{isArchivedGraph
? replaceVariablesInText(commonTexts.common.metadata.last_insertion_date_archived, {
dateOfInsertion: formatDateFromSeconds(dateOfInsertion, 'weekday-long'),
})
: replaceVariablesInText(commonTexts.common.metadata.last_insertion_date, { dateOfInsertion: formatDateFromSeconds(dateOfInsertion, 'weekday-long') })}
</Text>
</Box>
)}
Expand Down
60 changes: 44 additions & 16 deletions packages/app/src/components/time-series-chart/time-series-chart.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TimeframeOption, TimestampedValue } from '@corona-dashboard/common';
import { TimeframeOption, TimestampedValue, isDateSeries, isDateSpanSeries } from '@corona-dashboard/common';
import css from '@styled-system/css';
import { TickFormatter } from '@visx/axis';
import { useTooltip } from '@visx/tooltip';
Expand Down Expand Up @@ -53,6 +53,7 @@ import {
useValuesInTimeframe,
useValueWidth,
} from './logic';
import { DateRange } from '../metadata';
export type { SeriesConfig } from './logic';

/**
Expand Down Expand Up @@ -129,6 +130,19 @@ export type TimeSeriesChartProps<T extends TimestampedValue, C extends SeriesCon
forceLegend?: boolean;
onSeriesClick?: (seriesConfig: C[number], value: T) => void;

/**
* These handlers are responsible for managing the parent to child to parent relation.
* The dashboard is not currently adapted to having the CurrentDateContext available
* at page level. In order to connect the state values to the context, we either extract
* all the timeseries instances into separate components or pass the handlers as functions
* from the parent component. onHandleTimeIntervalChange is responsible for handling the
* metadata interval for the X axis. onHandleDateOfInsertion is responsible for handling
* the last insertion date metadata for the interval.
* @param value: DateRange | number
* @returns
*/
onHandleTimeIntervalChange?: (value: DateRange) => void;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very solid work on figuring this out!

/**
* By default markers for all series are displayed on hover, also the tooltip
* will display all series of the selected X-value. The `markNearestPointOnly`
Expand All @@ -151,27 +165,28 @@ export type TimeSeriesChartProps<T extends TimestampedValue, C extends SeriesCon

export function TimeSeriesChart<T extends TimestampedValue, C extends SeriesConfig<T>>({
accessibility,
values: allValues,
dataOptions,
disableLegend,
displayTooltipValueOnly,
endDate,
seriesConfig,
forceLegend = false,
formatTickValue: formatYTickValue,
formatTooltip,
initialWidth = 840,
isYAxisCollapsed: defaultIsYAxisCollapsed,
markNearestPointOnly,
minHeight = 250,
timeframe = TimeframeOption.ALL,
formatTooltip,
dataOptions,
showWeekNumbers,
numGridLines = 4,
tickValues: yTickValues,
xTickNumber,
formatTickValue: formatYTickValue,
onHandleTimeIntervalChange,
onSeriesClick,
paddingLeft,
seriesConfig,
showWeekNumbers,
tickValues: yTickValues,
timeframe = TimeframeOption.ALL,
tooltipTitle,
disableLegend,
forceLegend = false,
onSeriesClick,
markNearestPointOnly,
displayTooltipValueOnly,
isYAxisCollapsed: defaultIsYAxisCollapsed,
values: allValues,
xTickNumber,
}: TimeSeriesChartProps<T, C>) {
const { commonTexts } = useIntl();

Expand All @@ -193,6 +208,19 @@ export function TimeSeriesChart<T extends TimestampedValue, C extends SeriesConf

const values = useValuesInTimeframe(allValues, timeframe, endDate);

useEffect(() => {
if (onHandleTimeIntervalChange) {
if (isDateSpanSeries(values)) {
onHandleTimeIntervalChange({
start: values[0] ? values[0].date_start_unix : 0,
end: values[values.length - 1] ? values[values.length - 1].date_end_unix : 0,
});
} else if (isDateSeries(values)) {
onHandleTimeIntervalChange({ start: values[0] ? values[0].date_unix : 0, end: values[values.length - 1] ? values[values.length - 1].date_unix : 0 });
}
}
}, [values, timeframe, onHandleTimeIntervalChange]);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onHandleTimeIntervalChange was added right before the PR. If something is not working correctly, try removing this from dependencies

const cutValuesConfig = useMemo(() => extractCutValuesConfig(timespanAnnotations), [timespanAnnotations]);

const seriesList = useSeriesList(values, seriesConfig, cutValuesConfig, dataOptions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { AccessibilityDefinition } from '~/utils/use-accessibility-annotations';
import { useBreakpoints } from '~/utils/use-breakpoints';
import { useList } from '~/utils/use-list';
import { BASE_SERIES_CONFIG } from './series-config';
import { DateRange } from '~/components/metadata';

interface InfectionRadarSymptomsPerAgeGroup {
/**
Expand All @@ -25,9 +26,10 @@ interface InfectionRadarSymptomsPerAgeGroup {
timeframe: TimeframeOption;
timelineEvents?: TimelineEventConfig[];
text: SiteText['pages']['infectie_radar_page']['nl'];
onHandleTimeIntervalChange?: (value: DateRange) => void;
}

export function InfectionRadarSymptomsPerAgeGroup({ values, timeframe, accessibility, timelineEvents, text }: InfectionRadarSymptomsPerAgeGroup) {
export function InfectionRadarSymptomsPerAgeGroup({ values, timeframe, accessibility, timelineEvents, text, onHandleTimeIntervalChange }: InfectionRadarSymptomsPerAgeGroup) {
const { commonTexts } = useIntl();
const { list, toggle, clear } = useList<string>();
const breakpoints = useBreakpoints(true);
Expand Down Expand Up @@ -89,6 +91,7 @@ export function InfectionRadarSymptomsPerAgeGroup({ values, timeframe, accessibi
valueAnnotation: text.infection_radar_infected_per_age_group.value_annotation,
timelineEvents,
}}
onHandleTimeIntervalChange={onHandleTimeIntervalChange}
/>
</ErrorBoundary>
);
Expand Down
41 changes: 29 additions & 12 deletions packages/app/src/domain/sewer/sewer-chart/sewer-chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@ import { AccessibilityDefinition } from '~/utils/use-accessibility-annotations';
import { Box } from '~/components/base';
import { ChartTile } from '~/components/chart-tile';
import { ChartTimeControls } from '~/components/chart-time-controls';
import { colors, NlSewer, SewerPerInstallationData, TimeframeOption, TimeframeOptionsList } from '@corona-dashboard/common';
import { colors, isDateSpanSeries, NlSewer, SewerPerInstallationData, TimeframeOption, TimeframeOptionsList } from '@corona-dashboard/common';
import { DateRange } from '~/components/metadata';
import { isPresent } from 'ts-is-present';
import { mediaQueries, space } from '~/style/theme';
import { mergeData, useSewerStationSelectPropsSimplified } from './logic';
import { RichContentSelect } from '~/components/rich-content-select';
import styled from 'styled-components';
import { Text } from '~/components/typography';
import { TimelineEventConfig } from '~/components/time-series-chart/components/timeline';
import { TimeSeriesChart } from '~/components/time-series-chart';
import { useRouter } from 'next/router';
import { useEffect, useMemo, useState } from 'react';
import { useScopedWarning } from '~/utils/use-scoped-warning';
import { useIntl } from '~/intl';
import { useRouter } from 'next/router';
import { useScopedWarning } from '~/utils/use-scoped-warning';
import { useValuesInTimeframe } from '~/components/time-series-chart/logic';
import { Warning } from '@corona-dashboard/icons';
import { WarningTile } from '~/components/warning-tile';
import styled from 'styled-components';

interface SewerChartProps {
/**
Expand Down Expand Up @@ -82,23 +84,36 @@ export const SewerChart = ({ accessibility, dataAverages, dataPerInstallation, t
} as SewerPerInstallationData),
text.rwziSelectDropdown?.select_none_label || ''
);
const { commonTexts } = useIntl();

const [timeframe, setTimeframe] = useState(TimeframeOption.ALL);
const [sewerTimeframe, setSewerTimeframe] = useState<TimeframeOption>(TimeframeOption.ALL);

const router = useRouter();
const values = useValuesInTimeframe(dataAverages.values, timeframe);

const [metadataTimeInterval, setMetadataTimeInterval] = useState<DateRange>({ start: 0, end: 0 });
const metadataLastInsertion = values[values.length - 1] ? values[values.length - 1].date_of_insertion_unix : 1; // Weird behavior if set to 0

const scopedGmName = commonTexts.gemeente_index.municipality_warning;
const scopedWarning = useScopedWarning(vrNameOrGmName || '', warning || '');

useEffect(() => {
const routeChangeHandler = () => onChange(undefined);
router.events.on('routeChangeStart', routeChangeHandler);
return () => router.events.off('routeChangeStart', routeChangeHandler);
}, [onChange, router.events]);

const [sewerTimeframe, setSewerTimeframe] = useState<TimeframeOption>(TimeframeOption.ALL);

const { commonTexts } = useIntl();
const scopedGmName = commonTexts.gemeente_index.municipality_warning;

const scopedWarning = useScopedWarning(vrNameOrGmName || '', warning || '');

const [timeframe, setTimeframe] = useState(TimeframeOption.ALL);
useEffect(() => {
if (isDateSpanSeries(values)) {
setMetadataTimeInterval({
start: values[0] ? values[0].date_start_unix : 0,
end: values[values.length - 1] ? values[values.length - 1].date_end_unix : 0,
});
} else {
setMetadataTimeInterval({ start: values[0] ? values[0].date_unix : 0, end: values[values.length - 1] ? values[values.length - 1].date_unix : 0 });
}
}, [timeframe, values, setMetadataTimeInterval]);

useEffect(() => {
setSewerTimeframe(timeframe);
Expand Down Expand Up @@ -142,6 +157,8 @@ export const SewerChart = ({ accessibility, dataAverages, dataPerInstallation, t
title={text.title}
metadata={{
source: text.source,
datePeriod: metadataTimeInterval,
dateOfInsertion: metadataLastInsertion,
}}
description={text.description}
>
Expand Down
17 changes: 17 additions & 0 deletions packages/app/src/pages/landelijk/infectieradar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { TimeSeriesChart } from '~/components/time-series-chart';
import { useDynamicLokalizeTexts } from '~/utils/cms/use-dynamic-lokalize-texts';
import { useIntl } from '~/intl';
import { useState } from 'react';
import { DateRange } from '~/components/metadata';

const pageMetrics = ['self_test_overall', 'infection_radar_symptoms_per_age_group'];

Expand Down Expand Up @@ -67,8 +68,10 @@ const InfectionRadar = (props: StaticProps<typeof getStaticProps>) => {
const reverseRouter = useReverseRouter();

const [confirmedCasesSelfTestedTimeframe, setConfirmedCasesSelfTestedTimeframe] = useState<TimeframeOption>(TimeframeOption.SIX_MONTHS);
const [confirmedCasesSelfTestedTimeInterval, setConfirmedCasesSelfTestedTimeInterval] = useState<DateRange>({ start: 0, end: 0 });

const [confirmedCasesCovidSymptomsPerAgeTimeFrame, setConfirmedCasesCovidSymptomsPerAgeTimeFrame] = useState<TimeframeOption>(TimeframeOption.THREE_MONTHS);
const [confirmedCasesCovidSymptomsPerAgeTimeInterval, setConfirmedCasesCovidSymptomsPerAgeTimeInterval] = useState<DateRange>({ start: 0, end: 0 });

const { commonTexts } = useIntl();

Expand All @@ -82,6 +85,14 @@ const InfectionRadar = (props: StaticProps<typeof getStaticProps>) => {
description: textNl.metadata.description,
};

const handleSetConfirmedCasesSelfTestedTimeInterval = (value: DateRange) => {
setConfirmedCasesSelfTestedTimeInterval(value);
};

const handleSetConfirmedCasesCovidSymptomsPerAgeTimeInterval = (value: DateRange) => {
setConfirmedCasesCovidSymptomsPerAgeTimeInterval(value);
};

const lastInsertionDateOfPage = getLastInsertionDateOfPage(data, pageMetrics);

return (
Expand Down Expand Up @@ -140,6 +151,8 @@ const InfectionRadar = (props: StaticProps<typeof getStaticProps>) => {
description={textNl.chart_self_tests.description}
metadata={{
source: textNl.sources.self_test,
datePeriod: confirmedCasesSelfTestedTimeInterval,
dateOfInsertion: data.self_test_overall.last_value.date_of_insertion_unix,
}}
timeframeOptions={TimeframeOptionsList}
timeframeInitialValue={confirmedCasesSelfTestedTimeframe}
Expand All @@ -164,6 +177,7 @@ const InfectionRadar = (props: StaticProps<typeof getStaticProps>) => {
timelineEvents: getTimelineEvents(content.elements.timeSeries, 'self_test_overall'),
}}
forceLegend
onHandleTimeIntervalChange={handleSetConfirmedCasesSelfTestedTimeInterval}
/>
</ChartTile>

Expand All @@ -174,6 +188,8 @@ const InfectionRadar = (props: StaticProps<typeof getStaticProps>) => {
timeframeInitialValue={confirmedCasesCovidSymptomsPerAgeTimeFrame}
metadata={{
source: textNl.chart_infection_radar_age_groups.source.rivm,
datePeriod: confirmedCasesCovidSymptomsPerAgeTimeInterval,
dateOfInsertion: data.infectionradar_symptoms_trend_per_age_group_weekly.last_value.date_of_insertion_unix,
}}
onSelectTimeframe={setConfirmedCasesCovidSymptomsPerAgeTimeFrame}
>
Expand All @@ -185,6 +201,7 @@ const InfectionRadar = (props: StaticProps<typeof getStaticProps>) => {
timeframe={confirmedCasesCovidSymptomsPerAgeTimeFrame}
timelineEvents={getTimelineEvents(content.elements.timeSeries, 'infectionradar_symptoms_trend_per_age_group_weekly')}
text={textNl}
onHandleTimeIntervalChange={handleSetConfirmedCasesCovidSymptomsPerAgeTimeInterval}
/>
</ChartTile>

Expand Down
Loading
Loading