Skip to content

Commit 919af35

Browse files
committed
🎉 🔧 improve y axis maximum input and styling, added locale
1 parent 3540651 commit 919af35

File tree

4 files changed

+174
-54
lines changed

4 files changed

+174
-54
lines changed

locales/de-settings.json5

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
{
55
title: 'Liniendiagramm Einstellungen',
6+
yAxisMaxValue: 'Y-Achse Maximum',
7+
yAxisMaxValueDescription: 'Setzen Sie den Maximalwert für die Y-Achse',
68
manageGroups: 'Filter',
79
manageGroupsDescription: 'Verwalten Sie Filtergruppen, um spezifische Daten im Diagramm anzuzeigen oder auszublenden.',
810
manageThreshold: 'Schwellwerte',
@@ -14,6 +16,18 @@
1416
threshold: 'Schwellwert',
1517
noThresholds: 'Keine Schwellwerte festgelegt.',
1618
},
19+
'y-axis-settings': {
20+
title: 'Y-Achse Maximum',
21+
editTooltip: 'Y-Achse Maximum bearbeiten',
22+
resetTooltip: 'Y-Achse Maximum auf aktuellen Daten-Maximalwert zurücksetzen',
23+
messages: {
24+
success: 'Y-Achse Maximum erfolgreich aktualisiert.',
25+
error: 'Ungültige Eingabe. Bitte überprüfen Sie den Wert.',
26+
},
27+
validation: {
28+
positiveNumber: 'Wert muss eine positive Zahl sein',
29+
},
30+
},
1731
'group-filters': {
1832
title: 'Gruppen verwalten',
1933
'nothing-selected': 'Wählen Sie eine Gruppe aus um diese zu bearbeiten oder erstellen Sie eine neue Gruppe.',

locales/en-settings.json5

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
{
55
title: 'Line Chart Settings',
6+
yAxisMaxValue: 'Y-Axis Maximum',
7+
yAxisMaxValueDescription: 'Set the maximum value for the Y-axis',
68
manageGroups: 'Filters',
79
manageGroupsDescription: 'Set the group filters for each scenario',
810
manageThreshold: 'Thresholds',
@@ -14,6 +16,18 @@
1416
threshold: 'Threshold',
1517
noThresholds: 'No thresholds set.',
1618
},
19+
'y-axis-settings': {
20+
title: 'Y-Axis Maximum',
21+
editTooltip: 'Edit Y-Axis Maximum',
22+
resetTooltip: 'Reset Y-Axis maximum value to current data maximum value',
23+
messages: {
24+
success: 'Y-Axis Maximum value updated successfully.',
25+
error: 'Invalid input. Please check the value.',
26+
},
27+
validation: {
28+
positiveNumber: 'Value must be a positive number',
29+
},
30+
},
1731
'group-filters': {
1832
title: 'Manage Groups',
1933
'nothing-selected': 'Select a group to edit or create a new one.',

src/components/LineChartComponents/LineChartSettingsComponents/LineChartSettings.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ export default function LineChartSettings({
9393
const {i18n} = useTranslation();
9494
const {formatNumber} = NumberFormatter(i18n.language, 1, 0);
9595

96-
9796
const [currentView, setCurrentView] = useState<SettingsView>('settingsMenu');
9897
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
9998
const [showPopover, setShowPopover] = useState<boolean>(false);
@@ -107,8 +106,9 @@ export default function LineChartSettings({
107106

108107
/**
109108
* The settings menu for the line chart. Each item in the menu has a label, a view, and an icon.
109+
* kind: 'inline' - the item is displayed inline
110+
* kind: 'navigate' - the item is displayed as a button that navigates to a new view
110111
*/
111-
112112
const settingsMenu: SettingsItem[] = [
113113
{
114114
kind: 'inline',

src/components/LineChartComponents/LineChartSettingsComponents/yAxisValueSettings/yAxisValueSettings.tsx

Lines changed: 144 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,31 @@
44
import React, {useState} from 'react';
55
import Box from '@mui/material/Box';
66
import {Localization} from 'types/localization';
7-
import {TextField, Typography, useTheme} from '@mui/material';
7+
import {Button, useTheme} from '@mui/material';
8+
import TextField from '@mui/material/TextField';
9+
import Typography from '@mui/material/Typography';
10+
import Snackbar from '@mui/material/Snackbar';
811
import Tooltip from '@mui/material/Tooltip';
912
import IconButton from '@mui/material/IconButton';
1013
import CheckIcon from '@mui/icons-material/Check';
1114
import CancelIcon from '@mui/icons-material/Cancel';
1215
import EditIcon from '@mui/icons-material/Edit';
1316
import RefreshIcon from '@mui/icons-material/Refresh';
14-
17+
import Divider from '@mui/material/Divider';
18+
import Portal from '@mui/material/Portal';
19+
import Alert from '@mui/material/Alert';
20+
import {useTranslation} from 'react-i18next';
1521
interface YAxisValueSettingsProps {
22+
/** The maximum value for the Y-axis */
1623
yAxisMaxValue: number | undefined;
24+
25+
/** The actual maximum value of the currently displayed data on the chart*/
1726
maxDataValue: number;
27+
28+
/** The function to update the Y-axis maximum value */
1829
updateYAxisMaxValue: (newYAxisMaxValue: number) => void;
30+
31+
/** The localization object */
1932
localization: Localization;
2033
}
2134

@@ -30,20 +43,53 @@ export default function YAxisValueSettings({
3043
},
3144
}: YAxisValueSettingsProps) {
3245
const theme = useTheme();
46+
const {t} = useTranslation('settings');
3347
const [localYAxisMaxValue, setLocalYAxisMaxValue] = useState<number | null>(yAxisMaxValue ?? maxDataValue);
3448
const [editing, setEditing] = useState<boolean>(false);
35-
const isValid = localYAxisMaxValue !== null && localYAxisMaxValue > 0;
49+
const [snackbarOpen, setSnackbarOpen] = useState<boolean>(false);
50+
const [snackbarMessage, setSnackbarMessage] = useState<string>('');
51+
const [snackbarSeverity, setSnackbarSeverity] = useState<'success' | 'info' | 'warning' | 'error'>('info');
52+
const [errors, setErrors] = useState<string[]>([]);
3653

3754
const getFormattedAndTranslatedValues = (filteredValues: number): string => {
3855
return localization.formatNumber ? localization.formatNumber(filteredValues) : filteredValues.toString();
3956
};
4057

41-
const handleSave = () => {
42-
if (localYAxisMaxValue === null || localYAxisMaxValue < 0) return;
43-
console.log('localYAxisMaxValue', localYAxisMaxValue);
44-
updateYAxisMaxValue(localYAxisMaxValue);
45-
setEditing(false);
46-
console.log('UPDATE Y-AXIS MAX VALUE');
58+
const validateInput = (newYValue: number | null): boolean => {
59+
const errors: string[] = [];
60+
if (newYValue === null || newYValue < 0) {
61+
errors.push(t('y-axis-settings.validation.positiveNumber'));
62+
}
63+
64+
setErrors(errors);
65+
return errors.length === 0;
66+
};
67+
68+
const handleSnackbarOpen = (message: string, severity: 'success' | 'info' | 'warning' | 'error' = 'info') => {
69+
setSnackbarMessage(message);
70+
setSnackbarSeverity(severity);
71+
setSnackbarOpen(true);
72+
};
73+
74+
const handleSave = (newYValue: number | null) => {
75+
if (newYValue === null) {
76+
updateYAxisMaxValue(maxDataValue);
77+
setLocalYAxisMaxValue(maxDataValue);
78+
setEditing(false);
79+
return;
80+
}
81+
82+
if (validateInput(newYValue)) {
83+
if (newYValue === yAxisMaxValue) {
84+
setEditing(false);
85+
return;
86+
}
87+
88+
updateYAxisMaxValue(newYValue);
89+
setLocalYAxisMaxValue(newYValue);
90+
setEditing(false);
91+
handleSnackbarOpen(t('y-axis-settings.messages.success'), 'success');
92+
}
4793
};
4894

4995
const handleCancel = () => {
@@ -57,33 +103,74 @@ export default function YAxisValueSettings({
57103
};
58104

59105
return (
60-
<Box sx={{width: '100%', marginLeft: 4}}>
61-
{editing ? (
62-
<Box
106+
<Box
107+
sx={{
108+
width: '100%',
109+
marginLeft: 4,
110+
display: 'flex',
111+
flexDirection: 'row',
112+
alignItems: 'center',
113+
gap: 4,
114+
}}
115+
>
116+
<Portal>
117+
<Snackbar
118+
open={snackbarOpen}
119+
autoHideDuration={4000}
120+
onClose={() => setSnackbarOpen(false)}
121+
anchorOrigin={{vertical: 'bottom', horizontal: 'left'}}
122+
>
123+
<Alert severity={snackbarSeverity}>{snackbarMessage}</Alert>
124+
</Snackbar>
125+
</Portal>
126+
<Box sx={{display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 2}}>
127+
<Typography
128+
variant='h2'
63129
sx={{
64-
display: 'flex',
65-
flexDirection: 'row',
66-
gap: 1,
67-
alignItems: 'center',
68-
justifyContent: 'space-between',
130+
color: theme.palette.primary.main,
131+
textTransform: 'uppercase',
132+
paddingRight: 2,
69133
}}
70134
>
71-
<Typography variant='h2' sx={{color: 'black'}}>
72-
Y-Axis Maximum
73-
</Typography>
74-
<Box sx={{display: 'flex', flexDirection: 'row', gap: 1, alignItems: 'center'}}>
135+
{t('y-axis-settings.title')}
136+
</Typography>
137+
</Box>
138+
<Divider orientation='vertical' flexItem />
139+
<Box
140+
sx={{
141+
display: 'flex',
142+
flexDirection: 'row',
143+
gap: 1,
144+
flex: 1,
145+
alignItems: 'center',
146+
justifyContent: 'space-between',
147+
}}
148+
>
149+
{editing ? (
150+
<Box
151+
sx={{
152+
display: 'flex',
153+
flexDirection: 'row',
154+
gap: 3,
155+
alignItems: 'center',
156+
width: '100%',
157+
justifyContent: 'space-between',
158+
}}
159+
>
75160
<TextField
76-
label='Y-Axis Max Value'
77161
id='y-axis-max-value'
78162
value={localYAxisMaxValue}
79163
placeholder={getFormattedAndTranslatedValues(yAxisMaxValue ?? maxDataValue)}
80-
error={!isValid}
164+
error={errors.length > 0}
165+
helperText={errors.join(', ')}
81166
onChange={(e) => {
167+
setErrors([]);
82168
const value = e.target.value === '' ? null : Number(e.target.value);
83169
setLocalYAxisMaxValue(value);
84170
}}
85171
size='small'
86172
variant='outlined'
173+
sx={{width: '100%'}}
87174
/>
88175
<Box
89176
sx={{
@@ -97,9 +184,9 @@ export default function YAxisValueSettings({
97184
data-testid='save-threshold'
98185
onClick={(e) => {
99186
e.stopPropagation();
100-
handleSave();
187+
handleSave(localYAxisMaxValue);
101188
}}
102-
disabled={!isValid}
189+
disabled={errors.length > 0}
103190
sx={{color: theme.palette.success.main}}
104191
>
105192
<CheckIcon />
@@ -117,49 +204,54 @@ export default function YAxisValueSettings({
117204
</IconButton>
118205
</Box>
119206
</Box>
120-
</Box>
121-
) : (
122-
<Box
123-
sx={{
124-
display: 'flex',
125-
flexDirection: 'row',
126-
127-
justifyContent: 'space-between',
128-
alignItems: 'center',
129-
}}
130-
>
131-
<Box sx={{display: 'flex', flexDirection: 'column', alignItems: 'flex-start'}}>
132-
<Typography variant='h2' sx={{color: 'black'}}>
133-
Y-Axis Maximum
134-
</Typography>
135-
<Typography variant='caption' sx={{color: 'gray'}}>
136-
Global maximum value of the y-axis.
137-
</Typography>
138-
</Box>
139-
<Box sx={{display: 'flex', flexDirection: 'row', gap: 2, alignItems: 'center'}}>
140-
<Typography variant='h2' sx={{marginRight: '1rem'}}>
141-
{getFormattedAndTranslatedValues(yAxisMaxValue ?? maxDataValue)}
142-
</Typography>
207+
) : (
208+
<Box
209+
sx={{
210+
display: 'flex',
211+
flexDirection: 'row',
212+
gap: 3,
213+
alignItems: 'center',
214+
width: '100%',
215+
justifyContent: 'space-between',
216+
}}
217+
>
218+
<Button
219+
variant='text'
220+
onClick={() => setEditing(true)}
221+
sx={{
222+
cursor: 'text',
223+
}}
224+
>
225+
<Typography
226+
variant='body1'
227+
sx={{
228+
color: 'black',
229+
}}
230+
>
231+
{getFormattedAndTranslatedValues(yAxisMaxValue ?? maxDataValue)}
232+
</Typography>
233+
</Button>
143234
<Box sx={{display: 'flex', flexDirection: 'row', gap: 1, alignItems: 'center'}}>
144-
<Tooltip title='Edit Y-Axis Maximum'>
235+
<Tooltip title={t('y-axis-settings.editTooltip')}>
145236
<IconButton onClick={() => setEditing(true)}>
146237
<EditIcon />
147238
</IconButton>
148239
</Tooltip>
149-
<Tooltip title='Reset to current data maximum value'>
240+
<Tooltip title={t('y-axis-settings.resetTooltip')}>
150241
<IconButton
151242
onClick={(e) => {
152243
e.stopPropagation();
153244
handleReset();
154245
}}
246+
disabled={localYAxisMaxValue === maxDataValue}
155247
>
156248
<RefreshIcon />
157249
</IconButton>
158250
</Tooltip>
159251
</Box>
160252
</Box>
161-
</Box>
162-
)}
253+
)}
254+
</Box>
163255
</Box>
164256
);
165257
}

0 commit comments

Comments
 (0)