Skip to content

Commit

Permalink
Merge pull request #186 from cisagov/RSC-Nav
Browse files Browse the repository at this point in the history
Update RSC Dashboard Navigation
  • Loading branch information
schmelz21 authored Apr 26, 2024
2 parents 3278b1d + ce3a6b6 commit 932a3c4
Show file tree
Hide file tree
Showing 14 changed files with 442 additions and 70 deletions.
25 changes: 25 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"react-markdown": "^8.0.3",
"react-media": "^1.10.0",
"react-router-dom": "^5.3.4",
"react-router-hash-link": "^2.4.3",
"react-scripts": "5.0.1",
"react-select": "^5.5.9",
"react-simple-maps": "^3.0.0",
Expand All @@ -76,6 +77,7 @@
"@types/react-dom": "^18.2.0",
"@types/react-lazylog": "^4.5.1",
"@types/react-router-dom": "^5.3.3",
"@types/react-router-hash-link": "^2.4.9",
"@types/react-simple-maps": "^3.0.0",
"@types/react-table": "^7.7.12",
"ajv": "^8.12.0",
Expand Down
91 changes: 91 additions & 0 deletions frontend/src/components/ReadySetCyber/FloatingNav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import React from 'react';
import { Divider, useScrollTrigger } from '@mui/material';
import Box from '@mui/material/Box';
import Fab from '@mui/material/Fab';
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
import NavigationIcon from '@mui/icons-material/Navigation';
import Zoom from '@mui/material/Zoom';
import { HashLink } from 'react-router-hash-link';

interface Props {
categories: Category[];
}

export interface Category {
name: string;
}
export const FloatingNav: React.FC<Props> = ({ categories }) => {
const trigger = useScrollTrigger({
threshold: 100
});
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};

return (
<>
<Zoom in={trigger}>
<Box
role="presentation"
sx={{
position: 'fixed',
bottom: 80,
right: 32,
zIndex: 1
}}
>
<Fab
onClick={handleClick}
color="primary"
size="small"
aria-label="Scroll back to top"
style={{ outline: 'none' }}
>
<NavigationIcon fontSize="medium" />
</Fab>
</Box>
</Zoom>
<Menu
id="basic-menu"
anchorEl={anchorEl}
open={open}
onClose={handleClose}
anchorOrigin={{
vertical: 'top',
horizontal: 'left'
}}
transformOrigin={{
vertical: 'bottom',
horizontal: 'right'
}}
MenuListProps={{
'aria-labelledby': 'basic-button'
}}
>
{categories.map((category, index) => (
<div key={index}>
<MenuItem onClick={handleClose}>
<HashLink
style={{
textDecoration: 'none',
color: 'black',
outline: 'none'
}}
to={`#${category.name}`}
>
{category.name}
</HashLink>
</MenuItem>
<Divider />
</div>
))}
</Menu>
</>
);
};
38 changes: 38 additions & 0 deletions frontend/src/components/ReadySetCyber/RSCAccordionNav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import { Accordion, AccordionDetails, AccordionSummary } from '@mui/material';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import { HashLink } from 'react-router-hash-link';

interface Props {
categories: Category[];
}

export interface Category {
name: string;
}

export const RSCAccordionNav: React.FC<Props> = ({ categories }) => {
return (
<Accordion>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
style={{ outline: 'none' }}
>
{' '}
Categories
</AccordionSummary>
{categories.map((category, index) => (
<AccordionDetails key={index}>
<HashLink
style={{ textDecoration: 'none', outline: 'none', color: 'black' }}
to={`#${category.name}`}
>
{category.name}
</HashLink>
</AccordionDetails>
))}
</Accordion>
);
};
4 changes: 2 additions & 2 deletions frontend/src/components/ReadySetCyber/RSCDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ export const RSCDashboard: React.FC = () => {
return (
<Box sx={{ flexGrow: 1, padding: 2 }}>
<Grid container spacing={2}>
<Grid item xs={4}>
<Grid item sm={4} sx={{ display: { xs: 'none', sm: 'grid' } }}>
<RSCDefaultSideNav />
</Grid>
<Grid item xs={8}>
<Grid item xs={12} sm={8}>
<Box sx={{ flexGrow: 1, padding: 2, backgroundColor: 'white' }}>
<Stack>
<h2>Assessment Results</h2>
Expand Down
26 changes: 20 additions & 6 deletions frontend/src/components/ReadySetCyber/RSCDefaultSideNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,33 @@ import Box from '@mui/material/Box';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import Divider from '@mui/material/Divider';
import { useAuthContext } from 'context';
import { ListItemButton } from '@mui/material';

export const RSCDefaultSideNav: React.FC = () => {
const { user, logout } = useAuthContext();

return (
<div>
<Box sx={{ width: '100%', maxWidth: 360, bgcolor: 'background.paper' }}>
<Box>
<Box
sx={{
width: '100%',
maxWidth: 360,
bgcolor: 'background.paper'
}}
>
<List>
<ListItem>Welcome User</ListItem>
<ListItem>Welcome, {user?.fullName ?? 'Guest'}</ListItem>
<Divider component="li" />
<ListItem>Take Questionnaire Again</ListItem>
<ListItemButton style={{ outline: 'none' }}>
Take Questionnaire Again
</ListItemButton>
<Divider component="li" />
<ListItem>Logout</ListItem>
<ListItemButton style={{ outline: 'none' }} onClick={logout}>
Logout
</ListItemButton>
</List>
</Box>
</div>
</Box>
);
};
99 changes: 57 additions & 42 deletions frontend/src/components/ReadySetCyber/RSCDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import Typography from '@mui/material/Typography';
import { RSCSideNav } from './RSCSideNav';
import { Category, Entry, RSCQuestion } from './RSCQuestion';
import { useAuthContext } from 'context';
import { RSCAccordionNav } from './RSCAccordionNav';
import { FloatingNav } from './FloatingNav';
import { ScrollTop } from './ScrollTop';

export const RSCDetail: React.FC = () => {
const { apiGet } = useAuthContext();
Expand Down Expand Up @@ -40,52 +43,64 @@ export const RSCDetail: React.FC = () => {
useEffect(() => {
fetchResult();
}, [fetchResult]);
console.log('Transformed categories:', categories);

return (
<Box sx={{ flexGrow: 1, padding: 2 }}>
<Grid container spacing={2}>
<Grid item xs={4}>
<RSCSideNav categories={categories} />
</Grid>
<Grid item xs={8}>
<Box sx={{ flexGrow: 1, padding: 2, backgroundColor: 'white' }}>
<Stack spacing={2}>
<Stack
direction="row"
justifyContent="space-between"
alignItems="center"
padding={2}
>
<Typography variant="h5" component="div">
Summary and Resources
<>
<Box sx={{ flexGrow: 1, padding: 2 }}>
<Grid container spacing={2}>
<Grid item sm={4} sx={{ display: { xs: 'none', sm: 'grid' } }}>
<RSCSideNav categories={categories} />
</Grid>
<Grid item xs={12} sm={8}>
<Box sx={{ marginBottom: 2, display: { sm: 'none' } }}>
<RSCAccordionNav categories={categories} />
</Box>
<Box
sx={{
flexGrow: 1,
padding: 2,
backgroundColor: 'white'
}}
>
<Stack spacing={2}>
<Stack
direction="row"
justifyContent="space-between"
alignItems="center"
padding={2}
>
<Typography variant="h5" component="div">
Summary and Resources
</Typography>
<Button variant="contained" color="success">
Download PDF
</Button>
</Stack>
<Divider />
<Typography variant="h6" component="h3" gutterBottom>
Thank you for completing the ReadySetCyber questionnaire!
</Typography>
<Typography>
Below, you’ll find a full summary of your completed
ReadySetCyber questionnaire. Please note the areas where you
can improve your organization’s cybersecurity posture, along
with the recommended resources to help you address these
areas. To take further action, contact your regional CISA
Cybersecurity Advisor (CSA) for personalized support. You can
also explore Crossfeed, CISA’s Attack Surface Management
platform, for free vulnerability scanning services to
kickstart or enhance your cybersecurity measures.
</Typography>
<Button variant="contained" color="success">
Download PDF
</Button>
{categories.map((category, index) => (
<RSCQuestion key={index} categories={[category]} />
))}
</Stack>
<Divider />
<Typography variant="h6" component="h3" gutterBottom>
Thank you for completing the ReadySetCyber questionnaire!
</Typography>
<Typography>
Below, you’ll find a full summary of your completed
ReadySetCyber questionnaire. Please note the areas where you can
improve your organization’s cybersecurity posture, along with
the recommended resources to help you address these areas. To
take further action, contact your regional CISA Cybersecurity
Advisor (CSA) for personalized support. You can also explore
Crossfeed, CISA’s Attack Surface Management platform, for free
vulnerability scanning services to kickstart or enhance your
cybersecurity measures.
</Typography>
{categories.map((category, index) => (
<RSCQuestion key={index} categories={[category]} />
))}
</Stack>
</Box>
</Box>
</Grid>
</Grid>
</Grid>
</Box>
</Box>
<FloatingNav categories={categories} />
<ScrollTop />
</>
);
};
8 changes: 4 additions & 4 deletions frontend/src/components/ReadySetCyber/RSCHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ export const RSCHeader: React.FC = () => {
};

return (
<Box>
<AppBar position="static" sx={{ bgcolor: 'white' }}>
<>
<AppBar position="relative" sx={{ bgcolor: 'white' }}>
<Container maxWidth="xl">
<Toolbar disableGutters>
<Tooltip title="Go to Ready Set Cyber" arrow>
Expand Down Expand Up @@ -128,7 +128,7 @@ export const RSCHeader: React.FC = () => {
>
<MenuItem style={{ outline: 'none' }}>
{' '}
Welcome, user
Welcome, {user.fullName}{' '}
</MenuItem>
<MenuItem style={{ outline: 'none' }} onClick={handleNavHome}>
Dashboard
Expand Down Expand Up @@ -184,6 +184,6 @@ export const RSCHeader: React.FC = () => {
</Toolbar>
</Container>
</AppBar>
</Box>
</>
);
};
Loading

0 comments on commit 932a3c4

Please sign in to comment.