Skip to content

Commit

Permalink
Merge pull request #326 from pkpdapp-team/styles
Browse files Browse the repository at this point in the history
Sorting variables; Lag Time required; Various fixes
  • Loading branch information
martinjrobins authored Jan 9, 2024
2 parents 857cda4 + 633398f commit 24d4804
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 68 deletions.
3 changes: 3 additions & 0 deletions frontend-v2/src/components/TextField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type Props<T extends FieldValues> = {
rules?: Record<string, unknown>;
mode?: "onChange" | "onBlur";
textFieldProps?: material.TextFieldProps;
autoShrink?: boolean;
sx?: material.SxProps
};

Expand All @@ -26,6 +27,7 @@ function TextField<T extends FieldValues>({
rules,
mode,
textFieldProps,
autoShrink,
sx
}: Props<T>): React.ReactElement {
const [fieldValue, setFieldValue] = useFieldState({ name, control });
Expand Down Expand Up @@ -66,6 +68,7 @@ function TextField<T extends FieldValues>({
}
name={name}
id={name}
InputLabelProps={autoShrink !== undefined ? { shrink: autoShrink } : {}}
variant="outlined"
value={
fieldValue === undefined || fieldValue === null ? "" : fieldValue
Expand Down
2 changes: 2 additions & 0 deletions frontend-v2/src/features/login/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,15 @@ const Login: React.FC<LoginProps> = ({ onLogin, isLoading, errorMessage }) => {
control={control}
textFieldProps={{ autoComplete: "username" }}
mode="onChange"
autoShrink={true}
/>
<TextField
label="Password"
name="password"
control={control}
textFieldProps={{ autoComplete: "password", type: "password" }}
mode="onChange"
autoShrink={true}
/>
<Button
type="submit"
Expand Down
46 changes: 38 additions & 8 deletions frontend-v2/src/features/model/MapVariablesTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
CombinedModelRead,
CompoundRead,
ProjectRead,
ProjectSpeciesEnum,
UnitRead,
VariableRead,
} from "../../app/backendApi";
Expand Down Expand Up @@ -39,10 +40,13 @@ const MapVariablesTab: React.FC<Props> = ({
compound,
}: Props) => {
const [dosings, setDosing] = React.useState<
{ key: number; hasDosingSelected: boolean, projectId: number }[]
{ key: number; hasDosingSelected: boolean; projectId: number, species: ProjectSpeciesEnum | undefined }[]
>([]);
const [linkToPds, setLinkToPd] = React.useState<
{ key: number; hasPdSelected: boolean, projectId: number }[]
{ key: number; hasPdSelected: boolean; projectId: number, species: ProjectSpeciesEnum | undefined }[]
>([]);
const [lagTimes, setLagTimes] = React.useState<
{ key: number; hasLagTimeSelected: boolean; projectId: number, species: ProjectSpeciesEnum | undefined }[]
>([]);

const iconRef = React.useRef<HTMLDivElement | null>(null);
Expand All @@ -54,6 +58,10 @@ const MapVariablesTab: React.FC<Props> = ({
.filter(({ projectId }) => projectId === project?.id)
.map(({ hasPdSelected }) => hasPdSelected)
.some(Boolean);
const isAnyLagTimeSelected = lagTimes
.filter(({ projectId }) => projectId === project?.id)
.map(({ hasLagTimeSelected }) => hasLagTimeSelected)
.some(Boolean);
const isPreclinical = project.species !== "H" && model.is_library_model;
const concentrationUnit = units.find((unit) => unit.symbol === "pmol/L");
const amountUnit = isPreclinical
Expand Down Expand Up @@ -154,18 +162,38 @@ const MapVariablesTab: React.FC<Props> = ({

const updateDosings = (key: number, value: boolean) => {
setDosing((prevDosings) => [
...prevDosings.filter(({ key: dosingKey }) => key !== dosingKey),
{ key, hasDosingSelected: value, projectId: project?.id },
...prevDosings.filter(({ key: dosingKey, species, projectId }) => key !== dosingKey && species === project.species && projectId === project.id),
{ key, hasDosingSelected: value, projectId: project?.id, species: project?.species },
]);
};

const updateLinksToPd = (key: number, value: boolean) => {
setLinkToPd((prevLinks) => [
...prevLinks.filter(({ key: linkKey }) => key !== linkKey),
{ key, hasPdSelected: value, projectId: project?.id },
...prevLinks.filter(({ key: linkKey, species, projectId }) => key !== linkKey && species === project.species && projectId === project.id),
{ key, hasPdSelected: value, projectId: project?.id, species: project?.species },
]);
};

const updateLagTimes = (key: number, value: boolean) => {
setLagTimes((prevLags) => [
...prevLags.filter(({ key: lagKey, species, projectId }) => key !== lagKey && species === project.species && projectId === project.id),
{ key, hasLagTimeSelected: value, projectId: project?.id, species: project?.species },
]);
};

const sortVariables = (variable1: VariableRead, variable2: VariableRead) => {
if (variable1.name.startsWith('C') && variable2.name.startsWith('A')) {
return -1;
}

if (variable1.name.startsWith('A') && variable2.name.startsWith('C')) {
return 1;
}

return variable1.name < variable2.name ? -1 : 1;
}


return (
<TableContainer sx={{ width: "90%" }}>
<Table>
Expand Down Expand Up @@ -196,7 +224,7 @@ const MapVariablesTab: React.FC<Props> = ({
<TableCell>
<div style={{ ...defaultHeaderSx }}>
{" "}
Lag Time
Lag Time <span style={{ color: "red" }}>*</span>
<HelpButton title={"Lag Time"}>{lagTimeHelp}</HelpButton>
</div>
</TableCell>
Expand Down Expand Up @@ -265,7 +293,7 @@ const MapVariablesTab: React.FC<Props> = ({
<TableCell colSpan={5}>No variables found</TableCell>
</TableRow>
)}
{timeVaryingVariables.map((variable) => (
{timeVaryingVariables.sort(sortVariables).map((variable) => (
<VariableRow
key={variable.id}
variable={variable}
Expand All @@ -280,6 +308,8 @@ const MapVariablesTab: React.FC<Props> = ({
isAnyDosingSelected={isAnyDosingSelected}
updateLinksToPd={updateLinksToPd}
isAnyLinkToPdSelected={isAnyLinkToPdSelected}
updateLagTimes={updateLagTimes}
isAnyLagTimeSelected={isAnyLagTimeSelected}
/>
))}
</TableBody>
Expand Down
43 changes: 28 additions & 15 deletions frontend-v2/src/features/model/VariableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ interface Props {
isAnyDosingSelected: boolean;
updateLinksToPd: (key: number, value: boolean) => void;
isAnyLinkToPdSelected: boolean;
updateLagTimes: (key: number, value: boolean) => void;
isAnyLagTimeSelected: boolean;
}

type DerivedVariableType = "RO" | "FUP" | "BPR" | "TLG";
Expand All @@ -57,6 +59,8 @@ const VariableRow: React.FC<Props> = ({
isAnyDosingSelected,
updateLinksToPd,
isAnyLinkToPdSelected,
updateLagTimes,
isAnyLagTimeSelected,
}) => {
const {
fields: mappings,
Expand Down Expand Up @@ -125,6 +129,21 @@ const VariableRow: React.FC<Props> = ({
: mappings.find((mapping) => mapping.pk_variable === variable.id) !==
undefined;

const onClickDerived = (type: DerivedVariableType) => () => {
const index = derivedIndex(type);
return index >= 0 ? removeDerived(index) : addDerived(type);
};

const derivedIndex = (type: DerivedVariableType) => {
return derivedVariables.findIndex(
(ro) => ro.pk_variable === variable.id && ro.type === type,
);
};

const isLinkedTo = (type: DerivedVariableType) => {
return derivedIndex(type) >= 0;
};

useEffect(() => {
updateDosings(variable.id, hasProtocol);
}, [hasProtocol]);
Expand All @@ -133,6 +152,10 @@ const VariableRow: React.FC<Props> = ({
updateLinksToPd(variable.id, linkToPD);
}, [linkToPD]);

useEffect(() => {
updateLagTimes(variable.id, isLinkedTo("TLG"));
}, [isLinkedTo("TLG")]);

if (
variable.constant ||
variable.name === "t" ||
Expand Down Expand Up @@ -247,21 +270,6 @@ const VariableRow: React.FC<Props> = ({
derivedVariablesRemove(index);
};

const onClickDerived = (type: DerivedVariableType) => () => {
const index = derivedIndex(type);
return index >= 0 ? removeDerived(index) : addDerived(type);
};

const derivedIndex = (type: DerivedVariableType) => {
return derivedVariables.findIndex(
(ro) => ro.pk_variable === variable.id && ro.type === type,
);
};

const isLinkedTo = (type: DerivedVariableType) => {
return derivedIndex(type) >= 0;
};

const noMapToPD = isPD || effectVariable === undefined || !isConcentration;
const noDerivedVariables = !isConcentration || isPD;
const isC1 = model.is_library_model && variable.qname.endsWith(".C1");
Expand Down Expand Up @@ -315,6 +323,11 @@ const VariableRow: React.FC<Props> = ({
<FormControlLabel
control={
<MuiCheckbox
sx={{
"& .MuiSvgIcon-root": {
color: isAnyLagTimeSelected ? "inherit" : "red",
},
}}
checked={isLinkedTo("TLG")}
onClick={onClickDerived("TLG")}
data-cy={`checkbox-tlag-${variable.name}`}
Expand Down
66 changes: 35 additions & 31 deletions frontend-v2/src/features/simulation/Simulations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ const Simulations: React.FC = () => {
setParametersHeight(height);
}, [parametersRef?.current?.clientHeight])

const updateWindowDimensions = () => window.innerWidth < 1000 && setLayout('horizontal');
window.addEventListener("resize", updateWindowDimensions);

// reset form and sliders if simulation changes
useEffect(() => {
Expand Down Expand Up @@ -495,8 +497,8 @@ const Simulations: React.FC = () => {
};

return (
<Grid container xl={12} sx={{ marginBottom: layout === 'horizontal' ? `${parametersHeight}px` : 0}}>
<Grid item xs={layout === "vertical" ? 7 : 12}>
<Grid container sx={{ marginBottom: layout === 'vertical' ? 0 : `${parametersHeight}px` }}>
<Grid item xl={layout === "vertical" ? 8 : 12} md={layout === "vertical" ? 7 : 12} xs={layout === "vertical" ? 6 : 12}>
<Stack direction={"row"} alignItems={"center"}>
<DropdownButton
useIcon={false}
Expand All @@ -507,33 +509,6 @@ const Simulations: React.FC = () => {
Add new plot
</DropdownButton>
</Stack>
<Grid container spacing={1}>
{plots.map((plot, index) => (
<Grid item xs={12} xl={layout === "vertical" ? 12 : 6} key={index}>
{data && model ? (
<SimulationPlotView
index={index}
plot={plot}
data={data}
variables={variables || []}
control={control}
setValue={setValue}
remove={removePlot}
units={units}
compound={compound}
model={model}
/>
) : (
<div>Loading...</div>
)}
</Grid>
))}
</Grid>
<Snackbar open={Boolean(simulateError)} autoHideDuration={6000}>
<Alert severity="error">
Error simulating model: {simulateError?.error || "unknown error"}
</Alert>
</Snackbar>
{plots.length > 0 && (
<>
<Stack
Expand Down Expand Up @@ -561,15 +536,44 @@ const Simulations: React.FC = () => {
</Stack>
</>
)}
<Grid container spacing={1}>
{plots.map((plot, index) => (
<Grid item xl={layout === "vertical" ? 12 : 6} md={layout === "vertical" ? 12 : 6} xs={layout === "vertical" ? 12 : 12} key={index}>
{data && model ? (
<SimulationPlotView
index={index}
plot={plot}
data={data}
variables={variables || []}
control={control}
setValue={setValue}
remove={removePlot}
units={units}
compound={compound}
model={model}
/>
) : (
<div>Loading...</div>
)}
</Grid>
))}
</Grid>
<Snackbar open={Boolean(simulateError)} autoHideDuration={6000}>
<Alert severity="error">
Error simulating model: {simulateError?.error || "unknown error"}
</Alert>
</Snackbar>
</Grid>
<Grid
ref={parametersRef}
item
xl={layout === "vertical" ? 4 : 12}
xl={layout === "vertical" ? 3 : 12}
md={layout === "vertical" ? 4 : 12}
xs={layout === "vertical" ? 5 : 12}
sx={
layout === "vertical"
? { position: "fixed", right: 0, paddingLeft: "1rem", width: '100%' }
: { position: "fixed", bottom: 0, height: 'auto', backgroundColor: 'white', width: '-webkit-fill-available' }
: { position: "fixed", bottom: 0, paddingBottom: '3rem', height: 'auto', backgroundColor: 'white', width: '-webkit-fill-available' }
}
>
<Stack direction="column">
Expand Down
23 changes: 15 additions & 8 deletions frontend-v2/src/features/trial/Doses.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useEffect } from "react";
import { TableCell, TableRow, IconButton, Button } from "@mui/material";
import { TableCell, TableRow, IconButton, Button, Stack } from "@mui/material";
import {
ProjectRead,
Protocol,
Expand All @@ -14,6 +14,7 @@ import UnitField from "../../components/UnitField";
import FloatField from "../../components/FloatField";
import IntegerField from "../../components/IntegerField";
import useDirty from "../../hooks/useDirty";
import HelpButton from "../../components/HelpButton";

interface Props {
project: ProjectRead;
Expand Down Expand Up @@ -186,13 +187,19 @@ const Doses: React.FC<Props> = ({ project, protocol, units }) => {
</TableCell>
</TableRow>
))}
<Button
onClick={handleAddRow}
variant="outlined"
sx={{ fontSize: ".5rem" }}
>
Add New Row
</Button>
<Stack direction='row' width='max-content'>
<Button
onClick={handleAddRow}
variant="outlined"
sx={{ fontSize: ".5rem" }}
>
Add New Row
</Button>
<HelpButton title="Add Dose Line">
Adding an additional dosing line allows defining complex dosing
regimens (e.g. changing dosing frequency and/or dosing levels)
</HelpButton>
</Stack>
</>
);
};
Expand Down
7 changes: 1 addition & 6 deletions frontend-v2/src/features/trial/Protocols.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,7 @@ const Protocols: React.FC = () => {
<TableCell align="right">
<div style={{ ...defaultHeaderSx }}>
{" "}
Add Dose Line{" "}
<HelpButton title="Add Dose Line">
Adding an additional dosing line allows defining complex
dosing regimens (e.g. changing dosing frequency and/or dosing
levels)
</HelpButton>
Remove{" "}
</div>
</TableCell>
</TableRow>
Expand Down

0 comments on commit 24d4804

Please sign in to comment.