From 35fd68b46049f289f3d7cfae605bda4dcc3f610c Mon Sep 17 00:00:00 2001 From: Rob Ellison Date: Fri, 30 Jun 2023 10:30:00 +0000 Subject: [PATCH] feat: add ToC --- .../navigation-drawer/navigation-drawer.js | 5 +- components/content/TableOfContents.jsx | 110 ++++++++++++ components/content/index.js | 3 +- components/dashboard/TopBar.jsx | 2 +- components/display/PresentationOutput.jsx | 1 + components/etherpad/Etherpad.jsx | 17 +- components/solutions/SolutionView.jsx | 53 +++--- constants/mdxProvider.js | 14 +- constants/theme.js | 10 +- lib/content/mdx.js | 90 +++------- pages/customers/[...customer].jsx | 4 +- pages/solutions/[...solution].jsx | 158 ++++++++++-------- 12 files changed, 277 insertions(+), 190 deletions(-) create mode 100644 components/content/TableOfContents.jsx diff --git a/components/airview-ui/navigation-drawer/navigation-drawer.js b/components/airview-ui/navigation-drawer/navigation-drawer.js index 3cfef18d..94af9711 100644 --- a/components/airview-ui/navigation-drawer/navigation-drawer.js +++ b/components/airview-ui/navigation-drawer/navigation-drawer.js @@ -18,7 +18,7 @@ export function NavigationDrawer({ bottom: 0, left: 0, width: drawerWidth, - borderRight: 1, + borderRight: 0, borderColor: "grey.300", paddingY: 6, paddingX: 3, @@ -26,7 +26,8 @@ export function NavigationDrawer({ backgroundColor: "common.white", zIndex: 1200, overflowY: "auto", - displayPrint: 'none' + displayPrint: 'none', + borderTop: '1px solid #e0e0e0' }} > {children} diff --git a/components/content/TableOfContents.jsx b/components/content/TableOfContents.jsx new file mode 100644 index 00000000..571c864f --- /dev/null +++ b/components/content/TableOfContents.jsx @@ -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 ( + + {tableOfContents.map((item, index) => { + const { depth, value, id, children } = item; + const itemNumbering = [...numbering, index + 1]; + const numberingString = itemNumbering.join('.'); + + const listItemText = ( + + {`${numberingString} `} + {value} + + ); + + if (children && children.length > 0) { + return ( + + {listItemText} + + {generateTableOfContents(children, itemNumbering)} + + + ); + } + + return ( + + + {listItemText} + + + ); + })} + + ); +}; + +export const TableOfContents = ({ tableOfContents }) => { + const [collapsed, setCollapsed] = useState(false); + const menuTitleElement = "h3" + const loading = false; + const menuTitle = 'Page Contents' + return ( + + + + {loading ? : menuTitle} + + + setCollapsed((prevState) => !prevState)} + size="medium" + aria-label={collapsed ? "Expand menu" : "Collapse menu"} + disabled={loading} + sx={{ + marginLeft: 1, + padding: 0, + color: "primary.main", + }} + > + {collapsed ? ( + + ) : ( + + )} + + + + + + {generateTableOfContents(tableOfContents)} + + + + ); +}; diff --git a/components/content/index.js b/components/content/index.js index 02e704e9..2a868b42 100644 --- a/components/content/index.js +++ b/components/content/index.js @@ -1,2 +1,3 @@ export { IndexView } from './IndexView' -export { ContentView } from './ContentView' \ No newline at end of file +export { ContentView } from './ContentView' +export { TableOfContents } from './TableOfContents' \ No newline at end of file diff --git a/components/dashboard/TopBar.jsx b/components/dashboard/TopBar.jsx index 8e235b47..863ecd47 100644 --- a/components/dashboard/TopBar.jsx +++ b/components/dashboard/TopBar.jsx @@ -43,7 +43,7 @@ export function TopBar({ return ( - + {/* has menu */} {menu && {navOpen ? : }} diff --git a/components/display/PresentationOutput.jsx b/components/display/PresentationOutput.jsx index 51d18d64..56c7a031 100644 --- a/components/display/PresentationOutput.jsx +++ b/components/display/PresentationOutput.jsx @@ -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 }); diff --git a/components/etherpad/Etherpad.jsx b/components/etherpad/Etherpad.jsx index 9916a6be..eef8f5a8 100644 --- a/components/etherpad/Etherpad.jsx +++ b/components/etherpad/Etherpad.jsx @@ -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 @@ -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(() => { @@ -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]); diff --git a/components/solutions/SolutionView.jsx b/components/solutions/SolutionView.jsx index ae0aad94..8aa0733f 100644 --- a/components/solutions/SolutionView.jsx +++ b/components/solutions/SolutionView.jsx @@ -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, @@ -24,6 +25,11 @@ export function SolutionView({ }) { + let tableOfContents = []; + if (frontmatter && frontmatter.tableOfContents) { + + + } // console.log('SolutionView:menuStructure: ', menuStructure) const navDrawerWidth = 300; const topBarHeight = 64; @@ -111,6 +117,7 @@ export function SolutionView({ {children && children}