Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/changelog/changelog-de.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions docs/changelog/changelog-en.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
14 changes: 14 additions & 0 deletions locales/de-settings.json5
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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: 'Der 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.',
Expand Down
14 changes: 14 additions & 0 deletions locales/en-settings.json5
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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.',
Expand Down
19 changes: 18 additions & 1 deletion src/components/LineChartComponents/LineChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
yAxisMaxValue?: number;
}
/**
* React Component to render the Linechart Section
Expand All @@ -88,6 +91,7 @@ export default function LineChart({
yAxisLabel,
localization,
horizontalYAxisThreshold = undefined,
yAxisMaxValue,
}: LineChartProps): JSX.Element {
const {t: defaultT, i18n} = useTranslation();

Expand Down Expand Up @@ -165,11 +169,13 @@ 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
Expand All @@ -179,6 +185,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 (yAxisMaxValue != null) {
yAxis.set('max', yAxisMaxValue);
} else {
yAxis.set('max', undefined);
}
}, [yAxis, yAxisMaxValue, root, chart]);

// Effect to add cursor to chart
useLayoutEffect(() => {
if (!chart || !root || !xAxis || chart.isDisposed() || root.isDisposed() || xAxis.isDisposed()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -12,25 +12,38 @@ 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 ShowChartIcon from '@mui/icons-material/ShowChart';
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';
import {NumberFormatter} from 'util/hooks';

/**
* 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 SettingsMenu = {
[key: string]: {
label: string;
description: string;
view: string;
icon: JSX.Element;
};
type SettingsView = 'settingsMenu' | 'thresholdSettings' | 'yAxisMaxValueSettings';

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;
Expand All @@ -49,6 +62,15 @@ export interface LineChartSettingsProps {

/** The function to update a horizontal threshold. */
updateThreshold: (newThreshold: Threshold) => void;

/** The maximum value for the y-axis. */
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 | undefined) => void;
}

/**
Expand All @@ -63,34 +85,54 @@ export default function LineChartSettings({
thresholds,
removeThreshold,
updateThreshold,
yAxisMaxValue,
maxDataValue,
updateYAxisMaxValue,
}: LineChartSettingsProps) {
const {t: tSettings} = useTranslation('settings');
const {i18n} = useTranslation();
const {formatNumber} = NumberFormatter(i18n.language, 1, 0);

const [currentView, setCurrentView] = useState<SettingsView>('settingsMenu');
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [showPopover, setShowPopover] = useState<boolean>(false);

const localization = useMemo(() => {
return {
formatNumber: formatNumber,
customLang: 'backend',
};
}, [formatNumber]);

/**
* 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: SettingsMenu = {
threshold: {
const settingsMenu: SettingsItem[] = [
{
kind: 'inline',
label: tSettings('yAxisMaxValue'),
element: (
<Box sx={{display: 'flex', p: 2, alignItems: 'center'}}>
<ShowChartIcon sx={{bgcolor: 'primary.main', color: 'white', p: '4px', borderRadius: '10%'}} />
<YAxisValueSettings
yAxisMaxValue={yAxisMaxValue}
maxDataValue={maxDataValue}
updateYAxisMaxValue={updateYAxisMaxValue}
localization={localization}
/>
</Box>
),
},
{
kind: 'navigate',
label: tSettings('manageThreshold'),
description: tSettings('manageThresholdDescription'),
icon: <DataThresholdingIcon sx={{bgcolor: 'primary.main', color: 'white', p: '4px', borderRadius: '10%'}} />,
view: 'thresholdSettings',
icon: (
<DataThresholdingIcon
sx={{backgroundColor: 'primary.main', color: 'white', padding: '4px', borderRadius: '10%'}}
/>
),
},
// filters: {
// label: tSettings('manageGroups'),
// view: 'filters',
// icon: <HorizontalRuleIcon />,
// },
};

const [currentView, setCurrentView] = useState<SettingsView>('settingsMenu');
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [showPopover, setShowPopover] = useState<boolean>(false);
];

const handlePopoverOpen = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
Expand Down Expand Up @@ -162,36 +204,33 @@ export default function LineChartSettings({
{currentView === 'settingsMenu' && (
<Box p={4} data-testid='main-settings-menu'>
{renderHeader(tSettings('title'))}
{Object.entries(settingsMenu).map(([key, item]) => (
<Box key={key}>
<Divider sx={{marginY: 2}} variant='middle' />
<Button
data-testid={`settings-menu-item-${key}`}
onClick={() => handleNavigate(item.view as SettingsView)}
sx={{
display: 'flex',
flexDirection: 'row',
width: '100%',
justifyContent: 'flex-start',
alignContent: 'center',
}}
>
{item.icon}
<Box
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start',
justifyContent: 'center',
marginLeft: 4,
}}
{settingsMenu.map((item, idx) => (
<Box key={idx}>
<Divider sx={{my: '10px'}} variant='middle' />
{item.kind === 'navigate' ? (
<Button
onClick={() => handleNavigate(item.view)}
sx={{display: 'flex', width: '100%', justifyContent: 'flex-start'}}
>
<Typography variant='h2'>{item.label}</Typography>
<Typography variant='body1' sx={{textTransform: 'none', color: 'gray'}}>
{item.description}
</Typography>
</Box>
</Button>
{item.icon}
<Box
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start',
justifyContent: 'center',
marginLeft: 4,
}}
>
<Typography variant='h2'>{item.label}</Typography>
<Typography variant='body1' sx={{textTransform: 'none', color: 'gray'}}>
{item.description}
</Typography>
</Box>
</Button>
) : (
<Box>{item.element}</Box>
)}
</Box>
))}
</Box>
Expand Down
Loading
Loading