From 511aea613ed1cab028a66c14bae8d1977a6bed97 Mon Sep 17 00:00:00 2001 From: Frikky Date: Tue, 15 Aug 2023 19:59:05 +0200 Subject: [PATCH 01/15] Did some minor fixes for documentation management --- docker-compose.yml | 2 +- frontend/src/views/Docs.jsx | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index daf8f7a0..2eb61619 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ version: '3' services: frontend: - image: ghcr.io/shuffle/shuffle-frontend:nightly + image: ghcr.io/shuffle/shuffle-frontend:latest container_name: shuffle-frontend hostname: shuffle-frontend ports: diff --git a/frontend/src/views/Docs.jsx b/frontend/src/views/Docs.jsx index a1fcf857..4d15fc42 100755 --- a/frontend/src/views/Docs.jsx +++ b/frontend/src/views/Docs.jsx @@ -436,7 +436,7 @@ const Docs = (defaultprops) => { href={selectedMeta.link} style={{ textDecoration: "none", color: "#f85a3e" }} > - @@ -792,17 +792,21 @@ const Docs = (defaultprops) => {
{data} @@ -811,6 +815,7 @@ const Docs = (defaultprops) => {
); + // remarkPlugins={[remarkGfm]} const mobileStyle = { color: "white", From 7282185805634958d3dfebe9987f858c79777828 Mon Sep 17 00:00:00 2001 From: Frikky Date: Tue, 15 Aug 2023 19:59:32 +0200 Subject: [PATCH 02/15] Repacked multiple files with old mui to merge together --- frontend/src/components/AppFramework.jsx | 10 +- frontend/src/components/Appsearch.jsx | 44 +- frontend/src/components/EditWorkflow.jsx | 151 +++-- frontend/src/components/Files.jsx | 6 +- frontend/src/components/Header.jsx | 52 +- frontend/src/components/Oauth2Auth.jsx | 16 +- frontend/src/components/OrgHeader.jsx | 33 +- frontend/src/components/Priorities.jsx | 6 +- frontend/src/components/Priority.jsx | 33 +- frontend/src/views/Admin.jsx | 380 +++++++---- frontend/src/views/AngularWorkflow.jsx | 822 +++++++++++++++++++---- frontend/src/views/Welcome.jsx | 20 +- frontend/src/views/Workflows.jsx | 342 ++++++++-- 13 files changed, 1440 insertions(+), 475 deletions(-) diff --git a/frontend/src/components/AppFramework.jsx b/frontend/src/components/AppFramework.jsx index 54fb6869..e562a159 100644 --- a/frontend/src/components/AppFramework.jsx +++ b/frontend/src/components/AppFramework.jsx @@ -23,13 +23,16 @@ import { Dialog, Chip, Avatar, +} from "@material-ui/core"; + +import { Button -} from "@mui/material"; +} from '@material-ui/core'; import { Close as CloseIcon, Delete as DeleteIcon, -} from "@mui/icons-material"; +} from "@material-ui/icons"; import * as edgehandles from "cytoscape-edgehandles"; import * as cytoscape from "cytoscape"; @@ -1856,6 +1859,7 @@ const AppFramework = (props) => { //autounselectify={true} var usecasediff = -100 const bgColor = color === undefined || color === null || color.length === 0 ? theme.palette.surfaceColor : color + console.log("Background: ", bgColor) return (
@@ -1996,7 +2000,7 @@ const AppFramework = (props) => { {paperTitle.length > 0 ? - {paperTitle} + {paperTitle.replace("_", " ", -1)} diff --git a/frontend/src/components/Appsearch.jsx b/frontend/src/components/Appsearch.jsx index 5defd0f0..40af3e48 100644 --- a/frontend/src/components/Appsearch.jsx +++ b/frontend/src/components/Appsearch.jsx @@ -1,14 +1,14 @@ import React, { useState, useEffect } from 'react'; -import theme from '../theme.jsx'; import ReactGA from 'react-ga4'; +import { useTheme } from '@material-ui/core/styles'; import {Link} from 'react-router-dom'; import { useAlert } from "react-alert"; -import { Search as SearchIcon, CloudQueue as CloudQueueIcon, Code as CodeIcon } from '@mui/icons-material'; +import { Search as SearchIcon, CloudQueue as CloudQueueIcon, Code as CodeIcon } from '@material-ui/icons'; //import algoliasearch from 'algoliasearch/lite'; import algoliasearch from 'algoliasearch'; import { InstantSearch, connectSearchBox, connectHits } from 'react-instantsearch-dom'; -import { Grid, Paper, TextField, ButtonBase, InputAdornment, Typography, Button, Tooltip} from '@mui/material'; +import { Grid, Paper, TextField, ButtonBase, InputAdornment, Typography, Button, Tooltip} from '@material-ui/core'; import aa from 'search-insights' const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e5240") const Appsearch = props => { @@ -18,6 +18,7 @@ const Appsearch = props => { const alert = useAlert(); const rowHandler = maxRows === undefined || maxRows === null ? 50 : maxRows const xs = parsedXs === undefined || parsedXs === null ? 12 : parsedXs + const theme = useTheme(); //const [apps, setApps] = React.useState([]); //const [filteredApps, setFilteredApps] = React.useState([]); const [formMail, setFormMail] = React.useState(""); @@ -69,43 +70,6 @@ const Appsearch = props => { console.log(error); }); }; - const submitContact = (email, message) => { - const data = { - "firstname": "", - "lastname": "", - "title": "", - "companyname": "", - "email": email, - "phone": "", - "message": message, - } - - const errorMessage = "Something went wrong. Please contact frikky@shuffler.io directly." - - fetch(globalUrl+"/api/v1/contact", { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(data), - }) - .then(response => response.json()) - .then(response => { - if (response.success === true) { - setFormMessage(response.reason) - //alert.info("Thanks for submitting!") - } else { - setFormMessage(errorMessage) - } - - setFormMail("") - setMessage("") - }) - .catch(error => { - setFormMessage(errorMessage) - console.log(error) - }); - } // value={currentRefinement} const SearchBox = ({currentRefinement, refine, isSearchStalled} ) => { diff --git a/frontend/src/components/EditWorkflow.jsx b/frontend/src/components/EditWorkflow.jsx index 5e8b0493..f4a2b6e0 100644 --- a/frontend/src/components/EditWorkflow.jsx +++ b/frontend/src/components/EditWorkflow.jsx @@ -3,6 +3,7 @@ import theme from '../theme.jsx'; import { isMobile } from "react-device-detect" import ChipInput from "material-ui-chip-input"; import UsecaseSearch from "../components/UsecaseSearch.jsx" +import dayjs from 'dayjs'; import { Badge, @@ -37,28 +38,35 @@ import { FormControl, FormLabel, -} from "@mui/material"; +} from "@material-ui/core"; + +import { + DatePicker, + LocalizationProvider, +} from '@mui/x-date-pickers' + +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs' import { ExpandLess as ExpandLessIcon, ExpandMore as ExpandMoreIcon, Publish as PublishIcon, OpenInNew as OpenInNewIcon, -} from "@mui/icons-material"; +} from "@material-ui/icons"; const EditWorkflow = (props) => { const { globalUrl, workflow, setWorkflow, modalOpen, setModalOpen, showUpload, usecases, setNewWorkflow, appFramework, isEditing, userdata, } = props + const [_, setUpdate] = React.useState(""); // Used for rendering, don't remove const [submitLoading, setSubmitLoading] = React.useState(false); const [showMoreClicked, setShowMoreClicked] = React.useState(false); const [innerWorkflow, setInnerWorkflow] = React.useState(workflow) - const [_, setUpdate] = React.useState(""); // Used for rendering, don't remove const [newWorkflowTags, setNewWorkflowTags] = React.useState(workflow.tags !== undefined && workflow.tags !== null ? JSON.parse(JSON.stringify(workflow.tags)) : []) const [selectedUsecases, setSelectedUsecases] = React.useState(workflow.usecase_ids !== undefined && workflow.usecase_ids !== null ? JSON.parse(JSON.stringify(workflow.usecase_ids)) : []); const [foundWorkflowId, setFoundWorkflowId] = React.useState("") const [name, setName] = React.useState(workflow.name !== undefined ? workflow.name : "") const [description, setDescription] = React.useState(workflow.description !== undefined ? workflow.description : "") - + const [dueDate, setDueDate] = React.useState(workflow.due_date !== undefined && workflow.due_date !== null && workflow.due_date !== 0 ? dayjs(workflow.due_date*1000) : dayjs().subtract(1, 'day')) // Gets the generated workflow const getGeneratedWorkflow = (workflow_id) => { @@ -231,24 +239,26 @@ const EditWorkflow = (props) => { autoFocus fullWidth /> - { - setDescription(event.target.value) - }} - InputProps={{ - style: { - color: "white", - }, - }} - maxRows={4} - color="primary" - defaultValue={innerWorkflow.description} - placeholder="Description" - multiline - label="Description" - margin="dense" - fullWidth - /> +
+ { + setDescription(event.target.value) + }} + InputProps={{ + style: { + color: "white", + }, + }} + maxRows={4} + color="primary" + defaultValue={innerWorkflow.description} + placeholder="Description" + multiline + label="Description" + margin="dense" + fullWidth + /> +
{ setNewWorkflowTags(newWorkflowTags); }} onDelete={(chip, index) => { + console.log("Deleting: ", chip, index) newWorkflowTags.splice(index, 1); setNewWorkflowTags(newWorkflowTags); + setUpdate(Math.random()); }} /> {usecases !== null && usecases !== undefined && usecases.length > 0 ? @@ -328,26 +340,41 @@ const EditWorkflow = (props) => { {showMoreClicked === true ? +
+ + Status + { + console.log("Data: ", e.target.value) + + innerWorkflow.workflow_type = e.target.value + setInnerWorkflow(innerWorkflow) + }} + > + } label="Test" /> + } label="Production" /> - - Status - { - console.log("Data: ", e.target.value) - - innerWorkflow.workflow_type = e.target.value - setInnerWorkflow(innerWorkflow) + + + + - } label="Test" /> - } label="Production" /> - - - + value={dueDate} + label="Due Date" + format="YYYY-MM-DD" + onChange={(newValue) => { + setDueDate(newValue) + }} + /> + +
@@ -430,38 +457,27 @@ const EditWorkflow = (props) => { : null} - { - setShowMoreClicked(!showMoreClicked); - }} - > - {showMoreClicked ? : } - - -
- {/*newWorkflow === true ? -
- -
- : null*/} + { + setShowMoreClicked(!showMoreClicked); + }} + > + {showMoreClicked ? : } + + +
+
@@ -698,17 +703,24 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho {/* */} - Apps + Apps + {/* + + +
Dashboard
+ +
+ */}
{/* */} - Docs + Docs
@@ -782,14 +794,13 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho : null*/} - - {userdata === undefined || userdata.orgs === undefined || userdata.orgs === null || userdata.orgs.length <= 1 ? null : -
{ @@ -2266,7 +2443,6 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user > -
{selectedOrganization.defaults !== undefined && selectedOrganization.defaults.documentation_reference !== undefined && selectedOrganization.defaults.documentation_reference !== null && selectedOrganization.defaults.documentation_reference.includes("http") ? -
-
: null} {selectedOrganization.name.length > 0 ? ( @@ -2341,7 +2515,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user - Billing + Billing (Beta)
/> /> - - Usage - - /> - {/* - - Notifications - - /> - */} , + icon: , }; return ( - -
- -
+ + ); })} @@ -2614,6 +2772,8 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user adminTab={adminTab} globalUrl={globalUrl} checkLogin={checkLogin} + setAdminTab={setAdminTab} + setCurTab={setCurTab} /> : adminTab === 3 ? @@ -2635,6 +2796,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user globalUrl={globalUrl} handleGetOrg={handleGetOrg} selectedOrganization={selectedOrganization} + selectedOrganization={selectedOrganization} setSelectedOrganization={setSelectedOrganization} /> : null @@ -2940,7 +3102,6 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user style={{}} aria-label={"Copy APIkey"} > -
{ @@ -2977,7 +3138,6 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user style={{ color: "rgba(255,255,255,0.8)" }} /> -
) } @@ -3550,19 +3710,17 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user title="Set in EVERY workflow" placement="top" > -
- { - editAuthenticationConfig(data.id); - }} - > - - -
+ { + editAuthenticationConfig(data.id); + }} + > + + ) : ( -
{}} @@ -3579,7 +3736,6 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user color={data.defined ? "primary" : "secondary"} /> -
)} -
-
} /> @@ -3920,7 +4074,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user {showCPUAlert === false ? null : -
+
90% CPU the server(s) hosting the Shuffle App Runner (Orborus) was found. @@ -4202,7 +4356,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user - + Environments /> diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index 024799fb..f88ae850 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -1,18 +1,19 @@ /* eslint-disable react/no-multi-comp */ import React, { useState, useEffect, useLayoutEffect } from "react"; import ReactDOM from "react-dom" -import theme from '../theme.jsx'; import { useInterval } from "react-powerhooks"; -//import { makeStyles, } from "@mui/styles"; +import { makeStyles, useTheme } from "@material-ui/core/styles"; import { v4 as uuidv4 } from "uuid"; import { useNavigate, 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 "mui-nested-menu" +import NestedMenuItem from "material-ui-nested-menu-item"; import ReactMarkdown from "react-markdown"; import { useAlert } from "react-alert"; +import theme from '../theme.jsx'; import { isMobile } from "react-device-detect" import aa from 'search-insights' import Drift from "react-driftjs"; @@ -50,7 +51,7 @@ import { IconButton, Menu, Input, - Collapse, + Fade, FormGroup, FormControlLabel, Typography, @@ -66,9 +67,11 @@ import { ListItemText, ListItemAvatar, Badge, - Autocomplete, +} from "@material-ui/core"; + +import { AvatarGroup, -} from "@mui/material"; +} from "@mui/material" import { Folder as FolderIcon, @@ -84,7 +87,7 @@ import { ArrowLeft as ArrowLeftIcon, Cached as CachedIcon, DirectionsRun as DirectionsRunIcon, - Code as CodeIcon, + Polymer as PolymerIcon, FormatListNumbered as FormatListNumberedIcon, PlayArrow as PlayArrowIcon, AspectRatio as AspectRatioIcon, @@ -104,25 +107,30 @@ import { VpnKey as VpnKeyIcon, AddComment as AddCommentIcon, Edit as EditIcon, - Send as SendIcon, + Send as SendIcon, + Restore as RestoreIcon, +} from "@material-ui/icons"; + +import { Preview as PreviewIcon, ContentCopy as ContentCopyIcon, Circle as CircleIcon, SquareFoot as SquareFootIcon, AutoFixHigh as AutoFixHighIcon, -} from "@mui/icons-material"; +} from '@mui/icons-material'; +import Autocomplete from "@material-ui/lab/Autocomplete"; import * as cytoscape from "cytoscape"; import * as edgehandles from "cytoscape-edgehandles"; -//import * as clipboard from "cytoscape-clipboard"; -//import undoRedo from "cytoscape-undo-redo"; -//import cxtmenu from "cytoscape-cxtmenu"; +import * as clipboard from "cytoscape-clipboard"; import CytoscapeComponent from "react-cytoscapejs"; +import undoRedo from "cytoscape-undo-redo"; import Draggable from "react-draggable"; import cytoscapestyle from "../defaultCytoscapeStyle.jsx"; +import cxtmenu from "cytoscape-cxtmenu"; import { validateJson, GetIconInfo } from "./Workflows.jsx"; import { GetParsedPaths } from "./Apps.jsx"; @@ -228,9 +236,9 @@ const inputColor = "#383B40"; // http://apps.cytoscape.org/apps/yfileslayoutalgorithms cytoscape.use(edgehandles); -//cytoscape.use(clipboard); -//cytoscape.use(undoRedo); -//cytoscape.use(cxtmenu); +cytoscape.use(clipboard); +cytoscape.use(undoRedo); +cytoscape.use(cxtmenu); // Adds specific text to items //import popper from 'cytoscape-popper'; @@ -353,6 +361,32 @@ export function removeParam(key, sourceURL) { return rtn; } +const useStyles = makeStyles({ + notchedOutline: { + borderColor: "#f85a3e !important", + }, + root: { + "& .MuiAutocomplete-listbox": { + border: "2px solid #f85a3e", + color: "white", + fontSize: 18, + "& li:nth-child(even)": { + backgroundColor: "#CCC", + }, + "& li:nth-child(odd)": { + backgroundColor: "#FFF", + }, + }, + }, + inputRoot: { + color: "white", + // This matches the specificity of the default styles at https://github.com/mui-org/material-ui/blob/v4.11.3/packages/material-ui-lab/src/Autocomplete/Autocomplete.js#L90 + "&:hover .MuiOutlinedInput-notchedOutline": { + borderColor: "#f86a3e", + }, + }, +}); + const splitter = "|~|"; const svgSize = 24; //const referenceUrl = "https://shuffler.io/functions/webhooks/" @@ -369,6 +403,8 @@ const AngularWorkflow = (defaultprops) => { props.match = {} props.match.params = params + //const theme = useTheme(); + var to_be_copied = ""; const [firstrequest, setFirstrequest] = React.useState(true); @@ -385,6 +421,7 @@ const AngularWorkflow = (defaultprops) => { const [editWorkflowDetails, setEditWorkflowDetails] = React.useState(false); const [workflow, setWorkflow] = React.useState({}); + const [originalWorkflow, setOriginalWorkflow] = React.useState({}); const [userSettings, setUserSettings] = React.useState({}); const [subworkflow, setSubworkflow] = React.useState({}); const [subworkflowStartnode, setSubworkflowStartnode] = React.useState(""); @@ -448,6 +485,8 @@ const AngularWorkflow = (defaultprops) => { const [destinationValue, setDestinationValue] = React.useState({}); const [conditionValue, setConditionValue] = React.useState({}); const [dragging, setDragging] = React.useState(false); + const [showWorkflowRevisions, setShowWorkflowRevisions] = React.useState(false); + const [selectedRevision, setSelectedRevision] = useState({}) const [dragPosition, setDragPosition] = React.useState({ x: 0, y: 0, @@ -461,6 +500,7 @@ const AngularWorkflow = (defaultprops) => { const [selectedEdgeIndex, setSelectedEdgeIndex] = React.useState({}); const [visited, setVisited] = React.useState([]); + const [allRevisions, setAllRevisions] = useState([]) const [apps, setApps] = React.useState([]); const [filteredApps, setFilteredApps] = React.useState([]); @@ -524,6 +564,7 @@ const AngularWorkflow = (defaultprops) => { const appBarSize = isCloud ? 75 : 72; const triggerEnvironments = isCloud ? ["cloud"] : ["onprem", "cloud"]; const unloadText = "Are you sure you want to leave without saving (CTRL+S)?"; + const classes = useStyles(); const [bodyWidth, bodyHeight] = useWindowSize() //console.log("Mobile: ", isMobile, bodyWidth, bodyHeight) @@ -1539,6 +1580,7 @@ const AngularWorkflow = (defaultprops) => { console.log("Save workflow error: ", error.toString()); }); + setOriginalWorkflow(useworkflow) return success; }; @@ -2076,13 +2118,13 @@ const AngularWorkflow = (defaultprops) => { var nodefound = false; var target = sourcenode.parameters.find((item) => item.name === "startnode"); - console.log("Got rightclick target: ", target) - if (target === undefined || target === null) { - target = { - "name": "startnode", - "value": responseJson.start - } - } + console.log("Got rightclick target: ", target) + if (target === undefined || target === null) { + target = { + "name": "startnode", + "value": responseJson.start + } + } console.log(sourcenode.parameters); console.log(target); @@ -2223,6 +2265,7 @@ const AngularWorkflow = (defaultprops) => { cy.on("add", "node", (e) => onNodeAdded(e)); cy.on("add", "edge", (e) => onEdgeAdded(e)); } else { + setOriginalWorkflow(responseJson); setWorkflow(responseJson); setWorkflowDone(true); @@ -2236,7 +2279,7 @@ const AngularWorkflow = (defaultprops) => { responseJson.errors !== // what responseJson.errors.length > 0 ) { - console.log("Setting configure Modal to open") + console.log("Setting configure Modal to open") setConfigureWorkflowModalOpen(true); } } @@ -3765,8 +3808,10 @@ const AngularWorkflow = (defaultprops) => { workflow.branches[branchkey].source_id === edge.source ) { console.log(edge.source); - alert.error("That branch already exists"); + + //alert.error("That branch already exists"); event.target.remove(); + found = true; break; } else if (edge.target === workflow.start) { @@ -4005,18 +4050,14 @@ const AngularWorkflow = (defaultprops) => { data: newcybranch, }; - if ( - nodedata.name !== "User Input" && - nodedata.name !== "Shuffle Workflow" - ) { - if ( - workflow.actions !== undefined && - workflow.actions !== null && - workflow.actions.length > 0 - ) { - cy.add(edgeToBeAdded); - } - } + if (edgeToBeAdded.data.source !== edgeToBeAdded.data.target && edgeToBeAdded.data.source !== undefined && edgeToBeAdded.data.target !== undefined) { + if (nodedata.name !== "User Input" && nodedata.name !== "Shuffle Workflow") { + if (workflow.actions !== undefined && workflow.actions !== null && workflow.actions.length > 0) { + console.log("Edge handle: ", edgeToBeAdded) + cy.add(edgeToBeAdded); + } + } + } setWorkflow(workflow); } @@ -4041,7 +4082,7 @@ const AngularWorkflow = (defaultprops) => { } // Check if the source is trigger and can start - console.log("Removed: ", edge.data()) + //console.log("Removed: ", edge.data()) const allNodes = cy.nodes().jsons() for (let nodekey in allNodes) { const curnode = allNodes[nodekey] @@ -4049,33 +4090,33 @@ const AngularWorkflow = (defaultprops) => { continue } - if (curnode.data.id === edge.data("source")) { - console.log("Found matching trigger source: ", curnode) - if (curnode.data.app_name !== "Shuffle Workflow" && curnode.data.app_name !== "User Input") { - // If it's started, READD the edge - if (curnode.data.status === "running") { - console.log("Edge is running - readd it: ", edge.data()) + if (curnode.data.id === edge.data("source")) { + console.log("Found matching trigger source: ", curnode) + if (curnode.data.app_name !== "Shuffle Workflow" && curnode.data.app_name !== "User Input") { + // If it's started, READD the edge + if (curnode.data.status === "running") { + console.log("Edge is running - readd it: ", edge.data()) - // Just making sure it's not running infinitely - var newdata = edge.data() - newdata.readded = true + // Just making sure it's not running infinitely + var newdata = edge.data() + newdata.readded = true - try { - cy.add({ - group: "edges", - data: newdata, - }) + try { + cy.add({ + group: "edges", + data: newdata, + }) - alert.error("You must STOP the trigger before deleting its branches") - } catch (e) { - console.log("Failed re-adding edge: ", e) - } - } + alert.error("You must STOP the trigger before deleting its branches") + } catch (e) { + console.log("Failed re-adding edge: ", e) + } + } - //status: "uninitialized", - } - } - } + //status: "uninitialized", + } + } + } workflow.branches = workflow.branches.filter( (a) => a.id !== edge.data().id @@ -5117,8 +5158,36 @@ const AngularWorkflow = (defaultprops) => { } } - const setupGraph = () => { - const actions = workflow.actions.map((action) => { + const setupGraph = (inputworkflow) => { + // Reset cytoscape nodes and branches + if (cy !== undefined && cy !== null) { + if (inputworkflow.actions !== undefined && inputworkflow.actions !== null && inputworkflow.actions.length > 0) { + cy.remove('*') + } + console.log("INPUT: ", inputworkflow) + } + + if (inputworkflow.actions === undefined || inputworkflow.actions === null) { + inputworkflow.actions = [] + } + + if (inputworkflow.branches === undefined || inputworkflow.branches === null) { + inputworkflow.branches = [] + } + + if (inputworkflow.triggers === undefined || inputworkflow.triggers === null) { + inputworkflow.triggers = [] + } + + if (inputworkflow.comments === undefined || inputworkflow.comments === null) { + inputworkflow.comments = [] + } + + if (inputworkflow.visual_branches === undefined || inputworkflow.visual_branches === null) { + inputworkflow.visual_branches = [] + } + + const actions = inputworkflow.actions.map((action) => { const node = {}; if (!action.isStartNode && action.app_name === "Shuffle Tools") { @@ -5145,9 +5214,9 @@ const AngularWorkflow = (defaultprops) => { node.data.id = action["id"]; node.data._id = action["id"]; node.data.type = "ACTION"; - node.isStartNode = action["id"] === workflow.start; + node.isStartNode = action["id"] === inputworkflow.start; - if (workflow.public === true) { + if (inputworkflow.public === true) { node.data.is_valid = true node.is_valid = true } @@ -5166,7 +5235,7 @@ const AngularWorkflow = (defaultprops) => { return node; }); - const decoratorNodes = workflow.actions.map((action) => { + const decoratorNodes = inputworkflow.actions.map((action) => { if (!action.isStartNode) { if (action.app_name === "Testing") { return null; @@ -5200,7 +5269,7 @@ const AngularWorkflow = (defaultprops) => { }); - const foundtriggers = workflow.triggers.map((trigger) => { + const foundtriggers = inputworkflow.triggers.map((trigger) => { const node = {}; node.position = trigger.position; node.data = trigger; @@ -5214,11 +5283,11 @@ const AngularWorkflow = (defaultprops) => { var comments = []; if ( - workflow.comments !== undefined && - workflow.comments !== null && - workflow.comments.length > 0 + inputworkflow.comments !== undefined && + inputworkflow.comments !== null && + inputworkflow.comments.length > 0 ) { - comments = workflow.comments.map((comment) => { + comments = inputworkflow.comments.map((comment) => { const node = {}; node.position = comment.position; node.data = comment; @@ -5230,13 +5299,12 @@ const AngularWorkflow = (defaultprops) => { }); } - // FIXME - tmp branch update var insertedNodes = [].concat(actions, foundtriggers, decoratorNodes, comments); insertedNodes = insertedNodes.filter((node) => node !== null); - var edges = workflow.branches.map((branch, index) => { + var edges = inputworkflow.branches.map((branch, index) => { const edge = {}; - var conditions = workflow.branches[index].conditions; + var conditions = inputworkflow.branches[index].conditions; if (conditions === undefined || conditions === null) { conditions = []; } @@ -5248,6 +5316,26 @@ const AngularWorkflow = (defaultprops) => { label = conditions.length + " conditions"; } + // Verify if branch.source_id and branch.destination_id exists in triggers or actions + /* + var sourceExists = false; + var destinationExists = false; + for (var i = 0; i < insertedNodes.length; i++) { + console.log("Insertednode: ", insertedNodes[i].data); + if (insertedNodes[i].data._id === branch.source_id) { + sourceExists = true; + } + if (insertedNodes[i].data._id === branch.destination_id) { + destinationExists = true; + } + } + + if (sourceExists === false || destinationExists === false) { + console.log("Couldn't find source node for branch " + branch.id); + return null; + } + */ + edge.data = { id: branch.id, _id: branch.id, @@ -5287,18 +5375,18 @@ const AngularWorkflow = (defaultprops) => { }); if ( - workflow.visual_branches !== undefined && - workflow.visual_branches !== null && - workflow.visual_branches.length > 0 + inputworkflow.visual_branches !== undefined && + inputworkflow.visual_branches !== null && + inputworkflow.visual_branches.length > 0 ) { - const visualedges = workflow.visual_branches.map((branch, index) => { + const visualedges = inputworkflow.visual_branches.map((branch, index) => { const edge = {}; - if (workflow.branches[index] === undefined) { + if (inputworkflow.branches[index] === undefined) { return {}; } - var conditions = workflow.branches[index].conditions; + var conditions = inputworkflow.branches[index].conditions; if (conditions === undefined || conditions === null) { conditions = []; } @@ -5319,7 +5407,6 @@ const AngularWorkflow = (defaultprops) => { edges = edges.concat(visualedges); } - setWorkflow(workflow); // Verifies if a branch is valid and skips others var newedges = []; @@ -5343,7 +5430,18 @@ const AngularWorkflow = (defaultprops) => { } insertedNodes = insertedNodes.concat(newedges); - setElements(insertedNodes); + + console.log("NODES: ", insertedNodes) + setWorkflow(inputworkflow); + + // Reset view for cytoscape + if (cy !== undefined && cy !== null) { + console.log("In cy add!") + cy.add(insertedNodes); + cy.fit(null, 200); + } else { + setElements(insertedNodes); + } }; const removeNode = (nodeId) => { @@ -5487,11 +5585,47 @@ const AngularWorkflow = (defaultprops) => { }) } + const getRevisionHistory = (workflow_id) => { + console.log("Loading revisions for workflow ID ", workflow_id) + + fetch(`${globalUrl}/api/v1/workflows/${workflow_id}/revisions`, { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for workflows :O!"); + } + + // Read text from stream + //return response.text(); + return response.json(); + }) + .then((responseJson) => { + console.log("Got workflow revisions: ", responseJson) + + if (responseJson.success === false) { + console.log("Error getting workflow revisions: ", responseJson) + return + } + + setAllRevisions(responseJson) + }) + .catch((error) => { + console.log("Error getting workflow revisions: ", error) + }); + } + // eslint-disable-next-line react-hooks/exhaustive-deps //useEffect(() => { if (firstrequest) { setFirstrequest(false); getWorkflow(props.match.params.key, {}); + getRevisionHistory(props.match.params.key) getApps(); fetchUsecases() @@ -5532,7 +5666,7 @@ const AngularWorkflow = (defaultprops) => { // App length necessary cus of cy initialization if (elements.length === 0 && workflow.actions !== undefined && !graphSetup && Object.getOwnPropertyNames(workflow).length > 0) { setGraphSetup(true); - setupGraph(); + setupGraph(workflow); console.log("In graph setup") // 2nd load - configures cytoscape @@ -7080,6 +7214,12 @@ const AngularWorkflow = (defaultprops) => {
{ if (allitems !== undefined && allitems !== null) { for (let itemkey in allitems) { const item = allitems[itemkey]; - if ( - item.app_name === appName && - item.label !== undefined && - item.label !== null - ) { + console.log("Appname: ", appName, "Item: ", item); + + if (item.app_name === appName && item.label !== undefined && item.label !== null) { var number = item.label.split("_"); - if ( - isNaN(number[-1]) && - parseInt(number[number.length - 1]) > highest - ) { + if (isNaN(number[-1]) && parseInt(number[number.length - 1]) > highest) { highest = number[number.length - 1]; } } @@ -7783,6 +7918,15 @@ const AngularWorkflow = (defaultprops) => { backgroundColor: inputColor, borderRadius: theme.palette.borderRadius, }} + InputProps={{ + style: { + color: "white", + minHeight: 50, + marginLeft: "5px", + maxWidth: "95%", + fontSize: "1em", + }, + }} fullWidth multiline={multiline} color="primary" @@ -9131,6 +9275,15 @@ const AngularWorkflow = (defaultprops) => { backgroundColor: inputColor, borderRadius: theme.palette.borderRadius, }} + InputProps={{ + style: { + color: "white", + marginLeft: "5px", + maxWidth: "95%", + height: 50, + fontSize: "1em", + }, + }} fullWidth color="primary" placeholder={selectedTrigger.label} @@ -9145,6 +9298,13 @@ const AngularWorkflow = (defaultprops) => { borderRadius: theme.palette.borderRadius, }} InputProps={{ + style: { + color: "white", + marginLeft: "5px", + maxWidth: "95%", + height: 50, + fontSize: "1em", + }, }} required disabled @@ -9875,6 +10035,15 @@ const AngularWorkflow = (defaultprops) => { backgroundColor: inputColor, borderRadius: theme.palette.borderRadius, }} + InputProps={{ + style: { + color: "white", + marginLeft: "5px", + maxWidth: "95%", + height: 50, + fontSize: "1em", + }, + }} fullWidth color="primary" placeholder={selectedTrigger.label} @@ -9891,6 +10060,14 @@ const AngularWorkflow = (defaultprops) => { Delay { freeSolo //autoSelect value={subworkflow} + classes={{ inputRoot: classes.inputRoot }} ListboxProps={{ style: { backgroundColor: theme.palette.inputColor, @@ -10119,6 +10297,7 @@ const AngularWorkflow = (defaultprops) => { id="subflow_node_search" autoHighlight value={subworkflowStartnode} + classes={{ inputRoot: classes.inputRoot }} ListboxProps={{ style: { backgroundColor: theme.palette.inputColor, @@ -10211,6 +10390,12 @@ const AngularWorkflow = (defaultprops) => { borderRadius: theme.palette.borderRadius, }} InputProps={{ + style: { + color: "white", + marginLeft: "5px", + maxWidth: "95%", + fontSize: "1em", + }, endAdornment: ( @@ -10357,6 +10542,12 @@ const AngularWorkflow = (defaultprops) => { borderRadius: theme.palette.borderRadius, }} InputProps={{ + style: { + color: "white", + marginLeft: "5px", + maxWidth: "95%", + fontSize: "1em", + }, }} multiline rows="4" @@ -10378,6 +10569,13 @@ const AngularWorkflow = (defaultprops) => { borderRadius: theme.palette.borderRadius, }} InputProps={{ + style: { + color: "white", + marginLeft: "5px", + maxWidth: "95%", + height: 50, + fontSize: "1em", + }, }} fullWidth color="primary" @@ -10425,6 +10623,13 @@ const AngularWorkflow = (defaultprops) => { borderRadius: theme.palette.borderRadius, }} InputProps={{ + style: { + color: "white", + marginLeft: "5px", + maxWidth: "95%", + height: 50, + fontSize: "1em", + }, }} fullWidth color="primary" @@ -10444,6 +10649,13 @@ const AngularWorkflow = (defaultprops) => { borderRadius: theme.palette.borderRadius, }} InputProps={{ + style: { + color: "white", + marginLeft: "5px", + maxWidth: "95%", + height: 50, + fontSize: "1em", + }, }} fullWidth color="primary" @@ -10463,6 +10675,13 @@ const AngularWorkflow = (defaultprops) => { borderRadius: theme.palette.borderRadius, }} InputProps={{ + style: { + color: "white", + marginLeft: "5px", + maxWidth: "95%", + height: 50, + fontSize: "1em", + }, }} fullWidth color="primary" @@ -10567,6 +10786,13 @@ const AngularWorkflow = (defaultprops) => { borderRadius: theme.palette.borderRadius, }} InputProps={{ + style: { + color: "white", + marginLeft: "5px", + maxWidth: "95%", + height: 50, + fontSize: "1em", + }, }} fullWidth color="primary" @@ -10579,6 +10805,7 @@ const AngularWorkflow = (defaultprops) => { id="action_search" autoHighlight value={selectedTrigger.app_association} + classes={{ inputRoot: classes.inputRoot }} ListboxProps={{ style: { backgroundColor: theme.palette.inputColor, @@ -10913,6 +11140,12 @@ const AngularWorkflow = (defaultprops) => { id="webhook_uri_header" onClick={() => { }} InputProps={{ + style: { + color: "white", + marginLeft: "5px", + maxWidth: "95%", + fontSize: "1em", + }, }} fullWidth multiline @@ -10964,6 +11197,12 @@ const AngularWorkflow = (defaultprops) => { id="webhook_uri_header" onClick={() => { }} InputProps={{ + style: { + color: "white", + marginLeft: "5px", + maxWidth: "95%", + fontSize: "1em", + }, }} fullWidth multiline @@ -11367,6 +11606,13 @@ const AngularWorkflow = (defaultprops) => { borderRadius: theme.palette.borderRadius, }} InputProps={{ + style: { + color: "white", + marginLeft: "5px", + maxWidth: "95%", + height: 50, + fontSize: "1em", + }, }} fullWidth color="primary" @@ -11434,6 +11680,13 @@ const AngularWorkflow = (defaultprops) => { borderRadius: theme.palette.borderRadius, }} InputProps={{ + style: { + color: "white", + marginLeft: "5px", + maxWidth: "95%", + marginTop: "3px", + fontSize: "1em", + }, }} fullWidth rows="4" @@ -11523,6 +11776,7 @@ const AngularWorkflow = (defaultprops) => { id="subflow_search" autoHighlight value={subworkflow} + classes={{ inputRoot: classes.inputRoot }} ListboxProps={{ style: { backgroundColor: theme.palette.inputColor, @@ -11641,6 +11895,13 @@ const AngularWorkflow = (defaultprops) => { marginTop: 10, }} InputProps={{ + style: { + color: "white", + marginLeft: "5px", + maxWidth: "95%", + height: 50, + fontSize: "1em", + }, }} fullWidth color="primary" @@ -11723,6 +11984,13 @@ const AngularWorkflow = (defaultprops) => { borderRadius: theme.palette.borderRadius, }} InputProps={{ + style: { + color: "white", + marginLeft: "5px", + maxWidth: "95%", + height: 50, + fontSize: "1em", + }, }} fullWidth color="primary" @@ -11820,6 +12088,13 @@ const AngularWorkflow = (defaultprops) => { borderRadius: theme.palette.borderRadius, }} InputProps={{ + style: { + color: "white", + height: 50, + marginLeft: "5px", + maxWidth: "95%", + fontSize: "1em", + }, }} fullWidth disabled={ @@ -11868,6 +12143,13 @@ const AngularWorkflow = (defaultprops) => { borderRadius: theme.palette.borderRadius, }} InputProps={{ + style: { + color: "white", + marginLeft: "5px", + maxWidth: "95%", + marginTop: "3px", + fontSize: "1em", + }, }} disabled={ workflow.triggers[selectedTriggerIndex].status === "running" @@ -11975,7 +12257,7 @@ const AngularWorkflow = (defaultprops) => { margin: "0px 0px 0px 0px", }} > - + Workflows @@ -12517,6 +12799,27 @@ const AngularWorkflow = (defaultprops) => { + + + + +
); @@ -12696,11 +12999,11 @@ const AngularWorkflow = (defaultprops) => { {defaultReturn} : - +
{defaultReturn}
-
+ ); //return null; @@ -14776,7 +15079,7 @@ const AngularWorkflow = (defaultprops) => {
) : ( - + { setCy(incy); }} /> - + )}
{executionModal} @@ -14835,36 +15138,16 @@ const AngularWorkflow = (defaultprops) => { setSelectedActionEnvironment={setSelectedActionEnvironment} requiresAuthentication={requiresAuthentication} /> - - + + {showWorkflowRevisions ? null : + + + + + }
); - const editWorkflowModal = - { - setEditWorkflowDetails(false) - }} - PaperProps={{ - style: { - pointerEvents: "auto", - backgroundColor: surfaceColor, - color: "white", - border: theme.palette.defaultBorder, - maxWidth: "100%", - padding: 50, - }, - }} - > - Edit workflow! - const ExecutionVariableModal = (props) => { const { variableInfo } = props @@ -16140,6 +16423,290 @@ const AngularWorkflow = (defaultprops) => { ) } + + /*else if (selectedRevision === undefined || selectedRevision === null || selectedRevision == {} && originalWorkflow !== undefined && originalWorkflow !== null && originalWorkflow !== {}) { + console.log("Setting original workflow as selected revision") + setSelectedRevision(originalWorkflow) + }*/ + + const RevisionBox = (props) => { + const { revision, } = props + + if (revision === undefined || revision === null || revision === {}) { + return null + } + + // Make unix timestamp into ISO timestamp in the format July 27th, 3:05 AM + // Format: July 27th, 3:05 AM + const translatedDate = new Date(revision.edited).toLocaleString('en-US', { month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: true }) + + var workflowStatus = revision.status !== undefined && revision.status !== null && revision.status !== "" ? revision.status : "test" + if (revision.name !== undefined && revision.name !== null && revision.name !== "") { + if (revision.name.toLowerCase().includes("test")) { + workflowStatus = "test" + } + + if (revision.name.toLowerCase().includes("dev") || revision.name.toLowerCase().includes("staging") || revision.name.toLowerCase().includes("rollback")) { + workflowStatus = "dev" + } + + if (revision.name.toLowerCase().includes("prod") || revision.name.toLowerCase().includes("main")) { + workflowStatus = "prod" + } + } + + return ( + { + if (revision.edited === selectedRevision.edited) { + console.log("Same revision! No setting.") + return + } + + // Should render if it's not the same as workflow.edited + console.log("Clicked revision: ", revision) + setLastSaved(false) + setSelectedRevision(revision) + setWorkflow(revision) + setSelectedAction({}); + setSelectedApp({}) + + // Remove all cytoscape triggers first? + if (cy !== undefined && cy !== null) { + cy.removeListener("select"); + cy.removeListener("unselect"); + + cy.removeListener("add"); + cy.removeListener("remove"); + + cy.removeListener("mouseover"); + cy.removeListener("mouseout"); + + cy.removeListener("drag"); + cy.removeListener("free"); + cy.removeListener("cxttap"); + } + + setupGraph(revision) + + // Re-adding cytoscape triggers + if (cy !== undefined && cy !== null) { + cy.on("select", "node", (e) => { + onNodeSelect(e, appAuthentication); + }); + cy.on("select", "edge", (e) => onEdgeSelect(e)); + + cy.on("unselect", (e) => onUnselect(e)); + + cy.on("add", "node", (e) => onNodeAdded(e)); + cy.on("add", "edge", (e) => onEdgeAdded(e)); + cy.on("remove", "node", (e) => onNodeRemoved(e)); + cy.on("remove", "edge", (e) => onEdgeRemoved(e)); + + cy.on("mouseover", "edge", (e) => onEdgeHover(e)); + cy.on("mouseout", "edge", (e) => onEdgeHoverOut(e)); + cy.on("mouseover", "node", (e) => onNodeHover(e)); + cy.on("mouseout", "node", (e) => onNodeHoverOut(e)); + + // Handles dragging + cy.on("drag", "node", (e) => onNodeDrag(e, selectedAction)); + cy.on("free", "node", (e) => onNodeDragStop(e, selectedAction)); + + cy.on("cxttap", "node", (e) => onCtxTap(e)); + } + + // Need to run through graph setup with this one + }}> +
+ + + {translatedDate} + + + + + +
+ {/*revision.edited === originalWorkflow.edited ? + + Current version + + : null*/} +
+ {revision.actions !== undefined && revision.actions !== null ? + + + + + {revision.actions.length} + + + + : null} + {revision.triggers !== undefined && revision.triggers !== null ? + + + + + {revision.triggers.length} + + + + : null} +
+ {revision.updated_by !== undefined && revision.updated_by !== null && revision.updated_by !== "" ? + + {revision.updated_by} + + : null} +
+ ) + } + + const drawerData = originalWorkflow !== undefined && originalWorkflow !== null && originalWorkflow !== {} ? +
+ + Version History (Beta) + + + + + {allRevisions.length > 0 ? + allRevisions.map((revision, index) => { + if (revision.edited === originalWorkflow.edited) { + return null + } + + return ( + + ) + }) + : +
+ + No other revisions found. Save your workflow with changes to create a revision. + +
+ } +
+ : null + + const workflowRevisions = !showWorkflowRevisions ? null : +
+ { + //setShowWorkflowRevisions(false) + }} + style={{ resize: "both", overflow: "auto", zIndex: 10005 }} + hideBackdrop={true} + variant="persistent" + BackdropProps={{ + style: { + //backgroundColor: "transparent", + } + }} + PaperProps={{ + style: { + resize: "both", + overflow: "auto", + minWidth: isMobile ? "100%" : 360, + maxWidth: isMobile ? "100%" : 360, + backgroundColor: theme.palette.platformColor, + color: "white", + fontSize: 18, + zIndex: 15001, + borderRight: theme.palette.defaultBorder, + paddingTop: 15, + }, + }} + > + {drawerData} + +
+
+ {/*selectedRevision.edited !== undefined && selectedRevision.edited !== null && selectedRevision.edited !== originalWorkflow.edited ? + + : null*/} +
+
+ + {selectedRevision.name} + +
+ {/* Cross icon to close it */} +
+ { + setShowWorkflowRevisions(false) + }} + style={{color: "white", height: 50, width: 50, }} + > + + +
+
+
+ + const loadedCheck = isLoaded && workflowDone ? (
@@ -16150,9 +16717,9 @@ const AngularWorkflow = (defaultprops) => { {authenticationModal} {codePopoutModal} {configureWorkflowModal} - {editWorkflowModal} - - + {/*editWorkflowModal*/} + {workflowRevisions} + {editWorkflowModalOpen === true ? { return (
+ {/* Removed due to missing react router features + + */} {loadedCheck}
); diff --git a/frontend/src/views/Welcome.jsx b/frontend/src/views/Welcome.jsx index 7cafddfd..1e209780 100644 --- a/frontend/src/views/Welcome.jsx +++ b/frontend/src/views/Welcome.jsx @@ -1,17 +1,15 @@ import React, { useState, useEffect } from 'react'; import ReactGA from 'react-ga4'; import WelcomeForm2 from "../components/WelcomeForm2.jsx"; -import { - Stepper, - Step, - StepLabel, -} from '@mui/material'; +import Stepper from "@material-ui/core/Stepper"; +import Step from "@material-ui/core/Step"; +import StepLabel from "@material-ui/core/StepLabel"; import AppFramework from "../components/AppFramework.jsx"; import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos'; import { Grid, Container, - Collapse, + Fade, Typography, Paper, Button, @@ -417,7 +415,7 @@ const Welcome = (props) => { App Framework - + { isLoggedIn={true} globalUrl={globalUrl} size={0.78} - color={theme.palette.platformColor} + color={theme.palette.backgroundColor} discoveryWrapper={discoveryWrapper} setDiscoveryWrapper={setDiscoveryWrapper} apps={apps} inputUsecases={usecases} setInputUsecases={setUsecases} /> - +
} : - +
{/*
@@ -537,7 +535,7 @@ const Welcome = (props) => {
-
+ } ) diff --git a/frontend/src/views/Workflows.jsx b/frontend/src/views/Workflows.jsx index d7f83edb..cd26d205 100755 --- a/frontend/src/views/Workflows.jsx +++ b/frontend/src/views/Workflows.jsx @@ -1,14 +1,14 @@ import React, { useEffect, useContext } from "react"; import ReactDOM from "react-dom" -import { makeStyles } from "@mui/styles"; +import { makeStyles } from "@material-ui/core/styles"; import { Navigate } from "react-router-dom"; //import { Redirect } from "react-router-dom"; import SecurityFramework from '../components/SecurityFramework.jsx'; import EditWorkflow from "../components/EditWorkflow.jsx" -//import { ShepherdTour, ShepherdTourContext } from 'react-shepherd' +import { ShepherdTour, ShepherdTourContext } from 'react-shepherd' import Priority from "../components/Priority.jsx"; import { isMobile } from "react-device-detect" @@ -41,7 +41,7 @@ import { Checkbox, LinearProgress, ListItemText, -} from "@mui/material" +} from "@material-ui/core"; import { AvatarGroup, @@ -79,7 +79,7 @@ import { RadioButtonUnchecked as RadioButtonUncheckedIcon, ArrowLeft as ArrowLeftIcon, ArrowRight as ArrowRightIcon, -} from "@mui/icons-material"; +} from "@material-ui/icons"; //import NestedMenuItem from "material-ui-nested-menu-item"; //import {Search as SearchIcon, ArrowUpward as ArrowUpwardIcon, Visibility as VisibilityIcon, Close as CloseIcon, Error as ErrorIcon, FindReplace as FindreplaceIcon, ArrowLeft as ArrowLeftIcon, Cached as CachedIcon, DirectionsRun as DirectionsRunIcon, Add as AddIcon, Polymer as PolymerIcon, FormatListNumbered as FormatListNumberedIcon, Create as CreateIcon, PlayArrow as PlayArrowIcon, AspectRatio as AspectRatioIcon, MoreVert as MoreVertIcon, Apps as AppsIcon, Schedule as ScheduleIcon, FavoriteBorder as FavoriteBorderIcon, Pause as PauseIcon, Delete as DeleteIcon, AddCircleOutline as AddCircleOutlineIcon, Save as SaveIcon, KeyboardArrowLeft as KeyboardArrowLeftIcon, KeyboardArrowRight as KeyboardArrowRightIcon, ArrowBack as ArrowBackIcon, Settings as SettingsIcon, LockOpen as LockOpenIcon, ExpandMore as ExpandMoreIcon, VpnKey as VpnKeyIcon} from '@material-ui/icons'; @@ -409,16 +409,16 @@ export const validateJson = (showResult) => { } if (typeof showResult === "object" || typeof showResult === "array") { - return { - valid: true, - result: showResult, - } + return { + valid: true, + result: showResult, + } } if (showResult[0] === "\"") { - return { - valid: false, - result: showResult, + return { + valid: false, + result: showResult, } } @@ -427,10 +427,10 @@ export const validateJson = (showResult) => { if (!showResult.includes("{") && !showResult.includes("[")) { jsonvalid = false - return { - valid: jsonvalid, - result: showResult, - }; + return { + valid: jsonvalid, + result: showResult, + }; } } catch (e) { showResult = showResult.split("'").join('"'); @@ -1182,7 +1182,7 @@ const Workflows = (props) => { setUsecases(newcategories) } else { - setUsecases(categorydata) + setUsecases(categorydata) } } @@ -1272,11 +1272,11 @@ const Workflows = (props) => { width: "100%", color: "white", backgroundColor: surfaceColor, + padding: "12px 12px 0px 15px", borderRadius: 5, display: "flex", boxSizing: "border-box", position: "relative", - padding: "12px 12px 0px 15px", }; const gridContainer = { @@ -1603,9 +1603,10 @@ const Workflows = (props) => { const innerColor = "rgba(255,255,255,0.3)"; const setupPaperStyle = { minHeight: paperAppStyle.minHeight, - maxWidth: "100%", + maxWidth: "100%", minWidth: paperAppStyle.width, color: innerColor, + padding: paperAppStyle.padding, borderRadius: paperAppStyle.borderRadius, display: "flex", boxSizing: "border-box", @@ -1613,12 +1614,10 @@ const Workflows = (props) => { border: `2px solid ${innerColor}`, cursor: "pointer", backgroundColor: hover ? "rgba(39,41,45,0.5)" : "rgba(39,41,45,1)", - - padding: paperAppStyle.padding, }; return ( - + { selectedUsecases.push(subcase.name) } - setUpdate(Math.random()); + setUpdate(Math.random()); setSelectedUsecases(selectedUsecases) }}> @@ -3067,12 +3066,153 @@ const Workflows = (props) => { ); + // const tourOptions = { + // defaultStepOptions: { + // classes: "shadow-md bg-purple-dark", + // scrollTo: true + // }, + // useModalOverlay: true, + // tourName: workflows, + // exitOnEsc: true, + // } + + // //classes: "custom-class-name-1 custom-class-name-2", + // const newSteps = [ + // { + // id: "intro", + // scrollTo: true, + // beforeShowPromise: function() { + // return new Promise(function(resolve) { + // setTimeout(function() { + // window.scrollTo(0, 0); + // resolve(); + // }, 500); + // }); + // }, + // buttons: [ + // { + // classes: "shepherd-button-primary", + // style: { + // backgroundColor: "red", + // color: "white", + // }, + // text: "Next", + // type: "next" + // } + // ], + // highlightClass: "highlight", + // showCancelLink: true, + // text: [ + // "React-Shepherd is a JavaScript library for guiding users through your React app." + // ], + // when: { + // show: () => { + // console.log("show step 1"); + // }, + // hide: () => { + // console.log("hide step 1"); + // } + // } + // }, + // { + // id: "second", + // attachTo: { + // element: "second-step", + // on: "top" + // }, + // text: [ + // "Yuk eksplorasi hasil Tes Minat Bakat-mu dan rekomendasi Jurusan dan Karier." + // ], + // buttons: [ + // { + // classes: "btn btn-info", + // text: "Kembali", + // type: "back" + // }, + // { + // classes: "btn btn-success", + // text: "Saya Mengerti", + // type: "cancel" + // } + // ], + // when: { + // show: () => { + // console.log("show stepp"); + // }, + // hide: () => { + // console.log("complete step"); + // } + // }, + // showCancelLink: false, + // scrollTo: true, + // modalOverlayOpeningPadding: 4, + // useModalOverlay: false, + // canClickTarget: false + // } + // ] + + // function TourButton() { + // const tour = useContext(ShepherdTourContext); + + // return ( + // + // ); + // } + const WorkflowView = () => { if (workflows.length === 0) { - // Not going there yet - //if ((userdata.tutorials !== undefined && userdata.tutorials !== null && !userdata.tutorials.includes("getting-started")) || userdata.tutorials === null) { - // return ; - //} + // Not going there yet + //if ((userdata.tutorials !== undefined && userdata.tutorials !== null && !userdata.tutorials.includes("getting-started")) || userdata.tutorials === null) { + // return ; + //} + //return ( + //
+ // + //
+ //

Welcome to Shuffle

+ //
+ //
+ //

+ // Shuffle is a flexible, easy to use, automation platform + // allowing users to integrate their services and devices freely. + // It's made to significantly reduce the amount of manual labor, + // and is focused on security applications.{" "} + // + // Click here to learn more. + // + //

+ //
+ //
+ // If you want to jump straight into it, click here to create your + // first workflow: + //
+ //
+ // + // + // + // ..OR + // + // {workflowButtons} + // + //
+ //
+ //
+ //) } var workflowDelay = -150 @@ -3084,40 +3224,101 @@ const Workflows = (props) => {
- - Workflows - + + Workflows +
- {isMobile ? null : -
-
- { - addFilter(chip); - }} - onDelete={(_, index) => { - removeFilter(index); - }} - /> -
-
- } + {/* + + */} + {isMobile ? null : +
+
+ { + addFilter(chip); + }} + onDelete={(_, index) => { + removeFilter(index); + }} + /> +
+
+ }
{workflowButtons}
+ {/* +
+
+
+
+
+
{workflows.length}
+
ACTIVE WORKFLOWS
+
+
+
+
+
+
+
+
{workflows.length}
+
AVAILABE WORKFLOWS
+
+
+
+
+
+
+
+
{workflows.length}
+
NOTIFICATIONS
+
+
+
+
+ */} + + {/* + chipRenderer={({ value, isFocused, isDisabled, handleClick, handleRequestDelete }, key) => { + console.log("VALUE: ", value) + + return ( + + {value} + + ) + }} + */}
{!isMobile && usecases !== null && usecases !== undefined && usecases.length > 0 ? @@ -3125,6 +3326,7 @@ const Workflows = (props) => { {usecases.map((usecase, index) => { //console.log(usecase) const percentDone = usecase.matches.length > 0 ? parseInt(usecase.matches.length/usecase.list.length*100) : 0 + console.log("Usecase Matches: ", usecase.matches, ", Percent: ", percentDone) return ( {
- {!isMobile && actionImageList !== undefined && actionImageList !== null && actionImageList.length > 0 ? ( + {!isMobile && + actionImageList !== undefined && + actionImageList !== null && + actionImageList.length > 0 ? (
{ return returnData } - /**/ return ( - - {returnData} - + + {returnData} + ); })}
@@ -3296,11 +3500,13 @@ const Workflows = (props) => { /> : null} - {/**/}
{view === "grid" ? ( - + + + + {filteredWorkflows.map((data, index) => { // Shouldn't be a part of this list if (data.public === true) { @@ -3311,17 +3517,15 @@ const Workflows = (props) => { workflowDelay += 75 } else { return ( - - - - - + + + ) } return ( - + @@ -3728,7 +3932,7 @@ const Workflows = (props) => { setWorkflow={setEditingWorkflow} modalOpen={modalOpen} setModalOpen={setModalOpen} - usecases={usecases} + usecases={usecases} setNewWorkflow={setNewWorkflow} appFramework={appFramework} isEditing={isEditing} From 2c140d23bd7d8614bca7e7ec1c1b25d0f076ccf3 Mon Sep 17 00:00:00 2001 From: Frikky Date: Tue, 15 Aug 2023 21:08:35 +0200 Subject: [PATCH 03/15] Fixed some of the first basic rendering issues --- backend/go-app/main.go | 11 ++- frontend/package.json | 4 +- frontend/src/App.jsx | 2 +- frontend/src/components/AppFramework.jsx | 16 ++--- frontend/src/components/Appsearch.jsx | 19 +++-- frontend/src/components/EditWorkflow.jsx | 8 +-- frontend/src/components/Files.jsx | 4 +- frontend/src/components/Header.jsx | 31 +++++---- frontend/src/components/Oauth2Auth.jsx | 5 +- frontend/src/components/OrgHeader.jsx | 29 ++++---- frontend/src/components/Priorities.jsx | 2 +- frontend/src/components/Priority.jsx | 8 +-- frontend/src/components/WelcomeForm2.jsx | 10 +-- frontend/src/views/Admin.jsx | 37 +++++----- frontend/src/views/AngularWorkflow.jsx | 43 ++++-------- frontend/src/views/AppCreator.jsx | 6 +- frontend/src/views/Apps.jsx | 6 -- frontend/src/views/GettingStarted.jsx | 6 +- frontend/src/views/Welcome.jsx | 12 ++-- frontend/src/views/Workflows.jsx | 88 +++++++++++------------- 20 files changed, 178 insertions(+), 169 deletions(-) diff --git a/backend/go-app/main.go b/backend/go-app/main.go index 26644fb8..cfaf3f5e 100755 --- a/backend/go-app/main.go +++ b/backend/go-app/main.go @@ -6052,9 +6052,16 @@ func initHandlers() { r.HandleFunc("/api/v1/orgs/{orgId}/list_cache", shuffle.HandleListCacheKeys).Methods("GET", "OPTIONS") r.HandleFunc("/api/v1/orgs/{orgId}/get_cache", shuffle.HandleGetCacheKey).Methods("POST", "OPTIONS") r.HandleFunc("/api/v1/orgs/{orgId}/set_cache", shuffle.HandleSetCacheKey).Methods("POST", "OPTIONS") - r.HandleFunc("/api/v1/orgs/{orgId}/cache/{cache_key}", shuffle.HandleDeleteCacheKey).Methods("DELETE", "OPTIONS") + r.HandleFunc("/api/v1/orgs/{orgId}/stats", shuffle.HandleGetStatistics).Methods("GET", "OPTIONS") - r.HandleFunc("/api/v1/orgs/{orgId}/revisions", shuffle.GetWorkflowRevisions).Methods("GET", "OPTIONS") + + r.HandleFunc("/api/v1/orgs/{orgId}/cache", shuffle.HandleListCacheKeys).Methods("GET", "OPTIONS") + r.HandleFunc("/api/v1/orgs/{orgId}/cache", shuffle.HandleSetCacheKey).Methods("POST", "OPTIONS") + r.HandleFunc("/api/v1/orgs/{orgId}/cache/{cache_key}", shuffle.HandleDeleteCacheKey).Methods("DELETE", "OPTIONS") + r.HandleFunc("/api/v1/orgs/{orgId}/datastore", shuffle.HandleListCacheKeys).Methods("GET", "OPTIONS") + r.HandleFunc("/api/v1/orgs/{orgId}/datastore", shuffle.HandleSetCacheKey).Methods("POST", "OPTIONS") + r.HandleFunc("/api/v1/orgs/{orgId}/datastore/{cache_key}", shuffle.HandleDeleteCacheKey).Methods("DELETE", "OPTIONS") + // Docker orborus specific - downloads an image r.HandleFunc("/api/v1/get_docker_image", getDockerImage).Methods("POST", "OPTIONS") diff --git a/frontend/package.json b/frontend/package.json index 4a4e9808..eb281a80 100755 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,6 +13,7 @@ "@mui/material": "^5.14.0", "@mui/styles": "^5.14.0", "@mui/x-data-grid": "^5.17.11", + "@mui/x-date-pickers": "^6.11.1", "@uiw/codemirror-themes": "^4.21.7", "@uiw/react-codemirror": "^4.21.7", "@use-it/interval": "^1.0.0", @@ -24,6 +25,7 @@ "cytoscape-edgehandles": "^3.6.0", "cytoscape-node-html-label": "^1.1.5", "d3": "^7.1.1", + "dayjs": "^1.11.9", "dotenv": "^6.1.0", "downshift": "^3.3.5", "github-markdown-css": "^3.0.1", @@ -36,11 +38,11 @@ "jss-nested": "^6.0.1", "jss-props-sort": "^6.0.0", "jss-vendor-prefixer": "^8.0.1", - "material-ui-chip-input": "^2.0.0-beta.2", "md5-file": "^4.0.0", "mdbreact": "^4.21.1", "mime": "^3.0.0", "moment": "^2.29.1", + "mui-chips-input": "^2.1.3", "mui-nested-menu": "^3.2.1", "process": "^0.11.10", "react": "^18.2.0", diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index abeb8ab3..28b665b0 100755 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -167,7 +167,7 @@ const App = (message, props) => { const includedData =
{ { Object.getOwnPropertyNames(discoveryData).length > 0 ? - + {paperTitle.length > 0 ? @@ -2130,7 +2128,7 @@ const AppFramework = (props) => { ? - Click an app below to select it + Search to find your app : @@ -2165,7 +2163,7 @@ const AppFramework = (props) => { elements={elements} minZoom={0.35} maxZoom={2.00} - style={{width: 560*scale, height: 560*scale, backgroundColor: "transparent", margin: "auto",}} + style={{width: 560*scale, height: 560*scale, backgroundColor: theme.palette.backgroundColor, margin: "auto",}} stylesheet={frameworkStyle} boxSelectionEnabled={false} panningEnabled={false} diff --git a/frontend/src/components/Appsearch.jsx b/frontend/src/components/Appsearch.jsx index 40af3e48..ee8f22b8 100644 --- a/frontend/src/components/Appsearch.jsx +++ b/frontend/src/components/Appsearch.jsx @@ -1,14 +1,25 @@ import React, { useState, useEffect } from 'react'; import ReactGA from 'react-ga4'; -import { useTheme } from '@material-ui/core/styles'; +import theme from '../theme'; +//import { useTheme } from '@material-ui/core/styles'; import {Link} from 'react-router-dom'; import { useAlert } from "react-alert"; -import { Search as SearchIcon, CloudQueue as CloudQueueIcon, Code as CodeIcon } from '@material-ui/icons'; +import { Search as SearchIcon, CloudQueue as CloudQueueIcon, Code as CodeIcon } from '@mui/icons-material'; //import algoliasearch from 'algoliasearch/lite'; import algoliasearch from 'algoliasearch'; import { InstantSearch, connectSearchBox, connectHits } from 'react-instantsearch-dom'; -import { Grid, Paper, TextField, ButtonBase, InputAdornment, Typography, Button, Tooltip} from '@material-ui/core'; +import { + Grid, + Paper, + TextField, + ButtonBase, + InputAdornment, + Typography, + Button, + Tooltip +} from '@mui/material'; + import aa from 'search-insights' const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e5240") const Appsearch = props => { @@ -18,7 +29,7 @@ const Appsearch = props => { const alert = useAlert(); const rowHandler = maxRows === undefined || maxRows === null ? 50 : maxRows const xs = parsedXs === undefined || parsedXs === null ? 12 : parsedXs - const theme = useTheme(); + //const theme = useTheme(); //const [apps, setApps] = React.useState([]); //const [filteredApps, setFilteredApps] = React.useState([]); const [formMail, setFormMail] = React.useState(""); diff --git a/frontend/src/components/EditWorkflow.jsx b/frontend/src/components/EditWorkflow.jsx index f4a2b6e0..f9aacdde 100644 --- a/frontend/src/components/EditWorkflow.jsx +++ b/frontend/src/components/EditWorkflow.jsx @@ -1,7 +1,7 @@ import React, { useEffect, useContext } from "react"; import theme from '../theme.jsx'; import { isMobile } from "react-device-detect" -import ChipInput from "material-ui-chip-input"; +import { MuiChipsInput } from "mui-chips-input"; import UsecaseSearch from "../components/UsecaseSearch.jsx" import dayjs from 'dayjs'; @@ -38,7 +38,7 @@ import { FormControl, FormLabel, -} from "@material-ui/core"; +} from "@mui/material"; import { DatePicker, @@ -52,7 +52,7 @@ import { ExpandMore as ExpandMoreIcon, Publish as PublishIcon, OpenInNew as OpenInNewIcon, -} from "@material-ui/icons"; +} from "@mui/icons-material"; const EditWorkflow = (props) => { const { globalUrl, workflow, setWorkflow, modalOpen, setModalOpen, showUpload, usecases, setNewWorkflow, appFramework, isEditing, userdata, } = props @@ -260,7 +260,7 @@ const EditWorkflow = (props) => { />
- { const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, homePage, userdata, serverside, } = props; - const theme = useTheme(); + //const theme = useTheme(); const alert = useAlert() @@ -519,6 +521,7 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho } // Handle top bar or something + const defaultTop = 7 const loginTextBrowser = !isLoggedIn ?
@@ -669,7 +672,7 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho
: -
+
@@ -691,9 +694,9 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho
{/* - + */} - Workflows + Workflows
@@ -703,7 +706,7 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho {/* */} - Apps + Apps
@@ -720,7 +723,7 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho {/* */} - Docs + Docs
@@ -1029,16 +1032,16 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho const loadedCheck =
- {loginTextBrowser} + {loginTextBrowser} - {loginTextMobile} + {loginTextMobile}
//
return ( -
- {loadedCheck} +
+ {loadedCheck}
) } diff --git a/frontend/src/components/Oauth2Auth.jsx b/frontend/src/components/Oauth2Auth.jsx index 2b2996cc..27659be3 100755 --- a/frontend/src/components/Oauth2Auth.jsx +++ b/frontend/src/components/Oauth2Auth.jsx @@ -1,6 +1,6 @@ import React, { useRef, useState, useEffect, useLayoutEffect } from "react"; import { useParams, useNavigate, Link } from "react-router-dom"; -import { useTheme } from "@material-ui/core/styles"; +//import { useTheme } from "@material-ui/core/styles"; import theme from '../theme.jsx'; import { useAlert } from "react-alert"; @@ -38,7 +38,8 @@ import { CircularProgress, Switch, Fade, -} from "@material-ui/core"; +} from "@mui/material"; + import { LockOpen as LockOpenIcon, SupervisorAccount as SupervisorAccountIcon, diff --git a/frontend/src/components/OrgHeader.jsx b/frontend/src/components/OrgHeader.jsx index 9b4a344d..3b5a091a 100644 --- a/frontend/src/components/OrgHeader.jsx +++ b/frontend/src/components/OrgHeader.jsx @@ -1,17 +1,23 @@ import React, { useEffect } from "react"; -import { makeStyles } from "@material-ui/styles"; -import { useTheme } from "@material-ui/core/styles"; +import theme from "../theme"; +import { makeStyles } from "@mui/styles"; + +import { + Tooltip, + Grid, + Button, + TextField, + Typography, + IconButton, +} from "@mui/material"; + +import { + ExpandLess as ExpandLessIcon, + ExpandMore as ExpandMoreIcon, + Save as SaveIcon, +} from "@mui/icons-material"; -import Tooltip from "@material-ui/core/Tooltip"; -import Grid from "@material-ui/core/Grid"; -import Button from "@material-ui/core/Button"; -import TextField from "@material-ui/core/TextField"; -import Typography from "@material-ui/core/Typography"; import { useAlert } from "react-alert"; -import IconButton from "@material-ui/core/IconButton"; -import ExpandLessIcon from "@material-ui/icons/ExpandLess"; -import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; -import SaveIcon from "@material-ui/icons/Save"; const useStyles = makeStyles({ notchedOutline: { @@ -33,7 +39,6 @@ const OrgHeader = (props) => { handleEditOrg, } = props; - const theme = useTheme(); const alert = useAlert(); const classes = useStyles(); diff --git a/frontend/src/components/Priorities.jsx b/frontend/src/components/Priorities.jsx index f0a61a3a..86215b6f 100644 --- a/frontend/src/components/Priorities.jsx +++ b/frontend/src/components/Priorities.jsx @@ -9,7 +9,7 @@ import { Grid, Card, Switch, -} from "@material-ui/core"; +} from "@mui/material"; import Priority from "../components/Priority.jsx"; import { useAlert } from "react-alert"; diff --git a/frontend/src/components/Priority.jsx b/frontend/src/components/Priority.jsx index 15f71754..a4f93729 100644 --- a/frontend/src/components/Priority.jsx +++ b/frontend/src/components/Priority.jsx @@ -10,7 +10,7 @@ import { Button, Grid, Card, -} from "@material-ui/core"; +} from "@mui/material"; // import magic wand icon from material ui icons import { @@ -69,7 +69,7 @@ const Priority = (props) => { return ( -
+
{priority.type === "usecase" || priority.type == "apps" ? : null} @@ -102,7 +102,7 @@ const Priority = (props) => { }
- {priority.active === true ?
- -
- -
diff --git a/frontend/src/views/Admin.jsx b/frontend/src/views/Admin.jsx index b7f42b03..0befde05 100755 --- a/frontend/src/views/Admin.jsx +++ b/frontend/src/views/Admin.jsx @@ -1,16 +1,14 @@ import React, { useState, useEffect } from "react"; -import { makeStyles } from "@material-ui/styles"; +import theme from "../theme.jsx"; +import { makeStyles } from "@mui/styles"; + import { useNavigate, Link } from "react-router-dom"; import countries from "../components/Countries.jsx"; import CodeEditor from "../components/ShuffleCodeEditor.jsx"; import getLocalCodeData from "../components/ShuffleCodeEditor.jsx"; import CacheView from "../components/CacheView.jsx"; -import theme from "../theme.jsx"; -import AddIcon from "@mui/icons-material/Add"; -import ClearIcon from '@mui/icons-material/Clear'; -import StorageIcon from '@mui/icons-material/Storage'; -//import ToggleButton from '@mui/material/ToggleButton'; + import { FormControl, InputLabel, @@ -45,19 +43,21 @@ import { DialogContent, CircularProgress, Box, - InputAdornment, -} from "@material-ui/core"; - -import { Autocomplete } from "@mui/material"; + InputAdornment, + Autocomplete +} from "@mui/material"; import { + Add as AddIcon, + Clear as ClearIcon, + Storage as StorageIcon, Edit as EditIcon, FileCopy as FileCopyIcon, SelectAll as SelectAllIcon, OpenInNew as OpenInNewIcon, CloudDownload as CloudDownloadIcon, Description as DescriptionIcon, - Polymer as PolymerIcon, + Polyline as PolylineIcon, CheckCircle as CheckCircleIcon, Close as CloseIcon, Apps as AppsIcon, @@ -66,13 +66,14 @@ import { Cached as CachedIcon, AccessibilityNew as AccessibilityNewIcon, Lock as LockIcon, - Eco as EcoIcon, Schedule as ScheduleIcon, Cloud as CloudIcon, Business as BusinessIcon, - Visibility as VisibilityIcon, - VisibilityOff as VisibilityOffIcon, -} from "@material-ui/icons"; + Visibility as VisibilityIcon, + VisibilityOff as VisibilityOffIcon, + + FmdGood as FmdGoodIcon, +} from "@mui/icons-material"; import { useAlert } from "react-alert"; import Dropzone from "../components/Dropzone.jsx"; @@ -2199,7 +2200,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user primary: "Workflows", secondary: "", active: true, - icon: , + icon: , }, { primary: "Apps", @@ -2753,7 +2754,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user item.usage === null ? 0 : item.usage, data_collection: "None", active: item.active, - icon: , + icon: , }; return ( @@ -4356,7 +4357,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user - + Environments /> diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index f88ae850..c14260dd 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -2,26 +2,21 @@ import React, { useState, useEffect, useLayoutEffect } from "react"; import ReactDOM from "react-dom" +import theme from "../theme.jsx"; import { useInterval } from "react-powerhooks"; -import { makeStyles, useTheme } from "@material-ui/core/styles"; +import { makeStyles, } from "@mui/styles"; import { v4 as uuidv4 } from "uuid"; import { useNavigate, 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"; +import { NestedMenuItem } from 'mui-nested-menu'; import ReactMarkdown from "react-markdown"; import { useAlert } from "react-alert"; -import theme from '../theme.jsx'; import { isMobile } from "react-device-detect" import aa from 'search-insights' import Drift from "react-driftjs"; -//import { Cron } from 'react-js-cron'; -//import 'react-js-cron/dist/styles.css' - - import { InstantSearch, Configure, connectSearchBox, connectHits, Index } from 'react-instantsearch-dom'; import algoliasearch from 'algoliasearch/lite'; @@ -67,11 +62,9 @@ import { ListItemText, ListItemAvatar, Badge, -} from "@material-ui/core"; - -import { AvatarGroup, -} from "@mui/material" + Autocomplete, +} from "@mui/material"; import { Folder as FolderIcon, @@ -87,7 +80,6 @@ import { ArrowLeft as ArrowLeftIcon, Cached as CachedIcon, DirectionsRun as DirectionsRunIcon, - Polymer as PolymerIcon, FormatListNumbered as FormatListNumberedIcon, PlayArrow as PlayArrowIcon, AspectRatio as AspectRatioIcon, @@ -109,28 +101,26 @@ import { Edit as EditIcon, Send as SendIcon, Restore as RestoreIcon, -} from "@material-ui/icons"; - -import { Preview as PreviewIcon, ContentCopy as ContentCopyIcon, Circle as CircleIcon, SquareFoot as SquareFootIcon, AutoFixHigh as AutoFixHighIcon, -} from '@mui/icons-material'; -import Autocomplete from "@material-ui/lab/Autocomplete"; + Polyline as PolylineIcon, +} from "@mui/icons-material"; + import * as cytoscape from "cytoscape"; import * as edgehandles from "cytoscape-edgehandles"; -import * as clipboard from "cytoscape-clipboard"; +//import * as clipboard from "cytoscape-clipboard"; +//import undoRedo from "cytoscape-undo-redo"; +//import cxtmenu from "cytoscape-cxtmenu"; import CytoscapeComponent from "react-cytoscapejs"; -import undoRedo from "cytoscape-undo-redo"; import Draggable from "react-draggable"; import cytoscapestyle from "../defaultCytoscapeStyle.jsx"; -import cxtmenu from "cytoscape-cxtmenu"; import { validateJson, GetIconInfo } from "./Workflows.jsx"; import { GetParsedPaths } from "./Apps.jsx"; @@ -236,9 +226,9 @@ const inputColor = "#383B40"; // http://apps.cytoscape.org/apps/yfileslayoutalgorithms cytoscape.use(edgehandles); -cytoscape.use(clipboard); -cytoscape.use(undoRedo); -cytoscape.use(cxtmenu); +//cytoscape.use(clipboard); +//cytoscape.use(undoRedo); +//cytoscape.use(cxtmenu); // Adds specific text to items //import popper from 'cytoscape-popper'; @@ -403,9 +393,6 @@ const AngularWorkflow = (defaultprops) => { props.match = {} props.match.params = params - //const theme = useTheme(); - - var to_be_copied = ""; const [firstrequest, setFirstrequest] = React.useState(true); const [cystyle] = useState(cytoscapestyle); @@ -12257,7 +12244,7 @@ const AngularWorkflow = (defaultprops) => { margin: "0px 0px 0px 0px", }} > - + Workflows diff --git a/frontend/src/views/AppCreator.jsx b/frontend/src/views/AppCreator.jsx index eab88472..26ad2553 100755 --- a/frontend/src/views/AppCreator.jsx +++ b/frontend/src/views/AppCreator.jsx @@ -45,7 +45,7 @@ import { import { v4 as uuidv4 } from "uuid"; import { Link, useParams } from "react-router-dom"; import YAML from "yaml"; -import ChipInput from "material-ui-chip-input"; +import { MuiChipsInput } from "mui-chips-input"; import { useAlert } from "react-alert"; import words from "shellwords"; @@ -2925,7 +2925,7 @@ const AppCreator = (defaultprops) => { > Scopes for Oauth2 - { })}

Tags

- { style={{ backgroundColor: inputColor, borderRadius: 5 }} InputProps={{ style: { - color: "white", - minHeight: "50px", - marginLeft: "5px", - maxWidth: "95%", - fontSize: "1em", - borderRadius: 5, }, }} disabled={ diff --git a/frontend/src/views/GettingStarted.jsx b/frontend/src/views/GettingStarted.jsx index 9324e159..fb96e671 100644 --- a/frontend/src/views/GettingStarted.jsx +++ b/frontend/src/views/GettingStarted.jsx @@ -69,7 +69,7 @@ import Dropzone from "../components/Dropzone.jsx"; import { useNavigate, Link, useParams } from "react-router-dom"; import { useAlert } from "react-alert"; -import ChipInput from "material-ui-chip-input"; +import { MuiChipsInput } from "mui-chips-input"; import { v4 as uuidv4 } from "uuid"; const inputColor = "#383B40"; @@ -1930,7 +1930,7 @@ const GettingStarted = (props) => { margin="dense" fullWidth /> - {
- { }} PaperProps={{ style: { - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, color: "white", minWidth: 500, padding: 30, @@ -835,7 +827,7 @@ const Workflows = (props) => { }} PaperProps={{ style: { - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, color: "white", minWidth: 500, padding: 50, @@ -892,7 +884,7 @@ const Workflows = (props) => { }} PaperProps={{ style: { - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, color: "white", minWidth: 500, }, @@ -1253,7 +1245,7 @@ const Workflows = (props) => { width: "100%", height: "250px", color: "white", - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, display: "flex", flexDirection: "column", }; @@ -1271,7 +1263,7 @@ const Workflows = (props) => { overflow: "hidden", width: "100%", color: "white", - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, padding: "12px 12px 0px 15px", borderRadius: 5, display: "flex", @@ -1283,7 +1275,7 @@ const Workflows = (props) => { height: "auto", color: "white", margin: "10px", - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, }; const workflowActionStyle = { @@ -1603,7 +1595,7 @@ const Workflows = (props) => { const innerColor = "rgba(255,255,255,0.3)"; const setupPaperStyle = { minHeight: paperAppStyle.minHeight, - maxWidth: "100%", + maxWidth: "100%", minWidth: paperAppStyle.width, color: innerColor, padding: paperAppStyle.padding, @@ -1710,7 +1702,7 @@ const Workflows = (props) => { }} > { event.stopPropagation() ReactDOM.unstable_batchedUpdates(() => { @@ -1734,7 +1726,7 @@ const Workflows = (props) => { {"Edit details"} { setSelectedWorkflow(data); setPublishModalOpen(true); @@ -1745,7 +1737,7 @@ const Workflows = (props) => { {"Publish Workflow"} { copyWorkflow(data); setOpen(false); @@ -1755,7 +1747,7 @@ const Workflows = (props) => { {"Duplicate Workflow"} - {/*= 0} style={{backgroundColor: inputColor, color: "white"}} onClick={() => { + {/*= 0} style={{backgroundColor: theme.palette.inputColor, color: "white"}} onClick={() => { //copyWorkflow(data) //setOpen(false) }} key={"duplicate"}> @@ -1763,7 +1755,7 @@ const Workflows = (props) => { {"Copy to Child Org"} */} { setExportModalOpen(true); @@ -1817,7 +1809,7 @@ const Workflows = (props) => { {"Export Workflow"} { setDeleteModalOpen(true); setSelectedWorkflowId(data.id); @@ -1909,7 +1901,7 @@ const Workflows = (props) => { } return ( -
+
{selectedCategory !== "" ? @@ -2704,7 +2696,7 @@ const Workflows = (props) => { }} PaperProps={{ style: { - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, color: "white", minWidth: isMobile ? "90%" : "800px", maxWidth: isMobile ? "90%" : "800px", @@ -2760,7 +2752,7 @@ const Workflows = (props) => { fullWidth />
- { {isMobile ? null :
- { {usecases.map((usecase, index) => { //console.log(usecase) const percentDone = usecase.matches.length > 0 ? parseInt(usecase.matches.length/usecase.list.length*100) : 0 - console.log("Usecase Matches: ", usecase.matches, ", Percent: ", percentDone) + //console.log("Usecase Matches: ", usecase.matches, ", Percent: ", percentDone) return ( { } return ( - - {returnData} - + + {/**/} + {returnData} + {/**/} + ); })}
@@ -3500,12 +3494,12 @@ const Workflows = (props) => { /> : null} -
+
{view === "grid" ? ( - + {/**/} - + {/**/} {filteredWorkflows.map((data, index) => { // Shouldn't be a part of this list @@ -3524,11 +3518,13 @@ const Workflows = (props) => { } return ( - + + {/**/} - + {/**/} + ) })} @@ -3613,7 +3609,7 @@ const Workflows = (props) => { onClose={() => {}} PaperProps={{ style: { - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, color: "white", minWidth: "800px", minHeight: "320px", @@ -3640,7 +3636,7 @@ const Workflows = (props) => { Repository (supported: github, gitlab, bitbucket) {
{
{ fullWidth /> { }} PaperProps={{ style: { - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, color: "white", minWidth: 560, minHeight: 415, From bb8b14be64a194f23ac0055075b3a5b1ed24fb01 Mon Sep 17 00:00:00 2001 From: Frikky Date: Tue, 15 Aug 2023 21:58:00 +0200 Subject: [PATCH 04/15] Fixed most of the textfield and button problems from mui 18. Next is autocomplete --- frontend/src/components/EditWorkflow.jsx | 93 ++++--- frontend/src/theme.jsx | 3 +- frontend/src/views/AngularWorkflow.jsx | 319 ++++++++--------------- frontend/src/views/Workflows.jsx | 2 +- 4 files changed, 158 insertions(+), 259 deletions(-) diff --git a/frontend/src/components/EditWorkflow.jsx b/frontend/src/components/EditWorkflow.jsx index f9aacdde..41bdffea 100644 --- a/frontend/src/components/EditWorkflow.jsx +++ b/frontend/src/components/EditWorkflow.jsx @@ -26,6 +26,7 @@ import { Typography, Zoom, CircularProgress, + Drawer, Dialog, DialogTitle, DialogActions, @@ -58,6 +59,7 @@ const EditWorkflow = (props) => { const { globalUrl, workflow, setWorkflow, modalOpen, setModalOpen, showUpload, usecases, setNewWorkflow, appFramework, isEditing, userdata, } = props const [_, setUpdate] = React.useState(""); // Used for rendering, don't remove + const [submitLoading, setSubmitLoading] = React.useState(false); const [showMoreClicked, setShowMoreClicked] = React.useState(false); const [innerWorkflow, setInnerWorkflow] = React.useState(workflow) @@ -144,18 +146,17 @@ const EditWorkflow = (props) => { var total_count = 0 return ( - { setModalOpen(false); }} PaperProps={{ style: { - backgroundColor: theme.palette.surfaceColor, color: "white", minWidth: isMobile ? "90%" : 550, maxWidth: isMobile ? "90%" : 550, - minHeight: 400, + minHeight: 400, //minWidth: isMobile ? "90%" : newWorkflow === true ? 1000 : 550, //maxWidth: isMobile ? "90%" : newWorkflow === true ? 1000 : 550, }, @@ -220,11 +221,11 @@ const EditWorkflow = (props) => { -
+
{ - setName(event.target.value) - }} + onChange={(event) => { + setName(event.target.value) + }} InputProps={{ style: { color: "white", @@ -261,7 +262,7 @@ const EditWorkflow = (props) => {
{ color="primary" fullWidth value={newWorkflowTags} + onChange={(chip) => { + console.log("Chip: ", chip) + //newWorkflowTags.push(chip); + setNewWorkflowTags(chip); + }} onAdd={(chip) => { newWorkflowTags.push(chip); setNewWorkflowTags(newWorkflowTags); @@ -486,41 +492,48 @@ const EditWorkflow = (props) => { -
+ ) } diff --git a/frontend/src/theme.jsx b/frontend/src/theme.jsx index e9da742d..ef91194b 100644 --- a/frontend/src/theme.jsx +++ b/frontend/src/theme.jsx @@ -17,8 +17,8 @@ const theme = createTheme(adaptV4Theme({ secondary: "rgba(255,255,255,0.7)", }, type: "dark", - surfaceColor: "#27292d", inputColor: "#383B40", + surfaceColor: "#27292d", platformColor: "#1c1c1d", backgroundColor: "#1a1a1a", borderRadius: 5, @@ -34,6 +34,7 @@ const theme = createTheme(adaptV4Theme({ borderRadius: 5, }, innerTextfieldStyle: { + // Removed since upgrading to mui 18 //color: "white", //minHeight: 50, //marginLeft: "5px", diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index c14260dd..f5ccd244 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -22,6 +22,8 @@ import algoliasearch from 'algoliasearch/lite'; import { Zoom, + Fade, + Avatar, Popover, TextField, @@ -46,7 +48,6 @@ import { IconButton, Menu, Input, - Fade, FormGroup, FormControlLabel, Typography, @@ -221,9 +222,6 @@ export const triggers = [ ]; // is_valid: cloudSyncEnabled || isCloud ? true : false, -const surfaceColor = "#27292D"; -const inputColor = "#383B40"; - // http://apps.cytoscape.org/apps/yfileslayoutalgorithms cytoscape.use(edgehandles); //cytoscape.use(clipboard); @@ -5899,7 +5897,7 @@ const AngularWorkflow = (defaultprops) => { maxWidth: isMobile ? 50 : "100%", marginTop: "5px", color: "white", - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, cursor: "pointer", display: "flex", }; @@ -5912,7 +5910,7 @@ const AngularWorkflow = (defaultprops) => { maxWidth: "100%", marginTop: "5px", color: "white", - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, cursor: "pointer", display: "flex", }; @@ -6014,7 +6012,7 @@ const AngularWorkflow = (defaultprops) => { open={open} PaperProps={{ style: { - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, }, }} onClose={() => { @@ -6024,7 +6022,7 @@ const AngularWorkflow = (defaultprops) => { > { @@ -6050,7 +6048,7 @@ const AngularWorkflow = (defaultprops) => { { @@ -6259,7 +6257,7 @@ const AngularWorkflow = (defaultprops) => { - {isMobile ? null : Variables} + {isMobile ? null : Vars} } style={tabStyle} @@ -6992,10 +6990,6 @@ const AngularWorkflow = (defaultprops) => { style={{ backgroundColor: theme.palette.inputColor, borderRadius: theme.palette.borderRadius, maxWidth: leftBarSize - 20, }} InputProps={{ style: { - color: "white", - fontSize: "1em", - height: 50, - margin: 0, }, startAdornment: ( @@ -7202,18 +7196,13 @@ const AngularWorkflow = (defaultprops) => {
@@ -7254,11 +7243,13 @@ const AngularWorkflow = (defaultprops) => { delay += 75 return ( runDelay ? - + + {/**/}
-
+ {/*
*/} + :
{extraMessage} @@ -7902,16 +7893,11 @@ const AngularWorkflow = (defaultprops) => { var datafield = ( { return ( { if (data.type === "Execution Argument") { @@ -8106,7 +8092,7 @@ const AngularWorkflow = (defaultprops) => { const menuItemStyle = { color: "white", - backgroundColor: inputColor, + backgroundColor: theme.palette.inputColor, }; const conditionsModal = ( @@ -8122,7 +8108,7 @@ const AngularWorkflow = (defaultprops) => { PaperProps={{ style: { pointerEvents: "auto", - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, color: "white", minWidth: isMobile ? "90%" : 800, border: theme.palette.defaultBorder, @@ -8227,7 +8213,7 @@ const AngularWorkflow = (defaultprops) => { anchorEl={variableAnchorEl} PaperProps={{ style: { - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, }, }} onClose={() => { @@ -8460,7 +8446,7 @@ const AngularWorkflow = (defaultprops) => { maxWidth: "100%", marginTop: "5px", color: "white", - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, cursor: "pointer", display: "flex", }; @@ -8571,7 +8557,7 @@ const AngularWorkflow = (defaultprops) => { open={open} PaperProps={{ style: { - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, }, }} onClose={() => { @@ -8580,7 +8566,7 @@ const AngularWorkflow = (defaultprops) => { }} > { duplicateCondition(index); }} @@ -8589,7 +8575,7 @@ const AngularWorkflow = (defaultprops) => { {"Duplicate"} { setOpen(false); deleteCondition(index); @@ -9158,7 +9144,7 @@ const AngularWorkflow = (defaultprops) => {
{ } InputProps={{ style: { - color: "white", - height: 50, - marginLeft: "5px", - maxWidth: "95%", - fontSize: "1em", }, endAdornment: @@ -11121,17 +11040,13 @@ const AngularWorkflow = (defaultprops) => {
{ }} InputProps={{ style: { - color: "white", - marginLeft: "5px", - maxWidth: "95%", - fontSize: "1em", }, }} fullWidth @@ -11178,17 +11093,13 @@ const AngularWorkflow = (defaultprops) => {
{ }} InputProps={{ style: { - color: "white", - marginLeft: "5px", - maxWidth: "95%", - fontSize: "1em", }, }} fullWidth @@ -11213,7 +11124,7 @@ const AngularWorkflow = (defaultprops) => {
{isCloud && workflow.triggers[selectedTriggerIndex].parameters.length > 4 ? {
Name
{ Environment: {
{
{ workflow.triggers[selectedTriggerIndex].parameters[2].value.includes("email") ? ( { ].parameters[2].value.includes("sms") ? ( {
Name
{ setUpdate(Math.random()); }} style={{ - backgroundColor: inputColor, + backgroundColor: theme.palette.inputColor, color: "white", height: 50, }} @@ -12029,7 +11920,7 @@ const AngularWorkflow = (defaultprops) => { return ( {data} @@ -12071,16 +11962,11 @@ const AngularWorkflow = (defaultprops) => {
{
{ id="execution_argument_input_field" style={theme.palette.textFieldStyle} disabled={workflow.public} - InputProps={{ - style: theme.palette.innerTextfieldStyle, - }} color="secondary" placeholder={"Execution Argument"} defaultValue={executionText} @@ -12986,11 +12864,12 @@ const AngularWorkflow = (defaultprops) => { {defaultReturn} : - + + {/**/}
{defaultReturn}
-
+
); //return null; @@ -13316,11 +13195,11 @@ const AngularWorkflow = (defaultprops) => { color: "white", marginBottom: 10, padding: 5, - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, cursor: "pointer", display: "flex", - minHeight: 40, - maxHeight: 40, + minHeight: 50, + maxHeight: 50, }; const parsedExecutionArgument = () => { @@ -13766,7 +13645,6 @@ const AngularWorkflow = (defaultprops) => { overflow: "auto", minWidth: isMobile ? "100%" : 420, maxWidth: isMobile ? "100%" : 420, - backgroundColor: "#1F2023", color: "white", fontSize: 18, zIndex: 10005, @@ -13864,7 +13742,8 @@ const AngularWorkflow = (defaultprops) => { } return ( - + + {/**/}
{
-
+
); })}
) : ( -
There are no executions yet, or they are not loaded.
+
+ + There are no executions yet, or they are not loaded. + + +
)}
) : ( -
+
{ }} />
-

Execution info

+

Details

{ style={{ backgroundColor: "rgba(255,255,255,0.6)", marginTop: 15, - marginBottom: 30, + marginBottom: 20, }} /> {executionData.results !== undefined && @@ -14241,14 +14136,14 @@ const AngularWorkflow = (defaultprops) => { executionData.status !== "FAILURE" && executionData.status !== "WAITING" && !(executionData.results === undefined || executionData.results === null || (executionData.results.length === 0 && executionData.status === "EXECUTING")) ? ( -
- { - console.log(environments, defaultEnvironmentIndex, nonskippedResults) - }} /> +
+ { + console.log(environments, defaultEnvironmentIndex, nonskippedResults) + }} /> {environments.length > 0 && defaultEnvironmentIndex < environments.length && nonskippedResults.length === 0 && environments[defaultEnvironmentIndex].Name !== "Cloud" ? - No results yet. Is Orborus running for the "{environments[defaultEnvironmentIndex].Name}" environment? Learn more. If the Workflow doesn't start within 30 seconds with Orborus running, contact support: support@shuffler.io + No results yet. Is Orborus running for the "{environments[defaultEnvironmentIndex].Name}" environment? Find out here. If the Workflow doesn't start within 30 seconds with Orborus running, contact support: support@shuffler.io : null}
@@ -14256,12 +14151,12 @@ const AngularWorkflow = (defaultprops) => {
{ - executionData.results === undefined || + executionData.results === undefined || executionData.results === null || (executionData.results.length === 0 && executionData.status === "EXECUTING") ? ( -
- +
+ {environments.length > 0 && defaultEnvironmentIndex < environments.length && nonskippedResults.length === 0 && environments[defaultEnvironmentIndex].Name !== "Cloud" ? No results yet. Is Orborus running for the "{environments[defaultEnvironmentIndex].Name}" environment? Learn more. If the Workflow doesn't start within 30 seconds with Orborus running, contact support: support@shuffler.io @@ -14755,7 +14650,7 @@ const AngularWorkflow = (defaultprops) => { PaperProps={{ style: { pointerEvents: "auto", - backgroundColor: inputColor, + backgroundColor: theme.palette.inputColor, color: "white", minWidth: isMobile ? "90%" : 650, padding: 30, @@ -15066,7 +14961,8 @@ const AngularWorkflow = (defaultprops) => {
) : ( - + + {/**/} { style={{ width: cytoscapeWidth, height: bodyHeight - appBarSize - 5, - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, }} stylesheet={cystyle} boxSelectionEnabled={true} @@ -15089,7 +14985,7 @@ const AngularWorkflow = (defaultprops) => { setCy(incy); }} /> - + )}
{executionModal} @@ -15165,7 +15061,7 @@ const AngularWorkflow = (defaultprops) => { PaperProps={{ style: { pointerEvents: "auto", - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, color: "white", border: theme.palette.defaultBorder, maxWidth: isMobile ? bodyWidth - 100 : 800, @@ -15343,7 +15239,7 @@ const AngularWorkflow = (defaultprops) => { PaperProps={{ style: { pointerEvents: "auto", - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, color: "white", border: theme.palette.defaultBorder, maxWidth: isMobile ? bodyWidth - 100 : "100%", @@ -15632,16 +15528,11 @@ const AngularWorkflow = (defaultprops) => { Name - what is this used for? { ) : ( { open={configureWorkflowModalOpen} PaperProps={{ style: { - backgroundColor: surfaceColor, color: "white", minWidth: 650, border: theme.palette.defaultBorder, @@ -15844,7 +15729,7 @@ const AngularWorkflow = (defaultprops) => { PaperProps={{ style: { pointerEvents: "auto", - backgroundColor: surfaceColor, + backgroundColor: theme.palette.surfaceColor, color: "white", minWidth: 1100, minHeight: 700, @@ -15965,7 +15850,7 @@ const AngularWorkflow = (defaultprops) => {
{ style={{ marginTop: 25, marginBottom: 25, - backgroundColor: inputColor, + backgroundColor: theme.palette.inputColor, }} /> @@ -16721,7 +16606,7 @@ const AngularWorkflow = (defaultprops) => { : null} {/*selectionOpen === true ? -
+
{ overflow: "hidden", width: "100%", color: "white", - backgroundColor: theme.palette.surfaceColor, padding: "12px 12px 0px 15px", borderRadius: 5, display: "flex", boxSizing: "border-box", position: "relative", + backgroundColor: theme.palette.surfaceColor, }; const gridContainer = { From e331d06b8a0dfaaa88b10968a0e6173b65ca64c7 Mon Sep 17 00:00:00 2001 From: Frikky Date: Wed, 16 Aug 2023 00:07:02 +0200 Subject: [PATCH 05/15] Fixed Select and Autocomplete prompts to properly select and work with mui18 --- frontend/src/components/EditWorkflow.jsx | 2 +- frontend/src/components/ParsedAction.jsx | 270 +++++++++++++---------- frontend/src/views/AngularWorkflow.jsx | 114 ++++++---- frontend/src/views/AppCreator.jsx | 8 + frontend/src/views/Workflows.jsx | 3 + 5 files changed, 234 insertions(+), 163 deletions(-) diff --git a/frontend/src/components/EditWorkflow.jsx b/frontend/src/components/EditWorkflow.jsx index 41bdffea..c862f22b 100644 --- a/frontend/src/components/EditWorkflow.jsx +++ b/frontend/src/components/EditWorkflow.jsx @@ -475,7 +475,7 @@ const EditWorkflow = (props) => {
- + -
- ); - - // Requires src or dst as input - // FIXME - use this shit to edit an app or something - //const editButtonFix = (app, apptype) => { - // if (apptype === "src") { - - // } else if (apptype === "dst") { - - // } - //} - - const editSrcApp = (event) => { - // if tmpsrcapp, show RESET (can be an X or something too) - // if reset is clicked, set source app back to the original - setTmpSrcApp(scheduleConfig.appinfo.sourceapp); - - var tmpscheduleConfig = scheduleConfig; - tmpscheduleConfig.appinfo.sourceapp = {}; - - fetch(globalUrl + "/api/v1/schedules/" + props.match.params.key, { - method: "PUT", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - body: JSON.stringify(tmpscheduleConfig), - }) - .then((response) => response.json()) - .then((responseJson) => { - setScheduleConfig({}); - setSrcApp({}); - setSrcAppAction(""); - }) - .catch((error) => { - console.log(error); - }); - }; - - const editDstApp = (event) => { - // if tmpsrcapp, show RESET (can be an X or something too) - // if reset is clicked, set source app back to the original - setTmpDstApp(scheduleConfig.appinfo.destinationapp); - - var tmpscheduleConfig = scheduleConfig; - tmpscheduleConfig.appinfo.destinationapp = {}; - - fetch(globalUrl + "/api/v1/schedules/" + props.match.params.key, { - method: "PUT", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - body: JSON.stringify(tmpscheduleConfig), - }) - .then((response) => response.json()) - .then((responseJson) => { - setScheduleConfig({}); - setDstApp({}); - setDstAppAction(""); - }) - .catch((error) => { - console.log(error); - }); - }; - - const scheduleApp = (app, actiondata) => { - const editButton = - actiondata === "src" ? ( - - ) : ( - - ); - - const configureButton = - actiondata === "src" ? ( - - ) : ( - - ); - - // FIXME - set src vs dst - return ( - - - - - - - {splitter} - - - -
-

{app.name}

-
-
{app.description}
-
- {app.action} -
- {splitter} - -
{editButton}
-
{configureButton}
-
-
-
- ); - }; - - const splitter = ( -
- ); - - const dstDownshift = ( - - {({ - getInputProps, - getItemProps, - getMenuProps, - highlightedIndex, - inputValue, - isOpen, - selectedItem, - }) => ( -
- {renderInput("input", { - fullWidth: true, - InputProps: getInputProps({ - placeholder: "Search destination apps", - }), - })} - -
-
- {isOpen ? ( - - {getSuggestions(inputValue, "input").map( - (suggestion, index) => - renderSuggestion({ - suggestion, - index, - itemProps: getItemProps({ item: suggestion.name }), - highlightedIndex, - selectedItem, - }) - )} - - ) : null} -
- {dstappaction} -
-
- )} -
- ); - - const srcDownshift = ( - - {({ - getInputProps, - getItemProps, - getMenuProps, - highlightedIndex, - inputValue, - isOpen, - selectedItem, - }) => ( -
- {renderInput("output", { - fullWidth: true, - InputProps: getInputProps({ - placeholder: "Search source apps", - }), - })} - -
-
- {isOpen ? ( - - {getSuggestions(inputValue, "output").map( - (suggestion, index) => - renderSuggestion({ - suggestion, - index, - itemProps: getItemProps({ item: suggestion.name }), - highlightedIndex, - selectedItem, - }) - )} - - ) : null} -
- {srcappaction} -
-
- )} -
- ); - - const submitDstApp = (event) => { - var packagedSrc = { - name: dstApp.name, - id: dstApp.id, - description: dstApp.description, - action: dstAppAction, - }; - - var tmpscheduleConfig = scheduleConfig; - - tmpscheduleConfig.appinfo.destinationapp = packagedSrc; - - // Hmm, do this here? Idk - fetch(globalUrl + "/api/v1/schedules/" + props.match.params.key, { - method: "PUT", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - body: JSON.stringify(tmpscheduleConfig), - }) - .then((response) => response.json()) - .then((responseJson) => { - setScheduleConfig({}); - }) - .catch((error) => { - console.log(error); - }); - }; - - const submitSrcApp = (event) => { - var packagedSrc = { - name: srcApp.name, - id: srcApp.id, - description: srcApp.description, - action: srcAppAction, - }; - - var tmpscheduleConfig = scheduleConfig; - - // FIXME - future fred - // - tmpscheduleConfig.appinfo.sourceapp = packagedSrc; - - // Hmm, do this here? Idk - fetch(globalUrl + "/api/v1/schedules/" + props.match.params.key, { - method: "PUT", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - body: JSON.stringify(tmpscheduleConfig), - }) - .then((response) => response.json()) - .then((responseJson) => { - setScheduleConfig({}); - }) - .catch((error) => { - console.log(error); - }); - }; - - const resetDstApp = (event) => { - var tmpscheduleConfig = scheduleConfig; - tmpscheduleConfig.appinfo.destinationapp = tmpDstApp; - - // Hmm, do this here? Idk - fetch(globalUrl + "/api/v1/schedules/" + props.match.params.key, { - method: "PUT", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - body: JSON.stringify(tmpscheduleConfig), - }) - .then((response) => response.json()) - .then((responseJson) => { - setScheduleConfig({}); - setDstApp(tmpSrcApp); - setDstAppAction(tmpDstApp.action); - setTmpDstApp({}); - }) - .catch((error) => { - console.log(error); - }); - }; - - const resetSrcApp = (event) => { - var tmpscheduleConfig = scheduleConfig; - tmpscheduleConfig.appinfo.sourceapp = tmpSrcApp; - - // Hmm, do this here? Idk - fetch(globalUrl + "/api/v1/schedules/" + props.match.params.key, { - method: "PUT", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - body: JSON.stringify(tmpscheduleConfig), - }) - .then((response) => response.json()) - .then((responseJson) => { - setScheduleConfig({}); - setSrcApp(tmpSrcApp); - setSrcAppAction(tmpSrcApp.action); - setTmpSrcApp({}); - }) - .catch((error) => { - console.log(error); - }); - }; - - // Based on some srcthing - const searchGridSrc = ( - - - Choose Source app (FIXME) - clickable - - {splitter} - - - -
{srcDownshift}
-
-
- {splitter} - -
- -
-
- -
-
-
-
- ); - - const searchGridDst = ( - - - Choose Source app (FIXME) - clickable - - {splitter} - - - -
{dstDownshift}
-
-
- {splitter} - -
- -
-
- -
-
-
-
- ); - - const srcField = - Object.getOwnPropertyNames(scheduleConfig).length > 0 && - Object.getOwnPropertyNames(scheduleConfig.appinfo.sourceapp).length > 0 && - scheduleConfig.appinfo.sourceapp.name.length > 0 ? ( -
- - {scheduleApp(scheduleConfig.appinfo.sourceapp, "src")} - -
- ) : ( -
- - {searchGridSrc} - -
- ); - - const dstField = - Object.getOwnPropertyNames(scheduleConfig).length > 0 && - Object.getOwnPropertyNames(scheduleConfig.appinfo.destinationapp).length > - 0 && - scheduleConfig.appinfo.destinationapp.name.length > 0 ? ( -
- - {scheduleApp(scheduleConfig.appinfo.destinationapp, "dst")} - -
- ) : ( -
- - {searchGridDst} - -
- ); - - // Have to use array cus of datastore lol (no map[string]string) - const srcModalData = []; - const buildSrcModal = (event, fieldname) => { - var fieldfound = false; - for (var key in srcModalData) { - if (srcModalData[key]["key"] === fieldname) { - fieldfound = true; - srcModalData[key]["value"] = event.target.value; - break; - } - } - - if (!fieldfound) { - srcModalData.push({ key: fieldname, value: event.target.value }); - } - console.log(srcModalData); - }; - - // FIXME - verify required fields? - const submitSrcConfig = () => { - scheduleConfig.appinfo.sourceapp.config = srcModalData; - setScheduleConfig(scheduleConfig); - setSrcAppConfigOpen(false); - - fetch(globalUrl + "/api/v1/schedules/" + props.match.params.key, { - method: "PUT", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - body: JSON.stringify(scheduleConfig), - }) - .then((response) => response.json()) - .then((responseJson) => { - console.log(responseJson); - }) - .catch((error) => { - console.log(error); - }); - }; - - const dstModalData = []; - const buildDstModal = (event, fieldname) => { - var fieldfound = false; - for (var key in dstModalData) { - if (dstModalData[key]["key"] === fieldname) { - fieldfound = true; - dstModalData[key]["value"] = event.target.value; - break; - } - } - - if (!fieldfound) { - dstModalData.push({ key: fieldname, value: event.target.value }); - } - console.log(dstModalData); - }; - - // FIXME - verify required fields - const submitDstConfig = () => { - scheduleConfig.appinfo.destinationapp.config = dstModalData; - setScheduleConfig(scheduleConfig); - setDstAppConfigOpen(false); - - fetch(globalUrl + "/api/v1/schedules/" + props.match.params.key, { - method: "PUT", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - body: JSON.stringify(scheduleConfig), - }) - .then((response) => response.json()) - .then((responseJson) => { - console.log(responseJson); - }) - .catch((error) => { - console.log(error); - }); - }; - - const dstConfigModal = dstAppConfigOpen ? ( - { - setDstAppConfigOpen(false); - }} - > - Source configuration - - Configure {dstApp.name}'s required fields - {dstAppConfig.map((data) => ( - { - buildDstModal(event, data.name); - }} - autofocus - color="primary" - name="searchtext" - placeholder={data.name} - margin="dense" - id={data.name} - label={data.name} - fullWidth - /> - ))} - - - - - - - ) : null; - - // FIXME - load the actual fields! - const srcConfigModal = srcAppConfigOpen ? ( - { - setSrcAppConfigOpen(false); - }} - > - Source configuration - - Configure {srcApp.name}'s required fields - {srcAppConfig.map((data) => ( - { - buildSrcModal(event, data.name); - }} - autofocus - color="primary" - name="searchtext" - placeholder={data.name} - margin="dense" - id={data.name} - label={data.name} - fullWidth - /> - ))} - - - - - - - ) : null; - - return ( -
- {srcConfigModal} - {dstConfigModal} -
- {srcField} - {dstField} -
- -
{submitButton}
-
{relationshipBody}
-
- ); -}; - -export default EditSchedule; diff --git a/frontend/src/views/EditWebhook.jsx b/frontend/src/views/EditWebhook.jsx deleted file mode 100755 index e1a5d516..00000000 --- a/frontend/src/views/EditWebhook.jsx +++ /dev/null @@ -1,393 +0,0 @@ -import React, { useState, useEffect } from "react"; - -import Button from "@material-ui/core/Button"; -import Paper from "@material-ui/core/Paper"; -import Divider from "@material-ui/core/Divider"; -import Select from "@material-ui/core/Select"; -import MenuItem from "@material-ui/core/MenuItem"; - -import WebhookImage from "../assets/img/webhook.png"; -import KafkaImage from "../assets/img/kafka.png"; - -import EditWorkflow from "./EditWorkflow"; - -const EditWebhook = (props) => { - const { globalUrl, isLoaded } = props; - - // FIXME - //const [webhookData, setWebhookData] = useState(webhooktest) - const [webhookData, setWebhookData] = useState({}); - const [workflows, setWorkflows] = useState([]); - const [firstrequest, setFirstrequest] = React.useState(true); - - const [selectedWorkflows, setSelectedWorkflows] = useState([]); - - const getWorkflows = () => { - fetch(globalUrl + "/api/v1/workflows", { - method: "GET", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for workflows :O!"); - } - return response.json(); - }) - .then((responseJson) => { - setWorkflows(responseJson); - }) - .catch((error) => { - console.log(error); - }); - }; - - const setWebhook = (inputdata) => { - console.log(inputdata); - - fetch(globalUrl + "/api/v1/hooks/" + props.match.params.key, { - method: "PUT", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - body: JSON.stringify(inputdata), - }) - .then((response) => response.json()) - .then((responseJson) => { - console.log(responseJson); - }) - .catch((error) => { - console.log(error); - }); - }; - - const getCurrentWebhook = () => { - fetch(globalUrl + "/api/v1/hooks/" + props.match.params.key, { - method: "GET", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200!"); - window.location.pathname = "webhooks"; - } - return response.json(); - }) - .then((responseJson) => { - if (responseJson.actions === null) { - responseJson.actions = []; - } - - if (responseJson.transforms === null) { - responseJson.transforms = []; - } - - setWebhookData(responseJson); - }) - .catch((error) => { - console.log(error); - //window.location.pathname = "webhooks" - }); - }; - - useEffect(() => { - if (firstrequest) { - setFirstrequest(false); - getCurrentWebhook(); - if (workflows.length <= 0) { - getWorkflows(); - } - } - - // After everything is loaded - if ( - Object.getOwnPropertyNames(webhookData).length > 0 && - webhookData.actions.length > 0 && - workflows.length > 0 && - selectedWorkflows.length === 0 - ) { - // Setting startup actions. making like this in case we want other actions - var tmpActionWorkflows = []; - for (var key in webhookData.actions) { - if (webhookData.actions[key].type === "workflow") { - tmpActionWorkflows.push(webhookData.actions[key]); - } - } - - // Fix duplicates... Meh - var foundWorkflowIds = []; - var tmpWorkflows = []; - for (key in tmpActionWorkflows) { - if (foundWorkflowIds.includes(tmpActionWorkflows[key].id)) { - continue; - } - - for (var subkey in workflows) { - if (tmpActionWorkflows[key].id === workflows[subkey]["id_"]) { - console.log(tmpActionWorkflows[key].id, workflows[subkey]["id_"]); - foundWorkflowIds.push(tmpActionWorkflows[key].id); - tmpWorkflows.push(workflows[subkey]); - break; - } - } - } - - if (tmpWorkflows.length > 0) { - setSelectedWorkflows(tmpWorkflows); - } - } - }); - - const hookPicture = - Object.getOwnPropertyNames(webhookData).length > 0 && - webhookData.type === "webhook" ? ( - webhook - ) : ( - MQ - ); - - const executeHook = (action) => { - fetch( - globalUrl + "/api/v1/hooks/" + props.match.params.key + "/" + action, - { - method: "POST", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - } - ) - .then((response) => response.json()) - .then((responseJson) => { - setWebhookData({}); - }) - .catch((error) => { - console.log(error); - }); - }; - - const headerPaperStyle = { - display: "flex", - maxHeight: "800px", - minHeight: "800px", - margin: "10px 30px 10px 10px", - padding: "10px 5px 5px 5px", - flexDirection: "column", - }; - - // FIXME - add with counter to change the correct one (not just edit) - const addNewWorkflow = (event) => { - // Verify if it already exists in the array. Returns if it exists - for (var key in selectedWorkflows) { - var item = selectedWorkflows[key]; - if (item["id_"] === event.target.value["id_"]) { - return; - } - } - - // FIXME - make this possible for all accounts - if (selectedWorkflows.length === 0) { - console.log("ADD FIRST ITEM FOR SELECTEDWORKFLOWS"); - console.log(event.target.value); - - // Cleanup previous actions - var newActions = []; - if (webhookData.actions.length > 0) { - for (key in webhookData.actions) { - if ( - webhookData.actions[key].type === "" || - webhookData.actions[key].type === undefined - ) { - continue; - } - - newActions.push(webhookData.actions[key]); - } - } - - // FIXME - how to stringify this better hurr - var formattedWorkflow = { - type: "workflow", - name: event.target.value.name, - id: event.target.value.id_, - field: "", - }; - - // FIXME: patch this n - newActions.push(formattedWorkflow); - console.log(newActions); - - webhookData.actions = newActions; - setWebhook(webhookData); - } - - var tmpSelectedWorkflows = [].concat(selectedWorkflows, [ - event.target.value, - ]); - setSelectedWorkflows(tmpSelectedWorkflows); - }; - - // FIXME - // Create a list with + button - // For each, choose the new workflow I wanna add - // Current: JUST ONE - const selectedWorkflowIds = selectedWorkflows.map((data) => { - return data["id_"]; - }); - const availableWorkflows = workflows.filter( - (data) => !selectedWorkflowIds.includes(data["id_"]) - ); - - const WorkflowSelect = (counter) => { - if (selectedWorkflows[counter.counter] === undefined) { - return null; - } - - console.log(selectedWorkflows[0]); - console.log(selectedWorkflows[0]); - console.log(selectedWorkflows[0]); - console.log(selectedWorkflows[counter.counter]); - console.log(selectedWorkflows[counter.counter].name); - return ( -
- Workflow select: - -
- ); - }; - - const extraWorkflow = - workflows.length > 0 && availableWorkflows.length > 0 ? ( - - ) : null; - - const multiWorkflowSelect = - workflows.length > 0 && selectedWorkflows.length > 0 ? ( -
- {selectedWorkflows.map((data, count) => ( - - ))} - {extraWorkflow} -
- ) : ( - - ); - - const headerInfo = - Object.getOwnPropertyNames(webhookData).length > 0 ? ( -
- -
-
{hookPicture}
-
-
-

Name: {webhookData.info.name}

-
-
-
-
- Description: {webhookData.info.description} -
Id: {webhookData.id}
-
Url: {webhookData.info.url}
-
Type: {webhookData.type}
-
Status: {webhookData.status}
-
- CHOOSE ACTIONS: - {multiWorkflowSelect} -
-
- -
-
- -
-
- -
-
-
-
- ) : null; - - // FIXME - needs refresh every time you add a new workflow - const workflowdata = - Object.getOwnPropertyNames(webhookData).length > 0 && - selectedWorkflows.length > 0 ? ( - - ) : null; - - const loadedCheck = isLoaded ? ( -
-
{workflowdata}
-
{headerInfo}
-
- ) : ( -
- ); - - // FIXME: Use this for testing - // : null - return
{loadedCheck}
; -}; - -export default EditWebhook; diff --git a/frontend/src/views/ForgotPassword.jsx b/frontend/src/views/ForgotPassword.jsx deleted file mode 100755 index e4c95013..00000000 --- a/frontend/src/views/ForgotPassword.jsx +++ /dev/null @@ -1,118 +0,0 @@ -/* eslint-disable react/no-multi-comp */ -import React, { useState } from "react"; - -import TextField from "@material-ui/core/TextField"; -import Button from "@material-ui/core/Button"; -import Paper from "@material-ui/core/Paper"; - -const bodyDivStyle = { - margin: "auto", - marginTop: "100px", - width: "500px", -}; - -const ForgotPassword = (props) => { - const { globalUrl, isLoaded, isLoggedIn, surfaceColor, inputColor } = props; - - const boxStyle = { - paddingLeft: "30px", - paddingRight: "30px", - paddingBottom: "30px", - paddingTop: "30px", - backgroundColor: surfaceColor, - }; - - const [username, setUsername] = useState(""); - const [resetInfo, setResetInfo] = useState( - "You will receive an email with instructions shortly." - ); - - const handleValidateForm = () => { - return username.length > 3; - }; - - if (isLoggedIn === true) { - window.location.pathname = "/"; - } - - const onSubmit = (e) => { - e.preventDefault(); - // FIXME - add some check here ROFL - - // Just use this one? - var data = { username: username }; - var baseurl = globalUrl; - var url = baseurl + "/api/v1/passwordresetmail"; - fetch(url, { - method: "POST", - body: JSON.stringify(data), - headers: { - "Content-Type": "application/json; charset=utf-8", - }, - }) - .then((response) => - response.json().then((responseJson) => { - if (responseJson["success"] === false) { - setResetInfo(responseJson["reason"]); - } - }) - ) - .catch((error) => { - setResetInfo("Error in userdata: " + error); - }); - }; - - const onChangeUser = (e) => { - setUsername(e.target.value); - }; - - const data = ( -
- -
-

Password reset

-
- -
-
- -
-
{resetInfo}
-
-
-
- ); - - const loadedCheck = isLoaded ?
{data}
:
; - - return
{loadedCheck}
; -}; - -export default ForgotPassword; diff --git a/frontend/src/views/ForgotPasswordLink.jsx b/frontend/src/views/ForgotPasswordLink.jsx deleted file mode 100755 index 8944deed..00000000 --- a/frontend/src/views/ForgotPasswordLink.jsx +++ /dev/null @@ -1,136 +0,0 @@ -import React, { useState, useEffect } from "react"; - -import Paper from "@material-ui/core/Paper"; -import Button from "@material-ui/core/Button"; - -import TextField from "@material-ui/core/TextField"; - -const bodyDivStyle = { - margin: "auto", - textAlign: "center", - width: "768px", -}; - -const boxStyle = { - flex: "1", - marginLeft: "10px", - marginRight: "10px", - paddingLeft: "30px", - paddingRight: "30px", - paddingBottom: "30px", - paddingTop: "30px", - backgroundColor: "#e8eaf6", - display: "flex", - flexDirection: "column", -}; - -//const tmpdata = { -// "username": "frikky", -// "firstname": "fred", -// "lastname": "ode", -// "title": "topkek", -// "companyname": "company here", -// "email": "your email pls", -// "phone": "PHONE!!", -//} - -// FIXME - add fetch for data fields -// FIXME - remove tmpdata -// FIXME: Use isLoggedIn :) -const Settings = (props) => { - const { globalUrl, isLoaded } = props; - - const [newPassword, setNewPassword] = useState(""); - const [newPassword2, setNewPassword2] = useState(""); - const [passwordFormMessage, setPasswordFormMessage] = useState(""); - - const onPasswordChange = () => { - const data = { - newpassword: newPassword, - newpassword2: newPassword2, - reference: props.match.params.key, - }; - const url = globalUrl + "/api/v1/passwordreset"; - fetch(url, { - mode: "cors", - method: "POST", - body: JSON.stringify(data), - credentials: "include", - crossDomain: true, - withCredentials: true, - headers: { - "Content-Type": "application/json; charset=utf-8", - }, - }) - .then((response) => - response.json().then((responseJson) => { - if (responseJson["success"] === false) { - setPasswordFormMessage(responseJson["reason"]); - } - }) - ) - .catch((error) => { - setPasswordFormMessage("Something went wrong."); - }); - }; - - // This should "always" have data - useEffect(() => {}); - - // Random names for type & autoComplete. Didn't research :^) - const landingpageData = ( -
- -

Password Reset

-
- setNewPassword(e.target.value)} - /> - setNewPassword2(e.target.value)} - /> -
- -

{passwordFormMessage}

-
-
- ); - - const loadedCheck = isLoaded ? ( -
{landingpageData}
- ) : ( -
- ); - - return
{loadedCheck}
; -}; -export default Settings; diff --git a/frontend/src/views/GettingStarted.jsx b/frontend/src/views/GettingStarted.jsx index fb96e671..caba5b97 100644 --- a/frontend/src/views/GettingStarted.jsx +++ b/frontend/src/views/GettingStarted.jsx @@ -58,9 +58,7 @@ import { CloudDownload as CloudDownloadIcon, } from "@mui/icons-material"; -//import {Search as SearchIcon, ArrowUpward as ArrowUpwardIcon, Visibility as VisibilityIcon, Done as DoneIcon, Close as CloseIcon, Error as ErrorIcon, FindReplace as FindreplaceIcon, ArrowLeft as ArrowLeftIcon, Cached as CachedIcon, DirectionsRun as DirectionsRunIcon, Add as AddIcon, Polymer as PolymerIcon, FormatListNumbered as FormatListNumberedIcon, Create as CreateIcon, PlayArrow as PlayArrowIcon, AspectRatio as AspectRatioIcon, MoreVert as MoreVertIcon, Apps as AppsIcon, Schedule as ScheduleIcon, FavoriteBorder as FavoriteBorderIcon, Pause as PauseIcon, Delete as DeleteIcon, AddCircleOutline as AddCircleOutlineIcon, Save as SaveIcon, KeyboardArrowLeft as KeyboardArrowLeftIcon, KeyboardArrowRight as KeyboardArrowRightIcon, ArrowBack as ArrowBackIcon, Settings as SettingsIcon, LockOpen as LockOpenIcon, ExpandMore as ExpandMoreIcon, VpnKey as VpnKeyIcon} from '@material-ui/icons'; -//https://next.material-ui.com/components/material-icons/ import { DataGrid, GridToolbar } from "@mui/x-data-grid"; //import JSONPretty from 'react-json-pretty'; diff --git a/frontend/src/views/Introduction.jsx b/frontend/src/views/Introduction.jsx deleted file mode 100755 index e94295f3..00000000 --- a/frontend/src/views/Introduction.jsx +++ /dev/null @@ -1,221 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { Link, useParams } from "react-router-dom"; -import theme from '../theme.jsx'; - -import Grid from "@material-ui/core/Grid"; -import Card from "@material-ui/core/Card"; -import CardActionArea from "@material-ui/core/CardActionArea"; -import CardContent from "@material-ui/core/CardContent"; -import CardHeader from "@material-ui/core/CardHeader"; -import Typography from "@material-ui/core/Typography"; -import Button from "@material-ui/core/Button"; - -const Workflows = (defaultprops) => { - const { globalUrl, isLoggedIn, isLoaded } = defaultprops; - - 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([]); - - const viewdata1 = [ - { - title: "General", - content: "Learn about our ticketing solutions", - subitems: [ - { - name: "Search", - subtitle: "Search for anything, anywhere", - }, - { - name: "Message", - subtitle: "Read and send messages", - }, - { - name: "Parse emails", - subtitle: "what", - }, - ], - }, - { - title: "Ticketing", - subitems: [ - { - name: "Search", - subtitle: "Search for anything, anywhere", - }, - { - name: "Message", - subtitle: "Read and send messages", - }, - { - name: "Parse emails", - subtitle: "what", - }, - ], - }, - { - title: "Threat intel", - subitems: [ - { - name: "Search", - subtitle: "Search for anything, anywhere", - }, - { - name: "Message", - subtitle: "Read and send messages", - }, - { - name: "Parse emails", - subtitle: "what", - }, - ], - }, - ]; - - if (firstrequest) { - setFirstrequest(false); - if (props.match.params.key) { - console.log("PROPS: ", props.match.params.key); - const viewitem = viewdata1.find( - (item) => - item.title.toLowerCase() === props.match.params.key.toLowerCase() - ); - if (viewitem !== undefined && viewitem !== null) { - setCurView(1); - //setSelectedItem(viewitem) - } - } - } - - const cardContentStyle = { - height: "100%", - width: "100%", - padding: 40, - }; - - const outerGridView = { - width: "100%", - marginTop: 15, - }; - - const paperStyle = { - height: 300, - color: "white", - backgroundColor: theme.palette.surfaceColor, - color: "white", - cursor: "pointer", - display: "flex", - textAlign: "center", - }; - - const HandleSelection = (data) => { - const [selected, setSelected] = useState(false); - - var baseStyle = JSON.parse(JSON.stringify(paperStyle)); - if (selected) { - baseStyle.backgroundColor = "white"; - baseStyle.color = "black"; - } - - return ( - { - console.log(selectedItems); - if (selected) { - const index = selectedItems.findIndex( - (item) => item.title === data.title - ); - if (index >= 0) { - selectedItems.splice(index, 1); - setSelectedItems(selectedItems); - } - } else { - selectedItems.push(data); - setSelectedItems(selectedItems); - } - - setSelected(!selected); - - //setCurView(1) - //setSelectedItem(data) - //window.location.pathname += "/"+data.title.toLowerCase() - }} - > - - - - {data.title} - - - - - ); - }; - - const view1 = - curView === 0 ? ( -
- What are you interested in? - - {viewdata1.map((data) => { - return HandleSelection(data); - })} - - {/* - - */} -
- ) : null; - - const view2 = - curView === 1 ? ( -
- Step 2. - {/* - - {selectedItem.subitems === undefined ? null : - selectedItem.subitems.map(data => { - return ( - - - - - - {data.name} - - - {data.subtitle} - - - - - - ) - })} - - */} -
- ) : null; - - const baseView = ( -
- {view1} - {view2} -
- ); - - return
{baseView}
; -}; - -export default Workflows; diff --git a/frontend/src/views/Landingpage.jsx b/frontend/src/views/Landingpage.jsx deleted file mode 100755 index a0de1eee..00000000 --- a/frontend/src/views/Landingpage.jsx +++ /dev/null @@ -1,207 +0,0 @@ -import React from "react"; - -import Paper from "@material-ui/core/Paper"; -import Button from "@material-ui/core/Button"; -import Divider from "@material-ui/core/Divider"; -import { BrowserView, MobileView } from "react-device-detect"; -import { - Schedule as ScheduleIcon, - Web as WebIcon, - AccountTree as AccountTreeIcon, -} from "@mui/icons-material"; - -const bodyDivStyle = { - margin: "auto", - marginTop: "75px", - textAlign: "center", - width: "1100px", -}; - -const surfaceColor = "#27292D"; -const boxStyle = { - flex: "1", - marginLeft: "10px", - marginRight: "10px", - height: "400px", - //backgroundColor: "#e8eaf6", - backgroundColor: surfaceColor, - textAlign: "center", - display: "flex", - flexDirection: "column", -}; - -const bodyTextStyle = { - color: "#ffffff", -}; - -const hrefStyle = { - color: "black", - textDecoration: "none", -}; - -// Should be different if logged in :| -const LandingPage = (props) => { - const { isLoaded } = props; - - const textColor = "#8899A6"; - const iconColor = "#1DA1F2"; - const iconSize = "8em"; - const GridLayout = (header, description, link, icon) => { - return ( - - -
-

{header}

-
- -
- {description} -
-
{icon}
- -
-
Learn more
-
-
-
- ); - }; - - const listitems = [ - GridLayout( - "Simple integrations", - "Easily use others' or create your own integration", - "/docs/apps", - - ), - GridLayout( - "Workflows", - "Access the power of automation within minutes, whether its on premise or in the cloud", - "/docs/workflows", - - ), - GridLayout( - "Realtime actions", - "Beat the clock by leveraging our realtime triggers", - "/docs/triggers", - - ), - ]; - - // The actual landing page - // {"logo"} - const landingpageDataBrowser = ( -
-
-

Shuffle

-

- A general automation solution for Infosec and IT Professionals -

-
- - - - - - -
- {listitems.map((item) => { - return
{item}
; - })} -
-
- ); - - const landingpageDataMobile = ( -
-
-

Shuffle

-

A general automation solution for Infosec and IT Professionals

- - - -
-
-
{listitems[0]}
-
{listitems[1]}
-
- {listitems[2]} -
- -
-
- ); - - // Reroute if the user is logged in - // const landingSite = isLoggedIn ? :
{landingpageData}
- const landingSite =
{landingpageDataBrowser}
; - - const loadedCheck = isLoaded ? ( -
- {landingSite} - {landingpageDataMobile} -
- ) : ( -
- ); - - return
{loadedCheck}
; -}; -export default LandingPage; diff --git a/frontend/src/views/LandingpageNew.jsx b/frontend/src/views/LandingpageNew.jsx deleted file mode 100755 index c859beee..00000000 --- a/frontend/src/views/LandingpageNew.jsx +++ /dev/null @@ -1,531 +0,0 @@ -import React, { useState } from "react"; - -import Paper from "@material-ui/core/Paper"; -import Card from "@material-ui/core/Card"; -import CardActionArea from "@material-ui/core/CardActionArea"; -import CardMedia from "@material-ui/core/CardMedia"; -import CardContent from "@material-ui/core/CardContent"; -import CardActions from "@material-ui/core/CardActions"; -import Button from "@material-ui/core/Button"; -import Divider from "@material-ui/core/Divider"; -import Grid from "@material-ui/core/Grid"; -import { BrowserView, MobileView } from "react-device-detect"; - -import { - Schedule as ScheduleIcon, - Web as WebIcon, - AccountTree as AccountTreeIcon, - Info as InfoIcon, - ArrowForward as ArrowForwardIcon, - Create as CreateIcon, -} from "@mui/icons-material"; - -const bodyDivStyle = { - margin: "auto", -}; - -const surfaceColor = "#27292D"; -const boxStyle = { - flex: "1", - marginLeft: "10px", - marginRight: "10px", - height: "400px", - //backgroundColor: "#e8eaf6", - backgroundColor: surfaceColor, - textAlign: "center", - display: "flex", - flexDirection: "column", -}; - -const bodyTextStyle = { - color: "#ffffff", -}; - -const hrefStyle = { - color: "inherit", - textDecoration: "none", -}; - -// Should be different if logged in :| -const LandingPage = (props) => { - const { isLoaded } = props; - - const textColor = "#8899A6"; - const iconColor = "#1DA1F2"; - const iconSize = "8em"; - - const GridLayout = (header, description, link, icon) => { - return ( - - -
-

{header}

-
- -
- {description} -
-
{icon}
- -
-
Learn more
-
-
-
- ); - }; - - const listitems = [ - GridLayout( - "Simple integrations", - "Easily use others' or create your own integration", - "/docs/features", - - ), - GridLayout( - "Workflows", - "Access the power of automation within minutes, whether its on premise or in the cloud", - "/docs/features", - - ), - GridLayout( - "Realtime actions", - "Beat the clock by leveraging our realtime triggers", - "/docs/features", - - ), - ]; - - // The actual landing page - // {"logo"} - //We start by understanding your unique environment to help identify the right thing to automate. - const secondaryColor = "rgba(167,46,87,1)"; - const primaryColor = "rgba(25, 35, 94, 1)"; - - const paperStyle = { - flex: 1, - backgroundColor: "inherit", - cursor: "pointer", - }; - - const secondaryItemList = [ - { - primaryText: "No time to waste", - secondaryText: - "Bring all your applications into a single view, and make them all work together flawlessly!", - image: "/images/time.jpg", - }, - { - primaryText: "Get a better overview", - secondaryText: - "Don't know what's happening? We'll help you track and act on your most valuable KPI's!", - image: "/images/overview.jpg", - }, - { - primaryText: "Conquer your tasks", - secondaryText: - "Get access to powerful tools and pre-made workflows to help you crush your teams daily tasks!", - image: "/images/burnout.jpg", - }, - ]; - const [image, setImage] = useState(secondaryItemList[0].image); - - const landingpageDataBrowser = ( -
-
- -
-
Shuffle
-
- INFORMATION
OVERLOAD
-
-
- Everyone run into the same fundamental operational problems. Mailbox - chaos, tickets getting out of hand and a constant feeling of being - overwhelmed. The good news?{" "} -
- Shuffle solves them. -
-
- - - -
-
-
-
-
- Automation is just the beginning -
-
-
- {secondaryItemList.map((data, index) => { - const color = - image === data.image - ? "rgba(255,255,255,1)" - : "rgba(255,255,255,0.4)"; - return ( -
setImage(data.image)} - > - {data.primaryText} -
- {data.secondaryText} -
-
- ); - })} -
-
-
- -
-
-
-
- -
-
- Learn more about the benefits of Shuffle -
- -
-
-
-
-
- Focus on the work that matters to you -
-
- Menial tasks, scattered content, constant copy pasting, waste of - talent - there's a smarter way to work. -
-
- { - window.location.pathname = "/docs/features"; - }} - style={{ flex: 1, margin: 10, textAlign: "center" }} - > - - - -

Premade playbooks

-

Get your automation done with minimal effort

-
-
- -
- { - window.location.pathname = "/docs/features"; - }} - style={{ flex: 1, margin: 10, textAlign: "center" }} - > - - - -

Open frameworks

-

Mitre Att&ck, OpenAPI and more!

-
-
- -
- { - window.location.pathname = "/docs/features"; - }} - style={{ flex: 1, margin: 10, textAlign: "center" }} - > - - - -

Hundreds of integrations

-

Quickly integrate your software applications

-
-
- -
- { - window.location.pathname = "/docs/features"; - }} - > - - - -

Automated compliance

-

Stuck with compliance needs you can't meet?

-
-
- -
-
-
-
- ); - - const landingpageDataMobile = ( -
-
-

Shuffle

-

A general automation solution for Infosec and IT Professionals

- - - -
-
-
{listitems[0]}
-
{listitems[1]}
-
- {listitems[2]} -
- -
-
- ); - - // Reroute if the user is logged in - // const landingSite = isLoggedIn ? :
{landingpageData}
- const landingSite =
{landingpageDataBrowser}
; - - const loadedCheck = isLoaded ? ( -
- {landingSite} - {landingpageDataMobile} -
- ) : ( -
- ); - - return
{loadedCheck}
; -}; -export default LandingPage; diff --git a/frontend/src/views/MyView.jsx b/frontend/src/views/MyView.jsx deleted file mode 100755 index 42c72bc3..00000000 --- a/frontend/src/views/MyView.jsx +++ /dev/null @@ -1,2147 +0,0 @@ -import React, { useEffect } from "react"; -import { useInterval } from "react-powerhooks"; - -import Grid from "@material-ui/core/Grid"; -import Paper from "@material-ui/core/Paper"; -import Tooltip from "@material-ui/core/Tooltip"; -import Divider from "@material-ui/core/Divider"; -import Button from "@material-ui/core/Button"; -import TextField from "@material-ui/core/TextField"; -import FormControl from "@material-ui/core/FormControl"; -import IconButton from "@material-ui/core/IconButton"; -import Menu from "@material-ui/core/Menu"; -import MenuItem from "@material-ui/core/MenuItem"; -import FormControlLabel from "@material-ui/core/FormControlLabel"; -import Chip from "@material-ui/core/Chip"; -import Switch from "@material-ui/core/Switch"; -import Typography from "@material-ui/core/Typography"; -import Zoom from "@material-ui/core/Zoom"; - -import CircularProgress from "@material-ui/core/CircularProgress"; -import CachedIcon from "@material-ui/icons/Cached"; -import GetAppIcon from "@material-ui/icons/GetApp"; -import AppsIcon from "@material-ui/icons/Apps"; -import EditIcon from "@material-ui/icons/Edit"; -import MoreVertIcon from "@material-ui/icons/MoreVert"; -import PlayArrowIcon from "@material-ui/icons/PlayArrow"; -import AddIcon from "@material-ui/icons/Add"; -import PublishIcon from "@material-ui/icons/Publish"; -//import JSONPretty from 'react-json-pretty'; -//import JSONPrettyMon from 'react-json-pretty/dist/monikai' -import ReactJson from "react-json-view"; - -import { Link } from "react-router-dom"; -import { useAlert } from "react-alert"; -import ChipInput from "material-ui-chip-input"; - -import Dialog from "@material-ui/core/Dialog"; -import DialogTitle from "@material-ui/core/DialogTitle"; -import DialogActions from "@material-ui/core/DialogActions"; -import DialogContent from "@material-ui/core/DialogContent"; -import CloudDownloadIcon from "@material-ui/icons/CloudDownload"; -import BubbleChartIcon from "@material-ui/icons/BubbleChart"; -import RestoreIcon from "@material-ui/icons/Restore"; - -import mobileImage from "../assets/img/mobile.svg"; -import bagImage from "../assets/img/bag.svg"; -import bookImage from "../assets/img/book.svg"; - -import { - DataGrid, - GridToolbarContainer, - GridDensitySelector, - GridToolbar, -} from "@mui/x-data-grid"; - -import { makeStyles } from "@material-ui/core/styles"; - -import ListIcon from "@material-ui/icons/List"; -import GridOnIcon from "@material-ui/icons/GridOn"; - -const inputColor = "#383B40"; -const surfaceColor = "#27292D"; - -const flexContainerStyle = { - display: "flex", - flexDirection: "row", - justifyContent: "left", - alignContent: "space-between", -}; - -const flexBoxStyle = { - height: 125, - borderRadius: 4, - boxSizing: "border-box", - letterSpacing: "0.4px", - color: "#D6791E", - margin: 10, - flex: 1, -}; - -//const activeWorkflowStyle = {backgroundColor: "#FFF5EE"} -//const notificationStyle = {backgroundColor: "#E5F9FF"} -//const activeWorkflowStyle = {backgroundColor: "#3d3f43"} -const availableWorkflowStyle = { backgroundColor: "#3d3f43" }; -const notificationStyle = { backgroundColor: "#3d3f43" }; -const activeWorkflowStyle = { backgroundColor: "#3d3f43" }; - -const flexContentStyle = { - display: "flex", - flexDirection: "row", -}; - -const iconStyle = { - width: "75px", - height: "75px", - padding: "20px", -}; - -const fontSize_16 = { fontSize: "16px" }; -const counterStyle = { fontSize: "36px", fontWeight: "bold" }; -const blockRightStyle = { - textAlign: "right", - padding: "20px 20px 0px 0px", - width: "100%", -}; - -export const validateJson = (showResult) => { - //showResult = showResult.split(" None").join(" \"None\"") - showResult = showResult.split(" False").join(" false"); - showResult = showResult.split(" True").join(" true"); - - var jsonvalid = true; - try { - const tmp = String(JSON.parse(showResult)); - if (!showResult.includes("{") && !showResult.includes("[")) { - jsonvalid = false; - } - } catch (e) { - showResult = showResult.split("'").join('"'); - - try { - const tmp = String(JSON.parse(showResult)); - if (!showResult.includes("{") && !showResult.includes("[")) { - jsonvalid = false; - } - } catch (e) { - jsonvalid = false; - } - } - - const result = jsonvalid ? JSON.parse(showResult) : showResult; - //console.log("VALID: ", jsonvalid, result) - return { - valid: jsonvalid, - result: result, - }; -}; - -const MyView = (props) => { - const { globalUrl, isLoggedIn, isLoaded, userdata } = props; - document.title = "Shuffle - Workflows"; - - const alert = useAlert(); - - var upload = ""; - const [file, setFile] = React.useState(""); - - const [workflows, setWorkflows] = React.useState([]); - const [selectedWorkflow, setSelectedWorkflow] = React.useState({}); - const [selectedExecution, setSelectedExecution] = React.useState({}); - const [workflowExecutions, setWorkflowExecutions] = React.useState([]); - const [firstrequest, setFirstrequest] = React.useState(true); - const [workflowDone, setWorkflowDone] = React.useState(false); - const [, setTrackingId] = React.useState(""); - const [selectedWorkflowId, setSelectedWorkflowId] = React.useState(""); - - const [collapseJson, setCollapseJson] = React.useState(false); - const [field1, setField1] = React.useState(""); - const [field2, setField2] = React.useState(""); - const [downloadUrl, setDownloadUrl] = React.useState( - "https://github.com/frikky/shuffle-workflows" - ); - const [downloadBranch, setDownloadBranch] = React.useState("master"); - const [loadWorkflowsModalOpen, setLoadWorkflowsModalOpen] = - React.useState(false); - - const [modalOpen, setModalOpen] = React.useState(false); - const [newWorkflowName, setNewWorkflowName] = React.useState(""); - const [newWorkflowDescription, setNewWorkflowDescription] = - React.useState(""); - const [newWorkflowTags, setNewWorkflowTags] = React.useState([]); - const [update, setUpdate] = React.useState("test"); - const [deleteModalOpen, setDeleteModalOpen] = React.useState(false); - const [editingWorkflow, setEditingWorkflow] = React.useState({}); - const [executionLoading, setExecutionLoading] = React.useState(false); - const [view, setView] = React.useState("grid"); - const { start, stop } = useInterval({ - duration: 5000, - startImmediate: false, - callback: () => { - //getWorkflowExecution(selectedWorkflow.id) - }, - }); - - // DEBUG HERE - const handleClickLogout = () => {}; - - const deleteModal = deleteModalOpen ? ( - { - setDeleteModalOpen(false); - setSelectedWorkflowId(""); - }} - PaperProps={{ - style: { - backgroundColor: surfaceColor, - color: "white", - minWidth: 500, - }, - }} - > - -
- Are you sure?
- Other workflows relying on this one may stop working -
- - - - - -
- ) : null; - - const getAvailableWorkflows = () => { - fetch(globalUrl + "/api/v1/workflows", { - method: "GET", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for workflows :O!"); - return; - } - return response.json(); - }) - .then((responseJson) => { - setSelectedExecution({}); - setWorkflowExecutions([]); - - if (responseJson !== undefined) { - setWorkflows(responseJson); - setWorkflowDone(true); - } else { - if (isLoggedIn) { - alert.error("An error occurred while loading workflows"); - } else { - handleClickLogout(); - } - - return; - } - - if (responseJson.length > 0) { - setSelectedWorkflow(responseJson[0]); - //getWorkflowExecution(responseJson[0].id) - } - }) - .catch((error) => { - alert.error(error.toString()); - }); - }; - - useEffect(() => { - if (workflows.length <= 0 && firstrequest) { - setFirstrequest(false); - getAvailableWorkflows(); - } - }); - - const viewStyle = { - color: "#ffffff", - width: "100%", - display: "flex", - minWidth: 1024, - maxWidth: 1024, - margin: "auto", - /*maxHeight: "90vh",*/ - }; - - const emptyWorkflowStyle = { - paddingTop: "200px", - width: 1024, - margin: "auto", - }; - - const boxStyle = { - padding: "20px 20px 20px 20px", - width: "100%", - height: "250px", - color: "white", - backgroundColor: surfaceColor, - display: "flex", - flexDirection: "column", - }; - - const scrollStyle = { - marginTop: "10px", - overflow: "scroll", - height: "90%", - overflowX: "hidden", - overflowY: "auto", - }; - - const paperAppContainer = { - display: "flex", - flexWrap: "wrap", - alignContent: "space-between", - }; - - const paperAppStyle = { - minHeight: 130, - width: "100%", - color: "white", - backgroundColor: surfaceColor, - padding: "12px 12px 0px 15px", - borderRadius: 5, - display: "flex", - boxSizing: "border-box", - position: "relative", - }; - - const gridContainer = { - height: "auto", - color: "white", - margin: "10px", - backgroundColor: surfaceColor, - }; - - const workflowActionStyle = { - flex: "1", - display: "flex", - width: 150, - height: 44, - justifyContent: "space-between", - overflow: "hidden", - }; - - const getWorkflowExecution = (id) => { - setExecutionLoading(true); - fetch(globalUrl + "/api/v1/workflows/" + id + "/executions", { - method: "GET", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - }) - .then((response) => { - setExecutionLoading(false); - if (response.status !== 200) { - console.log("Status not 200 for WORKFLOW EXECUTION :O!"); - } - - return response.json(); - }) - .then((responseJson) => { - if (responseJson.success === false) { - alert.error("Failed getting executions"); - } else { - if (responseJson.length > 0) { - setSelectedExecution(responseJson[0]); - setWorkflowExecutions(responseJson); - } else { - //alert.info("Couldn't find executions for the workflow") - setSelectedExecution({}); - setWorkflowExecutions([]); - } - } - }) - .catch((error) => { - setExecutionLoading(false); - alert.error(error.toString()); - }); - }; - - const abortExecution = (workflowid, executionid) => { - alert.success("Aborting execution"); - fetch( - globalUrl + - "/api/v1/workflows/" + - workflowid + - "/executions/" + - executionid + - "/abort", - { - method: "GET", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - } - ) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for WORKFLOW EXECUTION :O!"); - } - //getWorkflowExecution(workflowid) - - return response.json(); - }) - .catch((error) => { - alert.error(error.toString()); - }); - }; - - const executeWorkflow = (id) => { - alert.show("Executing workflow " + id); - setTrackingId(id); - fetch(globalUrl + "/api/v1/workflows/" + id + "/execute", { - method: "GET", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for WORKFLOW EXECUTION :O!"); - } - - return response.json(); - }) - .then((responseJson) => { - if (!responseJson.success) { - alert.error(responseJson.reason); - } - }) - .catch((error) => { - alert.error(error.toString()); - }); - - if (id === selectedWorkflow.id) { - sleep(2000).then(() => { - stop(); - start(); - }); - } - }; - - function sleep(time) { - return new Promise((resolve) => setTimeout(resolve, time)); - } - - const exportAllWorkflows = () => { - for (var key in workflows) { - exportWorkflow(workflows[key]); - } - }; - - const exportWorkflow = (data) => { - console.log("export"); - let dataStr = JSON.stringify(data); - - let dataUri = - "data:application/json;charset=utf-8," + encodeURIComponent(dataStr); - let exportFileDefaultName = data.name + ".json"; - - data["owner"] = ""; - for (var key in data.triggers) { - const trigger = data.triggers[key]; - if (trigger.app_name === "Shuffle Workflow") { - if (trigger.parameters.length > 2) { - trigger.parameters[2].value = ""; - } - } - - if (trigger.status == "running") { - trigger.status = "stopped"; - } - } - - for (var key in data.actions) { - data.actions[key].authentication_id = ""; - } - - //return - - data["org"] = []; - data["org_id"] = ""; - data.execution_org = { id: "" }; - console.log(data); - - let linkElement = document.createElement("a"); - linkElement.setAttribute("href", dataUri); - linkElement.setAttribute("download", exportFileDefaultName); - linkElement.click(); - }; - - const copyWorkflow = (data) => { - data = JSON.parse(JSON.stringify(data)); - alert.success("Copying workflow " + data.name); - console.log("data: ", data); - data.id = ""; - data.name = data.name + "_copy"; - //return - - fetch(globalUrl + "/api/v1/workflows", { - method: "POST", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - body: JSON.stringify(data), - credentials: "include", - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for workflows :O!"); - return; - } - return response.json(); - }) - .then((responseJson) => { - getAvailableWorkflows(); - }) - .catch((error) => { - alert.error(error.toString()); - }); - }; - - const deleteWorkflow = (id) => { - alert.success("Deleted workflow " + id); - fetch(globalUrl + "/api/v1/workflows/" + id, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for setting workflows :O!"); - } - - return response.json(); - }) - .then((responseJson) => { - getAvailableWorkflows(); - }) - .catch((error) => { - alert.error(error.toString()); - }); - }; - - const getWorkflowMeta = (data) => { - let triggers = 0; - let schedules = 0; - let webhooks = 0; - let subflows = 0; - if ( - data.triggers !== undefined && - data.triggers !== null && - data.triggers.length > 0 - ) { - triggers = data.triggers.length; - for (let key in data.triggers) { - if (data.triggers[key].app_name === "Webhook") { - webhooks += 1; - //webhookImg = data.triggers[key].large_image - } else if (data.triggers[key].app_name === "Schedule") { - schedules += 1; - //scheduleImg = data.triggers[key].large_image - } else if (data.triggers[key].app_name === "Subflow") { - subflows += 1; - } - } - } - - return [triggers, schedules, webhooks, subflows]; - }; - - // dropdown with copy etc I guess - const WorkflowPaper = (props) => { - const { data } = props; - const [open, setOpen] = React.useState(false); - const [anchorEl, setAnchorEl] = React.useState(null); - - var boxWidth = "2px"; - if (selectedWorkflow.id === data.id) { - boxWidth = "4px"; - } - - var boxColor = "#FECC00"; - if (data.is_valid) { - boxColor = "#86c142"; - } - - if (!data.previously_saved) { - boxColor = "#f85a3e"; - } - - const menuClick = (event) => { - setOpen(!open); - setAnchorEl(event.currentTarget); - }; - - var parsedName = data.name; - if ( - parsedName !== undefined && - parsedName !== null && - parsedName.length > 25 - ) { - parsedName = parsedName.slice(0, 25) + ".."; - } - - const actions = data.actions !== null ? data.actions.length : 0; - const [triggers, schedules, webhooks, subflows] = getWorkflowMeta(data); - - return ( - - -
- - - - {parsedName} - - - - - - - - {actions} - - - - - - - - {triggers} - - - - - - - - - - {subflows} - - - - {/* - - - - - - - : null} - {schedules > 0 ? - - - - : null} - */} - - - {data.tags !== undefined - ? data.tags.map((tag, index) => { - if (index >= 3) { - return null; - } - - return ( - - ); - }) - : null} - - - {data.actions !== undefined && data.actions !== null ? ( - - - - - - { - setOpen(false); - setAnchorEl(null); - }} - > - { - setModalOpen(true); - setEditingWorkflow(data); - setNewWorkflowName(data.name); - setNewWorkflowDescription(data.description); - if (data.tags !== undefined && data.tags !== null) { - setNewWorkflowTags( - JSON.parse(JSON.stringify(data.tags)) - ); - } - }} - key={"change"} - > - {"Change details"} - - { - copyWorkflow(data); - setOpen(false); - }} - key={"copy"} - > - {"Copy"} - - { - exportWorkflow(data); - setOpen(false); - }} - key={"export"} - > - {"Export"} - - { - setDeleteModalOpen(true); - setSelectedWorkflowId(data.id); - setOpen(false); - }} - key={"delete"} - > - {"Delete"} - - - - - - - - - - - - ) : null} - - - ); - }; - - const executionPaper = (data) => { - var boxWidth = "2px"; - if (selectedExecution.execution_id === data.execution_id) { - boxWidth = "4px"; - } - - var boxColor = "orange"; - if ( - data.status === "ABORTED" || - data.status === "UNFINISHED" || - data.status === "FAILURE" - ) { - boxColor = "red"; - } else if (data.status === "FINISHED") { - boxColor = "green"; - } - - var t = new Date(data.started_at * 1000); - if (data.workflow.actions === null || data.workflow.actions === undefined) { - return null; - } - - if (data.workflow.actions === null || data.workflow.actions === undefined) { - return null; - } - - var actions = data.workflow.actions.length; - if (data.results !== null) { - var results = data.results.length; - } - - return ( - { - setSelectedExecution(data); - }} - > -
- - - -
-

- Status: {data.status} -

- Actions: {results}/{actions} -
-
- -
-
-
- - Started: {t.toISOString()} - -
-
-
- - ); - }; - - const dividerColor = "rgb(225, 228, 232)"; - - const resultPaperAppStyle = { - minHeight: "100px", - minWidth: "100%", - overflow: "hidden", - maxWidth: "100%", - marginTop: "5px", - color: "white", - backgroundColor: surfaceColor, - display: "flex", - }; - - function replaceAll(string, search, replace) { - return string.split(search).join(replace); - } - - const resultsPaper = (data) => { - var boxWidth = "2px"; - var boxColor = "orange"; - if ( - data.status === "ABORTED" || - data.status === "UNFINISHED" || - data.status === "FAILURE" - ) { - boxColor = "red"; - } else if (data.status === "FINISHED" || data.status === "SUCCESS") { - boxColor = "green"; - } else if (data.status === "SKIPPED" || data.status === "EXECUTING") { - boxColor = "yellow"; - } else { - boxColor = "green"; - } - - var t = new Date(data.started_at * 1000); - var showResult = data.result.trim(); - const validate = validateJson(showResult); - - if (validate.valid) { - showResult = ( - - ); - } else { - // FIXME - have everything parsed as json, either just for frontend - // or in the backend? - /* - const newdata = {"result": data.result} - showResult = - */ - } - - return ( - {}} - > -
- - - -

- Name: {data.action.label} -

-
- - App: {data.action.app_name}, Version: {data.action.app_version} - - - Action: {data.action.name}, Environment: {data.action.environment} - , Status: {data.status} - -
- - Started: {t.toISOString()} - -
- -
- - {showResult} - -
-
-
-
- ); - }; - - const resultsHandler = - Object.getOwnPropertyNames(selectedExecution).length > 0 && - selectedExecution.results !== null ? ( -
- {selectedExecution.results - .sort((a, b) => a.started_at - b.started_at) - .map((data, index) => { - return
{resultsPaper(data)}
; - })} -
- ) : ( -
No results yet
- ); - - const resultsLength = - Object.getOwnPropertyNames(selectedExecution).length > 0 && - selectedExecution.results !== null - ? selectedExecution.results.length - : 0; - - const ExecutionDetails = () => { - var starttime = new Date(selectedExecution.started_at * 1000); - var endtime = new Date(selectedExecution.started_at * 1000); - - var parsedArgument = selectedExecution.execution_argument; - if ( - selectedExecution.execution_argument !== undefined && - selectedExecution.execution_argument.length > 0 - ) { - parsedArgument = replaceAll(parsedArgument, " None", ' "None"'); - } - - var arg = null; - if ( - selectedExecution.execution_argument !== undefined && - selectedExecution.execution_argument.length > 0 - ) { - var showResult = selectedExecution.execution_argument.trim(); - const validate = validateJson(showResult); - - arg = validate.valid ? ( - - ) : ( - showResult - ); - } - - var lastresult = null; - if ( - selectedExecution.result !== undefined && - selectedExecution.result.length > 0 - ) { - var showResult = selectedExecution.result.trim(); - const validate = validateJson(showResult); - lastresult = validate.valid ? ( - - ) : ( - showResult - ); - } - - /* -
- ID: {selectedExecution.execution_id} -
-
- Last node: {selectedExecution.workflow.actions.find(data => data.id === selectedExecution.last_node).actions[0].label} -
- */ - if ( - Object.getOwnPropertyNames(selectedExecution).length > 0 && - selectedExecution.workflow.actions !== null - ) { - return ( -
-
- Status: {selectedExecution.status} -
-
- Started: {starttime.toISOString()} -
-
- Finished: {endtime.toISOString()} -
- {/* -
- Last Result: {lastresult} -
- */} -
{arg}
- - {resultsHandler} -
- ); - } - - return executionLoading ? ( -
- -
- ) : ( -

- There are no executiondetails yet. Click "execute" to run your first - one. -

- ); - }; - - const ExecutionsView = () => { - if (workflowExecutions.length > 0) { - const sortedWorkflows = workflowExecutions - .sort((a, b) => a.started_at - b.started_at) - .reverse(); - - return ( -
- {sortedWorkflows.map((data) => { - return executionPaper(data); - })} -
- ); - } - return executionLoading ? ( -
- -
- ) : ( -

- Executions have been moved to the Workflow itself.
- - Click here to see them - -

- ); - }; - - // Can create and set workflows - const setNewWorkflow = ( - name, - description, - tags, - editingWorkflow, - redirect - ) => { - var method = "POST"; - var extraData = ""; - var workflowdata = {}; - - if (editingWorkflow.id !== undefined) { - console.log("Building original workflow"); - method = "PUT"; - extraData = "/" + editingWorkflow.id; - workflowdata = editingWorkflow; - - console.log("REMOVING OWNER"); - workflowdata["owner"] = ""; - // FIXME: Loop triggers and turn them off? - } - - workflowdata["name"] = name; - workflowdata["description"] = description; - if (tags !== undefined) { - workflowdata["tags"] = tags; - } - //console.log(workflowdata) - //return - - return fetch(globalUrl + "/api/v1/workflows" + extraData, { - method: method, - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - body: JSON.stringify(workflowdata), - credentials: "include", - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for workflows :O!"); - return; - } - return response.json(); - }) - .then((responseJson) => { - if (method === "POST" && redirect) { - window.location.pathname = "/workflows/" + responseJson["id"]; - } else if (!redirect) { - // Update :) - getAvailableWorkflows(); - } else { - alert.info("Successfully changed basic info for workflow"); - } - - return responseJson; - }) - .catch((error) => { - alert.error(error.toString()); - }); - }; - - const importFiles = (event) => { - console.log("Importing!"); - const file = event.target.value; - if (event.target.files.length > 0) { - for (var key in event.target.files) { - const file = event.target.files[key]; - if (file.type !== "application/json") { - if (file.type !== undefined) { - alert.error("File has to contain valid json"); - } - - continue; - } - - const reader = new FileReader(); - // Waits for the read - reader.addEventListener("load", (event) => { - var data = reader.result; - try { - data = JSON.parse(reader.result); - } catch (e) { - alert.error("Invalid JSON: " + e); - return; - } - - // Initialize the workflow itself - const ret = setNewWorkflow( - data.name, - data.description, - data.tags, - {}, - false - ) - .then((response) => { - if (response !== undefined) { - // SET THE FULL THING - data.id = response.id; - - // Actually create it - const ret = setNewWorkflow( - data.name, - data.description, - data.tags, - data, - false - ).then((response) => { - if (response !== undefined) { - alert.success("Successfully imported " + data.name); - } - }); - } - }) - .catch((error) => { - alert.error("Import error: " + error.toString()); - }); - }); - - // Actually reads - reader.readAsText(file); - } - } - - setLoadWorkflowsModalOpen(false); - }; - - const modalView = modalOpen ? ( - { - setModalOpen(false); - }} - PaperProps={{ - style: { - backgroundColor: surfaceColor, - color: "white", - minWidth: "800px", - }, - }} - > - -
- {editingWorkflow.id !== undefined ? "Editing" : "New"} workflow -
- - - -
-
-
- - - setNewWorkflowName(event.target.value)} - InputProps={{ - style: { - color: "white", - }, - }} - color="primary" - placeholder="Name" - margin="dense" - defaultValue={newWorkflowName} - fullWidth - /> - setNewWorkflowDescription(event.target.value)} - InputProps={{ - style: { - color: "white", - }, - }} - color="primary" - defaultValue={newWorkflowDescription} - placeholder="Description" - margin="dense" - fullWidth - /> - { - newWorkflowTags.push(chip); - setNewWorkflowTags(newWorkflowTags); - }} - onDelete={(chip, index) => { - newWorkflowTags.splice(index, 1); - setNewWorkflowTags(newWorkflowTags); - setUpdate("delete " + chip); - }} - /> - - - - - - -
- ) : null; - - const viewSize = { - workflowView: 4, - executionsView: 3, - executionResults: 4, - }; - - const workflowViewStyle = { - flex: viewSize.workflowView, - marginLeft: "10px", - marginRight: "10px", - }; - - if (viewSize.workflowView === 0) { - workflowViewStyle.display = "none"; - } - - const workflowButtons = ( - - {view === "grid" && ( - - - - )} - {view === "list" && ( - - - - )} - {workflows.length > 0 ? ( - - - - ) : null} - - - - (upload = ref)} - onChange={importFiles} - /> - {workflows.length > 0 ? ( - - - - ) : null} - - - - - ); - - const useStyles = makeStyles((theme) => ({ - root: { - border: 0, - "& .MuiDataGrid-columnsContainer": { - backgroundColor: theme.palette.type === "light" ? "#fafafa" : "#1d1d1d", - }, - "& .MuiDataGrid-iconSeparator": { - display: "none", - }, - "& .MuiDataGrid-colCell, .MuiDataGrid-cell": { - borderRight: `1px solid ${ - theme.palette.type === "light" ? "white" : "#303030" - }`, - }, - "& .MuiDataGrid-columnsContainer, .MuiDataGrid-cell": { - borderBottom: `1px solid ${ - theme.palette.type === "light" ? "#f0f0f0" : "#303030" - }`, - }, - "& .MuiDataGrid-cell": { - color: - theme.palette.type === "light" ? "white" : "rgba(255,255,255,0.65)", - }, - "& .MuiPaginationItem-root, .MuiTablePagination-actions, .MuiTablePagination-caption": - { - borderRadius: 0, - color: "white", - }, - }, - })); - const classes = useStyles(); - - const WorkflowGridView = () => { - let workflowData = ""; - if (workflows.length > 0) { - const columns = [ - { field: "title", headerName: "Title", width: 330 }, - { - field: "actions", - headerName: "Actions", - width: 200, - sortable: false, - disableClickEventBubbling: true, - renderCell: (params) => { - const data = params.row.record; - let [triggers, schedules, webhooks, subflows] = - getWorkflowMeta(data); - - return ( - - - - - - - - - executeWorkflow(data.id)} - /> - - - - - {webhooks > 0 ? ( - - - - ) : null} - {schedules > 0 ? ( - - - - ) : null} - - ); - }, - }, - { - field: "tags", - headerName: "Tags", - width: 390, - sortable: false, - disableClickEventBubbling: true, - renderCell: (params) => { - const data = params.row.record; - return ( - - {data.tags !== undefined - ? data.tags.map((tag, index) => { - if (index >= 3) { - return null; - } - - return ( - - ); - }) - : null} - - ); - }, - }, - ]; - let rows = []; - rows = workflows.map((data, index) => { - let obj = { id: index + 1, title: data.name, record: data }; - return obj; - }); - workflowData = ( - - ); - } - return
{workflowData}
; - }; - - const WorkflowView = () => { - if (workflows.length === 0) { - return ( -
- -
-

Welcome to Shuffle

-
-
-

- Shuffle is a flexible, easy to use, automation platform - allowing users to integrate their services and devices freely. - It's made to significantly reduce the amount of manual labor, - and is focused on security applications.{" "} - - Click here to learn more. - -

-
-
- If you want to jump straight into it, click here to create your - first workflow: -
-
- - - - ..OR - - {workflowButtons} - -
-
-
- ); - } - - return ( -
-
-
-
-

Workflows

-
-
- -
-
-
-
- -
-
-
{workflows.length}
-
ACTIVE WORKFLOWS
-
-
-
-
-
-
- -
-
-
{workflows.length}
-
AVAILABE WORKFLOWS
-
-
-
-
-
-
- -
-
-
{workflows.length}
-
NOTIFICATIONS
-
-
-
-
- -
-
- - This is your workflow view.{" "} - - Learn more about Workflows - - -
-
{workflowButtons}
-
-
- {view === "grid" && ( - - {workflows.map((data, index) => { - return ; - })} - - )} - - {view === "list" && } - -
-
-
- ); - }; - - const importWorkflowsFromUrl = (url) => { - console.log("IMPORT WORKFLOWS FROM ", downloadUrl); - - const parsedData = { - url: url, - field_3: downloadBranch || "master", - }; - - if (field1.length > 0) { - parsedData["field_1"] = field1; - } - - if (field2.length > 0) { - parsedData["field_2"] = field2; - } - - alert.success("Getting specific workflows from your URL."); - var cors = "cors"; - fetch(globalUrl + "/api/v1/workflows/download_remote", { - method: "POST", - mode: "cors", - headers: { - Accept: "application/json", - }, - body: JSON.stringify(parsedData), - credentials: "include", - }) - .then((response) => { - if (response.status === 200) { - alert.success("Successfully loaded workflows from " + downloadUrl); - getAvailableWorkflows(); - } - - return response.json(); - }) - .then((responseJson) => { - console.log("DATA: ", responseJson); - if (!responseJson.success) { - if (responseJson.reason !== undefined) { - alert.error("Failed loading: " + responseJson.reason); - } else { - alert.error("Failed loading"); - } - } - }) - .catch((error) => { - alert.error(error.toString()); - }); - }; - - const handleGithubValidation = () => { - importWorkflowsFromUrl(downloadUrl); - setLoadWorkflowsModalOpen(false); - }; - - const workflowDownloadModalOpen = loadWorkflowsModalOpen ? ( - {}} - PaperProps={{ - style: { - backgroundColor: surfaceColor, - color: "white", - minWidth: "800px", - minHeight: "320px", - }, - }} - > - -
- Load workflows from github repo -
- - - -
-
-
- - Repository (supported: github, gitlab, bitbucket) - 0 - ? userdata.active_org.defaults.workflow_download_repo - : downloadUrl - } - InputProps={{ - style: { - color: "white", - height: "50px", - fontSize: "1em", - }, - }} - onChange={(e) => setDownloadUrl(e.target.value)} - placeholder="https://github.com/frikky/shuffle-apps" - fullWidth - /> - - Branch (default value is "master"): - -
- 0 - ? userdata.active_org.defaults.workflow_download_branch - : downloadBranch - } - InputProps={{ - style: { - color: "white", - height: "50px", - fontSize: "1em", - }, - }} - onChange={(e) => setDownloadBranch(e.target.value)} - placeholder="master" - fullWidth - /> -
- - Authentication (optional - private repos etc): - -
- setField1(e.target.value)} - type="username" - placeholder="Username / APIkey (optional)" - fullWidth - /> - setField2(e.target.value)} - type="password" - placeholder="Password (optional)" - fullWidth - /> -
-
- - - - -
- ) : null; - - const loadedCheck = - isLoaded && isLoggedIn && workflowDone ? ( -
- - {modalView} - {deleteModal} - {workflowDownloadModalOpen} -
- ) : ( -
- - Loading Workflows -
- ); - - // Maybe use gridview or something, idk - return
{loadedCheck}
; -}; - -export default MyView; diff --git a/frontend/src/views/RegisterLink.jsx b/frontend/src/views/RegisterLink.jsx deleted file mode 100755 index 1e4827c6..00000000 --- a/frontend/src/views/RegisterLink.jsx +++ /dev/null @@ -1,93 +0,0 @@ -import React, { useState, useEffect } from "react"; -import { useParams } from "react-router-dom"; - -import Paper from "@material-ui/core/Paper"; - -const bodyDivStyle = { - margin: "auto", - textAlign: "center", - width: "768px", -}; - -//const tmpdata = { -// "username": "frikky", -// "firstname": "fred", -// "lastname": "ode", -// "title": "topkek", -// "companyname": "company here", -// "email": "your email pls", -// "phone": "PHONE!!", -//} - -// FIXME - add fetch for data fields -// FIXME - remove tmpdata -// FIXME: Use isLoggedIn :) -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 = { - flex: "1", - marginLeft: "10px", - marginRight: "10px", - paddingLeft: "30px", - paddingRight: "30px", - paddingBottom: "30px", - paddingTop: "30px", - backgroundColor: surfaceColor, - color: "white", - display: "flex", - flexDirection: "column", - }; - - const registerCall = () => { - const url = globalUrl + "/api/v1/register/" + props.match.params.key; - fetch(url, { - method: "GET", - credentials: "include", - headers: { - "Content-Type": "application/json; charset=utf-8", - }, - }) - .then((response) => - response.json().then((responseJson) => { - console.log(responseJson); - }) - ) - .catch((error) => { - console.log("SOMETHING WRONG"); - }); - }; - - // This should "always" have data - useEffect(() => { - if (firstRequest) { - setFirstRequest(false); - registerCall(); - } - }); - - // Random names for type & autoComplete. Didn't research :^) - const landingpageData = ( -
- -

Registration verification

-

Thanks for verifying, redirecting you to our login!

-
-
- ); - - const loadedCheck = isLoaded ? ( -
{landingpageData}
- ) : ( -
- ); - - return
{loadedCheck}
; -}; -export default Settings; diff --git a/frontend/src/views/RegisterPage.jsx b/frontend/src/views/RegisterPage.jsx deleted file mode 100755 index 34df7666..00000000 --- a/frontend/src/views/RegisterPage.jsx +++ /dev/null @@ -1,176 +0,0 @@ -/* eslint-disable react/no-multi-comp */ -import React, { useState } from "react"; - -import DialogTitle from "@material-ui/core/DialogTitle"; -import Dialog from "@material-ui/core/Dialog"; -import TextField from "@material-ui/core/TextField"; -import Button from "@material-ui/core/Button"; - -const LoginDialog = (props) => { - const { - classes, - onClose, - open, - globalUrl, - isLoggedIn, - setIsLoggedIn, - ...other - } = props; - - const [username, setUsername] = useState(""); - const [password, setPassword] = useState(""); - //const [selectedValue, setSelectedValue] = useState(false); - - // Used to swap from login to register. True = login, false = register - const [loginCheck, setLoginCheck] = useState(true); - - // Error messages etc - const [loginInfo, setLoginInfo] = useState(""); - - const handleValidateForm = () => { - return username.length > 1 && password.length > 8; - }; - - const onSubmit = (e) => { - e.preventDefault(); - - // Just use this one? - var data = - '{"username": "' + username + '", "password": "' + password + '"}'; - var baseurl = globalUrl; - if (loginCheck) { - var url = baseurl + "/login"; - fetch(url, { - method: "POST", - body: data, - headers: { - "Content-Type": "application/json", - }, - }) - .then((response) => - response.json().then((responseJson) => { - console.log(responseJson); - //console.log(e) - if (responseJson["success"] === false) { - setLoginInfo(responseJson["reason"]); - } else { - setLoginInfo("Successful login :)"); - onClose(); - setIsLoggedIn(true); - } - }) - ) - .catch((error) => { - setLoginInfo("Error in userdata"); - }); - } else { - url = baseurl + "/register"; - fetch(url, { - method: "POST", - body: data, - headers: { - "Content-Type": "application/json", - }, - }) - .then((response) => - response.json().then((responseJson) => { - if (responseJson["success"] === false) { - setLoginInfo(responseJson["reason"]); - } else { - setLoginInfo("Successful register. Please check your mail :)"); - onClose(); - setIsLoggedIn(true); - } - }) - ) - .catch((error) => { - setLoginInfo("Error in userdata"); - }); - } - }; - - const onChangeUser = (e) => { - setUsername(e.target.value); - }; - - const onChangePass = (e) => { - setPassword(e.target.value); - }; - - const onClickRegister = () => { - setLoginCheck(!loginCheck); - }; - - //var loginChange = loginCheck ? (

Want to register? Click here.

) : (

Go back to login? Click here.

); - var formtitle = loginCheck ?
Login
:
Register
; - var formButton = loginCheck ? ( -
Click to Register
- ) : ( -
Click to Login
- ); - - return ( - - {formtitle} -
- Username -
- -
- Password -
- -
-
- - - -
- {loginInfo} -
-
- -
-
- ); -}; - -export default LoginDialog; diff --git a/frontend/src/views/Schedules.jsx b/frontend/src/views/Schedules.jsx deleted file mode 100755 index 88c92251..00000000 --- a/frontend/src/views/Schedules.jsx +++ /dev/null @@ -1,232 +0,0 @@ -import React, { useEffect } from "react"; - -import Paper from "@material-ui/core/Paper"; -import Grid from "@material-ui/core/Grid"; -import ButtonBase from "@material-ui/core/ButtonBase"; -import List from "@material-ui/core/List"; -import ListItem from "@material-ui/core/ListItem"; -import Button from "@material-ui/core/Button"; -//import Breadcrumbs from '@material-ui/core/Breadcrumbs'; - -const Schedules = (props) => { - const { globalUrl } = props; - - //const [schedules, setSchedules] = React.useState(scheduledata); - const [schedules, setSchedules] = React.useState({}); - - const getAvailableSchedules = () => { - fetch(globalUrl + "/api/v1/schedules", { - method: "GET", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - }) - .then((response) => response.json()) - .then((responseJson) => { - setSchedules(responseJson); - }) - .catch((error) => { - console.log(error); - }); - }; - - // FIXME - add automated redirection, as empty apps look horrible currently - const newSchedule = () => { - fetch(globalUrl + "/api/v1/schedules/new", { - method: "POST", - headers: { "content-type": "application/json" }, - body: JSON.stringify(), - }) - .then((response) => response.json()) - .then((responseJson) => { - console.log(responseJson); - setSchedules({}); - }) - .catch((error) => { - console.log(error); - }); - }; - - const deleteSchedule = (id) => { - if (id === undefined) { - return; - } - - fetch(globalUrl + "/api/v1/schedules/" + id + "/delete", { - method: "DELETE", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - }) - .then((response) => response.json()) - .then((responseJson) => { - setSchedules({}); - }) - .catch((error) => { - console.log(error); - }); - }; - - // FIXME - use this? - //const getNewScheduleInfo = () => { - // fetch(globalUrl+"/api/v1/schedules", { - // method: 'GET', - // headers: { - // 'Content-Type': 'application/json', - // 'Accept': 'application/json', - // }, - // }) - // .then((response) => response.json()) - // .then((responseJson) => { - // setSchedules(responseJson) - // }) - // .catch(error => { - // console.log(error) - // }); - //} - - useEffect(() => { - if (Object.getOwnPropertyNames(schedules).length <= 0) { - getAvailableSchedules(); - } - }); - - const bodyDivStyle = { - marginLeft: "20px", - marginRight: "20px", - width: "1350px", - minWidth: "1350px", - maxWidth: "1350px", - }; - - const scheduleApp = (app) => { - console.log(app); - return ( - - - - - - - - - -
-

{app.name}

-
-
{app.description}
-
- {app.action} -
-
-
- ); - }; - - const splitter = ( -
- ); - - const hrefStyle = { - color: "#385f71", - textDecoration: "none", - }; - - // FIXME - add Schedule modal - const schedulePaper = (schedule) => { - return ( -
- -
- {scheduleApp(schedule.appinfo.sourceapp)} -
-
ARROW
-
- {scheduleApp(schedule.appinfo.destinationapp)} -
- {splitter} -
- - - - - - - - - - -
-
-
- ); - }; - - console.log(schedules); - console.log(schedules); - console.log(schedules.schedules); - const schedulemap = - Object.getOwnPropertyNames(schedules).length > 0 && - schedules.schedules && - schedules.schedules.length > 0 ? ( -
{schedules.schedules.map((data) => schedulePaper(data))}
- ) : ( -
- -
- ); - - const scheduleView = - Object.getOwnPropertyNames(schedules).length > 0 ? ( -
- - {schedulemap} -
- ) : null; - - // Maybe use gridview or something, idk - return
{scheduleView}
; -}; - -export default Schedules; diff --git a/frontend/src/views/TempDashboard.jsx b/frontend/src/views/TempDashboard.jsx deleted file mode 100644 index a34ac730..00000000 --- a/frontend/src/views/TempDashboard.jsx +++ /dev/null @@ -1,298 +0,0 @@ -import React from "react"; -import { Grid, Container, Divider } from "@mui/material"; - -import { makeStyles } from "@mui/material/styles"; -import Card from "@material-ui/core/Card"; -import CardContent from "@material-ui/core/CardContent"; -import Typography from "@material-ui/core/Typography"; - -import Table from "@material-ui/core/Table"; -import TableBody from "@material-ui/core/TableBody"; -import TableCell from "@material-ui/core/TableCell"; -import TableContainer from "@material-ui/core/TableContainer"; -import TableHead from "@material-ui/core/TableHead"; -import TableRow from "@material-ui/core/TableRow"; -import Paper from "@material-ui/core/Paper"; - -import { LineChart, LineSeries, BarChart } from "reaviz"; -import { GridStripe } from "reaviz"; -//import { GridlineSeries } from "reaviz"; - -import InputLabel from '@material-ui/core/InputLabel'; -import FormControl from '@material-ui/core/FormControl'; -import Select from '@material-ui/core/Select'; -import MenuItem from '@material-ui/core/MenuItem'; - -const data = [ - { - key: new Date("11/29/2019"), - data: 10, - }, - { - key: new Date("11/30/2019"), - data: 14, - }, - { - key: new Date("12/01/2019"), - data: 5, - }, - { - key: new Date("12/02/2019"), - data: 18, - }, -]; - -const useStyles1 = makeStyles((theme) => ({ - formControl: { - margin: theme.spacing(1), - minWidth: 120, - }, - selectEmpty: { - marginTop: theme.spacing(2), - }, -})); - - -const useStyles = makeStyles({ - table: { - minWidth: 650, - }, - root: { - minWidth: 275, - }, - bullet: { - display: "inline-block", - margin: "0 2px", - transform: "scale(0.8)", - }, - title: { - fontSize: 14, - }, - pos: { - marginBottom: 12, - }, -}); - -function createData(name, calories, fat, carbs, protein) { - return { name, calories, fat, carbs, protein }; -} - -const rows = [ - createData("Frozen yoghurt", 159, 6.0, 24, 4.0), - createData("Ice cream sandwich", 237, 9.0, 37, 4.3), - createData("Eclair", 262, 16.0, 24, 6.0), - createData("Cupcake", 305, 3.7, 67, 4.3), - createData("Gingerbread", 356, 16.0, 49, 3.9), -]; - -const DashboardPage = () => { - const classes = useStyles(); - const classes1 = useStyles1(); - - const [age, setAge] = React.useState(0); - - const handleChange = (event) => { - setAge(event.target.value); - - }; - - return ( - - - -
- - Dashboard - -
- - Organization - - -
-
-
- -
- - - - - - Total workflows executions - - - 456 - - - - - - - - - Total Apps executions - - - 587 - - - - - - - - - Total failed executions - - - 999 - - - - - - - - - - - } - series={} - /> - - - - - - - - - Dessert (100g serving) - Calories - Fat (g) - Carbs (g) - Protein (g) - - - - {rows.map((row) => ( - - - {row.name} - - {row.calories} - {row.fat} - {row.carbs} - {row.protein} - - ))} - -
-
-
-
-
- ); -}; - -export default DashboardPage; diff --git a/frontend/src/views/Webhooks.jsx b/frontend/src/views/Webhooks.jsx deleted file mode 100755 index 64a463b9..00000000 --- a/frontend/src/views/Webhooks.jsx +++ /dev/null @@ -1,316 +0,0 @@ -import React, { useEffect } from "react"; - -import Paper from "@material-ui/core/Paper"; -import Grid from "@material-ui/core/Grid"; -import ButtonBase from "@material-ui/core/ButtonBase"; -import Button from "@material-ui/core/Button"; -import List from "@material-ui/core/List"; -import ListItem from "@material-ui/core/ListItem"; -import TextField from "@material-ui/core/TextField"; -import Select from "@material-ui/core/Select"; -import MenuItem from "@material-ui/core/MenuItem"; - -import Dialog from "@material-ui/core/Dialog"; -import DialogTitle from "@material-ui/core/DialogTitle"; -import DialogActions from "@material-ui/core/DialogActions"; -import DialogContent from "@material-ui/core/DialogContent"; - -import WebhookImage from "../assets/img/webhook.png"; -import KafkaImage from "../assets/img/kafka.png"; - -const Webhooks = (props) => { - const { globalUrl, isLoaded } = props; - const validtypes = ["webhook"]; - - //const [hooks, setSchedules] = React.useState(hookdata); - const [hooks, setHooks] = React.useState([]); - const [modalOpen, setModalOpen] = React.useState(false); - const [newHookName, setNewHookName] = React.useState(""); - const [newHookDescription, setNewHookDescription] = React.useState(""); - const [newHookType, setNewHookType] = React.useState(""); - const [firstrequest, setFirstrequest] = React.useState(true); - const [, setModalError] = React.useState(""); - - useEffect(() => { - if (firstrequest) { - setFirstrequest(false); - getAvailableHooks(); - } - }); - - const newHook = () => { - if (newHookName.length === 0) { - setModalError("Missing name in modal"); - return; - } - - if (!validtypes.includes(newHookType)) { - setModalError( - newHookType + " is not a valid type. Try this: " + validtypes - ); - } - - fetch(globalUrl + "/api/v1/hooks/new", { - method: "POST", - headers: { "content-type": "application/json" }, - body: JSON.stringify({ - name: newHookName, - description: newHookDescription, - type: newHookType, - }), - credentials: "include", - }) - .then((response) => response.json()) - .then((responseJson) => { - console.log(responseJson); - setHooks([]); - }) - .catch((error) => { - console.log(error); - }); - }; - - const getAvailableHooks = () => { - fetch(globalUrl + "/api/v1/hooks", { - method: "GET", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - }) - .then((response) => response.json()) - .then((responseJson) => { - setHooks(responseJson); - }) - .catch((error) => { - console.log(error); - // window.location.pathname = "/" - }); - }; - - const deleteHook = (id) => { - if (id === undefined) { - return; - } - - fetch(globalUrl + "/api/v1/hooks/" + id + "/delete", { - method: "DELETE", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - }) - .then((response) => response.json()) - .then((responseJson) => { - setHooks([]); - }) - .catch((error) => { - console.log(error); - }); - }; - - const bodyDivStyle = { - marginLeft: "20px", - marginRight: "20px", - width: "1350px", - minWidth: "1350px", - maxWidth: "1350px", - }; - - const hookApp = (app) => { - // Might be more options, but should be webhook or MQ - const appPicture = - app.type === "webhook" ? ( - webhook - ) : ( - MQ - ); - - return ( - - - {appPicture} - - {splitter} - - - -
-

{app.info.name}

-
-
Desc: {app.info.description}
-
Status: {app.status}
-
- {app.action} -
-
-
- ); - }; - - const splitter = ( -
- ); - - const hrefStyle = { - color: "#385f71", - textDecoration: "none", - }; - - // FIXME - add Schedule modal - const hookPaper = (hook) => { - return ( -
- -
{hookApp(hook)}
- {splitter} -
- - - - - - - - - - -
-
-
- ); - }; - - const modalView = modalOpen ? ( - { - setModalOpen(false); - }} - > - Hook configuration - - { - setNewHookName(event.target.value); - }} - color="primary" - placeholder="Name" - margin="dense" - fullWidth - /> - { - setNewHookDescription(event.target.value); - }} - color="primary" - placeholder="Description" - margin="dense" - fullWidth - /> - - - - - - - - - ) : null; - - const hookmap = - hooks.length > 0 ? ( -
{hooks.map((data) => hookPaper(data))}
- ) : ( -
- -
- ); - - const hookView = ( -
- - {hookmap} -
- ); - - const loadedCheck = isLoaded ? ( -
- {modalView} - {hookView} -
- ) : ( -
- ); - - // Maybe use gridview or something, idk - return
{loadedCheck}
; -}; - -export default Webhooks; diff --git a/frontend/src/views/Workflows.jsx b/frontend/src/views/Workflows.jsx index ab6eddd6..a892dbb3 100755 --- a/frontend/src/views/Workflows.jsx +++ b/frontend/src/views/Workflows.jsx @@ -75,14 +75,8 @@ import { ArrowRight as ArrowRightIcon, } from "@mui/icons-material"; -//import NestedMenuItem from "material-ui-nested-menu-item"; -//import {Search as SearchIcon, ArrowUpward as ArrowUpwardIcon, Visibility as VisibilityIcon, Close as CloseIcon, Error as ErrorIcon, FindReplace as FindreplaceIcon, ArrowLeft as ArrowLeftIcon, Cached as CachedIcon, DirectionsRun as DirectionsRunIcon, Add as AddIcon, Polymer as PolymerIcon, FormatListNumbered as FormatListNumberedIcon, Create as CreateIcon, PlayArrow as PlayArrowIcon, AspectRatio as AspectRatioIcon, MoreVert as MoreVertIcon, Apps as AppsIcon, Schedule as ScheduleIcon, FavoriteBorder as FavoriteBorderIcon, Pause as PauseIcon, Delete as DeleteIcon, AddCircleOutline as AddCircleOutlineIcon, Save as SaveIcon, KeyboardArrowLeft as KeyboardArrowLeftIcon, KeyboardArrowRight as KeyboardArrowRightIcon, ArrowBack as ArrowBackIcon, Settings as SettingsIcon, LockOpen as LockOpenIcon, ExpandMore as ExpandMoreIcon, VpnKey as VpnKeyIcon} from '@material-ui/icons'; - -//https://next.material-ui.com/components/material-icons/ import { DataGrid, GridToolbar } from "@mui/x-data-grid"; -//import JSONPretty from 'react-json-pretty'; -//import JSONPrettyMon from 'react-json-pretty/dist/monikai' import Dropzone from "../components/Dropzone.jsx"; import { useNavigate, Link } from "react-router-dom"; @@ -1747,13 +1741,6 @@ const Workflows = (props) => { {"Duplicate Workflow"} - {/*= 0} style={{backgroundColor: theme.palette.inputColor, color: "white"}} onClick={() => { - //copyWorkflow(data) - //setOpen(false) - }} key={"duplicate"}> - - {"Copy to Child Org"} - */} { From 1461d6ad6b6e67e4e1647c8b9331911891858c7c Mon Sep 17 00:00:00 2001 From: Frikky Date: Thu, 17 Aug 2023 02:13:38 +0200 Subject: [PATCH 12/15] Fixed another new workflow recommendation issue --- backend/go-app/go.mod | 2 +- frontend/src/components/EditWorkflow.jsx | 118 ++++++++++++++--------- frontend/src/components/WorkflowGrid.jsx | 95 ++++++++++-------- 3 files changed, 126 insertions(+), 89 deletions(-) diff --git a/backend/go-app/go.mod b/backend/go-app/go.mod index 5f0ffdff..e400b547 100755 --- a/backend/go-app/go.mod +++ b/backend/go-app/go.mod @@ -1,6 +1,6 @@ module shuffle-shared -//replace github.com/shuffle/shuffle-shared => ../../../../git/shuffle-shared +replace github.com/shuffle/shuffle-shared => ../../../../git/shuffle-shared go 1.19 diff --git a/frontend/src/components/EditWorkflow.jsx b/frontend/src/components/EditWorkflow.jsx index c862f22b..38ddbcf5 100644 --- a/frontend/src/components/EditWorkflow.jsx +++ b/frontend/src/components/EditWorkflow.jsx @@ -3,6 +3,7 @@ import theme from '../theme.jsx'; import { isMobile } from "react-device-detect" import { MuiChipsInput } from "mui-chips-input"; import UsecaseSearch from "../components/UsecaseSearch.jsx" +import WorkflowGrid from "../components/WorkflowGrid.jsx" import dayjs from 'dayjs'; import { @@ -62,12 +63,14 @@ const EditWorkflow = (props) => { const [submitLoading, setSubmitLoading] = React.useState(false); const [showMoreClicked, setShowMoreClicked] = React.useState(false); - const [innerWorkflow, setInnerWorkflow] = React.useState(workflow) + const [innerWorkflow, setInnerWorkflow] = React.useState(workflow) + const [newWorkflowTags, setNewWorkflowTags] = React.useState(workflow.tags !== undefined && workflow.tags !== null ? JSON.parse(JSON.stringify(workflow.tags)) : []) + const [description, setDescription] = React.useState(workflow.description !== undefined ? workflow.description : "") + const [selectedUsecases, setSelectedUsecases] = React.useState(workflow.usecase_ids !== undefined && workflow.usecase_ids !== null ? JSON.parse(JSON.stringify(workflow.usecase_ids)) : []); const [foundWorkflowId, setFoundWorkflowId] = React.useState("") const [name, setName] = React.useState(workflow.name !== undefined ? workflow.name : "") - const [description, setDescription] = React.useState(workflow.description !== undefined ? workflow.description : "") const [dueDate, setDueDate] = React.useState(workflow.due_date !== undefined && workflow.due_date !== null && workflow.due_date !== 0 ? dayjs(workflow.due_date*1000) : dayjs().subtract(1, 'day')) // Gets the generated workflow @@ -154,58 +157,59 @@ const EditWorkflow = (props) => { PaperProps={{ style: { color: "white", - minWidth: isMobile ? "90%" : 550, - maxWidth: isMobile ? "90%" : 550, + minWidth: isMobile ? "90%" : 650, + maxWidth: isMobile ? "90%" : 650, minHeight: 400, + paddingTop: 25, //minWidth: isMobile ? "90%" : newWorkflow === true ? 1000 : 550, //maxWidth: isMobile ? "90%" : newWorkflow === true ? 1000 : 550, }, }} > -
+
-
- - {newWorkflow ? "New" : "Editing"} workflow - - {newWorkflow === true ? null : -
- - - - - -
- } +
+ + {newWorkflow ? "New" : "Editing"} workflow + + {newWorkflow === true ? null : +
+ + + + +
- - Workflows can be built from scratch, or from templates. Usecases can help you discover next steps, and you can search for them directly. Learn more - - {showUpload === true ? -
- - - -
- : null} + } +
+ + Workflows can be built from scratch, or from templates. Usecases can help you discover next steps, and you can search for them directly. Learn more + + {showUpload === true ? +
+ + + +
+ : null}
{/*newWorkflow === true ?
@@ -220,8 +224,8 @@ const EditWorkflow = (props) => {
- -
+ +
{ setName(event.target.value) @@ -475,7 +479,8 @@ const EditWorkflow = (props) => {
- + + + + {newWorkflow === true && name.length > 5 ? +
+ +
+ : null} ) diff --git a/frontend/src/components/WorkflowGrid.jsx b/frontend/src/components/WorkflowGrid.jsx index e4542e06..fb19e806 100644 --- a/frontend/src/components/WorkflowGrid.jsx +++ b/frontend/src/components/WorkflowGrid.jsx @@ -25,12 +25,9 @@ import WorkflowPaperNew from "../components/WorkflowPaperNew.jsx" const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e5240") const AppGrid = props => { - const { maxRows, showName, showSuggestion, isMobile, globalUrl, parsedXs, alternativeView, } = props - - const isCloud = - window.location.host === "localhost:3002" || - window.location.host === "shuffler.io"; + const { maxRows, showName, showSuggestion, isMobile, globalUrl, parsedXs, alternativeView, onlyResults, inputsearch } = props + const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"; const rowHandler = maxRows === undefined || maxRows === null ? 50 : maxRows const xs = parsedXs === undefined || parsedXs === null ? isMobile ? 6 : 4 : parsedXs //const [apps, setApps] = React.useState([]); @@ -38,7 +35,9 @@ const AppGrid = props => { const [formMail, setFormMail] = React.useState(""); const [message, setMessage] = React.useState(""); const [formMessage, setFormMessage] = React.useState(""); - const [usecases, setUsecases] = React.useState([]); + const [usecases, setUsecases] = React.useState([]); + + const [localMessage, setLocalMessage] = React.useState(""); const buttonStyle = {borderRadius: 30, height: 50, width: 220, margin: isMobile ? "15px auto 15px auto" : 20, fontSize: 18,} @@ -153,10 +152,10 @@ const AppGrid = props => { return response.json(); }) .then((responseJson) => { - if (responseJson.success !== false) { - console.log("Usecases: ", responseJson) - //handleKeysetting(responseJson, workflows) - } + if (responseJson.success !== false) { + console.log("Usecases: ", responseJson) + //handleKeysetting(responseJson, workflows) + } }) .catch((error) => { //alert.error("ERROR: " + error.toString()); @@ -166,8 +165,10 @@ const AppGrid = props => { useEffect(() => { fetchUsecases() + }, []) + // value={currentRefinement} const SearchBox = ({currentRefinement, refine, isSearchStalled} ) => { useEffect(() => { @@ -182,16 +183,23 @@ const AppGrid = props => { } }, []) + if (localMessage !== inputsearch && inputsearch !== undefined && inputsearch !== null && inputsearch.length > 0) { + console.log("In refinement: ", inputsearch) + //setLocalMessage(inputsearch) + refine(inputsearch) + } else if (onlyResults === true) { + // Don't return anything unless refinement works + return null + } + return (
+ {onlyResults !== true ? @@ -210,8 +218,8 @@ const AppGrid = props => { }} limit={5} /> - {/*isSearchStalled ? 'My search is stalled' : ''*/} - + : null} + ) } @@ -228,29 +236,35 @@ const AppGrid = props => { var counted = 0 return ( - - {hits.map((data, index) => { - workflowDelay += 50 +
+ {onlyResults === true && hits.length > 0 ? + + Relevant Workflows + + : null} + + {hits.map((data, index) => { + workflowDelay += 50 - if (counted === 12/xs*rowHandler) { - return null - } + if (counted === 12/xs*rowHandler) { + return null + } - counted += 1 + counted += 1 - return ( - - + return ( + + {/**/} {alternativeView === true ? : } - - ) - })} - + ) + })} + +
) } @@ -331,11 +345,11 @@ const AppGrid = props => { fullWidth={true} placeholder="What apps do you want to see?" type="" - id="standard-required" + id="standard-required" margin="normal" variant="outlined" autoComplete="off" - onChange={e => setMessage(e.target.value)} + onChange={e => setMessage(e.target.value)} />
: null } - - - - Search by - - - Algolia logo - - + {onlyResults === true ? null : + + + Search by + + + Algolia logo + + + }
) } From 99d1a96c63ffc11b5b743ec68c55ca5729392986 Mon Sep 17 00:00:00 2001 From: Frikky Date: Thu, 17 Aug 2023 03:16:43 +0200 Subject: [PATCH 13/15] Changed from Alert to Toast to work well with mui v18 --- frontend/src/components/AppFramework.jsx | 27 ++- frontend/src/components/AppGrid.jsx | 2 +- frontend/src/components/Appsearch.jsx | 8 +- .../src/components/AuthenticationItem.jsx | 17 +- .../src/components/AuthenticationNormal.jsx | 10 +- .../src/components/AuthenticationWindow.jsx | 12 +- frontend/src/components/Branding.jsx | 4 +- frontend/src/components/CacheView.jsx | 22 +- frontend/src/components/ConfigureWorkflow.jsx | 22 +- frontend/src/components/CreatorGrid.jsx | 2 +- frontend/src/components/DocsGrid.jsx | 2 +- frontend/src/components/EditWorkflow.jsx | 2 +- frontend/src/components/Files.jsx | 34 +-- frontend/src/components/Header.jsx | 12 +- frontend/src/components/Oauth2Auth.jsx | 10 +- frontend/src/components/OrgHeader.jsx | 8 +- frontend/src/components/ParsedAction.jsx | 12 +- frontend/src/components/Priorities.jsx | 2 +- frontend/src/components/Priority.jsx | 8 +- frontend/src/components/ShuffleCodeEditor.jsx | 6 +- frontend/src/components/UsecaseSearch.jsx | 40 ++-- frontend/src/components/WelcomeForm2.jsx | 16 +- frontend/src/components/WorkflowGrid.jsx | 4 +- frontend/src/components/Workflowsearch.jsx | 2 +- frontend/src/views/Admin.jsx | 189 ++++++++-------- frontend/src/views/AngularWorkflow.jsx | 211 +++++++++--------- frontend/src/views/AppCreator.jsx | 81 +++---- frontend/src/views/Apps.jsx | 81 +++---- frontend/src/views/Dashboard.jsx | 33 +-- frontend/src/views/DashboardViews.jsx | 13 +- frontend/src/views/FrameworkWrapper.jsx | 11 +- frontend/src/views/GettingStarted.jsx | 77 +++---- frontend/src/views/SettingsPage.jsx | 21 +- frontend/src/views/UpdateAuthentication.jsx | 9 +- frontend/src/views/Welcome.jsx | 4 +- frontend/src/views/Workflows.jsx | 81 +++---- 36 files changed, 553 insertions(+), 542 deletions(-) diff --git a/frontend/src/components/AppFramework.jsx b/frontend/src/components/AppFramework.jsx index b5ab004e..aca62d61 100644 --- a/frontend/src/components/AppFramework.jsx +++ b/frontend/src/components/AppFramework.jsx @@ -1,10 +1,9 @@ import React, { useState, useEffect } from 'react'; +import theme from '../theme.jsx'; import CytoscapeComponent from 'react-cytoscapejs'; import frameworkStyle from '../frameworkStyle.jsx'; import { v4 as uuidv4 } from "uuid"; -import theme from '../theme.jsx'; -import { useAlert } from "react-alert"; import AppSearch from '../components/Appsearch.jsx'; import PaperComponent from "../components/PaperComponent.jsx" @@ -34,10 +33,10 @@ import { import * as edgehandles from "cytoscape-edgehandles"; import * as cytoscape from "cytoscape"; +import { toast } from 'react-toastify'; cytoscape.use(edgehandles); - const svgSize = "40px" const parsedDatatypeImages = { "SIEM": encodeURI(`data:image/svg+xml;utf-8,`), @@ -521,7 +520,7 @@ const AppFramework = (props) => { const scale = size === undefined ? 1 : size > 5 ? 3 : size - const alert = useAlert() + //const alert = useAlert() const handleLoadNextSuggestion = (frameworkData) => { @@ -784,16 +783,16 @@ const AppFramework = (props) => { .then((responseJson) => { if (responseJson.success === false) { if (responseJson.reason !== undefined) { - alert.error("Failed updating: " + responseJson.reason) + toast("Failed updating: " + responseJson.reason) } else { - alert.error("Failed to update framework for your org.") + toast("Failed to update framework for your org.") } } else { - alert.info("Updated usecase.") + toast("Updated usecase.") } }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); //setFrameworkLoaded(true) }) } @@ -816,13 +815,13 @@ const AppFramework = (props) => { }) .then((responseJson) => { if (responseJson.success === false) { - alert.error("Failed to activate the app") + toast("Failed to activate the app") } else { - //alert.success("App activated for your organization! Refresh the page to use the app.") + //toast("App activated for your organization! Refresh the page to use the app.") } }) .catch(error => { - //alert.error(error.toString()) + //toast(error.toString()) console.log("Activate app error: ", error.toString()) }); } @@ -852,9 +851,9 @@ const AppFramework = (props) => { .then((responseJson) => { if (responseJson.success === false) { if (responseJson.reason !== undefined) { - alert.error("Failed updating: " + responseJson.reason) + toast("Failed updating: " + responseJson.reason) } else { - alert.error("Failed to update framework for your org.") + toast("Failed to update framework for your org.") } } @@ -863,7 +862,7 @@ const AppFramework = (props) => { //setFrameworkData(responseJson) }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); //setFrameworkLoaded(true) }) } diff --git a/frontend/src/components/AppGrid.jsx b/frontend/src/components/AppGrid.jsx index 1e6ab296..57369deb 100644 --- a/frontend/src/components/AppGrid.jsx +++ b/frontend/src/components/AppGrid.jsx @@ -74,7 +74,7 @@ const AppGrid = props => { .then(response => { if (response.success === true) { setFormMessage(response.reason) - //alert.info("Thanks for submitting!") + //toast("Thanks for submitting!") } else { setFormMessage(errorMessage) } diff --git a/frontend/src/components/Appsearch.jsx b/frontend/src/components/Appsearch.jsx index 8beb1014..5f88e99a 100644 --- a/frontend/src/components/Appsearch.jsx +++ b/frontend/src/components/Appsearch.jsx @@ -2,8 +2,8 @@ import React, { useState, useEffect } from 'react'; import ReactGA from 'react-ga4'; import theme from '../theme'; import {Link} from 'react-router-dom'; -import { useAlert } from "react-alert"; import { Search as SearchIcon, CloudQueue as CloudQueueIcon, Code as CodeIcon } from '@mui/icons-material'; +import { toast } from 'react-toastify'; //import algoliasearch from 'algoliasearch/lite'; import algoliasearch from 'algoliasearch'; @@ -25,7 +25,7 @@ const Appsearch = props => { const { maxRows, showName, showSuggestion, isMobile, globalUrl, parsedXs, newSelectedApp, setNewSelectedApp, defaultSearch, showSearch, ConfiguredHits, userdata, cy, isCreatorPage, actionImageList, setActionImageList} = props const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"; - const alert = useAlert(); + //const alert = useAlert(); const rowHandler = maxRows === undefined || maxRows === null ? 50 : maxRows const xs = parsedXs === undefined || parsedXs === null ? 12 : parsedXs //const theme = useTheme(); @@ -68,12 +68,12 @@ const Appsearch = props => { if (response.status !== 200) { console.log("Status not 200 for set creator :O!"); } - alert.success("Sucessfully updated specialzed app.") + toast("Sucessfully updated specialzed app.") return response.json(); }) .then((responseJson) => { if (!responseJson.success && responseJson.reason !== undefined) { - alert.error("Failed updating user: " + responseJson.reason); + toast("Failed updating user: " + responseJson.reason); } }) .catch((error) => { diff --git a/frontend/src/components/AuthenticationItem.jsx b/frontend/src/components/AuthenticationItem.jsx index 06329a35..593eacb4 100644 --- a/frontend/src/components/AuthenticationItem.jsx +++ b/frontend/src/components/AuthenticationItem.jsx @@ -1,7 +1,8 @@ import React, { useState, useEffect } from "react"; import theme from '../theme.jsx'; -import { useAlert } from "react-alert"; +import { toast } from 'react-toastify'; + import { Tooltip, IconButton, @@ -34,7 +35,7 @@ const AuthenticationItem = (props) => { const [selectedAuthenticationModalOpen, setSelectedAuthenticationModalOpen] = React.useState(false); const [authenticationFields, setAuthenticationFields] = React.useState([]); - const alert = useAlert(); + //const alert = useAlert(); var bgColor = "#27292d"; if (index % 2 === 0) { bgColor = "#1f2023"; @@ -63,7 +64,7 @@ const AuthenticationItem = (props) => { } const deleteAuthentication = (data) => { - alert.info("Deleting auth " + data.label); + toast("Deleting auth " + data.label); // Just use this one? const url = globalUrl + "/api/v1/apps/authentication/" + data.id; @@ -79,13 +80,13 @@ const AuthenticationItem = (props) => { response.json().then((responseJson) => { console.log("RESP: ", responseJson); if (responseJson["success"] === false) { - alert.error("Failed deleting auth"); + toast("Failed deleting auth"); } else { // Need to wait because query in ES is too fast setTimeout(() => { getAppAuthentication(); }, 1000); - //alert.success("Successfully deleted authentication!") + //toast("Successfully deleted authentication!") } }) ) @@ -115,9 +116,9 @@ const AuthenticationItem = (props) => { .then((response) => response.json().then((responseJson) => { if (responseJson["success"] === false) { - alert.error("Failed overwriting appauth in workflows"); + toast("Failed overwriting appauth in workflows"); } else { - alert.success("Successfully updated auth everywhere!"); + toast("Successfully updated auth everywhere!"); //setSelectedUserModalOpen(false); setTimeout(() => { getAppAuthentication(); @@ -126,7 +127,7 @@ const AuthenticationItem = (props) => { }) ) .catch((error) => { - alert.error("Err: " + error.toString()); + toast("Err: " + error.toString()); }); }; diff --git a/frontend/src/components/AuthenticationNormal.jsx b/frontend/src/components/AuthenticationNormal.jsx index a0d6acab..1140de10 100644 --- a/frontend/src/components/AuthenticationNormal.jsx +++ b/frontend/src/components/AuthenticationNormal.jsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from "react"; import theme from '../theme.jsx'; import { v4 as uuidv4 } from "uuid"; - +import { toast } from 'react-toastify'; import { Button, @@ -54,7 +54,7 @@ const AuthenticationData = (props) => { }) .then((responseJson) => { if (!responseJson.success) { - alert.error("Failed to set app auth: " + responseJson.reason); + toast("Failed to set app auth: " + responseJson.reason); } else { if (getAppAuthentication !== undefined) { getAppAuthentication() @@ -65,11 +65,11 @@ const AuthenticationData = (props) => { } // Needs a refresh with the new authentication.. - //alert.success("Successfully saved new app auth") + //toast("Successfully saved new app auth") } }) .catch((error) => { - //alert.error(error.toString()); + //toast(error.toString()); console.log("New auth error: ", error.toString()); }); } @@ -146,7 +146,7 @@ const AuthenticationData = (props) => { selectedApp.authentication.parameters[key].name ] = "false"; } else { - alert.info( + toast( "Field " + selectedApp.authentication.parameters[key].name + " can't be empty" diff --git a/frontend/src/components/AuthenticationWindow.jsx b/frontend/src/components/AuthenticationWindow.jsx index 47dd9b4e..d7bcc55a 100755 --- a/frontend/src/components/AuthenticationWindow.jsx +++ b/frontend/src/components/AuthenticationWindow.jsx @@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react"; import theme from '../theme.jsx'; import { v4 as uuidv4 } from "uuid"; -import { useAlert } from "react-alert"; +import { toast } from 'react-toastify'; import { Divider, @@ -44,7 +44,7 @@ const AuthenticationData = (props) => { authFieldsOnly, } = props - const alert = useAlert() + //const alert = useAlert() let navigate = useNavigate(); const [submitSuccessful, setSubmitSuccessful] = useState(false) const [authenticationOption, setAuthenticationOptions] = React.useState({ @@ -99,9 +99,9 @@ const AuthenticationData = (props) => { .then((responseJson) => { if (!responseJson.success) { if (responseJson.reason === undefined) { - alert.error("Failed to set app auth. Are you logged in?") + toast("Failed to set app auth. Are you logged in?") } else { - alert.error("Failed to set app auth: " + responseJson.reason); + toast("Failed to set app auth: " + responseJson.reason); } } else { setSubmitSuccessful(true) @@ -115,7 +115,7 @@ const AuthenticationData = (props) => { } }) .catch((error) => { - //alert.error(error.toString()); + //toast(error.toString()); console.log("New auth error: ", error.toString()); }); }; @@ -175,7 +175,7 @@ const AuthenticationData = (props) => { selectedApp.authentication.parameters[paramkey].name ] = "false"; } else { - alert.info( + toast( "Field " + selectedApp.authentication.parameters[paramkey].name + " can't be empty" diff --git a/frontend/src/components/Branding.jsx b/frontend/src/components/Branding.jsx index 4b44f5c1..e565a013 100644 --- a/frontend/src/components/Branding.jsx +++ b/frontend/src/components/Branding.jsx @@ -11,11 +11,11 @@ import { Card, } from "@mui/material"; -import { useAlert } from "react-alert"; +//import { useAlert const Branding = (props) => { const { globalUrl, userdata, serverside, billingInfo, stripeKey, selectedOrganization, handleGetOrg, } = props; - const alert = useAlert(); + //const alert = useAlert(); const [publishingInfo, setPublishingInfo] = useState(""); // Should enable / disable org branding diff --git a/frontend/src/components/CacheView.jsx b/frontend/src/components/CacheView.jsx index 62394423..6546885c 100644 --- a/frontend/src/components/CacheView.jsx +++ b/frontend/src/components/CacheView.jsx @@ -16,7 +16,7 @@ import { DialogTitle, DialogActions, } from "@mui/material"; -import { useAlert } from "react-alert"; +//import { useAlert import { Edit as EditIcon, @@ -72,7 +72,7 @@ const CacheView = (props) => { const [dataValue, setDataValue] = React.useState({}); const [editCache, setEditCache] = React.useState(false); const [show, setShow] = useState({}); - const alert = useAlert(); + //const alert = useAlert(); useEffect(() => { listOrgCache(orgId); console.log("orgid", orgId); @@ -105,7 +105,7 @@ const CacheView = (props) => { } }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -148,7 +148,7 @@ const CacheView = (props) => { const deleteCache = (orgId, key) => { - alert.info("Attempting to delete Cache"); + toast("Attempting to delete Cache"); fetch(globalUrl + `/api/v1/orgs/${orgId}/cache/${key}`, { method: "DELETE", headers: { @@ -158,16 +158,16 @@ const CacheView = (props) => { }) .then((response) => { if (response.status === 200) { - alert.success("Successfully deleted Cache"); + toast("Successfully deleted Cache"); setTimeout(() => { listOrgCache(orgId); }, 1000); } else { - alert.error("Failed deleting Cache. Does it still exist?"); + toast("Failed deleting Cache. Does it still exist?"); } }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -197,12 +197,12 @@ const CacheView = (props) => { }) .then((responseJson) => { setAddCache(responseJson); - alert.success("Cache Edited Successfully!"); + toast("Cache Edited Successfully!"); listOrgCache(orgId); setModalOpen(false); }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -231,12 +231,12 @@ const CacheView = (props) => { }) .then((responseJson) => { setAddCache(responseJson); - alert.success("New Cache Added Successfully!"); + toast("New Cache Added Successfully!"); listOrgCache(orgId); setModalOpen(false); }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; diff --git a/frontend/src/components/ConfigureWorkflow.jsx b/frontend/src/components/ConfigureWorkflow.jsx index c24703fe..6c734c8e 100755 --- a/frontend/src/components/ConfigureWorkflow.jsx +++ b/frontend/src/components/ConfigureWorkflow.jsx @@ -112,9 +112,9 @@ const ConfigureWorkflow = (props) => { }) .then((response) => { if (response.status === 200) { - //alert.success("Successfully GOT app "+appId) + //toast("Successfully GOT app "+appId) } else { - alert.error("Failed getting app"); + toast("Failed getting app"); } return response.json(); @@ -128,7 +128,7 @@ const ConfigureWorkflow = (props) => { } }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -566,7 +566,7 @@ const ConfigureWorkflow = (props) => { .then((response) => { if (response.status !== 200) { //window.location.pathname = "/search" - //alert.error("Failed to find this app. Is it public?") + //toast("Failed to find this app. Is it public?") } return response.json(); @@ -574,16 +574,16 @@ const ConfigureWorkflow = (props) => { .then((responseJson) => { if (responseJson.success === false) { if (responseJson.reason !== undefined) { - alert.error("Failed to activate the app: "+responseJson.reason); + toast("Failed to activate the app: "+responseJson.reason); } else { - alert.error("Failed to activate the app"); + toast("Failed to activate the app"); } } else { - alert.success("App activated for your organization!"); + toast("App activated for your organization!"); } }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -693,7 +693,7 @@ const ConfigureWorkflow = (props) => { if (workflow.actions !== null) { //console.log(workflow.actions) - alert.info("Setting action to version "+action.update_version) + toast("Setting action to version "+action.update_version) for (let [key,keyval] in Object.entries(workflow.actions)) { if (workflow.actions[key].app_name === action.app_name && workflow.actions[key].app_version === action.app_version) { workflow.actions[key].app_version = action.update_version @@ -851,7 +851,7 @@ const ConfigureWorkflow = (props) => { console.log("NAVIGATOR: ", navigator); const clipboard = navigator.clipboard; if (clipboard === undefined) { - alert.error("Can only copy over HTTPS (port 3443)"); + toast("Can only copy over HTTPS (port 3443)"); return; } @@ -864,7 +864,7 @@ const ConfigureWorkflow = (props) => { /* Copy the text inside the text field */ document.execCommand("copy"); - alert.success("Copied Webhook URL"); + toast("Copied Webhook URL"); } }}> {webhook.description} diff --git a/frontend/src/components/CreatorGrid.jsx b/frontend/src/components/CreatorGrid.jsx index 9d23b439..712a2197 100644 --- a/frontend/src/components/CreatorGrid.jsx +++ b/frontend/src/components/CreatorGrid.jsx @@ -81,7 +81,7 @@ const CreatorGrid = props => { .then(response => { if (response.success === true) { setFormMessage(response.reason) - //alert.info("Thanks for submitting!") + //toast("Thanks for submitting!") } else { setFormMessage(errorMessage) } diff --git a/frontend/src/components/DocsGrid.jsx b/frontend/src/components/DocsGrid.jsx index fa194a25..947a2d76 100644 --- a/frontend/src/components/DocsGrid.jsx +++ b/frontend/src/components/DocsGrid.jsx @@ -69,7 +69,7 @@ const DocsGrid = props => { .then(response => { if (response.success === true) { setFormMessage(response.reason) - //alert.info("Thanks for submitting!") + //toast("Thanks for submitting!") } else { setFormMessage(errorMessage) } diff --git a/frontend/src/components/EditWorkflow.jsx b/frontend/src/components/EditWorkflow.jsx index 38ddbcf5..9971ff3d 100644 --- a/frontend/src/components/EditWorkflow.jsx +++ b/frontend/src/components/EditWorkflow.jsx @@ -127,7 +127,7 @@ const EditWorkflow = (props) => { } }) .catch((error) => { - //alert.error(error.toString()); + //toast(error.toString()); console.log("Get workflow error: ", error.toString()); }) } diff --git a/frontend/src/components/Files.jsx b/frontend/src/components/Files.jsx index 9f013ee3..2d5b68d2 100644 --- a/frontend/src/components/Files.jsx +++ b/frontend/src/components/Files.jsx @@ -29,7 +29,7 @@ import { Add as AddIcon, } from "@mui/icons-material"; -import { useAlert } from "react-alert"; +//import { useAlert import Dropzone from "../components/Dropzone.jsx"; import CodeEditor from "../components/ShuffleCodeEditor.jsx"; import theme from "../theme.jsx"; @@ -45,7 +45,7 @@ const Files = (props) => { const [openEditor, setOpenEditor] = React.useState(false); const [renderTextBox, setRenderTextBox] = React.useState(false); - const alert = useAlert(); + //const alert = useAlert(); const allowedFileTypes = ["txt", "py", "yaml", "yml","json", "html", "js", "csv", "log"] var upload = ""; @@ -113,7 +113,7 @@ const Files = (props) => { } }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -139,12 +139,12 @@ const Files = (props) => { }) .then((responseJson) => { if (responseJson.success) { - alert.info("Successfully deleted file " + file.name); + toast("Successfully deleted file " + file.name); } else if ( responseJson.reason !== undefined && responseJson.reason !== null ) { - alert.error("Failed to delete file: " + responseJson.reason); + toast("Failed to delete file: " + responseJson.reason); } setTimeout(() => { getFiles(); @@ -153,7 +153,7 @@ const Files = (props) => { console.log(responseJson); }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -178,7 +178,7 @@ const Files = (props) => { // console.log("respdata type ->", typeof(respdata)); if (respdata.length === 0) { - alert.error("Failed getting file. Is it deleted?"); + toast("Failed getting file. Is it deleted?"); return; } return respdata @@ -189,7 +189,7 @@ const Files = (props) => { //console.log("filecontent state ",fileContent); }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -210,7 +210,7 @@ const Files = (props) => { }) .then((respdata) => { if (respdata.length === 0) { - alert.error("Failed getting file. Is it deleted?"); + toast("Failed getting file. Is it deleted?"); return; } @@ -249,7 +249,7 @@ const Files = (props) => { //setSchedules(responseJson) }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -291,11 +291,11 @@ const Files = (props) => { if (responseJson.success === true) { handleFileUpload(responseJson.id, file); } else { - alert.error("Failed to upload file ", filename); + toast("Failed to upload file ", filename); } }) .catch((error) => { - alert.error("Failed to upload file ", filename); + toast("Failed to upload file ", filename); console.log(error.toString()); }); }; @@ -312,7 +312,7 @@ const Files = (props) => { .then((response) => { if (response.status !== 200 && response.status !== 201) { console.log("Status not 200 for apps :O!"); - alert.error("File was created, but failed to upload."); + toast("File was created, but failed to upload."); return; } @@ -323,7 +323,7 @@ const Files = (props) => { //setFiles(responseJson) }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -364,7 +364,7 @@ const Files = (props) => { const files = isDropzone ? e.dataTransfer.files : e.target.files; //const reader = new FileReader(); - //alert.info("Starting fileupload") + //toast("Starting fileupload") uploadFiles(files); }; @@ -742,7 +742,7 @@ const Files = (props) => { ) { const clipboard = navigator.clipboard; if (clipboard === undefined) { - alert.error( + toast( "Can only copy over HTTPS (port 3443)" ); return; @@ -758,7 +758,7 @@ const Files = (props) => { /* Copy the text inside the text field */ document.execCommand("copy"); - alert.info(file.id + " copied to clipboard"); + toast(file.id + " copied to clipboard"); } }} > diff --git a/frontend/src/components/Header.jsx b/frontend/src/components/Header.jsx index 892334e3..e54877b2 100644 --- a/frontend/src/components/Header.jsx +++ b/frontend/src/components/Header.jsx @@ -42,7 +42,7 @@ import { Lightbulb as LightbulbIcon, } from "@mui/icons-material"; -import { useAlert } from "react-alert"; +//import { useAlert import SearchField from '../components/Searchfield.jsx' const hoverColor = "#f85a3e" @@ -51,7 +51,7 @@ const hoverOutColor = "#e8eaf6" const Header = props => { const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, homePage, userdata, serverside, } = props; //const theme = useTheme(); - const alert = useAlert() + //const alert = useAlert() const [HomeHoverColor, setHomeHoverColor] = useState(hoverOutColor); @@ -101,7 +101,7 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho setNotifications([]) handleClose() } else { - alert.error("Failed dismissing notifications. Please try again later.") + toast("Failed dismissing notifications. Please try again later.") } }) .catch(error => { @@ -131,7 +131,7 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho console.log("NEW NOTIFICATIONS: ", newNotifications) setNotifications(newNotifications) } else { - alert.error("Failed dismissing notification. Please try again later.") + toast("Failed dismissing notification. Please try again later.") } }) .catch(error => { @@ -406,9 +406,9 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho setTimeout(() => { window.location.reload() }, 2000) - alert.success("Successfully changed active organization - refreshing!") + toast("Successfully changed active organization - refreshing!") } else { - alert.error("Failed changing org: ", responseJson.reason) + toast("Failed changing org: ", responseJson.reason) } }) .catch(error => { diff --git a/frontend/src/components/Oauth2Auth.jsx b/frontend/src/components/Oauth2Auth.jsx index 8bccfb5a..4c37a251 100755 --- a/frontend/src/components/Oauth2Auth.jsx +++ b/frontend/src/components/Oauth2Auth.jsx @@ -1,7 +1,7 @@ import React, { useRef, useState, useEffect, useLayoutEffect } from "react"; import { useParams, useNavigate, Link } from "react-router-dom"; import theme from '../theme.jsx'; -import { useAlert } from "react-alert"; +//import { useAlert import { v4 as uuidv4 } from "uuid"; import { @@ -99,7 +99,7 @@ const AuthenticationOauth2 = (props) => { } = props; let navigate = useNavigate(); - const alert = useAlert() + //const alert = useAlert() //const [update, setUpdate] = React.useState("|") const [defaultConfigSet, setDefaultConfigSet] = React.useState( @@ -422,7 +422,7 @@ const AuthenticationOauth2 = (props) => { //} //while(open === true) } catch (e) { - alert.error( + toast( "Failed authentication - probably bad credentials. Try again" ); setButtonClicked(false); @@ -451,7 +451,7 @@ const AuthenticationOauth2 = (props) => { console.log("NEW AUTH: ", authenticationOption); if (authenticationOption.label.length === 0) { authenticationOption.label = `Auth for ${selectedApp.name}`; - //alert.info("Label can't be empty") + //toast("Label can't be empty") //return } @@ -479,7 +479,7 @@ const AuthenticationOauth2 = (props) => { selectedApp.authentication.parameters[key].name ] = "false"; } else { - alert.info( + toast( "Field " + selectedApp.authentication.parameters[key].name.replace("_basic", "", -1).replace("_", " ", -1) + " can't be empty" ); diff --git a/frontend/src/components/OrgHeader.jsx b/frontend/src/components/OrgHeader.jsx index 3b5a091a..b29ed7a9 100644 --- a/frontend/src/components/OrgHeader.jsx +++ b/frontend/src/components/OrgHeader.jsx @@ -17,7 +17,7 @@ import { Save as SaveIcon, } from "@mui/icons-material"; -import { useAlert } from "react-alert"; +//import { useAlert const useStyles = makeStyles({ notchedOutline: { @@ -39,7 +39,7 @@ const OrgHeader = (props) => { handleEditOrg, } = props; - const alert = useAlert(); + //const alert = useAlert(); const classes = useStyles(); var upload = ""; @@ -210,13 +210,13 @@ const OrgHeader = (props) => { const invalid = ["#", ":", "."]; for (var key in invalid) { if (e.target.value.includes(invalid[key])) { - alert.error("Can't use " + invalid[key] + " in name"); + toast("Can't use " + invalid[key] + " in name"); return; } } if (e.target.value.length > 100) { - alert.error("Choose a shorter name."); + toast("Choose a shorter name."); return; } diff --git a/frontend/src/components/ParsedAction.jsx b/frontend/src/components/ParsedAction.jsx index 10353f2f..3751dfa7 100755 --- a/frontend/src/components/ParsedAction.jsx +++ b/frontend/src/components/ParsedAction.jsx @@ -7,7 +7,7 @@ import { validateJson, GetIconInfo } from "../views/Workflows.jsx"; import { GetParsedPaths } from "../views/Apps.jsx"; import { sortByKey } from "../views/AngularWorkflow.jsx"; import { NestedMenuItem } from "mui-nested-menu"; -import { useAlert } from "react-alert"; +//import { useAlert import { ButtonGroup, @@ -172,7 +172,7 @@ const ParsedAction = (props) => { } = props; const classes = useStyles(); - const alert = useAlert() + //const alert = useAlert() const [hideBody, setHideBody] = React.useState(true); const [activateHidingBodyButton, setActivateHidingBodyButton] = React.useState(false); @@ -227,9 +227,9 @@ const ParsedAction = (props) => { }) .then((response) => { if (response.status === 200) { - //alert.success("Successfully GOT app "+appId) + //toast("Successfully GOT app "+appId) } else { - alert.error("Failed getting app"); + toast("Failed getting app"); } return response.json(); @@ -290,7 +290,7 @@ const ParsedAction = (props) => { //foundparams.push(param.name) } } else { - alert.error("Couldn't find action " + selectedAction.name); + toast("Couldn't find action " + selectedAction.name); } selectedAction.errors = []; @@ -306,7 +306,7 @@ const ParsedAction = (props) => { } }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; diff --git a/frontend/src/components/Priorities.jsx b/frontend/src/components/Priorities.jsx index 86215b6f..f003540c 100644 --- a/frontend/src/components/Priorities.jsx +++ b/frontend/src/components/Priorities.jsx @@ -12,7 +12,7 @@ import { } from "@mui/material"; import Priority from "../components/Priority.jsx"; -import { useAlert } from "react-alert"; +//import { useAlert const Priorities = (props) => { const { globalUrl, userdata, serverside, billingInfo, stripeKey, checkLogin, setAdminTab, setCurTab, } = props; diff --git a/frontend/src/components/Priority.jsx b/frontend/src/components/Priority.jsx index a4f93729..3a23f15f 100644 --- a/frontend/src/components/Priority.jsx +++ b/frontend/src/components/Priority.jsx @@ -17,7 +17,7 @@ import { AutoFixHigh as AutoFixHighIcon, ArrowForward as ArrowForwardIcon, } from '@mui/icons-material'; -import { useAlert } from "react-alert"; +//import { useAlert const Priority = (props) => { const { globalUrl, userdata, serverside, priority, checkLogin, setAdminTab, setCurTab, } = props; @@ -56,14 +56,14 @@ const Priority = (props) => { } } else { if (responseJson.success === false && responseJson.reason !== undefined) { - alert.error("Failed change recommendation: ", responseJson.reason) + toast("Failed change recommendation: ", responseJson.reason) } else { - alert.error("Failed change recommendation"); + toast("Failed change recommendation"); } } }) .catch((error) => { - alert.info("Failed dismissing alert. Please contact support@shuffler.io if this persists."); + toast("Failed dismissing alert. Please contact support@shuffler.io if this persists."); }); } diff --git a/frontend/src/components/ShuffleCodeEditor.jsx b/frontend/src/components/ShuffleCodeEditor.jsx index 21293d7c..4b9dd48a 100644 --- a/frontend/src/components/ShuffleCodeEditor.jsx +++ b/frontend/src/components/ShuffleCodeEditor.jsx @@ -861,12 +861,12 @@ const CodeEditor = (props) => { var newResult = {} if (responseJson.success === true && responseJson.result !== null && responseJson.result !== undefined && responseJson.result.length > 0) { const result = responseJson.result.slice(0, 50)+"..." - //alert.info("SUCCESS: "+result) + //toast("SUCCESS: "+result) const validate = validateJson(responseJson.result) newResult = validate } else if (responseJson.success === false && responseJson.reason !== undefined && responseJson.reason !== null) { - alert.error(responseJson.reason) + toast(responseJson.reason) newResult = {"valid": false, "result": responseJson.reason} } else if (responseJson.success === true) { newResult = {"valid": false, "result": "Couldn't finish execution. Please fill all the required fields, and retry the execution."} @@ -882,7 +882,7 @@ const CodeEditor = (props) => { setExecuting(false) }) .catch(error => { - //alert.error("Execution error: "+error.toString()) + //toast("Execution error: "+error.toString()) console.log("error: ", error) setExecuting(false) }) diff --git a/frontend/src/components/UsecaseSearch.jsx b/frontend/src/components/UsecaseSearch.jsx index ba8a98a1..6d0f2eef 100644 --- a/frontend/src/components/UsecaseSearch.jsx +++ b/frontend/src/components/UsecaseSearch.jsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from "react"; import theme from '../theme.jsx'; import { useNavigate, Link } from "react-router-dom"; -import { useAlert } from "react-alert"; +//import { useAlert import ConfigureWorkflow from "../components/ConfigureWorkflow.jsx"; import PaperComponent from "../components/PaperComponent.jsx" import AuthenticationOauth2 from "../components/Oauth2Auth.jsx"; @@ -349,14 +349,14 @@ const UsecaseSearch = (props) => { const [firstRequest, setFirstRequest] = React.useState(true); const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"; - const alert = useAlert() + //const alert = useAlert() useEffect(() => { // if (firstRequest !== true && workflow.id !== undefined && autotry === true && setUsecaseSearch !== undefined && authenticationModalOpen === false && configureWorkflowModalOpen === false) { // if (autotry === true && configureWorkflowModalOpen === false && workflow.id !== undefined && setUsecaseSearch !== undefined) { console.log("Close it?") - alert.info("Workflow successfully added! Add more apps, and we will suggest more workflows") + toast("Workflow successfully added! Add more apps, and we will suggest more workflows") if (setCloseWindow !== undefined) { setCloseWindow(true) @@ -793,7 +793,7 @@ const UsecaseSearch = (props) => { console.log("Deleted workflow") }) .catch((error) => { - //alert.error(error.toString()); + //toast(error.toString()); console.log("Delete workflow error: ", error.toString()); }) } @@ -822,7 +822,7 @@ const UsecaseSearch = (props) => { } }) .catch((error) => { - //alert.error(error.toString()); + //toast(error.toString()); console.log("Get workflows error: ", error.toString()); }) } @@ -894,9 +894,9 @@ const UsecaseSearch = (props) => { .then((responseJson) => { if (responseJson.success === false) { if (responseJson.reason !== undefined) { - alert.error("Error setting workflow: ", responseJson.reason) + toast("Error setting workflow: ", responseJson.reason) } else { - alert.error("Error setting workflow.") + toast("Error setting workflow.") } return @@ -905,7 +905,7 @@ const UsecaseSearch = (props) => { return responseJson; }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); } @@ -930,7 +930,7 @@ const UsecaseSearch = (props) => { if (responseJson.success === false) { if (responseJson.reason !== null && responseJson.reason !== undefined) { - //alert.error(responseJson.reason) + //toast(responseJson.reason) } if (responseJson.source === "") { @@ -1009,13 +1009,13 @@ const UsecaseSearch = (props) => { responseJson.status, ).then((response) => { if (response !== undefined) { - alert.success("Successfully generated " + responseJson.name); + toast("Successfully generated " + responseJson.name); } }); } }) .catch((error) => { - alert.error("Generate error: " + error.toString()); + toast("Generate error: " + error.toString()); }) @@ -1057,7 +1057,7 @@ const UsecaseSearch = (props) => { .catch((error) => { setIsUploading(false) console.log("Merge err: ", error.toString()) - //alert.error("Err: " + error.toString()); + //toast("Err: " + error.toString()); }); } @@ -1207,7 +1207,7 @@ const UsecaseSearch = (props) => { } if (changed) { - //alert.error("Errors were found. Click them to sort sort them out or go to the next usecase.") + //toast("Errors were found. Click them to sort sort them out or go to the next usecase.") //setUpdate(Math.random()) //setIsUploading(false) @@ -1268,13 +1268,13 @@ const UsecaseSearch = (props) => { }) .then((responseJson) => { if (responseJson.success === false) { - alert.error("Failed to activate the app") + toast("Failed to activate the app") } else { - //alert.success("App activated for your organization! Refresh the page to use the app.") + //toast("App activated for your organization! Refresh the page to use the app.") } }) .catch(error => { - //alert.error(error.toString()) + //toast(error.toString()) console.log("Activate app error: ", error.toString()) }); } @@ -1304,9 +1304,9 @@ const UsecaseSearch = (props) => { .then((responseJson) => { if (responseJson.success === false) { if (responseJson.reason !== undefined) { - alert.error("Failed updating default app: " + responseJson.reason) + toast("Failed updating default app: " + responseJson.reason) } else { - alert.error("Failed to update framework for your org.") + toast("Failed to update framework for your org.") } } else { @@ -1319,7 +1319,7 @@ const UsecaseSearch = (props) => { //setFrameworkData(responseJson) }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); //setFrameworkLoaded(true) }) } @@ -1516,7 +1516,7 @@ const UsecaseSearch = (props) => { return (
{ if (subdata.disabled === true) { - //alert.info("Usecase not available yet.") + //toast("Usecase not available yet.") return } diff --git a/frontend/src/components/WelcomeForm2.jsx b/frontend/src/components/WelcomeForm2.jsx index 5d887851..83d43e2b 100644 --- a/frontend/src/components/WelcomeForm2.jsx +++ b/frontend/src/components/WelcomeForm2.jsx @@ -38,7 +38,7 @@ import { Chip, ButtonGroup, } from "@mui/material"; -import { useAlert } from "react-alert"; +//import { useAlert import { useNavigate, Link } from "react-router-dom"; import WorkflowSearch from '../components/Workflowsearch.jsx'; @@ -134,7 +134,7 @@ const WelcomeForm = (props) => { const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"; - const alert = useAlert(); + //const alert = useAlert(); let navigate = useNavigate(); const onNodeSelect = (label) => { @@ -262,16 +262,16 @@ const WelcomeForm = (props) => { response.json().then((responseJson) => { if (responseJson["success"] === false) { console.log("Update user success") - //alert.error("Failed updating org: ", responseJson.reason); + //toast("Failed updating org: ", responseJson.reason); } else { console.log("Update success!") - //alert.success("Successfully edited org!"); + //toast("Successfully edited org!"); } }) ) .catch((error) => { console.log("Update err: ", error.toString()) - //alert.error("Err: " + error.toString()); + //toast("Err: " + error.toString()); }); } @@ -308,15 +308,15 @@ const WelcomeForm = (props) => { response.json().then((responseJson) => { if (responseJson["success"] === false) { console.log("Update of org failed") - //alert.error("Failed updating org: ", responseJson.reason); + //toast("Failed updating org: ", responseJson.reason); } else { - //alert.success("Successfully edited org!"); + //toast("Successfully edited org!"); } }) ) .catch((error) => { console.log("Update err: ", error.toString()) - //alert.error("Err: " + error.toString()); + //toast("Err: " + error.toString()); }); } diff --git a/frontend/src/components/WorkflowGrid.jsx b/frontend/src/components/WorkflowGrid.jsx index fb19e806..e721dc3f 100644 --- a/frontend/src/components/WorkflowGrid.jsx +++ b/frontend/src/components/WorkflowGrid.jsx @@ -69,7 +69,7 @@ const AppGrid = props => { .then(response => { if (response.success === true) { setFormMessage(response.reason) - //alert.info("Thanks for submitting!") + //toast("Thanks for submitting!") } else { setFormMessage(errorMessage) } @@ -158,7 +158,7 @@ const AppGrid = props => { } }) .catch((error) => { - //alert.error("ERROR: " + error.toString()); + //toast("ERROR: " + error.toString()); console.log("ERROR: " + error.toString()); }); }; diff --git a/frontend/src/components/Workflowsearch.jsx b/frontend/src/components/Workflowsearch.jsx index 267face5..b8f4c022 100644 --- a/frontend/src/components/Workflowsearch.jsx +++ b/frontend/src/components/Workflowsearch.jsx @@ -53,7 +53,7 @@ const WorkflowSearch = props => { .then(response => { if (response.success === true) { setFormMessage(response.reason) - //alert.info("Thanks for submitting!") + //toast("Thanks for submitting!") } else { setFormMessage(errorMessage) } diff --git a/frontend/src/views/Admin.jsx b/frontend/src/views/Admin.jsx index 0befde05..95a4f042 100755 --- a/frontend/src/views/Admin.jsx +++ b/frontend/src/views/Admin.jsx @@ -75,7 +75,8 @@ import { FmdGood as FmdGoodIcon, } from "@mui/icons-material"; -import { useAlert } from "react-alert"; +//import { useAlert +import { ToastContainer, toast } from "react-toastify" import Dropzone from "../components/Dropzone.jsx"; import HandlePaymentNew from "../views/HandlePaymentNew.jsx"; import OrgHeader from "../components/OrgHeader.jsx"; @@ -216,13 +217,13 @@ const Admin = (props) => { .then((responseJson) => { //console.log("RESPONSE: ", responseJson) if (responseJson.success === true) { - //alert.info(responseJson.reason) + //toast(responseJson.reason) setImage2FA(responseJson.reason); setSecret2FA(responseJson.extra); } }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -256,7 +257,7 @@ const Admin = (props) => { //} }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -287,7 +288,7 @@ const Admin = (props) => { ] */ - const alert = useAlert(); + //const alert = useAlert(); const handleStatusChange = (event) => { const { value } = event.target; console.log("value: ", value) @@ -465,7 +466,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user } const deleteAuthentication = (data) => { - alert.info("Deleting auth " + data.label); + toast("Deleting auth " + data.label); // Just use this one? const url = globalUrl + "/api/v1/apps/authentication/" + data.id; @@ -480,13 +481,13 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user .then((response) => response.json().then((responseJson) => { if (responseJson["success"] === false) { - alert.error("Failed deleting auth"); + toast("Failed deleting auth"); } else { // Need to wait because query in ES is too fast setTimeout(() => { getAppAuthentication(); }, 1000); - //alert.success("Successfully deleted authentication!") + //toast("Successfully deleted authentication!") } }) ) @@ -518,12 +519,12 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user response.json().then((responseJson) => { console.log("RESP: ", responseJson); if (responseJson["success"] === false) { - alert.error("Failed stopping schedule"); + toast("Failed stopping schedule"); } else { setTimeout(() => { getSchedules(); }, 1500); - //alert.success("Successfully stopped schedule!") + //toast("Successfully stopped schedule!") } }) ) @@ -534,7 +535,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user if (userdata.support === true && selectedOrganization.id !== "" && selectedOrganization.id !== undefined && selectedOrganization.id !== null && selectedOrganization.id !== userdata.active_org.id) { - alert.info("Refreshing window to fix org support access") + toast("Refreshing window to fix org support access") window.location.reload() return null } @@ -559,15 +560,15 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user .then((response) => { if (response.status === 200) { } else { - //alert.info("Wrong code sent.") - //alert.info("Wrong code sent. Please try again.") + //toast("Wrong code sent.") + //toast("Wrong code sent. Please try again.") } return response.json(); }) .then((responseJson) => { if (responseJson.success === true) { - alert.info("Successfully enabled 2fa"); + toast("Successfully enabled 2fa"); setTimeout(() => { getUsers(); @@ -579,19 +580,19 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user setSelectedUserModalOpen(false); }, 1000); } else { - alert.info("Wrong code sent. Please try again."); - //alert.error("Failed setting 2fa: ", responseJson.reason) + toast("Wrong code sent. Please try again."); + //toast("Failed setting 2fa: ", responseJson.reason) } }) .catch((error) => { - alert.info("Wrong code sent. Please try again."); - //alert.error("Err: " + error.toString()) + toast("Wrong code sent. Please try again."); + //toast("Err: " + error.toString()) }); }; const handleStopOrgSync = (org_id) => { if (org_id === undefined || org_id === null) { - alert.error("Couldn't get org " + org_id); + toast("Couldn't get org " + org_id); return; } @@ -612,10 +613,10 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user .then((response) => { if (response.status === 200) { console.log("Cloud sync success?"); - alert.success("Successfully stopped cloud sync"); + toast("Successfully stopped cloud sync"); } else { console.log("Cloud sync fail?"); - alert.error( + toast( "Failed stopping sync. Try again, and contact support if this persists." ); } @@ -628,7 +629,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user }, 1000); }) .catch((error) => { - alert.error("Err: " + error.toString()); + toast("Err: " + error.toString()); }); }; @@ -672,16 +673,16 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user responseJson.reason !== undefined ) { setOrgSyncResponse(responseJson.reason); - alert.error("Failed to handle sync: " + responseJson.reason); + toast("Failed to handle sync: " + responseJson.reason); } else if (!responseJson.success) { - alert.error("Failed to handle sync."); + toast("Failed to handle sync."); } else { getOrgs(); if (disableSync) { - alert.success("Successfully disabled sync!"); + toast("Successfully disabled sync!"); setOrgSyncResponse("Successfully disabled syncronization"); } else { - alert.success("Cloud Syncronization successfully set up!"); + toast("Cloud Syncronization successfully set up!"); setOrgSyncResponse( "Successfully started syncronization. Cloud features you now have access to can be seen below." ); @@ -696,7 +697,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user }) .catch((error) => { setLoading(false); - alert.error("Err: " + error.toString()); + toast("Err: " + error.toString()); }); }; @@ -718,16 +719,16 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user .then((response) => response.json().then((responseJson) => { if (responseJson["success"] === false) { - alert.error("Failed changing authentication"); + toast("Failed changing authentication"); } else { - //alert.success("Successfully password!") + //toast("Successfully password!") setSelectedUserModalOpen(false); getAppAuthentication(); } }) ) .catch((error) => { - alert.error("Err: " + error.toString()); + toast("Err: " + error.toString()); }); }; @@ -766,16 +767,16 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user .then((response) => response.json().then((responseJson) => { if (responseJson["success"] === false) { - alert.error("Failed updating org: ", responseJson.reason); + toast("Failed updating org: ", responseJson.reason); } else { if (lead_info === undefined || lead_info === null || lead_info === []) { - alert.success("Successfully edited org!"); + toast("Successfully edited org!"); } } }) ) .catch((error) => { - alert.error("Err: " + error.toString()); + toast("Err: " + error.toString()); }); }; @@ -800,9 +801,9 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user .then((response) => response.json().then((responseJson) => { if (responseJson["success"] === false) { - alert.error("Failed overwriting appauth in workflows"); + toast("Failed overwriting appauth in workflows"); } else { - alert.success("Successfully updated auth everywhere!"); + toast("Successfully updated auth everywhere!"); setSelectedUserModalOpen(false); setTimeout(() => { getAppAuthentication(); @@ -811,7 +812,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user }) ) .catch((error) => { - alert.error("Err: " + error.toString()); + toast("Err: " + error.toString()); }); }; @@ -835,12 +836,12 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user response.json().then((responseJson) => { if (responseJson["success"] === false) { if (responseJson.reason !== undefined) { - alert.error(responseJson.reason); + toast(responseJson.reason); } else { - alert.error("Failed creating suborg. Please try again"); + toast("Failed creating suborg. Please try again"); } } else { - alert.success( + toast( "Successfully created suborg. Reloading in 3 seconds!" ); setSelectedUserModalOpen(false); @@ -855,7 +856,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user }) ) .catch((error) => { - alert.error("Err: " + error.toString()); + toast("Err: " + error.toString()); }); }; @@ -878,18 +879,18 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user response.json().then((responseJson) => { if (responseJson["success"] === false) { if (responseJson.reason !== undefined) { - alert.error(responseJson.reason); + toast(responseJson.reason); } else { - alert.error("Failed setting new password"); + toast("Failed setting new password"); } } else { - alert.success("Successfully updated password!"); + toast("Successfully updated password!"); setSelectedUserModalOpen(false); } }) ) .catch((error) => { - alert.error("Err: " + error.toString()); + toast("Err: " + error.toString()); }); }; @@ -914,9 +915,9 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user }) .then((responseJson) => { if (!responseJson.success && responseJson.reason !== undefined) { - alert.error("Failed to deactivate user: " + responseJson.reason); + toast("Failed to deactivate user: " + responseJson.reason); } else { - alert.success("Changed activation for user " + data.id); + toast("Changed activation for user " + data.id); } }) @@ -939,7 +940,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user } if (orgId.length === 0) { - alert.error("Organization ID not defined. Please contact us on https://shuffler.io if this persists logout."); + toast("Organization ID not defined. Please contact us on https://shuffler.io if this persists logout."); return; } @@ -960,7 +961,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user }) .then((responseJson) => { if (responseJson["success"] === false) { - alert.error("Failed getting your org. If this persists, please contact support."); + toast("Failed getting your org. If this persists, please contact support."); } else { if ( responseJson.sync_features === undefined || @@ -1032,7 +1033,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user }) .catch((error) => { console.log("Error getting org: ", error); - alert.error("Error getting current organization"); + toast("Error getting current organization"); }); }; @@ -1061,7 +1062,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user response.json().then((responseJson) => { if (responseJson["success"] === false) { setLoginInfo("Error: " + responseJson.reason); - alert.error("Failed to send email (2). Please try again and contact support if this persists.") + toast("Failed to send email (2). Please try again and contact support if this persists.") } else { setLoginInfo(""); setModalOpen(false); @@ -1069,13 +1070,13 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user getUsers(); }, 1000); - alert.info("Invite sent! They will show up in the list when they have accepted the invite.") + toast("Invite sent! They will show up in the list when they have accepted the invite.") } }) ) .catch((error) => { console.log("Error in userdata: ", error); - alert.error("Failed to send email. Please try again and contact support if this persists.") + toast("Failed to send email. Please try again and contact support if this persists.") }); }; @@ -1117,12 +1118,12 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user // Horrible frontend fix for environments const setDefaultEnvironment = (environment) => { // FIXME - add more checks to this - alert.info("Setting default env to " + environment.name); + toast("Setting default env to " + environment.name); var newEnv = []; for (var key in environments) { if (environments[key].id == environment.id) { if (environments[key].archived) { - alert.error("Can't set archived to default"); + toast("Can't set archived to default"); return; } @@ -1150,7 +1151,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user .then((response) => response.json().then((responseJson) => { if (responseJson["success"] === false) { - alert.error(responseJson.reason); + toast(responseJson.reason); setTimeout(() => { getEnvironments(); }, 1500); @@ -1181,7 +1182,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user .then((response) => response.json().then((responseJson) => { if (responseJson["success"] === false) { - alert.error(responseJson.reason); + toast(responseJson.reason); getEnvironments(); } else { setLoginInfo(""); @@ -1196,7 +1197,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user }; const rerunCloudWorkflows = (environment) => { - alert.info("Starting execution reruns. This can run in the background.") + toast("Starting execution reruns. This can run in the background.") fetch( `${globalUrl}/api/v1/environments/${environment.id}/rerun`, { @@ -1209,8 +1210,8 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user console.log("Status not 200 for apps :O!"); return; } else { - alert.error(response.reason); - //alert.info("Aborted all dangling workflows"); + toast(response.reason); + //toast("Aborted all dangling workflows"); } return response.json(); @@ -1221,7 +1222,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user //setFiles(responseJson) }) .catch((error) => { - //alert.error(error.toString()) + //toast(error.toString()) }); }; @@ -1238,10 +1239,10 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user .then((response) => { if (response.status !== 200) { console.log("Status not 200 for apps :O!"); - alert.error("Failed aborting dangling workflows"); + toast("Failed aborting dangling workflows"); return; } else { - alert.info("Aborted all dangling workflows"); + toast("Aborted all dangling workflows"); } return response.json(); @@ -1252,7 +1253,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user //setFiles(responseJson) }) .catch((error) => { - //alert.error(error.toString()) + //toast(error.toString()) }); }; @@ -1260,17 +1261,17 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user // FIXME - add some check here ROFL //const name = environment.name - //alert.info("Modifying environment " + name) + //toast("Modifying environment " + name) //var newEnv = [] //for (var key in environments) { // if (environments[key].Name == name) { // if (environments[key].default) { - // alert.error("Can't modify the default environment") + // toast("Can't modify the default environment") // return // } // if (environments[key].type === "cloud" && !environments[key].archived) { - // alert.error("Can't modify cloud environments") + // toast("Can't modify cloud environments") // return // } @@ -1281,17 +1282,17 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user //} const id = environment.id; - //alert.info("Modifying environment " + environment.Name) + //toast("Modifying environment " + environment.Name) var newEnv = []; for (var key in environments) { if (environments[key].id == id) { if (environments[key].default) { - alert.error("Can't modify the default environment"); + toast("Can't modify the default environment"); return; } if (environments[key].type === "cloud" && !environments[key].archived) { - alert.error("Can't modify cloud environments"); + toast("Can't modify cloud environments"); return; } @@ -1314,7 +1315,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user .then((response) => response.json().then((responseJson) => { if (responseJson["success"] === false) { - alert.error(responseJson.reason); + toast(responseJson.reason); getEnvironments(); } else { setLoginInfo(""); @@ -1387,7 +1388,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user setSchedules(responseJson); }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -1414,11 +1415,11 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user //console.log(responseJson) setAuthentication(responseJson.data); } else { - alert.error("Failed getting authentications"); + toast("Failed getting authentications"); } }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -1443,7 +1444,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user setEnvironments(responseJson); }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -1471,7 +1472,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user setOrganizations(responseJson); }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -1497,7 +1498,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user setUsers(responseJson); }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -1672,10 +1673,10 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user }) .then((responseJson) => { if (!responseJson.success && responseJson.reason !== undefined) { - alert.error("Failed setting user: " + responseJson.reason); + toast("Failed setting user: " + responseJson.reason); } else { - //alert.success("Set the user field " + field + " to " + value); - alert.success("Successfully updated user field " + field) + //toast("Set the user field " + field + " to " + value); + toast("Successfully updated user field " + field) if (field !== "suborgs") { setSelectedUserModalOpen(false); @@ -1712,9 +1713,9 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user .then((responseJson) => { console.log("RESP: ", responseJson); if (!responseJson.success && responseJson.reason !== undefined) { - alert.error("Failed getting new: " + responseJson.reason); + toast("Failed getting new: " + responseJson.reason); } else { - alert.success("Got new API key"); + toast("Got new API key"); } }) .catch((error) => { @@ -1808,9 +1809,9 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user } if (error) { - alert.error("All fields must have a new value"); + toast("All fields must have a new value"); } else { - alert.success("Saving new version of this authentication"); + toast("Saving new version of this authentication"); selectedAuthentication.fields = authenticationFields; saveAuthentication(selectedAuthentication); setSelectedAuthentication({}); @@ -1827,7 +1828,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user const handleOrgEditChange = (event) => { if (userdata.id === selectedUser.id) { - alert.info("Can't remove orgs from yourself"); + toast("Can't remove orgs from yourself"); return; } @@ -2424,7 +2425,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user if (copyText !== null && copyText !== undefined) { const clipboard = navigator.clipboard; if (clipboard === undefined) { - alert.error("Can only copy over HTTPS (port 3443)"); + toast("Can only copy over HTTPS (port 3443)"); return; } @@ -2438,7 +2439,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user /* Copy the text inside the text field */ document.execCommand("copy"); - alert.info(org_id + " copied to clipboard"); + toast(org_id + " copied to clipboard"); } }} > @@ -3115,7 +3116,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user ) { const clipboard = navigator.clipboard; if (clipboard === undefined) { - alert.error( + toast( "Can only copy over HTTPS (port 3443)" ); return; @@ -3131,7 +3132,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user /* Copy the text inside the text field */ document.execCommand("copy"); - alert.info("Apikey copied to clipboard"); + toast("Apikey copied to clipboard"); } }} > @@ -3786,14 +3787,14 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user } } else { if (responseJson.success === false && responseJson.reason !== undefined) { - alert.error("Failed change recommendation: ", responseJson.reason) + toast("Failed change recommendation: ", responseJson.reason) } else { - alert.error("Failed change recommendation"); + toast("Failed change recommendation"); } } }) .catch((error) => { - alert.info("Failed dismissing alert. Please contact support@shuffler.io if this persists."); + toast("Failed dismissing alert. Please contact support@shuffler.io if this persists."); }); } @@ -3953,7 +3954,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user disabled={environment.Type === "cloud"} onClick={() => { if (environment.Type === "cloud") { - alert.info("No Orborus necessary for environment cloud. Create and use a different environment to run executions on-premises.") + toast("No Orborus necessary for environment cloud. Create and use a different environment to run executions on-premises.") return } @@ -3964,7 +3965,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user if (copyText !== null && copyText !== undefined) { const clipboard = navigator.clipboard; if (clipboard === undefined) { - alert.error("Can only copy over HTTPS (port 3443)"); + toast("Can only copy over HTTPS (port 3443)"); return; } @@ -3978,7 +3979,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user /* Copy the text inside the text field */ document.execCommand("copy"); - alert.info("Orborus command copied to clipboard"); + toast("Orborus command copied to clipboard"); } }} > diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index 5378d297..bc2191aa 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -12,7 +12,8 @@ import { useBeforeunload } from "react-beforeunload"; import ReactJson from "react-json-view"; import { NestedMenuItem } from 'mui-nested-menu'; import ReactMarkdown from "react-markdown"; -import { useAlert } from "react-alert"; +//import { useAlert +import { ToastContainer, toast } from "react-toastify" import { isMobile } from "react-device-detect" import aa from 'search-insights' import Drift from "react-driftjs"; @@ -384,7 +385,7 @@ const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e52 const AngularWorkflow = (defaultprops) => { const { globalUrl, isLoggedIn, isLoaded, userdata, data_id } = defaultprops; const referenceUrl = globalUrl + "/api/v1/hooks/"; - const alert = useAlert() + //const alert = useAlert() let navigate = useNavigate(); const params = useParams(); var props = JSON.parse(JSON.stringify(defaultprops)) @@ -584,9 +585,9 @@ const AngularWorkflow = (defaultprops) => { }) .then((response) => { if (response.status === 200) { - //alert.success("Successfully GOT app "+appId) + //toast("Successfully GOT app "+appId) } else { - //alert.error("Failed getting app"); + //toast("Failed getting app"); } return response.json(); @@ -604,7 +605,7 @@ const AngularWorkflow = (defaultprops) => { }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -644,7 +645,7 @@ const AngularWorkflow = (defaultprops) => { setListCache(responseJson); }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -746,7 +747,7 @@ const AngularWorkflow = (defaultprops) => { } }) .catch((error) => { - //alert.error(error.toString()); + //toast(error.toString()); console.log("Workflow error: ", error.toString()) }); }; @@ -893,17 +894,17 @@ const AngularWorkflow = (defaultprops) => { }) .then((responseJson) => { if (!responseJson.success) { - alert.error("Failed to set app auth: " + responseJson.reason); + toast("Failed to set app auth: " + responseJson.reason); } else { getAppAuthentication(true, false); setAuthenticationModalOpen(false); // Needs a refresh with the new authentication.. - //alert.success("Successfully saved new app auth") + //toast("Successfully saved new app auth") } }) .catch((error) => { - //alert.error(error.toString()); + //toast(error.toString()); console.log("New auth error: ", error.toString()); }); }; @@ -992,7 +993,7 @@ const AngularWorkflow = (defaultprops) => { } }) .catch((error) => { - //alert.error(error.toString()); + //toast(error.toString()); console.log("Get execution error: ", error.toString()); }); }; @@ -1046,7 +1047,7 @@ const AngularWorkflow = (defaultprops) => { return response.json(); }) .catch((error) => { - //alert.error(error.toString()); + //toast(error.toString()); console.log("Abort error: ", error.toString()); }); }; @@ -1159,7 +1160,7 @@ const AngularWorkflow = (defaultprops) => { if (!visited.includes(label)) { //if (item.action.result !== undefined && item.action.result !== null && !item.action.result.includes("failed condition")) { - // alert.error("Error for " + item.action.label + " with result " + item.result); + // toast("Error for " + item.action.label + " with result " + item.result); //} visited.push(label); setVisited(visited); @@ -1287,7 +1288,7 @@ const AngularWorkflow = (defaultprops) => { }) .catch((error) => { console.log("Stream send error: ", error.toString()) - //alert.error(error.toString()); + //toast(error.toString()); }) } @@ -1458,7 +1459,7 @@ const AngularWorkflow = (defaultprops) => { newComments.push(curworkflowComment); } else { - alert.info("No handler for type: " + type); + toast("No handler for type: " + type); } } } @@ -1519,9 +1520,9 @@ const AngularWorkflow = (defaultprops) => { if (!responseJson.success) { console.log(responseJson); if (responseJson.reason !== undefined && responseJson.reason !== null) { - alert.error("Failed to save: " + responseJson.reason); + toast("Failed to save: " + responseJson.reason); } else { - alert.error("Failed to save. Please contact your support@shuffler.io or your local admin if this is unexpected.") + toast("Failed to save. Please contact your support@shuffler.io or your local admin if this is unexpected.") } } else { @@ -1570,7 +1571,7 @@ const AngularWorkflow = (defaultprops) => { }) .catch((error) => { setSavingState(0); - //alert.error(error.toString()); + //toast(error.toString()); console.log("Save workflow error: ", error.toString()); }); @@ -1615,12 +1616,12 @@ const AngularWorkflow = (defaultprops) => { } if (workflow.public) { - alert.info("Save it to get a new version"); + toast("Save it to get a new version"); } var returncheck = monitorUpdates(); if (!returncheck) { - alert.error("No startnode set."); + toast("No startnode set."); return; } @@ -1656,7 +1657,7 @@ const AngularWorkflow = (defaultprops) => { }) .then((responseJson) => { if (!responseJson.success) { - alert.error("Failed to start: " + responseJson.reason); + toast("Failed to start: " + responseJson.reason); setExecutionRunning(false); setExecutionRequestStarted(false); stop(); @@ -1676,7 +1677,7 @@ const AngularWorkflow = (defaultprops) => { responseJson.authorization === "" || responseJson.authorization === undefined ) { - alert.error("Something went wrong during execution startup"); + toast("Something went wrong during execution startup"); console.log("BAD RESPONSE FOR EXECUTION: ", responseJson); setExecutionRunning(false); setExecutionRequestStarted(false); @@ -1698,7 +1699,7 @@ const AngularWorkflow = (defaultprops) => { start(); }) .catch((error) => { - //alert.error(error.toString()); + //toast(error.toString()); setExecutionRequestStarted(false) console.log("Execute workflow err: ", error.toString()); }); @@ -1809,16 +1810,16 @@ const AngularWorkflow = (defaultprops) => { setSelectedAction(selectedAction); setWorkflow(workflow); saveWorkflow(workflow); - alert.info("Added and updated authentication!"); + toast("Added and updated authentication!"); shouldClose = true } else { console.log("Closing auth modal? FAIL") - alert.error("Failed to find new authentication. See details in Oauth2 popup window where auth was attempted."); + toast("Failed to find new authentication. See details in Oauth2 popup window where auth was attempted."); shouldClose = false } } else { - alert.info("No authentication to update"); + toast("No authentication to update"); } } else { shouldClose = true @@ -1835,7 +1836,7 @@ const AngularWorkflow = (defaultprops) => { }) .catch((error) => { setAppAuthentication([]); - //alert.error("Auth loading error: " + error.toString()); + //toast("Auth loading error: " + error.toString()); console.log("AppAuth error: " + error.toString()); }); }; @@ -1867,7 +1868,7 @@ const AngularWorkflow = (defaultprops) => { setFilteredApps(pretend_apps) setPrioritizedApps(pretend_apps); - alert.error("Something went wrong while loading apps. Please refresh the window to try again.") + toast("Something went wrong while loading apps. Please refresh the window to try again.") return } @@ -1930,7 +1931,7 @@ const AngularWorkflow = (defaultprops) => { .catch((error) => { console.log("App loading error: " + error.toString()); setAppsLoaded(true) - //alert.error("App loading error: "+error.toString()); + //toast("App loading error: "+error.toString()); }); }; @@ -2008,7 +2009,7 @@ const AngularWorkflow = (defaultprops) => { } }) .catch((error) => { - //alert.error(error.toString()); + //toast(error.toString()); console.log("Error loading files: ", error) }); }; @@ -2027,9 +2028,9 @@ const AngularWorkflow = (defaultprops) => { console.log("Status not 200 for workflows :O!"); if (response.status >= 500) { - alert.info("Something went wrong while loading the workflow. Please reload.") + toast("Something went wrong while loading the workflow. Please reload.") } else { - alert.info("You don't access to this workflow or loading failed.") + toast("You don't access to this workflow or loading failed.") window.location.pathname = "/workflows"; } } @@ -2064,7 +2065,7 @@ const AngularWorkflow = (defaultprops) => { fetchRecommendations(responseJson) if (responseJson.public) { - //alert.info("This workflow is public. Save the workflow to use it in your organization."); + //toast("This workflow is public. Save the workflow to use it in your organization."); setAppAuthentication([]) console.log("RESP: ", responseJson) @@ -2280,7 +2281,7 @@ const AngularWorkflow = (defaultprops) => { } }) .catch((error) => { - //alert.error(error.toString()); + //toast(error.toString()); console.log("Get workflows error: ", error.toString()); }); }; @@ -2411,7 +2412,7 @@ const AngularWorkflow = (defaultprops) => { event.target.data("type") !== "COMMENT" && event.target.data().decorator ) { - alert.info("This edge can't be edited."); + toast("This edge can't be edited."); } else { //console.log("DATA: ", event.target.data()) const destinationId = event.target.data("target"); @@ -2423,7 +2424,7 @@ const AngularWorkflow = (defaultprops) => { curaction.app_name === "Shuffle Tools" && curaction.name === "router" ) { - alert.info("Router action can't have incoming conditions"); + toast("Router action can't have incoming conditions"); event.target.unselect(); return; } @@ -2455,7 +2456,7 @@ const AngularWorkflow = (defaultprops) => { if (nodedata.type === "TRIGGER" && (nodedata.app_name === "Shuffle Workflow" || nodedata.app_name === "User Input")) { if (nodedata.parameters === null) { - alert.error("Set a workflow first"); + toast("Set a workflow first"); return; } @@ -3045,7 +3046,7 @@ const AngularWorkflow = (defaultprops) => { curaction = data } else { if (workflow.public !== true) { - alert.error("Action not found. Please remake it."); + toast("Action not found. Please remake it."); } event.target.remove(); @@ -3103,7 +3104,7 @@ const AngularWorkflow = (defaultprops) => { if (!curapp || curapp === undefined) { console.log("APPS - couldn't find it: ", newapps) - //alert.error(`App ${curaction.app_name}:${curaction.app_version} not found. Is it activated?`); + //toast(`App ${curaction.app_name}:${curaction.app_version} not found. Is it activated?`); const tmpapp = { name: curaction.app_name, @@ -3295,7 +3296,7 @@ const AngularWorkflow = (defaultprops) => { // workflow.actions.push(data) // curaction = data //} else { - // alert.error("Action not found. Please remake it."); + // toast("Action not found. Please remake it."); // event.target.remove(); // return; //} @@ -3329,7 +3330,7 @@ const AngularWorkflow = (defaultprops) => { } else if (data.type === "COMMENT") { setSelectedComment(data); } else { - alert.error("Can't handle node type " + data.type); + toast("Can't handle node type " + data.type); return; } @@ -3383,16 +3384,16 @@ const AngularWorkflow = (defaultprops) => { }) .then((responseJson) => { if (responseJson.success === false) { - alert.error("Failed to auto-activate the app. Go to /apps and activate it.") + toast("Failed to auto-activate the app. Go to /apps and activate it.") } else { if (refresh === true) { - //alert.success("App activated for your organization! Refresh the page to use the app.") + //toast("App activated for your organization! Refresh the page to use the app.") getApps() } } }) .catch(error => { - //alert.error(error.toString()) + //toast(error.toString()) console.log("Activate app error: ", error.toString()) }); } @@ -3707,7 +3708,7 @@ const AngularWorkflow = (defaultprops) => { event.target.remove() //console.log("Found branch already!") - alert.info("Triggers can have exactly one target node") + toast("Triggers can have exactly one target node") return @@ -3740,7 +3741,7 @@ const AngularWorkflow = (defaultprops) => { workflow.triggers[targetnode].app_name === "Shuffle Workflow" ) { } else { - alert.error("Can't have triggers as target of branch"); + toast("Can't have triggers as target of branch"); event.target.remove(); } } @@ -3793,7 +3794,7 @@ const AngularWorkflow = (defaultprops) => { workflow.branches[branchkey].destination_id === edge.source && workflow.branches[branchkey].source_id === edge.target ) { - alert.error("A branch in the opposite direction already exists"); + toast("A branch in the opposite direction already exists"); event.target.remove(); found = true; break; @@ -3803,7 +3804,7 @@ const AngularWorkflow = (defaultprops) => { ) { console.log(edge.source); - //alert.error("That branch already exists"); + //toast("That branch already exists"); event.target.remove(); found = true; @@ -3814,7 +3815,7 @@ const AngularWorkflow = (defaultprops) => { ); if (targetnode === -1) { if (targetnode.type !== "TRIGGER") { - alert.error("Can't make arrow to starting node"); + toast("Can't make arrow to starting node"); event.target.remove(); break; } @@ -3829,7 +3830,7 @@ const AngularWorkflow = (defaultprops) => { // console.log("Destination: ", edge.target) // console.log("CHECK SOURCE IF ITS A TRIGGER: ", targetnode) // if (targetnode !== -1) { - // alert.error("Triggers can only target one target (startnode)") + // toast("Triggers can only target one target (startnode)") // event.target.remove() // found = true // break @@ -3844,7 +3845,7 @@ const AngularWorkflow = (defaultprops) => { console.log("TARGETNODE: ", targetnode) if (workflow.triggers[targetnode].app_name === "User Input" || workflow.triggers[targetnode].app_name === "Shuffle Workflow") { } else { - alert.error("Can't have triggers as target of branch") + toast("Can't have triggers as target of branch") event.target.remove() found = true break @@ -3937,7 +3938,7 @@ const AngularWorkflow = (defaultprops) => { /* var curaction = workflow.actions.find((a) => a.id === nodedata.id); if (curaction === null || curaction === undefined) { - alert.error("Node not found. Please remake it.") + toast("Node not found. Please remake it.") event.target.remove(); } */ @@ -4016,7 +4017,7 @@ const AngularWorkflow = (defaultprops) => { setWorkflow(workflow); } else if (nodedata.type === "TRIGGER") { if (nodedata.is_valid === false) { - alert.info("This trigger is not available to you"); + toast("This trigger is not available to you"); node.remove(); return; } @@ -4101,7 +4102,7 @@ const AngularWorkflow = (defaultprops) => { data: newdata, }) - alert.error("You must STOP the trigger before deleting its branches") + toast("You must STOP the trigger before deleting its branches") } catch (e) { console.log("Failed re-adding edge: ", e) } @@ -4258,7 +4259,7 @@ const AngularWorkflow = (defaultprops) => { if (copyText !== null && copyText !== undefined) { const clipboard = navigator.clipboard; if (clipboard === undefined) { - alert.error("Can only copy over HTTPS (port 3443)"); + toast("Can only copy over HTTPS (port 3443)"); return; } @@ -4266,7 +4267,7 @@ const AngularWorkflow = (defaultprops) => { copyText.select(); copyText.setSelectionRange(0, 99999); /* For mobile devices */ document.execCommand("copy"); - alert.success(`Copied ${cydata.length} element(s)`); + toast(`Copied ${cydata.length} element(s)`); } } } @@ -4279,7 +4280,7 @@ const AngularWorkflow = (defaultprops) => { /* const clipboard = navigator.clipboard if (clipboard === undefined || window === undefined || window === null) { - alert.error("Can only use cliboard over HTTPS (port 3443)") + toast("Can only use cliboard over HTTPS (port 3443)") return } @@ -4387,7 +4388,7 @@ const AngularWorkflow = (defaultprops) => { } } catch (e) { console.log("Error pasting: ", e); - //alert.info("Failed parsing clipboard: ", e) + //toast("Failed parsing clipboard: ", e) } }; @@ -4458,7 +4459,7 @@ const AngularWorkflow = (defaultprops) => { } }) .catch((error) => { - //alert.error(error.toString()); + //toast(error.toString()); console.log("Get environments error: ", error.toString()); }); }; @@ -5478,7 +5479,7 @@ const AngularWorkflow = (defaultprops) => { //} const parsedSelection = cy.$(":selected"); if (selectedNode.data().decorator === true && selectedNode.data("type") !== "COMMENT") { - alert.info("This node can't be deleted."); + toast("This node can't be deleted."); } else { console.log("Deleted.") selectedNode.remove(); @@ -5545,7 +5546,7 @@ const AngularWorkflow = (defaultprops) => { } }) .catch((error) => { - //alert.error("ERROR: " + error.toString()); + //toast("ERROR: " + error.toString()); console.log("ERROR getting usecases: " + error.toString()); }) } @@ -5574,7 +5575,7 @@ const AngularWorkflow = (defaultprops) => { } }) .catch((error) => { - //alert.error("ERROR: " + error.toString()); + //toast("ERROR: " + error.toString()); console.log("ERROR getting usecases: " + error.toString()); }) } @@ -5749,7 +5750,7 @@ const AngularWorkflow = (defaultprops) => { console.log("END: ", cy) var cydata = cy.$(":selected").jsons(); if (cydata !== undefined && cydata !== null && cydata.length > 0) { - alert.success(`Selected ${cydata.length} element(s). CTRL+C to copy them.`); + toast(`Selected ${cydata.length} element(s). CTRL+C to copy them.`); } }); @@ -5804,10 +5805,10 @@ const AngularWorkflow = (defaultprops) => { // No matter what, it's being stopped. if (!responseJson.success) { if (responseJson.reason !== undefined) { - alert.error("Failed to stop schedule: " + responseJson.reason); + toast("Failed to stop schedule: " + responseJson.reason); } } else { - alert.success("Successfully stopped schedule"); + toast("Successfully stopped schedule"); } workflow.triggers[triggerindex].status = "stopped"; @@ -5817,14 +5818,14 @@ const AngularWorkflow = (defaultprops) => { saveWorkflow(workflow); }) .catch((error) => { - //alert.error(error.toString()); + //toast(error.toString()); console.log("Stop schedule error: ", error.toString()); }); }; const submitSchedule = (trigger, triggerindex) => { if (trigger.name.length <= 0) { - alert.error("Error: name can't be empty"); + toast("Error: name can't be empty"); return; } @@ -5841,7 +5842,7 @@ const AngularWorkflow = (defaultprops) => { } } - alert.info("Creating schedule") + toast("Creating schedule") const data = { name: trigger.name, frequency: workflow.triggers[triggerindex].parameters[0].value, @@ -5872,9 +5873,9 @@ const AngularWorkflow = (defaultprops) => { }) .then((responseJson) => { if (!responseJson.success) { - alert.error("Failed to set schedule: " + responseJson.reason); + toast("Failed to set schedule: " + responseJson.reason); } else { - alert.success("Successfully created schedule"); + toast("Successfully created schedule"); workflow.triggers[triggerindex].status = "running"; trigger.status = "running"; setSelectedTrigger(trigger); @@ -5884,7 +5885,7 @@ const AngularWorkflow = (defaultprops) => { } }) .catch((error) => { - //alert.error(error.toString()); + //toast(error.toString()); console.log("Get schedule error: ", error.toString()); }); }; @@ -6397,7 +6398,7 @@ const AngularWorkflow = (defaultprops) => { currentnode[0].renderedPosition("y", e.pageY - cycontainer.offsetTop); } else { if (workflow.start === "" || workflow.start === undefined) { - alert.error("Define a starting action first."); + toast("Define a starting action first."); return; } @@ -6602,7 +6603,7 @@ const AngularWorkflow = (defaultprops) => { app.actions === null || app.actions.length === 0 ) { - alert.error( + toast( "App " + app.name + " currently has no actions to perform. Please go to https://shuffler.io/apps to edit it." @@ -7131,13 +7132,13 @@ const AngularWorkflow = (defaultprops) => { return (
{ //if (!isCloud) { - // alert.info("Since this is an on-prem instance. You will need to activate the app yourself. Opening link to download it in a new window.") + // toast("Since this is an on-prem instance. You will need to activate the app yourself. Opening link to download it in a new window.") // setTimeout(() => { // event.preventDefault() // window.open(parsedUrl, '_blank') // }, 2000) //} else { - alert.info(`Activating ${name}`) + toast(`Activating ${name}`) //} console.log("CLICK: ", hit) @@ -7346,7 +7347,7 @@ const AngularWorkflow = (defaultprops) => { ); if (newaction === undefined || newaction === null) { - alert.error("Failed to find the action"); + toast("Failed to find the action"); return; } @@ -7696,7 +7697,7 @@ const AngularWorkflow = (defaultprops) => { // Max 1 folder for office for some reason. MailFolders('MAILBOX_ID') in resource // Can't parse URL with multiple folders. if (selectedTrigger.name === "Office365" & value !== undefined && value !== null && value.length > 1) { - alert.info("Max 1 folder at a time allowed for Office365") + toast("Max 1 folder at a time allowed for Office365") console.log("VALUE: ", value) value = [value[0]] } @@ -8900,7 +8901,7 @@ const AngularWorkflow = (defaultprops) => { (branch) => branch.source_id === selectedTrigger.id ); if (branch === undefined || branch === null) { - alert.error( + toast( "No startnode connected to node. Connect it to an action." ); return; @@ -8996,7 +8997,7 @@ const AngularWorkflow = (defaultprops) => { (branch) => branch.source_id === selectedTrigger.id ); if (branch === undefined || branch === null) { - alert.error( + toast( "No startnode connected to node. Connect it to an action." ); return; @@ -10982,7 +10983,7 @@ const AngularWorkflow = (defaultprops) => { console.log("NAVIGATOR: ", navigator); const clipboard = navigator.clipboard; if (clipboard === undefined) { - alert.error("Can only copy over HTTPS (port 3443)"); + toast("Can only copy over HTTPS (port 3443)"); return; } @@ -10995,7 +10996,7 @@ const AngularWorkflow = (defaultprops) => { /* Copy the text inside the text field */ document.execCommand("copy"); - alert.success("Copied Webhook URL"); + toast("Copied Webhook URL"); } else { console.log("Couldn't find webhook URI field: ", copyText); } @@ -11207,7 +11208,7 @@ const AngularWorkflow = (defaultprops) => { return; } - alert.info("Stopping mail trigger"); + toast("Stopping mail trigger"); const requesttype = triggerAuthentication.type; fetch( `${globalUrl}/api/v1/workflows/${props.match.params.key}/${requesttype}/${trigger.id}`, @@ -11229,7 +11230,7 @@ const AngularWorkflow = (defaultprops) => { }) .then((responseJson) => { if (responseJson.success) { - alert.success("Successfully stopped trigger"); + toast("Successfully stopped trigger"); // Set the status workflow.triggers[triggerindex].status = "stopped"; trigger.status = "stopped"; @@ -11237,11 +11238,11 @@ const AngularWorkflow = (defaultprops) => { setSelectedTrigger(trigger); saveWorkflow(workflow); } else { - alert.error("Failed stopping trigger: " + responseJson.reason); + toast("Failed stopping trigger: " + responseJson.reason); } }) .catch((error) => { - //alert.error(error.toString()); + //toast(error.toString()); console.log("Stop mailsub error: ", error.toString()); }); }; @@ -11263,7 +11264,7 @@ const AngularWorkflow = (defaultprops) => { const item = splitItem[splitkey]; const curfolder = triggerFolders.find((a) => a.displayName === item); if (curfolder === undefined) { - alert.error("Something went wrong with folder selection: " + item); + toast("Something went wrong with folder selection: " + item); return; } @@ -11277,7 +11278,7 @@ const AngularWorkflow = (defaultprops) => { }; const requesttype = triggerAuthentication.type; - alert.info( + toast( "Creating " + requesttype + " subscription with name " + trigger.name ); @@ -11306,9 +11307,9 @@ const AngularWorkflow = (defaultprops) => { }) .then((responseJson) => { if (!responseJson.success) { - alert.error("Failed to start trigger: " + responseJson.reason); + toast("Failed to start trigger: " + responseJson.reason); } else { - alert.success( + toast( "Successfully started folder subscription trigger. Test it by sending yoursend an email" ); @@ -11320,7 +11321,7 @@ const AngularWorkflow = (defaultprops) => { } }) .catch((error) => { - //alert.error(error.toString()); + //toast(error.toString()); console.log("Start mailsub error: ", error.toString()); }); }; @@ -11328,12 +11329,12 @@ const AngularWorkflow = (defaultprops) => { const newWebhook = (trigger) => { const hookname = trigger.label; if (hookname.length === 0) { - alert.error("Missing name"); + toast("Missing name"); return; } if (trigger.id.length !== 36) { - alert.error("Missing id"); + toast("Missing id"); return; } @@ -11343,10 +11344,10 @@ const AngularWorkflow = (defaultprops) => { (branch) => branch.source_id === trigger.id ); if (branch === undefined && (workflow.start === undefined || workflow.start === null || workflow.start.length === 0)) { - alert.error("No webhook node defined"); + toast("No webhook node defined"); } - alert.info("Starting webhook"); + toast("Starting webhook"); if (branch !== undefined) { startNode = branch.destination_id; } @@ -11398,14 +11399,14 @@ const AngularWorkflow = (defaultprops) => { .then((responseJson) => { if (responseJson.success) { // Set the status - alert.success("Successfully started webhook"); + toast("Successfully started webhook"); trigger.status = "running"; setSelectedTrigger(trigger); workflow.triggers[selectedTriggerIndex].status = "running"; setWorkflow(workflow); saveWorkflow(workflow); } else { - alert.error("Failed starting webhook: " + responseJson.reason); + toast("Failed starting webhook: " + responseJson.reason); } }) .catch((error) => { @@ -11444,7 +11445,7 @@ const AngularWorkflow = (defaultprops) => { saveWorkflow(workflow); } else { if (responseJson.reason !== undefined) { - alert.error("Failed stopping webhook: " + responseJson.reason); + toast("Failed stopping webhook: " + responseJson.reason); } } @@ -11453,8 +11454,8 @@ const AngularWorkflow = (defaultprops) => { setSelectedTrigger(trigger); }) .catch((error) => { - //alert.error(error.toString()); - alert.error("Delete webhook error. Contact support or check logs if this persists.") + //toast(error.toString()); + toast("Delete webhook error. Contact support or check logs if this persists.") }); }; @@ -13406,7 +13407,7 @@ const AngularWorkflow = (defaultprops) => { const clipboard = navigator.clipboard; if (clipboard === undefined) { - alert.error("Can only copy over HTTPS (port 3443)"); + toast("Can only copy over HTTPS (port 3443)"); return; } @@ -13423,7 +13424,7 @@ const AngularWorkflow = (defaultprops) => { document.execCommand("copy"); console.log("COPYING!"); - alert.info("Copied value to clipboard, NOT json path.") + toast("Copied value to clipboard, NOT json path.") } else { console.log("Failed to copy from " + elementName + ": ", copyText); } @@ -13494,7 +13495,7 @@ const AngularWorkflow = (defaultprops) => { console.log("NAVIGATOR: ", navigator); const clipboard = navigator.clipboard; if (clipboard === undefined) { - alert.error("Can only copy over HTTPS (port 3443)"); + toast("Can only copy over HTTPS (port 3443)"); return; } @@ -13505,7 +13506,7 @@ const AngularWorkflow = (defaultprops) => { /* Copy the text inside the text field */ document.execCommand("copy"); console.log("COPYING!"); - alert.info("Copied JSON path to clipboard.") + toast("Copied JSON path to clipboard.") } else { console.log("Couldn't find element ", elementName); } @@ -14875,7 +14876,7 @@ const AngularWorkflow = (defaultprops) => { console.log("NAVIGATOR: ", navigator); const clipboard = navigator.clipboard; if (clipboard === undefined) { - alert.error("Can only copy over HTTPS (port 3443)"); + toast("Can only copy over HTTPS (port 3443)"); return; } @@ -15480,7 +15481,7 @@ const AngularWorkflow = (defaultprops) => { selectedApp.authentication.parameters[paramkey].name ] = "false"; } else { - alert.info( + toast( "Field " + selectedApp.authentication.parameters[paramkey].name + " can't be empty" diff --git a/frontend/src/views/AppCreator.jsx b/frontend/src/views/AppCreator.jsx index cb77cf0e..9b7646bd 100755 --- a/frontend/src/views/AppCreator.jsx +++ b/frontend/src/views/AppCreator.jsx @@ -46,7 +46,8 @@ import { v4 as uuidv4 } from "uuid"; import { Link, useParams } from "react-router-dom"; import YAML from "yaml"; import { MuiChipsInput } from "mui-chips-input"; -import { useAlert } from "react-alert"; +//import { useAlert +import { ToastContainer, toast } from "react-toastify" import words from "shellwords"; import AvatarEditor from "react-avatar-editor"; @@ -350,7 +351,7 @@ const getJsonObject = (properties) => { const AppCreator = (defaultprops) => { const { globalUrl, isLoaded } = defaultprops; const classes = useStyles(); - const alert = useAlert(); + //const alert = useAlert(); const params = useParams(); var props = JSON.parse(JSON.stringify(defaultprops)) @@ -451,7 +452,7 @@ const AppCreator = (defaultprops) => { }) .then((responseJson) => { if (responseJson.success === false) { - alert.error("Failed to get the app"); + toast("Failed to get the app"); setIsAppLoaded(true); window.location.pathname = "/search"; } else { @@ -459,7 +460,7 @@ const AppCreator = (defaultprops) => { } }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -494,14 +495,14 @@ const AppCreator = (defaultprops) => { .then((responseJson) => { setIsAppLoaded(true); if (!responseJson.success) { - alert.error("Failed to get app config. Do you have access?"); + toast("Failed to get app config. Do you have access?"); } else { parseIncomingOpenapiData(responseJson); } }) .catch((error) => { console.log("Error: ", error.toString()); - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -568,7 +569,7 @@ const AppCreator = (defaultprops) => { } if (data.openapi === null) { - alert.info("Failed to load OpenAPI for app. Please contact support if this persists.") + toast("Failed to load OpenAPI for app. Please contact support if this persists.") setIsAppLoaded(true); return } @@ -600,7 +601,7 @@ const AppCreator = (defaultprops) => { } if (!jsonvalid) { - alert.info("OpenAPI data is invalid."); + toast("OpenAPI data is invalid."); return; } @@ -726,7 +727,7 @@ const AppCreator = (defaultprops) => { for (let [method, methodvalue] of Object.entries(pathvalue)) { if (methodvalue === null) { - alert.info("Skipped method (null)" + method); + toast("Skipped method (null)" + method); continue; } @@ -734,7 +735,7 @@ const AppCreator = (defaultprops) => { // Typical YAML issue if (method !== "parameters") { console.log("Invalid method: ", method, "data: ", methodvalue); - //alert.info("Skipped method (not allowed): " + method); + //toast("Skipped method (not allowed): " + method); } continue; } @@ -1596,7 +1597,7 @@ const AppCreator = (defaultprops) => { setParameterLocation(value.in); if (!apikeySelection.includes(value.in)) { console.log("APIKEY SELECT: ", apikeySelection); - alert.error("Might be error in setting up API key authentication"); + toast("Might be error in setting up API key authentication"); } console.log("PARAM NAME: ", value.name); @@ -1637,7 +1638,7 @@ const AppCreator = (defaultprops) => { optionset = true } else if (value.type === "oauth2" || key === "Oauth2" || key === "Oauth2c" || (key !== undefined && key !== null && key.toLowerCase().includes("oauth2"))) { - //alert.info("Can't handle Oauth2 auth yet.") + //toast("Can't handle Oauth2 auth yet.") setAuthenticationOption("Oauth2"); setAuthenticationRequired(true); optionset = true @@ -1686,7 +1687,7 @@ const AppCreator = (defaultprops) => { const scopekeysplit = scopekey.split("/"); if (scopekeysplit.length < 5) { console.log("Skipping scope: ", scopekey); - alert.info("Skipping scope: " + scopekey); + toast("Skipping scope: " + scopekey); continue; } @@ -1707,7 +1708,7 @@ const AppCreator = (defaultprops) => { ); } } else { - alert.error("Couldn't handle AUTH type: ", key); + toast("Couldn't handle AUTH type: ", key); //newauth.push({ // "name": key, // "type": value.in, @@ -1716,7 +1717,7 @@ const AppCreator = (defaultprops) => { } } } catch (e) { - alert.error("Failed to handle auth") + toast("Failed to handle auth") console.log("Error: ", e) } @@ -1790,7 +1791,7 @@ const AppCreator = (defaultprops) => { //const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" if (newActions.length > 1000 && isCloud) { - alert.error("Cut down actions from " + newActions.length + " to 999 because of limit"); + toast("Cut down actions from " + newActions.length + " to 999 because of limit"); newActions = newActions.slice(0, 999); } @@ -1812,7 +1813,7 @@ const AppCreator = (defaultprops) => { // Saving the app that's been configured. // Save SAVE app const submitApp = () => { - alert.info("Uploading and building app " + name); + toast("Uploading and building app " + name); setAppBuilding(true); setErrorCode(""); @@ -1881,7 +1882,7 @@ const AppCreator = (defaultprops) => { for (let actionkey in actions) { var item = JSON.parse(JSON.stringify(actions[actionkey])) if (item.errors.length > 0) { - alert.error("Saving with error in action " + item.name); + toast("Saving with error in action " + item.name); } if (item.name === undefined && item.description !== undefined) { @@ -2107,7 +2108,7 @@ const AppCreator = (defaultprops) => { // Bad code as it doesn't allow for "anything". if (skipped) { - alert.info( + toast( "Bad configuration of " + item.name + ". Skipping because queries are invalid." @@ -2358,7 +2359,7 @@ const AppCreator = (defaultprops) => { if (authenticationOption === "API key") { if (parameterName.length === 0) { - alert.error("A field name for the APIkey must be defined"); + toast("A field name for the APIkey must be defined"); setAppBuilding(false); return; } @@ -2424,7 +2425,7 @@ const AppCreator = (defaultprops) => { const curauth = extraAuth[authkey]; if (curauth.name.toLowerCase() == "url") { - alert.error("Can't add extra auth with Name URL"); + toast("Can't add extra auth with Name URL"); setAppBuilding(false); return; } @@ -2459,10 +2460,10 @@ const AppCreator = (defaultprops) => { if (!responseJson.success) { if (responseJson.reason !== undefined) { setErrorCode(responseJson.reason); - alert.error("Failed to verify: " + responseJson.reason); + toast("Failed to verify: " + responseJson.reason); } } else { - alert.success("Successfully uploaded openapi"); + toast("Successfully uploaded openapi"); if (window.location.pathname.includes("/new")) { if (responseJson.id !== undefined && responseJson.id !== null) { window.location = `/apps/edit/${responseJson.id}`; @@ -2473,7 +2474,7 @@ const AppCreator = (defaultprops) => { .catch((error) => { setAppBuilding(false); setErrorCode(error.toString()); - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -2805,7 +2806,7 @@ const AppCreator = (defaultprops) => { !tmpstring.startsWith("http") && !tmpstring.startsWith("ftp") ) { - alert.error("Auth URL must start with http(s)://"); + toast("Auth URL must start with http(s)://"); } if (tmpstring.includes("?")) { @@ -2854,7 +2855,7 @@ const AppCreator = (defaultprops) => { !tmpstring.startsWith("http") && !tmpstring.startsWith("ftp") ) { - alert.error("Token URL must start with http(s)://"); + toast("Token URL must start with http(s)://"); } if (tmpstring.includes("?")) { @@ -2900,7 +2901,7 @@ const AppCreator = (defaultprops) => { !tmpstring.startsWith("http") && !tmpstring.startsWith("ftp") ) { - alert.error("Refresh URL must start with http(s)://"); + toast("Refresh URL must start with http(s)://"); } if (tmpstring.includes("?")) { @@ -3791,7 +3792,7 @@ const AppCreator = (defaultprops) => { value = keysplit[1].trim() } else { - alert.error("Removed key: ", key) + toast("Removed key: ", key) continue } } @@ -4626,11 +4627,11 @@ const AppCreator = (defaultprops) => { setSelectedAction(selectedAction); } - //alert.error("Failed getting authentications") + //toast("Failed getting authentications") } }) .catch((error) => { - alert.error("Auth loading error: " + error.toString()); + toast("Auth loading error: " + error.toString()); }); }; @@ -4686,17 +4687,17 @@ const AppCreator = (defaultprops) => { }) .then((responseJson) => { if (!responseJson.success) { - alert.error("Failed to set app auth: " + responseJson.reason); + toast("Failed to set app auth: " + responseJson.reason); } else { getAppAuthentication(true); setAuthenticationModalOpen(false); // Needs a refresh with the new authentication.. - //alert.success("Successfully saved new app auth") + //toast("Successfully saved new app auth") } }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -4747,7 +4748,7 @@ const AppCreator = (defaultprops) => { console.log("NEW AUTH: ", authenticationOption); if (authenticationOption.label.length === 0) { authenticationOption.label = `Auth for ${selectedApp.name}`; - //alert.info("Label can't be empty") + //toast("Label can't be empty") //return } @@ -4757,7 +4758,7 @@ const AppCreator = (defaultprops) => { selectedApp.authentication.parameters[key].name ].length === 0 ) { - alert.info( + toast( "Field " + selectedApp.authentication.parameters[key].name + " can't be empty" @@ -5165,7 +5166,7 @@ const AppCreator = (defaultprops) => { setFileBase64(canvasUrl); } } catch (e) { - alert.error("Failed to parse canvasurl!"); + toast("Failed to parse canvasurl!"); } }; @@ -5253,7 +5254,7 @@ const AppCreator = (defaultprops) => { setOpenImageModal(false); setDisableImageUpload(true); } catch (e) { - alert.error("Failed to set image. Replace it if this persists."); + toast("Failed to set image. Replace it if this persists."); } } }; @@ -5468,7 +5469,7 @@ const AppCreator = (defaultprops) => { const invalid = ["#", ":", "."]; for (var key in invalid) { if (e.target.value.includes(invalid[key])) { - alert.error("Can't use " + invalid[key] + " in name"); + toast("Can't use " + invalid[key] + " in name"); setName(e.target.value.replaceAll(".", "").replaceAll("#", "").replaceAll(":", "").replaceAll(",", "")) return; @@ -5476,7 +5477,7 @@ const AppCreator = (defaultprops) => { } if (e.target.value.length > 29) { - alert.error("Choose a shorter name (max 29)."); + toast("Choose a shorter name (max 29)."); setName(e.target.value.slice(0,28)) return; } @@ -5588,7 +5589,7 @@ const AppCreator = (defaultprops) => { !tmpstring.startsWith("http") && !tmpstring.startsWith("ftp") ) { - alert.error("URL must start with http(s)://"); + toast("URL must start with http(s)://"); } if (tmpstring.includes("?")) { diff --git a/frontend/src/views/Apps.jsx b/frontend/src/views/Apps.jsx index dccc81bc..c9ee901c 100755 --- a/frontend/src/views/Apps.jsx +++ b/frontend/src/views/Apps.jsx @@ -59,7 +59,8 @@ import algoliasearch from 'algoliasearch/lite'; import YAML from "yaml"; import { useNavigate, Link, useParams } from "react-router-dom"; -import { useAlert } from "react-alert"; +//import { useAlert +import { ToastContainer, toast } from "react-toastify" import Dropzone from "../components/Dropzone.jsx"; const surfaceColor = "#27292D"; @@ -272,7 +273,7 @@ const Apps = (props) => { //const [workflows, setWorkflows] = React.useState([]); const baseRepository = "https://github.com/frikky/shuffle-apps"; - const alert = useAlert(); + //const alert = useAlert(); let navigate = useNavigate(); const [selectedApp, setSelectedApp] = React.useState({}); @@ -454,7 +455,7 @@ const Apps = (props) => { //}, 5000) }) .catch((error) => { - alert.error(error.toString()); + toast(error.toString()); setIsLoading(false); }); }; @@ -462,7 +463,7 @@ const Apps = (props) => { const downloadApp = (inputdata) => { const id = inputdata.id; - alert.info("Downloading.."); + toast("Downloading.."); fetch(globalUrl + "/api/v1/apps/" + id + "/config", { method: "GET", headers: { @@ -480,7 +481,7 @@ const Apps = (props) => { }) .then((responseJson) => { if (!responseJson.success) { - alert.error("Failed to download file"); + toast("Failed to download file"); } else { console.log(responseJson); const basedata = atob(responseJson.openapi); @@ -538,7 +539,7 @@ const Apps = (props) => { }) .catch((error) => { console.log(error); - alert.error(error.toString()); + toast(error.toString()); }); }; @@ -1152,7 +1153,7 @@ const Apps = (props) => {