From 03e24e3fa158aa8d9cb986ddf1628d28574674a1 Mon Sep 17 00:00:00 2001 From: JonasGilg Date: Fri, 7 Jun 2024 10:52:48 +0200 Subject: [PATCH 1/7] :beetle: Fix parameter fetching. --- frontend/src/components/ParameterEditor.tsx | 23 ++++++++++++++++++--- frontend/src/store/services/scenarioApi.ts | 8 +++++-- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/ParameterEditor.tsx b/frontend/src/components/ParameterEditor.tsx index 2ef4e0bc..501b30ac 100644 --- a/frontend/src/components/ParameterEditor.tsx +++ b/frontend/src/components/ParameterEditor.tsx @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2024 German Aerospace Center (DLR) // SPDX-License-Identifier: Apache-2.0 -import React, {useCallback} from 'react'; +import React, {useCallback, useEffect, useState} from 'react'; import TableContainer from '@mui/material/TableContainer'; import Table from '@mui/material/Table'; import TableHead from '@mui/material/TableHead'; @@ -14,9 +14,10 @@ import {useTheme} from '@mui/material/styles'; import Divider from '@mui/material/Divider'; import Box from '@mui/material/Box'; import MathMarkdown from './shared/MathMarkdown'; -import {ParameterData, useGetScenarioParametersQuery} from '../store/services/scenarioApi'; +import {ParameterData, useGetScenarioParametersQuery, useGetSimulationsQuery} from '../store/services/scenarioApi'; import {useTranslation} from 'react-i18next'; import {useGetGroupSubcategoriesQuery} from '../store/services/groupApi'; +import {useAppSelector} from '../store/hooks'; /** * This component visualizes the parameters of the selected scenario. It uses a table with the following format: @@ -33,7 +34,23 @@ import {useGetGroupSubcategoriesQuery} from '../store/services/groupApi'; export default function ParameterEditor() { const {t} = useTranslation('backend'); const theme = useTheme(); - const {data} = useGetScenarioParametersQuery(1); + + const {data: simulations} = useGetSimulationsQuery(); + const selectedScenario = useAppSelector((state) => state.dataSelection.scenario); + const [scenarioId, setScenarioId] = useState(null); + + useEffect(() => { + const scenario = simulations?.results.find((sim) => sim.id === selectedScenario); + const scenarioIdResult = scenario?.scenario.match(/(\d+)(?!.*\d)/); + if (scenarioIdResult) { + const id = parseInt(scenarioIdResult[0]); + setScenarioId(id); + } else { + setScenarioId(null); + } + }, [simulations, selectedScenario]); + + const {data} = useGetScenarioParametersQuery(scenarioId); const {data: groups} = useGetGroupSubcategoriesQuery(); return ( diff --git a/frontend/src/store/services/scenarioApi.ts b/frontend/src/store/services/scenarioApi.ts index 16b35fe5..54fc0e3e 100644 --- a/frontend/src/store/services/scenarioApi.ts +++ b/frontend/src/store/services/scenarioApi.ts @@ -108,8 +108,12 @@ export const scenarioApi = createApi({ }, }), - getScenarioParameters: builder.query, number>({ - queryFn: async function (arg: number, _queryApi, _extraOptions, fetchWithBQ) { + getScenarioParameters: builder.query | null, number | null>({ + queryFn: async function (arg: number | null, _queryApi, _extraOptions, fetchWithBQ) { + if (!arg) { + return {data: null}; + } + const response = await fetchWithBQ(`scenarios/${arg}/`); if (response.error) return {error: response.error}; const parameters = response.data as ParameterRESTData; From a32e9cc2e9688c2c82c156f638889f677133cd77 Mon Sep 17 00:00:00 2001 From: JonasGilg Date: Fri, 7 Jun 2024 12:18:27 +0200 Subject: [PATCH 2/7] :wrench: Display an info message, if the scenario has no parameters. --- frontend/locales/de-global.json5 | 3 + frontend/locales/en-global.json5 | 3 + frontend/src/components/ParameterEditor.tsx | 80 +++++++++++++++------ 3 files changed, 65 insertions(+), 21 deletions(-) diff --git a/frontend/locales/de-global.json5 b/frontend/locales/de-global.json5 index 684ba357..86a1497f 100644 --- a/frontend/locales/de-global.json5 +++ b/frontend/locales/de-global.json5 @@ -69,6 +69,9 @@ timeSeries: 'Zeitreihe', parameters: 'Parameter', }, + parameters: { + 'no-parameters': 'Für das ausgewählte Szenario existieren keine Parameter.', + }, today: 'Heute', more: 'Mehr', less: 'Weniger', diff --git a/frontend/locales/en-global.json5 b/frontend/locales/en-global.json5 index 9afedfbb..de96694e 100644 --- a/frontend/locales/en-global.json5 +++ b/frontend/locales/en-global.json5 @@ -78,6 +78,9 @@ timeSeries: 'Time Series', parameters: 'Parameters', }, + parameters: { + 'no-parameters': 'No parameters available for the selected scenario.', + }, today: 'Today', more: 'More', less: 'Less', diff --git a/frontend/src/components/ParameterEditor.tsx b/frontend/src/components/ParameterEditor.tsx index 501b30ac..de61d1b1 100644 --- a/frontend/src/components/ParameterEditor.tsx +++ b/frontend/src/components/ParameterEditor.tsx @@ -18,6 +18,7 @@ import {ParameterData, useGetScenarioParametersQuery, useGetSimulationsQuery} fr import {useTranslation} from 'react-i18next'; import {useGetGroupSubcategoriesQuery} from '../store/services/groupApi'; import {useAppSelector} from '../store/hooks'; +import GridOff from '@mui/icons-material/GridOff'; /** * This component visualizes the parameters of the selected scenario. It uses a table with the following format: @@ -32,15 +33,21 @@ import {useAppSelector} from '../store/hooks'; * be different socio-economic groups, e.g. age. */ export default function ParameterEditor() { - const {t} = useTranslation('backend'); + const {t} = useTranslation(); const theme = useTheme(); - const {data: simulations} = useGetSimulationsQuery(); - const selectedScenario = useAppSelector((state) => state.dataSelection.scenario); const [scenarioId, setScenarioId] = useState(null); + const selectedScenario = useAppSelector((state) => state.dataSelection.scenario); + const {data: simulations} = useGetSimulationsQuery(); + const {data: parameters} = useGetScenarioParametersQuery(scenarioId); + + // This effect gets the id of the scenario, where the parameters are stored. useEffect(() => { const scenario = simulations?.results.find((sim) => sim.id === selectedScenario); + + // The scenario id is unfortunately hidden in a URL. It is always the last number in the URL, so we use the + // following regex to extract that number. const scenarioIdResult = scenario?.scenario.match(/(\d+)(?!.*\d)/); if (scenarioIdResult) { const id = parseInt(scenarioIdResult[0]); @@ -50,26 +57,57 @@ export default function ParameterEditor() { } }, [simulations, selectedScenario]); - const {data} = useGetScenarioParametersQuery(scenarioId); - const {data: groups} = useGetGroupSubcategoriesQuery(); + if (scenarioId !== null) { + return ( + + + + + {parameters?.map((entry) => )} + +
+
+ ); + } return ( - - - - - - {groups?.results // Currently only age groups are supported. We also need to ignore the 'total' group. - ?.filter((group) => group.key !== 'total') - .filter((group) => group.category === 'age') - .map((group) => )} - - - - {data?.map((entry) => )} - -
-
+ + + + +
+
+ + + {t('parameters.no-parameters')} + +
+ ); +} + +function TableHeader(): JSX.Element { + const {t: tBackend} = useTranslation('backend'); + const {data: groups} = useGetGroupSubcategoriesQuery(); + return ( + + + + {groups?.results // Currently only age groups are supported. We also need to ignore the 'total' group. + ?.filter((group) => group.key !== 'total') + .filter((group) => group.category === 'age') + .map((group) => ( + + ))} + + ); } From dfe63bcec172f42005603138b31543f0f641d503 Mon Sep 17 00:00:00 2001 From: JonasGilg Date: Fri, 7 Jun 2024 14:04:26 +0200 Subject: [PATCH 3/7] :memo: Add some translations. --- frontend/locales/de-backend.json5 | 4 ++++ frontend/locales/en-backend.json5 | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/frontend/locales/de-backend.json5 b/frontend/locales/de-backend.json5 index d4d83605..f67e5adc 100644 --- a/frontend/locales/de-backend.json5 +++ b/frontend/locales/de-backend.json5 @@ -277,6 +277,10 @@ }, 'scenario-names': { 'Baseline Scenario': 'Basisszenario', + 'baseline': 'Basisszenario', + 'closed_schools': 'Geschlossene Schulen', + 'remote_work': 'Homeoffice', + '10p_reduced_contacts ': '10% Kontaktreduzierung', 'Summer 2021 Simulation 1': 'Szenario ohne Maßnahmen', 'Summer 2021 Simulation 2': 'Szenario mit Maßnahmen', }, diff --git a/frontend/locales/en-backend.json5 b/frontend/locales/en-backend.json5 index aa5af20d..2022606a 100644 --- a/frontend/locales/en-backend.json5 +++ b/frontend/locales/en-backend.json5 @@ -275,6 +275,10 @@ }, 'scenario-names': { 'Baseline Scenario': 'Baseline Scenario', + 'baseline': 'Baseline Scenario', + 'closed_schools': 'Schools Closed', + 'remote_work': 'Home Office', + '10p_reduced_contacts ': '10% Reduced Contacts', 'Summer 2021 Simulation 1': 'Scenario without Interventions', 'Summer 2021 Simulation 2': 'Scenario with Interventions', }, From 2d0685e01704299141e97a504235507fc61b3fb2 Mon Sep 17 00:00:00 2001 From: JonasGilg Date: Fri, 7 Jun 2024 14:08:31 +0200 Subject: [PATCH 4/7] :memo: Add changelog entry. --- frontend/docs/changelog/changelog-de.md | 3 +++ frontend/docs/changelog/changelog-en.md | 3 +++ frontend/locales/de-backend.json5 | 6 +++--- frontend/locales/en-backend.json5 | 6 +++--- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/frontend/docs/changelog/changelog-de.md b/frontend/docs/changelog/changelog-de.md index 35c48f42..269b71bf 100644 --- a/frontend/docs/changelog/changelog-de.md +++ b/frontend/docs/changelog/changelog-de.md @@ -13,10 +13,13 @@ SPDX-License-Identifier: CC-BY-4.0 ### Verbesserungen +- Es wurde mehr Übersetzungen für Szenarien hinzugefügt. + ### Fehlerbehebungen - Fehlende Übersetzungen wurden ergänzt. - Die Auswahl der Farblegenden zeigt jetzt wieder eine Vorschau für alle Optionen. +- Die Parameter werden jetzt korrekt dem ausgewählten Szenario zugeordnet und eine Info wird angezeigt, wenn keine Parameter verfügbar sind. --- diff --git a/frontend/docs/changelog/changelog-en.md b/frontend/docs/changelog/changelog-en.md index 96025a86..35e33f37 100644 --- a/frontend/docs/changelog/changelog-en.md +++ b/frontend/docs/changelog/changelog-en.md @@ -13,10 +13,13 @@ SPDX-License-Identifier: CC-BY-4.0 ### Improvements +- Added translations for additional scenarios. + ### Bug fixes - Missing translations were fixed. - The heat legend selection now shows a preview for all legends again. +- The Parameters will now correctly be associated with the selected scenario and an info will be displayed, when no parameters are available. --- diff --git a/frontend/locales/de-backend.json5 b/frontend/locales/de-backend.json5 index f67e5adc..6632f000 100644 --- a/frontend/locales/de-backend.json5 +++ b/frontend/locales/de-backend.json5 @@ -277,9 +277,9 @@ }, 'scenario-names': { 'Baseline Scenario': 'Basisszenario', - 'baseline': 'Basisszenario', - 'closed_schools': 'Geschlossene Schulen', - 'remote_work': 'Homeoffice', + baseline: 'Basisszenario', + closed_schools: 'Geschlossene Schulen', + remote_work: 'Homeoffice', '10p_reduced_contacts ': '10% Kontaktreduzierung', 'Summer 2021 Simulation 1': 'Szenario ohne Maßnahmen', 'Summer 2021 Simulation 2': 'Szenario mit Maßnahmen', diff --git a/frontend/locales/en-backend.json5 b/frontend/locales/en-backend.json5 index 2022606a..bb2aa387 100644 --- a/frontend/locales/en-backend.json5 +++ b/frontend/locales/en-backend.json5 @@ -275,9 +275,9 @@ }, 'scenario-names': { 'Baseline Scenario': 'Baseline Scenario', - 'baseline': 'Baseline Scenario', - 'closed_schools': 'Schools Closed', - 'remote_work': 'Home Office', + baseline: 'Baseline Scenario', + closed_schools: 'Schools Closed', + remote_work: 'Home Office', '10p_reduced_contacts ': '10% Reduced Contacts', 'Summer 2021 Simulation 1': 'Scenario without Interventions', 'Summer 2021 Simulation 2': 'Scenario with Interventions', From 2cf08b23048d781d9aae81fcfd3ae860d4b0df4d Mon Sep 17 00:00:00 2001 From: JonasGilg Date: Fri, 7 Jun 2024 14:44:39 +0200 Subject: [PATCH 5/7] :memo: Add documentation. --- frontend/src/components/ParameterEditor.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend/src/components/ParameterEditor.tsx b/frontend/src/components/ParameterEditor.tsx index de61d1b1..5c6bc9af 100644 --- a/frontend/src/components/ParameterEditor.tsx +++ b/frontend/src/components/ParameterEditor.tsx @@ -93,6 +93,9 @@ export default function ParameterEditor() { ); } +/** + * Creates the header row of the parameter editor. + */ function TableHeader(): JSX.Element { const {t: tBackend} = useTranslation('backend'); const {data: groups} = useGetGroupSubcategoriesQuery(); From 7ef41294b7a56f0b22fe0ee27435862f51c9a7a1 Mon Sep 17 00:00:00 2001 From: JonasGilg Date: Fri, 7 Jun 2024 16:50:54 +0200 Subject: [PATCH 6/7] :beetle: Fix tests. --- .../__tests__/components/ParameterEditor.test.tsx | 5 +++++ frontend/src/__tests__/mocks/handlers.ts | 15 +++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/frontend/src/__tests__/components/ParameterEditor.test.tsx b/frontend/src/__tests__/components/ParameterEditor.test.tsx index cec6f626..773e0b8d 100644 --- a/frontend/src/__tests__/components/ParameterEditor.test.tsx +++ b/frontend/src/__tests__/components/ParameterEditor.test.tsx @@ -9,6 +9,7 @@ import i18n from '../../util/i18nForTests'; import {Provider} from 'react-redux'; import React from 'react'; import ParameterEditor from '../../components/ParameterEditor'; +import {selectScenario} from '../../store/DataSelectionSlice'; describe('ParameterEditor', () => { test('Editor Loaded', async () => { @@ -29,6 +30,10 @@ describe('ParameterEditor', () => { await screen.findByText('group-filters.groups.age_4'); await screen.findByText('group-filters.groups.age_5'); + await screen.findByText('parameters.no-parameters'); + + Store.dispatch(selectScenario(1)); + await screen.findByText('parameters.Test Parameter 1.symbol'); await screen.findByText('parameters.Test Parameter 1.description'); await screen.findByText(/0 - 1 parameters\.Test Parameter 1\.unit/); diff --git a/frontend/src/__tests__/mocks/handlers.ts b/frontend/src/__tests__/mocks/handlers.ts index b0c94af3..ae5512ce 100644 --- a/frontend/src/__tests__/mocks/handlers.ts +++ b/frontend/src/__tests__/mocks/handlers.ts @@ -4,6 +4,21 @@ import {http, HttpResponse} from 'msw'; export default [ + http.get('*/api/v1/simulations/', () => { + return HttpResponse.json({ + results: [ + { + id: 1, + name: 'Test Scenario', + description: 'Test', + startDay: '2024-01-01', + numberOfDays: 30, + scenario: 'http://localhost:8000/api/v1/scenarios/1/', + percentiles: [5, 15, 25, 50, 75, 85, 95], + }, + ], + }); + }), http.get('*/api/v1/scenarios/1/', () => { return HttpResponse.json({ results: { From 3731c3bbc6b2ae590980eaf66601d7bee3706026 Mon Sep 17 00:00:00 2001 From: Jonas Gilg Date: Mon, 10 Jun 2024 09:43:12 +0200 Subject: [PATCH 7/7] :beetle: Fix an error in a translation. --- frontend/locales/de-backend.json5 | 2 +- frontend/locales/en-backend.json5 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/locales/de-backend.json5 b/frontend/locales/de-backend.json5 index 6632f000..d9108ebc 100644 --- a/frontend/locales/de-backend.json5 +++ b/frontend/locales/de-backend.json5 @@ -280,7 +280,7 @@ baseline: 'Basisszenario', closed_schools: 'Geschlossene Schulen', remote_work: 'Homeoffice', - '10p_reduced_contacts ': '10% Kontaktreduzierung', + '10p_reduced_contacts': '10% Kontaktreduzierung', 'Summer 2021 Simulation 1': 'Szenario ohne Maßnahmen', 'Summer 2021 Simulation 2': 'Szenario mit Maßnahmen', }, diff --git a/frontend/locales/en-backend.json5 b/frontend/locales/en-backend.json5 index bb2aa387..e68b8bef 100644 --- a/frontend/locales/en-backend.json5 +++ b/frontend/locales/en-backend.json5 @@ -278,7 +278,7 @@ baseline: 'Baseline Scenario', closed_schools: 'Schools Closed', remote_work: 'Home Office', - '10p_reduced_contacts ': '10% Reduced Contacts', + '10p_reduced_contacts': '10% Reduced Contacts', 'Summer 2021 Simulation 1': 'Scenario without Interventions', 'Summer 2021 Simulation 2': 'Scenario with Interventions', },