diff --git a/frontend-v2/src/components/DynamicTabs.tsx b/frontend-v2/src/components/DynamicTabs.tsx index a2c7b879..6d63fece 100644 --- a/frontend-v2/src/components/DynamicTabs.tsx +++ b/frontend-v2/src/components/DynamicTabs.tsx @@ -1,11 +1,13 @@ -import React, { PropsWithChildren, ReactElement, useState } from "react"; +import React, { PropsWithChildren, ReactElement, useState, useEffect } from "react"; import Box from "@mui/material/Box"; import Tabs from "@mui/material/Tabs"; import Tab from "@mui/material/Tab"; import ErrorIcon from "@mui/icons-material/Error"; +import { useDispatch } from "react-redux"; import { Tooltip } from "@mui/material"; import { useCustomToast } from "../hooks/useCustomToast"; import { notificationTypes } from "./Notification/notificationTypes"; +import { SubPageName, setSubPage } from "../features/main/mainSlice"; interface TabContextProps { currentTab: number; @@ -18,7 +20,7 @@ export const TabContext = React.createContext({ }); interface DynamicTabsProps { - tabNames: string[]; + tabNames: SubPageName[]; tabErrors?: { [key: string]: string }; isOtherSpeciesSelected?: boolean; } @@ -44,6 +46,7 @@ export const DynamicTabs: React.FC> = ({ }) => { const [currentTab, setCurrentTab] = useState(0); const toast = useCustomToast(); + const dispatch = useDispatch(); const errors: { [key: string]: ReactElement } = {}; for (const key in tabErrors) { @@ -71,8 +74,10 @@ export const DynamicTabs: React.FC> = ({ autoClose: 3500 }) setCurrentTab(newValue); + dispatch(setSubPage(tabNames[newValue])) } else { setCurrentTab(newValue); + dispatch(setSubPage(tabNames[newValue])) } }; diff --git a/frontend-v2/src/components/HelpButton.tsx b/frontend-v2/src/components/HelpButton.tsx index b505b9de..47d748c8 100644 --- a/frontend-v2/src/components/HelpButton.tsx +++ b/frontend-v2/src/components/HelpButton.tsx @@ -1,7 +1,9 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import { HelpOutline } from "@mui/icons-material"; import { IconButton, Tooltip } from "@mui/material"; import { tooltipWrapper } from "../shared/tooltipWrapper"; +import { useSelector } from "react-redux"; +import { RootState } from "../app/store"; interface HelpButtonProps { title: string; @@ -10,6 +12,18 @@ interface HelpButtonProps { const HelpButton: React.FC = ({ title, children }) => { const [open, setOpen] = useState(false); + const selectedPage = useSelector( + (state: RootState) => state.main.selectedPage, + ); + const selectedSubPage = useSelector( + (state: RootState) => state.main.selectedSubPage, + ); + + useEffect(() => { + if (open) { + setOpen(false); + } + }, [selectedPage, selectedSubPage]); const handleOpen = () => { setOpen(true); @@ -26,6 +40,7 @@ const HelpButton: React.FC = ({ title, children }) => { title={tooltipWrapper(children, handleClose)} disableHoverListener={true} open={open} + TransitionProps={{ timeout: { enter: 200, exit: 0} }} componentsProps={{ tooltip: { sx: { diff --git a/frontend-v2/src/features/help/Help.tsx b/frontend-v2/src/features/help/Help.tsx index 80d253fb..ec9ef0d1 100644 --- a/frontend-v2/src/features/help/Help.tsx +++ b/frontend-v2/src/features/help/Help.tsx @@ -2,6 +2,7 @@ import React, { useEffect } from "react"; import { DynamicTabs, TabPanel } from "../../components/DynamicTabs"; import HelpTab from "./HelpTab"; import { parse } from "papaparse"; +import { SubPageName } from "../main/mainSlice"; export type Question = { question: string; @@ -40,7 +41,9 @@ const Help: React.FC = () => { title: rowList[TITLE_COLUMN], type: rowList[TYPE_COLUMN], link: rowList[LINK_COLUMN].replace("view?usp=sharing", "preview"), - keywords: rowList[KEYWORDS_COLUMN].split(",").map((keyword) => keyword.trim()), + keywords: rowList[KEYWORDS_COLUMN].split(",").map((keyword) => + keyword.trim(), + ), }; }), ); @@ -79,12 +82,12 @@ const Help: React.FC = () => { return ( {questions.map((question, index) => ( diff --git a/frontend-v2/src/features/main/Sidebar.tsx b/frontend-v2/src/features/main/Sidebar.tsx index 3fdcde15..8d9ea66f 100644 --- a/frontend-v2/src/features/main/Sidebar.tsx +++ b/frontend-v2/src/features/main/Sidebar.tsx @@ -14,7 +14,7 @@ import MenuIcon from "@mui/icons-material/Menu"; import Toolbar from "@mui/material/Toolbar"; import Typography from "@mui/material/Typography"; import MainContent from "./MainContent"; -import { PageName, setPage } from "./mainSlice"; +import { PageName, SubPageName, setPage, setSubPage } from "./mainSlice"; import { useSelector } from "react-redux"; import { RootState } from "../../app/store"; import { LinearProgress, Tooltip } from "@mui/material"; @@ -126,7 +126,20 @@ export default function Sidebar() { }); const handlePageClick = (key: string) => () => { - dispatch(setPage(PageName[key as keyof typeof PageName])); + const chosenPage = PageName[key as keyof typeof PageName]; + dispatch(setPage(chosenPage)); + + switch (chosenPage) { + case (PageName.MODEL): + dispatch(setSubPage(SubPageName.PKPDMODEL)); + break; + case (PageName.HELP): + dispatch(setSubPage(SubPageName.TUTORIALS)); + break + default: + dispatch(setSubPage(null)); + break; + } }; const isPageDisabled = (key: string) => { diff --git a/frontend-v2/src/features/main/mainSlice.ts b/frontend-v2/src/features/main/mainSlice.ts index 3b6220ed..a479a8f9 100644 --- a/frontend-v2/src/features/main/mainSlice.ts +++ b/frontend-v2/src/features/main/mainSlice.ts @@ -10,14 +10,28 @@ export enum PageName { HELP = "Help & Feedback", } +export enum SubPageName { + PKPDMODEL = 'PK/PD Model', + MAPVARIABLES = 'Map Variables', + PARAMETERS = 'Parameters', + TUTORIALS = 'Tutorials', + PROJECTS = 'Projects', + DRUG = 'Drug', + MODEL = 'Model', + TRAILDESIGN = 'Trial Design', + SIMULATION = 'Simulation' +} + interface MainState { selectedPage: PageName; + selectedSubPage: SubPageName | null; selectedProject: number | null; dirtyCount: number; } const initialState: MainState = { selectedPage: PageName.PROJECTS, + selectedSubPage: null, selectedProject: null, dirtyCount: 0, }; @@ -29,6 +43,9 @@ const mainSlice = createSlice({ setPage: (state, action: PayloadAction) => { state.selectedPage = action.payload; }, + setSubPage: (state, action: PayloadAction) => { + state.selectedSubPage = action.payload; + }, setProject: (state, action: PayloadAction) => { state.selectedProject = action.payload; }, @@ -41,6 +58,6 @@ const mainSlice = createSlice({ }, }); -export const { setPage, setProject, incrementDirtyCount, decrementDirtyCount } = +export const { setPage, setSubPage, setProject, incrementDirtyCount, decrementDirtyCount } = mainSlice.actions; export default mainSlice.reducer; diff --git a/frontend-v2/src/features/model/Model.tsx b/frontend-v2/src/features/model/Model.tsx index 74f6c3f1..6344e92a 100644 --- a/frontend-v2/src/features/model/Model.tsx +++ b/frontend-v2/src/features/model/Model.tsx @@ -23,6 +23,7 @@ import MapVariablesTab from "./MapVariablesTab"; import PKPDModelTab from "./PKPDModelTab"; import ParametersTab from "./ParametersTab"; import useDirty from "../../hooks/useDirty"; +import { SubPageName } from "../main/mainSlice"; export type FormData = { project: ProjectRead; @@ -193,7 +194,7 @@ const Model: React.FC = () => { } const tabErrors: { [key: string]: string } = {}; - const tabKeys = ["PK/PD Model", "Map Variables", "Parameters"]; + const tabKeys = [SubPageName.PKPDMODEL, SubPageName.MAPVARIABLES, SubPageName.PARAMETERS]; if (model.pk_model === null) { tabErrors[tabKeys[0]] = "Please select a PK model to simulate"; } diff --git a/frontend-v2/src/shared/tooltipWrapper.tsx b/frontend-v2/src/shared/tooltipWrapper.tsx index 69af5b92..5545a688 100644 --- a/frontend-v2/src/shared/tooltipWrapper.tsx +++ b/frontend-v2/src/shared/tooltipWrapper.tsx @@ -6,6 +6,6 @@ export const tooltipWrapper = (children: React.ReactNode, onClose: () => void) =
{children}
- + ) \ No newline at end of file