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

Commit

Permalink
feature/COR-1857-refactor-order-of-variants (#4967)
Browse files Browse the repository at this point in the history
* feat(COR-1857): Reversed variants in graph and legend items

* feat(COR-1857): Add logic for tooltip

* feat(COR-1857): Removed newline

* feat(COR-1857): Reorder tooltip

* feat(COR-1857): Make mechanism for putting other variants at end more elegant

* feat(COR-1857): Remove todo and skeleton code

* feat(COR-1857): Add ordering based on rank in tooltip
  • Loading branch information
ben-van-eekelen authored Jan 18, 2024
1 parent 4770e6c commit 608e7f0
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ export interface StackedBarSeriesDefinition<T extends TimestampedValue> extends
shortLabel?: string;
color: string;
fillOpacity?: number;
order: number;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function getVariantBarChartData(variants: NlVariants) {
return EMPTY_VALUES;
}

const sortedVariants = variants.values.sort((a, b) => b.last_value.order - a.last_value.order);
const sortedVariants = variants.values.sort((a, b) => a.last_value.order - b.last_value.order);

const firstVariantInList = sortedVariants.shift();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { NlVariants } from '@corona-dashboard/common';
import { OrderMatch } from '~/domain/variants/data-selection/types';
import { isDefined } from 'ts-is-present';

export const getVariantOrders = (variants: NlVariants): OrderMatch[] => {
if (!isDefined(variants) || !isDefined(variants.values)) {
return [];
}

const order = variants.values
.sort((a, b) => a.last_value.order - b.last_value.order)
.map((variant) => {
const variantOrder = variant.last_value.order;
return {
variant: variant.variant_code,
order: variantOrder,
};
});

return order;
};
1 change: 1 addition & 0 deletions packages/app/src/domain/variants/data-selection/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './get-variant-bar-chart-data';
export * from './get-archived-variant-chart-data';
export * from './get-variant-order-colors';
export * from './get-variant-table-data';
export * from './get-variant-orders';
5 changes: 5 additions & 0 deletions packages/app/src/domain/variants/data-selection/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ export type ColorMatch = {
color: string;
};

export type OrderMatch = {
variant: VariantCode;
order: number;
};

export type VariantTableData = ReturnType<typeof getVariantTableData>;

export type VariantChartValue = {
Expand Down
27 changes: 21 additions & 6 deletions packages/app/src/domain/variants/logic/reorder-and-filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,33 @@ const hasMetricProperty = (config: any): config is { metricProperty: string } =>
* @param selectionOptions - Currently selected variants
*/
export const reorderAndFilter = <T, P>(context: TooltipData<VariantChartValue & T>, selectionOptions: P[]) => {
const hasSelectedMetrics = context.config.length !== selectionOptions.length; // Check whether the user has selected any variants from the interactive legend.
const filterSelectionActive = context.config.length !== selectionOptions.length; // Check whether the user has selected any variants from the interactive legend.

/* Filter out any variants that have an occcurrence value of 0 */
const filteredValues = Object.fromEntries(
// If the user has no filter selected -> Filter out any variants that have an occurrence value of 0
const valuesFromContext = Object.fromEntries(
Object.entries(context.value).filter(([key, value]) => (key.includes('occurrence') ? value !== 0 && isPresent(value) && !isNaN(Number(value)) : value))
) as VariantChartValue;

/* Rebuild tooltip data context with filtered values */
// If the user has no filter selected -> Filter out configs that do not contain a 'metricProperty' key OR have an occurrence value of 0
const filteredConfigs = context.config
.filter((value) => {
return !hasMetricProperty(value) || valuesFromContext[value.metricProperty] || filterSelectionActive;
})
.filter(isDefined);

// Sort variants by occurrence, always put 'other variants' at the end
const sortedConfigs = filteredConfigs.sort((a: any, b: any) => {
if (a.metricProperty.includes('other_variants')) return 1;
if (b.metricProperty.includes('other_variants')) return -1;
if (context.value[a.metricProperty] === context.value[b.metricProperty]) return b.order - a.order;
return context.value[b.metricProperty] - context.value[a.metricProperty];
});

// Generate filtered tooltip context
const reorderContext = {
...context,
config: [...context.config.filter((value) => !hasMetricProperty(value) || filteredValues[value.metricProperty] || hasSelectedMetrics)].filter(isDefined),
value: !hasSelectedMetrics ? filteredValues : context.value,
config: sortedConfigs,
value: !filterSelectionActive ? valuesFromContext : context.value,
};

return reorderContext as TooltipData<VariantChartValue & T>;
Expand Down
8 changes: 6 additions & 2 deletions packages/app/src/domain/variants/logic/use-bar-config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColorMatch, VariantChartValue, VariantDynamicLabels, VariantsOverTimeGraphText } from '~/domain/variants/data-selection/types';
import { ColorMatch, OrderMatch, VariantChartValue, VariantDynamicLabels, VariantsOverTimeGraphText } from '~/domain/variants/data-selection/types';
import { useMemo } from 'react';
import { getValuesInTimeframe, TimeframeOption } from '@corona-dashboard/common';
import { isPresent } from 'ts-is-present';
Expand All @@ -25,6 +25,7 @@ export const useBarConfig = (
variantLabels: VariantDynamicLabels,
tooltipLabels: VariantsOverTimeGraphText,
colors: ColorMatch[],
orders: OrderMatch[],
timeframe: TimeframeOption,
today: Date
) => {
Expand Down Expand Up @@ -54,6 +55,8 @@ export const useBarConfig = (

const color = colors.find((variantColors) => variantColors.variant === variantCodeName)?.color;

const order = orders.find((varianOrders) => varianOrders.variant === variantCodeName)?.order;

if (variantDynamicLabel) {
const barChartConfigEntry = {
type: 'stacked-bar',
Expand All @@ -62,12 +65,13 @@ export const useBarConfig = (
label: variantDynamicLabel,
fillOpacity: 1,
shape: 'gapped-area',
order: order,
};

barChartConfig.push(barChartConfigEntry as StackedBarSeriesDefinition<VariantChartValue>);
}
});

return barChartConfig;
}, [values, tooltipLabels.tooltip_labels.other_percentage, variantLabels, colors, timeframe, today]);
}, [values, tooltipLabels.tooltip_labels.other_percentage, variantLabels, colors, orders, timeframe, today]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ChartTile, MetadataProps, TimeSeriesChart } from '~/components';
import { Spacer } from '~/components/base';
import { TimeframeOption, TimeframeOptionsList } from '@corona-dashboard/common';
import { useState } from 'react';
import { ColorMatch, VariantChartValue, VariantDynamicLabels, VariantsOverTimeGraphText } from '~/domain/variants/data-selection/types';
import { ColorMatch, OrderMatch, VariantChartValue, VariantDynamicLabels, VariantsOverTimeGraphText } from '~/domain/variants/data-selection/types';
import { useBarConfig } from '~/domain/variants/logic/use-bar-config';
import { InteractiveLegend, SelectOption } from '~/components/interactive-legend';
import { useList } from '~/utils/use-list';
Expand All @@ -13,13 +13,14 @@ import { reorderAndFilter } from '~/domain/variants/logic/reorder-and-filter';
import { useIntl } from '~/intl';

interface VariantsStackedBarChartTileProps {
title: string;
description: string;
values: VariantChartValue[];
metadata: MetadataProps;
title: string;
tooltipLabels: VariantsOverTimeGraphText;
variantLabels: VariantDynamicLabels;
values: VariantChartValue[];
variantColors: ColorMatch[];
metadata: MetadataProps;
variantLabels: VariantDynamicLabels;
variantOrders: OrderMatch[];
}

const alwaysEnabled: (keyof VariantChartValue)[] = [];
Expand All @@ -35,12 +36,21 @@ const alwaysEnabled: (keyof VariantChartValue)[] = [];
* @param metadata - Metadata block
* @constructor
*/
export const VariantsStackedBarChartTile = ({ title, description, tooltipLabels, values, variantLabels, variantColors, metadata }: VariantsStackedBarChartTileProps) => {
export const VariantsStackedBarChartTile = ({
title,
description,
tooltipLabels,
values,
variantLabels,
variantColors,
variantOrders,
metadata,
}: VariantsStackedBarChartTileProps) => {
const today = useCurrentDate();
const { commonTexts } = useIntl();
const { list, toggle, clear } = useList<keyof VariantChartValue>(alwaysEnabled);
const [variantTimeFrame, setVariantTimeFrame] = useState<TimeframeOption>(TimeframeOption.THIRTY_DAYS);
const barSeriesConfig = useBarConfig(values, variantLabels, tooltipLabels, variantColors, variantTimeFrame, today);
const barSeriesConfig = useBarConfig(values, variantLabels, tooltipLabels, variantColors, variantOrders, variantTimeFrame, today);

const text = commonTexts.variants_page;

Expand All @@ -59,7 +69,7 @@ export const VariantsStackedBarChartTile = ({ title, description, tooltipLabels,
timeframeInitialValue={TimeframeOption.THIRTY_DAYS}
onSelectTimeframe={setVariantTimeFrame}
>
<InteractiveLegend helpText={text.legend_help_text} selectOptions={interactiveLegendOptions} selection={list} onToggleItem={toggle} onReset={clear} />
<InteractiveLegend helpText={text.legend_help_text} selectOptions={interactiveLegendOptions.reverse()} selection={list} onToggleItem={toggle} onReset={clear} />
<Spacer marginBottom={space[2]} />
<TimeSeriesChart
accessibility={{
Expand Down
7 changes: 6 additions & 1 deletion packages/app/src/pages/landelijk/varianten.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { getLastInsertionDateOfPage } from '~/utils/get-last-insertion-date-of-p
import { getPageInformationHeaderContent } from '~/utils/get-page-information-header-content';
import { BorderedKpiSection } from '~/components/kpi/bordered-kpi-section';
import { useState } from 'react';
import { getArchivedVariantChartData, getVariantBarChartData, getVariantOrderColors, getVariantTableData } from '~/domain/variants/data-selection';
import { getArchivedVariantChartData, getVariantBarChartData, getVariantOrderColors, getVariantOrders, getVariantTableData } from '~/domain/variants/data-selection';
import { VariantsStackedAreaTile, VariantsStackedBarChartTile, VariantsTableTile } from '~/domain/variants';
import { VariantDynamicLabels } from '~/domain/variants/data-selection/types';
import { NlVariantsVariant } from '@corona-dashboard/common';
Expand Down Expand Up @@ -51,11 +51,14 @@ export const getStaticProps = createGetStaticProps(

const variantColors = getVariantOrderColors(variants);

const variantOrders = getVariantOrders(variants);

return {
...getVariantTableData(variants, data.selectedNlData.named_difference, variantColors),
...getVariantBarChartData(variants),
...getArchivedVariantChartData(variants_archived_20231101),
variantColors,
variantOrders,
};
},
async (context: GetStaticPropsContext) => {
Expand Down Expand Up @@ -83,6 +86,7 @@ export default function CovidVariantenPage(props: StaticProps<typeof getStaticPr
variantChart,
archivedVariantChart,
variantColors,
variantOrders,
dates,
} = props;

Expand Down Expand Up @@ -173,6 +177,7 @@ export default function CovidVariantenPage(props: StaticProps<typeof getStaticPr
values={variantChart}
variantLabels={variantLabels}
variantColors={variantColors}
variantOrders={variantOrders}
metadata={{
datumsText: textNl.datums,
date: getLastInsertionDateOfPage(data, ['variants']),
Expand Down

0 comments on commit 608e7f0

Please sign in to comment.