Added table of contents to left-side documentation view

This commit is contained in:
frikky
2021-10-04 19:05:05 +02:00
parent 6ecbba137e
commit 908d8d9cd3
7 changed files with 158 additions and 25 deletions
+4
View File
@@ -5896,6 +5896,10 @@ func initHandlers() {
r.HandleFunc("/api/v1/files/{fileId}", shuffle.HandleDeleteFile).Methods("DELETE", "OPTIONS") r.HandleFunc("/api/v1/files/{fileId}", shuffle.HandleDeleteFile).Methods("DELETE", "OPTIONS")
r.HandleFunc("/api/v1/files", shuffle.HandleGetFiles).Methods("GET", "OPTIONS") r.HandleFunc("/api/v1/files", shuffle.HandleGetFiles).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/notifications", shuffle.HandleGetNotifications).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/notifications/{notificationId}/markasread", shuffle.HandleMarkAsRead).Methods("GET", "OPTIONS")
//r.HandleFunc("/api/v1/notifications/{notificationId}/markasread", shuffle.HandleMarkAsRead).Methods("GET", "OPTIONS")
http.Handle("/", r) http.Handle("/", r)
} }
+1
View File
@@ -108,6 +108,7 @@ const App = (message, props) => {
<div style={{ backgroundColor: "#1F2023", color: "rgba(255, 255, 255, 0.65)", minHeight: "100vh" }}> <div style={{ backgroundColor: "#1F2023", color: "rgba(255, 255, 255, 0.65)", minHeight: "100vh" }}>
<ScrollToTop setCurpath={setCurpath} /> <ScrollToTop setCurpath={setCurpath} />
<Header checkLogin={checkLogin} cookies={cookies} removeCookie={removeCookie} isLoaded={isLoaded} globalUrl={globalUrl} setIsLoggedIn={setIsLoggedIn} isLoggedIn={isLoggedIn} userdata={userdata} {...props} /> <Header checkLogin={checkLogin} cookies={cookies} removeCookie={removeCookie} isLoaded={isLoaded} globalUrl={globalUrl} setIsLoggedIn={setIsLoggedIn} isLoggedIn={isLoggedIn} userdata={userdata} {...props} />
<div style={{marginTop: 60}}/>
<Route exact path="/login" render={props => <LoginPage isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} checkLogin={checkLogin} {...props} />} /> <Route exact path="/login" render={props => <LoginPage isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} checkLogin={checkLogin} {...props} />} />
<Route exact path="/admin" render={props => <Admin userdata={userdata} isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} {...props} />} /> <Route exact path="/admin" render={props => <Admin userdata={userdata} isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} {...props} />} />
<Route exact path="/admin/:key" render={props => <Admin isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} {...props} />} /> <Route exact path="/admin/:key" render={props => <Admin isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} {...props} />} />
+60 -9
View File
@@ -5,8 +5,8 @@ import {Link} from 'react-router-dom';
import { useTheme } from '@material-ui/core/styles'; import { useTheme } from '@material-ui/core/styles';
import { Tooltip, List, Avatar, Menu, ListItem, MenuItem, Select, Button, IconButton, Grid } from '@material-ui/core'; import { Badge, Typography, Paper, Tooltip, List, Avatar, Menu, ListItem, MenuItem, Select, Button, IconButton, Grid } from '@material-ui/core';
import { Home as HomeIcon, Polymer as PolymerIcon, Apps as AppsIcon, Description as DescriptionIcon} from '@material-ui/icons'; import { Notifications as NotificationsIcon, Home as HomeIcon, Polymer as PolymerIcon, Apps as AppsIcon, Description as DescriptionIcon} from '@material-ui/icons';
import { useAlert } from "react-alert"; import { useAlert } from "react-alert";
const hoverColor = "#f85a3e" const hoverColor = "#f85a3e"
@@ -148,12 +148,60 @@ const Header = props => {
setAnchorEl(null); setAnchorEl(null);
}; };
const notifications = [{
"image": "https://dytvr9ot2sszz.cloudfront.net/whats-new-announcements/billboard_metricsdashbd_sept2021.png",
"date": "1519211809934",
"title": "some title",
"description": "This is a escription",
"dismissable": true,
"personal": false,
"org_id": "",
}]
const notificationMenu =
<span style={{zIndex: 10001}}>
<IconButton color="primary" style={{zIndex: 10001, marginRight: 15, }} aria-controls="simple-menu" aria-haspopup="true" onClick={(event) => {
setAnchorEl(event.currentTarget);
}}>
<Badge badgeContent={notifications.length} color="primary">
<NotificationsIcon color="secondary" style={{height: 35, width: 35,}} alt="Your username here" src="" />
</Badge>
</IconButton>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
style={{zIndex: 10002}}
onClose={() => {
handleClose()
}}
>
{notifications.map((data, index) => {
return (
<MenuItem onClick={(event) => {}}>
<Paper style={{width: 300, height: 150, }}>
<Grid container direction="row" alignItems="center">
<Grid item>
<Typography variant="h6">
{new Date(data.date).toISOString()}
</Typography >
<Typography variant="h6">
{data.title}
</Typography >
</Grid>
</Grid>
</Paper>
</MenuItem>
)
})}
</Menu>
</span>
// Should be based on some path // Should be based on some path
const avatarMenu = const avatarMenu =
<span> <span style={{zIndex: 10001}}>
<IconButton color="primary" style={{marginRight: 15, }} aria-controls="simple-menu" aria-haspopup="true" onClick={(event) => { <IconButton color="primary" style={{zIndex: 10001, marginRight: 15, }} aria-controls="simple-menu" aria-haspopup="true" onClick={(event) => {
setAnchorEl(event.currentTarget); setAnchorEl(event.currentTarget);
}}> }}>
<Avatar style={{height: 35, width: 35,}} alt="Your username here" src="" /> <Avatar style={{height: 35, width: 35,}} alt="Your username here" src="" />
@@ -163,6 +211,7 @@ const Header = props => {
anchorEl={anchorEl} anchorEl={anchorEl}
keepMounted keepMounted
open={Boolean(anchorEl)} open={Boolean(anchorEl)}
style={{zIndex: 10002}}
onClose={() => { onClose={() => {
handleClose() handleClose()
}} }}
@@ -188,8 +237,9 @@ const Header = props => {
// Handle top bar or something // Handle top bar or something
const logoCheck = !homePage ? null : null const logoCheck = !homePage ? null : null
//<div style={{position: "fixed", top: 0, left: 0, display: "flex"}}>
const loginTextBrowser = !isLoggedIn ? const loginTextBrowser = !isLoggedIn ?
<div style={{display: "flex"}}> <div style={{display: "flex"}}>
<List style={{display: "flex", flexDirect: "row"}} component="nav"> <List style={{display: "flex", flexDirect: "row"}} component="nav">
<ListItem style={{textAlign: "center", marginLeft: "0px"}}> <ListItem style={{textAlign: "center", marginLeft: "0px"}}>
<Link to ="/docs/about" style={hrefStyle}> <Link to ="/docs/about" style={hrefStyle}>
@@ -265,6 +315,7 @@ const Header = props => {
</div> </div>
<div style={{flex: "10", display: "flex", flexDirection: "row-reverse"}}> <div style={{flex: "10", display: "flex", flexDirection: "row-reverse"}}>
{avatarMenu} {avatarMenu}
{notificationMenu}
{userdata === undefined || userdata.admin === undefined || userdata.admin === null || !userdata.admin ? null : {userdata === undefined || userdata.admin === undefined || userdata.admin === null || !userdata.admin ? null :
<Link to="/admin" style={hrefStyle}> <Link to="/admin" style={hrefStyle}>
<Button color="primary" variant="contained" style={{marginRight: 15, marginTop: 12}}> <Button color="primary" variant="contained" style={{marginRight: 15, marginTop: 12}}>
@@ -376,7 +427,7 @@ const Header = props => {
// <Divider style={{height: "1px", width: "100%", backgroundColor: "rgb(91, 96, 100)"}}/> // <Divider style={{height: "1px", width: "100%", backgroundColor: "rgb(91, 96, 100)"}}/>
const loadedCheck = const loadedCheck =
<div style={{minHeight: 60}}> <div style={{minHeight: 60, }}>
<BrowserView> <BrowserView>
{loginTextBrowser} {loginTextBrowser}
</BrowserView> </BrowserView>
@@ -386,10 +437,10 @@ const Header = props => {
</div> </div>
// <div style={{backgroundImage: "linear-gradient(-90deg,#342f78 0,#29255e 50%,#1b1947 100%"}}> // <div style={{backgroundImage: "linear-gradient(-90deg,#342f78 0,#29255e 50%,#1b1947 100%"}}>
return ( return (
<div> <div style={{width: "100%", position: "fixed", minHeight: 60, top: 0, zIndex: 10000, backgroundColor: "inherit",}}>
{loadedCheck} {loadedCheck}
</div> </div>
) )
} }
export default Header; export default Header;
+1 -1
View File
@@ -2936,7 +2936,7 @@ const Admin = (props) => {
const iconStyle = {marginRight: 10} const iconStyle = {marginRight: 10}
const data = const data =
<div style={{width: 1366, margin: "auto", overflowX: "hidden", marginTop: 25,}}> <div style={{width: 1300, margin: "auto", overflowX: "hidden", marginTop: 25,}}>
<Paper style={paperStyle}> <Paper style={paperStyle}>
<Tabs <Tabs
value={curTab} value={curTab}
+1 -1
View File
@@ -8671,7 +8671,7 @@ const AngularWorkflow = (props) => {
minZoom={0.35} minZoom={0.35}
maxZoom={2.00} maxZoom={2.00}
wheelSensitivity={0.25} wheelSensitivity={0.25}
style={{width: bodyWidth-leftBarSize-5, height: bodyHeight-appBarSize-5, backgroundColor: surfaceColor}} style={{width: bodyWidth-leftBarSize-15, height: bodyHeight-appBarSize-5, backgroundColor: surfaceColor}}
stylesheet={cystyle} stylesheet={cystyle}
boxSelectionEnabled={true} boxSelectionEnabled={true}
autounselectify={false} autounselectify={false}
+10 -7
View File
@@ -129,6 +129,7 @@ const Apps = (props) => {
const upload = React.useRef(null); const upload = React.useRef(null);
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" ? true : false const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" ? true : false
const borderRadius = 3 const borderRadius = 3
const viewWidth = 590
const { start, stop } = useInterval({ const { start, stop } = useInterval({
duration: 5000, duration: 5000,
@@ -177,6 +178,7 @@ const Apps = (props) => {
color: "#ffffff", color: "#ffffff",
width: "100%", width: "100%",
display: "flex", display: "flex",
margin: "auto",
} }
const paperAppStyle = { const paperAppStyle = {
@@ -473,13 +475,14 @@ const Apps = (props) => {
const dividerColor = "rgb(225, 228, 232)" const dividerColor = "rgb(225, 228, 232)"
const uploadViewPaperStyle = { const uploadViewPaperStyle = {
minWidth: 662.5, minWidth: viewWidth,
maxWidth: 662.5, maxWidth: viewWidth,
color: "white", color: "white",
borderRadius: 5, borderRadius: 5,
backgroundColor: surfaceColor, backgroundColor: surfaceColor,
display: "flex", display: "flex",
marginBottom: 10, marginBottom: 10,
overflow: "hidden",
} }
const UploadView = () => { const UploadView = () => {
@@ -761,7 +764,7 @@ const Apps = (props) => {
{/*<p><b>Owner:</b> {selectedApp.owner}</p>*/} {/*<p><b>Owner:</b> {selectedApp.owner}</p>*/}
{selectedApp.privateId !== undefined && selectedApp.privateId.length > 0 ? <p><b>PrivateID:</b> {selectedApp.privateId}</p> : null} {selectedApp.privateId !== undefined && selectedApp.privateId.length > 0 ? <p><b>PrivateID:</b> {selectedApp.privateId}</p> : null}
<Divider style={{marginBottom: 10, marginTop: 10, backgroundColor: dividerColor}}/> <Divider style={{marginBottom: 10, marginTop: 10, backgroundColor: dividerColor}}/>
<div style={{padding: 20}}> <div style={{paddingTop: 20, paddingBottom: 20, }}>
{selectedApp.link.length > 0 ? <p><b>URL:</b> {selectedApp.link}</p> : null} {selectedApp.link.length > 0 ? <p><b>URL:</b> {selectedApp.link}</p> : null}
<div style={{marginTop: 15, marginBottom: 15}}> <div style={{marginTop: 15, marginBottom: 15}}>
<b>Actions</b> <b>Actions</b>
@@ -944,9 +947,9 @@ const Apps = (props) => {
}, [appValidation, isDropzone]); }, [appValidation, isDropzone]);
const appView = isLoggedIn ? const appView = isLoggedIn ?
<Dropzone style={{maxWidth: window.innerWidth > 1366 ? 1366 : 1200, margin: "auto", padding: 20 }} onDrop={uploadFile}> <Dropzone style={{width: viewWidth*2+20, margin: "auto", padding: 20 }} onDrop={uploadFile}>
<div style={appViewStyle}> <div style={appViewStyle}>
<div style={{flex: 1, }}> <div style={{flex: 1, maxWidth: viewWidth, marginRight: 10,}}>
<Breadcrumbs aria-label="breadcrumb" separator="" style={{color: "white",}}> <Breadcrumbs aria-label="breadcrumb" separator="" style={{color: "white",}}>
<Link to="/apps" style={{textDecoration: "none", color: "inherit",}}> <Link to="/apps" style={{textDecoration: "none", color: "inherit",}}>
<Typography variant="h6" style={{color: "rgba(255,255,255,0.5)"}}> <Typography variant="h6" style={{color: "rgba(255,255,255,0.5)"}}>
@@ -963,9 +966,9 @@ const Apps = (props) => {
: null} : null}
</Breadcrumbs> </Breadcrumbs>
<div style={{marginTop: 15}} /> <div style={{marginTop: 15}} />
<UploadView/> <UploadView />
</div> </div>
<div style={{flex: 1, marginLeft: 10, marginRight: 10, }}> <div style={{flex: 1, marginLeft: 10, maxWidth: viewWidth, }}>
<div style={{display: "flex",}}> <div style={{display: "flex",}}>
<div style={{flex: 1, marginBottom: 15, }}> <div style={{flex: 1, marginBottom: 15, }}>
<Typography variant="h6"> <Typography variant="h6">
+81 -7
View File
@@ -13,7 +13,7 @@ const Body = {
minWidth: '768px', minWidth: '768px',
margin: 'auto', margin: 'auto',
display: "flex", display: "flex",
heigth: "100%", height: "100%",
color: "white", color: "white",
//textAlign: "center", //textAlign: "center",
}; };
@@ -24,6 +24,11 @@ const hrefStyle = {
textDecoration: "none" textDecoration: "none"
} }
const innerHrefStyle = {
color: "rgba(255, 255, 255, 0.75)",
textDecoration: "none"
}
const Docs = (props) => { const Docs = (props) => {
const { globalUrl, selectedDoc, serverside, isMobile, } = props; const { globalUrl, selectedDoc, serverside, isMobile, } = props;
@@ -36,6 +41,7 @@ const Docs = (props) => {
const [anchorEl, setAnchorEl] = React.useState(null); const [anchorEl, setAnchorEl] = React.useState(null);
const [headingSet, setHeadingSet] = React.useState(false); const [headingSet, setHeadingSet] = React.useState(false);
const [selectedMeta, setSelectedMeta] = React.useState({link: "hello", read_time: 2, }); const [selectedMeta, setSelectedMeta] = React.useState({link: "hello", read_time: 2, });
const [tocLines, setTocLines] = React.useState([]);
const [baseUrl, setBaseUrl] = React.useState(serverside === true ? "" : window.location.href) const [baseUrl, setBaseUrl] = React.useState(serverside === true ? "" : window.location.href)
function handleClick(event) { function handleClick(event) {
@@ -52,14 +58,14 @@ const Docs = (props) => {
position: "relative", position: "relative",
padding: 30, padding: 30,
paddingTop: 15, paddingTop: 15,
borderRadius: 5, height: "80vh",
marginTop: 15,
} }
const SideBar = { const SideBar = {
maxWidth: 250, maxWidth: 250,
flex: "1", flex: "1",
position: "fixed", position: "fixed",
marginTop: 35,
} }
const fetchDocList = () => { const fetchDocList = () => {
@@ -99,6 +105,54 @@ const Docs = (props) => {
if (responseJson.meta !== undefined) { if (responseJson.meta !== undefined) {
setSelectedMeta(responseJson.meta) setSelectedMeta(responseJson.meta)
} }
//console.log("TOC list: ", responseJson.reason)
if (responseJson.reason !== undefined && responseJson.reason !== null) {
const splitkey = responseJson.reason.split("\n")
var innerTocLines = []
var record = false
for (var key in splitkey) {
const line = splitkey[key]
//console.log("Line: ", line)
if (line.toLowerCase().includes("table of contents")) {
record = true
continue
}
if (record && line.length < 3) {
record = false
}
if (record) {
const parsedline = line.split("](")
if (parsedline.length > 1) {
parsedline[0] = parsedline[0].replaceAll("*", "")
parsedline[0] = parsedline[0].replaceAll("[", "")
parsedline[0] = parsedline[0].replaceAll("]", "")
parsedline[0] = parsedline[0].replaceAll("(", "")
parsedline[0] = parsedline[0].replaceAll(")", "")
parsedline[0] = parsedline[0].trim()
parsedline[1] = parsedline[1].replaceAll("*", "")
parsedline[1] = parsedline[1].replaceAll("[", "")
parsedline[1] = parsedline[1].replaceAll("]", "")
parsedline[1] = parsedline[1].replaceAll(")", "")
parsedline[1] = parsedline[1].replaceAll("(", "")
parsedline[1] = parsedline[1].trim()
console.log(parsedline[0], parsedline[1])
innerTocLines.push({
"text": parsedline[0],
"link": parsedline[1]
})
} else {
console.log("Bad line for parsing: ", line)
}
}
}
setTocLines(innerTocLines)
}
} else { } else {
setData("# Error\nThis page doesn't exist.") setData("# Error\nThis page doesn't exist.")
} }
@@ -230,7 +284,7 @@ const Docs = (props) => {
} }
const Heading = (props) => { const Heading = (props) => {
const element = React.createElement(`h${props.level}`, {style: {marginTop: 50}}, props.children) const element = React.createElement(`h${props.level}`, {style: {marginTop: props.level === 1 ? 20 : 50}}, props.children)
const [hover, setHover] = useState(false) const [hover, setHover] = useState(false)
var extraInfo = "" var extraInfo = ""
@@ -315,11 +369,31 @@ const Docs = (props) => {
const path = "/docs/"+item const path = "/docs/"+item
const newname = item.charAt(0).toUpperCase()+item.substring(1).split("_").join(" ").split("-").join(" ") const newname = item.charAt(0).toUpperCase()+item.substring(1).split("_").join(" ").split("-").join(" ")
const itemMatching = props.match.params.key.toLowerCase() === item.toLowerCase()
//const [tocLines, setTocLines] = React.useState([]);
return ( return (
<li key={index} style={{marginTop: 10,}}> <li key={index} style={{marginTop: 10,}}>
<Link key={index} style={hrefStyle} to={path} onClick={() => {fetchDocs(item)}}> <Link key={index} style={hrefStyle} to={path} onClick={() => {
<Typography style={{color: props.match.params.key.toLowerCase() === item.toLowerCase() ? "#f86a3e" : "inherit"}} variant="body1"><b>> {newname}</b></Typography> setTocLines([])
fetchDocs(item)
}}>
<Typography style={{color: itemMatching ? "#f86a3e" : "inherit"}} variant="body1"><b>> {newname}</b></Typography>
</Link> </Link>
{itemMatching && tocLines !== null && tocLines !== undefined && tocLines.length > 0 ?
<div style={{marginLeft: 13}}>
{tocLines.map((data, index) => {
console.log(data)
return (
<Link key={index} style={innerHrefStyle} to={data.link} onClick={() => {}}>
<Typography variant="body2" style={{cursor: "pointer"}}>
{data.text}
</Typography>
</Link>
)
})}
</div>
: null}
</li> </li>
) )
})} })}
@@ -422,7 +496,7 @@ const Docs = (props) => {
</div> </div>
return ( return (
<div> <div style={{}}>
{loadedCheck} {loadedCheck}
</div> </div>
) )