From 5797e926ec5f4a19d52f28e4b03120201e7e10d7 Mon Sep 17 00:00:00 2001 From: Eric Boucher Date: Mon, 24 Jul 2023 16:49:40 +0200 Subject: [PATCH] Add a table for phase data in tooltips; COUNTRY=cameroon (#867) --- .../components/MapView/MapTooltip/index.tsx | 163 ++++++++++++++++-- frontend/src/config/southsudan/layers.json | 4 +- 2 files changed, 150 insertions(+), 17 deletions(-) diff --git a/frontend/src/components/MapView/MapTooltip/index.tsx b/frontend/src/components/MapView/MapTooltip/index.tsx index 58eaaca3a..70bb83442 100644 --- a/frontend/src/components/MapView/MapTooltip/index.tsx +++ b/frontend/src/components/MapView/MapTooltip/index.tsx @@ -6,15 +6,86 @@ import { withStyles, WithStyles, LinearProgress, + Typography, } from '@material-ui/core'; -import { isEqual } from 'lodash'; -import { tooltipSelector } from 'context/tooltipStateSlice'; +import { isEmpty, isEqual, sum } from 'lodash'; +import { PopupData, tooltipSelector } from 'context/tooltipStateSlice'; import { isEnglishLanguageSelected, useSafeTranslation } from 'i18n'; +import { TFunction } from 'utils/data-utils'; +import { ClassNameMap } from '@material-ui/styles'; + +// This function prepares phasePopulationTable for rendering and is specific +// to the data structure of the phase classification layer. +// Note - this is a bit hacky for now and will likely need to be revamped if we +// encounter other complex needs for tooltips. +const generatePhasePopulationTable = ( + popupData: PopupData, + t: TFunction, + classes: ClassNameMap, +): JSX.Element | null => { + const phasePopulations: Record = Object.entries( + popupData, + ).reduce((acc: any, cur: any) => { + const [key, value] = cur; + if (key.includes('Population in phase ')) { + // extract number from string looking like "Phase classification 1" + const phaseNumber = key.replace('Population in phase ', ''); + if (phaseNumber) { + return { ...acc, [phaseNumber]: value.data }; + } + } + return acc; + }, {}); + + if (isEmpty(phasePopulations)) { + return null; + } + + // calculate total population + // eslint-disable-next-line no-param-reassign, fp/no-mutation + phasePopulations.Total = + sum(Object.values(phasePopulations)) - phasePopulations['3 to 5']; + + const phasePopulationTable = ( +
+ + {t('Ref. period')}: {popupData['Reference period start']?.data} -{' '} + {popupData['Reference period end']?.data} + + + {t('Population and percentage by phase classification')} + + + + {Object.keys(phasePopulations).map((phaseName: string) => ( + + ))} + + + {Object.values(phasePopulations).map((populationInPhase: number) => ( + + ))} + + + {Object.values(phasePopulations).map((populationInPhase: number) => ( + + ))} + +
{t(phaseName)}
{populationInPhase.toLocaleString()}
+ {Math.round((populationInPhase / phasePopulations.Total) * 100)}% +
+
+ ); + + return phasePopulationTable; +}; const MapTooltip = memo(({ classes }: TooltipProps) => { const popup = useSelector(tooltipSelector); const { t, i18n } = useSafeTranslation(); + const popupData = popup.data; + const popupTitle = useMemo(() => { if (isEnglishLanguageSelected(i18n)) { return popup.locationName; @@ -23,21 +94,64 @@ const MapTooltip = memo(({ classes }: TooltipProps) => { }, [i18n, popup.locationLocalName, popup.locationName]); const renderedPopupContent = useMemo(() => { - return Object.entries(popup.data) + const phasePopulationTable = generatePhasePopulationTable( + popupData, + t, + classes, + ); + // filter out popupData where key value contains "Population in phase " + const popupDataWithoutPhasePopulations: PopupData = Object.entries( + popupData, + ).reduce((acc: any, cur: any) => { + const [key, value] = cur; + if ( + // keep "Population in phase 1" as a placeholder for the phase population table + key === 'Population in phase 1' || + (!key.includes('Population in phase ') && + !key.includes('Reference period ')) + ) { + return { ...acc, [key]: value }; + } + return acc; + }, {}); + return Object.entries(popupDataWithoutPhasePopulations) .filter(([, value]) => { return isEqual(value.coordinates, popup.coordinates); }) .map(([key, value]) => { return ( -

{`${t(key)}: ${value.data}`}

-

+ {/* Allow users to show data without a key/title */} + {!key.includes('do_not_display') && + key !== 'Population in phase 1' && ( + + {`${t(key)}: `} + + )} + {key !== 'Population in phase 1' && ( + + {`${value.data}`} + + )} + {/* Phase classification data */} + {value.adminLevel && `${t('Admin Level')}: ${value.adminLevel}`} -

+ + {key === 'Population in phase 1' && phasePopulationTable}
); }); - }, [popup.coordinates, popup.data, t]); + }, [classes, popup.coordinates, popupData, t]); const renderedPopupLoader = useMemo(() => { if (!popup.wmsGetFeatureInfoLoading) { @@ -51,18 +165,17 @@ const MapTooltip = memo(({ classes }: TooltipProps) => { return null; } return ( - -

{popupTitle}

+ + + {popupTitle} + {renderedPopupContent} {renderedPopupLoader} ); }, [ classes.popup, + classes.title, popup.coordinates, popup.showing, popupTitle, @@ -73,17 +186,37 @@ const MapTooltip = memo(({ classes }: TooltipProps) => { const styles = () => createStyles({ + phasePopulationTable: { + tableLayout: 'fixed', + borderCollapse: 'collapse', + width: '100%', + borderWidth: '1px;', + borderColor: 'inherit', + borderStyle: 'solid', + border: '1px solid white', + }, + phasePopulationTableRow: { + border: '1px solid white', + }, + title: { + fontWeight: 600, + marginBottom: '8px', + }, + text: { + marginBottom: '4px', + }, popup: { '& div.mapboxgl-popup-content': { background: 'black', color: 'white', - padding: '10px 10px 10px', + padding: '5px 5px 5px 5px', maxWidth: '30em', - maxHeight: '12em', + maxHeight: '20em', overflow: 'auto', }, '& div.mapboxgl-popup-tip': { 'border-top-color': 'black', + 'border-bottom-color': 'black', }, }, }); diff --git a/frontend/src/config/southsudan/layers.json b/frontend/src/config/southsudan/layers.json index 82379a015..1af3ceb2c 100644 --- a/frontend/src/config/southsudan/layers.json +++ b/frontend/src/config/southsudan/layers.json @@ -3066,11 +3066,11 @@ }, "event_date": { "type": "string", - "dataTitle": "Date" + "dataTitle": "do_not_display_date" }, "notes": { "type": "string", - "dataTitle": "Details" + "dataTitle": "do_not_display_details" } } },