From d4c33624b78fe61cc0b0aa3615e44e43f456d55c Mon Sep 17 00:00:00 2001 From: frikky Date: Sun, 9 Jan 2022 04:56:33 +0100 Subject: [PATCH] Added basic frontend elements for timing actions --- backend/go-app/go.mod | 4 +- backend/go-app/main.go | 2 +- backend/go-app/walkoff.go | 7 +- docker-compose.yml | 2 +- frontend/src/components/ParsedAction.jsx | 145 ++++++++----- frontend/src/components/ShuffleCodeEditor.jsx | 100 +++++---- frontend/src/views/AngularWorkflow.jsx | 201 ++++++++++++------ functions/onprem/worker/build.sh | 2 +- functions/onprem/worker/go.mod | 2 +- 9 files changed, 297 insertions(+), 168 deletions(-) diff --git a/backend/go-app/go.mod b/backend/go-app/go.mod index 94d499b4..ad9d40b5 100644 --- a/backend/go-app/go.mod +++ b/backend/go-app/go.mod @@ -10,7 +10,7 @@ go 1.15 require ( cloud.google.com/go/datastore v1.6.0 cloud.google.com/go/pubsub v1.17.0 - cloud.google.com/go/storage v1.18.1 + cloud.google.com/go/storage v1.18.2 github.com/basgys/goxml2json v1.1.0 github.com/carlescere/scheduler v0.0.0-20170109141437-ee74d2f83d82 github.com/docker/docker v20.10.9+incompatible @@ -22,7 +22,7 @@ require ( github.com/gorilla/mux v1.8.0 github.com/h2non/filetype v1.1.1 github.com/satori/go.uuid v1.2.0 - github.com/shuffle/shuffle-shared v0.1.70 + github.com/shuffle/shuffle-shared v0.1.72 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect go4.org v0.0.0-20201209231011-d4a079459e60 // indirect golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 diff --git a/backend/go-app/main.go b/backend/go-app/main.go index 72caab2f..61de2288 100644 --- a/backend/go-app/main.go +++ b/backend/go-app/main.go @@ -3960,7 +3960,7 @@ func runInitEs(ctx context.Context) { for _, org := range activeOrgs { if !org.CloudSync { - log.Printf("[WARNING] Skipping org syncCheck for %s because sync isn't set (1).", org.Id) + log.Printf("[INFO] Skipping org syncCheck for %s because sync isn't set (1).", org.Id) continue } diff --git a/backend/go-app/walkoff.go b/backend/go-app/walkoff.go index c7af3c50..390187e0 100644 --- a/backend/go-app/walkoff.go +++ b/backend/go-app/walkoff.go @@ -419,7 +419,7 @@ func handleWorkflowQueue(resp http.ResponseWriter, request *http.Request) { resp.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "success"}`))) return } else { - log.Printf("[DEBUG] Handling other execution variant: %s", err) + log.Printf("[DEBUG] Handling other execution variant (subflow): %s", err) } var actionResult shuffle.ActionResult @@ -1058,6 +1058,9 @@ func executeWorkflow(resp http.ResponseWriter, request *http.Request) { } fileId = location[4] + if strings.Contains(fileId, "?") { + fileId = strings.Split(fileId, "?")[0] + } } if len(fileId) != 36 { @@ -1072,7 +1075,7 @@ func executeWorkflow(resp http.ResponseWriter, request *http.Request) { if err != nil && workflow.ID == "" { log.Printf("[WARNING] Failed getting the workflow locally (execute workflow): %s", err) resp.WriteHeader(401) - resp.Write([]byte(`{"success": false}`)) + resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Workflow with ID %s doesn't exist."}`, fileId))) return } diff --git a/docker-compose.yml b/docker-compose.yml index d48c7797..f1c7ff7c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,7 +16,7 @@ services: depends_on: - backend backend: - build: ./backend + #build: ./backend image: ghcr.io/frikky/shuffle-backend:nightly container_name: shuffle-backend hostname: ${BACKEND_HOSTNAME} diff --git a/frontend/src/components/ParsedAction.jsx b/frontend/src/components/ParsedAction.jsx index 6031622e..c66db8f2 100644 --- a/frontend/src/components/ParsedAction.jsx +++ b/frontend/src/components/ParsedAction.jsx @@ -161,6 +161,8 @@ const ParsedAction = (props) => { authenticationType, appAuthentication, getAppAuthentication, + actionDelayChange, + isCloud, } = props; //const theme = useTheme(); @@ -1015,6 +1017,26 @@ const ParsedAction = (props) => { Parameters + {selectedAction.description !== undefined && selectedAction.description !== null && selectedAction.description.length > 0 && hiddenDescription === false ? ( +
+ + Description + + + {selectedAction.description} + +
+ ) : null} {selectedActionParameters.map((data, count) => { if (data.variant === "") { data.variant = "STATIC_VALUE"; @@ -2282,6 +2304,7 @@ const ParsedAction = (props) => { +
@@ -2351,39 +2374,76 @@ const ParsedAction = (props) => { backgroundColor: "rgb(91, 96, 100)", }} /> - Name - { - const name = e.target.value; - console.log("CHANGED FROM2: ", baselabel); - console.log("CHANGED TO: ", name); - for (var key in workflow.actions) { - for (var subkey in workflow.actions[key].parameters) { - const param = workflow.actions[key].parameters[subkey]; - if (param.value.includes(baselabel)) { - //if (param.value.toLowerCase().includes(baselabel)) { - console.log("FOUND: ", param); - workflow.actions[key].parameters[subkey].value.replaceAll( - baselabel, - e.target.value - ); - } - } - } +
+
+ Name + { + const name = e.target.value; + console.log("CHANGED FROM2: ", baselabel); + console.log("CHANGED TO: ", name); + for (var key in workflow.actions) { + for (var subkey in workflow.actions[key].parameters) { + const param = workflow.actions[key].parameters[subkey]; + if (param.value.includes(baselabel)) { + //if (param.value.toLowerCase().includes(baselabel)) { + console.log("FOUND: ", param); + workflow.actions[key].parameters[subkey].value.replaceAll( + baselabel, + e.target.value + ); + } + } + } - console.log("DID REPLACE ACTUALLY WORK?? - Something is buggy."); - setWorkflow(workflow); - }} - /> + console.log("DID REPLACE ACTUALLY WORK?? - Something is buggy."); + setWorkflow(workflow); + }} + /> +
+ {!isCloud ? null : +
+ + + Delay + { + if (actionDelayChange !== undefined) { + actionDelayChange(event) + } + }} + /> + + +
+ } +
)} {selectedApp.name !== undefined && @@ -2792,27 +2852,6 @@ const ParsedAction = (props) => { : null*/} - {selectedAction.description !== undefined && selectedAction.description !== null && selectedAction.description.length > 0 && hiddenDescription === false ? ( -
- - Description - - - {selectedAction.description} - -
- ) : null} -
{ const [localcodedata, setlocalcodedata] = React.useState(codedata === undefined || codedata === null || codedata.length === 0 ? "" : codedata); // const {codelang, setcodelang} = props const theme = useTheme(); - const [validation, setvalidation] = React.useState(" "); - const [expOutput, setexpOutput] = React.useState(" "); + const [validation, setValidation] = React.useState(false); + const [expOutput, setExpOutput] = React.useState(" "); - function IsJsonString(str) { - try { - var o = JSON.parse(str); - if (o && typeof o === "object") { - setvalidation("Correct!") - } - } catch (e) {setvalidation("Incorrect!");} - } - function expectedOutput(input) { const found = input.match(/[$]{1}([a-zA-Z0-9_-]+\.?){1}([a-zA-Z0-9#_-]+\.?){0,}/g) @@ -56,21 +49,15 @@ const CodeEditor = (props) => { } } catch (e) {} - try { - // var x = document.getElementById("expOutput"); - // x.innerHTML = JSON.stringify(JSON.parse(input), null, 4) - setexpOutput(JSON.stringify(JSON.parse(input), null, 4)) - } catch (e) { - setexpOutput(input) + const tmpValidation = validateJson(input.valueOf()) + //setValidation(true) + if (tmpValidation.valid === true) { + setValidation(true) + setExpOutput(tmpValidation.result) + } else { + setExpOutput(input.valueOf()) + setValidation(false) } - - // const obj = JSON.parse(input); - // setexpOutput(JSON.stringify(JSON.parse(input), null, 4)) - // x.innerHTML = "" + JSON.stringify(input, null, 4) + "" - // x.appendChild(document.createTextNode(JSON.stringify(JSON.parse(input), null, 4))); - // setexpOutput(JSON.stringify(input, undefined, 4).replace('\ ', '\n')) - // setexpOutput("Hi there \n Hey there") - // Variables + Syntax highlighting + Validation } return ( @@ -108,14 +95,12 @@ const CodeEditor = (props) => { }}> { setlocalcodedata(value.getValue()) expectedOutput(value.getValue()) - IsJsonString(value.getValue()) - // console.log(actionlist.slice(-1)) }} options={{ theme: 'gruvbox-dark', @@ -141,22 +126,47 @@ const CodeEditor = (props) => { Output -

- {expOutput} -

+ {validation === true ? + { + //handleReactJsonClipboard(copy); + }} + displayDataTypes={false} + onSelect={(select) => { + //HandleJsonCopy(validate.result, select, "exec"); + }} + name={"JSON autocompletion"} + /> + : +

+ {expOutput} +

+ }

{ marginTop: -15, }} > - JSON Validation: {validation} + JSON Validation: {validation ? "Correct" : "Incorrect"}

diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index 12e7fa3f..3996d622 100644 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -2173,11 +2173,9 @@ const AngularWorkflow = (defaultprops) => { // FIXME: Trust it to just work? //event.target.data() var curaction = workflow.actions.find((a) => a.id === data.id); - var newapps = JSON.parse(JSON.stringify(apps)) if (!curaction || curaction === undefined) { console.log("NOT FOUND DATA: ", event.target.data()) if (data.id !== undefined && data.app_name !== undefined) { - //newapps.push(data) workflow.actions.push(data) setWorkflow(workflow) curaction = data @@ -2188,6 +2186,7 @@ const AngularWorkflow = (defaultprops) => { } } + var newapps = JSON.parse(JSON.stringify(apps)) const curapp = newapps.find( (a) => a.name === curaction.app_name && @@ -5310,13 +5309,10 @@ const AngularWorkflow = (defaultprops) => { } const newParamIndex = newSelectedAction.parameters.findIndex(paramdata => paramdata.name === param.name) - console.log("INDEX: ", newParamIndex) if (newParamIndex < 0) { - console.log("NOT FOUND: ", param) continue } - console.log("FOUND: ", param) newSelectedAction.parameters[newParamIndex].value = param.value } } @@ -5352,8 +5348,6 @@ const AngularWorkflow = (defaultprops) => { // based on previous actions' newSelectedAction = RunAutocompleter(newSelectedAction); - console.log("ACTION: ", newSelectedAction); - if ( newaction.returns.example !== undefined && newaction.returns.example !== null && @@ -5377,7 +5371,17 @@ const AngularWorkflow = (defaultprops) => { //} //setSelectedActionEnvironment(env) + + console.log("ACTION: ", newSelectedAction); setSelectedAction(newSelectedAction); + if (workflow.actions !== undefined && workflow.actions !== null && workflow.actions.length > 0) { + const foundActionIndex = workflow.actions.findIndex(actiondata => actiondata.id === newSelectedAction.id) + console.log("Found action on index ", foundActionIndex) + if (foundActionIndex >= 0) { + workflow.actions[foundActionIndex] = newSelectedAction + setWorkflow(workflow) + } + } setUpdate(Math.random()); // FIXME - should change icon-node (descriptor) as well @@ -5406,7 +5410,6 @@ const AngularWorkflow = (defaultprops) => { // appname & version // description // ACTION select - // const selectedNameChange = (event) => { event.target.value = event.target.value.replaceAll("(", ""); event.target.value = event.target.value.replaceAll(")", ""); @@ -5429,6 +5432,22 @@ const AngularWorkflow = (defaultprops) => { setSelectedAction(selectedAction); }; + const actionDelayChange = (event) => { + if (isNaN(event.target.value)) { + console.log("NAN: ", event.target.value) + return + } + + const parsedNumber = parseInt(event.target.value) + if (parsedNumber > 86400) { + console.log("Max number is 1 day (86400)") + return + } + + selectedAction.execution_delay = parsedNumber + setSelectedAction(selectedAction) + } + const selectedTriggerChange = (event) => { selectedTrigger.label = event.target.value; setSelectedTrigger(selectedTrigger); @@ -7595,6 +7614,10 @@ const AngularWorkflow = (defaultprops) => { const handleSubflowStartnodeSelection = (e) => { setSubworkflowStartnode(e.target.value); + if (e.target.value === null || e.target.value === undefined) { + return + } + const branchId = uuidv4(); const newbranch = { source_id: workflow.triggers[selectedTriggerIndex].id, @@ -7736,26 +7759,75 @@ const AngularWorkflow = (defaultprops) => { backgroundColor: "rgb(91, 96, 100)", }} /> -
Name
- +
+
+ Name + +
+
+ {!isCloud ? null : +
+ + + Delay + { + if (isNaN(event.target.value)) { + console.log("NAN: ", event.target.value) + return + } + + const parsedNumber = parseInt(event.target.value) + if (parsedNumber > 86400) { + console.log("Max number is 1 day (86400)") + return + } + + selectedTrigger.execution_delay = parseInt(event.target.value) + setSelectedTrigger(selectedTrigger) + }} + /> + + +
+ } +
+
{ />
- Parameters -
-
- Select a workflow to execute -
-
+
+
+
+ Select a workflow to execute +
+
+ {workflow.triggers[selectedTriggerIndex].parameters[0].value + .length === 0 ? null : workflow.triggers[selectedTriggerIndex] + .parameters[0].value === props.match.params.key ? null : ( +
+ + + +
+ )} +
{workflows === undefined || workflows === null || workflows.length === 0 ? null : ( @@ -7832,7 +7925,7 @@ const AngularWorkflow = (defaultprops) => { option.name === undefined || option.name === null ) { - return "Loading"; + return "No Workflow Selected"; } const newname = ( @@ -7883,24 +7976,6 @@ const AngularWorkflow = (defaultprops) => { }} /> )} - {workflow.triggers[selectedTriggerIndex].parameters[0].value - .length === 0 ? null : workflow.triggers[selectedTriggerIndex] - .parameters[0].value === props.match.params.key ? null : ( - - - Explore selected workflow - - - )} {subworkflow === undefined || subworkflow === null || @@ -8131,7 +8206,7 @@ const AngularWorkflow = (defaultprops) => { } else { // Always update const newUrl = referenceUrl+"webhook_"+selectedTrigger.id - console.log("Validating webhook url: ", newUrl) + //console.log("Validating webhook url: ", newUrl) if (newUrl !== workflow.triggers[selectedTriggerIndex].parameters[0].value) { console.log("Url is wrong - updating") workflow.triggers[selectedTriggerIndex].parameters[0].value = newUrl @@ -8336,7 +8411,7 @@ const AngularWorkflow = (defaultprops) => { } else { // Always update const newUrl = referenceUrl + "webhook_" + selectedTrigger.id; - console.log("Validating webhook url: ", newUrl); + //console.log("Validating webhook url: ", newUrl); if ( newUrl !== workflow.triggers[selectedTriggerIndex].parameters[0].value ) { @@ -10079,6 +10154,8 @@ const AngularWorkflow = (defaultprops) => {
{ ); }} > - See sub-execution + ) : (