From 296a573e4ef8f97850540c8f1416879b8d4fcdab Mon Sep 17 00:00:00 2001 From: kunkoala Date: Thu, 3 Jul 2025 13:52:22 +0200 Subject: [PATCH 01/11] :tada: save max value into useMemo for use --- .../LineChartComponents/LineChart.tsx | 10 ++++++- src/components/LineChartContainer.tsx | 26 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/components/LineChartComponents/LineChart.tsx b/src/components/LineChartComponents/LineChart.tsx index a737afe9..5bf27757 100644 --- a/src/components/LineChartComponents/LineChart.tsx +++ b/src/components/LineChartComponents/LineChart.tsx @@ -70,6 +70,9 @@ interface LineChartProps { /** Optional horizontal limit for the Y-axis. Defaults to 0. */ horizontalYAxisThreshold?: number; + + /** Optional maximum value from the chart data. Can be used to set custom Y-axis limits. */ + maxDataValue?: number; } /** * React Component to render the Linechart Section @@ -88,6 +91,7 @@ export default function LineChart({ yAxisLabel, localization, horizontalYAxisThreshold = undefined, + maxDataValue, }: LineChartProps): JSX.Element { const {t: defaultT, i18n} = useTranslation(); @@ -173,9 +177,13 @@ export default function LineChart({ // Fix lower end to 0 min: 0, // Add tooltip instance so cursor can display value + + //here we can set the max value of the y-axis, if we want to limit the y-axis to a certain value + max: maxDataValue, + tooltip: Tooltip.new(root, {}), }; - }, [root, chart]); + }, [root, chart, maxDataValue]); const yAxis = useValueAxis(root, chart, yAxisSettings); diff --git a/src/components/LineChartContainer.tsx b/src/components/LineChartContainer.tsx index f9420bd6..f4ed9438 100644 --- a/src/components/LineChartContainer.tsx +++ b/src/components/LineChartContainer.tsx @@ -153,6 +153,31 @@ export default function LineChartContainer() { }); }, [groupFilterLineChartData, groupFilters, lineChartData, scenarios, scenariosState, selectedScenario]); + // Calculate maximum value from chart data + const maxDataValue = useMemo(() => { + if (!mappedLineChartData || mappedLineChartData.length === 0) { + return 0; + } + + let maxValue = 0; + + mappedLineChartData.forEach((serie) => { + serie.values.forEach((entry) => { + // Check main value + if (entry.value > maxValue) { + maxValue = entry.value; + } + + // Check openValue if it exists (for percentile bands) + if (entry.openValue && entry.openValue > maxValue) { + maxValue = entry.openValue; + } + }); + }); + + return maxValue; + }, [mappedLineChartData]); + // Set reference day in store useEffect(() => { dispatch(setReferenceDayBottom(referenceDayBottomPosition)); @@ -175,6 +200,7 @@ export default function LineChartContainer() { referenceDay={referenceDay} yAxisLabel={yAxisLabel} horizontalYAxisThreshold={thresholds[`${selectedDistrict.nuts}-${selectedCompartment}`]?.threshold} + maxDataValue={maxDataValue} /> Date: Mon, 7 Jul 2025 12:23:38 +0200 Subject: [PATCH 02/11] :tada: add text input to chart settings to change yAxis max value - Still have some rendering problems - TODO on the LineChart.tsx --- .../LineChartComponents/LineChart.tsx | 7 +- .../LineChartSettings.tsx | 34 +++++++-- .../yAxisValueSettings/yAxisValueSettings.tsx | 69 +++++++++++++++++++ src/components/LineChartContainer.tsx | 19 ++++- .../shared/LineChart/ChartMaxValue.ts | 0 src/store/UserPreferenceSlice.ts | 13 ++++ 6 files changed, 130 insertions(+), 12 deletions(-) create mode 100644 src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx create mode 100644 src/components/shared/LineChart/ChartMaxValue.ts diff --git a/src/components/LineChartComponents/LineChart.tsx b/src/components/LineChartComponents/LineChart.tsx index 5bf27757..7a94fd99 100644 --- a/src/components/LineChartComponents/LineChart.tsx +++ b/src/components/LineChartComponents/LineChart.tsx @@ -169,17 +169,18 @@ export default function LineChart({ ); const yAxisSettings = useMemo(() => { - if (!root || !chart) { + if (!root || !chart || chart.isDisposed() || root.isDisposed()) { return null; } return { renderer: AxisRendererY.new(root, {}), + + strictMinMax: true, // Fix lower end to 0 min: 0, // Add tooltip instance so cursor can display value - //here we can set the max value of the y-axis, if we want to limit the y-axis to a certain value - max: maxDataValue, + max: maxDataValue ?? undefined, tooltip: Tooltip.new(root, {}), }; diff --git a/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx b/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx index 95df8bf6..8d77a39e 100644 --- a/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx +++ b/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx @@ -12,16 +12,18 @@ import IconButton from '@mui/material/IconButton'; import CloseIcon from '@mui/icons-material/Close'; import ArrowBackIosNewIcon from '@mui/icons-material/ArrowBackIosNew'; import DataThresholdingIcon from '@mui/icons-material/DataThresholdingRounded'; +import HorizontalRuleIcon from '@mui/icons-material/HorizontalRule'; import type {Threshold} from 'types/threshold'; import type {District} from 'types/district'; import {useTranslation} from 'react-i18next'; import ThresholdSettings from './ThresholdSettings/ThresholdSettings'; +import YAxisValueSettings from './yAxisValueSettings/yAxisValueSettings'; /** * The different views that can be displayed in the settings popover. * You can add more views here if you want to add more settings. */ -type SettingsView = 'settingsMenu' | 'thresholdSettings' | 'filters'; +type SettingsView = 'settingsMenu' | 'thresholdSettings' | 'yAxisMaxValueSettings'; type SettingsMenu = { [key: string]: { @@ -49,6 +51,12 @@ export interface LineChartSettingsProps { /** The function to update a horizontal threshold. */ updateThreshold: (newThreshold: Threshold) => void; + + /** The maximum value for the y-axis. */ + yAxisMaxValue: number; + + /** The function to update the maximum value for the y-axis. */ + updateYAxisMaxValue: (newYAxisMaxValue: number) => void; } /** @@ -63,6 +71,8 @@ export default function LineChartSettings({ thresholds, removeThreshold, updateThreshold, + yAxisMaxValue, + updateYAxisMaxValue, }: LineChartSettingsProps) { const {t: tSettings} = useTranslation('settings'); @@ -81,11 +91,12 @@ export default function LineChartSettings({ /> ), }, - // filters: { - // label: tSettings('manageGroups'), - // view: 'filters', - // icon: , - // }, + yAxisMaxValue: { + label: tSettings('yAxisMaxValue'), + description: tSettings('yAxisMaxValueDescription'), + view: 'yAxisMaxValueSettings', + icon: , + }, }; const [currentView, setCurrentView] = useState('settingsMenu'); @@ -210,6 +221,17 @@ export default function LineChartSettings({ /> )} + {currentView === 'yAxisMaxValueSettings' && ( + + {renderHeader(tSettings('yAxisMaxValue'))} + + + )} ); diff --git a/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx b/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx new file mode 100644 index 00000000..22178332 --- /dev/null +++ b/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx @@ -0,0 +1,69 @@ +import React, {useState} from 'react'; +import Box from '@mui/material/Box'; +import {District} from 'types/district'; +import {TextField, useTheme} from '@mui/material'; +import IconButton from '@mui/material/IconButton'; +import CheckIcon from '@mui/icons-material/Check'; +import CancelIcon from '@mui/icons-material/Cancel'; + +interface YAxisValueSettingsProps { + selectedDistrict: District; + selectedCompartment: string; + yAxisMaxValue: number; + updateYAxisMaxValue: (newYAxisMaxValue: number) => void; +} + +export default function YAxisValueSettings({yAxisMaxValue, updateYAxisMaxValue}: YAxisValueSettingsProps) { + const theme = useTheme(); + const [localYAxisMaxValue, setLocalYAxisMaxValue] = useState(yAxisMaxValue); + const [, setEditingYAxisMaxValue] = useState(false); + const isValid = localYAxisMaxValue !== null && localYAxisMaxValue > 0; + + return ( + + { + const value = e.target.value === '' ? null : Number(e.target.value); + setLocalYAxisMaxValue(value); + }} + /> + + { + if (localYAxisMaxValue === null || localYAxisMaxValue < 0) return; + console.log('localYAxisMaxValue', localYAxisMaxValue); + updateYAxisMaxValue(localYAxisMaxValue); + setEditingYAxisMaxValue(false); + console.log('UPDATE Y-AXIS MAX VALUE'); + }} + disabled={!isValid} + sx={{color: theme.palette.success.main}} + > + + + { + setEditingYAxisMaxValue(false); + }} + sx={{color: theme.palette.error.main}} + > + + + + + ); +} diff --git a/src/components/LineChartContainer.tsx b/src/components/LineChartContainer.tsx index f4ed9438..25938ded 100644 --- a/src/components/LineChartContainer.tsx +++ b/src/components/LineChartContainer.tsx @@ -13,8 +13,11 @@ import {useTranslation} from 'react-i18next'; import {LineChartData} from 'types/lineChart'; import {InfectionData} from 'store/services/APITypes'; import {DataContext} from 'context/SelectedDataContext'; -import {updateHorizontalYAxisThreshold, removeHorizontalYAxisThreshold} from 'store/UserPreferenceSlice'; - +import { + updateHorizontalYAxisThreshold, + removeHorizontalYAxisThreshold, + setYAxisMaxValue, +} from 'store/UserPreferenceSlice'; export default function LineChartContainer() { const {t: tBackend, i18n: i18nBackend} = useTranslation('backend'); const theme = useTheme(); @@ -28,6 +31,7 @@ export default function LineChartContainer() { const selectedDistrict = useAppSelector((state) => state.dataSelection.district); const selectedDate = useAppSelector((state) => state.dataSelection.date); const thresholds = useAppSelector((state) => state.userPreference.horizontalYAxisThresholds ?? {}); + const yAxisMaxValue = useAppSelector((state) => state.userPreference.yAxisMaxValue ?? {}); const referenceDay = useAppSelector((state) => state.dataSelection.simulationStart); const minDate = useAppSelector((state) => state.dataSelection.minDate); const maxDate = useAppSelector((state) => state.dataSelection.maxDate); @@ -200,7 +204,7 @@ export default function LineChartContainer() { referenceDay={referenceDay} yAxisLabel={yAxisLabel} horizontalYAxisThreshold={thresholds[`${selectedDistrict.nuts}-${selectedCompartment}`]?.threshold} - maxDataValue={maxDataValue} + maxDataValue={yAxisMaxValue[`${selectedDistrict.nuts}-${selectedCompartment}`] ?? undefined} /> + dispatch( + setYAxisMaxValue({ + key: `${selectedDistrict.nuts}-${selectedCompartment}`, + value: newYAxisMaxValue, + }) + ) + } /> ); diff --git a/src/components/shared/LineChart/ChartMaxValue.ts b/src/components/shared/LineChart/ChartMaxValue.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/store/UserPreferenceSlice.ts b/src/store/UserPreferenceSlice.ts index 98d9ca49..6bd01e36 100644 --- a/src/store/UserPreferenceSlice.ts +++ b/src/store/UserPreferenceSlice.ts @@ -10,6 +10,7 @@ export interface UserPreference { selectedTab?: string; isInitialVisit: boolean; horizontalYAxisThresholds?: Record; + yAxisMaxValue?: Record; scenarioColors: Record; } @@ -26,6 +27,7 @@ const initialState: UserPreference = { selectedTab: '1', isInitialVisit: true, horizontalYAxisThresholds: {}, + yAxisMaxValue: {}, scenarioColors: {}, }; @@ -81,6 +83,16 @@ export const UserPreferenceSlice = createSlice({ } delete state.horizontalYAxisThresholds[action.payload]; }, + /** Set the maximum value for the Y-axis */ + setYAxisMaxValue(state, action: PayloadAction<{key: string; value: number}>) { + if (!state.yAxisMaxValue) { + state.yAxisMaxValue = {}; + } + state.yAxisMaxValue = { + ...state.yAxisMaxValue, + [action.payload.key]: action.payload.value, + }; + }, }, }); @@ -92,6 +104,7 @@ export const { updateHorizontalYAxisThreshold, removeHorizontalYAxisThreshold, setScenarioColors, + setYAxisMaxValue, } = UserPreferenceSlice.actions; export default UserPreferenceSlice.reducer; From 89289b46da62688152fda4c4715486858a196ea0 Mon Sep 17 00:00:00 2001 From: kunkoala Date: Mon, 14 Jul 2025 12:37:52 +0200 Subject: [PATCH 03/11] :wrench: fix yAxis not updating --- src/components/LineChartComponents/LineChart.tsx | 12 ++++++++++++ src/components/shared/LineChart/ChartMaxValue.ts | 0 2 files changed, 12 insertions(+) delete mode 100644 src/components/shared/LineChart/ChartMaxValue.ts diff --git a/src/components/LineChartComponents/LineChart.tsx b/src/components/LineChartComponents/LineChart.tsx index 7a94fd99..f761959b 100644 --- a/src/components/LineChartComponents/LineChart.tsx +++ b/src/components/LineChartComponents/LineChart.tsx @@ -178,6 +178,7 @@ export default function LineChart({ strictMinMax: true, // Fix lower end to 0 min: 0, + // Add tooltip instance so cursor can display value max: maxDataValue ?? undefined, @@ -188,6 +189,17 @@ export default function LineChart({ const yAxis = useValueAxis(root, chart, yAxisSettings); + // max value y-axis change so that its not recreated everytime max value changes + useLayoutEffect(() => { + if (!yAxis || !root || !chart || chart.isDisposed() || root.isDisposed()) return; + + if (maxDataValue != null) { + yAxis.set('max', maxDataValue); + } else { + yAxis.set('max', undefined); + } + }, [yAxis, maxDataValue, root, chart]); + // Effect to add cursor to chart useLayoutEffect(() => { if (!chart || !root || !xAxis || chart.isDisposed() || root.isDisposed() || xAxis.isDisposed()) { diff --git a/src/components/shared/LineChart/ChartMaxValue.ts b/src/components/shared/LineChart/ChartMaxValue.ts deleted file mode 100644 index e69de29b..00000000 From 84ee36c542a6b98c8f21a4d3256df8be4151ccb1 Mon Sep 17 00:00:00 2001 From: kunkoala Date: Thu, 17 Jul 2025 12:35:26 +0200 Subject: [PATCH 04/11] :tada: line chart updates when updating y-axis --- src/components/LineChartComponents/LineChart.tsx | 6 +----- src/components/LineChartContainer.tsx | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/components/LineChartComponents/LineChart.tsx b/src/components/LineChartComponents/LineChart.tsx index f761959b..a231808e 100644 --- a/src/components/LineChartComponents/LineChart.tsx +++ b/src/components/LineChartComponents/LineChart.tsx @@ -179,13 +179,9 @@ export default function LineChart({ // Fix lower end to 0 min: 0, - // Add tooltip instance so cursor can display value - - max: maxDataValue ?? undefined, - tooltip: Tooltip.new(root, {}), }; - }, [root, chart, maxDataValue]); + }, [root, chart]); const yAxis = useValueAxis(root, chart, yAxisSettings); diff --git a/src/components/LineChartContainer.tsx b/src/components/LineChartContainer.tsx index 25938ded..a55518e0 100644 --- a/src/components/LineChartContainer.tsx +++ b/src/components/LineChartContainer.tsx @@ -179,7 +179,7 @@ export default function LineChartContainer() { }); }); - return maxValue; + return Math.ceil(maxValue); }, [mappedLineChartData]); // Set reference day in store @@ -220,7 +220,7 @@ export default function LineChartContainer() { }) ) } - yAxisMaxValue={yAxisMaxValue[`${selectedDistrict.nuts}-${selectedCompartment}`]} + yAxisMaxValue={yAxisMaxValue[`${selectedDistrict.nuts}-${selectedCompartment}`] ?? maxDataValue} updateYAxisMaxValue={(newYAxisMaxValue: number) => dispatch( setYAxisMaxValue({ From 3f8cd2a5826301109693304bfb2b342a8bb9d06c Mon Sep 17 00:00:00 2001 From: kunkoala Date: Thu, 17 Jul 2025 12:35:41 +0200 Subject: [PATCH 05/11] :tada: added number formatter for placeholder --- .../LineChartSettings.tsx | 13 ++++++++++++- .../yAxisValueSettings/yAxisValueSettings.tsx | 17 ++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx b/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx index 8d77a39e..0ef39cd6 100644 --- a/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx +++ b/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2024 German Aerospace Center (DLR) // SPDX-License-Identifier: Apache-2.0 -import React, {useState} from 'react'; +import React, {useMemo, useState} from 'react'; import SettingsIcon from '@mui/icons-material/Settings'; import Popover from '@mui/material/Popover'; import Typography from '@mui/material/Typography'; @@ -18,6 +18,7 @@ import type {District} from 'types/district'; import {useTranslation} from 'react-i18next'; import ThresholdSettings from './ThresholdSettings/ThresholdSettings'; import YAxisValueSettings from './yAxisValueSettings/yAxisValueSettings'; +import {NumberFormatter} from 'util/hooks'; /** * The different views that can be displayed in the settings popover. @@ -75,6 +76,7 @@ export default function LineChartSettings({ updateYAxisMaxValue, }: LineChartSettingsProps) { const {t: tSettings} = useTranslation('settings'); + const {i18n} = useTranslation(); /** * The settings menu for the line chart. Each item in the menu has a label, a view, and an icon. @@ -102,6 +104,14 @@ export default function LineChartSettings({ const [currentView, setCurrentView] = useState('settingsMenu'); const [anchorEl, setAnchorEl] = useState(null); const [showPopover, setShowPopover] = useState(false); + const {formatNumber} = NumberFormatter(i18n.language, 1, 0); + + const localization = useMemo(() => { + return { + formatNumber: formatNumber, + customLang: 'backend', + }; + }, [formatNumber]); const handlePopoverOpen = (event: React.MouseEvent) => { setAnchorEl(event.currentTarget); @@ -229,6 +239,7 @@ export default function LineChartSettings({ selectedCompartment={selectedCompartment} yAxisMaxValue={yAxisMaxValue} updateYAxisMaxValue={updateYAxisMaxValue} + localization={localization} /> )} diff --git a/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx b/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx index 22178332..4e238a6f 100644 --- a/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx +++ b/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx @@ -1,5 +1,6 @@ import React, {useState} from 'react'; import Box from '@mui/material/Box'; +import {Localization} from 'types/localization'; import {District} from 'types/district'; import {TextField, useTheme} from '@mui/material'; import IconButton from '@mui/material/IconButton'; @@ -11,20 +12,34 @@ interface YAxisValueSettingsProps { selectedCompartment: string; yAxisMaxValue: number; updateYAxisMaxValue: (newYAxisMaxValue: number) => void; + localization: Localization; } -export default function YAxisValueSettings({yAxisMaxValue, updateYAxisMaxValue}: YAxisValueSettingsProps) { +export default function YAxisValueSettings({ + yAxisMaxValue, + updateYAxisMaxValue, + localization = { + formatNumber: (value: number) => value.toString(), + customLang: 'global', + overrides: {}, + }, +}: YAxisValueSettingsProps) { const theme = useTheme(); const [localYAxisMaxValue, setLocalYAxisMaxValue] = useState(yAxisMaxValue); const [, setEditingYAxisMaxValue] = useState(false); const isValid = localYAxisMaxValue !== null && localYAxisMaxValue > 0; + function GetFormattedAndTranslatedValues(filteredValues: number): string { + return localization.formatNumber ? localization.formatNumber(filteredValues) : filteredValues.toString(); + } + return ( { const value = e.target.value === '' ? null : Number(e.target.value); From e40487d21ae91ca96abfd42860319e9300af7f64 Mon Sep 17 00:00:00 2001 From: kunkoala Date: Tue, 22 Jul 2025 12:33:59 +0200 Subject: [PATCH 06/11] :tada: :wrench: refactor y-axis max value handling in LineChart components, added reset functionality to reset to current data y-axis max value --- .../LineChartComponents/LineChart.tsx | 12 +- .../LineChartSettings.tsx | 152 ++++++++------- .../yAxisValueSettings/yAxisValueSettings.tsx | 181 +++++++++++++----- src/components/LineChartContainer.tsx | 17 +- src/store/UserPreferenceSlice.ts | 14 +- 5 files changed, 226 insertions(+), 150 deletions(-) diff --git a/src/components/LineChartComponents/LineChart.tsx b/src/components/LineChartComponents/LineChart.tsx index a231808e..c092011d 100644 --- a/src/components/LineChartComponents/LineChart.tsx +++ b/src/components/LineChartComponents/LineChart.tsx @@ -72,7 +72,7 @@ interface LineChartProps { horizontalYAxisThreshold?: number; /** Optional maximum value from the chart data. Can be used to set custom Y-axis limits. */ - maxDataValue?: number; + yAxisMaxValue?: number; } /** * React Component to render the Linechart Section @@ -91,7 +91,7 @@ export default function LineChart({ yAxisLabel, localization, horizontalYAxisThreshold = undefined, - maxDataValue, + yAxisMaxValue, }: LineChartProps): JSX.Element { const {t: defaultT, i18n} = useTranslation(); @@ -174,8 +174,8 @@ export default function LineChart({ } return { renderer: AxisRendererY.new(root, {}), - strictMinMax: true, + // Fix lower end to 0 min: 0, @@ -189,12 +189,12 @@ export default function LineChart({ useLayoutEffect(() => { if (!yAxis || !root || !chart || chart.isDisposed() || root.isDisposed()) return; - if (maxDataValue != null) { - yAxis.set('max', maxDataValue); + if (yAxisMaxValue != null) { + yAxis.set('max', yAxisMaxValue); } else { yAxis.set('max', undefined); } - }, [yAxis, maxDataValue, root, chart]); + }, [yAxis, yAxisMaxValue, root, chart]); // Effect to add cursor to chart useLayoutEffect(() => { diff --git a/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx b/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx index 0ef39cd6..90ca7143 100644 --- a/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx +++ b/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx @@ -12,7 +12,7 @@ import IconButton from '@mui/material/IconButton'; import CloseIcon from '@mui/icons-material/Close'; import ArrowBackIosNewIcon from '@mui/icons-material/ArrowBackIosNew'; import DataThresholdingIcon from '@mui/icons-material/DataThresholdingRounded'; -import HorizontalRuleIcon from '@mui/icons-material/HorizontalRule'; +import ShowChartIcon from '@mui/icons-material/ShowChart'; import type {Threshold} from 'types/threshold'; import type {District} from 'types/district'; import {useTranslation} from 'react-i18next'; @@ -26,14 +26,24 @@ import {NumberFormatter} from 'util/hooks'; */ type SettingsView = 'settingsMenu' | 'thresholdSettings' | 'yAxisMaxValueSettings'; -type SettingsMenu = { - [key: string]: { - label: string; - description: string; - view: string; - icon: JSX.Element; - }; +type NavigationItem = { + kind: 'navigate'; + label?: string; + description: string; + icon: JSX.Element; + view: SettingsView; // 'horizontalThresholdSettings' | ... +}; + +type InlineItem = { + kind: 'inline'; + label?: string; + description?: string; + icon?: JSX.Element; + element: JSX.Element; // the component you want to show inline }; + +type SettingsItem = NavigationItem | InlineItem; + export interface LineChartSettingsProps { /** The district to which the settings apply. */ selectedDistrict: District; @@ -54,7 +64,10 @@ export interface LineChartSettingsProps { updateThreshold: (newThreshold: Threshold) => void; /** The maximum value for the y-axis. */ - yAxisMaxValue: number; + yAxisMaxValue: number | undefined; + + /** The maximum value for the data. */ + maxDataValue: number; /** The function to update the maximum value for the y-axis. */ updateYAxisMaxValue: (newYAxisMaxValue: number) => void; @@ -73,38 +86,17 @@ export default function LineChartSettings({ removeThreshold, updateThreshold, yAxisMaxValue, + maxDataValue, updateYAxisMaxValue, }: LineChartSettingsProps) { const {t: tSettings} = useTranslation('settings'); const {i18n} = useTranslation(); + const {formatNumber} = NumberFormatter(i18n.language, 1, 0); - /** - * The settings menu for the line chart. Each item in the menu has a label, a view, and an icon. - */ - - const settingsMenu: SettingsMenu = { - threshold: { - label: tSettings('manageThreshold'), - description: tSettings('manageThresholdDescription'), - view: 'thresholdSettings', - icon: ( - - ), - }, - yAxisMaxValue: { - label: tSettings('yAxisMaxValue'), - description: tSettings('yAxisMaxValueDescription'), - view: 'yAxisMaxValueSettings', - icon: , - }, - }; const [currentView, setCurrentView] = useState('settingsMenu'); const [anchorEl, setAnchorEl] = useState(null); const [showPopover, setShowPopover] = useState(false); - const {formatNumber} = NumberFormatter(i18n.language, 1, 0); const localization = useMemo(() => { return { @@ -113,6 +105,35 @@ export default function LineChartSettings({ }; }, [formatNumber]); + /** + * The settings menu for the line chart. Each item in the menu has a label, a view, and an icon. + */ + + const settingsMenu: SettingsItem[] = [ + { + kind: 'inline', + label: tSettings('yAxisMaxValue'), + element: ( + + + + + ), + }, + { + kind: 'navigate', + label: tSettings('manageThreshold'), + description: tSettings('manageThresholdDescription'), + icon: , + view: 'thresholdSettings', + }, + ]; + const handlePopoverOpen = (event: React.MouseEvent) => { setAnchorEl(event.currentTarget); setShowPopover(true); @@ -183,36 +204,33 @@ export default function LineChartSettings({ {currentView === 'settingsMenu' && ( {renderHeader(tSettings('title'))} - {Object.entries(settingsMenu).map(([key, item]) => ( - - - + {item.icon} + + {item.label} + + {item.description} + + + + ) : ( + {item.element} + )} ))} @@ -231,18 +249,6 @@ export default function LineChartSettings({ /> )} - {currentView === 'yAxisMaxValueSettings' && ( - - {renderHeader(tSettings('yAxisMaxValue'))} - - - )} ); diff --git a/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx b/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx index 4e238a6f..7e3f736a 100644 --- a/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx +++ b/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx @@ -1,22 +1,27 @@ +// SPDX-FileCopyrightText: 2024 German Aerospace Center (DLR) +// SPDX-License-Identifier: Apache-2.0 + import React, {useState} from 'react'; import Box from '@mui/material/Box'; import {Localization} from 'types/localization'; -import {District} from 'types/district'; -import {TextField, useTheme} from '@mui/material'; +import {TextField, Typography, useTheme} from '@mui/material'; +import Tooltip from '@mui/material/Tooltip'; import IconButton from '@mui/material/IconButton'; import CheckIcon from '@mui/icons-material/Check'; import CancelIcon from '@mui/icons-material/Cancel'; +import EditIcon from '@mui/icons-material/Edit'; +import RefreshIcon from '@mui/icons-material/Refresh'; interface YAxisValueSettingsProps { - selectedDistrict: District; - selectedCompartment: string; - yAxisMaxValue: number; + yAxisMaxValue: number | undefined; + maxDataValue: number; updateYAxisMaxValue: (newYAxisMaxValue: number) => void; localization: Localization; } export default function YAxisValueSettings({ yAxisMaxValue, + maxDataValue, updateYAxisMaxValue, localization = { formatNumber: (value: number) => value.toString(), @@ -25,60 +30,136 @@ export default function YAxisValueSettings({ }, }: YAxisValueSettingsProps) { const theme = useTheme(); - const [localYAxisMaxValue, setLocalYAxisMaxValue] = useState(yAxisMaxValue); - const [, setEditingYAxisMaxValue] = useState(false); + const [localYAxisMaxValue, setLocalYAxisMaxValue] = useState(yAxisMaxValue ?? maxDataValue); + const [editing, setEditing] = useState(false); const isValid = localYAxisMaxValue !== null && localYAxisMaxValue > 0; - function GetFormattedAndTranslatedValues(filteredValues: number): string { + const getFormattedAndTranslatedValues = (filteredValues: number): string => { return localization.formatNumber ? localization.formatNumber(filteredValues) : filteredValues.toString(); - } + }; + + const handleSave = () => { + if (localYAxisMaxValue === null || localYAxisMaxValue < 0) return; + console.log('localYAxisMaxValue', localYAxisMaxValue); + updateYAxisMaxValue(localYAxisMaxValue); + setEditing(false); + console.log('UPDATE Y-AXIS MAX VALUE'); + }; + + const handleCancel = () => { + setEditing(false); + setLocalYAxisMaxValue(yAxisMaxValue ?? maxDataValue); + }; + + const handleReset = () => { + updateYAxisMaxValue(maxDataValue); + setLocalYAxisMaxValue(maxDataValue); + }; return ( - - { - const value = e.target.value === '' ? null : Number(e.target.value); - setLocalYAxisMaxValue(value); - }} - /> - - { - if (localYAxisMaxValue === null || localYAxisMaxValue < 0) return; - console.log('localYAxisMaxValue', localYAxisMaxValue); - updateYAxisMaxValue(localYAxisMaxValue); - setEditingYAxisMaxValue(false); - console.log('UPDATE Y-AXIS MAX VALUE'); + + {editing ? ( + - - - { - setEditingYAxisMaxValue(false); + + Y-Axis Maximum + + + { + const value = e.target.value === '' ? null : Number(e.target.value); + setLocalYAxisMaxValue(value); + }} + size='small' + variant='outlined' + /> + + { + e.stopPropagation(); + handleSave(); + }} + disabled={!isValid} + sx={{color: theme.palette.success.main}} + > + + + { + e.stopPropagation(); + handleCancel(); + }} + sx={{color: theme.palette.error.main}} + > + + + + + + ) : ( + - - - + + + Y-Axis Maximum + + + Global maximum value of the y-axis. + + + + + {getFormattedAndTranslatedValues(yAxisMaxValue ?? maxDataValue)} + + + + setEditing(true)}> + + + + + { + e.stopPropagation(); + handleReset(); + }} + > + + + + + + + )} ); } diff --git a/src/components/LineChartContainer.tsx b/src/components/LineChartContainer.tsx index a55518e0..95403ea8 100644 --- a/src/components/LineChartContainer.tsx +++ b/src/components/LineChartContainer.tsx @@ -31,7 +31,7 @@ export default function LineChartContainer() { const selectedDistrict = useAppSelector((state) => state.dataSelection.district); const selectedDate = useAppSelector((state) => state.dataSelection.date); const thresholds = useAppSelector((state) => state.userPreference.horizontalYAxisThresholds ?? {}); - const yAxisMaxValue = useAppSelector((state) => state.userPreference.yAxisMaxValue ?? {}); + const yAxisMaxValue = useAppSelector((state) => state.userPreference.yAxisMaxValue ?? undefined); const referenceDay = useAppSelector((state) => state.dataSelection.simulationStart); const minDate = useAppSelector((state) => state.dataSelection.minDate); const maxDate = useAppSelector((state) => state.dataSelection.maxDate); @@ -204,8 +204,9 @@ export default function LineChartContainer() { referenceDay={referenceDay} yAxisLabel={yAxisLabel} horizontalYAxisThreshold={thresholds[`${selectedDistrict.nuts}-${selectedCompartment}`]?.threshold} - maxDataValue={yAxisMaxValue[`${selectedDistrict.nuts}-${selectedCompartment}`] ?? undefined} + yAxisMaxValue={yAxisMaxValue ?? maxDataValue} /> + - dispatch( - setYAxisMaxValue({ - key: `${selectedDistrict.nuts}-${selectedCompartment}`, - value: newYAxisMaxValue, - }) - ) - } + yAxisMaxValue={yAxisMaxValue} + maxDataValue={maxDataValue} + updateYAxisMaxValue={(newYAxisMaxValue: number) => dispatch(setYAxisMaxValue(newYAxisMaxValue))} /> ); diff --git a/src/store/UserPreferenceSlice.ts b/src/store/UserPreferenceSlice.ts index 6bd01e36..9bfebc7f 100644 --- a/src/store/UserPreferenceSlice.ts +++ b/src/store/UserPreferenceSlice.ts @@ -10,7 +10,7 @@ export interface UserPreference { selectedTab?: string; isInitialVisit: boolean; horizontalYAxisThresholds?: Record; - yAxisMaxValue?: Record; + yAxisMaxValue?: number; scenarioColors: Record; } @@ -27,7 +27,7 @@ const initialState: UserPreference = { selectedTab: '1', isInitialVisit: true, horizontalYAxisThresholds: {}, - yAxisMaxValue: {}, + yAxisMaxValue: undefined, scenarioColors: {}, }; @@ -84,14 +84,8 @@ export const UserPreferenceSlice = createSlice({ delete state.horizontalYAxisThresholds[action.payload]; }, /** Set the maximum value for the Y-axis */ - setYAxisMaxValue(state, action: PayloadAction<{key: string; value: number}>) { - if (!state.yAxisMaxValue) { - state.yAxisMaxValue = {}; - } - state.yAxisMaxValue = { - ...state.yAxisMaxValue, - [action.payload.key]: action.payload.value, - }; + setYAxisMaxValue(state, action: PayloadAction) { + state.yAxisMaxValue = action.payload; }, }, }); From cac046ab619901b86f1e466996ed841a599f8f8b Mon Sep 17 00:00:00 2001 From: kunkoala Date: Fri, 1 Aug 2025 17:05:22 +0200 Subject: [PATCH 07/11] :tada: :wrench: improve y axis maximum input and styling, added locale --- locales/de-settings.json5 | 14 ++ locales/en-settings.json5 | 14 ++ .../LineChartSettings.tsx | 4 +- .../yAxisValueSettings/yAxisValueSettings.tsx | 196 +++++++++++++----- 4 files changed, 174 insertions(+), 54 deletions(-) diff --git a/locales/de-settings.json5 b/locales/de-settings.json5 index 080b5a26..4045c527 100644 --- a/locales/de-settings.json5 +++ b/locales/de-settings.json5 @@ -3,6 +3,8 @@ { title: 'Liniendiagramm Einstellungen', + yAxisMaxValue: 'Y-Achse Maximum', + yAxisMaxValueDescription: 'Setzen Sie den Maximalwert für die Y-Achse', manageGroups: 'Filter', manageGroupsDescription: 'Verwalten Sie Filtergruppen, um spezifische Daten im Diagramm anzuzeigen oder auszublenden.', manageThreshold: 'Schwellwerte', @@ -14,6 +16,18 @@ threshold: 'Schwellwert', noThresholds: 'Keine Schwellwerte festgelegt.', }, + 'y-axis-settings': { + title: 'Y-Achse Maximum', + editTooltip: 'Y-Achse Maximum bearbeiten', + resetTooltip: 'Y-Achse Maximum auf aktuellen Daten-Maximalwert zurücksetzen', + messages: { + success: 'Y-Achse Maximum erfolgreich aktualisiert.', + error: 'Ungültige Eingabe. Bitte überprüfen Sie den Wert.', + }, + validation: { + positiveNumber: 'Wert muss eine positive Zahl sein', + }, + }, 'group-filters': { title: 'Gruppen verwalten', 'nothing-selected': 'Wählen Sie eine Gruppe aus um diese zu bearbeiten oder erstellen Sie eine neue Gruppe.', diff --git a/locales/en-settings.json5 b/locales/en-settings.json5 index fd06d085..aede3f65 100644 --- a/locales/en-settings.json5 +++ b/locales/en-settings.json5 @@ -3,6 +3,8 @@ { title: 'Line Chart Settings', + yAxisMaxValue: 'Y-Axis Maximum', + yAxisMaxValueDescription: 'Set the maximum value for the Y-axis', manageGroups: 'Filters', manageGroupsDescription: 'Set the group filters for each scenario', manageThreshold: 'Thresholds', @@ -14,6 +16,18 @@ threshold: 'Threshold', noThresholds: 'No thresholds set.', }, + 'y-axis-settings': { + title: 'Y-Axis Maximum', + editTooltip: 'Edit Y-Axis Maximum', + resetTooltip: 'Reset Y-Axis maximum value to current data maximum value', + messages: { + success: 'Y-Axis Maximum value updated successfully.', + error: 'Invalid input. Please check the value.', + }, + validation: { + positiveNumber: 'Value must be a positive number', + }, + }, 'group-filters': { title: 'Manage Groups', 'nothing-selected': 'Select a group to edit or create a new one.', diff --git a/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx b/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx index 90ca7143..4a2855f8 100644 --- a/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx +++ b/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx @@ -93,7 +93,6 @@ export default function LineChartSettings({ const {i18n} = useTranslation(); const {formatNumber} = NumberFormatter(i18n.language, 1, 0); - const [currentView, setCurrentView] = useState('settingsMenu'); const [anchorEl, setAnchorEl] = useState(null); const [showPopover, setShowPopover] = useState(false); @@ -107,8 +106,9 @@ export default function LineChartSettings({ /** * The settings menu for the line chart. Each item in the menu has a label, a view, and an icon. + * kind: 'inline' - the item is displayed inline + * kind: 'navigate' - the item is displayed as a button that navigates to a new view */ - const settingsMenu: SettingsItem[] = [ { kind: 'inline', diff --git a/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx b/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx index 7e3f736a..b23031bb 100644 --- a/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx +++ b/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx @@ -4,18 +4,31 @@ import React, {useState} from 'react'; import Box from '@mui/material/Box'; import {Localization} from 'types/localization'; -import {TextField, Typography, useTheme} from '@mui/material'; +import {Button, useTheme} from '@mui/material'; +import TextField from '@mui/material/TextField'; +import Typography from '@mui/material/Typography'; +import Snackbar from '@mui/material/Snackbar'; import Tooltip from '@mui/material/Tooltip'; import IconButton from '@mui/material/IconButton'; import CheckIcon from '@mui/icons-material/Check'; import CancelIcon from '@mui/icons-material/Cancel'; import EditIcon from '@mui/icons-material/Edit'; import RefreshIcon from '@mui/icons-material/Refresh'; - +import Divider from '@mui/material/Divider'; +import Portal from '@mui/material/Portal'; +import Alert from '@mui/material/Alert'; +import {useTranslation} from 'react-i18next'; interface YAxisValueSettingsProps { + /** The maximum value for the Y-axis */ yAxisMaxValue: number | undefined; + + /** The actual maximum value of the currently displayed data on the chart*/ maxDataValue: number; + + /** The function to update the Y-axis maximum value */ updateYAxisMaxValue: (newYAxisMaxValue: number) => void; + + /** The localization object */ localization: Localization; } @@ -30,20 +43,53 @@ export default function YAxisValueSettings({ }, }: YAxisValueSettingsProps) { const theme = useTheme(); + const {t} = useTranslation('settings'); const [localYAxisMaxValue, setLocalYAxisMaxValue] = useState(yAxisMaxValue ?? maxDataValue); const [editing, setEditing] = useState(false); - const isValid = localYAxisMaxValue !== null && localYAxisMaxValue > 0; + const [snackbarOpen, setSnackbarOpen] = useState(false); + const [snackbarMessage, setSnackbarMessage] = useState(''); + const [snackbarSeverity, setSnackbarSeverity] = useState<'success' | 'info' | 'warning' | 'error'>('info'); + const [errors, setErrors] = useState([]); const getFormattedAndTranslatedValues = (filteredValues: number): string => { return localization.formatNumber ? localization.formatNumber(filteredValues) : filteredValues.toString(); }; - const handleSave = () => { - if (localYAxisMaxValue === null || localYAxisMaxValue < 0) return; - console.log('localYAxisMaxValue', localYAxisMaxValue); - updateYAxisMaxValue(localYAxisMaxValue); - setEditing(false); - console.log('UPDATE Y-AXIS MAX VALUE'); + const validateInput = (newYValue: number | null): boolean => { + const errors: string[] = []; + if (newYValue === null || newYValue < 0) { + errors.push(t('y-axis-settings.validation.positiveNumber')); + } + + setErrors(errors); + return errors.length === 0; + }; + + const handleSnackbarOpen = (message: string, severity: 'success' | 'info' | 'warning' | 'error' = 'info') => { + setSnackbarMessage(message); + setSnackbarSeverity(severity); + setSnackbarOpen(true); + }; + + const handleSave = (newYValue: number | null) => { + if (newYValue === null) { + updateYAxisMaxValue(maxDataValue); + setLocalYAxisMaxValue(maxDataValue); + setEditing(false); + return; + } + + if (validateInput(newYValue)) { + if (newYValue === yAxisMaxValue) { + setEditing(false); + return; + } + + updateYAxisMaxValue(newYValue); + setLocalYAxisMaxValue(newYValue); + setEditing(false); + handleSnackbarOpen(t('y-axis-settings.messages.success'), 'success'); + } }; const handleCancel = () => { @@ -57,33 +103,74 @@ export default function YAxisValueSettings({ }; return ( - - {editing ? ( - + + setSnackbarOpen(false)} + anchorOrigin={{vertical: 'bottom', horizontal: 'left'}} + > + {snackbarMessage} + + + + - - Y-Axis Maximum - - + {t('y-axis-settings.title')} + + + + + {editing ? ( + 0} + helperText={errors.join(', ')} onChange={(e) => { + setErrors([]); const value = e.target.value === '' ? null : Number(e.target.value); setLocalYAxisMaxValue(value); }} size='small' variant='outlined' + sx={{width: '100%'}} /> { e.stopPropagation(); - handleSave(); + handleSave(localYAxisMaxValue); }} - disabled={!isValid} + disabled={errors.length > 0} sx={{color: theme.palette.success.main}} > @@ -117,49 +204,54 @@ export default function YAxisValueSettings({ - - ) : ( - - - - Y-Axis Maximum - - - Global maximum value of the y-axis. - - - - - {getFormattedAndTranslatedValues(yAxisMaxValue ?? maxDataValue)} - + ) : ( + + - + setEditing(true)}> - + { e.stopPropagation(); handleReset(); }} + disabled={localYAxisMaxValue === maxDataValue} > - - )} + )} + ); } From 40196bbb4d3fa8ed1167af62b8c5b5499c0f172b Mon Sep 17 00:00:00 2001 From: Moritz Zeumer Date: Mon, 24 Nov 2025 16:47:34 +0100 Subject: [PATCH 08/11] Add changelog entries --- docs/changelog/changelog-de.md | 1 + docs/changelog/changelog-en.md | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/changelog/changelog-de.md b/docs/changelog/changelog-de.md index 778ad5d6..cd7cf70a 100644 --- a/docs/changelog/changelog-de.md +++ b/docs/changelog/changelog-de.md @@ -31,6 +31,7 @@ SPDX-License-Identifier: CC-BY-4.0 - In der Bibliothek, wenn die Maus über eine Karte hovered. - Auf der Hauptseite über den Infobutton unter der Karte. - Angemeldete Admin-Benutzer können jetzt auf die Schaltfläche Admin im Anwendungsmenü klicken und auf die Benutzerverwaltung zugreifen. +- Nutzer können die Skalierung der Y-Achse manuell verändern (Maximalwert einstellen). ### Fehlerbehebungen diff --git a/docs/changelog/changelog-en.md b/docs/changelog/changelog-en.md index c0493277..4b1fce3b 100644 --- a/docs/changelog/changelog-en.md +++ b/docs/changelog/changelog-en.md @@ -31,6 +31,7 @@ SPDX-License-Identifier: CC-BY-4.0 - In the library when hovering over a card with the mouse. - On the main page via the info button below the card. - Logged in admin users can now click on the Admin button in the application menu and access the user management. +- Users can now change the scaling of the Y-Axis by setting a maximum value. ### Bug fixes From f310d779db1b219b3db7bcacf8e254ab029eb1ef Mon Sep 17 00:00:00 2001 From: Moritz Zeumer Date: Mon, 24 Nov 2025 16:48:44 +0100 Subject: [PATCH 09/11] moved changes from improvement to new features --- docs/changelog/changelog-de.md | 2 +- docs/changelog/changelog-en.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/changelog/changelog-de.md b/docs/changelog/changelog-de.md index cd7cf70a..c7b10032 100644 --- a/docs/changelog/changelog-de.md +++ b/docs/changelog/changelog-de.md @@ -18,6 +18,7 @@ SPDX-License-Identifier: CC-BY-4.0 - Nutzer können benutzerdefinierte Schwellenwerte für aktuell ausgewählte Bezirk und Kompartiment festlegen, die über den Einstellungsbutton in der unteren linken Ecke des Liniendiagramms erreicht werden - Die horizontale Schwellenlinie wird als rote Linie im Diagramm angezeigt und Werte über der Schwellenlinie werden in rot angezeigt - Nutzer können Schwellenwerte auswählen, um zu den entsprechenden Bezirk und Kompartiment zu navigieren +- Nutzer können die Skalierung der Y-Achse manuell verändern (Maximalwert einstellen). ### Verbesserungen @@ -31,7 +32,6 @@ SPDX-License-Identifier: CC-BY-4.0 - In der Bibliothek, wenn die Maus über eine Karte hovered. - Auf der Hauptseite über den Infobutton unter der Karte. - Angemeldete Admin-Benutzer können jetzt auf die Schaltfläche Admin im Anwendungsmenü klicken und auf die Benutzerverwaltung zugreifen. -- Nutzer können die Skalierung der Y-Achse manuell verändern (Maximalwert einstellen). ### Fehlerbehebungen diff --git a/docs/changelog/changelog-en.md b/docs/changelog/changelog-en.md index 4b1fce3b..c429c800 100644 --- a/docs/changelog/changelog-en.md +++ b/docs/changelog/changelog-en.md @@ -18,6 +18,7 @@ SPDX-License-Identifier: CC-BY-4.0 - Users can set custom threshold values for currently selected district and compartment accessible via the settings button on the lower left corner of the line chart - The horizontal threshold is displayed as a red horizontal line on the chart and values above the threshold are displayed in red - Users can select thresholds to navigate to the corresponding district and compartment +- Users can now change the scaling of the Y-Axis by setting a maximum value. ### Improvements @@ -31,7 +32,6 @@ SPDX-License-Identifier: CC-BY-4.0 - In the library when hovering over a card with the mouse. - On the main page via the info button below the card. - Logged in admin users can now click on the Admin button in the application menu and access the user management. -- Users can now change the scaling of the Y-Axis by setting a maximum value. ### Bug fixes From f2b1dd710c21afe296e047587a47de617ae71683 Mon Sep 17 00:00:00 2001 From: kunkoala Date: Tue, 25 Nov 2025 15:17:23 +0100 Subject: [PATCH 10/11] :beetle: reset button now set yAxisMaxValue to undefined to enable auto scaling if switching compartments or districts --- .../LineChartSettingsComponents/LineChartSettings.tsx | 2 +- .../yAxisValueSettings/yAxisValueSettings.tsx | 4 ++-- src/components/LineChartContainer.tsx | 2 +- src/store/UserPreferenceSlice.ts | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx b/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx index 4a2855f8..655a0267 100644 --- a/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx +++ b/src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx @@ -70,7 +70,7 @@ export interface LineChartSettingsProps { maxDataValue: number; /** The function to update the maximum value for the y-axis. */ - updateYAxisMaxValue: (newYAxisMaxValue: number) => void; + updateYAxisMaxValue: (newYAxisMaxValue: number | undefined) => void; } /** diff --git a/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx b/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx index b23031bb..d3846da5 100644 --- a/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx +++ b/src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx @@ -26,7 +26,7 @@ interface YAxisValueSettingsProps { maxDataValue: number; /** The function to update the Y-axis maximum value */ - updateYAxisMaxValue: (newYAxisMaxValue: number) => void; + updateYAxisMaxValue: (newYAxisMaxValue: number | undefined) => void; /** The localization object */ localization: Localization; @@ -98,7 +98,7 @@ export default function YAxisValueSettings({ }; const handleReset = () => { - updateYAxisMaxValue(maxDataValue); + updateYAxisMaxValue(undefined); setLocalYAxisMaxValue(maxDataValue); }; diff --git a/src/components/LineChartContainer.tsx b/src/components/LineChartContainer.tsx index 95403ea8..ca144ed1 100644 --- a/src/components/LineChartContainer.tsx +++ b/src/components/LineChartContainer.tsx @@ -223,7 +223,7 @@ export default function LineChartContainer() { } yAxisMaxValue={yAxisMaxValue} maxDataValue={maxDataValue} - updateYAxisMaxValue={(newYAxisMaxValue: number) => dispatch(setYAxisMaxValue(newYAxisMaxValue))} + updateYAxisMaxValue={(newYAxisMaxValue: number | undefined) => dispatch(setYAxisMaxValue(newYAxisMaxValue))} /> ); diff --git a/src/store/UserPreferenceSlice.ts b/src/store/UserPreferenceSlice.ts index 9bfebc7f..00e908fb 100644 --- a/src/store/UserPreferenceSlice.ts +++ b/src/store/UserPreferenceSlice.ts @@ -10,7 +10,7 @@ export interface UserPreference { selectedTab?: string; isInitialVisit: boolean; horizontalYAxisThresholds?: Record; - yAxisMaxValue?: number; + yAxisMaxValue?: number | undefined; scenarioColors: Record; } @@ -84,7 +84,7 @@ export const UserPreferenceSlice = createSlice({ delete state.horizontalYAxisThresholds[action.payload]; }, /** Set the maximum value for the Y-axis */ - setYAxisMaxValue(state, action: PayloadAction) { + setYAxisMaxValue(state, action: PayloadAction) { state.yAxisMaxValue = action.payload; }, }, From fce964b7ebef8ecfd427bef429231848153c8cea Mon Sep 17 00:00:00 2001 From: kunkoala Date: Tue, 25 Nov 2025 15:21:01 +0100 Subject: [PATCH 11/11] :wrench: apply suggested changes --- locales/de-settings.json5 | 2 +- src/components/LineChartComponents/LineChart.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/de-settings.json5 b/locales/de-settings.json5 index 4045c527..066796d6 100644 --- a/locales/de-settings.json5 +++ b/locales/de-settings.json5 @@ -25,7 +25,7 @@ error: 'Ungültige Eingabe. Bitte überprüfen Sie den Wert.', }, validation: { - positiveNumber: 'Wert muss eine positive Zahl sein', + positiveNumber: 'Der Wert muss eine positive Zahl sein', }, }, 'group-filters': { diff --git a/src/components/LineChartComponents/LineChart.tsx b/src/components/LineChartComponents/LineChart.tsx index c092011d..23907b0c 100644 --- a/src/components/LineChartComponents/LineChart.tsx +++ b/src/components/LineChartComponents/LineChart.tsx @@ -178,7 +178,7 @@ export default function LineChart({ // Fix lower end to 0 min: 0, - + // Add tooltip instance so cursor can display value tooltip: Tooltip.new(root, {}), }; }, [root, chart]);