From 3856cbe1f7884e46028833adb1fc4450766ec77d Mon Sep 17 00:00:00 2001 From: VWSCoronaDashboard29 <137172332+VWSCoronaDashboard29@users.noreply.github.com> Date: Tue, 19 Sep 2023 09:10:50 +0200 Subject: [PATCH 1/2] Bugfix/cor 1769 variants table and graph 2 (#4870) * fix(COR-1769): Removed keys from schemas * fix(COR-1769): Removed historical significance key * fix(COR-1769): Update getter functions * fix(COR-1769): Remove unused code from variants chart * fix(COR-1769): Re-add destructuring based on suggestion --------- Co-authored-by: VWSCoronaDashboard29 --- packages/app/schema/nl/variants.json | 8 ---- .../static-props/get-variant-chart-data.ts | 25 +++++++------ .../static-props/get-variant-order-colors.ts | 6 +-- .../static-props/get-variant-table-data.ts | 32 +++++++++------- .../variants-stacked-area-tile.tsx | 37 +++++-------------- .../cms/src/studio/data/data-structure.ts | 4 +- packages/common/src/types/data.ts | 12 +----- 7 files changed, 49 insertions(+), 75 deletions(-) diff --git a/packages/app/schema/nl/variants.json b/packages/app/schema/nl/variants.json index d628af7a57..7f2473f281 100644 --- a/packages/app/schema/nl/variants.json +++ b/packages/app/schema/nl/variants.json @@ -41,8 +41,6 @@ "order", "occurrence", "percentage", - "is_variant_of_concern", - "has_historical_significance", "sample_size", "date_start_unix", "date_end_unix", @@ -61,12 +59,6 @@ "percentage": { "type": "number" }, - "is_variant_of_concern": { - "type": "boolean" - }, - "has_historical_significance": { - "type": "boolean" - }, "sample_size": { "type": "integer" }, diff --git a/packages/app/src/domain/variants/static-props/get-variant-chart-data.ts b/packages/app/src/domain/variants/static-props/get-variant-chart-data.ts index 600d5ea608..9943c5ef49 100644 --- a/packages/app/src/domain/variants/static-props/get-variant-chart-data.ts +++ b/packages/app/src/domain/variants/static-props/get-variant-chart-data.ts @@ -18,31 +18,32 @@ const EMPTY_VALUES = { }, } as const; +/** + * Returns values for variant timeseries chart + * @param variants + */ export function getVariantChartData(variants: NlVariants | undefined) { if (!isDefined(variants) || !isDefined(variants.values)) { return EMPTY_VALUES; } - const variantsOfConcern = variants.values - .filter((variant) => variant.last_value.is_variant_of_concern || variant.last_value.has_historical_significance) - .filter((variant) => variant.variant_code !== 'other_graph' && variant.variant_code !== 'other_table') - .sort((a, b) => b.last_value.order - a.last_value.order); + const sortedVariants = variants.values.sort((a, b) => b.last_value.order - a.last_value.order); - const firstVariant = variantsOfConcern.shift(); + const firstVariantInList = sortedVariants.shift(); - if (!isDefined(firstVariant)) { + if (!isDefined(firstVariantInList)) { return EMPTY_VALUES; } - const values = firstVariant.values.map((value, index) => { + const values = firstVariantInList.values.map((value, index) => { const item = { is_reliable: true, date_start_unix: value.date_start_unix, date_end_unix: value.date_end_unix, - [`${firstVariant.variant_code}_percentage`]: value.percentage, + [`${firstVariantInList.variant_code}_percentage`]: value.percentage, } as VariantChartValue; - variantsOfConcern.forEach((variant) => { + sortedVariants.forEach((variant) => { (item as unknown as Record)[`${variant.variant_code}_percentage`] = variant.values[index].percentage; }); @@ -52,9 +53,9 @@ export function getVariantChartData(variants: NlVariants | undefined) { return { variantChart: values, dates: { - date_of_report_unix: firstVariant.last_value.date_of_report_unix, - date_start_unix: firstVariant.last_value.date_start_unix, - date_end_unix: firstVariant.last_value.date_end_unix, + date_of_report_unix: firstVariantInList.last_value.date_of_report_unix, + date_start_unix: firstVariantInList.last_value.date_start_unix, + date_end_unix: firstVariantInList.last_value.date_end_unix, }, } as const; } diff --git a/packages/app/src/domain/variants/static-props/get-variant-order-colors.ts b/packages/app/src/domain/variants/static-props/get-variant-order-colors.ts index d899e624a9..b100539ff3 100644 --- a/packages/app/src/domain/variants/static-props/get-variant-order-colors.ts +++ b/packages/app/src/domain/variants/static-props/get-variant-order-colors.ts @@ -8,8 +8,7 @@ export type ColorMatch = { }; const getColorForVariant = (variantCode: VariantCode, index: number): string => { - if (variantCode === 'other_table') return colors.gray5; - if (variantCode === 'other_graph') return colors.gray5; + if (variantCode === 'other_variants') return colors.gray5; return colors.variants.colorList[index]; }; @@ -20,8 +19,7 @@ export const getVariantOrderColors = (variants: NlVariants | undefined): ColorMa } const colorOrder = variants.values - .filter((variant) => variant.last_value.is_variant_of_concern || variant.last_value.has_historical_significance) - .sort((a, b) => (a.variant_code.includes('other') || b.variant_code.includes('other') ? -1 : a.last_value.order - b.last_value.order)) + .sort((a, b) => a.last_value.order - b.last_value.order) .map((variant, index) => { const variantColor = getColorForVariant(variant.variant_code, index); return { diff --git a/packages/app/src/domain/variants/static-props/get-variant-table-data.ts b/packages/app/src/domain/variants/static-props/get-variant-table-data.ts index 7e173b3168..73081fb5d4 100644 --- a/packages/app/src/domain/variants/static-props/get-variant-table-data.ts +++ b/packages/app/src/domain/variants/static-props/get-variant-table-data.ts @@ -13,6 +13,12 @@ export type VariantRow = { export type VariantTableData = ReturnType; +/** + * Return values to populate the variants table + * @param variants + * @param namedDifference + * @param variantColors + */ export function getVariantTableData(variants: NlVariants | undefined, namedDifference: NlNamedDifference, variantColors: ColorMatch[]) { const emptyValues = { variantTable: null, @@ -31,14 +37,14 @@ export function getVariantTableData(variants: NlVariants | undefined, namedDiffe if (isPresent(namedDifference.variants__percentage)) { const difference = namedDifference.variants__percentage.find((x) => x.variant_code === name); - if (!difference) { - return null; - } - - return difference; + return difference ?? null; } } + function mapVariantToNamedDifference(namedDifferenceVariantCode: string) { + return variants?.values.find((x) => x.variant_code === namedDifferenceVariantCode) ?? null; + } + const firstLastValue = first(variants.values); if (!isDefined(firstLastValue)) { @@ -50,16 +56,16 @@ export function getVariantTableData(variants: NlVariants | undefined, namedDiffe date_of_report_unix: firstLastValue.last_value.date_of_report_unix, }; - const variantTable = variants.values - .filter((variant) => variant.variant_code !== 'other_graph' && !variant.last_value.has_historical_significance) - .sort((a, b) => b.last_value.order - a.last_value.order) - .map((variant) => { - const color = variantColors.find((variantColor) => variantColor.variant === variant.variant_code)?.color || colors.gray5; + const variantTable = namedDifference.variants__percentage + .filter((namedDifferencePercentage) => mapVariantToNamedDifference(namedDifferencePercentage.variant_code) !== null) + .sort((a, b) => mapVariantToNamedDifference(b.variant_code)!.last_value.order - mapVariantToNamedDifference(a.variant_code)!.last_value.order) + .map((namedDifferenceEntry) => { + const color = variantColors.find((variantColor) => variantColor.variant === namedDifferenceEntry.variant_code)?.color || colors.gray5; return { - variantCode: variant.variant_code, - percentage: variant.last_value.percentage, - difference: findDifference(variant.variant_code), + variantCode: namedDifferenceEntry.variant_code, + percentage: mapVariantToNamedDifference(namedDifferenceEntry.variant_code)?.last_value.percentage as unknown as number, + difference: findDifference(namedDifferenceEntry.variant_code), color, }; }); diff --git a/packages/app/src/domain/variants/variants-stacked-area-tile/variants-stacked-area-tile.tsx b/packages/app/src/domain/variants/variants-stacked-area-tile/variants-stacked-area-tile.tsx index 27311fa89b..753222a673 100644 --- a/packages/app/src/domain/variants/variants-stacked-area-tile/variants-stacked-area-tile.tsx +++ b/packages/app/src/domain/variants/variants-stacked-area-tile/variants-stacked-area-tile.tsx @@ -1,4 +1,4 @@ -import { colors, TimeframeOption, TimeframeOptionsList } from '@corona-dashboard/common'; +import { TimeframeOption, TimeframeOptionsList } from '@corona-dashboard/common'; import { useMemo, useState } from 'react'; import { isDefined, isPresent } from 'ts-is-present'; import { Spacer } from '~/components/base'; @@ -35,9 +35,9 @@ export const VariantsStackedAreaTile = ({ text, values, variantColors, metadata const { list, toggle, clear } = useList(alwaysEnabled); - const [seriesConfig, otherConfig, selectOptions] = useSeriesConfig(text, values, variantColors); + const [seriesConfig, selectOptions] = useSeriesConfig(text, values, variantColors); - const filteredConfig = useFilteredSeriesConfig(seriesConfig, otherConfig, list); + const filteredConfig = useFilteredSeriesConfig(seriesConfig, list); /* Static legend contains only the inaccurate item */ const staticLegendItems: LegendItem[] = []; @@ -93,8 +93,8 @@ export const VariantsStackedAreaTile = ({ text, values, variantColors, metadata const reorderContext = { ...context, config: [ + // Destructuring so as to not interact with the object directly and eliminate the possibility of introducing inconsistencies ...context.config.filter((value) => !hasMetricProperty(value) || filteredValues[value.metricProperty] || hasSelectedMetrics), - context.config.find((value) => hasMetricProperty(value) && value.metricProperty === 'other_graph_percentage'), ].filter(isDefined), value: !hasSelectedMetrics ? filteredValues : context.value, }; @@ -117,16 +117,10 @@ const hasMetricProperty = (config: any): config is { metricProperty: string } => return 'metricProperty' in config; }; -const useFilteredSeriesConfig = ( - seriesConfig: GappedAreaSeriesDefinition[], - otherConfig: GappedAreaSeriesDefinition, - compareList: (keyof VariantChartValue)[] -) => { +const useFilteredSeriesConfig = (seriesConfig: GappedAreaSeriesDefinition[], compareList: (keyof VariantChartValue)[]) => { return useMemo(() => { - return [otherConfig, ...seriesConfig].filter( - (item) => item.metricProperty !== 'other_graph_percentage' && (compareList.includes(item.metricProperty) || compareList.length === alwaysEnabled.length) - ); - }, [seriesConfig, otherConfig, compareList]); + return seriesConfig.filter((item) => compareList.includes(item.metricProperty) || compareList.length === alwaysEnabled.length); + }, [seriesConfig, compareList]); }; const useSeriesConfig = (text: VariantsStackedAreaTileText, values: VariantChartValue[], variantColors: ColorMatch[]) => { @@ -134,7 +128,7 @@ const useSeriesConfig = (text: VariantsStackedAreaTileText, values: VariantChart const baseVariantsFiltered = values .flatMap((x) => Object.keys(x)) .filter((x, index, array) => array.indexOf(x) === index) // de-dupe - .filter((x) => x.endsWith('_percentage') && x !== 'other_graph_percentage') + .filter((x) => x.endsWith('_percentage')) .reverse(); // Reverse to be in an alphabetical order /* Enrich config with dynamic data / locale */ @@ -146,7 +140,7 @@ const useSeriesConfig = (text: VariantsStackedAreaTileText, values: VariantChart const variantDynamicLabel = text.variantCodes[variantCode]; - const color = variantColors.find((variantColors) => variantColors.variant === variantCode)?.color || colors.gray5; + const color = variantColors.find((variantColors) => variantColors.variant === variantCode)?.color; if (variantDynamicLabel) { const newConfig = { @@ -164,19 +158,8 @@ const useSeriesConfig = (text: VariantsStackedAreaTileText, values: VariantChart } }); - const otherConfig = { - type: 'gapped-area', - metricProperty: 'other_graph_percentage', - label: text.tooltip_labels.other_percentage, - fillOpacity: 0.2, - shape: 'square', - color: colors.gray5, - strokeWidth: 2, - mixBlendMode: 'multiply', - } as GappedAreaSeriesDefinition; - const selectOptions = [...seriesConfig]; - return [seriesConfig, otherConfig, selectOptions] as const; + return [seriesConfig, selectOptions] as const; }, [values, text.tooltip_labels.other_percentage, text.variantCodes, variantColors]); }; diff --git a/packages/cms/src/studio/data/data-structure.ts b/packages/cms/src/studio/data/data-structure.ts index 7e394fe459..6e80c22a9c 100644 --- a/packages/cms/src/studio/data/data-structure.ts +++ b/packages/cms/src/studio/data/data-structure.ts @@ -28,6 +28,7 @@ export const dataStructure = { tested_overall_archived_20230331: ['infected', 'infected_moving_average', 'infected_moving_average_rounded', 'infected_per_100k', 'infected_per_100k_moving_average'], }, archived_gm_collection: { + hospital_nice_choropleth_archived_20230830: ['admissions_on_date_of_admission', 'admissions_on_date_of_admission_per_100000', 'admissions_on_date_of_reporting'], sewer_archived_20230623: ['average', 'total_installation_count', 'data_is_outdated'], tested_overall_archived_20230331: ['infected_per_100k', 'infected'], }, @@ -226,6 +227,7 @@ export const dataStructure = { 'admissions_on_date_of_admission', 'admissions_on_date_of_admission_moving_average', 'admissions_on_date_of_admission_moving_average_rounded', + 'admissions_in_the_last_7_days', 'admissions_on_date_of_reporting', ], sewer: ['average', 'data_is_outdated'], @@ -243,7 +245,7 @@ export const dataStructure = { ], }, gm_collection: { - hospital_nice_choropleth: ['admissions_on_date_of_admission', 'admissions_on_date_of_admission_per_100000', 'admissions_on_date_of_reporting'], + hospital_nice_choropleth: ['admissions_in_the_last_7_days_per_100000'], sewer: ['average', 'data_is_outdated'], vaccine_coverage_per_age_group: [ 'vaccination_type', diff --git a/packages/common/src/types/data.ts b/packages/common/src/types/data.ts index 0011031c18..5c81e342de 100644 --- a/packages/common/src/types/data.ts +++ b/packages/common/src/types/data.ts @@ -758,14 +758,7 @@ export interface GmStaticValues { population_count_connected_to_rwzis: number; } export interface GmDifference { - hospital_nice__admissions_on_date_of_reporting_moving_average: DifferenceDecimal; - sewer__average?: DifferenceInteger; -} -export interface DifferenceDecimal { - old_value: number; - difference: number; - old_date_unix: number; - new_date_unix: number; + sewer__average: DifferenceInteger; } export interface DifferenceInteger { old_value: number; @@ -1209,8 +1202,7 @@ export interface NlVariantsVariantValue { order: number; occurrence: number; percentage: number; - is_variant_of_concern: boolean; - has_historical_significance: boolean; + has_historical_significance?: boolean; sample_size: number; date_start_unix: number; date_end_unix: number; From dc750b9147dbdf034bf9cd380f665325decd1f10 Mon Sep 17 00:00:00 2001 From: VWSCoronaDashboard29 <137172332+VWSCoronaDashboard29@users.noreply.github.com> Date: Tue, 19 Sep 2023 16:30:28 +0200 Subject: [PATCH 2/2] Hotfix/cor 1769 other variants on top (#4876) * fix(COR-1769): Put other_variants at bottom of table * fix(COR-1769): Add comment * fix(COR-1769): Clean up code * fix(COR-1769): Remove unused filter --------- Co-authored-by: VWSCoronaDashboard29 --- .../static-props/get-variant-table-data.ts | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/packages/app/src/domain/variants/static-props/get-variant-table-data.ts b/packages/app/src/domain/variants/static-props/get-variant-table-data.ts index 73081fb5d4..de5947f6ed 100644 --- a/packages/app/src/domain/variants/static-props/get-variant-table-data.ts +++ b/packages/app/src/domain/variants/static-props/get-variant-table-data.ts @@ -1,11 +1,12 @@ import { colors, NlNamedDifference, NlVariants, NlVariantsVariant, NamedDifferenceDecimal } from '@corona-dashboard/common'; import { first } from 'lodash'; -import { isDefined, isPresent } from 'ts-is-present'; +import { isDefined } from 'ts-is-present'; import { ColorMatch } from './get-variant-order-colors'; import { VariantCode } from '../static-props'; export type VariantRow = { variantCode: VariantCode; + order: number; percentage: number | null; difference?: NamedDifferenceDecimal | null; color: string; @@ -33,18 +34,6 @@ export function getVariantTableData(variants: NlVariants | undefined, namedDiffe return emptyValues; } - function findDifference(name: string) { - if (isPresent(namedDifference.variants__percentage)) { - const difference = namedDifference.variants__percentage.find((x) => x.variant_code === name); - - return difference ?? null; - } - } - - function mapVariantToNamedDifference(namedDifferenceVariantCode: string) { - return variants?.values.find((x) => x.variant_code === namedDifferenceVariantCode) ?? null; - } - const firstLastValue = first(variants.values); if (!isDefined(firstLastValue)) { @@ -56,18 +45,28 @@ export function getVariantTableData(variants: NlVariants | undefined, namedDiffe date_of_report_unix: firstLastValue.last_value.date_of_report_unix, }; + /** + * Reverse order of variants to what is received from the master table + * Move 'other variants' all the way to the bottom of the table + */ const variantTable = namedDifference.variants__percentage - .filter((namedDifferencePercentage) => mapVariantToNamedDifference(namedDifferencePercentage.variant_code) !== null) - .sort((a, b) => mapVariantToNamedDifference(b.variant_code)!.last_value.order - mapVariantToNamedDifference(a.variant_code)!.last_value.order) .map((namedDifferenceEntry) => { - const color = variantColors.find((variantColor) => variantColor.variant === namedDifferenceEntry.variant_code)?.color || colors.gray5; + // There is ALWAYS a corresponding variant to a namedDifference entry. + const variant = variants.values.find((x) => x.variant_code === namedDifferenceEntry.variant_code)!; return { variantCode: namedDifferenceEntry.variant_code, - percentage: mapVariantToNamedDifference(namedDifferenceEntry.variant_code)?.last_value.percentage as unknown as number, - difference: findDifference(namedDifferenceEntry.variant_code), - color, + order: variant.last_value.order, + percentage: variant.last_value.percentage, + difference: namedDifferenceEntry, + color: variantColors.find((variantColor) => variantColor.variant === namedDifferenceEntry.variant_code)?.color || colors.gray5, }; + }) + .sort((a, b) => { + // Other Variants must always take the bottom row in the table + if (a.variantCode === 'other_variants') return 1; + if (b.variantCode === 'other_variants') return -1; + return b.order - a.order; }); return { variantTable, dates };