From 37c0baf02a2984db5178b52090a5e5ce7b94b838 Mon Sep 17 00:00:00 2001 From: Frikky Date: Tue, 4 Mar 2025 19:37:44 +0100 Subject: [PATCH] Last builds for 2.0 --- backend/go-app/go.mod | 2 +- frontend/src/components/Navbar.jsx | 10 +- frontend/src/components/RuntimeDebugger.jsx | 2 +- frontend/src/views/Docs.jsx | 329 +++++++++++++++++--- frontend/src/views/Workflows2.jsx | 8 + functions/onprem/orborus/go.mod | 2 +- functions/onprem/worker/go.mod | 2 +- 7 files changed, 298 insertions(+), 57 deletions(-) diff --git a/backend/go-app/go.mod b/backend/go-app/go.mod index 9864b1dc..8af42425 100644 --- a/backend/go-app/go.mod +++ b/backend/go-app/go.mod @@ -18,7 +18,7 @@ require ( github.com/gorilla/mux v1.8.1 github.com/h2non/filetype v1.1.3 github.com/satori/go.uuid v1.2.0 - github.com/shuffle/shuffle-shared v0.8.6 + github.com/shuffle/shuffle-shared v0.8.7 golang.org/x/crypto v0.32.0 google.golang.org/api v0.176.1 google.golang.org/grpc v1.68.1 diff --git a/frontend/src/components/Navbar.jsx b/frontend/src/components/Navbar.jsx index fd808894..ebee1db5 100644 --- a/frontend/src/components/Navbar.jsx +++ b/frontend/src/components/Navbar.jsx @@ -48,7 +48,7 @@ const menuData = { description: "The most versatile automation engine with focus on security.", icon: "images/logos/orange_logo.svg", - path: "/docs", + path: "/docs/about", gaData: { category: "navbar", action: "products_click", @@ -150,7 +150,7 @@ const menuData = { title: "Documentation", icon: "/images/icons/docs.svg", hoverIcon: "/images/icons/docs_hover.svg", - link: "/docs", + link: "/docs/about", gaData: { category: "navbar", action: "resources_click", @@ -1516,7 +1516,7 @@ const Navbar = (props) => {
{/* Shuffle 1.4.0 is out! Read more about  */} - Shuffle 2.0.0 is out now! + Shuffle 2.0.0 is out now!  { ReactGA.event({ @@ -1528,7 +1528,7 @@ const Navbar = (props) => { navigate("/articles/2.0_release") }} style={{ cursor: "pointer", textDecoration: "none", fontWeight: 600, color: "rgba(255,255,255,0.9)" }}> -  Read about it here. + Read about it here. @@ -1701,6 +1701,7 @@ const Navbar = (props) => { { { imageSource = "/images/no_image.png" } }else { - if (userdata.active_org.image?.length > 0){ + if (userdata?.active_org.image?.length > 0){ imageSource = userdata?.active_org?.image }else { imageSource = "/images/no_image.png" diff --git a/frontend/src/views/Docs.jsx b/frontend/src/views/Docs.jsx index 836ada35..7a9c371e 100755 --- a/frontend/src/views/Docs.jsx +++ b/frontend/src/views/Docs.jsx @@ -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( {props.alt} @@ -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} - { + 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) => {
- {extraInfo} + {extraInfo && userdata?.support} ) } @@ -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 tags and translate them into ![]() format const imgRegex = / { .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 : (
-
+
- + {list.map((data, index) => { const item = data.name; if (item === undefined) { @@ -965,23 +1119,62 @@ const Docs = (defaultprops) => { - {newname} - + style={{ + color: itemMatching ? "#f86a3e" : "inherit", + flex: 1, + }} + primary={ + + {newname} + + } + /> + ); })} + { + isArticlePage && ( + + {sidebarOpen ? : } + + ) + }
-
+
{props.match.params.key === undefined ? mainpageInfo : @@ -1003,12 +1196,26 @@ const Docs = (defaultprops) => { }
+ {userdata?.support && isArticlePage && ( + + )} {tocLines.length > 0 ? ( -

Table of Content

+

Table Of Content

) : null} - +
@@ -1083,7 +1297,7 @@ const Docs = (defaultprops) => { color="primary" onClick={handleClick} > -
More docs
+
More {isArticlePage ? "articles" : "docs"}
{ 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) => { { + 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(); + }} > - {data.title} + {data.title} ) })} @@ -1178,7 +1407,7 @@ const Docs = (defaultprops) => { color="primary" onClick={handleClick} > -
More docs
+
More {isArticlePage ? "articles" : "docs"}
); @@ -1198,7 +1427,7 @@ export default Docs; const DocsContent = memo(({postDataBrowser, postDataMobile}) => { return( -
+
{postDataBrowser} {postDataMobile}
@@ -1210,12 +1439,14 @@ const DocsWrapper = memo(({isLoggedIn, isLoaded, children })=>{ return (
{children} diff --git a/frontend/src/views/Workflows2.jsx b/frontend/src/views/Workflows2.jsx index 33f8618f..0b079407 100644 --- a/frontend/src/views/Workflows2.jsx +++ b/frontend/src/views/Workflows2.jsx @@ -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; diff --git a/functions/onprem/orborus/go.mod b/functions/onprem/orborus/go.mod index 6b8018a5..7909c2ee 100644 --- a/functions/onprem/orborus/go.mod +++ b/functions/onprem/orborus/go.mod @@ -9,7 +9,7 @@ require ( github.com/docker/docker v27.5.0+incompatible github.com/docker/go-connections v0.5.0 github.com/satori/go.uuid v1.2.0 - github.com/shuffle/shuffle-shared v0.8.6 + github.com/shuffle/shuffle-shared v0.8.7 k8s.io/api v0.30.2 k8s.io/apimachinery v0.30.2 ) diff --git a/functions/onprem/worker/go.mod b/functions/onprem/worker/go.mod index 01cad7bf..5b8cbd22 100644 --- a/functions/onprem/worker/go.mod +++ b/functions/onprem/worker/go.mod @@ -8,7 +8,7 @@ require ( github.com/docker/docker v27.5.0+incompatible github.com/gorilla/mux v1.8.1 github.com/satori/go.uuid v1.2.0 - github.com/shuffle/shuffle-shared v0.8.6 + github.com/shuffle/shuffle-shared v0.8.7 k8s.io/api v0.30.2 k8s.io/apimachinery v0.30.2 k8s.io/client-go v0.30.2