Skip to content

Commit

Permalink
📝 Add comments.
Browse files Browse the repository at this point in the history
  • Loading branch information
JonasGilg committed Mar 15, 2024
1 parent aa92349 commit 9795fe0
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 90 deletions.
2 changes: 1 addition & 1 deletion frontend/assets/third-party-attributions.json

Large diffs are not rendered by default.

63 changes: 39 additions & 24 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@
"@types/react-lazyload": "^3.2.3",
"@types/react-redux": "^7.1.33",
"@types/react-scroll-sync": "^0.9.0",
"@typescript-eslint/eslint-plugin": "^7.1.1",
"@typescript-eslint/parser": "^7.1.1",
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0",
"@vitejs/plugin-react": "^4.2.1",
"@vitest/coverage-v8": "^1.3.1",
"@babel/eslint-parser": "^7.23.10",
Expand Down
11 changes: 8 additions & 3 deletions frontend/src/components/MainContentTabs.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import Grid from '@mui/material/Grid';
import SimulationChart from './SimulationChart';
import React from 'react';
import TabContext from '@mui/lab/TabContext';
import TabPanel from '@mui/lab/TabPanel';
import Tab, {tabClasses, TabProps} from '@mui/material/Tab';
import TabList from '@mui/lab/TabList';
import Box from '@mui/material/Box';
import ParameterEditor from './ParameterEditor';
import ShowChart from '@mui/icons-material/ShowChart';
import Coronavirus from '@mui/icons-material/Coronavirus';
import styled from '@mui/material/styles/styled';
Expand All @@ -16,6 +14,10 @@ import {useTranslation} from 'react-i18next';
import {useAppDispatch, useAppSelector} from '../store/hooks';
import {selectTab} from '../store/UserPreferenceSlice';

// Lazily load the tab contents to enable code splitting.
const ParameterEditor = React.lazy(() => import('./ParameterEditor'));
const SimulationChart = React.lazy(() => import('./SimulationChart'));

const TabItem = styled(Tab)<TabProps>(({theme}) => ({
background: theme.palette.background.default,
[`&.${buttonBaseClasses.root}`]: {
Expand All @@ -30,6 +32,10 @@ const TabItem = styled(Tab)<TabProps>(({theme}) => ({
},
}));

/**
* This component manages the main content, which is a collection of tabs that the user can navigate through. By default
* the Simulation Chart is being shown.
*/
export default function MainContentTabs() {
const {t} = useTranslation();
const selectedTab = useAppSelector((state) => state.userPreference.selectedTab ?? '1');
Expand All @@ -56,7 +62,6 @@ export default function MainContentTabs() {
<TabList
onChange={handleChange}
centered
aria-label='TODO'
sx={{
minHeight: '0',
}}
Expand Down
158 changes: 99 additions & 59 deletions frontend/src/components/ParameterEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ import MathMarkdown from './shared/MathMarkdown';
import {ParameterData, useGetScenarioParametersQuery} from '../store/services/scenarioApi';
import {useTranslation} from 'react-i18next';

/**
* This component visualizes the parameters of the selected scenario. It uses a table with the following format:
*
* | Parameter | Group 1 | Group 2 | Group 3 |
* | ------------ | ----------- | ----------- | ----------- |
* | Parameter 1 | (Min - Max) | (Min - Max) | (Min - Max) |
* | Parameter 2 | (Min - Max) | (Min - Max) | (Min - Max) |
* | Parameter 3 | (Min - Max) | (Min - Max) | (Min - Max) |
*
* The parameter always consists of a symbol and a description. The symbol is in latex equation format. The groups could
* be different socio-economic groups, e.g. age.
*/
export default function ParameterEditor() {
const theme = useTheme();
const {data} = useGetScenarioParametersQuery(1);
Expand All @@ -40,6 +52,7 @@ export default function ParameterEditor() {
);
}

/** A simple header component it creates a table cell with the given header name and it spans by default one column. */
function ParameterColumHeader(props: Readonly<{name: string; colSpan?: number}>): JSX.Element {
const theme = useTheme();

Expand All @@ -53,6 +66,10 @@ function ParameterColumHeader(props: Readonly<{name: string; colSpan?: number}>)
);
}

/**
* This component creates the header for each parameter. The symbol is the scientific symbol for the parameter in latex
* equation format. The description explains the parameter in a single sentence.
*/
function ParameterRowHeader(props: Readonly<{symbol: string; description: string}>): JSX.Element {
return (
<>
Expand All @@ -66,70 +83,93 @@ function ParameterRowHeader(props: Readonly<{symbol: string; description: string
);
}

/**
* Depending on the type of parameter, this component renders different types of parameter rows.
*/
function ParameterRow(props: Readonly<{params: ParameterData}>): JSX.Element | null {
const theme = useTheme();
const {t, i18n} = useTranslation('backend');
if (!i18n.exists(`parameters.${props.params.key}`, {ns: 'backend'})) {
return null;
}

if (props.params.type === 'MIN_MAX_GROUPED') {
return (
<TableRow>
<ParameterRowHeader
symbol={t(`parameters.${props.params.key}.symbol`)}
description={t(`parameters.${props.params.key}.description`)}
return (
<TableRow>
<ParameterRowHeader
symbol={t(`parameters.${props.params.key}.symbol`)}
description={t(`parameters.${props.params.key}.description`)}
/>
{((): JSX.Element | null => {
// jsx inline switch case
switch (props.params.type) {
case 'MIN_MAX_GROUPED':
return <ParameterRowMinMaxGrouped params={props.params} />;
case 'COMPUTED':
return <ParameterRowComputed params={props.params} />;
default:
return null;
}
})()}
</TableRow>
);
}

/**
* Renders parameter values for all groups with min and max values. If min and max are identical only one value is
* shown.
*/
function ParameterRowMinMaxGrouped(props: Readonly<{params: ParameterData}>): Array<JSX.Element> {
const theme = useTheme();
const {i18n} = useTranslation('backend');

return (props.params.data as Array<{span: number; min: number; max: number}>).map((entry) => (
<TableCell
key={`cell-${props.params.symbol}-${crypto.randomUUID()}`}
colSpan={entry.span}
sx={{textAlign: 'center', padding: 0}}
>
<Box sx={{display: 'flex', alignItems: 'center'}}>
<Divider
sx={{
flexGrow: 1,
borderBottomStyle: 'dashed',
borderBottomWidth: '2px',
visibility: entry.span > 1 ? 'visible' : 'hidden',
}}
/>
{(props.params.data as Array<{span: number; min: number; max: number}>).map((entry) => (
<TableCell
key={`cell-${props.params.symbol}-${crypto.randomUUID()}`}
colSpan={entry.span}
sx={{textAlign: 'center', padding: 0}}
>
<Box sx={{display: 'flex', alignItems: 'center'}}>
<Divider
sx={{
flexGrow: 1,
borderBottomStyle: 'dashed',
borderBottomWidth: '2px',
visibility: entry.span > 1 ? 'visible' : 'hidden',
}}
/>
<Typography
variant='body2'
sx={{
borderWidth: '1px',
borderColor: theme.palette.divider,
borderStyle: 'solid',
borderRadius: '5px',
padding: theme.spacing(2),
}}
>
{entry.min === entry.max
? entry.min.toLocaleString(i18n.language)
: `${entry.min.toLocaleString(i18n.language)} - ${entry.max.toLocaleString(i18n.language)}`}
</Typography>
<Divider
sx={{
flexGrow: 1,
borderBottomStyle: 'dashed',
borderBottomWidth: '2px',
visibility: entry.span > 1 ? 'visible' : 'hidden',
}}
/>
</Box>
</TableCell>
))}
</TableRow>
);
} else {
return (
<TableRow>
<ParameterRowHeader symbol={props.params.symbol} description={props.params.key} />
<TableCell colSpan={6} sx={{textAlign: 'center'}}>
<MathMarkdown>{props.params.data as string}</MathMarkdown>
</TableCell>
</TableRow>
);
}
<Typography
variant='body2'
sx={{
borderWidth: '1px',
borderColor: theme.palette.divider,
borderStyle: 'solid',
borderRadius: '5px',
padding: theme.spacing(2),
}}
>
{entry.min === entry.max
? entry.min.toLocaleString(i18n.language)
: `${entry.min.toLocaleString(i18n.language)} - ${entry.max.toLocaleString(i18n.language)}`}
</Typography>
<Divider
sx={{
flexGrow: 1,
borderBottomStyle: 'dashed',
borderBottomWidth: '2px',
visibility: entry.span > 1 ? 'visible' : 'hidden',
}}
/>
</Box>
</TableCell>
));
}

/**
* Renders an equation which makes up the parameter. The equation is spanning over the whole row.
*/
function ParameterRowComputed(props: Readonly<{params: ParameterData}>): JSX.Element {
return (
<TableCell colSpan={6} sx={{textAlign: 'center'}}>
<MathMarkdown>{props.params.data as string}</MathMarkdown>
</TableCell>
);
}
3 changes: 2 additions & 1 deletion frontend/src/components/ReferenceDayConnector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ import {useBoundingclientrectRef} from 'rooks';
*/
export function ReferenceDayConnector(): JSX.Element {
const theme = useTheme();
const selectedTab = useAppSelector((state) => state.userPreference.selectedTab ?? '1');

// The selected tab is used to decide, if the connecting border is being drawn. Tab '1' would be the simulation chart.
const selectedTab = useAppSelector((state) => state.userPreference.selectedTab ?? '1');
const referenceDayPos = useAppSelector((state) => state.layoutSlice.referenceDayXPositions);

const [ref, boundingRect] = useBoundingclientrectRef();
Expand Down

0 comments on commit 9795fe0

Please sign in to comment.