From 7406395d38432abf66411ced12ec8f1e7938e975 Mon Sep 17 00:00:00 2001 From: niestrow Date: Fri, 8 Nov 2024 16:36:32 +0100 Subject: [PATCH 01/12] PKPDX-29 Add headers to results tables --- .../src/features/results/ResultsTab.tsx | 50 +++++++++++++++++-- .../src/features/results/ResultsTable.tsx | 14 +++--- 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/frontend-v2/src/features/results/ResultsTab.tsx b/frontend-v2/src/features/results/ResultsTab.tsx index e7fa039d..b459f335 100644 --- a/frontend-v2/src/features/results/ResultsTab.tsx +++ b/frontend-v2/src/features/results/ResultsTab.tsx @@ -5,6 +5,7 @@ import { MenuItem, Select, SelectChangeEvent, + Typography, } from "@mui/material"; import { TimeInterval } from "../../App"; @@ -146,6 +147,46 @@ const ResultsTab: FC = () => { rowFilter2 = columns === "intervals" ? variableSelect : intervalSelect; } + const generateTableHeader = () => { + if (rows === "parameters" || columns === "parameters") { + const var1 = rows === "parameters" ? columns : rows; + + return ( +
+ All Secondary PK parameters of all selected {var1} of{" "} + {rowFilter1?.label?.toLowerCase()} ' + {rowFilter1?.items?.[rowFilter1?.value.toString()]?.name}' and{" "} + {rowFilter2?.label.toLowerCase()} ' + {rowFilter2?.items?.[rowFilter2?.value.toString()]?.name}'` +
+ ); + } + + const var1 = + rowFilter1?.label === "Parameter" + ? rowFilter1?.items?.[rowFilter1?.value.toString()]?.name + : rowFilter2?.items?.[rowFilter2?.value.toString()]?.name; + const var2 = + rowFilter1?.label === "Parameter" ? rowFilter2?.label : rowFilter1?.label; + const var3 = + rowFilter1?.label === "Parameter" + ? rowFilter2?.items?.[rowFilter2?.value.toString()]?.name + : rowFilter1?.items?.[rowFilter1?.value.toString()]?.name; + + const desc1 = () => { + if (var2 === "Interval") return "and time interval"; + if (var2 === "Group") return "of group"; + if (var2 === "Variable") return "for variable"; + }; + + return ( +
+ Secondary PK Parameter ({var1}) of all {columns} for all {rows}{" "} + {desc1()} '{var3}' +
+ ); + }; + try { return ( <> @@ -156,7 +197,7 @@ const ResultsTab: FC = () => { onChange={(event) => setColumns(event.target.value)} label="Columns" labelId="columns-label" - sx={{ minWidth: '10rem', marginRight: '1rem'}} + sx={{ minWidth: "10rem", marginRight: "1rem" }} > {options .filter((option) => option.value !== rows) @@ -176,7 +217,7 @@ const ResultsTab: FC = () => { onChange={handleRowsChange} label="Rows" labelId="rows-label" - sx={{ minWidth: '10rem', marginRight: '1rem'}} + sx={{ minWidth: "10rem", marginRight: "1rem" }} > {options .filter((option) => option.value !== columns) @@ -196,7 +237,7 @@ const ResultsTab: FC = () => { label={rowFilter1?.label} value={rowFilter1?.value.toString()} onChange={rowFilter1?.filter} - sx={{ minWidth: '10rem', marginRight: '1rem'}} + sx={{ minWidth: "10rem", marginRight: "1rem" }} > {rowFilter1?.items.map((item, index) => { return ( @@ -214,7 +255,7 @@ const ResultsTab: FC = () => { label={rowFilter2?.label} value={rowFilter2?.value.toString()} onChange={rowFilter2?.filter} - sx={{ minWidth: '10rem'}} + sx={{ minWidth: "10rem" }} > {rowFilter2?.items.map((item, index) => { return ( @@ -225,6 +266,7 @@ const ResultsTab: FC = () => { })} + {generateTableHeader()} Date: Fri, 8 Nov 2024 16:40:16 +0100 Subject: [PATCH 02/12] Remove unnecessary quotation mark --- frontend-v2/src/features/results/ResultsTab.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend-v2/src/features/results/ResultsTab.tsx b/frontend-v2/src/features/results/ResultsTab.tsx index b459f335..dfcf5963 100644 --- a/frontend-v2/src/features/results/ResultsTab.tsx +++ b/frontend-v2/src/features/results/ResultsTab.tsx @@ -157,7 +157,7 @@ const ResultsTab: FC = () => { {rowFilter1?.label?.toLowerCase()} ' {rowFilter1?.items?.[rowFilter1?.value.toString()]?.name}' and{" "} {rowFilter2?.label.toLowerCase()} ' - {rowFilter2?.items?.[rowFilter2?.value.toString()]?.name}'` + {rowFilter2?.items?.[rowFilter2?.value.toString()]?.name}' ); } From 569a3fb3610c906496fe22a2220b51598da492b9 Mon Sep 17 00:00:00 2001 From: niestrow Date: Tue, 12 Nov 2024 13:05:08 +0100 Subject: [PATCH 03/12] Fix plots being constantly resized when changing layout --- frontend-v2/src/features/simulation/SimulationPlotView.tsx | 2 ++ frontend-v2/src/features/simulation/Simulations.tsx | 4 ---- frontend-v2/src/features/simulation/SimulationsSidePanel.tsx | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/frontend-v2/src/features/simulation/SimulationPlotView.tsx b/frontend-v2/src/features/simulation/SimulationPlotView.tsx index ba423606..ae5543a7 100644 --- a/frontend-v2/src/features/simulation/SimulationPlotView.tsx +++ b/frontend-v2/src/features/simulation/SimulationPlotView.tsx @@ -461,6 +461,8 @@ const SimulationPlotView: FC = ({ // const { dticky, dticky2 } = dticks(rangey, rangey2, plot); const plotLayout: Partial = { + width: 650, + autosize: false, dragmode: "pan", showlegend: shouldShowLegend, shapes: icLines.map((icLine, i) => { diff --git a/frontend-v2/src/features/simulation/Simulations.tsx b/frontend-v2/src/features/simulation/Simulations.tsx index 7d23e294..13c748f3 100644 --- a/frontend-v2/src/features/simulation/Simulations.tsx +++ b/frontend-v2/src/features/simulation/Simulations.tsx @@ -254,10 +254,6 @@ const Simulations: FC = () => { const defaultLayout = layoutOptions[0]?.value; const [layout, setLayout] = useState(defaultLayout); - const updateWindowDimensions = () => - window.innerWidth < 1000 && setLayout("horizontal"); - window.addEventListener("resize", updateWindowDimensions); - // reset form and sliders if simulation changes useEffect(() => { if (simulation && variables) { diff --git a/frontend-v2/src/features/simulation/SimulationsSidePanel.tsx b/frontend-v2/src/features/simulation/SimulationsSidePanel.tsx index af5b0d2e..3b765eaf 100644 --- a/frontend-v2/src/features/simulation/SimulationsSidePanel.tsx +++ b/frontend-v2/src/features/simulation/SimulationsSidePanel.tsx @@ -213,7 +213,6 @@ export const SimulationsSidePanel = ({ checked={layout === value} onChange={() => { setLayout(value); - window.dispatchEvent(new Event("resize")); }} /> } From 1c80400307e9519d604e1f1ea0b3b0d946781801 Mon Sep 17 00:00:00 2001 From: niestrow Date: Tue, 12 Nov 2024 15:37:32 +0100 Subject: [PATCH 04/12] Fix plots being constantly resized when changing layout --- frontend-v2/src/features/simulation/SimulationPlotView.tsx | 5 ++--- frontend-v2/src/features/simulation/Simulations.tsx | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/frontend-v2/src/features/simulation/SimulationPlotView.tsx b/frontend-v2/src/features/simulation/SimulationPlotView.tsx index ae5543a7..ebcc677f 100644 --- a/frontend-v2/src/features/simulation/SimulationPlotView.tsx +++ b/frontend-v2/src/features/simulation/SimulationPlotView.tsx @@ -461,8 +461,8 @@ const SimulationPlotView: FC = ({ // const { dticky, dticky2 } = dticks(rangey, rangey2, plot); const plotLayout: Partial = { - width: 650, - autosize: false, + autosize: true, + width: 550, dragmode: "pan", showlegend: shouldShowLegend, shapes: icLines.map((icLine, i) => { @@ -640,7 +640,6 @@ const SimulationPlotView: FC = ({ layout={plotLayout} style={{ width: "100%", height: "100%" }} config={config} - useResizeHandler={true} /> Date: Wed, 13 Nov 2024 17:13:36 +0100 Subject: [PATCH 05/12] Added controlling of plots width in dependence to resolution/scale --- .../simulation/SimulationPlotView.tsx | 24 ++++++++++++++++--- .../src/features/simulation/Simulations.tsx | 1 + 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/frontend-v2/src/features/simulation/SimulationPlotView.tsx b/frontend-v2/src/features/simulation/SimulationPlotView.tsx index ebcc677f..81aec41e 100644 --- a/frontend-v2/src/features/simulation/SimulationPlotView.tsx +++ b/frontend-v2/src/features/simulation/SimulationPlotView.tsx @@ -266,6 +266,7 @@ interface SimulationPlotProps { model: CombinedModelRead; visibleGroups: string[]; shouldShowLegend: boolean; + layout: string; } const SimulationPlotView: FC = ({ @@ -281,7 +282,8 @@ const SimulationPlotView: FC = ({ compound, model, visibleGroups, - shouldShowLegend + shouldShowLegend, + layout }) => { const projectId = useSelector( (state: RootState) => state.main.selectedProject, @@ -460,9 +462,25 @@ const SimulationPlotView: FC = ({ // axis dticks // const { dticky, dticky2 } = dticks(rangey, rangey2, plot); + const getPlotWidth = () => { + if (window.innerWidth > 1900 ) { + return 650 + } + + if (window.innerWidth > 1700) { + return 550 + } + + if (window.innerWidth > 1500) { + return screen.width > 1400 ? 450 : 650 + } + + return 680; + } + const plotLayout: Partial = { - autosize: true, - width: 550, + autosize: false, + width: getPlotWidth(), dragmode: "pan", showlegend: shouldShowLegend, shapes: icLines.map((icLine, i) => { diff --git a/frontend-v2/src/features/simulation/Simulations.tsx b/frontend-v2/src/features/simulation/Simulations.tsx index 9bce10d8..28a5bb3b 100644 --- a/frontend-v2/src/features/simulation/Simulations.tsx +++ b/frontend-v2/src/features/simulation/Simulations.tsx @@ -501,6 +501,7 @@ const Simulations: FC = () => { model={model} visibleGroups={visibleGroups} shouldShowLegend={shouldShowLegend} + layout={layout} /> ) : (
Loading...
From 478d66f25b1fd4cc9eb65f7fdca44491c7df0bf7 Mon Sep 17 00:00:00 2001 From: niestrow Date: Wed, 20 Nov 2024 09:21:18 +0100 Subject: [PATCH 06/12] PKPDX-30 Added collapsible sidebar, added animations for main content and simulations sidebar --- frontend-v2/src/features/main/MainContent.tsx | 1 + frontend-v2/src/features/main/Sidebar.css | 21 +++ frontend-v2/src/features/main/Sidebar.tsx | 157 ++++++++++++++++-- .../src/features/simulation/Simulations.tsx | 34 +--- .../simulation/SimulationsSidePanel.tsx | 3 + 5 files changed, 169 insertions(+), 47 deletions(-) create mode 100644 frontend-v2/src/features/main/Sidebar.css diff --git a/frontend-v2/src/features/main/MainContent.tsx b/frontend-v2/src/features/main/MainContent.tsx index 94ee400f..afd7a58c 100644 --- a/frontend-v2/src/features/main/MainContent.tsx +++ b/frontend-v2/src/features/main/MainContent.tsx @@ -28,6 +28,7 @@ function TabPanel(props: TabPanelProps) { hidden={value !== index} id={`simple-tabpanel-${index}`} aria-labelledby={`simple-tab-${index}`} + style={{ width: '100%'}} {...other} > {children} diff --git a/frontend-v2/src/features/main/Sidebar.css b/frontend-v2/src/features/main/Sidebar.css new file mode 100644 index 00000000..4ae524a6 --- /dev/null +++ b/frontend-v2/src/features/main/Sidebar.css @@ -0,0 +1,21 @@ +@keyframes onExpand { + 0% {transform: translate(-190px); overflow-X: 'visible';} + 100% {transform: translate(0); overflow-x: 'hidden';} + } + + @keyframes onCollapse { + 0% {transform: translate(190px); overflow-X: 'visible';} + 100% {transform: translate(0); overflow-x: 'hidden';} + } + +.on-expand { + animation-name: onExpand; + animation-duration: .35s; + animation-timing-function: linear; +} + +.on-collapse { + animation-name: onCollapse; + animation-duration: .35s; + animation-timing-function: linear; +} \ No newline at end of file diff --git a/frontend-v2/src/features/main/Sidebar.tsx b/frontend-v2/src/features/main/Sidebar.tsx index 6408ebd4..124eefed 100644 --- a/frontend-v2/src/features/main/Sidebar.tsx +++ b/frontend-v2/src/features/main/Sidebar.tsx @@ -42,8 +42,12 @@ import ContactSupportIcon from "@mui/icons-material/ContactSupport"; import TableViewIcon from "@mui/icons-material/TableView"; import "@fontsource/comfortaa"; // Defaults to weight 400 import useSubjectGroups from "../../hooks/useSubjectGroups"; +import ArrowBackIcon from "@mui/icons-material/ArrowBack"; +import ArrowForwardIcon from "@mui/icons-material/ArrowForward"; +import "./Sidebar.css"; -const drawerWidth = 240; +const drawerExpandedWidth = 240; +const drawerCollapsedWidth = 50; export default function Sidebar() { const dispatch = useAppDispatch(); @@ -208,7 +212,34 @@ export default function Sidebar() { (step) => step !== projectsPage && step !== helpPage, ); - const drawer = ( + const [isExpanded, setIsExpanded] = useState(true); + const onCollapse = () => { + const element = document.getElementById("main-content"); + element?.classList.remove("on-expand"); + element?.classList.add("on-collapse"); + + const simulationsNav = document.getElementById("simulations-content"); + if (simulationsNav) { + simulationsNav?.classList.remove("on-expand"); + simulationsNav?.classList.add("on-collapse"); + } + setIsExpanded(false); + }; + + const onExpand = () => { + const element = document.getElementById("main-content"); + element?.classList.remove("on-collapse"); + element?.classList.add("on-expand"); + + const simulationsNav = document.getElementById("simulations-content"); + if (simulationsNav) { + simulationsNav?.classList.remove("on-collapse"); + simulationsNav?.classList.add("on-expand"); + } + setIsExpanded(true); + }; + + const drawerMobile = (
@@ -276,14 +307,102 @@ export default function Sidebar() {
); + const drawer = ( +
+ {isExpanded ? ( + + + + ) : ( + + + + )} + + + + + + {projectsPage?.value in errorComponents + ? errorComponents[projectsPage?.value] + : icons[projectsPage?.value]} + + + + + + {projectIdOrZero !== 0 && ( + <> + {isExpanded ? ( + + STEPS + + ) : ( + + )} + + + {steps.map(({ key, value }) => ( + + + + {value in errorComponents + ? errorComponents[value] + : icons[value]} + + + + + ))} + + + )} + {isExpanded && ( + + pkpdx version {import.meta.env.VITE_APP_VERSION?.slice(0, 7) || "dev"} + + )} +
+ ); + return ( - + {/* The implementation can be swapped with js to avoid SEO duplication of links. */} @@ -377,11 +501,11 @@ export default function Sidebar() { display: { xs: "block", sm: "none" }, "& .MuiDrawer-paper": { boxSizing: "border-box", - width: drawerWidth, + width: drawerExpandedWidth, }, }} > - {drawer} + {drawerMobile} )} diff --git a/frontend-v2/src/features/simulation/Simulations.tsx b/frontend-v2/src/features/simulation/Simulations.tsx index 28a5bb3b..421b6582 100644 --- a/frontend-v2/src/features/simulation/Simulations.tsx +++ b/frontend-v2/src/features/simulation/Simulations.tsx @@ -43,38 +43,6 @@ import { getConstVariables } from "../model/resetToSpeciesDefaults"; import useSubjectGroups from "../../hooks/useSubjectGroups"; import useExportSimulation from "./useExportSimulation"; import { SimulationsSidePanel } from "./SimulationsSidePanel"; -import { getTableHeight } from "../../shared/calculateTableHeights"; - -const PlotsWidthSteps = [ - { - minHeight: "1100", - tableHeight: "75vw", - }, - { - minHeight: "1000", - tableHeight: "72vw", - }, - { - minHeight: "900", - tableHeight: "70vw", - }, - { - minHeight: "800", - tableHeight: "65vw", - }, - { - minHeight: "700", - tableHeight: "60vw", - }, - { - minHeight: "600", - tableHeight: "55vw", - }, - { - minHeight: "500", - tableHeight: "53vw", - }, -]; type SliderValues = { [key: number]: number }; @@ -474,7 +442,7 @@ const Simulations: FC = () => { diff --git a/frontend-v2/src/features/simulation/SimulationsSidePanel.tsx b/frontend-v2/src/features/simulation/SimulationsSidePanel.tsx index 3b765eaf..9f732b14 100644 --- a/frontend-v2/src/features/simulation/SimulationsSidePanel.tsx +++ b/frontend-v2/src/features/simulation/SimulationsSidePanel.tsx @@ -141,12 +141,15 @@ export const SimulationsSidePanel = ({ return ReactDOM.createPortal( Date: Wed, 20 Nov 2024 19:07:27 +0100 Subject: [PATCH 07/12] Refactor of collapsible sidebar, added context controlling the classes and expansion of sidebar --- frontend-v2/src/App.css | 22 +++++++++ frontend-v2/src/App.tsx | 7 ++- frontend-v2/src/features/main/Sidebar.css | 21 --------- frontend-v2/src/features/main/Sidebar.tsx | 46 ++++--------------- .../simulation/SimulationsSidePanel.tsx | 11 +++-- .../contexts/CollapsibleSidebarContext.tsx | 46 +++++++++++++++++++ 6 files changed, 90 insertions(+), 63 deletions(-) delete mode 100644 frontend-v2/src/features/main/Sidebar.css create mode 100644 frontend-v2/src/shared/contexts/CollapsibleSidebarContext.tsx diff --git a/frontend-v2/src/App.css b/frontend-v2/src/App.css index 353df09f..47324435 100644 --- a/frontend-v2/src/App.css +++ b/frontend-v2/src/App.css @@ -26,6 +26,28 @@ color: rgb(112, 76, 182); } +@keyframes onExpand { + 0% {transform: translate(-190px); overflow-X: 'visible';} + 100% {transform: translate(0); overflow-x: 'hidden';} +} + +@keyframes onCollapse { + 0% {transform: translate(190px); overflow-X: 'visible';} + 100% {transform: translate(0); overflow-x: 'hidden';} +} + +.on-expand { + animation-name: onExpand; + animation-duration: .35s; + animation-timing-function: linear; +} + +.on-collapse { + animation-name: onCollapse; + animation-duration: .35s; + animation-timing-function: linear; +} + @keyframes App-logo-float { 0% { transform: translateY(0); diff --git a/frontend-v2/src/App.tsx b/frontend-v2/src/App.tsx index ff20d940..0be05f95 100644 --- a/frontend-v2/src/App.tsx +++ b/frontend-v2/src/App.tsx @@ -16,6 +16,7 @@ import "react-toastify/dist/ReactToastify.css"; import { SimulationContext } from "./contexts/SimulationContext"; import { SimulateResponse } from "./app/backendApi"; +import { CollapsibleSidebarProvider } from "./shared/contexts/CollapsibleSidebarContext"; export type TimeInterval = { start: number; @@ -80,8 +81,10 @@ function App() { {isAuth ? ( <> - - + + + + ) : ( diff --git a/frontend-v2/src/features/main/Sidebar.css b/frontend-v2/src/features/main/Sidebar.css deleted file mode 100644 index 4ae524a6..00000000 --- a/frontend-v2/src/features/main/Sidebar.css +++ /dev/null @@ -1,21 +0,0 @@ -@keyframes onExpand { - 0% {transform: translate(-190px); overflow-X: 'visible';} - 100% {transform: translate(0); overflow-x: 'hidden';} - } - - @keyframes onCollapse { - 0% {transform: translate(190px); overflow-X: 'visible';} - 100% {transform: translate(0); overflow-x: 'hidden';} - } - -.on-expand { - animation-name: onExpand; - animation-duration: .35s; - animation-timing-function: linear; -} - -.on-collapse { - animation-name: onCollapse; - animation-duration: .35s; - animation-timing-function: linear; -} \ No newline at end of file diff --git a/frontend-v2/src/features/main/Sidebar.tsx b/frontend-v2/src/features/main/Sidebar.tsx index 124eefed..b30d2262 100644 --- a/frontend-v2/src/features/main/Sidebar.tsx +++ b/frontend-v2/src/features/main/Sidebar.tsx @@ -44,7 +44,8 @@ import "@fontsource/comfortaa"; // Defaults to weight 400 import useSubjectGroups from "../../hooks/useSubjectGroups"; import ArrowBackIcon from "@mui/icons-material/ArrowBack"; import ArrowForwardIcon from "@mui/icons-material/ArrowForward"; -import "./Sidebar.css"; +import { useCollapsibleSidebar } from "../../shared/contexts/CollapsibleSidebarContext"; +import '../../App.css' const drawerExpandedWidth = 240; const drawerCollapsedWidth = 50; @@ -150,6 +151,8 @@ export default function Sidebar() { setMobileOpen(!mobileOpen); }; + const { onCollapse, onExpand, isExpanded, animationClasses } = useCollapsibleSidebar(); + const pageKeys = Object.keys(PageName); const pageValues = Object.values(PageName); @@ -212,33 +215,6 @@ export default function Sidebar() { (step) => step !== projectsPage && step !== helpPage, ); - const [isExpanded, setIsExpanded] = useState(true); - const onCollapse = () => { - const element = document.getElementById("main-content"); - element?.classList.remove("on-expand"); - element?.classList.add("on-collapse"); - - const simulationsNav = document.getElementById("simulations-content"); - if (simulationsNav) { - simulationsNav?.classList.remove("on-expand"); - simulationsNav?.classList.add("on-collapse"); - } - setIsExpanded(false); - }; - - const onExpand = () => { - const element = document.getElementById("main-content"); - element?.classList.remove("on-collapse"); - element?.classList.add("on-expand"); - - const simulationsNav = document.getElementById("simulations-content"); - if (simulationsNav) { - simulationsNav?.classList.remove("on-collapse"); - simulationsNav?.classList.add("on-expand"); - } - setIsExpanded(true); - }; - const drawerMobile = (
@@ -310,11 +286,11 @@ export default function Sidebar() { const drawer = (
{isExpanded ? ( - + ) : ( - + )} @@ -341,7 +317,6 @@ export default function Sidebar() { {isExpanded ? ( {/* The implementation can be swapped with js to avoid SEO duplication of links. */} )} - , +
, portalRoot, ); }; diff --git a/frontend-v2/src/shared/contexts/CollapsibleSidebarContext.tsx b/frontend-v2/src/shared/contexts/CollapsibleSidebarContext.tsx new file mode 100644 index 00000000..ed661ebd --- /dev/null +++ b/frontend-v2/src/shared/contexts/CollapsibleSidebarContext.tsx @@ -0,0 +1,46 @@ +import { createContext, ReactNode, useContext, useState } from 'react'; + + +const CollapsibleSidebarContext = createContext({ + onCollapse: () => { return }, + onExpand: () => { return }, + isExpanded: true, + animationClasses: '' +}); + +export const CollapsibleSidebarProvider = ({ children }: { children: ReactNode }) => { + const [isExpanded, setIsExpanded] = useState(true); + const [hasExpandedChanged, setHasExpandedChanged] = useState(false); + const onCollapse = () => { + setHasExpandedChanged(true); + setIsExpanded(false); + }; + + const onExpand = () => { + setHasExpandedChanged(true); + setIsExpanded(true); + }; + + + const getAnimationClasses = () => { + if (!hasExpandedChanged) return ''; + return isExpanded ? 'on-expand' : 'on-collapse'; + } + + const animationClasses = getAnimationClasses(); + + return ( + + {children} + + ); +}; + +export const useCollapsibleSidebar = () => useContext(CollapsibleSidebarContext); From 7be26bfd19517f1f8299f46d157fcdc1014f5395 Mon Sep 17 00:00:00 2001 From: niestrow Date: Wed, 20 Nov 2024 19:09:18 +0100 Subject: [PATCH 08/12] Revert div to box --- .../src/features/simulation/SimulationsSidePanel.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend-v2/src/features/simulation/SimulationsSidePanel.tsx b/frontend-v2/src/features/simulation/SimulationsSidePanel.tsx index 50d3b4f9..1ab4df17 100644 --- a/frontend-v2/src/features/simulation/SimulationsSidePanel.tsx +++ b/frontend-v2/src/features/simulation/SimulationsSidePanel.tsx @@ -143,9 +143,9 @@ export const SimulationsSidePanel = ({ if (!portalRoot) return null; return ReactDOM.createPortal( -
-
, + , portalRoot, ); }; From 74c47008704483992f69e5925ffa5287956a8645 Mon Sep 17 00:00:00 2001 From: Jim O'Donnell Date: Thu, 21 Nov 2024 11:07:48 +0000 Subject: [PATCH 09/12] fix: merge conflict --- frontend-v2/src/features/main/Sidebar.tsx | 48 ++++++++++++++--------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/frontend-v2/src/features/main/Sidebar.tsx b/frontend-v2/src/features/main/Sidebar.tsx index be4479c5..320323b2 100644 --- a/frontend-v2/src/features/main/Sidebar.tsx +++ b/frontend-v2/src/features/main/Sidebar.tsx @@ -45,7 +45,7 @@ import useSubjectGroups from "../../hooks/useSubjectGroups"; import ArrowBackIcon from "@mui/icons-material/ArrowBack"; import ArrowForwardIcon from "@mui/icons-material/ArrowForward"; import { useCollapsibleSidebar } from "../../shared/contexts/CollapsibleSidebarContext"; -import '../../App.css' +import "../../App.css"; const drawerExpandedWidth = 240; const drawerCollapsedWidth = 50; @@ -156,7 +156,13 @@ export default function Sidebar() { setMobileOpen(!mobileOpen); }; - const { onCollapse, onExpand, setHasSimulationsExpandedChanged, isExpanded, animationClasses } = useCollapsibleSidebar(); + const { + onCollapse, + onExpand, + setHasSimulationsExpandedChanged, + isExpanded, + animationClasses, + } = useCollapsibleSidebar(); const pageKeys = Object.keys(PageName); const pageValues = Object.values(PageName); @@ -297,11 +303,19 @@ export default function Sidebar() { const drawer = (
{isExpanded ? ( - + ) : ( - + )} @@ -508,20 +522,18 @@ export default function Sidebar() { {drawer} - {selectedPage === PageName.SIMULATIONS && ( - - )} + Date: Thu, 21 Nov 2024 12:29:19 +0100 Subject: [PATCH 10/12] Update frontend-v2/src/features/main/Sidebar.tsx update aria-label to more specific label Co-authored-by: Jim O'Donnell --- frontend-v2/src/features/main/Sidebar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend-v2/src/features/main/Sidebar.tsx b/frontend-v2/src/features/main/Sidebar.tsx index 320323b2..411b4b5c 100644 --- a/frontend-v2/src/features/main/Sidebar.tsx +++ b/frontend-v2/src/features/main/Sidebar.tsx @@ -486,7 +486,7 @@ export default function Sidebar() { }, flexShrink: { sm: 0 }, }} - aria-label="navigation" + aria-label="project navigation" > {/* The implementation can be swapped with js to avoid SEO duplication of links. */} Date: Thu, 21 Nov 2024 13:25:59 +0100 Subject: [PATCH 11/12] Changed aria-label for main navigation; added resizing of plots on window.resize event; added additional plot widths --- frontend-v2/src/features/main/Sidebar.tsx | 4 +- .../simulation/SimulationPlotView.tsx | 41 +++++++++++++++++-- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/frontend-v2/src/features/main/Sidebar.tsx b/frontend-v2/src/features/main/Sidebar.tsx index e99f81f4..1caa5b97 100644 --- a/frontend-v2/src/features/main/Sidebar.tsx +++ b/frontend-v2/src/features/main/Sidebar.tsx @@ -486,7 +486,7 @@ export default function Sidebar() { }, flexShrink: { sm: 0 }, }} - aria-label="project navigation" + aria-label="main" > {/* The implementation can be swapped with js to avoid SEO duplication of links. */} = ({ ); useProtocolListQuery({ projectId: projectId || 0 }, { skip: !projectId }); + const [dimensions, setDimensions] = useState({ + height: window.innerHeight, + width: window.innerWidth, + }); + + useEffect(() => { + const debouncedHandleResize = debounce(function handleResize() { + setDimensions({ + height: window.innerHeight, + width: window.innerWidth, + }); + }, 200); + + window.addEventListener("resize", debouncedHandleResize); + + return () => { + window.removeEventListener("resize", debouncedHandleResize); + }; + }); + const { groups } = useSubjectGroups(); const { subjectBiomarkers } = useDataset(projectId); @@ -463,14 +485,21 @@ const SimulationPlotView: FC = ({ // const { dticky, dticky2 } = dticks(rangey, rangey2, plot); const getPlotWidth = () => { + if (window.innerWidth > 2500) { + return 980; + } + if (window.innerWidth > 2300) { + return 900; + } + if (window.innerWidth > 2100) { + return 750; + } if (window.innerWidth > 1900) { return 650; } - if (window.innerWidth > 1700) { return 550; } - if (window.innerWidth > 1500) { return screen.width > 1400 ? 450 : 650; } @@ -478,9 +507,13 @@ const SimulationPlotView: FC = ({ return 680; }; + const { isExpanded } = useCollapsibleSidebar(); + + const plotWidth = getPlotWidth() + (isExpanded ? 0 : 95); + const plotLayout: Partial = { autosize: false, - width: getPlotWidth(), + width: plotWidth, dragmode: "pan", showlegend: shouldShowLegend, shapes: icLines.map((icLine, i) => { From 7edb41de5f4013cf609f820bbf23b453493b5996 Mon Sep 17 00:00:00 2001 From: niestrow Date: Fri, 22 Nov 2024 13:15:25 +0100 Subject: [PATCH 12/12] Refactored plot widths to be calucalated on container width; Simulation sidebar collapsible sections to be collapsed by default; Dislpay Parameter input below the slider --- .../simulation/SimulationPlotView.tsx | 58 ++++--------------- .../simulation/SimulationSliderView.tsx | 11 ++-- .../src/features/simulation/Simulations.tsx | 35 +++++++++-- .../simulation/SimulationsSidePanel.tsx | 16 ++--- .../contexts/CollapsibleSidebarContext.tsx | 10 +++- 5 files changed, 64 insertions(+), 66 deletions(-) diff --git a/frontend-v2/src/features/simulation/SimulationPlotView.tsx b/frontend-v2/src/features/simulation/SimulationPlotView.tsx index 2ffa2e1e..278d5566 100644 --- a/frontend-v2/src/features/simulation/SimulationPlotView.tsx +++ b/frontend-v2/src/features/simulation/SimulationPlotView.tsx @@ -1,4 +1,4 @@ -import { FC, useEffect, useState } from "react"; +import { FC, useState } from "react"; import createPlotlyComponent from "react-plotly.js/factory"; import { CombinedModelRead, @@ -34,7 +34,6 @@ import { useSelector } from "react-redux"; import { RootState } from "../../app/store"; import useDataset from "../../hooks/useDataset"; import useSubjectGroups from "../../hooks/useSubjectGroups"; -import { useCollapsibleSidebar } from "../../shared/contexts/CollapsibleSidebarContext"; const Plot = createPlotlyComponent(Plotly); // https://github.com/plotly/plotly.js/blob/8c47c16daaa2020468baf9376130e085a4f01ec6/src/components/color/attributes.js#L4-L16 @@ -269,6 +268,9 @@ interface SimulationPlotProps { visibleGroups: string[]; shouldShowLegend: boolean; layout: string; + dimensions: { + width: number; + } } const SimulationPlotView: FC = ({ @@ -285,33 +287,13 @@ const SimulationPlotView: FC = ({ model, visibleGroups, shouldShowLegend, - layout, + dimensions, }) => { const projectId = useSelector( (state: RootState) => state.main.selectedProject, ); useProtocolListQuery({ projectId: projectId || 0 }, { skip: !projectId }); - const [dimensions, setDimensions] = useState({ - height: window.innerHeight, - width: window.innerWidth, - }); - - useEffect(() => { - const debouncedHandleResize = debounce(function handleResize() { - setDimensions({ - height: window.innerHeight, - width: window.innerWidth, - }); - }, 200); - - window.addEventListener("resize", debouncedHandleResize); - - return () => { - window.removeEventListener("resize", debouncedHandleResize); - }; - }); - const { groups } = useSubjectGroups(); const { subjectBiomarkers } = useDataset(projectId); @@ -481,35 +463,17 @@ const SimulationPlotView: FC = ({ ln: { type: "log", dtick: Math.log10(Math.E) }, }; - // axis dticks - // const { dticky, dticky2 } = dticks(rangey, rangey2, plot); - const getPlotWidth = () => { - if (window.innerWidth > 2500) { - return 980; - } - if (window.innerWidth > 2300) { - return 900; - } - if (window.innerWidth > 2100) { - return 750; - } - if (window.innerWidth > 1900) { - return 650; - } - if (window.innerWidth > 1700) { - return 550; - } - if (window.innerWidth > 1500) { - return screen.width > 1400 ? 450 : 650; + const buffor = 10; + const columnCount = screen.width > 2500 ? 3 : 2; + if (screen.width > 1536) { + return dimensions.width / columnCount - buffor; } - return 680; + return dimensions.width - buffor; }; - const { isExpanded } = useCollapsibleSidebar(); - - const plotWidth = getPlotWidth() + (isExpanded ? 0 : 95); + const plotWidth = getPlotWidth(); const plotLayout: Partial = { autosize: false, diff --git a/frontend-v2/src/features/simulation/SimulationSliderView.tsx b/frontend-v2/src/features/simulation/SimulationSliderView.tsx index 9dd62ef9..2bd6737a 100644 --- a/frontend-v2/src/features/simulation/SimulationSliderView.tsx +++ b/frontend-v2/src/features/simulation/SimulationSliderView.tsx @@ -212,8 +212,7 @@ const SimulationSliderView: FC = ({ - - + = ({ valueLabelDisplay="off" aria-labelledby="input-slider" /> - - + + = ({ "aria-labelledby": "input-slider", }} /> - - +
); }; diff --git a/frontend-v2/src/features/simulation/Simulations.tsx b/frontend-v2/src/features/simulation/Simulations.tsx index 7e43d3af..90c66d10 100644 --- a/frontend-v2/src/features/simulation/Simulations.tsx +++ b/frontend-v2/src/features/simulation/Simulations.tsx @@ -1,4 +1,4 @@ -import { Alert, Grid, Snackbar, Box } from "@mui/material"; +import { Alert, Grid, Snackbar, Box, debounce } from "@mui/material"; import { useSelector } from "react-redux"; import { RootState } from "../../app/store"; import { @@ -25,6 +25,7 @@ import { useCallback, useEffect, useMemo, + useRef, useState, } from "react"; import SimulationPlotView from "./SimulationPlotView"; @@ -37,6 +38,7 @@ import { getConstVariables } from "../model/resetToSpeciesDefaults"; import useSubjectGroups from "../../hooks/useSubjectGroups"; import useExportSimulation from "./useExportSimulation"; import { SimulationsSidePanel } from "./SimulationsSidePanel"; +import { useCollapsibleSidebar } from "../../shared/contexts/CollapsibleSidebarContext"; type SliderValues = { [key: number]: number }; @@ -392,6 +394,30 @@ const Simulations: FC = () => { }); }; + const [dimensions, setDimensions] = useState({ + width: window.innerWidth, + }); + + const containerRef = useRef(null); + + useEffect(() => { + const debouncedHandleResize = debounce(function handleResize() { + setDimensions({ + width: containerRef?.current?.clientWidth, + }); + }, 1000); + + window.addEventListener("resize", debouncedHandleResize); + window.addEventListener("eventCollapse", debouncedHandleResize); + window.addEventListener("eventExpand", debouncedHandleResize); + + return () => { + window.removeEventListener("resize", debouncedHandleResize); + window.removeEventListener("eventCollapse", debouncedHandleResize); + window.removeEventListener("eventExpand", debouncedHandleResize); + }; + }); + const loading = [ isProjectLoading, isSimulationsLoading, @@ -408,7 +434,7 @@ const Simulations: FC = () => { } return ( - + { @@ -450,7 +476,7 @@ const Simulations: FC = () => { wrap={layout === "horizontal" ? "nowrap" : "wrap"} > {plots.map((plot, index) => ( - + 2500 ? 4 : 6} md={12} sm={12} item key={index}> {data?.length && model ? ( { visibleGroups={visibleGroups} shouldShowLegend={shouldShowLegend} layout={layout} + dimensions={dimensions} /> ) : (
Loading...
diff --git a/frontend-v2/src/features/simulation/SimulationsSidePanel.tsx b/frontend-v2/src/features/simulation/SimulationsSidePanel.tsx index 2a6732c1..a82bd4cd 100644 --- a/frontend-v2/src/features/simulation/SimulationsSidePanel.tsx +++ b/frontend-v2/src/features/simulation/SimulationsSidePanel.tsx @@ -17,7 +17,7 @@ import UnitField from "../../components/UnitField"; import SimulationSliderView from "./SimulationSliderView"; import HelpButton from "../../components/HelpButton"; import { ExpandLess, ExpandMore } from "@mui/icons-material"; -import { ChangeEvent, useEffect, useState } from "react"; +import { ChangeEvent, useState } from "react"; import { getTableHeight } from "../../shared/calculateTableHeights"; import { useSelector } from "react-redux"; import { RootState } from "../../app/store"; @@ -145,12 +145,12 @@ export const SimulationsSidePanel = ({ (state: RootState) => state.main.selectedPage, ); const portalRoot = document.getElementById(portalId); - const [collapseLayout, setCollapseLayout] = useState(true); - const [collapseOptions, setCollapseOptions] = useState(true); - const [collapseGroups, setCollapseGroups] = useState(true); - const [collapseParameters, setCollapseParameters] = useState(true); - const [collapseReference, setCollapseReference] = useState(true); - const [collapseLegend, setCollapseLegend] = useState(true); + const [collapseLayout, setCollapseLayout] = useState(false); + const [collapseOptions, setCollapseOptions] = useState(false); + const [collapseGroups, setCollapseGroups] = useState(false); + const [collapseParameters, setCollapseParameters] = useState(false); + const [collapseReference, setCollapseReference] = useState(false); + const [collapseLegend, setCollapseLegend] = useState(false); const { simulationAnimationClasses } = useCollapsibleSidebar(); if (!portalRoot || selectedPage !== PageName.SIMULATIONS) return null; @@ -165,7 +165,7 @@ export const SimulationsSidePanel = ({ height: "100%", paddingBottom: "1rem", backgroundColor: "#FBFBFA", - borderRight: "1px solid #DBD6D1", + borderRight: "1px solid #DBD6D1" }} > { return; }, - setHasSimulationsExpandedChanged: (isChanged: boolean) => { return; }, + setHasSimulationsExpandedChanged: (isChanged: boolean) => { + return; + }, isExpanded: true, animationClasses: "", simulationAnimationClasses: "", @@ -22,14 +24,20 @@ export const CollapsibleSidebarProvider = ({ const [hasExpandedChanged, setHasExpandedChanged] = useState(false); const [hasSimulationsExpandedChanged, setHasSimulationsExpandedChanged] = useState(false); + + const eventCollapse = new Event("eventCollapse"); + const eventExpand = new Event("eventExpand"); + const onCollapse = () => { setHasExpandedChanged(true); + dispatchEvent(eventCollapse) setHasSimulationsExpandedChanged(true); setIsExpanded(false); }; const onExpand = () => { setHasExpandedChanged(true); + dispatchEvent(eventExpand); setHasSimulationsExpandedChanged(true); setIsExpanded(true); };