From 883a722bcc7684dcff0e1cde6d4a24471bcbe8c6 Mon Sep 17 00:00:00 2001 From: Tero Tikkanen Date: Fri, 29 Nov 2024 11:57:57 +0200 Subject: [PATCH] Unify indicator graph styles --- components/graphs/GraphAsTable.js | 19 +++++++-- components/graphs/IndicatorGraph.tsx | 42 +++++++++---------- .../indicators/IndicatorVisualisation.js | 5 +-- .../contentblocks/CategoryPageHeaderBlock.tsx | 5 ++- .../paths/graphs/IndicatorSparkline.tsx | 2 +- 5 files changed, 41 insertions(+), 32 deletions(-) diff --git a/components/graphs/GraphAsTable.js b/components/graphs/GraphAsTable.js index fe5a4e45..75a1465e 100644 --- a/components/graphs/GraphAsTable.js +++ b/components/graphs/GraphAsTable.js @@ -4,7 +4,7 @@ import dayjs from 'common/dayjs'; import { Table, Collapse, Button } from 'reactstrap'; import { beautifyValue } from 'common/data/format'; import Icon from 'components/common/Icon'; -import { useTranslations } from 'next-intl'; +import { useFormatter, useTranslations } from 'next-intl'; const CollapsibleTable = styled.div` background-color: ${(props) => props.theme.themeColors.white}; @@ -12,7 +12,6 @@ const CollapsibleTable = styled.div` `; const Trigger = styled.div` - padding-bottom: ${(props) => props.theme.spaces.s050}; background-color: ${(props) => props.theme.cardBackground.primary}; text-align: center; `; @@ -56,6 +55,7 @@ const TriggerButton = styled(Button)` function GraphAsTable(props) { const t = useTranslations(); + const format = useFormatter(); const [isOpen, setIsOpen] = useState(false); const toggle = () => setIsOpen(!isOpen); @@ -83,14 +83,25 @@ function GraphAsTable(props) { tableRows.sort((a, b) => dayjs(a).diff(dayjs(b))); } - const dateFormat = timeResolution === 'YEAR' ? 'YYYY' : 'l'; + const dateFormat = + timeResolution === 'YEAR' + ? { + year: 'numeric', + } + : { + year: 'numeric', + month: 'numeric', + day: 'numeric', + }; // Create table data row by row const tableData = []; tableRows.map((row, i) => { const rowObj = {}; rowObj.label = - data[0].xType === 'time' ? dayjs(row).format(dateFormat) : row; + data[0].xType === 'time' + ? format.dateTime(new Date(row), dateFormat) + : row; rowObj.values = []; data.map((trace, i) => { const indexOfX = trace.x.indexOf(row); diff --git a/components/graphs/IndicatorGraph.tsx b/components/graphs/IndicatorGraph.tsx index 2c112116..9efb1136 100644 --- a/components/graphs/IndicatorGraph.tsx +++ b/components/graphs/IndicatorGraph.tsx @@ -29,7 +29,7 @@ const createLayout = ( const fontFamily = '-apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, ' + 'helvetica neue, helvetica, Ubuntu, roboto, noto, arial, sans-serif'; - const hasCategories = !hasTimeDimension; + const hasCategories = false; // With Plotly you have choice between one significant digit precision for y axis ticks (.1r) // then on smaller (first digit) ranges you get repeated numbers on ticks. @@ -117,6 +117,7 @@ const createLayout = ( }, ...yaxes, ...xaxes, + hovermode: 'x unified', paper_bgcolor: theme.themeColors.white, plot_bgcolor: graphCustomBackground || theme.themeColors.white, autosize: true, @@ -219,7 +220,7 @@ const createTraces: (params: CreateTracesParams) => TracesOutput = (params) => { allXValues.push(...trace.x); // we have multiple categories in one time point - draw bar groups - if (!hasTimeDimension) { + if (false) { modTrace.x = modTrace.x.map((name) => splitLines(name)); modTrace.type = 'bar'; modTrace.marker = { @@ -233,7 +234,7 @@ const createTraces: (params: CreateTracesParams) => TracesOutput = (params) => { layoutConfig.xaxis!.tickvals = undefined; } // we have one or more categories as time series - draw lines and markers - if (hasTimeDimension) { + if (true) { modTrace.type = 'scatter'; // we fill traces if there is only one trace and area graph is enabled if (traceCount === 1 && useAreaGraph) { @@ -258,7 +259,7 @@ const createTraces: (params: CreateTracesParams) => TracesOutput = (params) => { modTrace.marker = { size: 8, symbol: plotColors.symbols[idx % numSymbols], - color: '#ffffff', + //color: '#ffffff', line: { width: 2, color: plotColors.mainScale[idx % numColors], @@ -390,17 +391,17 @@ function IndicatorGraph(props: IndicatorGraphProps) { trace: theme.graphColors.red070, trend: theme.graphColors.red030, goalScale: [ - theme.graphColors.green070, - theme.graphColors.green030, theme.graphColors.green050, + theme.graphColors.green030, + theme.graphColors.green070, theme.graphColors.green090, theme.graphColors.green010, ], mainScale: [ - theme.graphColors.red070, - theme.graphColors.blue050, + theme.graphColors.blue070, theme.graphColors.yellow030, theme.graphColors.green030, + theme.graphColors.red070, theme.graphColors.blue030, theme.graphColors.yellow070, theme.graphColors.green070, @@ -463,11 +464,7 @@ function IndicatorGraph(props: IndicatorGraphProps) { styleCount = 1; } } - if (!hasTimeDimension) { - // For bar graphs, the red color looks too heavy. - // Shift to blue. - plotColors.mainScale.shift(); - } + const mainTraces = createTraces({ traces, unit: yRange.unit, @@ -543,20 +540,19 @@ function IndicatorGraph(props: IndicatorGraphProps) { name: goalTrace.name, type: 'scatter', cliponaxis: false, - mode: goalTrace.scenario ? 'markers' : 'lines+markers', - ...(!goalTrace.scenario && { - line: { - width: 3, - dash: 'dash', - color: plotColors.goalScale[idx % plotColors.goalScale.length], - }, - }), + mode: 'lines+markers', + + line: { + width: 3, + dash: 'dash', + color: plotColors.goalScale[idx % plotColors.goalScale.length], + }, marker: { size: 12, - symbol: 'x', + symbol: 'circle', color: plotColors.goalScale[idx % plotColors.goalScale.length], }, - opacity: 0.7, + opacity: 0.5, hovertemplate: `(%{x}) ${goalTrace.name}: %{y} ${yRange.unit}`, hoverlabel: { namelength: 0, diff --git a/components/indicators/IndicatorVisualisation.js b/components/indicators/IndicatorVisualisation.js index 53d4fb8d..bbc3ddf2 100644 --- a/components/indicators/IndicatorVisualisation.js +++ b/components/indicators/IndicatorVisualisation.js @@ -228,12 +228,12 @@ function getTraces( if (dimensions.length === 0) { return [ { - xType: cube.length === 1 ? 'category' : 'time', + xType: 'time', name: name, dataType: 'total', x: cube.map((val) => { const d = dayjs(val.date); - return cube.length < 2 ? d.year() : val.date; + return val.date; }), y: cube.map((val) => val.value), }, @@ -609,7 +609,6 @@ function IndicatorVisualisation({ indicatorId, indicatorLink }) { plan: { scenarios }, } = data; - console.log('indicator', data); if (!indicator) return {t('indicator-not-found')}; diff --git a/components/paths/contentblocks/CategoryPageHeaderBlock.tsx b/components/paths/contentblocks/CategoryPageHeaderBlock.tsx index 601f6014..07d6f1db 100644 --- a/components/paths/contentblocks/CategoryPageHeaderBlock.tsx +++ b/components/paths/contentblocks/CategoryPageHeaderBlock.tsx @@ -84,7 +84,8 @@ function CategoryPageHeaderBlock(props: CategoryPageHeaderProps) { ? getBreadcrumbsFromCategoryHierarchy([page.category.parent], false) : []; - // TODO: A better way to find root category list page + /* + // Not needed, leaving this here for reference const rootCategoryListPage = page?.category && page.category.type.id === '76' ? { id: 0, name: 'Bereiche', url: '/klimaschutzplan/bereiche' } @@ -99,6 +100,8 @@ function CategoryPageHeaderBlock(props: CategoryPageHeaderProps) { : null; if (rootCategoryListPage) breadcrumbs.unshift(rootCategoryListPage); if (currentCategoryListPage) breadcrumbs.push(currentCategoryListPage); + */ + return ( diff --git a/components/paths/graphs/IndicatorSparkline.tsx b/components/paths/graphs/IndicatorSparkline.tsx index 4db2c48b..828e1833 100644 --- a/components/paths/graphs/IndicatorSparkline.tsx +++ b/components/paths/graphs/IndicatorSparkline.tsx @@ -216,7 +216,7 @@ const IndicatorSparkline = (props: IndicatorSparklineProps) => { symbol: 'circle', symbolSize: 6, lineStyle: { - color: theme.graphColors.blue050, + color: theme.graphColors.blue070, width: 2, }, z: 2,