diff --git a/backend/go-app/main.go b/backend/go-app/main.go index 880f09c2..e337dfbc 100644 --- a/backend/go-app/main.go +++ b/backend/go-app/main.go @@ -1021,6 +1021,7 @@ func handleInfo(resp http.ResponseWriter, request *http.Request) { } } + tutorialsFinished := []string{} returnValue := shuffle.HandleInfo{ Success: true, Username: userInfo.Username, @@ -1035,7 +1036,8 @@ func handleInfo(resp http.ResponseWriter, request *http.Request) { Expiration: expiration.Unix(), }, }, - EthInfo: userInfo.EthInfo, + EthInfo: userInfo.EthInfo, + Tutorials: tutorialsFinished, } returnData, err := json.Marshal(returnValue) diff --git a/frontend/package.json b/frontend/package.json index 93f03993..5766f14f 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "shuffler", "homepage": "https://shuffler.io", - "version": "0.9.25", + "version": "0.9.50", "private": true, "dependencies": { "@babel/core": "^7.15.8", @@ -61,8 +61,8 @@ "react-markdown": "^4.2.2", "react-markdown-github": "^3.3.1", "react-powerhooks": "0.0.7", - "react-router": "^4.3.1", - "react-router-dom": "^4.3.1", + "react-router": "6.2.1", + "react-router-dom": "6.2.1", "react-scripts": "^4.0.1", "react-shepherd": "^3.3.6", "reactstrap": "^7.1.0", diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 3fbc4de1..6a8cd9ec 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,14 +1,12 @@ import React, { useState, useEffect } from "react"; -import { Route } from "react-router"; -import { BrowserRouter } from "react-router-dom"; +//import { Route, Routes } from "react-router"; +import { Route, Routes, BrowserRouter } from "react-router-dom"; import { CookiesProvider } from "react-cookie"; import { removeCookies, useCookies } from "react-cookie"; -import EditSchedule from "./views/EditSchedule"; -import Schedules from "./views/Schedules"; -import Webhooks from "./views/Webhooks"; import Workflows from "./views/Workflows"; +import GettingStarted from "./views/GettingStarted"; import EditWebhook from "./views/EditWebhook"; import AngularWorkflow from "./views/AngularWorkflow"; @@ -52,6 +50,7 @@ if (window.location.port === "3000") { } const App = (message, props) => { + const [userdata, setUserData] = useState({}); const [notifications, setNotifications] = useState([]) const [cookies, setCookie, removeCookie] = useCookies([]) @@ -271,11 +270,13 @@ const App = (message, props) => { window.location.pathname === "/home" || window.location.pathname === "/features" ? (
- } - /> + + } + /> +
) : (
{ {...props} />
- ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - {userdata.id !== undefined ? ( - ( - - )} - /> - ) : null} - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - } - /> - ( - + + } + /> + + } + /> + + } + /> + {userdata.id !== undefined ? ( + + } + /> + ) : null} + + } + /> + - )} - /> - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - } - /> - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - { - window.location.pathname = "/docs/about"; - }} - /> - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> + isLoaded={isLoaded} + isLoggedIn={isLoggedIn} + globalUrl={globalUrl} + {...props} + /> + } + /> + + } + /> + + } + /> + + } + /> + + } + /> + + } + /> + + } + /> + + } + /> + + } + /> + + } + /> + + } + /> + + } + /> + + } + /> + + } + /> + + } + /> +
); diff --git a/frontend/src/components/Header.js b/frontend/src/components/Header.js index 1abddaea..e8520fe9 100644 --- a/frontend/src/components/Header.js +++ b/frontend/src/components/Header.js @@ -29,7 +29,12 @@ import { Polymer as PolymerIcon, Apps as AppsIcon, Description as DescriptionIcon, + HelpOutline as HelpOutlineIcon, } from "@material-ui/icons"; + +import { + Analytics as AnalyticsIcon, +} from "@mui/icons-material"; //import LogoutIcon from '@mui/icons-material/Logout'; import { useAlert } from "react-alert"; @@ -440,6 +445,26 @@ const Header = (props) => { handleClose(); }} > + { + event.preventDefault(); + handleClose(); + }} + > + + About + + + { + event.preventDefault(); + handleClose(); + }} + > + + Get Started + + { event.preventDefault(); @@ -447,7 +472,7 @@ const Header = (props) => { }} > - Settings + Settings { handleClickLogout(); }} > -  Logout +  Logout diff --git a/frontend/src/components/ScrollToTop.jsx b/frontend/src/components/ScrollToTop.jsx index 00b8d09c..f166cf1f 100644 --- a/frontend/src/components/ScrollToTop.jsx +++ b/frontend/src/components/ScrollToTop.jsx @@ -1,25 +1,30 @@ import { useEffect } from "react"; -import { withRouter } from "react-router-dom"; +//import { withRouter } from "react-router-dom"; +import { useLocation } from "react-router-dom"; function ScrollToTop({ getUserNotifications, setCurpath, history }) { - useEffect(() => { - const unlisten = history.listen(() => { - window.scroll({ - top: 0, - left: 0, - behavior: "smooth", - }); + let location = useLocation(); - setCurpath(window.location.pathname); - getUserNotifications(); - }); - return () => { - unlisten(); - }; - }, []); + useEffect(() => { + //const unlisten = history.listen(() => { + window.scroll({ + top: 0, + left: 0, + behavior: "smooth", + }); + + setCurpath(window.location.pathname); + getUserNotifications(); + //}); + //return () => { + // unlisten(); + //}; + }, [location]); return null; } // https://stackoverflow.com/questions/36904185/react-router-scroll-to-top-on-every-transition -export default withRouter(ScrollToTop); +//export default withRouter(ScrollToTop); +// https://v5.reactrouter.com/web/api/Hooks/uselocation +export default ScrollToTop; diff --git a/frontend/src/views/Admin.jsx b/frontend/src/views/Admin.jsx index 03f3a72d..f1c130e8 100644 --- a/frontend/src/views/Admin.jsx +++ b/frontend/src/views/Admin.jsx @@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react"; import { makeStyles } from "@material-ui/styles"; import { useTheme } from "@material-ui/core/styles"; -import { Link } from "react-router-dom"; +import { useNavigate, Link } from "react-router-dom"; import { FormControl, @@ -92,6 +92,8 @@ const Admin = (props) => { var to_be_copied = ""; const theme = useTheme(); const classes = useStyles(); + let navigate = useNavigate(); + const [firstRequest, setFirstRequest] = React.useState(true); const [orgRequest, setOrgRequest] = React.useState(true); const [modalUser, setModalUser] = React.useState({}); @@ -1395,7 +1397,9 @@ const Admin = (props) => { console.log("Should get apps for categories."); } - props.history.push(`/admin?tab=${views[newValue]}`) + console.log("PROPS: ", props) + + navigate(`/admin?tab=${views[newValue]}`) setModalUser({}); }; diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index e40f91ad..182e9cf4 100644 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -3,8 +3,8 @@ import { useInterval } from "react-powerhooks"; import { makeStyles, useTheme } from "@material-ui/core/styles"; import { v4 as uuidv4 } from "uuid"; -import { Link } from "react-router-dom"; -import { Prompt } from "react-router"; +import { Link, useParams } from "react-router-dom"; +// import { Prompt } from "react-router"; // FIXME import { useBeforeunload } from "react-beforeunload"; import ReactJson from "react-json-view"; import NestedMenuItem from "material-ui-nested-menu-item"; @@ -210,10 +210,16 @@ const svgSize = 24; //const referenceUrl = "https://shuffler.io/functions/webhooks/" //const referenceUrl = window.location.origin+"/api/v1/hooks/" -const AngularWorkflow = (props) => { - const { globalUrl, isLoggedIn, isLoaded, userdata } = props; +const AngularWorkflow = (defaultprops) => { + const { globalUrl, isLoggedIn, isLoaded, userdata } = defaultprops; const referenceUrl = globalUrl + "/api/v1/hooks/"; const alert = useAlert() + + const params = useParams(); + var props = JSON.parse(JSON.stringify(defaultprops)) + props.match = {} + props.match.params = params + const green = "#86c142"; const yellow = "#FECC00"; //const theme = useTheme(); @@ -12636,7 +12642,9 @@ const AngularWorkflow = (props) => { return (
- + {/* Removed due to missing react router features + + */} {loadedCheck}
); diff --git a/frontend/src/views/AppCreator.jsx b/frontend/src/views/AppCreator.jsx index 41bc2563..c211572f 100644 --- a/frontend/src/views/AppCreator.jsx +++ b/frontend/src/views/AppCreator.jsx @@ -37,7 +37,7 @@ import { } from "@material-ui/icons"; import { v4 as uuidv4 } from "uuid"; -import { Link } from "react-router-dom"; +import { Link, useParams } from "react-router-dom"; import YAML from "yaml"; import ChipInput from "material-ui-chip-input"; import { useAlert } from "react-alert"; @@ -220,12 +220,17 @@ const parseCurl = (s) => { }; // Should be different if logged in :| -const AppCreator = (props) => { - const { globalUrl, isLoaded } = props; +const AppCreator = (defaultprops) => { + const { globalUrl, isLoaded } = defaultprops; const classes = useStyles(); const alert = useAlert(); const theme = useTheme(); + const params = useParams(); + var props = JSON.parse(JSON.stringify(defaultprops)) + props.match = {} + props.match.params = params + var upload = ""; const increaseAmount = 50; const actionNonBodyRequest = ["GET", "HEAD", "DELETE", "CONNECT"]; diff --git a/frontend/src/views/Docs.jsx b/frontend/src/views/Docs.jsx index f05e96c2..91ac42da 100644 --- a/frontend/src/views/Docs.jsx +++ b/frontend/src/views/Docs.jsx @@ -1,9 +1,9 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { useTheme } from "@material-ui/core/styles"; import ReactMarkdown from "react-markdown"; import { BrowserView, MobileView } from "react-device-detect"; -import { Link } from "react-router-dom"; +import { useParams, useNavigate, Link } from "react-router-dom"; import { Tooltip, @@ -39,10 +39,26 @@ const innerHrefStyle = { textDecoration: "none", }; -const Docs = (props) => { - const { globalUrl, selectedDoc, serverside, isMobile } = props; +const Docs = (defaultprops) => { + const { globalUrl, selectedDoc, serverside, isMobile } = defaultprops; + let navigate = useNavigate(); const theme = useTheme(); + + // Quickfix for react router 5 -> 6 + const params = useParams(); + var props = JSON.parse(JSON.stringify(defaultprops)) + props.match = {} + props.match.params = params + + useEffect(() => { + if (params["key"] === undefined) { + navigate("/docs/about") + return + } + }, []) + //console.log("PARAMS: ", params) + const [mobile, setMobile] = useState(isMobile === true ? true : false); const [data, setData] = useState(""); const [firstrequest, setFirstrequest] = useState(true); @@ -201,7 +217,15 @@ const Docs = (props) => { } else { if (!serverside) { fetchDocList(); - fetchDocs(props.match.params.key); + + console.log("PROPS: ", props) + //const propkey = props.match.params.key + //if (propkey === undefined) { + // navigate("/docs/about") + // return null + //} + + fetchDocs(props.match.params.key) } } } @@ -410,6 +434,7 @@ const Docs = (props) => { {selectedMeta.contributors.slice(0, 7).map((data, index) => { return ( { - const { globalUrl, isLoggedIn, isLoaded } = props; +const Workflows = (defaultprops) => { + const { globalUrl, isLoggedIn, isLoaded } = defaultprops; + const theme = useTheme(); + const params = useParams(); + var props = JSON.parse(JSON.stringify(defaultprops)) + props.match = {} + props.match.params = params + const [curView, setCurView] = useState(0); const [firstrequest, setFirstrequest] = useState(true); const [selectedItems, setSelectedItems] = useState([]); diff --git a/frontend/src/views/RegisterLink.jsx b/frontend/src/views/RegisterLink.jsx index 7fde36e1..1e4827c6 100644 --- a/frontend/src/views/RegisterLink.jsx +++ b/frontend/src/views/RegisterLink.jsx @@ -1,4 +1,5 @@ import React, { useState, useEffect } from "react"; +import { useParams } from "react-router-dom"; import Paper from "@material-ui/core/Paper"; @@ -21,8 +22,13 @@ const bodyDivStyle = { // FIXME - add fetch for data fields // FIXME - remove tmpdata // FIXME: Use isLoggedIn :) -const Settings = (props) => { - const { globalUrl, isLoaded, surfaceColor } = props; +const Settings = (defaultprops) => { + const { globalUrl, isLoaded, surfaceColor } = defaultprops; + + const params = useParams(); + var props = JSON.parse(JSON.stringify(defaultprops)) + props.match = {} + props.match.params = params const [firstRequest, setFirstRequest] = useState(true); const boxStyle = { diff --git a/frontend/src/views/Workflows.jsx b/frontend/src/views/Workflows.jsx index e9ec15d0..4cf46c90 100644 --- a/frontend/src/views/Workflows.jsx +++ b/frontend/src/views/Workflows.jsx @@ -1,6 +1,8 @@ import React, { useEffect, useContext } from "react"; import { makeStyles } from "@material-ui/core/styles"; import { useTheme } from "@material-ui/core/styles"; +import { Navigate } from "react-router-dom"; +//import { Redirect } from "react-router-dom"; import SecurityFramework from '../components/SecurityFramework.jsx'; import { ShepherdTour, ShepherdTourContext } from 'react-shepherd' @@ -2536,10 +2538,17 @@ const Workflows = (props) => { ); } - //import { ShepherdTour, ShepherdTourContext } from 'react-shepherd' const WorkflowView = () => { - /* if (workflows.length === 0) { + /* + console.log("USER: ", userdata) + console.log("PROPS: ", props) + if (userdata.tutorials !== undefined && userdata.tutorials !== null && !userdata.tutorials.includes("getting-started")) { + //return ; + return ; + } + */ + return (
@@ -2585,9 +2594,9 @@ const Workflows = (props) => {
- ); + ) + } - */ var workflowDelay = -150 var appDelay = -75 diff --git a/functions/onprem/orborus/orborus.go b/functions/onprem/orborus/orborus.go index 84c5fff8..479b847f 100644 --- a/functions/onprem/orborus/orborus.go +++ b/functions/onprem/orborus/orborus.go @@ -926,21 +926,23 @@ func main() { log.Printf("[INFO] Executionstatus issue: ", execution.Status) } - found := false - for _, executionId := range executionIds { - if execution.ExecutionId == executionId { - found = true - break + /* + found := false + for _, executionId := range executionIds { + if execution.ExecutionId == executionId { + found = true + break + } } - } - // Doesn't work because of USER INPUT - if found { - log.Printf("[INFO] Skipping duplicate %s", execution.ExecutionId) - continue - } else { - //log.Printf("[INFO] Adding to be ran %s", execution.ExecutionId) - } + // Doesn't work because of USER INPUT + if found { + log.Printf("[INFO] Skipping duplicate %s", execution.ExecutionId) + continue + } else { + //log.Printf("[INFO] Adding to be ran %s", execution.ExecutionId) + } + */ // Now, how do I execute this one? // FIXME - if error, check the status of the running one. If it's bad, send data back. @@ -1241,16 +1243,17 @@ func sendWorkerRequest(workflowExecution shuffle.ExecutionRequest) error { return err } - if newresp.StatusCode != 200 { - log.Printf("[ERROR] Error running request - status code is %d, not 200", newresp.StatusCode) - return errors.New(fmt.Sprintf("Bad statuscode: %d - expecting 200", newresp.StatusCode)) - } - body, err := ioutil.ReadAll(newresp.Body) if err != nil { log.Printf("[ERROR] Failed reading body in worker request body: %s", err) return err } + + if newresp.StatusCode != 200 { + log.Printf("[ERROR] Error running request - status code is %d, not 200. Body: %s", newresp.StatusCode, string(body)) + return errors.New(fmt.Sprintf("Bad statuscode: %d - expecting 200", newresp.StatusCode)) + } + _ = body log.Printf("[DEBUG] Ran worker from request with execution ID: %s. Worker URL: %s.\n\n DEBUGGING: docker service logs shuffle-workers | grep %s\n\n", workflowExecution.ExecutionId, streamUrl, workflowExecution.ExecutionId)