Skip to content

Commit

Permalink
Merge pull request #85 from SocialGouv/fix/map-and-dougnhuts
Browse files Browse the repository at this point in the history
feat: improve legends on map and dougnhut
  • Loading branch information
ClementNumericite authored Nov 15, 2023
2 parents 7a9409d + 1de2278 commit 8704938
Show file tree
Hide file tree
Showing 9 changed files with 274 additions and 46 deletions.
15 changes: 13 additions & 2 deletions webapp-next/components/charts/doughnut/Doughnut.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { doughnutProps } from '@/utils/chartjs/props';
import { Cm2dContext } from '@/utils/cm2d-provider';
import { orders, sortByOrder } from '@/utils/orders';
import { capitalizeString, getLabelFromKey } from '@/utils/tools';
import {
capitalizeString,
chartsAvailableColors,
getLabelFromKey
} from '@/utils/tools';
import { Box, Flex } from '@chakra-ui/react';
import { useContext, useEffect, useState } from 'react';
import { Doughnut } from 'react-chartjs-2';

Expand Down Expand Up @@ -45,11 +50,17 @@ export const ChartDoughnut = (props: Props) => {
label = getLabelFromKey(ds.label.toString());
}

const colors = yValues.map(
(_, index) =>
chartsAvailableColors[index % chartsAvailableColors.length]
);

return {
label: capitalizeString(label),
data: yValues,
fill: true,
borderRadius: 10
borderRadius: 10,
backgroundColor: colors
};
})
);
Expand Down
47 changes: 30 additions & 17 deletions webapp-next/components/charts/map/Map.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Cm2dContext } from '@/utils/cm2d-provider';
import { getMapProps } from '@/utils/map/props';
import { MapConfig } from '@/utils/map/type';
import { Flex } from '@chakra-ui/react';
import React, { useContext } from 'react';
import { Legends } from './Legends';
import { Cm2dContext } from '@/utils/cm2d-provider';
import React, { useContext, useState } from 'react';
import { MapDetails } from './MapDetails';
import { MapLegends } from './MapLegends';

type Props = {
id: string;
Expand All @@ -12,6 +14,7 @@ type Props = {
export default function MapIframe(props: Props) {
const iframeRef = React.useRef(null);
const { datasets, id } = props;
const [mapConfig, setMapConfig] = useState<MapConfig | null>(null);
const context = useContext(Cm2dContext);

if (!context) {
Expand All @@ -25,6 +28,7 @@ export default function MapIframe(props: Props) {

if (iframe) {
const doc = (iframe as any).contentWindow.document;
const mapProps = getMapProps(id, datasets, saveAggregateX);
doc.open();
doc.write(`
<html>
Expand All @@ -35,13 +39,13 @@ export default function MapIframe(props: Props) {
}, true);
</script>
<script type="text/javascript">
${getMapProps(id, datasets, saveAggregateX)}
${mapProps.injectJs}
</script>
<script type="text/javascript" src="libs/countrymap/countrymap.js"></script>
<style>
#${id}_access {
display: none !important;
}
}setMapConfig
</style>
</head>
<body style="display: flex; justify-content: center;">
Expand All @@ -50,6 +54,8 @@ export default function MapIframe(props: Props) {
</html>
`);
doc.close();

if (mapProps.config) setMapConfig(mapProps.config);
}
};

Expand All @@ -65,19 +71,26 @@ export default function MapIframe(props: Props) {
return (
<Flex flexDir="column">
<Flex justifyContent="end">
<Legends />
<MapLegends />
</Flex>
<Flex alignItems="center">
<iframe
title="Map"
ref={iframeRef}
width={'65%'}
height="700px"
loading="lazy"
onClick={e => {
e.preventDefault();
e.stopPropagation();
}}
/>
{mapConfig && (
<Flex w="30%" maxH="400px" overflowY="auto" mb={20}>
<MapDetails mapConfig={mapConfig} />
</Flex>
)}
</Flex>
<iframe
title="Map"
ref={iframeRef}
width={'100%'}
height="700px"
loading="lazy"
onClick={e => {
e.preventDefault();
e.stopPropagation();
}}
/>
</Flex>
);
}
59 changes: 59 additions & 0 deletions webapp-next/components/charts/map/MapDetails.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { MapConfig } from '@/utils/map/type';
import { getFirstIntFromString } from '@/utils/tools';
import { Box, Flex, ListItem, UnorderedList } from '@chakra-ui/react';

export type Props = {
mapConfig: MapConfig;
};

export function MapDetails({ mapConfig }: Props) {
console.log(mapConfig);

function extractDetailsValues(
input: string
): { label: string; value: number }[] {
const values: { label: string; value: number }[] = [];

const regex = /<div>([^:]+)\s*:\s*(\d+)<\/div>/g;
let match;

while ((match = regex.exec(input)) !== null) {
const label = match[1].trim();
const value = parseInt(match[2], 10);

values.push({ label, value });
}

return values;
}

return (
<Flex direction="column">
{Object.entries(mapConfig.state_specific).map(([key, value]) => (
<Flex key={key} mb={3}>
<Box
w={4}
h={4}
mr={2}
mt={1.5}
borderRadius="full"
borderWidth={1}
borderColor={value.hover_color}
bg={value.color}
/>
<p>
<strong>{value.name}</strong> :{' '}
{getFirstIntFromString(value.description)}
{extractDetailsValues(value.description).map((item, index) => (
<UnorderedList key={index} spacing={3} fontSize={'sm'}>
<ListItem>
{item.label} : {item.value}
</ListItem>
</UnorderedList>
))}
</p>
</Flex>
))}
</Flex>
);
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import { Box, Flex, Text } from '@chakra-ui/react';

export function Legends() {
export function MapLegends() {
const legends = [
{
color: 'green.100',
borderColor: 'green.300',
color: '#c9e7c8',
borderColor: '#4daf4a',
content: '0-10%'
},
{
color: 'blue.100',
borderColor: 'blue.300',
color: '#c3d8e9',
borderColor: '#377eb8',
content: '10-20%'
},
{
color: 'orange.100',
borderColor: 'orange.300',
color: '#ffd8b2',
borderColor: '#ff7f00',
content: '20-30%'
},
{
color: 'red.100',
borderColor: 'red.300',
color: '#f6baba',
borderColor: '#e41a1c',
content: '30%+'
}
];
Expand Down
1 change: 1 addition & 0 deletions webapp-next/pages/bo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ export default function Home() {
maxH={
['line', 'histogram', 'doughnut'].includes(view) ? '30rem' : 'auto'
}
position="relative"
>
<Text
as="h2"
Expand Down
36 changes: 33 additions & 3 deletions webapp-next/utils/chartjs/props.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChartOptions } from 'chart.js';
import { Chart, ChartData, ChartOptions, LegendItem } from 'chart.js';
import { legendSpacingPlugin, verticalLegendPlugin } from './utils';

export const lineProps: { options: ChartOptions<'line'>; plugins: any[] } = {
Expand Down Expand Up @@ -100,14 +100,44 @@ export const doughnutProps: {
options: {
responsive: true,
maintainAspectRatio: false,
layout: {
padding: {
bottom: 36,
top: 20
}
},
plugins: {
filler: {
propagate: false
},
legend: {
position: 'top',
position: 'right',
align: 'end',
labels: {
generateLabels: function (chart: Chart) {
const data = chart.data as ChartData<'doughnut'>;
if (data.labels && data.datasets) {
return data.labels.map((label, i) => {
const dataset = data.datasets[0];
const value = dataset?.data[i] || '';
const backgroundColor =
dataset?.backgroundColor || ''
? Array.isArray(dataset.backgroundColor)
? dataset.backgroundColor[i]
: dataset.backgroundColor
: 'grey';
return {
text: `${label} : ${value}`,
fillStyle: backgroundColor,
strokeStyle: backgroundColor,
lineWidth: 1,
hidden: !chart.getDataVisibility(i),
index: i
};
});
}
return [];
},
font: {
size: 14
},
Expand All @@ -117,7 +147,7 @@ export const doughnutProps: {
}
}
},
cutout: 140
cutout: 160
},
plugins: [legendSpacingPlugin]
};
44 changes: 33 additions & 11 deletions webapp-next/utils/map/props.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { orders, sortByOrder } from '../orders';
import { capitalizeString, getLabelFromKey, isNC } from '../tools';
import { capitalizeString, getLabelFromKey, hexToRGB, isNC } from '../tools';
import { MapConfig } from './type';

export const getMapProps = (
id: string,
datasets: { hits: any[]; total?: number }[],
saveAggregateX?: string
) => {
if (!datasets[0]) return '';
): {
config?: MapConfig;
injectJs: string;
} => {
if (!datasets[0]) return { injectJs: '' };

const { hits, total } = datasets[0];

Expand All @@ -33,11 +37,26 @@ export const getMapProps = (
}

const stateColors = {
GREEN: { initial: '#C6F6D5', hover: '#68D391' },
BLUE: { initial: '#E9F1FF', hover: '#A7C4FD' },
ORANGE: { initial: '#FEEBCB', hover: '#F8AB4E' },
RED: { initial: '#FED7D7', hover: '#FC8181' },
NEUTRAL: { initial: '#EDF2F7', hover: '#CBD5E0' }
GREEN: {
initial: '#c9e7c8',
hover: '#4daf4a'
},
BLUE: {
initial: '#c3d8e9',
hover: '#377eb8'
},
ORANGE: {
initial: '#ffd8b2',
hover: '#ff7f00'
},
RED: {
initial: '#f6baba',
hover: '#e41a1c'
},
NEUTRAL: {
initial: '#e0e0e0',
hover: '#999999'
}
};

const getCountFromKey = (key: number): number => {
Expand Down Expand Up @@ -98,10 +117,10 @@ export const getMapProps = (
return `Nombre de décès : ${getCountFromKey(key)}`;
};

const config = {
const config: MapConfig = {
main_settings: {
//General settings
width: 700,
width: 600,
background_color: '#FFFFFF',
background_transparent: 'yes',
border_color: '#246CF9',
Expand Down Expand Up @@ -239,5 +258,8 @@ export const getMapProps = (
}
};

return `var simplemaps_countrymap_mapdata=${JSON.stringify(config)}`;
return {
config: config,
injectJs: `var simplemaps_countrymap_mapdata=${JSON.stringify(config)}`
};
};
Loading

0 comments on commit 8704938

Please sign in to comment.