Last builds for 2.0

This commit is contained in:
Frikky
2025-03-04 19:37:44 +01:00
parent 63ce21fe60
commit 37c0baf02a
7 changed files with 298 additions and 57 deletions
+280 -49
View File
@@ -5,7 +5,7 @@ import theme from '../theme.jsx';
import ReactJson from "react-json-view-ssr";
import { isMobile } from "react-device-detect";
import { BrowserView, MobileView } from "react-device-detect";
import { useParams, useNavigate, Link } from "react-router-dom";
import { useParams, useNavigate, Link, useLocation } from "react-router-dom";
import { validateJson, GetIconInfo } from "../views/Workflows.jsx";
import remarkGfm from 'remark-gfm'
import { Context } from "../context/ContextApi.jsx";
@@ -30,7 +30,9 @@ import {
Edit as EditIcon,
KeyboardArrowRight as KeyboardArrowRightIcon,
ExpandMore as ExpandMoreIcon,
FileCopy as FileCopyIcon
FileCopy as FileCopyIcon,
ChevronLeft,
ChevronRight
} from "@mui/icons-material";
import { fontGrid } from "@mui/material/styles/cssUtils.js";
@@ -51,6 +53,7 @@ const dividerColor = "rgb(225, 228, 232)";
const hrefStyle = {
color: "rgba(255, 255, 255, 0.8)",
textDecoration: "none",
marginRight: window.location.pathname.includes("/articles/") ? "0.8em" : undefined,
};
@@ -152,11 +155,33 @@ export const OuterLink = (props) => {
}
export const Img = (props) => {
// Find parent container and check width
const isArticlePage = window.location.pathname.includes("/articles/");
var height = "auto"
var width = 750
var width = isArticlePage ? 1000 : 750
const docsImageStyle = {
border: "1px solid rgba(255,255,255,0.3)",
borderRadius: theme.palette?.borderRadius,
width: width,
maxWidth: width,
margin: "auto",
marginTop: 10,
marginBottom: 10
}
const articleImageStyle = {
borderRadius: theme.palette?.borderRadius,
minWidth: 350,
maxWidth: "100%",
textAlign: "center",
margin: "auto",
marginTop: 20,
marginBottom: 20,
}
if (props.height !== undefined && props.height !== null) {
height = props.height
}
@@ -167,7 +192,7 @@ export const Img = (props) => {
return(
<img
style={{border: "1px solid rgba(255,255,255,0.3)", borderRadius: theme.palette?.borderRadius, width: width, maxWidth: width, margin: "auto", marginTop: 10, marginBottom: 10, }}
style={isArticlePage ? articleImageStyle : docsImageStyle}
alt={props.alt}
src={props.src}
/>
@@ -251,8 +276,12 @@ export const CodeHandler = (props) => {
}
const Docs = (defaultprops) => {
const { globalUrl, selectedDoc, serverside, serverMobile, isLoggedIn, isLoaded } = defaultprops;
const { globalUrl, selectedDoc, serverside, serverMobile, isLoggedIn, isLoaded, userdata } = defaultprops;
console.log("\n\nSELECTED DOC\n", selectedDoc, "\n\n")
let navigate = useNavigate();
const location = useLocation();
// Quickfix for react router 5 -> 6
const params = useParams();
//var props = JSON.parse(JSON.stringify(defaultprops))
@@ -283,8 +312,16 @@ const Docs = (defaultprops) => {
serverside === true ? "" : window.location.href
);
const [hashRendered, setHashRendered] = React.useState(false)
const [sidebarOpen, setSidebarOpen] = useState(false);
const [activeSubItem, setActiveSubItem] = useState(false);
const headingElementsRef = useRef({})
var isArticlePage = window.location.pathname.includes("/articles/") || window.location.pathname === "/articles" ? true : false;
useEffect(() => {
fetchDocList();
setSidebarOpen(false);
}, [location]);
useEffect(() => {
//if (params["key"] === undefined) {
@@ -460,8 +497,13 @@ const Docs = (defaultprops) => {
}
const SidebarPaperStyle = {
backgroundColor: "rgb(26,26,26)",
backgroundColor: isArticlePage ? "transparent" : "rgb(26,26,26)",
border: isArticlePage ? "none" : undefined,
borderRadius: isArticlePage ? "none" : undefined,
boxShadow: isArticlePage ? "none" : undefined,
backgroundImage: "none",
width: isArticlePage ? "100%" : undefined,
height: isArticlePage ? "100%" : undefined,
overflowX: "hidden",
position: "relative",
paddingLeft: 15,
@@ -527,7 +569,7 @@ const Docs = (defaultprops) => {
backgroundColor: theme.palette.inputColor,
padding: 15,
borderRadius: theme.palette?.borderRadius,
marginBottom: 25,
marginBottom: isArticlePage ? 25 : 30,
display: "flex",
}}
>
@@ -620,7 +662,7 @@ const Docs = (defaultprops) => {
style={{
width: "90%",
marginTop: 60,
marginBottom: 20,
marginBottom: isArticlePage ? 40 : 20,
backgroundColor: theme.palette.inputColor,
}}
/>
@@ -630,7 +672,21 @@ const Docs = (defaultprops) => {
marginBlock: "0.85em", alignItems: "center"
}}>
{element}
<Link to={`#${id}`} style={{
<Link to={`#${id}`}
onClick={(e) => {
e.preventDefault(); // Prevent default navigation
document.getElementById(id)?.scrollIntoView({
behavior: 'smooth'
});
const url = `${window.location.origin}${window.location.pathname}#${id}`;
navigator.clipboard.writeText(url);
toast("Link copied to clipboard", {
position: "bottom-center",
autoClose: 2000,
});
}}
style={{
textDecoration: "none", color: "white",
paddingLeft: "0.3em", rotate: "-30deg",
paddingTop: "0.9em", display: props.level === 1 ? "none" : "block",
@@ -639,7 +695,7 @@ const Docs = (defaultprops) => {
</Link>
</div>
{extraInfo}
{extraInfo && userdata?.support}
</Typography>
)
}
@@ -647,21 +703,56 @@ const Docs = (defaultprops) => {
const SideBar = {
width: "17%",
borderRight: !isArticlePage ? "1px solid rgba(255,255,255,0.3)" : undefined,
minWidth: isArticlePage ? "250px" : "17%",
maxWidth: isArticlePage ? "250px" : "17%",
marginLeft: isArticlePage ? sidebarOpen ? 40 : 50 : undefined,
position: "sticky",
top: 50,
paddingTop: "0.25em",
minHeight: "95vh",
maxHeight: "95vh",
top: isArticlePage ? 120 : 50,
paddingTop: isArticlePage ? "0.65em" : "0.25em",
paddingRight: isArticlePage ? "1em" : undefined,
minHeight: isArticlePage ? "80vh" : "95vh",
maxHeight: isArticlePage ? "80vh" : "95vh",
overflowX: "hidden",
overflowY: "auto",
zIndex: 1000,
//borderRight: "1px solid rgba(255,255,255,0.3)",
backgroundColor: isArticlePage ? "#212121" : undefined,
borderRadius: isArticlePage ? theme.palette?.borderRadius : undefined,
transition: isArticlePage ? "width 0.3s ease, min-width 0.3s ease" : undefined,
};
const sideBarToggleButton = {
position: "absolute",
bottom: sidebarOpen ? 20 : "50%",
right: sidebarOpen ? 30 : 21,
zIndex: 1000,
backgroundColor: "#212121",
border: "1px solid rgba(255,255,255,0.3)",
borderRadius: "50%",
width: 40,
height: 40,
display: "flex",
alignItems: "center",
justifyContent: "center",
cursor: "pointer",
transition: "transform 0.3s ease",
"&:hover": {
backgroundColor: "#2c2c2c",
}
};
const collapsedSideBar = {
...SideBar,
width: "40px",
minWidth: "40px",
maxWidth: "40px",
overflow: "hidden",
};
const IndexBar = {
alignSelf: "flex-start",
position: "sticky",
top: 80,
top: 120,
overflowY: "auto",
minHeight: "93vh",
maxHeight: "93vh",
@@ -670,8 +761,9 @@ const Docs = (defaultprops) => {
overflow: "hidden",
}
const fetchDocList = () => {
fetch(`${globalUrl}/api/v1/docs`, {
const fetchDocList = (resetCache = false) => {
const url = isArticlePage ? `${globalUrl}/api/v1/articles?resetCache=${resetCache}` : `${globalUrl}/api/v1/docs`;
fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
@@ -692,7 +784,8 @@ const Docs = (defaultprops) => {
};
const fetchDocs = (docId) => {
fetch(`${globalUrl}/api/v1/docs/${docId}`, {
const url = isArticlePage ? `${globalUrl}/api/v1/articles/${docId}` : `${globalUrl}/api/v1/docs/${docId}`;
fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
@@ -706,18 +799,32 @@ const Docs = (defaultprops) => {
}
if (responseJson.success && responseJson.reason !== undefined) {
if(isArticlePage && window.location.pathname.includes("/articles/")) {
if (responseJson.reason !== undefined && responseJson.reason !== null && responseJson.reason.includes("404: Not Found")) {
setData("# Error\nThis page doesn't exist.");
toast("This page doesn't exist. Redirecting to the latest article...", {
position: "bottom-center",
autoClose: 2000,
});
setTimeout(() => {
navigate(`/articles/2.0_release`)
}, 2000)
return
}
}
// Find <img> tags and translate them into ![]() format
const imgRegex = /<img.*?src="(.*?)"/g;
const tocRegex = /^## Table of contents[\s\S]*?(?=^## )|^## Table of contents[\s\S]*$/gm;
const newdata = responseJson.reason.replace(imgRegex, '![]($1)').replace(tocRegex, "");
setData(newdata);
if (docId === undefined) {
document.title = "Shuffle automation documentation";
document.title = isArticlePage ? "Shuffle Articles introduction" : "Shuffle documentation";
} else {
document.title = "Shuffle " + docId.replace("_", " ") + " documentation";
document.title = "Shuffle " + docId.replace("_", " ") + (isArticlePage ? " articles" : " documentation");
}
if (responseJson.reason !== undefined && responseJson.reason !== null && responseJson.reason.includes("404: Not Found")) {
if (responseJson.reason !== undefined && responseJson.reason !== null && responseJson.reason.includes("404: Not Found") && !isArticlePage) {
navigate("/docs")
return
}
@@ -747,6 +854,11 @@ const Docs = (defaultprops) => {
.catch((error) => { });
};
const handleResetCache = () => {
fetchDocList(true);
toast("Cache has been reset");
}
if (firstrequest) {
setFirstrequest(false);
if (!serverside) {
@@ -769,8 +881,26 @@ const Docs = (defaultprops) => {
// return null
//}
//
if (props.match.params.key === undefined) {
if (props.match.params.key === undefined && isArticlePage) {
fetch(`${globalUrl}/api/v1/articles`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
})
.then((response) => response.json())
.then((responseJson) => {
if (responseJson.success && responseJson.list && responseJson.list.length > 0) {
// Navigate to the latest article
if (responseJson?.list[0]?.name) {
navigate(`/articles/${responseJson?.list[0].name}`);
}
}
})
.catch((error) => {
console.error("Error fetching articles:", error);
});
} else {
console.log("DOCID: ", props.match.params.key)
fetchDocs(props.match.params.key)
@@ -793,7 +923,7 @@ const Docs = (defaultprops) => {
maxWidth: "100%",
minWidth: "100%",
overflow: "hidden",
fontSize: isMobile ? "1.3rem" : "1rem",
fontSize: isMobile ? "1.3rem" : "1.1rem",
};
const alertNote = {
@@ -940,14 +1070,38 @@ const Docs = (defaultprops) => {
}
const activeHrefStyleToc2 = {
...hrefStyleToc2,
color: "#f86a3e",
};
const activeListItemStyle = {
backgroundColor: "rgba(248, 106, 62, 0.08)", // Slight orange tint
marginRight: window.location.pathname.includes("/articles/") ? "0.8em" : undefined,
borderLeft: "3px solid #f86a3e",
paddingLeft: "13px", // Compensate for the border
};
const toggleSidebar = () => {
setSidebarOpen(!sidebarOpen);
};
// PostDataBrowser Section
const postDataBrowser =
list === undefined || list === null ? null : (
<div style={Body}>
<div style={SideBar}>
<div style={!isArticlePage ? SideBar : (sidebarOpen ? SideBar : collapsedSideBar)}>
<Paper style={SidebarPaperStyle}>
<List style={{ listStyle: "none", paddingLeft: "0" }}>
<List style={{
listStyle: "none",
paddingLeft: "0",
display: isArticlePage ? sidebarOpen ? "block" : "none" : undefined,
opacity: isArticlePage ? sidebarOpen ? 1 : 0 : undefined,
transition: isArticlePage ? "opacity 0.3s ease" : undefined,
height: isArticlePage ? "90%" : undefined,
}}>
{list.map((data, index) => {
const item = data.name;
if (item === undefined) {
@@ -965,23 +1119,62 @@ const Docs = (defaultprops) => {
<ListItemButton
component={Link}
key={index}
style={hrefStyle}
style={{
...hrefStyle,
...(itemMatching ? activeListItemStyle : {}),
}}
to={path}
>
<ListItemText
style={{ color: itemMatching ? "#f86a3e" : "inherit" }}
variant="body1"
>
{newname}
</ListItemText>
style={{
color: itemMatching ? "#f86a3e" : "inherit",
flex: 1,
}}
primary={
<Typography
variant="body1"
style={{
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
}}
>
{newname}
</Typography>
}
/>
<KeyboardArrowRightIcon
style={{
color: itemMatching ? "#f86a3e" : "inherit",
fontSize: "1.1rem",
marginRight: "-6px",
}}
/>
</ListItemButton>
</li>
);
})}
</List>
{
isArticlePage && (
<IconButton
onClick={toggleSidebar}
style={sideBarToggleButton}
>
{sidebarOpen ? <ChevronLeft /> : <ChevronRight />}
</IconButton>
)
}
</Paper>
</div>
<div style={{ width: "60%", margin: "30px 0px 30px 30px", overflow: "hidden", paddingRight: 50, paddingLeft: 40 }}>
<div style={{
width: isArticlePage ? sidebarOpen ? "60%" : "70%" : "60%",
margin: isArticlePage ? sidebarOpen ? "0 0px 30px 30px" : "0 0px 30px 60px" : "30px 0px 30px 30px",
overflow: "hidden",
paddingRight: 50,
paddingLeft: 40,
transition: "width 0.3s ease, margin 0.3s ease",
}}>
{props.match.params.key === undefined ?
mainpageInfo
:
@@ -1003,12 +1196,26 @@ const Docs = (defaultprops) => {
}
</div>
<div style={IndexBar}>
{userdata?.support && isArticlePage && (
<Button
variant="contained"
color="secondary"
onClick={handleResetCache}
style={{marginBottom: "15px"}}
>
Reset Cache
</Button>
)}
{tocLines.length > 0 ?
(
<h4 style={{ fontWeight: 600, margin: 0, fontSize: "16px", marginBottom: "8px" }}>Table of Content</h4>
<h4 style={{ fontWeight: 600, margin: 0, fontSize: "16px", marginBottom: "8px" }}>Table Of Content</h4>
) : null}
<nav>
<div
style={{
overflowY: "auto",
maxHeight: "90vh",
}}>
{tocLines.map((data, index) => {
return (
<div className="toc"
@@ -1019,12 +1226,15 @@ const Docs = (defaultprops) => {
style={{
fontSize: "14px",
fontWeight: 400,
padding: "4px 8px 4px 8px",
padding: isArticlePage ? "4px 0" : "4px 8px 4px 8px",
paddingLeft: isArticlePage ? "0" : "8px",
paddingRight: isArticlePage ? "0" : "8px",
lineHeight: "20px",
color: activeId === data.id ? "#f86a3e" : "rgba(255,255,255,0.6)",
color: activeId === data.id ? "#f86a3e" : "inherit",
}}
onClick={(e) => {
handleCollapse(index)
setActiveId(data.id)
}}
>
{data.title}
@@ -1041,8 +1251,12 @@ const Docs = (defaultprops) => {
return (
<ListItemButton
key={i}
style={hrefStyleToc2}
style={activeSubItem === d.id ? activeHrefStyleToc2 : hrefStyleToc2}
href={`#${d.id}`}
onClick={(e) => {
// e.preventDefault()
setActiveSubItem(d.id)
}}
>
{d.title}
</ListItemButton>
@@ -1055,7 +1269,7 @@ const Docs = (defaultprops) => {
)
})}
</nav>
</div>
</div >
</div >
@@ -1083,7 +1297,7 @@ const Docs = (defaultprops) => {
color="primary"
onClick={handleClick}
>
<div style={{ color: "white" }}>More docs</div>
<div style={{ color: "white" }}>More {isArticlePage ? "articles" : "docs"}</div>
</Button>
<Menu
id="simple-menu"
@@ -1099,7 +1313,7 @@ const Docs = (defaultprops) => {
return null;
}
const path = "/docs/" + item;
const path = isArticlePage ? "/articles/" + item : "/docs/" + item;
const newname =
item.charAt(0).toUpperCase() +
item.substring(1).split("_").join(" ").split("-").join(" ");
@@ -1108,7 +1322,8 @@ const Docs = (defaultprops) => {
key={index}
style={{ color: "white" }}
onClick={() => {
window.location.pathname = path;
navigate(path)
handleClose()
}}
>
{newname}
@@ -1140,8 +1355,22 @@ const Docs = (defaultprops) => {
<MenuItem
key={index}
style={{ color: "white" }}
component={Link}
to={`#${data.id}`}
onClick={() => {
console.log(`Scrolling to: ${data.id}`);
setTimeout(() => {
const element = document.getElementById(data?.id);
if (element) {
element.scrollIntoView({ behavior: 'smooth' });
} else {
console.error(`Element with id ${data.id} not found.`);
}
}, 100); // Delay to ensure the content is loaded
handleCloseToc();
}}
>
<a href={`#${data.id}`} style={hrefStyle}>{data.title}</a>
{data.title}
</MenuItem>
)
})}
@@ -1178,7 +1407,7 @@ const Docs = (defaultprops) => {
color="primary"
onClick={handleClick}
>
<div style={{ color: "white" }}>More docs</div>
<div style={{ color: "white" }}>More {isArticlePage ? "articles" : "docs"}</div>
</Button>
</div>
);
@@ -1198,7 +1427,7 @@ export default Docs;
const DocsContent = memo(({postDataBrowser, postDataMobile}) => {
return(
<div>
<div style={{fontFamily: theme?.palette?.fontFamily}}>
<BrowserView>{postDataBrowser}</BrowserView>
<MobileView>{postDataMobile}</MobileView>
</div>
@@ -1210,12 +1439,14 @@ const DocsWrapper = memo(({isLoggedIn, isLoaded, children })=>{
return (
<div style={{
marginTop: window.location.pathname.includes("/articles/") ? 50 : undefined,
paddingBottom: 50,
minHeight: 1000, zIndex: 1,
maxWidth: Math.min(!(isLoggedIn && isLoaded) ? 1920 : leftSideBarOpenByClick ? windowWidth - 300 : windowWidth - 200, 1920),
minWidth: isMobile ? null : (isLoggedIn && isLoaded) ? leftSideBarOpenByClick ? 800 : 900 : null, margin: "auto",
position: (isLoggedIn && isLoaded) && leftSideBarOpenByClick ? "relative" : "static",
left: (isLoggedIn && isLoaded) && leftSideBarOpenByClick ? 120 : (isLoggedIn && isLoaded) && !leftSideBarOpenByClick ? 80 : 0,
marginLeft: windowWidth < 1920 ? leftSideBarOpenByClick && (isLoggedIn && isLoaded) ? 90 : (isLoggedIn && isLoaded) && !leftSideBarOpenByClick ? 80 : 0 : "auto", width: "100%",
marginLeft: windowWidth < 1920 ? leftSideBarOpenByClick && (isLoggedIn && isLoaded) ? window.location.pathname.includes("/articles/") ? 0 : 90 : (isLoggedIn && isLoaded) && !leftSideBarOpenByClick ? 80 : 0 : "auto", width: "100%",
transition: "left 0.3s ease-in-out, min-width 0.3s ease-in-out, max-width 0.3s ease-in-out, position 0.3s ease-in-out, margin 0.3s ease-in-out, margin-left 0.3s ease"
}}>
{children}
+8
View File
@@ -1758,9 +1758,17 @@ const Workflows2 = (props) => {
let exportFileDefaultName = data.name + ".json";
data["owner"] = "";
data["updated_by"] = "";
data["org"] = [];
data["org_id"] = "";
data["execution_org"] = {};
data["created"] = 0
data["due_date"] = 0
data["edited"] = 0
data["validation"] = {};
data["suborg_distribution"] = []
data["parentorg_workflow"] = ""
// These are backwards.. True = saved before. Very confuse.
data["previously_saved"] = false;