Skip to content

Commit

Permalink
refactor(client): clean home page layout
Browse files Browse the repository at this point in the history
  • Loading branch information
berdal84 committed Apr 4, 2024
1 parent 558ff90 commit 587efd6
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 100 deletions.
116 changes: 71 additions & 45 deletions client/app/components/home.tsx
Original file line number Diff line number Diff line change
@@ -1,86 +1,112 @@
"use client"
import {useCallback, useEffect, useState} from "react";
import {Alert, Box, Grid, Tab} from "@mui/material";
import {PropsWithChildren, useCallback, useEffect, useMemo, useState} from "react";
import {Alert, Box, Container, Drawer, Grid, IconButton, Tab, Typography} from "@mui/material";
import { Job } from "@/app/typings/schemas";
import TopBar from "@/app/components/top-bar";
import JobTable from "@/app/components/job-table";
import CreateJobDialog from "@/app/components/create-job-dialog";
import {useAppSelector} from "@/app/redux/hooks";
import {useAppDispatch, useAppSelector} from "@/app/redux/hooks";
import JobDetails from "@/app/components/job-details";
import { SankeyDiagram } from "./sankey-diagram";
import TabContext from '@mui/lab/TabContext';
import TabList from '@mui/lab/TabList';
import TabPanel from '@mui/lab/TabPanel';
import { selectJob } from "@/app/redux/jobSlice";
import { selectJob, setSelectedJob } from "@/app/redux/jobSlice";
import CloseIcon from '@mui/icons-material/Close';

function Title({ children }: PropsWithChildren) {
return (
<Typography fontSize='1.5rem'>{children}</Typography>
)
}

export default function Home() {
const [jobDialogOpen, setJobDialogOpen] = useState(false);
const { selectedJob: active } = useAppSelector(selectJob)
const [tab, setTab] = useState<string>("list")
const dispatch = useAppDispatch();

const handleNewJobBtnClick = useCallback(() => {
setJobDialogOpen(true);
}, []);

const handleCloseJobDialog = useCallback( async (_: Job | null) => {
const handleCloseJobDialog = useCallback( async ( job: Job | null) => {
setJobDialogOpen(false);
}, []);
job && dispatch(setSelectedJob({ id: job.id}))
}, [dispatch]);

const handleTabListChange = useCallback( (_: React.SyntheticEvent, value: any) => {
setTab(value)
}, [])

const handleCloseSelection = useCallback(() => {
dispatch(setSelectedJob({ id: null}))
}, [dispatch])

useEffect(() => {
if ( active.id !== null && active.showDetails) {
setTab("selection")
}
}, [active])

const common = useMemo( () => ({
padding: 4
}), [])

return (
<Box sx={{width: '100%', mb: 2}}>
<Box>
<TopBar onNewJobBtnClick={handleNewJobBtnClick}/>
<Grid container spacing={4} sx={{padding: 2}}>
<Grid item xs={6} sx={{padding: 2, minHeight: '90vh'}}>

<TabContext value={tab} >
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<TabList onChange={handleTabListChange}>
<Tab
label="Job List"
value="list"
/>
<Tab
label="Selected Job"
value="selection"
disabled={active.id === null}
/>
</TabList>
<Box
display="flex"
flexDirection="column"
{...common}
marginTop={8}
rowGap={1}
>
<Box
display="flex"
flexDirection="row"
columnGap={5}
flex={1}
>
<Box flex={2} flexGrow={2} {...common}>
<Title>List</Title>
<JobTable/>
</Box>
{ active.id !== null &&
<Box
flex={1}
flexShrink={5}
{...common}
display="flex"
gap={1}
flexDirection="column"
sx={{border: 'solid 2px #fff9', backgroundColor: '#00000010'}}
>
<Box
display="flex"
alignItems="center"
justifyContent="space-between"
>
<Title>Selection</Title>
<IconButton onClick={handleCloseSelection}>
<CloseIcon/>
</IconButton>
</Box>

<TabPanel value="list">
<JobTable/>
</TabPanel>

<TabPanel value="selection">
{ active.id === null
? <Alert severity="error">Unable to load job</Alert>
: <JobDetails jobId={active.id}/>
}
</TabPanel>

</TabContext>

</Grid>
<Grid item xs={6} sx={{padding: 2}}>
<JobDetails jobId={active.id}/>
</Box>
}
</Box>
<Box
flex={1}
padding={4}
>
<Title>Visualization</Title>
<SankeyDiagram
isolateSelection={tab==="selection"}
style={{
linkColor: "rgba(0.8,0.8,0.8,0.4)",
selectedLinkColor: "rgba(0.5,0.5,0.5, 0.6)",
}}
/>
</Grid>
</Grid>
</Box>
</Box>
<CreateJobDialog
open={jobDialogOpen}
onClose={handleCloseJobDialog}
Expand Down
12 changes: 6 additions & 6 deletions client/app/components/job-details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ export default function JobDetails({ jobId }: JobDetailsProps) {
}

return (
<Box sx={{ width: '100%' }}>
<Box sx={{ justifyContent: 'space-between', display: 'flex', justifyItems: "normal" }}>
<h3>{formatJobFullTitle(job) ?? 'No job selected'}</h3>
<Box display="flex" flexDirection="column" >
<Box flex={1} justifyContent="space-between" display="flex" justifyItems="normal">
<Typography fontSize='1rem'>{formatJobFullTitle(job) ?? 'No job selected'}</Typography>
<Button
disabled={!job}
variant="outlined"
Expand All @@ -64,15 +64,15 @@ export default function JobDetails({ jobId }: JobDetailsProps) {
Add Event
</Button>
</Box>
<Box sx={{ display: "flex", flexDirection: 'column', gap: 1 }}>
<Box sx={{ flex: 2 }}>
<Box flex={5} display="flex" flexDirection='column' gap={1}>
<Box flex={2}>
<h4>Notes</h4>
<p>
{job?.notes ?? "Select a job from the list or the diagram"}
</p>
</Box>

<TableContainer sx={{ flex: 2 }}>
<TableContainer sx={{ flex: 5 }}>
<h4>Event(s)</h4>
{job?.events ? <Table padding="none" size="small" aria-label="a dense table">
<TableHead>
Expand Down
96 changes: 47 additions & 49 deletions client/app/components/top-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,55 +80,53 @@ export default function TopBar({
}, []);

return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static">
<Menu
id="basic-menu"
anchorEl={anchorEl}
open={open}
onClose={closeMenu}
MenuListProps={{
'aria-labelledby': 'basic-button',
}}
<AppBar position="fixed" sx={{ zIndex: (theme) => theme.zIndex.drawer + 1 }}>
<Menu
id="basic-menu"
anchorEl={anchorEl}
open={open}
onClose={closeMenu}
MenuListProps={{
'aria-labelledby': 'basic-button',
}}
>
<MenuItem onClick={() => {handleNewJobBtnClick(); closeMenu()}}>
New Job
</MenuItem>
</Menu>

<Toolbar sx={{ display: 'flex'}}>
<IconButton
sx={{ display: { sm: 'none', xs: 'flex' } }}
size="large"
edge="start"
color="inherit"
aria-label="open drawer"
onClick={handleOpenMenuClick}
>
<MenuItem onClick={() => {handleNewJobBtnClick(); closeMenu()}}>
New Job
</MenuItem>
</Menu>

<Toolbar sx={{ display: 'flex'}}>
<IconButton
sx={{ display: { sm: 'none', xs: 'flex' } }}
size="large"
edge="start"
color="inherit"
aria-label="open drawer"
onClick={handleOpenMenuClick}
>
<MenuIcon />
</IconButton>
<Box sx={{ display: "flex", flexGrow: '1', justifyContent: { xs: "center", sm: 'left'}}}>
<Image
src="logo-with-title.svg"
height="48"
width="128"
alt="Seeking"
/>
<Box sx={{ gap: 1, margin: 1, display: { xs: 'none', sm: 'flex' } }}>
<Button variant="contained" onClick={handleNewJobBtnClick}>New Job</Button>
<Search>
<SearchIconWrapper>
<SearchIcon />
</SearchIconWrapper>
<StyledInputBase
placeholder="Search…"
inputProps={{ 'aria-label': 'search' }}
/>
</Search>
</Box>
</Box>
</Toolbar>
</AppBar>
</Box>
<MenuIcon />
</IconButton>
<Box sx={{ display: "flex", flexGrow: '1', justifyContent: { xs: "center", sm: 'left'}}}>
<Image
src="logo-with-title.svg"
height="48"
width="128"
alt="Seeking"
/>
<Box sx={{ gap: 1, margin: 1, display: { xs: 'none', sm: 'flex' } }}>
<Button variant="contained" onClick={handleNewJobBtnClick}>New Job</Button>
<Search>
<SearchIconWrapper>
<SearchIcon />
</SearchIconWrapper>
<StyledInputBase
placeholder="Search…"
inputProps={{ 'aria-label': 'search' }}
/>
</Search>
</Box>
</Box>
</Toolbar>
</AppBar>
);
}

0 comments on commit 587efd6

Please sign in to comment.