Skip to content

Commit

Permalink
feat: add ToC
Browse files Browse the repository at this point in the history
  • Loading branch information
Rob Ellison committed Jun 30, 2023
1 parent 359c849 commit 35fd68b
Show file tree
Hide file tree
Showing 12 changed files with 277 additions and 190 deletions.
5 changes: 3 additions & 2 deletions components/airview-ui/navigation-drawer/navigation-drawer.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,16 @@ export function NavigationDrawer({
bottom: 0,
left: 0,
width: drawerWidth,
borderRight: 1,
borderRight: 0,
borderColor: "grey.300",
paddingY: 6,
paddingX: 3,
boxSizing: "border-box",
backgroundColor: "common.white",
zIndex: 1200,
overflowY: "auto",
displayPrint: 'none'
displayPrint: 'none',
borderTop: '1px solid #e0e0e0'
}}
>
{children}
Expand Down
110 changes: 110 additions & 0 deletions components/content/TableOfContents.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import React, {useState} from 'react';
import { Link as MuiLink, Box, Typography, List, ListItem, ListItemText, styled, Collapse, IconButton } from '@mui/material';
import KeyboardArrowRightIcon from "@mui/icons-material/KeyboardArrowRight";
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
// Custom styled components
const SmallListItemText = styled(ListItemText)(({ theme }) => ({
fontSize: theme.typography.body2.fontSize,
lineHeight: theme.typography.body2.lineHeight,
paddingBottom: theme.spacing(0),
paddingTop: theme.spacing(0),
marginBottom: theme.spacing(0),
marginTop: theme.spacing(0),
}));

const generateTableOfContents = (tableOfContents, numbering = []) => {
if (!tableOfContents || tableOfContents.length === 0) {
return null;
}

return (
<List component="nav" aria-labelledby="table-of-contents">
{tableOfContents.map((item, index) => {
const { depth, value, id, children } = item;
const itemNumbering = [...numbering, index + 1];
const numberingString = itemNumbering.join('.');

const listItemText = (
<SmallListItemText
primaryTypographyProps={{ variant: 'body2' }}
disableTypography
>
<span>{`${numberingString} `}</span>
{value}
</SmallListItemText>
);

if (children && children.length > 0) {
return (
<List key={id} sx={{ p: 0 }}>
<ListItem sx={{ p: 0 }}>{listItemText}</ListItem>
<List sx={{ p: 0 }}>
{generateTableOfContents(children, itemNumbering)}
</List>
</List>
);
}

return (
<ListItem key={id} disableGutters sx={{ p: 0 }}>
<MuiLink href={`#${id}`} underline="none">
{listItemText}
</MuiLink>
</ListItem>
);
})}
</List>
);
};

export const TableOfContents = ({ tableOfContents }) => {
const [collapsed, setCollapsed] = useState(false);
const menuTitleElement = "h3"
const loading = false;
const menuTitle = 'Page Contents'
return (
<Box sx={{ pl: 0 }}>
<Box
component="header"
sx={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
marginBottom: 0,
}}
>
<Typography
component={menuTitleElement}
variant="subtitle2"
sx={{ display: "block", flex: "1 1 auto", fontSize: 16 }}
>
{loading ? <Skeleton width="90%" /> : menuTitle}
</Typography>

<IconButton
onClick={() => setCollapsed((prevState) => !prevState)}
size="medium"
aria-label={collapsed ? "Expand menu" : "Collapse menu"}
disabled={loading}
sx={{
marginLeft: 1,
padding: 0,
color: "primary.main",
}}
>
{collapsed ? (
<KeyboardArrowRightIcon fontSize="inherit" />
) : (
<KeyboardArrowDownIcon fontSize="inherit" />
)}
</IconButton>
</Box>
<Collapse in={!collapsed}>


{generateTableOfContents(tableOfContents)}

</Collapse>
</Box>
);
};
3 changes: 2 additions & 1 deletion components/content/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { IndexView } from './IndexView'
export { ContentView } from './ContentView'
export { ContentView } from './ContentView'
export { TableOfContents } from './TableOfContents'
2 changes: 1 addition & 1 deletion components/dashboard/TopBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export function TopBar({


return (
<AppBar position="fixed" color="white" elevation={0} sx={{ displayPrint: 'none',borderBottom: '1px solid #e0e0e0' }}>
<AppBar position="fixed" color="white" elevation={0} sx={{ displayPrint: 'none', borderBottom: 1, borderColor: 'grey.300' }}>
<Toolbar>
{/* has menu */}
{menu && <IconButton size="large" edge="start" color="inherit" aria-label="menu" sx={{ mr: 2 }} onClick={onNavButtonClick}>{navOpen ? <CloseIcon /> : <MenuIcon />}</IconButton>}
Expand Down
1 change: 1 addition & 0 deletions components/display/PresentationOutput.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const PresentationOutput = dynamic(() => Promise.resolve(PresentationOutp
ssr: true,
});


function PresentationOutputPage({ children, handlePresentation, refresh = false, content }) {
const [pageContent, setContent] = useState({ content: undefined, frontmatter: undefined });

Expand Down
17 changes: 10 additions & 7 deletions components/etherpad/Etherpad.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as matter from 'gray-matter';
import { siteConfig } from "../../site.config.js";


export function Etherpad({ file, children }) {
export function Etherpad({ file, frontMatterCallback }) {


const etherpad_host = siteConfig?.etherpad?.url ?? null
Expand Down Expand Up @@ -38,6 +38,7 @@ export function Etherpad({ file, children }) {
useEffect(() => { // process the rawcontent
const { mdxContent, frontmatter } = useMDX(content, 'mdx');
setPageContent({ content: mdxContent, frontmatter: frontmatter });
frontMatterCallback(frontmatter);
}, [content])

// useEffect(() => {
Expand Down Expand Up @@ -113,20 +114,22 @@ export function Etherpad({ file, children }) {
}
})
.catch(error => {
// // // console.log(error)
console.error('Etherpad:Error refreshing pad: ', error)
})
}

})
.catch(error => {
// // // console.log(error)
console.error('Etherpad:Error refreshing pad revisions: ', error)
})
.finally(() => {
setTimeout(() => setRefreshToken(Math.random()), 5000);
});

}

if (padId) { fetchPadContent() } else { fetchPadMetadata() }
if (padId) {
fetchPadContent()
setTimeout(() => setRefreshToken(Math.random()), 5000);
console.log('Etherpad:useEffect:PadRefresh')
} else { fetchPadMetadata() }

}, [refreshToken]);

Expand Down
53 changes: 31 additions & 22 deletions components/solutions/SolutionView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import SlideshowIcon from '@mui/icons-material/Slideshow';
import { IconButton, Typography, MenuItem, Box, Alert, Grid, ButtonBase } from '@mui/material';

import { AsideAndMainContainer, Aside, Main } from '@/components/airview-ui';
import { TableOfContents } from '@/components/content';

export function SolutionView({
children,
Expand All @@ -24,6 +25,11 @@ export function SolutionView({
}) {


let tableOfContents = [];
if (frontmatter && frontmatter.tableOfContents) {


}
// console.log('SolutionView:menuStructure: ', menuStructure)
const navDrawerWidth = 300;
const topBarHeight = 64;
Expand Down Expand Up @@ -111,6 +117,7 @@ export function SolutionView({
{children && children}
</Main>
<Aside sx={{ mt: '1%', displayPrint: 'none', display: print ? 'none' : '' }}>

<ContentMenu
content={relatedContent}
// chapters={chapters}
Expand All @@ -119,6 +126,8 @@ export function SolutionView({
handleContentClick={handleContentClick}
file={file}
/>
{frontmatter?.tableOfContents && <TableOfContents tableOfContents={frontmatter.tableOfContents} />}

{/* <ButtonMenu
menuTitle="Controls"
menuItems={createControlMenu(controls)}
Expand Down Expand Up @@ -188,28 +197,28 @@ function ContentMenu({ content, file, handleContentClick }) {

return (
<>
<ButtonBase
variant="text"
onClick={() => handleContentClick('/' + file, 'primary link')}
sx={{
textDecoration: "none",
textTransform: 'none',
textAlign: 'left',
fontWeight: 'bold',
color: 'secondary.main',
mb: '5%'
}}
>Main Content</ButtonBase>

<ButtonMenu
menuTitle="Content"
menuItems={chaptersMenu}
initialCollapsed={false}
loading={false}
fetching={false}
handleButtonClick={handleContentClick}
/></>
<ButtonBase
variant="text"
onClick={() => handleContentClick('/' + file, 'primary link')}
sx={{
textDecoration: "none",
textTransform: 'none',
textAlign: 'left',
fontWeight: 'bold',
color: 'secondary.main',
mb: '5%'
}}
>Main Content</ButtonBase>

<ButtonMenu
menuTitle="Related Content"
menuItems={chaptersMenu}
initialCollapsed={false}
loading={false}
fetching={false}
handleButtonClick={handleContentClick}
/></>

)
// return (
// <Menu
Expand Down
14 changes: 7 additions & 7 deletions constants/mdxProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,17 +195,17 @@ function MdxImage({ props, baseContext }) {

// export const mdComponents = {
export const mdComponents = (baseContext) => ({
h1: (props) => <Typography variant="h1">{props.children}</Typography>,
h2: (props) => <Typography variant="h2">{props.children}</Typography>,
h3: (props) => <Typography variant="h3">{props.children}</Typography>,
h4: (props) => <Typography variant="h4">{props.children}</Typography>,
h5: (props) => <Typography variant="h5">{props.children}</Typography>,
h1: (props) => <Typography variant="h1" id={props.id}>{props.children}</Typography>,
h2: (props) => <Typography variant="h2" id={props.id}>{props.children}</Typography>,
h3: (props) => <Typography variant="h3" id={props.id}>{props.children}</Typography>,
h4: (props) => <Typography variant="h4" id={props.id}>{props.children}</Typography>,
h5: (props) => <Typography variant="h5" id={props.id}>{props.children}</Typography>,
p: (props) => <Typography variant="p">{props.children}</Typography>,
img: (props) => (<MdxImage props={props} baseContext={baseContext} fill loading="lazy" />),
strong: (props) => <Typography variant="strong">{props.children}</Typography>,
ul: (props) => <Typography variant="ul">{props.children}</Typography>,
// ul: (props) => <Typography variant="ul">{props.children}</Typography>,
// table: (props) => <Typography variant="table">{props.children}</Typography>,
hr: (props) => null,
// hr: (props) => null,
pre: (props) => props.children,
code: (props) => {
const { className } = props;
Expand Down
10 changes: 7 additions & 3 deletions constants/theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,19 @@ const theme = deepmerge(
color: palette.palette.text.highlight,
},
ul: {
display: 'inline',
display: 'inline-block',
breakInside: 'avoid-column',
listStyleType: 'circle',
li: {
listStylePosition: 'inside',
"::marker": {
color: 'tertiary',
}
}
},
span: {
display: 'inline',
},
},

},
table: {
display: "inline-table",
Expand Down
Loading

0 comments on commit 35fd68b

Please sign in to comment.