diff --git a/app/front-end/src/app/provider.tsx b/app/front-end/src/app/provider.tsx index 928db5d..31c7e84 100644 --- a/app/front-end/src/app/provider.tsx +++ b/app/front-end/src/app/provider.tsx @@ -1,4 +1,3 @@ -import { BaseLayout } from '@/components/layouts/baseLayout'; import { SessionContextProvider, ThemeContextProvider } from '@/stores'; import { CircularProgress } from '@mui/material'; import React from 'react'; @@ -41,9 +40,7 @@ export const AppProvider = ({ children }: AppProviderProps) => { fallback={} > - - {children} - + {children} ); diff --git a/app/front-end/src/app/router.tsx b/app/front-end/src/app/router.tsx index 039123f..e8ba1a6 100644 --- a/app/front-end/src/app/router.tsx +++ b/app/front-end/src/app/router.tsx @@ -1,3 +1,4 @@ +import { BaseLayout } from '@/components/layouts/baseLayout'; import { Paths } from '@/types'; import { useMemo } from 'react'; import { createBrowserRouter, RouterProvider } from 'react-router-dom'; @@ -32,14 +33,26 @@ export const AppRouter = () => { path: Paths.HOME, lazy: async () => { const { Home } = await import('./routes/home'); - return { Component: Home }; + return { + Component: (props) => ( + + + + ), + }; }, }, { path: Paths.NOTFOUND, lazy: async () => { const { NotFound } = await import('./routes/notFound'); - return { Component: NotFound }; + return { + Component: (props) => ( + + + + ), + }; }, }, ]), diff --git a/app/front-end/src/components/buttons/IconTitleButton.tsx b/app/front-end/src/components/buttons/IconTitleButton.tsx index 4f9d877..bad6b76 100644 --- a/app/front-end/src/components/buttons/IconTitleButton.tsx +++ b/app/front-end/src/components/buttons/IconTitleButton.tsx @@ -1,4 +1,3 @@ -import { Colors } from '@/types'; import { alpha, Box, IconButton, Typography, useTheme } from '@mui/material'; interface Props { @@ -8,6 +7,8 @@ interface Props { height?: string; borderRadius?: string; onClick?: () => void; + isActive?: boolean; + disabled?: boolean; } /** @@ -29,8 +30,18 @@ interface Props { * * @returns {JSX.Element} The `IconTitleButton` component rendering an icon button and an optional title. */ -export const IconTitleButton: React.FC = ({ icon, title, width, height, borderRadius, onClick }) => { +export const IconTitleButton: React.FC = ({ + icon, + title, + width, + height, + borderRadius, + onClick, + isActive = false, + disabled = false, +}) => { const Theme = useTheme(); + return ( = ({ icon, title, width, height, b height: height || '3rem', borderRadius: borderRadius || '1rem', transition: 'background-color 0.5s ease', + color: disabled ? alpha(Theme.palette.primary.contrastText, 0.4) : Theme.palette.primary.contrastText, ':hover': { - backgroundColor: alpha(Theme.palette.primary.contrastText, 0.2), + backgroundColor: disabled + ? 'transparent' + : isActive + ? alpha(Theme.palette.primary.contrastText, 0.3) + : alpha(Theme.palette.primary.contrastText, 0.2), }, + backgroundColor: disabled + ? 'transparent' + : isActive + ? alpha(Theme.palette.primary.contrastText, 0.3) + : 'transparent', }} - onClick={onClick} + onClick={disabled ? () => {} : onClick} > {icon} {title && ( - + {} : onClick} + > {title} )} diff --git a/app/front-end/src/components/layouts/baseLayout.tsx b/app/front-end/src/components/layouts/baseLayout.tsx index 465e62c..764588f 100644 --- a/app/front-end/src/components/layouts/baseLayout.tsx +++ b/app/front-end/src/components/layouts/baseLayout.tsx @@ -1,12 +1,6 @@ -import { IconTitleButton } from '@/components/buttons/IconTitleButton'; import { SettingsDialog, ShortcutsDialog } from '@/components/dialogs'; +import { Sidebar } from '@/components/sidebar'; import { Colors } from '@/types'; -import { - AutoMode as AutoModeIcon, - Home as HomeIcon, - SettingsOutlined as SettingsOutlinedIcon, - SwitchAccessShortcut as SwitchAccessShortcutIcon, -} from '@mui/icons-material'; import { Box, Typography, useTheme } from '@mui/material'; import { useState } from 'react'; @@ -33,12 +27,12 @@ interface Props { export const BaseLayout: React.FC = ({ children }) => { const Theme = useTheme(); - const [isShortcutsMenuOpen, setIsShortcutsMenuOpen] = useState(false); - const handleShortcutsMenuOpen = () => { - setIsShortcutsMenuOpen(true); + const [isShortcutsDialogOpen, setIsShortcutsDialogOpen] = useState(false); + const handleShortcutsDialogOpen = () => { + setIsShortcutsDialogOpen(true); }; - const handleShortcutsMenuClose = () => { - setIsShortcutsMenuOpen(false); + const handleShortcutsDialogClose = () => { + setIsShortcutsDialogOpen(false); }; const [isSettingsDialogOpen, setIsSettingsDialogOpen] = useState(false); @@ -115,56 +109,8 @@ export const BaseLayout: React.FC = ({ children }) => { flexDirection: 'row', }} > - - - } - title={'Home'} - /> - } - title={'Macros'} - /> - - - - } - onClick={handleSettingsDialogOpen} - /> - - } - onClick={handleShortcutsMenuOpen} - /> - - + + = ({ children }) => { {children} - + ); diff --git a/app/front-end/src/components/sidebar/index.ts b/app/front-end/src/components/sidebar/index.ts new file mode 100644 index 0000000..bfed624 --- /dev/null +++ b/app/front-end/src/components/sidebar/index.ts @@ -0,0 +1 @@ +export { Sidebar } from './sidebar'; diff --git a/app/front-end/src/components/sidebar/sidebar.tsx b/app/front-end/src/components/sidebar/sidebar.tsx new file mode 100644 index 0000000..49a3b80 --- /dev/null +++ b/app/front-end/src/components/sidebar/sidebar.tsx @@ -0,0 +1,84 @@ +import { IconTitleButton } from '@/components/buttons/IconTitleButton'; +import { Paths } from '@/types'; +import { + AutoMode as AutoModeIcon, + Home as HomeIcon, + SettingsOutlined as SettingsOutlinedIcon, + SwitchAccessShortcut as SwitchAccessShortcutIcon, +} from '@mui/icons-material'; +import { Box } from '@mui/material'; +import { useLocation, useNavigate } from 'react-router-dom'; + +interface SidebarProps { + settingsDialogOpen: () => void; + shortcutsDialogOpen: () => void; +} + +export const Sidebar: React.FC = ({ settingsDialogOpen, shortcutsDialogOpen }) => { + const location = useLocation(); + const navigate = useNavigate(); + + return ( + + + + } + title={'Home'} + isActive={location.pathname === Paths.HOME} + onClick={() => navigate(Paths.HOME)} + /> + + } + title={'Macros'} + isActive={location.pathname === Paths.MACROS} + onClick={() => navigate(Paths.MACROS)} + disabled + /> + + + } + onClick={settingsDialogOpen} + /> + } + onClick={shortcutsDialogOpen} + /> + + + ); +}; diff --git a/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/applyGroupButtons.tsx b/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/applyGroupButtons.tsx new file mode 100644 index 0000000..3044051 --- /dev/null +++ b/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/applyGroupButtons.tsx @@ -0,0 +1,26 @@ +import { Deblur as DeblurIcon } from '@mui/icons-material'; + +import { ToolbarGroupItemProps } from '@/features/editor/components/toolbarView'; + +const applySpliceAiClick = () => { + console.log('Clicked Apply SpliceAI Button!'); +}; + +const applyCaddClick = () => { + console.log('Clicked Apply CADD Button!'); +}; + +export const ApplyGroupButtons: ToolbarGroupItemProps[] = [ + { + group: 'apply', + icon: DeblurIcon, + label: 'Apply SpliceAI', + onClick: applySpliceAiClick, + }, + { + group: 'apply', + icon: DeblurIcon, + label: 'Apply CADD', + onClick: applyCaddClick, + }, +]; diff --git a/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/downloadGroupButtons.tsx b/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/downloadGroupButtons.tsx new file mode 100644 index 0000000..febfd84 --- /dev/null +++ b/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/downloadGroupButtons.tsx @@ -0,0 +1,36 @@ +import { ToolbarGroupItemProps } from '@/features/editor/components/toolbarView'; + +import { Download as DownloadIcon } from '@mui/icons-material'; + +const handleDownloadLovdClick = () => { + console.log('Clicked Download Lovd Button!'); +}; + +const handleDownloadClinvarClick = () => { + console.log('Clicked Download Clinvar Button!'); +}; + +const handleDownloadGnomadClick = () => { + console.log('Clicked Download Gnomad Button!'); +}; + +export const DownloadGroupButtons: ToolbarGroupItemProps[] = [ + { + group: 'download', + icon: DownloadIcon, + label: 'LOVD', + onClick: handleDownloadLovdClick, + }, + { + group: 'download', + icon: DownloadIcon, + label: 'ClinVar', + onClick: handleDownloadClinvarClick, + }, + { + group: 'download', + icon: DownloadIcon, + label: 'gnomAD', + onClick: handleDownloadGnomadClick, + }, +]; diff --git a/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/index.ts b/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/index.ts new file mode 100644 index 0000000..243e3af --- /dev/null +++ b/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/index.ts @@ -0,0 +1,3 @@ +export { ApplyGroupButtons } from './applyGroupButtons'; +export { DownloadGroupButtons } from './downloadGroupButtons'; +export { MergeGroupButtons } from './mergeGroupButtons'; diff --git a/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/mergeGroupButtons.tsx b/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/mergeGroupButtons.tsx new file mode 100644 index 0000000..73d2271 --- /dev/null +++ b/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/mergeGroupButtons.tsx @@ -0,0 +1,26 @@ +import { MergeType as MergeTypeIcon } from '@mui/icons-material'; + +import { ToolbarGroupItemProps } from '@/features/editor/components/toolbarView'; + +const mergeLovdAndGnomadClick = () => { + console.log('Clicked Merge LOVD & gnomAD Button!'); +}; + +const mergeLovdAndClinvarClick = () => { + console.log('Clicked Merge LOVD & ClinVar Button!'); +}; + +export const MergeGroupButtons: ToolbarGroupItemProps[] = [ + { + group: 'merge', + icon: MergeTypeIcon, + label: 'Merge LOVD & gnomAD', + onClick: mergeLovdAndGnomadClick, + }, + { + group: 'merge', + icon: MergeTypeIcon, + label: 'Merge LOVD & ClinVar', + onClick: mergeLovdAndClinvarClick, + }, +]; diff --git a/app/front-end/src/features/editor/components/toolbarView/toolbarGroupItem.tsx b/app/front-end/src/features/editor/components/toolbarView/toolbarGroupItem.tsx index cdf4858..707773b 100644 --- a/app/front-end/src/features/editor/components/toolbarView/toolbarGroupItem.tsx +++ b/app/front-end/src/features/editor/components/toolbarView/toolbarGroupItem.tsx @@ -50,6 +50,7 @@ export const ToolbarGroupItem: React.FC = ({ icon: Icon, '&:hover': { backgroundColor: Theme.palette.action.selected, }, + textTransform: 'none', }} > {label} diff --git a/app/front-end/src/features/editor/components/toolbarView/toolbarView.tsx b/app/front-end/src/features/editor/components/toolbarView/toolbarView.tsx index 323fa93..58f4a2f 100644 --- a/app/front-end/src/features/editor/components/toolbarView/toolbarView.tsx +++ b/app/front-end/src/features/editor/components/toolbarView/toolbarView.tsx @@ -6,11 +6,13 @@ import { ToolbarGroupsSelectorItem, ToolbarGroupsSelectorItemProps, } from '@/features/editor/components/toolbarView'; + import { - AccessAlarms as AccessAlarmsIcon, - AccessibleForward as AccessibleForwardIcon, - Android as AndroidIcon, -} from '@mui/icons-material'; + ApplyGroupButtons, + DownloadGroupButtons, + MergeGroupButtons, +} from '@/features/editor/components/toolbarView/toolbarGroupButtons'; + import { useState } from 'react'; /** @@ -34,242 +36,30 @@ import { useState } from 'react'; * @returns {JSX.Element} The rendered ToolbarView component, which includes the toolbar group selector and the items of the selected group. */ export const ToolbarView: React.FC = () => { - const [selectedGroup, setSelectedGroup] = useState('group1'); + const [selectedGroup, setSelectedGroup] = useState('download'); - const ToolbarGroupsButtons: ToolbarGroupItemProps[] = [ - { - group: 'group1', - icon: AccessAlarmsIcon, - label: 'Alarm1', - onClick: () => { - console.log('Clicked Alarm1 Button!'); - }, - }, - { - group: 'group1', - icon: AccessibleForwardIcon, - label: 'Forward1', - onClick: () => { - console.log('Clicked Forward1 Button!'); - }, - }, - { - group: 'group1', - icon: AndroidIcon, - label: 'Android1', - onClick: () => { - console.log('Clicked Android1 Button!'); - }, - }, - { - group: 'group2', - icon: AccessAlarmsIcon, - label: 'Alarm2', - onClick: () => { - console.log('Clicked Alarm2 Button!'); - }, - }, - { - group: 'group2', - icon: AccessibleForwardIcon, - label: 'Forward2', - onClick: () => { - console.log('Clicked Forward2 Button!'); - }, - }, - { - group: 'group2', - icon: AndroidIcon, - label: 'Android2', - onClick: () => { - console.log('Clicked Android2 Button!'); - }, - }, - { - group: 'group2', - icon: AccessAlarmsIcon, - label: 'Alarm2', - onClick: () => { - console.log('Clicked Alarm2 Button!'); - }, - }, - { - group: 'group2', - icon: AccessibleForwardIcon, - label: 'Forward2', - onClick: () => { - console.log('Clicked Forward2 Button!'); - }, - }, - { - group: 'group2', - icon: AndroidIcon, - label: 'Android2', - onClick: () => { - console.log('Clicked Android2 Button!'); - }, - }, - { - group: 'group2', - icon: AccessAlarmsIcon, - label: 'Alarm2', - onClick: () => { - console.log('Clicked Alarm2 Button!'); - }, - }, - { - group: 'group2', - icon: AccessibleForwardIcon, - label: 'Forward2', - onClick: () => { - console.log('Clicked Forward2 Button!'); - }, - }, - { - group: 'group2', - icon: AndroidIcon, - label: 'Android2', - onClick: () => { - console.log('Clicked Android2 Button!'); - }, - }, - { - group: 'group3', - icon: AccessAlarmsIcon, - label: 'Alarm3', - onClick: () => { - console.log('Clicked Alarm3 Button!'); - }, - }, - { - group: 'group3', - icon: AccessibleForwardIcon, - label: 'Forward3', - onClick: () => { - console.log('Clicked Forward3 Button!'); - }, - }, - { - group: 'group3', - icon: AndroidIcon, - label: 'Android3', - onClick: () => { - console.log('Clicked Android3 Button!'); - }, - }, - { - group: 'group3', - icon: AccessAlarmsIcon, - label: 'Alarm3', - onClick: () => { - console.log('Clicked Alarm3 Button!'); - }, - }, - { - group: 'group3', - icon: AccessibleForwardIcon, - label: 'Forward3', - onClick: () => { - console.log('Clicked Forward3 Button!'); - }, - }, - { - group: 'group3', - icon: AndroidIcon, - label: 'Android3', - onClick: () => { - console.log('Clicked Android3 Button!'); - }, - }, - { - group: 'group3', - icon: AccessAlarmsIcon, - label: 'Alarm3', - onClick: () => { - console.log('Clicked Alarm3 Button!'); - }, - }, - { - group: 'group3', - icon: AccessibleForwardIcon, - label: 'Forward3', - onClick: () => { - console.log('Clicked Forward3 Button!'); - }, - }, - { - group: 'group3', - icon: AndroidIcon, - label: 'Android3', - onClick: () => { - console.log('Clicked Android3 Button!'); - }, - }, - { - group: 'group3', - icon: AccessAlarmsIcon, - label: 'Alarm3', - onClick: () => { - console.log('Clicked Alarm3 Button!'); - }, - }, - { - group: 'group3', - icon: AccessibleForwardIcon, - label: 'Forward3', - onClick: () => { - console.log('Clicked Forward3 Button!'); - }, - }, - { - group: 'group3', - icon: AndroidIcon, - label: 'Android3', - onClick: () => { - console.log('Clicked Android3 Button!'); - }, - }, - { - group: 'group3', - icon: AccessAlarmsIcon, - label: 'Alarm3', - onClick: () => { - console.log('Clicked Alarm3 Button!'); - }, - }, - { - group: 'group3', - icon: AccessibleForwardIcon, - label: 'Forward3', - onClick: () => { - console.log('Clicked Forward3 Button!'); - }, - }, - { - group: 'group3', - icon: AndroidIcon, - label: 'Android3', - onClick: () => { - console.log('Clicked Android3 Button!'); - }, - }, - ]; + // Combine the button groups into a dictionary for easy access + const ToolbarGroupsButtons: Record = { + download: DownloadGroupButtons, + merge: MergeGroupButtons, + apply: ApplyGroupButtons, + }; const ToolbarGroups: ToolbarGroupsSelectorItemProps[] = [ { - id: 'group1', - label: 'Group 1', - onClick: () => setSelectedGroup('group1'), + id: 'download', + label: 'Download', + onClick: () => setSelectedGroup('download'), }, { - id: 'group2', - label: 'Group 2', - onClick: () => setSelectedGroup('group2'), + id: 'merge', + label: 'Merge', + onClick: () => setSelectedGroup('merge'), }, { - id: 'group3', - label: 'Group 3', - onClick: () => setSelectedGroup('group3'), + id: 'apply', + label: 'Apply', + onClick: () => setSelectedGroup('apply'), }, ]; @@ -281,9 +71,7 @@ export const ToolbarView: React.FC = () => { ))} - {ToolbarGroupsButtons.map( - (button, index) => button.group === selectedGroup && - )} + {ToolbarGroupsButtons[selectedGroup]?.map((button, index) => )} ); diff --git a/app/front-end/src/types/constants/paths.ts b/app/front-end/src/types/constants/paths.ts index 920578e..04bfbf8 100644 --- a/app/front-end/src/types/constants/paths.ts +++ b/app/front-end/src/types/constants/paths.ts @@ -16,12 +16,13 @@ * @example * // Example usage of Paths * import { Paths } from './path/to/paths'; - * + * * // Configure routing * * */ export const Paths = { - HOME: '/', - NOTFOUND: '*', -}; \ No newline at end of file + HOME: '/', + MACROS: '/macros', + NOTFOUND: '*', +};