From 625d681fe51d326439dff9a901f89be3cc7cdc0b Mon Sep 17 00:00:00 2001 From: Frikky Date: Thu, 14 Mar 2024 09:47:01 +0100 Subject: [PATCH] Synced over files and go.mod --- backend/go-app/go.mod | 2 +- backend/go-app/go.sum | 2 + frontend/src/components/EditWorkflow.jsx | 96 +++++++++- frontend/src/components/ParsedAction.jsx | 132 ++++++------- frontend/src/components/ShuffleCodeEditor.jsx | 5 +- frontend/src/views/AngularWorkflow.jsx | 181 +++++++++++++----- frontend/src/views/AppCreator.jsx | 2 +- frontend/src/views/Docs.jsx | 6 +- frontend/src/views/RunWorkflow.jsx | 13 ++ 9 files changed, 309 insertions(+), 130 deletions(-) diff --git a/backend/go-app/go.mod b/backend/go-app/go.mod index d1678703..0895bde5 100644 --- a/backend/go-app/go.mod +++ b/backend/go-app/go.mod @@ -18,7 +18,7 @@ require ( github.com/gorilla/mux v1.8.0 github.com/h2non/filetype v1.1.3 github.com/satori/go.uuid v1.2.0 - github.com/shuffle/shuffle-shared v0.5.88 + github.com/shuffle/shuffle-shared v0.5.91 golang.org/x/crypto v0.16.0 google.golang.org/api v0.125.0 google.golang.org/grpc v1.55.0 diff --git a/backend/go-app/go.sum b/backend/go-app/go.sum index a86377b2..f99af079 100644 --- a/backend/go-app/go.sum +++ b/backend/go-app/go.sum @@ -461,6 +461,8 @@ github.com/shuffle/shuffle-shared v0.5.81 h1:pt4lT42FrXN/kd/vlYtm7nXShZI0mOamXUM github.com/shuffle/shuffle-shared v0.5.81/go.mod h1:Lg6/+qjQlWzNKwj4/4ATpvScyP2JQGLkTPlNlRM6RJk= github.com/shuffle/shuffle-shared v0.5.88 h1:YNM6xtnKg0BoMmw2pqV/LnNAsMWMrAzYIAy+o+ChdfI= github.com/shuffle/shuffle-shared v0.5.88/go.mod h1:Lg6/+qjQlWzNKwj4/4ATpvScyP2JQGLkTPlNlRM6RJk= +github.com/shuffle/shuffle-shared v0.5.91 h1:CN2K4iDt2zjx7MR9B+u5Yb7tA8IEw5lk8+Ab+Wia11Q= +github.com/shuffle/shuffle-shared v0.5.91/go.mod h1:Lg6/+qjQlWzNKwj4/4ATpvScyP2JQGLkTPlNlRM6RJk= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= diff --git a/frontend/src/components/EditWorkflow.jsx b/frontend/src/components/EditWorkflow.jsx index 081b6f92..07e21578 100644 --- a/frontend/src/components/EditWorkflow.jsx +++ b/frontend/src/components/EditWorkflow.jsx @@ -49,12 +49,14 @@ import { } from '@mui/x-date-pickers' import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs' +import { useStyles } from '../views/AppCreator.jsx' import { ExpandLess as ExpandLessIcon, ExpandMore as ExpandMoreIcon, Publish as PublishIcon, OpenInNew as OpenInNewIcon, + Add as AddIcon, } from "@mui/icons-material"; const EditWorkflow = (props) => { @@ -74,6 +76,10 @@ const EditWorkflow = (props) => { const [name, setName] = React.useState(workflow.name !== undefined ? workflow.name : "") 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')) + const [inputFields, setInputFields] = React.useState([]) + + const classes = useStyles(); + // Gets the generated workflow const getGeneratedWorkflow = (workflow_id) => { fetch(globalUrl + "/api/v1/workflows/" + workflow_id, { @@ -352,6 +358,9 @@ const EditWorkflow = (props) => { {showMoreClicked === true ? + + +
Status @@ -467,9 +476,94 @@ const EditWorkflow = (props) => { margin="dense" fullWidth /> + + {/* + + Input fields + + + Input fields are fields that will be used during the startup of the workflow. These will be formatted in JSON and is most commonly used from the workflow run page. + + + + + {inputFields.length === 0 ? + + : null} + + {inputFields.map((data, index) => { + console.log("Inputfield: ", data) + + return ( +
+ { + inputFields[index].name = e.target.value + setInputFields(inputFields) + setUpdate(Math.random()); + }} + InputProps={{ + classes: { + notchedOutline: classes.notchedOutline, + }, + style: { + color: "white", + minHeight: 50, + }, + }} + /> + +
+ ) + })} + */} : null} - + + { diff --git a/frontend/src/components/ParsedAction.jsx b/frontend/src/components/ParsedAction.jsx index ab2ead31..c13fecd9 100755 --- a/frontend/src/components/ParsedAction.jsx +++ b/frontend/src/components/ParsedAction.jsx @@ -2234,23 +2234,23 @@ const ParsedAction = (props) => { parsedPaths = GetParsedPaths(innerdata.example, ""); } - const coverColor = "#82ccc3" - //menuPosition.left -= 50 - //menuPosition.top -= 250 - //console.log("POS: ", menuPosition1) - var menuPosition1 = menuPosition - if (menuPosition1 === null) { - menuPosition1 = { - "left": 0, - "top": 0, - } - } else if (menuPosition1.top === null || menuPosition1.top === undefined) { - menuPosition1.top = 0 - } else if (menuPosition1.left === null || menuPosition1.left === undefined) { - menuPosition1.left = 0 - } + const coverColor = "#82ccc3" + //menuPosition.left -= 50 + //menuPosition.top -= 250 + //console.log("POS: ", menuPosition1) + var menuPosition1 = menuPosition + if (menuPosition1 === null) { + menuPosition1 = { + "left": 0, + "top": 0, + } + } else if (menuPosition1.top === null || menuPosition1.top === undefined) { + menuPosition1.top = 0 + } else if (menuPosition1.left === null || menuPosition1.left === undefined) { + menuPosition1.left = 0 + } - //console.log("POS1: ", menuPosition1) + //console.log("POS1: ", menuPosition1) return parsedPaths.length > 0 ? ( { handleItemClick([innerdata]); }} > - + { // const icon = pathdata.type === "value" ? ( - + ) : pathdata.type === "list" ? ( ) : ( - + ); // - const indentation_count = (pathdata.name.match(/\./g) || []).length+1 - const baseIndent =
- //const boxPadding = pathdata.type === "object" ? "10px 0px 0px 0px" : 0 - const boxPadding = 0 - const namesplit = pathdata.name.split(".") - const newname = namesplit[namesplit.length-1] - return ( + const indentation_count = (pathdata.name.match(/\./g) || []).length+1 + const baseIndent =
+ //const boxPadding = pathdata.type === "object" ? "10px 0px 0px 0px" : 0 + const boxPadding = 0 + const namesplit = pathdata.name.split(".") + const newname = namesplit[namesplit.length-1] + return ( { @@ -2341,35 +2339,31 @@ const ParsedAction = (props) => { placement="left" >
- {Array(indentation_count).fill().map((subdata, subindex) => { - return ( - baseIndent - ) - })} - {icon} {newname} - {pathdata.type === "list" ? { - e.preventDefault() - e.stopPropagation() + {Array(indentation_count).fill().map((subdata, subindex) => { + return ( + baseIndent + ) + })} + {icon} {newname} + {pathdata.type === "list" ? { + e.preventDefault() + e.stopPropagation() - console.log("INNER: ", innerdata, pathdata) - - // Removing .list from autocomplete - var newname = pathdata.name - if (newname.length > 5) { - newname = newname.slice(0, newname.length-5) - } - selectedActionParameters[count].value += `{{ $${innerdata.name}.${newname} | size }}` - selectedAction.parameters[count].value = selectedActionParameters[count].value; - setSelectedAction(selectedAction); - setUpdate(Math.random()); - setShowDropdown(false); - setMenuPosition(null); - - // innerdata.name - // pathdata.name - //handleItemClick([innerdata, newpathdata]) - //console.log("CLICK LENGTH!") - }} /> : null} + console.log("INNER: ", innerdata, pathdata) + + // Removing .list from autocomplete + var newname = pathdata.name + if (newname.length > 5) { + newname = newname.slice(0, newname.length-5) + } + + selectedActionParameters[count].value += `{{ $${innerdata.name}.${newname} | size }}` + selectedAction.parameters[count].value = selectedActionParameters[count].value; + setSelectedAction(selectedAction); + setUpdate(Math.random()); + setShowDropdown(false); + setMenuPosition(null); + }} /> : null}
@@ -2747,7 +2741,6 @@ const ParsedAction = (props) => { paddingRight: 0, }} onClick={() => { - console.log("FIND EXAMPLE RESULTS FOR ", selectedAction); if (workflowExecutions.length > 0) { // Look for the ID const found = false; @@ -2756,11 +2749,6 @@ const ParsedAction = (props) => { continue; } - // Enforces it to show at least one - //if (workflowExecutions[key].execution_argument.includes("too large") && key !== workflowExecutions.length - 1) { - // continue - //} - var foundResult = workflowExecutions[key].results.find( (result) => result.action.id === selectedAction.id ) @@ -2769,14 +2757,14 @@ const ParsedAction = (props) => { continue; } - const oldstartnode = cy.getElementById(selectedAction.id); - console.log("FOUND NODe: ", oldstartnode) - if (oldstartnode !== undefined && oldstartnode !== null) { - const foundname = oldstartnode.data("label") - if (foundname !== undefined && foundname !== null) { - foundResult.action.label = foundname - } - } + const oldstartnode = cy.getElementById(selectedAction.id); + console.log("FOUND NODe: ", oldstartnode) + if (oldstartnode !== undefined && oldstartnode !== null) { + const foundname = oldstartnode.data("label") + if (foundname !== undefined && foundname !== null) { + foundResult.action.label = foundname + } + } setSelectedResult(foundResult); if (setCodeModalOpen !== undefined) { @@ -3354,6 +3342,8 @@ const ParsedAction = (props) => { style={{ backgroundColor: theme.palette.inputColor, color: "white", + maxWidth: 500, + overflowX: "auto", }} value={data} > diff --git a/frontend/src/components/ShuffleCodeEditor.jsx b/frontend/src/components/ShuffleCodeEditor.jsx index 3b6e02a2..9015f485 100644 --- a/frontend/src/components/ShuffleCodeEditor.jsx +++ b/frontend/src/components/ShuffleCodeEditor.jsx @@ -61,10 +61,11 @@ import { tags as t } from '@lezer/highlight'; const liquidFilters = [ - {"name": "Size", "value": "size", "example": ""}, - {"name": "Date", "value": `date: "%Y%m%d"`, "example": `{{ "now" | date: "%s" }}`}, + {"name": "Default", "value": `default: []`, "example": `{{ "" | default: "no input" }}`}, {"name": "Split", "value": `split: ","`, "example": `{{ "this,can,become,a,list" | split: "," }}`}, {"name": "Join", "value": `join: ","`, "example": `{{ ["this","can","become","a","string"] | join: "," }}`}, + {"name": "Size", "value": "size", "example": ""}, + {"name": "Date", "value": `date: "%Y%m%d"`, "example": `{{ "now" | date: "%s" }}`}, {"name": "Escape String", "value": `{{ \"\"\"'string with weird'" quotes\"\"\" | escape_string }}`, "example": ``}, {"name": "Flatten", "value": `flatten`, "example": `{{ [1, [1, 2], [2, 3, 4]] | flatten }}`}, {"name": "URL encode", "value": `url_encode`, "example": `{{ "https://www.google.com/search?q=hello world" | url_encode }}`}, diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index 0468a12a..fb007b0b 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -80,6 +80,7 @@ import { Visibility as VisibilityIcon, Done as DoneIcon, Close as CloseIcon, + DragIndicator as DragIndicatorIcon, Error as ErrorIcon, Warning as WarningIcon, ArrowLeft as ArrowLeftIcon, @@ -250,6 +251,7 @@ function useWindowSize() { function updateSize() { setSize([window.innerWidth, window.innerHeight]); } + window.addEventListener("resize", updateSize); updateSize(); return () => window.removeEventListener("resize", updateSize); @@ -598,9 +600,29 @@ const AngularWorkflow = (defaultprops) => { 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) + var [bodyWidth, bodyHeight] = useWindowSize() const cytoscapeWidth = isMobile ? bodyWidth - leftBarSize : bodyWidth - leftBarSize - 25 + + /* + // Zoom testing to try autofixing for small screens + if (document !== undefined && document !== null && !isMobile) { + const currentZoom = document.body.style.zoom; + + if (bodyWidth < 1367 || bodyHeight < 769) { + console.log("LOWER ZOOM") + document.body.style.zoom = "80%" + bodyWidth = bodyWidth*0.8 + bodyHeight = bodyHeight*0.8 + } else { + console.log("RESET ZOOM") + document.body.style.zoom = "100%" + } + } + + console.log("Width, height: ", bodyWidth, bodyHeight) + */ + + //console.log("Mobile: ", isMobile, bodyWidth, bodyHeight) const [elements, setElements] = useState([]); const [loopRunning, setLoopRunning] = useState(false) @@ -7691,7 +7713,7 @@ const AngularWorkflow = (defaultprops) => { marginTop: 1, overflowY: "auto", overflowX: "hidden", - }; + } const handleAppDrag = (e, app) => { const cycontainer = cy.container(); @@ -8426,6 +8448,7 @@ const AngularWorkflow = (defaultprops) => {
) })} + {visibleApps.length <= 4 ? (
{
- ) : null} + ) : +
}
) : apps.length > 0 ? (
{ const AppConditionHandler = (props) => { const { tmpdata, type } = props; - const [data] = useState({...tmpdata}); + const [data] = useState(tmpdata); const [multiline, setMultiline] = useState(false); const [showAutocomplete, setShowAutocomplete] = React.useState(false); const [actionlist, setActionlist] = React.useState([]); @@ -9595,9 +9621,8 @@ const AngularWorkflow = (defaultprops) => { { - const newConditionValue = { ...conditionValue }; - newConditionValue.value = "equals"; - setConditionValue(newConditionValue); + conditionValue.value = "equals"; + setConditionValue(conditionValue); setVariableAnchorEl(null); }} key={"equals"} @@ -9607,9 +9632,8 @@ const AngularWorkflow = (defaultprops) => { { - const newConditionValue = { ...conditionValue }; - newConditionValue.value = "does not equal"; - setConditionValue(newConditionValue); + conditionValue.value = "does not equal"; + setConditionValue(conditionValue); setVariableAnchorEl(null); }} key={"does not equal"} @@ -9619,9 +9643,8 @@ const AngularWorkflow = (defaultprops) => { { - const newConditionValue = { ...conditionValue }; - newConditionValue.value = "startswith"; - setConditionValue(newConditionValue); + conditionValue.value = "startswith"; + setConditionValue(conditionValue); setVariableAnchorEl(null); }} key={"starts with"} @@ -9631,9 +9654,8 @@ const AngularWorkflow = (defaultprops) => { { - const newConditionValue = { ...conditionValue }; - newConditionValue.value = "endswith"; - setConditionValue(newConditionValue); + conditionValue.value = "endswith"; + setConditionValue(conditionValue); setVariableAnchorEl(null); }} key={"ends with"} @@ -9643,9 +9665,8 @@ const AngularWorkflow = (defaultprops) => { { - const newConditionValue = { ...conditionValue }; - newConditionValue.value = "contains"; - setConditionValue(newConditionValue); + conditionValue.value = "contains"; + setConditionValue(conditionValue); setVariableAnchorEl(null); }} key={"contains"} @@ -9655,9 +9676,8 @@ const AngularWorkflow = (defaultprops) => { { - const newConditionValue = { ...conditionValue }; - newConditionValue.value = "contains_any_of"; - setConditionValue(newConditionValue); + conditionValue.value = "contains_any_of"; + setConditionValue(conditionValue); setVariableAnchorEl(null); }} key={"contains_any_of"} @@ -9667,9 +9687,8 @@ const AngularWorkflow = (defaultprops) => { { - const newConditionValue = { ...conditionValue }; - newConditionValue.value = "matches regex"; - setConditionValue(newConditionValue); + conditionValue.value = "matches regex"; + setConditionValue(conditionValue); setVariableAnchorEl(null); }} key={"matches regex"} @@ -9679,9 +9698,8 @@ const AngularWorkflow = (defaultprops) => { { - const newConditionValue = { ...conditionValue }; - newConditionValue.value = "larger than"; - setConditionValue(newConditionValue); + conditionValue.value = "larger than"; + setConditionValue(conditionValue); setVariableAnchorEl(null); }} key={"larger than"} @@ -9691,9 +9709,8 @@ const AngularWorkflow = (defaultprops) => { { - const newConditionValue = { ...conditionValue }; - newConditionValue.value = "less than"; - setConditionValue(newConditionValue); + conditionValue.value = "less than"; + setConditionValue(conditionValue); setVariableAnchorEl(null); }} key={"less than"} @@ -9703,9 +9720,8 @@ const AngularWorkflow = (defaultprops) => { { - const newConditionValue = { ...conditionValue }; - newConditionValue.value = "is empty"; - setConditionValue(newConditionValue); + conditionValue.value = "is empty"; + setConditionValue(conditionValue); setVariableAnchorEl(null); }} key={"is empty"} @@ -9873,8 +9889,6 @@ const AngularWorkflow = (defaultprops) => { marginTop: "15px", marginLeft: "10px", overflow: "hidden", - textOverflow: "ellipsis", - whiteSpace: "nowrap", maxWidth: 72, }} > @@ -9894,7 +9908,7 @@ const AngularWorkflow = (defaultprops) => { flex: 1, textAlign: "center", marginTop: "15px", - overflow: "hidden", + overflow: "hidden", maxWidth: 72, }} onClick={() => { }} @@ -9918,8 +9932,6 @@ const AngularWorkflow = (defaultprops) => { marginBottom: "auto", marginLeft: "10px", overflow: "hidden", - textOverflow: "ellipsis", - whiteSpace: "nowrap", maxWidth: 72, }} > @@ -13582,16 +13594,14 @@ const AngularWorkflow = (defaultprops) => { }, }} disabled={ - workflow.triggers[selectedTriggerIndex].status === "running" + workflow.triggers[selectedTriggerIndex] === null || workflow.triggers[selectedTriggerIndex] === undefined ? false : workflow.triggers[selectedTriggerIndex].status === "running" } fullWidth rows="6" multiline color="primary" defaultValue={ - workflow.triggers[selectedTriggerIndex] !== undefined && workflow.triggers[selectedTriggerIndex].parameters !== undefined && workflow.triggers[selectedTriggerIndex].parameters !== null && workflow.triggers[selectedTriggerIndex].parameters.length > 1 ? - workflow.triggers[selectedTriggerIndex].parameters[1].value - : "" + workflow.triggers[selectedTriggerIndex] !== undefined && workflow.triggers[selectedTriggerIndex].parameters !== undefined && workflow.triggers[selectedTriggerIndex].parameters !== null && workflow.triggers[selectedTriggerIndex].parameters.length > 1 ? workflow.triggers[selectedTriggerIndex].parameters[1].value : "" } placeholder='{"example": {"json": "is cool"}}' onBlur={(e) => { @@ -13661,11 +13671,16 @@ const AngularWorkflow = (defaultprops) => { top: isMobile ? 30 : appBarSize + 20, }; + + + const TopCytoscapeBar = (props) => { if (workflow.public === true) { return null } + const isCorrectOrg = workflow.public === true || userdata.active_org.id === undefined || userdata.active_org.id === null || workflow.org_id === null || workflow.org_id === undefined || workflow.org_id.length === 0 || userdata.active_org.id === workflow.org_id + return (
@@ -13691,7 +13706,7 @@ const AngularWorkflow = (defaultprops) => {

{workflow.name}

- {workflow.public === true || userdata.active_org.id === undefined || userdata.active_org.id === null || workflow.org_id === null || workflow.org_id === undefined || workflow.org_id.length === 0 || userdata.active_org.id === workflow.org_id ? null : + {isCorrectOrg ? null : Warning: Change { ) } - const showErrors = !isMobile && !workflow.public && workflow.errors !== undefined && workflow.errors !== null && workflow.errors.length > 0 ?
{ > {/**/} + + Workflow Issues: {workflow.errors.length} { } var draggingDisabled = false; + + // Should probably put this on the backend instead when notifications are made :)) + const getErrorSuggestion = (result) => { + if (result === undefined || result === null) { + return "" + } + + if (result.success !== false) { + return "" + } + + var stringjson = result + try { + stringjson = JSON.stringify(result) + } catch (e) { + } + + console.log("JSON: ", stringjson) + stringjson = stringjson.toLowerCase() + if (stringjson.includes("localhost")) { + return "You can't use localhost in apps. Use the external ip or url of the server instead" + } + + if (stringjson.includes("connectionerror")) { + return "Your URL is most likely incorrect." + } + + if (stringjson.includes("result too large to handle")) { + return "Execution loading failed. Reload the execution by closing it and clicking it again" + } + + return "" + } + + const currentSuggestion = getErrorSuggestion(validate.result) const codePopoutModal = !codeModalOpen ? null : ( { + + { + }} + > + + + { e.preventDefault(); setCodeModalOpen(false); @@ -16836,12 +16907,20 @@ const AngularWorkflow = (defaultprops) => { > {selectedResult.action.label.replaceAll("_", " ")}
-
{selectedResult.action.name}
+
{selectedResult.action.name}
-
- Status {selectedResult.status} -
+ + + {currentSuggestion.length > 0 ? +
+ Debug Info: {currentSuggestion} +
+ : +
+ Status {selectedResult.status} +
+ } {validate.valid ? ( { margin: "auto", marginTop: 50, }}> - + Documentation
@@ -938,7 +938,7 @@ const Docs = (defaultprops) => { @@ -957,7 +957,7 @@ const Docs = (defaultprops) => { // Padding and zIndex etc set because of footer in cloud. const loadedCheck = ( -
+
{postDataBrowser} {postDataMobile}
diff --git a/frontend/src/views/RunWorkflow.jsx b/frontend/src/views/RunWorkflow.jsx index a8046fc2..bd5d1bc3 100644 --- a/frontend/src/views/RunWorkflow.jsx +++ b/frontend/src/views/RunWorkflow.jsx @@ -333,6 +333,19 @@ const RunWorkflow = (defaultprops) => { "execution_argument": executionArgument } + if (workflow.start !== undefined && workflow.start !== null && workflow.start.length > 0) { + data.start = workflow.start + } else { + if (workflow.actions !== undefined && workflow.actions !== null && workflow.actions.length > 0) { + for (let actionkey in workflow.actions) { + if (workflow.actions[actionkey].isStartNode) { + data.start = workflow.actions[actionkey].id + break + } + } + } + } + var url = `${globalUrl}/api/v1/workflows/${props.match.params.key}/execute` var fetchBody = { headers: {