Skip to content

Commit

Permalink
feat: refactor of pages to use hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
Rob Ellison committed Aug 8, 2023
1 parent 7c27e5a commit 43212fa
Show file tree
Hide file tree
Showing 17 changed files with 584 additions and 785 deletions.
89 changes: 59 additions & 30 deletions components/content/ContentPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,15 @@ export function ContentPage({
handlePageReset,
collection,
context,
menuComponent
menuComponent,
headerComponent = null,
sideComponent = null
}) {

const [frontmatter, setFrontmatter] = useState(pageContent.frontmatter);
const MenuComponent = menuComponent;
const HeaderComponent = headerComponent;
const SideComponent = sideComponent;

const isEmptyObject = (obj) => {
return Object.keys(obj).length === 0;
Expand Down Expand Up @@ -115,6 +119,9 @@ export function ContentPage({
handlePresentation={frontmatter?.format === 'presentation' ? handlePresentation : null}
collection={collection}
/>



{menuStructure && <MenuComponent
menu={menuStructure.primary}
open={menuOpen}
Expand All @@ -129,8 +136,13 @@ export function ContentPage({

}}
>
{/* {frontmatter && <ServicesHeader frontmatter={frontmatter} controlCoverage={controlCoverage} />} */}
<Typography variant="h1" component="h1" sx={{ pl: 0, mx: '2%' }}>{frontmatter?.title && frontmatter.title}</Typography>
{
headerComponent ? (
<HeaderComponent frontmatter={frontmatter} />
) : (
<Typography variant="h1" component="h1" sx={{ pl: 0, mx: '2%' }}>{frontmatter?.title && frontmatter.title}</Typography>
)
}
{frontmatter?.format === 'presentation' && <Grid container alignItems="center" spacing={1} style={{ textAlign: 'center' }} sx={{ background: 'rgb(229, 246, 253)', px: '10px' }}>
<Grid xs="auto" item>
<Alert severity="info">This is a presentation. View in presentation mode by clicking </Alert>
Expand Down Expand Up @@ -176,13 +188,14 @@ export function ContentPage({

<ContentMenu
content={relatedContent}
// chapters={chapters}
collection={collection}
// knowledge={knowledge}
// designs={designs}
handleContentChange={handleContentChange}
handlePageReset={handlePageReset}
file={file}
/>
{ sideComponent && <SideComponent /> }
{frontmatter?.tableOfContents && <TableOfContents tableOfContents={frontmatter.tableOfContents} />}

{/* <ButtonMenu
Expand Down Expand Up @@ -227,39 +240,55 @@ export function ContentPage({
}


function ContentMenu({ content, file, handleContentChange, handlePageReset }) {
function ContentMenu({ content, file, handleContentChange, handlePageReset, collection }) {
// let directory = file?.includes("/") ? file.split("/")[1] : file;

let directory = path.dirname(file);

// console.log('ChaptersMenu:File ', file)
// console.log('ContentMenu:directory ', directory)
// console.log('ContentMenu:content ', content)

let chaptersMenu = []
if (content && content[directory]) {
if (content[directory].chapters) {
chaptersMenu.push(
{
groupTitle: "Chapters",
links: content[directory].chapters
}
)
}
if (content[directory].knowledge) {
chaptersMenu.push(
{
groupTitle: "Knowledge",
links: content[directory].knowledge

}
)
}
if (content[directory].designs) {
chaptersMenu.push(
{
groupTitle: "Designs",
links: content[directory].designs
}
)
for (let collectionItem of collection.collections) {
if (content[directory][collectionItem]) {
chaptersMenu.push(
{
groupTitle: collectionItem.path,
links: content[directory][collectionItem]
}
)
}
}




// if (content[directory].chapters) {
// chaptersMenu.push(
// {
// groupTitle: "Chapters",
// links: content[directory].chapters
// }
// )
// }
// if (content[directory].knowledge) {
// chaptersMenu.push(
// {
// groupTitle: "Knowledge",
// links: content[directory].knowledge

// }
// )
// }
// if (content[directory].designs) {
// chaptersMenu.push(
// {
// groupTitle: "Designs",
// links: content[directory].designs
// }
// )
// }
}
if (chaptersMenu) {
// return (null)
Expand Down
2 changes: 1 addition & 1 deletion components/content/IndexView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function IndexView({
menu={true}
topBarHeight={topBarHeight} />

{menuStructure && <MenuComponent
{menuStructure && menuStructure.primary && <MenuComponent
menu={menuStructure.primary}
open={menuOpen}
top={topBarHeight}
Expand Down
94 changes: 94 additions & 0 deletions components/dashboard/Headers/ServicesHeader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React from 'react'

import Grid from '@mui/material/Grid';

import { Stack } from '@mui/material'
import { Chip } from '@mui/material'
import { MiniStatisticsCard } from "@/components/dashboard";
import { Dialog, DialogTitle, DialogContent, DialogActions, Button, IconButton, Typography, Box } from '@mui/material';
import { Container as MuiContainer } from "@mui/material";


export function ServicesHeader({ frontmatter, extraData }) {

const controlCoverage = createControlCoverage(extraData);

if (!frontmatter) { return <></> }
// frontmatter = frontmatter.frontmatter
// console.log('ServicesHeader:controlCoverage: ', controlCoverage)
// // console.log('ServicesHeader:frontmatter: ', frontmatter)

let icon = { color: 'success', icon: 'check' }

if (controlCoverage && controlCoverage.controlCoverage < 50) {
icon = { color: 'error', icon: 'circle-exclamation' }
} else if (controlCoverage && controlCoverage.controlCoverage < 100) {
icon = { color: 'warning', icon: 'triangle-exclamation' }
} else if (!controlCoverage.controlCoverage) {
icon = { color: 'info', icon: 'circle-exclamation' }
}

return (
<MuiContainer maxWidth={false} sx={{ paddingTop: 0, paddingBottom: 0 }}>
{/* <Box sx={{ display: "flex" }}>{children}</Box> */}

{/* <Container sx={{ px: '0px', mb: '2%' }}> */}
<Grid container spacing={2} alignItems="center" sx={{ mb: '3%' }} component="servicesHeader">
<Grid item xs={8}>
<Typography variant="h1" component="h1">{frontmatter.title}</Typography>
<Stack direction="row" spacing={1}>
{frontmatter.status === 'approved' ? <Chip label="Approved for use" color="success" /> : <Chip label="Unapproved" color="error" />}
{(frontmatter?.resilience?.redundancy) ? <Chip label={`Redundancy: ${frontmatter.resilience.redundancy}`} color="success" /> : <Chip label="No Redundancy info" color="error" />}
{frontmatter?.resilience?.find(item => item.name === "availability") ? (
<Chip
label={`Availability: ${frontmatter.resilience.find(item => item.name === "availability").availability}`}
color="success"
/>
) : (
<Chip label="No SLA Defined" color="error" />
)}

</Stack>
</Grid>
<Grid item xs={4}>
<MiniStatisticsCard
color="text.highlight"
title="Controls"
count={controlCoverage.controlCount}
percentage={{ value: controlCoverage.controlCoverage ? controlCoverage.controlCoverage : '0', text: "% coverage" }}
icon={icon}
/>
</Grid>
</Grid>
{/* </Container> */}
</MuiContainer>
)
}





function createControlCoverage(controls) {
// // console.log('createControlCoverage:controls: ', controls)

let controlCountCovered = 0
let controlCountUnCovered = 0
let controlMethods = 0
let controlCoverage = 0


for (const control of controls) {
if (control.data && control.data.methods && control.data.methods.length > 0) {
controlMethods += control.data.methods.length
controlCountCovered++
} else {
controlCountUnCovered++
}
}
// calculate the percentage of covered controls vs controls
controlCoverage = Math.round((controlCountCovered / controls.length) * 100)
// // console.log('createControlCoverage:controlCoverage: ', controlCoverage)
return ({ controlCountCovered, controlCountUnCovered, controlMethods, controlCoverage, controlCount: controls.length })
};

1 change: 1 addition & 0 deletions components/dashboard/Headers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { ServicesHeader } from './ServicesHeader'
88 changes: 88 additions & 0 deletions components/dashboard/Menus/ControlsMenu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React, { useState } from 'react'
import { ButtonMenu } from '@/components/airview-ui';
import { ControlDataDisplay } from '@/components/compliance/ControlData';
import CloseIcon from '@mui/icons-material/Close';

import { Dialog, DialogTitle, DialogContent, DialogActions, Button, IconButton, Typography, Box } from '@mui/material';


export function ControlsMenu({
controls
}) {

const [dialogOpen, setDialogOpen] = useState(false);
const [controlUrl, setControlUrl] = useState('');

const handleControlClick = (url, label) => {
// Show the dialog box
setDialogOpen(true);
const selectedControl = controls.find((control) => control.file === url);
setControlUrl({ url, label, selectedControl });

};

return (
<>
<ButtonMenu
menuTitle="Controls"
menuItems={createControlMenu(controls)}
initialCollapsed={false}
loading={false}
fetching={false}
handleButtonClick={handleControlClick}
/>

{controlUrl.selectedControl &&
<Dialog open={dialogOpen} onClose={() => setDialogOpen(false)} fullWidth={true} maxWidth={'lg'} sx={{
"& .MuiDialog-container": {
alignItems: "flex-start"
}
}}
scroll='paper'>
<DialogTitle sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<Typography variant="h4">{controlUrl.selectedControl?.data?.name} ({controlUrl.selectedControl?.data?.id || 'N/A'})</Typography>
<IconButton edge="end" color="inherit" onClick={() => setDialogOpen(false)} aria-label="close">
<CloseIcon />
</IconButton>
</DialogTitle>
<DialogContent>
<ControlDataDisplay data={controlUrl.selectedControl} />
</DialogContent>
</Dialog>
}
</>
)

}



function createControlMenu(controls) {
// console.log('createControlMenu:controls: ', controls)
try {
const links = controls.map((control) => {
const label = control.data.name || control.data.id || ''; // Adjust the property name according to your control data structure
const url = control.file;

return {
label,
url,
};
});

return [
{
links: links
}];
} catch (error) {
// // console.log('createControlMenu:error: ', error)

return [
{
groupTitle: "Controls",
links: [],
}]
}
};


Loading

0 comments on commit 43212fa

Please sign in to comment.