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", 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)
}
+1
View File
@@ -108,6 +108,7 @@ const App = (message, props) => {
<div style={{ backgroundColor: "#1F2023", color: "rgba(255, 255, 255, 0.65)", minHeight: "100vh" }}>
<ScrollToTop setCurpath={setCurpath} />
<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="/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} />} />
+60 -9
View File
@@ -5,8 +5,8 @@ import {Link} from 'react-router-dom';
import { useTheme } from '@material-ui/core/styles';
import { 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 { Badge, Typography, Paper, Tooltip, List, Avatar, Menu, ListItem, MenuItem, Select, Button, IconButton, Grid } from '@material-ui/core';
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";
const hoverColor = "#f85a3e"
@@ -148,12 +148,60 @@ const Header = props => {
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
const avatarMenu =
<span>
<IconButton color="primary" style={{marginRight: 15, }} aria-controls="simple-menu" aria-haspopup="true" onClick={(event) => {
<span style={{zIndex: 10001}}>
<IconButton color="primary" style={{zIndex: 10001, marginRight: 15, }} aria-controls="simple-menu" aria-haspopup="true" onClick={(event) => {
setAnchorEl(event.currentTarget);
}}>
<Avatar style={{height: 35, width: 35,}} alt="Your username here" src="" />
@@ -163,6 +211,7 @@ const Header = props => {
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
style={{zIndex: 10002}}
onClose={() => {
handleClose()
}}
@@ -188,8 +237,9 @@ const Header = props => {
// Handle top bar or something
const logoCheck = !homePage ? null : null
//<div style={{position: "fixed", top: 0, left: 0, display: "flex"}}>
const loginTextBrowser = !isLoggedIn ?
<div style={{display: "flex"}}>
<div style={{display: "flex"}}>
<List style={{display: "flex", flexDirect: "row"}} component="nav">
<ListItem style={{textAlign: "center", marginLeft: "0px"}}>
<Link to ="/docs/about" style={hrefStyle}>
@@ -265,6 +315,7 @@ const Header = props => {
</div>
<div style={{flex: "10", display: "flex", flexDirection: "row-reverse"}}>
{avatarMenu}
{notificationMenu}
{userdata === undefined || userdata.admin === undefined || userdata.admin === null || !userdata.admin ? null :
<Link to="/admin" style={hrefStyle}>
<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)"}}/>
const loadedCheck =
<div style={{minHeight: 60}}>
<div style={{minHeight: 60, }}>
<BrowserView>
{loginTextBrowser}
</BrowserView>
@@ -386,10 +437,10 @@ const Header = props => {
</div>
// <div style={{backgroundImage: "linear-gradient(-90deg,#342f78 0,#29255e 50%,#1b1947 100%"}}>
return (
<div>
{loadedCheck}
<div style={{width: "100%", position: "fixed", minHeight: 60, top: 0, zIndex: 10000, backgroundColor: "inherit",}}>
{loadedCheck}
</div>
)
)
}
export default Header;
+1 -1
View File
@@ -2936,7 +2936,7 @@ const Admin = (props) => {
const iconStyle = {marginRight: 10}
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}>
<Tabs
value={curTab}
+1 -1
View File
@@ -8671,7 +8671,7 @@ const AngularWorkflow = (props) => {
minZoom={0.35}
maxZoom={2.00}
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}
boxSelectionEnabled={true}
autounselectify={false}
+10 -7
View File
@@ -129,6 +129,7 @@ const Apps = (props) => {
const upload = React.useRef(null);
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" ? true : false
const borderRadius = 3
const viewWidth = 590
const { start, stop } = useInterval({
duration: 5000,
@@ -177,6 +178,7 @@ const Apps = (props) => {
color: "#ffffff",
width: "100%",
display: "flex",
margin: "auto",
}
const paperAppStyle = {
@@ -473,13 +475,14 @@ const Apps = (props) => {
const dividerColor = "rgb(225, 228, 232)"
const uploadViewPaperStyle = {
minWidth: 662.5,
maxWidth: 662.5,
minWidth: viewWidth,
maxWidth: viewWidth,
color: "white",
borderRadius: 5,
backgroundColor: surfaceColor,
display: "flex",
marginBottom: 10,
overflow: "hidden",
}
const UploadView = () => {
@@ -761,7 +764,7 @@ const Apps = (props) => {
{/*<p><b>Owner:</b> {selectedApp.owner}</p>*/}
{selectedApp.privateId !== undefined && selectedApp.privateId.length > 0 ? <p><b>PrivateID:</b> {selectedApp.privateId}</p> : null}
<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}
<div style={{marginTop: 15, marginBottom: 15}}>
<b>Actions</b>
@@ -944,9 +947,9 @@ const Apps = (props) => {
}, [appValidation, isDropzone]);
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={{flex: 1, }}>
<div style={{flex: 1, maxWidth: viewWidth, marginRight: 10,}}>
<Breadcrumbs aria-label="breadcrumb" separator="" style={{color: "white",}}>
<Link to="/apps" style={{textDecoration: "none", color: "inherit",}}>
<Typography variant="h6" style={{color: "rgba(255,255,255,0.5)"}}>
@@ -963,9 +966,9 @@ const Apps = (props) => {
: null}
</Breadcrumbs>
<div style={{marginTop: 15}} />
<UploadView/>
<UploadView />
</div>
<div style={{flex: 1, marginLeft: 10, marginRight: 10, }}>
<div style={{flex: 1, marginLeft: 10, maxWidth: viewWidth, }}>
<div style={{display: "flex",}}>
<div style={{flex: 1, marginBottom: 15, }}>
<Typography variant="h6">
+81 -7
View File
@@ -13,7 +13,7 @@ const Body = {
minWidth: '768px',
margin: 'auto',
display: "flex",
heigth: "100%",
height: "100%",
color: "white",
//textAlign: "center",
};
@@ -24,6 +24,11 @@ const hrefStyle = {
textDecoration: "none"
}
const innerHrefStyle = {
color: "rgba(255, 255, 255, 0.75)",
textDecoration: "none"
}
const Docs = (props) => {
const { globalUrl, selectedDoc, serverside, isMobile, } = props;
@@ -36,6 +41,7 @@ const Docs = (props) => {
const [anchorEl, setAnchorEl] = React.useState(null);
const [headingSet, setHeadingSet] = React.useState(false);
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)
function handleClick(event) {
@@ -52,14 +58,14 @@ const Docs = (props) => {
position: "relative",
padding: 30,
paddingTop: 15,
borderRadius: 5,
height: "80vh",
marginTop: 15,
}
const SideBar = {
maxWidth: 250,
flex: "1",
position: "fixed",
marginTop: 35,
}
const fetchDocList = () => {
@@ -99,6 +105,54 @@ const Docs = (props) => {
if (responseJson.meta !== undefined) {
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 {
setData("# Error\nThis page doesn't exist.")
}
@@ -230,7 +284,7 @@ const Docs = (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)
var extraInfo = ""
@@ -315,11 +369,31 @@ const Docs = (props) => {
const path = "/docs/"+item
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 (
<li key={index} style={{marginTop: 10,}}>
<Link key={index} style={hrefStyle} to={path} onClick={() => {fetchDocs(item)}}>
<Typography style={{color: props.match.params.key.toLowerCase() === item.toLowerCase() ? "#f86a3e" : "inherit"}} variant="body1"><b>> {newname}</b></Typography>
<Link key={index} style={hrefStyle} to={path} onClick={() => {
setTocLines([])
fetchDocs(item)
}}>
<Typography style={{color: itemMatching ? "#f86a3e" : "inherit"}} variant="body1"><b>> {newname}</b></Typography>
</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>
)
})}
@@ -422,7 +496,7 @@ const Docs = (props) => {
</div>
return (
<div>
<div style={{}}>
{loadedCheck}
</div>
)