Skip to content

Commit

Permalink
Merge branch 'ui-enhancements' into Simulation-layout-updates
Browse files Browse the repository at this point in the history
  • Loading branch information
eatyourgreens authored Nov 27, 2024
2 parents 0f460e9 + 66b6b46 commit 7da45b0
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 181 deletions.
4 changes: 3 additions & 1 deletion frontend-v2/src/features/model/secondary/ThresholdsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,17 +124,19 @@ function VariableRow({
type="number"
defaultValue={variable.lower_threshold || 0}
onChange={onChangeLowerThreshold}
size="small"
/>
</TableCell>
<TableCell>
<TextField
type="number"
defaultValue={variable.upper_threshold || Infinity}
onChange={onChangeUpperThreshold}
size="small"
/>
</TableCell>
<TableCell>
<Select value={unitSymbol} onChange={onChangeUnit}>
<Select value={unitSymbol} onChange={onChangeUnit} size="small">
{unit?.compatible_units?.map((unit) => (
<MenuItem key={unit.id} value={unit.symbol}>
{unit.symbol}
Expand Down
51 changes: 36 additions & 15 deletions frontend-v2/src/features/model/secondary/TimeIntervalsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ import {
import { RootState } from "../../../app/store";
import { useModelTimeIntervals } from "../../../hooks/useModelTimeIntervals";

type TimeUnitSelectProps = {
interval: TimeIntervalRead;
onChange: (interval: TimeIntervalRead) => void;
};

function useTimeUnits() {
const projectId = useSelector(
(state: RootState) => state.main.selectedProject,
Expand All @@ -46,10 +41,12 @@ function useTimeUnits() {
return hourUnit?.compatible_units || [];
}

function TimeUnitSelect({ interval, onChange }: TimeUnitSelectProps) {
function TimeUnitSelect() {
const defaultTimeUnit = 9; // set hours by default
const [intervals, setIntervals] = useModelTimeIntervals();
const interval = intervals[0];
const [selectedUnit, setSelectedUnit] = useState(
interval.unit || defaultTimeUnit,
interval?.unit || defaultTimeUnit,
);
const timeUnits = useTimeUnits();
const timeUnitOptions =
Expand All @@ -59,13 +56,17 @@ function TimeUnitSelect({ interval, onChange }: TimeUnitSelectProps) {
const unit = timeUnits?.find((unit) => unit.id === event.target.value);
if (unit) {
setSelectedUnit(+unit.id);
onChange({ ...interval, unit: +unit.id });
setIntervals(intervals.map((i) => ({ ...i, unit: +unit.id })));
}
}

return (
<FormControl>
<Select value={selectedUnit.toString()} onChange={onChangeUnit}>
<Select
value={selectedUnit.toString()}
onChange={onChangeUnit}
size="small"
>
{timeUnitOptions.map((option) => (
<MenuItem key={option.label} value={option.value}>
{option.label}
Expand All @@ -80,11 +81,20 @@ type IntervalRowProps = {
interval: TimeIntervalRead;
onDelete: () => void;
onUpdate: (interval: TimeIntervalRead) => void;
editUnits: boolean;
};

function IntervalRow({ interval, onDelete, onUpdate }: IntervalRowProps) {
function IntervalRow({
interval,
onDelete,
onUpdate,
editUnits = false,
}: IntervalRowProps) {
const [start, setStart] = useState(interval.start_time);
const [end, setEnd] = useState(interval.end_time);
const units = useTimeUnits();
const intervalUnit = units?.find((unit) => +unit.id === interval.unit);

function onChangeStart(event: React.ChangeEvent<HTMLInputElement>) {
const newStartTime = parseFloat(event.target.value);
setStart(newStartTime);
Expand All @@ -99,13 +109,23 @@ function IntervalRow({ interval, onDelete, onUpdate }: IntervalRowProps) {
return (
<TableRow>
<TableCell>
<TextField type="number" value={start} onChange={onChangeStart} />
<TextField
type="number"
value={start}
onChange={onChangeStart}
size="small"
/>
</TableCell>
<TableCell>
<TextField type="number" value={end} onChange={onChangeEnd} />
<TextField
type="number"
value={end}
onChange={onChangeEnd}
size="small"
/>
</TableCell>
<TableCell>
<TimeUnitSelect interval={interval} onChange={onUpdate} />
{editUnits ? <TimeUnitSelect /> : intervalUnit?.symbol}
</TableCell>
<TableCell>
<IconButton onClick={onDelete}>
Expand Down Expand Up @@ -153,6 +173,7 @@ const TimeIntervalsTable: FC<TableProps> = (props) => {

return (
<>
<Button onClick={addInterval}>Add interval</Button>
<Table {...props}>
<TableHead>
<TableCell>Start time</TableCell>
Expand All @@ -161,17 +182,17 @@ const TimeIntervalsTable: FC<TableProps> = (props) => {
<TableCell>Remove</TableCell>
</TableHead>
<TableBody>
{intervals.map((interval) => (
{intervals.map((interval, index) => (
<IntervalRow
key={interval.start_time}
interval={interval}
onDelete={onDelete(interval.id)}
onUpdate={onUpdate(interval.id)}
editUnits={index === 0}
/>
))}
</TableBody>
</Table>
<Button onClick={addInterval}>Add time interval</Button>
</>
);
};
Expand Down
96 changes: 2 additions & 94 deletions frontend-v2/src/features/results/ResultsTab.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { FC, useState } from "react";
import {
Box,
FormControl,
InputLabel,
MenuItem,
Expand All @@ -16,65 +15,6 @@ import { useConcentrationVariables } from "./useConcentrationVariables";
import { useParameters, Parameter } from "./useParameters";
import { ResultsTable } from "./ResultsTable";
import { useModelTimeIntervals } from "../../hooks/useModelTimeIntervals";
import { useUnits } from "./useUnits";

function TimeUnitSelect({
timeUnit,
onChangeTimeUnit,
}: {
timeUnit: string;
onChangeTimeUnit: (event: SelectChangeEvent) => void;
}) {
const units = useUnits();
const timeUnits = units?.find(
(unit) => unit.symbol === "h",
)?.compatible_units;
return (
<FormControl size="small">
<InputLabel id="time-unit-label">Time Unit</InputLabel>
<Select
labelId="time-unit-label"
value={timeUnit}
onChange={onChangeTimeUnit}
>
{timeUnits?.map((unit) => (
<MenuItem key={unit.id} value={unit.symbol}>
{unit.symbol}
</MenuItem>
))}
</Select>
</FormControl>
);
}

function ConcentrationUnitSelect({
concentrationUnit,
onChangeConcentrationUnit,
}: {
concentrationUnit: string;
onChangeConcentrationUnit: (event: SelectChangeEvent) => void;
}) {
const units = useUnits();
const concentrationUnits = units?.find(
(unit) => unit.symbol === "pmol/L",
)?.compatible_units;
return (
<FormControl size="small">
<InputLabel id="conc-unit-label">Concentration Unit</InputLabel>
<Select
labelId="conc-unit-label"
value={concentrationUnit}
onChange={onChangeConcentrationUnit}
>
{concentrationUnits?.map((unit) => (
<MenuItem key={unit.id} value={unit.symbol}>
{unit.symbol}
</MenuItem>
))}
</Select>
</FormControl>
);
}

const options = [
{ name: "Parameters", value: "parameters" },
Expand Down Expand Up @@ -103,22 +43,10 @@ type RowFilter = {
};

const ResultsTab: FC = () => {
const [timeUnit, setTimeUnit] = useState("h");
const [concentrationUnit, setConcentrationUnit] = useState("pmol/L");
function onChangeTimeUnit(event: SelectChangeEvent) {
setTimeUnit(event.target.value);
}
function onChangeConcentrationUnit(event: SelectChangeEvent) {
setConcentrationUnit(event.target.value);
}

const { groups = [] } = useSubjectGroups();
const [intervals] = useModelTimeIntervals();
const concentrationVariables = useConcentrationVariables();
const parameters = useParameters({
variableUnit: concentrationUnit,
timeUnit,
});
const parameters = useParameters();

const [columns, setColumns] = useState("parameters");
const [rows, setRows] = useState("variables");
Expand Down Expand Up @@ -360,27 +288,7 @@ const ResultsTab: FC = () => {
intervalIndex={intervalIndex}
rows={rowData}
rowColumn={rowColumn}
concentrationUnit={concentrationUnit}
timeUnit={timeUnit}
>
<Box
sx={{
justifyContent: "flex-end",
display: "flex",
mt: "1rem",
gap: "0.5rem",
}}
>
<ConcentrationUnitSelect
concentrationUnit={concentrationUnit}
onChangeConcentrationUnit={onChangeConcentrationUnit}
/>
<TimeUnitSelect
timeUnit={timeUnit}
onChangeTimeUnit={onChangeTimeUnit}
/>
</Box>
</ResultsTable>
/>
</>
);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down
22 changes: 4 additions & 18 deletions frontend-v2/src/features/results/ResultsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import {
TableHead,
TableRow,
} from "@mui/material";
import { FC, ReactElement } from "react";
import { FC } from "react";

import useSubjectGroups from "../../hooks/useSubjectGroups";

import { useParameters } from "./useParameters";
import { useParameterNames } from "./useParameters";
import { useConcentrationVariables } from "./useConcentrationVariables";

import { FilterIndex, RowData } from "./ResultsTab";
Expand Down Expand Up @@ -77,9 +77,6 @@ interface ResultsTableProps {
parameterIndex: FilterIndex;
rows: RowData;
rowColumn: string;
concentrationUnit: string;
timeUnit: string;
children?: ReactElement;
}

/**
Expand All @@ -92,8 +89,6 @@ interface ResultsTableProps {
* @param parameterIndex "rows" or "columns" or the index of the parameter to display in the table.
* @param rows an array of row data.
* @param rowColumn The name of the row column.
* @param concentrationUnit The unit of the displayed concentration values.
* @param timeUnit The unit of the displayed time values.
*/
export const ResultsTable: FC<ResultsTableProps> = ({
groupIndex,
Expand All @@ -102,15 +97,9 @@ export const ResultsTable: FC<ResultsTableProps> = ({
parameterIndex,
rows = [],
rowColumn = "",
concentrationUnit = "pmol/L",
timeUnit = "h",
children,
}) => {
const { groups } = useSubjectGroups();
const parameters = useParameters({
variableUnit: concentrationUnit,
timeUnit,
});
const parameterNames = useParameterNames();
const concentrationVariables = useConcentrationVariables();
const [intervals] = useModelTimeIntervals();
const tableRows = useTableRows({
Expand All @@ -119,8 +108,6 @@ export const ResultsTable: FC<ResultsTableProps> = ({
intervalIndex,
variableIndex,
parameterIndex,
concentrationUnit,
timeUnit,
});

if (!rows[0]) {
Expand All @@ -130,7 +117,7 @@ export const ResultsTable: FC<ResultsTableProps> = ({
try {
const columnHeadings =
parameterIndex === "columns"
? parameters.map((parameter) => parameter.name)
? parameterNames
: variableIndex === "columns"
? concentrationVariables.map((variable) => variable.name)
: intervalIndex === "columns"
Expand Down Expand Up @@ -168,7 +155,6 @@ export const ResultsTable: FC<ResultsTableProps> = ({
))}
</TableBody>
</Table>
{children}
</TableContainer>
);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down
12 changes: 10 additions & 2 deletions frontend-v2/src/features/results/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ interface ParametersProps {
intervals: TimeIntervalRead[];
}

/**
* Generate a list of table columns. Each column has a header, and a value function
* that returns the formatted value for each row in that column.
*/
export function columns({
variable,
aucVariable,
Expand All @@ -29,6 +33,7 @@ export function columns({
interval,
intervals = [],
}: ParametersProps) {
// variables as colummns
if (parameter && !variable) {
return concentrationVariables.map((variable) => {
return {
Expand All @@ -37,6 +42,7 @@ export function columns({
};
});
}
// time intervals as columns
if (parameter && !interval) {
return intervals.map((interval) => {
return {
Expand All @@ -45,6 +51,7 @@ export function columns({
};
});
}
// simulations (groups) as columns
if (parameter && !simulation) {
return simulations.map(() => {
return {
Expand All @@ -53,12 +60,13 @@ export function columns({
};
});
}
// secondary parameters as columns
if (simulation && variable && !parameter) {
return parameters.map((parameter) => {
return {
header: parameter.name,
value: (intervalIndex: number) =>
parameter.value(intervalIndex, simulation, variable, aucVariable),
value: (interval: TimeIntervalRead) =>
parameter.value(interval, simulation, variable, aucVariable),
};
});
}
Expand Down
Loading

0 comments on commit 7da45b0

Please sign in to comment.