From 0e168158728c1b1e745e1c172d0ee9338ec3506d Mon Sep 17 00:00:00 2001 From: monilprajapati Date: Fri, 5 Jul 2024 14:56:42 +0530 Subject: [PATCH 1/9] Minor subflow fix: label transition --- frontend/src/views/AngularWorkflow.jsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index 6ead5cf0..86bdd1b8 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -13160,7 +13160,7 @@ const releaseToConnectLabel = "Release to Connect" Date: Sat, 6 Jul 2024 13:42:39 +0530 Subject: [PATCH 2/9] Added Expand window button and code editor in subflow --- frontend/src/components/ParsedAction.jsx | 8 +- .../src/components/ShuffleCodeEditor1.jsx | 6 + frontend/src/views/AngularWorkflow.jsx | 302 +++++++++++------- 3 files changed, 205 insertions(+), 111 deletions(-) diff --git a/frontend/src/components/ParsedAction.jsx b/frontend/src/components/ParsedAction.jsx index 8a0ef74a..937b3111 100755 --- a/frontend/src/components/ParsedAction.jsx +++ b/frontend/src/components/ParsedAction.jsx @@ -3162,7 +3162,13 @@ const ParsedAction = (props) => { if (parsedvalue === undefined || parsedvalue === null) { parsedvalue = "" } - + console.log("Data sending to codeeditor(Action): ", { + "name": data.name, + "value": parsedvalue, + "field_number": count, + "actionlist": actionlist, + "field_id": clickedFieldId, + } ) setEditorData({ "name": data.name, "value": parsedvalue, diff --git a/frontend/src/components/ShuffleCodeEditor1.jsx b/frontend/src/components/ShuffleCodeEditor1.jsx index 05830da8..ab4fee06 100644 --- a/frontend/src/components/ShuffleCodeEditor1.jsx +++ b/frontend/src/components/ShuffleCodeEditor1.jsx @@ -1767,6 +1767,7 @@ const CodeEditor = (props) => { // This is to make it so we don't need to handle these fixes on the // backend by itself var fixedcodedata = localcodedata + console.log("Fixedcodedata: ", fixedcodedata) const valid = validateJson(localcodedata, true) if (valid.valid) { fixedcodedata = JSON.stringify(valid.result, null, 2) @@ -1779,6 +1780,11 @@ const CodeEditor = (props) => { setcodedata(fixedcodedata); setExpansionModalOpen(false) } else if (changeActionParameterCodeMirror !== undefined) { + console.log("Entering in Submit onCLick") + console.log("Data passing to chnageActionParameterCodeMirror: ", fixedcodedata) + console.log("Fieldcount: ", fieldCount) + console.log("Actionlist: ", actionlist) + console.log("Event: ", event) //changeActionParameterCodeMirror(event, fieldCount, fixedcodedata) changeActionParameterCodeMirror(event, fieldCount, fixedcodedata, actionlist) setExpansionModalOpen(false) diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index 86bdd1b8..1fe000b1 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -69,6 +69,7 @@ import { AvatarGroup, Autocomplete, Radio, + ButtonGroup, } from "@mui/material"; import { @@ -12833,6 +12834,7 @@ const releaseToConnectLabel = "Release to Connect" workflow.triggers[selectedTriggerIndex].parameters[1] = { name: "argument", value: "", + id:"subflow_field" }; workflow.triggers[selectedTriggerIndex].parameters[2] = { name: "user_apikey", @@ -13346,13 +13348,14 @@ const releaseToConnectLabel = "Release to Connect" } }} disabled={isCloud && isParent} - onClick={() => { - handleSubflowStartnodeSelection({ - target: { - value: action - } - }) - }} + onClick={() => { + handleSubflowStartnodeSelection({ + target: { + value: action + } + }) + document.activeElement.blur(); + }} style={{ backgroundColor: theme.palette.inputColor, color: isParent ? "red" : "white", @@ -13396,6 +13399,7 @@ const releaseToConnectLabel = "Release to Connect" - - { - setMenuPosition({ - top: event.pageY + 10, - left: event.pageX + 10, - }); - //setShowDropdownNumber(3) - setShowDropdown(true); - }} - /> - + + + { + event.preventDefault() + // setFieldCount(count) + setCodeEditorModalOpen(true) + setActiveDialog("codeeditor") + //setcodedata(data.value) + var parsedvalue = workflow.triggers[selectedTriggerIndex].parameters[1].value + // if (parsedvalue === undefined || parsedvalue === null) { + // parsedvalue = "" + // } + console.log("Data sending to codeeditor: ",{ + "name": workflow.triggers[selectedTriggerIndex].parameters[1].name, + "value": parsedvalue, + "field_number": 1, + "actionlist": actionlist, + "field_id": "subflow_field", + }) + setEditorData({ + "name": workflow.triggers[selectedTriggerIndex].parameters[1].name, + "value": parsedvalue, + "field_number": 1, + "actionlist": actionlist, + "field_id": "subflow_field", + }) + }} + /> + + + { + setMenuPosition({ + top: event.pageY + 10, + left: event.pageX + 10, + }); + //setShowDropdownNumber(3) + setShowDropdown(true); + }} + /> + + ), }} @@ -21767,108 +21803,154 @@ const releaseToConnectLabel = "Release to Connect" const changeActionParameterCodeMirror = (event, count, data, actionlist) => { - // Check if event.target.value is an array. If it is, split with comma - console.log("1 - SELECTED ACTION: ", selectedAction) - console.log("1 - DATA: ", data) + + if(selectedAction && selectedAction.parameters && selectedAction.parameters.length > 0){ - if (data.startsWith("${") && data.endsWith("}")) { - // PARAM FIX - Gonna use the ID field, even though it's a hack - const paramcheck = selectedAction.parameters.find(param => param.name === "body") - if (paramcheck !== undefined) { - // Escapes all double quotes - const toReplace = event.target.value.trim().replaceAll("\\\"", "\"").replaceAll("\"", "\\\""); - if (paramcheck["value_replace"] === undefined || paramcheck["value_replace"] === null) { - paramcheck["value_replace"] = [{ - "key": data.name, - "value": toReplace, - }] + // Check if event.target.value is an array. If it is, split with comma + console.log("1 - SELECTED ACTION: ", selectedAction) + console.log("1 - DATA: ", data) - } else { - const subparamindex = paramcheck["value_replace"].findIndex(param => param.key === data.name) - if (subparamindex === -1) { - paramcheck["value_replace"].push({ - "key": data.name, - "value": toReplace, - }) - } else { - paramcheck["value_replace"][subparamindex]["value"] = toReplace - } - } + if (data.startsWith("${") && data.endsWith("}")) { + // PARAM FIX - Gonna use the ID field, even though it's a hack + const paramcheck = selectedAction.parameters.find(param => param.name === "body") + if (paramcheck !== undefined) { + // Escapes all double quotes + const toReplace = event.target.value.trim().replaceAll("\\\"", "\"").replaceAll("\"", "\\\""); + if (paramcheck["value_replace"] === undefined || paramcheck["value_replace"] === null) { + paramcheck["value_replace"] = [{ + "key": data.name, + "value": toReplace, + }] - if (paramcheck["value_replace"] === undefined) { - selectedAction.parameters[count]["value_replace"] = paramcheck - } else { - //selectedActionParameters[count]["value_replace"] = paramcheck["value_replace"] - selectedAction.parameters[count]["value_replace"] = paramcheck["value_replace"] - } - setSelectedAction(selectedAction) - //setUpdate(Math.random()) - return - } - } + } else { + const subparamindex = paramcheck["value_replace"].findIndex(param => param.key === data.name) + if (subparamindex === -1) { + paramcheck["value_replace"].push({ + "key": data.name, + "value": toReplace, + }) + } else { + paramcheck["value_replace"][subparamindex]["value"] = toReplace + } + } - if (event.target.value[event.target.value.length-1] === "." && actionlist.length > 0) { - var curstring = "" - var record = false - for (let [key,keyval] in Object.entries(selectedAction.parameters[count].value)) { - const item = selectedAction.parameters[count].value[key] - if (record) { - curstring += item - } + if (paramcheck["value_replace"] === undefined) { + selectedAction.parameters[count]["value_replace"] = paramcheck + } else { + //selectedActionParameters[count]["value_replace"] = paramcheck["value_replace"] + selectedAction.parameters[count]["value_replace"] = paramcheck["value_replace"] + } + setSelectedAction(selectedAction) + //setUpdate(Math.random()) + return + } + } - if (item === "$") { - record = true - curstring = "" - } - } + if (event.target.value[event.target.value.length-1] === "." && actionlist.length > 0) { + var curstring = "" + var record = false + for (let [key,keyval] in Object.entries(selectedAction.parameters[count].value)) { + const item = selectedAction.parameters[count].value[key] + if (record) { + curstring += item + } - if (curstring.length > 0 && actionlist !== null) { - // Search back in the action list - curstring = curstring.split(" ").join("_").toLowerCase() - var actionItem = actionlist.find(data => data.autocomplete.split(" ").join("_").toLowerCase() === curstring) - if (actionItem !== undefined) { - console.log("Found item: ", actionItem) + if (item === "$") { + record = true + curstring = "" + } + } - var jsonvalid = true - try { - const tmp = String(JSON.parse(actionItem.example)) - if (!actionItem.example.includes("{") && !actionItem.example.includes("[")) { - jsonvalid = false - } - } catch (e) { - jsonvalid = false - } - } - } - } + if (curstring.length > 0 && actionlist !== null) { + // Search back in the action list + curstring = curstring.split(" ").join("_").toLowerCase() + var actionItem = actionlist.find(data => data.autocomplete.split(" ").join("_").toLowerCase() === curstring) + if (actionItem !== undefined) { + console.log("Found item: ", actionItem) - console.log("2 - SELECTED ACTION: ", selectedAction) - console.log("2 - DATA: ", data) + var jsonvalid = true + try { + const tmp = String(JSON.parse(actionItem.example)) + if (!actionItem.example.includes("{") && !actionItem.example.includes("[")) { + jsonvalid = false + } + } catch (e) { + jsonvalid = false + } + } + } + } - if (selectedAction.app_name === "Shuffle Tools" && selectedAction.name === "filter_list" && count === 0) { - const parsedvalue = data - console.log("Parsed value: ", parsedvalue) - if (parsedvalue.includes("#")) { - const splitparsed = parsedvalue.split(".#.") - //console.log("Cant contain #: ", splitparsed) - if (splitparsed.length > 1) { - console.log("IN HERE AY") - //data.value = splitparsed[0] + console.log("2 - SELECTED ACTION: ", selectedAction) + console.log("2 - DATA: ", data) - selectedAction.parameters[0].value = splitparsed[0] - selectedAction.parameters[1].value = splitparsed[1] + if (selectedAction.app_name === "Shuffle Tools" && selectedAction.name === "filter_list" && count === 0) { + const parsedvalue = data + console.log("Parsed value: ", parsedvalue) + if (parsedvalue.includes("#")) { + const splitparsed = parsedvalue.split(".#.") + //console.log("Cant contain #: ", splitparsed) + if (splitparsed.length > 1) { + console.log("IN HERE AY") + //data.value = splitparsed[0] - selectedAction.parameters[0].autocompleted = true - selectedAction.parameters[1].autocompleted = true - setUpdate(Math.random()) - } - } - } else { - selectedAction.parameters[count].autocompleted = false - selectedAction.parameters[count].value = data - } + selectedAction.parameters[0].value = splitparsed[0] + selectedAction.parameters[1].value = splitparsed[1] - setSelectedAction(selectedAction) + selectedAction.parameters[0].autocompleted = true + selectedAction.parameters[1].autocompleted = true + setUpdate(Math.random()) + } + } + } else { + selectedAction.parameters[count].autocompleted = false + selectedAction.parameters[count].value = data + } + + setSelectedAction(selectedAction) + } + + if(selectedTrigger && selectedTrigger.parameters && selectedTrigger.parameters.length > 0){ + + if (event.target.value[event.target.value.length-1] === "." && actionlist.length > 0) { + var curstring = "" + var record = false + for (let [key,keyval] in Object.entries(selectedTrigger.parameters[count].value)) { + const item = selectedTrigger.parameters[count].value[key] + if (record) { + curstring += item + } + + if (item === "$") { + record = true + curstring = "" + } + } + + if (curstring.length > 0 && actionlist !== null) { + // Search back in the action list + curstring = curstring.split(" ").join("_").toLowerCase() + var actionItem = actionlist.find(data => data.autocomplete.split(" ").join("_").toLowerCase() === curstring) + if (actionItem !== undefined) { + console.log("Found item: ", actionItem) + + var jsonvalid = true + try { + const tmp = String(JSON.parse(actionItem.example)) + if (!actionItem.example.includes("{") && !actionItem.example.includes("[")) { + jsonvalid = false + } + } catch (e) { + jsonvalid = false + } + } + } + } + + selectedTrigger.parameters[count].value = data + setSelectedTrigger(selectedTrigger); + console.log("get into trigger controller", selectedTrigger,data) + } //setUpdate(Math.random()) } From fc086dd565f65362e3370b4ab275e4a940f5d6df Mon Sep 17 00:00:00 2001 From: monilprajapati Date: Fri, 5 Jul 2024 13:55:09 +0530 Subject: [PATCH 3/9] Minor fix --- frontend/src/components/ParsedAction.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/components/ParsedAction.jsx b/frontend/src/components/ParsedAction.jsx index 937b3111..ee9b3163 100755 --- a/frontend/src/components/ParsedAction.jsx +++ b/frontend/src/components/ParsedAction.jsx @@ -629,6 +629,7 @@ const ParsedAction = (props) => { return {...param, value: paramvalue} }); selectedAction.parameters = newParameters; + setSelectedActionParameters(newParameters); setSelectedAction(selectedAction); return newParameters; },[actionlist,selectedAction,workflow.actions,workflow,selectedApp,setNewSelectedAction]) From 4f802557f0b282e59a33251f6d344fe10a26f9e3 Mon Sep 17 00:00:00 2001 From: monilprajapati Date: Fri, 5 Jul 2024 16:59:23 +0530 Subject: [PATCH 4/9] ParsedAction Fixes --- frontend/src/components/ParsedAction.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/ParsedAction.jsx b/frontend/src/components/ParsedAction.jsx index ee9b3163..2866b840 100755 --- a/frontend/src/components/ParsedAction.jsx +++ b/frontend/src/components/ParsedAction.jsx @@ -177,16 +177,16 @@ const ParsedAction = (props) => { const classes = useStyles(); const [hideBody, setHideBody] = React.useState(true) const [activateHidingBodyButton, setActivateHidingBodyButton] = React.useState(false) - const [appActionName, setAppActionName] = React.useState(selectedAction.label); + const [appActionName, setAppActionName] = React.useState(selectedAction?.label); const [delay, setDelay] = React.useState(selectedAction?.execution_delay || 0); - const [prevActionName, setPrevActionName] = React.useState(selectedAction.label); + const [prevActionName, setPrevActionName] = React.useState(selectedAction?.label); const [fieldCount, setFieldCount] = React.useState(0); const [hiddenDescription, setHiddenDescription] = React.useState(true); const [autoCompleting, setAutocompleting] = React.useState(false); const [selectedActionParameters, setSelectedActionParameters] = React.useState(selectedAction?.parameters || []); const [selectedVariableParameter, setSelectedVariableParameter] = React.useState(""); const [paramValues, setParamValues] = React.useState( - selectedAction?.parameters.map((param) => { + selectedAction?.parameters?.map((param) => { return { name: param.name, value: param.value, @@ -635,7 +635,7 @@ const ParsedAction = (props) => { },[actionlist,selectedAction,workflow.actions,workflow,selectedApp,setNewSelectedAction]) useEffect(() => { - setParamValues(memoizedParam.map((param) => { + setParamValues(memoizedParam?.map((param) => { return { name: param.name, value: param.value, From 3aa156de78080611892ed79ca677bd759fa2167e Mon Sep 17 00:00:00 2001 From: monilprajapati Date: Thu, 11 Jul 2024 12:29:57 +0530 Subject: [PATCH 5/9] Added dynamic parent node name change feature in subflow arg. param --- frontend/src/components/ParsedAction.jsx | 73 ++++++++++++++++++++++++ frontend/src/views/AngularWorkflow.jsx | 1 + 2 files changed, 74 insertions(+) diff --git a/frontend/src/components/ParsedAction.jsx b/frontend/src/components/ParsedAction.jsx index 2866b840..4fec9a67 100755 --- a/frontend/src/components/ParsedAction.jsx +++ b/frontend/src/components/ParsedAction.jsx @@ -130,6 +130,7 @@ const ParsedAction = (props) => { setSelectedResult, selectedAction, setSelectedApp, + selectedTrigger, setSelectedTrigger, setSelectedEdge, setCurrentView, @@ -1885,6 +1886,78 @@ const ParsedAction = (props) => { } } + if(workflow.triggers !== undefined && workflow.triggers !== null && workflow.triggers.length > 0) { + for(let [key,keyval] in Object.entries(workflow.triggers)) { + if(workflow.triggers[key].id === selectedTrigger.id) { + continue + } + + const params = workflow.triggers[key].parameters + if (params === null || params === undefined) { + continue + } + + for (let [subkey, subkeyval] in Object.entries(params)) { + const param = workflow.triggers[key].parameters[subkey]; + if(param.name === "argument"){ + if (!param.value.includes("$")) { + continue + } + + // Should have a smarter way of discovering node names + // Do regex? + // Finding index(es) and replacing at the location + // + + try { + var cnt = -1 + var previous = 0 + while (true) { + cnt += 1 + // Need to make sure e.g. changing the first here doesn't change the 2nd + // $change_me + // $change_me_2 + const foundindex = param.value.toLowerCase().indexOf(parsedBaseLabel, previous) + if (foundindex === previous && foundindex !== 0) { + break + } + + if (foundindex >= 0) { + previous = foundindex+newname.length + // Need to add diff of length to word + + // Check location: + // If it's a-zA-Z_ then don't replace + if (param.value.length > foundindex+parsedBaseLabel.length) { + const regex = /[a-zA-Z0-9_]/g; + const match = param.value[foundindex+parsedBaseLabel.length].match(regex); + if (match !== null) { + continue + } + } + + console.log("Old found: ", workflow.triggers[key].parameters[subkey].value) + const extralength = newname.length-parsedBaseLabel.length + param.value = param.value.substring(0, foundindex) + newname + param.value.substring(foundindex-extralength+newname.length, param.value.length) + + console.log("New: ", workflow.triggers[key].parameters[subkey].value) + } else { + break + } + + // Break no matter what after 5 replaces. May need to increase + if (cnt >= 5) { + break + } + + } + } catch (e) { + console.log("Failed value replacement based on index: ", e) + } + } + } + } + } setWorkflow(workflow); setUpdate(Math.random()); setPrevActionName(name) diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index 1fe000b1..948d64fc 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -20103,6 +20103,7 @@ const releaseToConnectLabel = "Release to Connect" workflowExecutions={workflowExecutions} setSelectedResult={setSelectedResult} setSelectedApp={setSelectedApp} + selectedTrigger={selectedTrigger} setSelectedTrigger={setSelectedTrigger} setSelectedEdge={setSelectedEdge} setCurrentView={setCurrentView} From 6c593f2ed4624c43be65ba0ae9641cb4f752e466 Mon Sep 17 00:00:00 2001 From: monilprajapati Date: Fri, 12 Jul 2024 15:46:50 +0530 Subject: [PATCH 6/9] Fixed the subflow Jumpy rendering issue but the value updation is remaining --- frontend/src/views/AngularWorkflow.jsx | 596 +++++++++++++------------ 1 file changed, 321 insertions(+), 275 deletions(-) diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index 948d64fc..61d6fbfe 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -522,7 +522,9 @@ const AngularWorkflow = (defaultprops) => { const [lastSaved, setLastSaved] = React.useState(true); const [selectionOpen, setSelectionOpen] = React.useState(false); - + const [menuPosition, setMenuPosition] = useState(null); + const [showDropdown, setShowDropdown] = React.useState(false); + const [subflowActionList, setSubflowActionlist] = React.useState([]); // eslint-disable-next-line no-unused-vars const [_, setUpdate] = useState(""); // Used to force rendring, don't remove @@ -538,7 +540,7 @@ const AngularWorkflow = (defaultprops) => { const [distributedFromParent, setDistributedFromParent] = React.useState("") const [suborgWorkflows, setSuborgWorkflows] = React.useState([]) - + const [subflowExec, setSubflowExec] = React.useState("") const [suggestionBox, setSuggestionBox] = React.useState({ "position": { "top": 500, @@ -547,7 +549,6 @@ const AngularWorkflow = (defaultprops) => { "open": false, "attachedTo": "", }) - useEffect(() => { if (!firstrequest && isLoaded && isLoggedIn && editWorkflowModalOpen === false) { saveWorkflow(workflow) @@ -788,6 +789,148 @@ const releaseToConnectLabel = "Release to Connect" }, [selectedApp]) + useEffect(() => { + + const newActionList = []; + + // Process workflowExecutions + if (workflowExecutions.length > 0) { + for (let execution of workflowExecutions) { + const execArg = execution.execution_argument; + if (execArg && execArg.length > 0) { + const valid = validateJson(execArg); + if (valid.valid) { + newActionList.push({ + type: "Execution Argument", + name: "Execution Argument", + value: "$exec", + highlight: "exec", + autocomplete: "exec", + example: valid.result, + }); + break; + } + } + } + } + + if (newActionList.length === 0) { + // FIXME: Have previous execution values in here + newActionList.push({ + type: "Execution Argument", + name: "Execution Argument", + value: "$exec", + highlight: "exec", + autocomplete: "exec", + example: "hello", + }) + newActionList.push({ + type: "Shuffle Database", + name: "Shuffle Database", + value: "$shuffle_cache", + highlight: "shuffle_db", + autocomplete: "shuffle_cache", + example: "hello", + }) + } + + if ( + workflow.workflow_variables !== null && + workflow.workflow_variables !== undefined && + workflow.workflow_variables.length > 0 + ) { + for (let varkey in workflow.workflow_variables) { + const item = workflow.workflow_variables[varkey]; + newActionList.push({ + type: "workflow_variable", + name: item.name, + value: item.value, + id: item.id, + autocomplete: `${item.name.split(" ").join("_")}`, + example: item.value, + }); + } + } + + // FIXME: Add values from previous executions if they exist + if ( + workflow.execution_variables !== null && + workflow.execution_variables !== undefined && + workflow.execution_variables.length > 0 + ) { + for (let varkey in workflow.execution_variables) { + const item = workflow.execution_variables[varkey]; + newActionList.push({ + type: "execution_variable", + name: item.name, + value: item.value, + id: item.id, + autocomplete: `${item.name.split(" ").join("_")}`, + example: "", + }); + } + } + + if(getParents){ + var parents = getParents(selectedTrigger); + if (parents.length > 1) { + for (let parentkey in parents) { + const item = parents[parentkey]; + if (item.label === "Execution Argument") { + continue; + } + + var exampledata = item.example === undefined ? "" : item.example; + // Find previous execution and their variables + if (workflowExecutions.length > 0) { + // Look for the ID + for (let execkey in workflowExecutions) { + if ( + workflowExecutions[execkey].results === undefined || + workflowExecutions[execkey].results === null + ) { + continue; + } + + var foundResult = workflowExecutions[execkey].results.find( + (result) => result.action.id === item.id + ); + if (foundResult === undefined) { + continue; + } + + const validated = validateJson(foundResult.result) + if (validated.valid) { + exampledata = validateJson.result + break + } + } + } + + // 1. Take + const actionvalue = { + type: "action", + id: item.id, + name: item.label, + autocomplete: `${item.label.split(" ").join("_")}`, + example: exampledata, + } + newActionList.push(actionvalue); + } + } + } + + setSubflowActionlist(newActionList); + + },[selectedTrigger, workflowExecutions]); + + + useEffect(() => { + if(selectedTrigger.parameters !== undefined && selectedTrigger.parameters.length > 1){ + setSubflowExec(selectedTrigger?.parameters[1]?.value) + } + },[selectedTrigger,selectedTriggerIndex,subflowActionList]); + const [executionArgumentModalOpen, setExecutionArgumentModalOpen] = React.useState(false); // This should all be set once, not on every iteration @@ -4528,7 +4671,7 @@ const releaseToConnectLabel = "Release to Connect" } - + console.log("Selected Trigger: ", selectedTrigger) // Nodeselectbatching: // https://stackoverflow.com/questions/16677856/cy-onselect-callback-only-once // onNodeClick @@ -4540,9 +4683,11 @@ const releaseToConnectLabel = "Release to Connect" const data = event.target.data() if (data.app_name === "Shuffle Workflow") { - if ((data.parameters !== undefined) && (data.parameters.length > 0)) { + if ((data.parameters !== undefined) && (data?.parameters?.length > 0)) { getWorkflowApps(data.parameters[0].value) } + console.log("data", data) + // setSubflowExec(data?.parameters[1]?.value) } if (data.buttonType == "ACTIONSUGGESTION") { @@ -10220,7 +10365,7 @@ const releaseToConnectLabel = "Release to Connect" var maxiter = 10; while (true) { for (let parentkey in allkeys) { - var currentnode = cy.getElementById(allkeys[parentkey]); + var currentnode = cy?.getElementById(allkeys[parentkey]); if (currentnode === undefined || currentnode === null) { continue; } @@ -12660,124 +12805,154 @@ const releaseToConnectLabel = "Release to Connect" ); }; - const SubflowSidebar = () => { - const [menuPosition, setMenuPosition] = useState(null); - const [showDropdown, setShowDropdown] = React.useState(false); - const [actionlist, setActionlist] = React.useState([]); + if (Object.getOwnPropertyNames(selectedTrigger).length > 0) { + if (workflow.triggers[selectedTriggerIndex] === undefined) { + return null; + } - if (actionlist.length === 0) { - // FIXME: Have previous execution values in here - actionlist.push({ - type: "Execution Argument", - name: "Execution Argument", - value: "$exec", - highlight: "exec", - autocomplete: "exec", - example: "hello", - }) - actionlist.push({ - type: "Shuffle Database", - name: "Shuffle Database", - value: "$shuffle_cache", - highlight: "shuffle_db", - autocomplete: "shuffle_cache", - example: "hello", - }) + if ( + workflow.triggers[selectedTriggerIndex].parameters === undefined || + workflow.triggers[selectedTriggerIndex].parameters === null || + workflow.triggers[selectedTriggerIndex].parameters.length === 0 + ) { + workflow.triggers[selectedTriggerIndex].parameters = []; + workflow.triggers[selectedTriggerIndex].parameters[0] = { + name: "workflow", + value: "", + }; + workflow.triggers[selectedTriggerIndex].parameters[1] = { + name: "argument", + value: "", + id:"subflow_field" + }; + workflow.triggers[selectedTriggerIndex].parameters[2] = { + name: "user_apikey", + value: "", + }; + workflow.triggers[selectedTriggerIndex].parameters[3] = { + name: "startnode", + value: "", + }; + workflow.triggers[selectedTriggerIndex].parameters[4] = { + name: "check_result", + value: "false", + }; + workflow.triggers[selectedTriggerIndex].parameters[5] = { + name: "auth_override", + value: "", + }; + + /* + // API-key has been replaced by auth key for the execution. + // Parents can now automatically execute children without auth from a user, as long as the subflow in question is owned by the same org and the subflow is actually referencing it during checkin. + console.log("SETTINGS: ", userSettings); if ( - workflow.workflow_variables !== null && - workflow.workflow_variables !== undefined && - workflow.workflow_variables.length > 0 + userSettings !== undefined && + userSettings !== null && + userSettings.apikey !== null && + userSettings.apikey !== undefined && + userSettings.apikey.length > 0 ) { - for (let varkey in workflow.workflow_variables) { - const item = workflow.workflow_variables[varkey]; - actionlist.push({ - type: "workflow_variable", - name: item.name, - value: item.value, - id: item.id, - autocomplete: `${item.name.split(" ").join("_")}`, - example: item.value, - }); - } + workflow.triggers[selectedTriggerIndex].parameters[2] = { + name: "user_apikey", + value: userSettings.apikey, + }; + } + */ + } + + var handleSubflowStartnodeSelection = (e) => { + setSubworkflowStartnode(e.target.value); + + if (e.target.value === null || e.target.value === undefined) { + return } - // FIXME: Add values from previous executions if they exist - if ( - workflow.execution_variables !== null && - workflow.execution_variables !== undefined && - workflow.execution_variables.length > 0 - ) { - for (let varkey in workflow.execution_variables) { - const item = workflow.execution_variables[varkey]; - actionlist.push({ - type: "execution_variable", - name: item.name, - value: item.value, - id: item.id, - autocomplete: `${item.name.split(" ").join("_")}`, - example: "", - }); - } - } + const branchId = uuidv4(); + const newbranch = { + source_id: workflow.triggers[selectedTriggerIndex].id, + destination_id: e.target.value.id, + source: workflow.triggers[selectedTriggerIndex].id, + target: e.target.value.id, + has_errors: false, + id: branchId, + _id: branchId, + label: "Subflow", + decorator: true, + }; - var parents = getParents(selectedTrigger); - if (parents.length > 1) { - for (let parentkey in parents) { - const item = parents[parentkey]; - if (item.label === "Execution Argument") { - continue; - } - - var exampledata = item.example === undefined ? "" : item.example; - // Find previous execution and their variables - if (workflowExecutions.length > 0) { - // Look for the ID - for (let execkey in workflowExecutions) { - if ( - workflowExecutions[execkey].results === undefined || - workflowExecutions[execkey].results === null - ) { - continue; - } - - var foundResult = workflowExecutions[execkey].results.find( - (result) => result.action.id === item.id - ); - if (foundResult === undefined) { - continue; - } - - const validated = validateJson(foundResult.result) - if (validated.valid) { - exampledata = validateJson.result - break - } + if (workflow.visual_branches !== undefined) { + if (workflow.visual_branches === null) { + workflow.visual_branches = [newbranch]; + } else if (workflow.visual_branches.length === 0) { + workflow.visual_branches.push(newbranch); + } else { + const foundIndex = workflow.visual_branches.findIndex( + (branch) => branch.source_id === newbranch.source_id + ); + if (foundIndex !== -1) { + const currentEdge = cy.getElementById( + workflow.visual_branches[foundIndex].id + ); + if ( + currentEdge !== undefined && + currentEdge !== null + ) { + currentEdge.remove(); } } - // 1. Take - const actionvalue = { - type: "action", - id: item.id, - name: item.label, - autocomplete: `${item.label.split(" ").join("_")}`, - example: exampledata, - } - actionlist.push(actionvalue); + workflow.visual_branches.splice(foundIndex, 1); + workflow.visual_branches.push(newbranch); } } - setActionlist(actionlist); - } + if (workflow.id === subworkflow.id) { + const cybranch = { + group: "edges", + source: newbranch.source_id, + target: newbranch.destination_id, + id: branchId, + data: newbranch, + }; + + cy.add(cybranch); + } + + console.log("Value to be set: ", e.target.value); + try { + workflow.triggers[ + selectedTriggerIndex + ].parameters[3].value = e.target.value.id; + } catch { + workflow.triggers[selectedTriggerIndex].parameters[3] = + { + name: "startnode", + value: e.target.value.id, + }; + } + + setWorkflow(workflow); + }; + } + + + var subflowtypes = [ + { + name: "Any", + }, + { + name: "Enrich", + } + ] - const handleMenuClose = () => { - setUpdate(Math.random()); - setMenuPosition(null); - }; + const handleMenuClose = () => { + setUpdate(Math.random()); + setMenuPosition(null); + }; - const handleItemClick = (values) => { - console.log("VALUES: ", values) + const handleItemClick = (values) => { if (values === undefined || values === null || values.length === 0) { return; } @@ -12799,164 +12974,30 @@ const releaseToConnectLabel = "Release to Connect" } */ - console.log("SELECTED TRIGGER: ", selectedTrigger) if (selectedTrigger.name === "Shuffle Workflow") { const toComplete = selectedTrigger.parameters[1].value + "$" + values[0].autocomplete selectedTrigger.parameters[1].value = toComplete + // setSubflowExec(selectedTrigger.parameters[1].value) setSelectedTrigger(selectedTrigger) + setWorkflow(workflow) } setUpdate(Math.random()); setShowDropdown(false); setMenuPosition(null); - }; + }; - const iconStyle = { - marginRight: 15, - }; + const handleSubflowExecChange = (e) => { + setSubflowExec(e.target.value) + // if(selectedTrigger.length > 0){ + // selectedTrigger.parameters[1].value = e.target.value + // setSelectedTrigger(selectedTrigger) + // setWorkflow(workflow) + // setLastSaved(false) + // } + } - - if (Object.getOwnPropertyNames(selectedTrigger).length > 0) { - if (workflow.triggers[selectedTriggerIndex] === undefined) { - return null; - } - - if ( - workflow.triggers[selectedTriggerIndex].parameters === undefined || - workflow.triggers[selectedTriggerIndex].parameters === null || - workflow.triggers[selectedTriggerIndex].parameters.length === 0 - ) { - workflow.triggers[selectedTriggerIndex].parameters = []; - workflow.triggers[selectedTriggerIndex].parameters[0] = { - name: "workflow", - value: "", - }; - workflow.triggers[selectedTriggerIndex].parameters[1] = { - name: "argument", - value: "", - id:"subflow_field" - }; - workflow.triggers[selectedTriggerIndex].parameters[2] = { - name: "user_apikey", - value: "", - }; - workflow.triggers[selectedTriggerIndex].parameters[3] = { - name: "startnode", - value: "", - }; - workflow.triggers[selectedTriggerIndex].parameters[4] = { - name: "check_result", - value: "false", - }; - workflow.triggers[selectedTriggerIndex].parameters[5] = { - name: "auth_override", - value: "", - }; - - /* - // API-key has been replaced by auth key for the execution. - // Parents can now automatically execute children without auth from a user, as long as the subflow in question is owned by the same org and the subflow is actually referencing it during checkin. - console.log("SETTINGS: ", userSettings); - if ( - userSettings !== undefined && - userSettings !== null && - userSettings.apikey !== null && - userSettings.apikey !== undefined && - userSettings.apikey.length > 0 - ) { - workflow.triggers[selectedTriggerIndex].parameters[2] = { - name: "user_apikey", - value: userSettings.apikey, - }; - } - */ - } - - 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, - destination_id: e.target.value.id, - source: workflow.triggers[selectedTriggerIndex].id, - target: e.target.value.id, - has_errors: false, - id: branchId, - _id: branchId, - label: "Subflow", - decorator: true, - }; - - if (workflow.visual_branches !== undefined) { - if (workflow.visual_branches === null) { - workflow.visual_branches = [newbranch]; - } else if (workflow.visual_branches.length === 0) { - workflow.visual_branches.push(newbranch); - } else { - const foundIndex = workflow.visual_branches.findIndex( - (branch) => branch.source_id === newbranch.source_id - ); - if (foundIndex !== -1) { - const currentEdge = cy.getElementById( - workflow.visual_branches[foundIndex].id - ); - if ( - currentEdge !== undefined && - currentEdge !== null - ) { - currentEdge.remove(); - } - } - - workflow.visual_branches.splice(foundIndex, 1); - workflow.visual_branches.push(newbranch); - } - } - - if (workflow.id === subworkflow.id) { - const cybranch = { - group: "edges", - source: newbranch.source_id, - target: newbranch.destination_id, - id: branchId, - data: newbranch, - }; - - cy.add(cybranch); - } - - console.log("Value to be set: ", e.target.value); - try { - workflow.triggers[ - selectedTriggerIndex - ].parameters[3].value = e.target.value.id; - } catch { - workflow.triggers[selectedTriggerIndex].parameters[3] = - { - name: "startnode", - value: e.target.value.id, - }; - } - - setWorkflow(workflow); - } - - - const subflowtypes = [ - { - name: "Any", - }, - { - name: "Enrich", - } - ] - - return ( + const SubflowSidebar = Object.getOwnPropertyNames(selectedTrigger).length === 0 || workflow.triggers[selectedTriggerIndex] === undefined || selectedTrigger.trigger_type !== "SUBFLOW" ? null :

@@ -13419,7 +13460,7 @@ const releaseToConnectLabel = "Release to Connect" setCodeEditorModalOpen(true) setActiveDialog("codeeditor") //setcodedata(data.value) - var parsedvalue = workflow.triggers[selectedTriggerIndex].parameters[1].value + var parsedvalue = workflow?.triggers[selectedTriggerIndex]?.parameters[1]?.value // if (parsedvalue === undefined || parsedvalue === null) { // parsedvalue = "" // } @@ -13427,14 +13468,14 @@ const releaseToConnectLabel = "Release to Connect" "name": workflow.triggers[selectedTriggerIndex].parameters[1].name, "value": parsedvalue, "field_number": 1, - "actionlist": actionlist, + "actionlist": subflowActionList, "field_id": "subflow_field", }) setEditorData({ "name": workflow.triggers[selectedTriggerIndex].parameters[1].name, "value": parsedvalue, "field_number": 1, - "actionlist": actionlist, + "actionlist": subflowActionList, "field_id": "subflow_field", }) }} @@ -13462,15 +13503,23 @@ const releaseToConnectLabel = "Release to Connect" fullWidth color="primary" placeholder="Some execution data" - defaultValue={ - workflow.triggers[selectedTriggerIndex].parameters[1].value - } - onBlur={(e) => { - setLastSaved(false) + // defaultValue={ + // workflow?.triggers[selectedTriggerIndex]?.parameters[1]?.value + // } + value={subflowExec} + onChange={(e) => { + // handleSubflowExecChange(e) + setSubflowExec(e.target.value) + // workflow.triggers[selectedTriggerIndex].parameters[1].value = e.target.value + // setWorkflow(workflow) - workflow.triggers[selectedTriggerIndex].parameters[1].value = e.target.value - setWorkflow(workflow) }} + // onBlur={(e) => { + // setLastSaved(false) + + // // workflow.triggers[selectedTriggerIndex].parameters[1].value = e.target.value + // // setWorkflow(workflow) + // }} /> {!showDropdown ? null : - {actionlist.map((innerdata) => { + {subflowActionList.map((innerdata) => { const icon = innerdata.type === "action" ? ( @@ -13821,11 +13870,6 @@ const releaseToConnectLabel = "Release to Connect"

- ); - } - - return null; - }; const CommentSidebar = () => { if (Object.getOwnPropertyNames(selectedComment).length > 0) { @@ -20139,7 +20183,7 @@ const releaseToConnectLabel = "Release to Connect" {/* Looks for triggers" */} {/* Only fixed the ones that require scrolling on a small screen */} {/* Most important: Actions. But these are a lot more complex */} - {rightSideBarOpen && (selectedTrigger.trigger_type === "SCHEDULE" || selectedTrigger.trigger_type === "WEBHOOK" || selectedTrigger.trigger_type === "PIPELINE" || selectedTrigger.trigger_type === "USERINPUT") ? + {rightSideBarOpen && (selectedTrigger.trigger_type === "SCHEDULE" || selectedTrigger.trigger_type === "WEBHOOK" || selectedTrigger.trigger_type === "PIPELINE" || selectedTrigger.trigger_type === "USERINPUT" || selectedTrigger.trigger_type === "SUBFLOW") ?
{Object.getOwnPropertyNames(selectedTrigger).length > 0 ? selectedTrigger.trigger_type === "SCHEDULE" ? @@ -20150,17 +20194,19 @@ const releaseToConnectLabel = "Release to Connect" WebhookSidebar : selectedTrigger.trigger_type === "USERINPUT" ? UserinputSidebar + : selectedTrigger.trigger_type === "SUBFLOW" ? + SubflowSidebar : null : null}
: null} - { + {/* { rightSideBarOpen && selectedTrigger.trigger_type === "SUBFLOW"&& Object.getOwnPropertyNames(selectedTrigger).length > 0 ?
: null - } + } */} {/* Date: Wed, 17 Jul 2024 15:14:03 +0530 Subject: [PATCH 7/9] Fixed the paramChange Issue and finally done with the rendering issue of Subflow --- .../src/components/ShuffleCodeEditor1.jsx | 54 +++++++++++-- frontend/src/views/AngularWorkflow.jsx | 75 ++++++------------- 2 files changed, 68 insertions(+), 61 deletions(-) diff --git a/frontend/src/components/ShuffleCodeEditor1.jsx b/frontend/src/components/ShuffleCodeEditor1.jsx index ab4fee06..667fafe3 100644 --- a/frontend/src/components/ShuffleCodeEditor1.jsx +++ b/frontend/src/components/ShuffleCodeEditor1.jsx @@ -109,6 +109,7 @@ const CodeEditor = (props) => { setActiveDialog, fieldname, contentLoading, + selectedTrigger, } = props const [localcodedata, setlocalcodedata] = React.useState(codedata === undefined || codedata === null || codedata.length === 0 ? "" : codedata); @@ -436,7 +437,8 @@ const CodeEditor = (props) => { } const autoFormat = (input) => { - // Check if it's default too + if(selectedAction && selectedAction.parameters && selectedAction.parameters.length > 0){ + // Check if it's default too if (validation !== true) { // Should try to automatically fix this input @@ -475,6 +477,48 @@ const CodeEditor = (props) => { if (input !== localcodedata) { setlocalcodedata(input) } + } + + if(selectedTrigger && selectedTrigger.parameters && selectedTrigger.parameters.length > 0){ + if (validation !== true) { + + // Should try to automatically fix this input + console.log("Running AI input fixer") + if (aiSubmit !== undefined && parameterName !== undefined && selectedTrigger !== undefined) { + + // Should remove params from selectedAction that aren't parameterName + var tmpAction = JSON.parse(JSON.stringify(selectedTrigger)) + var tmpParams = selectedTrigger.parameters.filter((param) => param.name === parameterName) + + var aiMsg = `Make it valid for trigger ${tmpAction.label} with parameter ${parameterName}: ` + if (tmpParams.length > 0) { + aiMsg += tmpParams[0].value + } + + + if (localcodedata.startsWith("//")) { + aiMsg = localcodedata + } + + tmpAction.parameters = tmpParams + console.log("Parameters: ", tmpParams.length) + + aiSubmit(aiMsg, tmpAction) + } + + return + } + + try { + input = JSON.stringify(JSON.parse(input), null, 4) + } catch (e) { + console.log("Failed magic JSON stringification: ", e) + } + + if (input !== localcodedata) { + setlocalcodedata(input) + } + } } const findIndex = (line, loc) => { @@ -1767,7 +1811,6 @@ const CodeEditor = (props) => { // This is to make it so we don't need to handle these fixes on the // backend by itself var fixedcodedata = localcodedata - console.log("Fixedcodedata: ", fixedcodedata) const valid = validateJson(localcodedata, true) if (valid.valid) { fixedcodedata = JSON.stringify(valid.result, null, 2) @@ -1780,11 +1823,6 @@ const CodeEditor = (props) => { setcodedata(fixedcodedata); setExpansionModalOpen(false) } else if (changeActionParameterCodeMirror !== undefined) { - console.log("Entering in Submit onCLick") - console.log("Data passing to chnageActionParameterCodeMirror: ", fixedcodedata) - console.log("Fieldcount: ", fieldCount) - console.log("Actionlist: ", actionlist) - console.log("Event: ", event) //changeActionParameterCodeMirror(event, fieldCount, fixedcodedata) changeActionParameterCodeMirror(event, fieldCount, fixedcodedata, actionlist) setExpansionModalOpen(false) @@ -1808,4 +1846,4 @@ const CodeEditor = (props) => { ) } -export default CodeEditor; +export default CodeEditor; \ No newline at end of file diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index 61d6fbfe..e9bb7b4c 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -1,5 +1,5 @@ /* eslint-disable react/no-multi-comp */ -import React, { useState, useEffect, useLayoutEffect, memo, useMemo, useRef } from "react"; +import React, { useState, useEffect, useLayoutEffect } from "react"; import ReactDOM from "react-dom" import theme from "../theme.jsx"; @@ -922,14 +922,8 @@ const releaseToConnectLabel = "Release to Connect" setSubflowActionlist(newActionList); - },[selectedTrigger, workflowExecutions]); - - - useEffect(() => { - if(selectedTrigger.parameters !== undefined && selectedTrigger.parameters.length > 1){ - setSubflowExec(selectedTrigger?.parameters[1]?.value) - } - },[selectedTrigger,selectedTriggerIndex,subflowActionList]); + },[selectedTrigger, workflowExecutions, workflow.workflow_variables, workflow.execution_variables, workflow.branches,workflow]); + const [executionArgumentModalOpen, setExecutionArgumentModalOpen] = React.useState(false); @@ -4671,7 +4665,6 @@ const releaseToConnectLabel = "Release to Connect" } - console.log("Selected Trigger: ", selectedTrigger) // Nodeselectbatching: // https://stackoverflow.com/questions/16677856/cy-onselect-callback-only-once // onNodeClick @@ -4686,8 +4679,6 @@ const releaseToConnectLabel = "Release to Connect" if ((data.parameters !== undefined) && (data?.parameters?.length > 0)) { getWorkflowApps(data.parameters[0].value) } - console.log("data", data) - // setSubflowExec(data?.parameters[1]?.value) } if (data.buttonType == "ACTIONSUGGESTION") { @@ -12976,9 +12967,14 @@ const releaseToConnectLabel = "Release to Connect" if (selectedTrigger.name === "Shuffle Workflow") { const toComplete = selectedTrigger.parameters[1].value + "$" + values[0].autocomplete - selectedTrigger.parameters[1].value = toComplete - // setSubflowExec(selectedTrigger.parameters[1].value) - setSelectedTrigger(selectedTrigger) + // selectedTrigger.parameters[1].value = toComplete + workflow.triggers[selectedTriggerIndex].parameters[1].value = toComplete + const foundfield = document.getElementById("subflow_field") + if (foundfield !== undefined && foundfield !== null) { + foundfield.value = toComplete + } + // setSelectedTrigger(selectedTrigger) + // setSubflowExec(toComplete) setWorkflow(workflow) } @@ -12987,16 +12983,6 @@ const releaseToConnectLabel = "Release to Connect" setMenuPosition(null); }; - const handleSubflowExecChange = (e) => { - setSubflowExec(e.target.value) - // if(selectedTrigger.length > 0){ - // selectedTrigger.parameters[1].value = e.target.value - // setSelectedTrigger(selectedTrigger) - // setWorkflow(workflow) - // setLastSaved(false) - // } - } - const SubflowSidebar = Object.getOwnPropertyNames(selectedTrigger).length === 0 || workflow.triggers[selectedTriggerIndex] === undefined || selectedTrigger.trigger_type !== "SUBFLOW" ? null :
@@ -13287,6 +13273,7 @@ const releaseToConnectLabel = "Release to Connect" value: data } }) + document.activeElement.blur(); }} > @@ -13302,11 +13289,6 @@ const releaseToConnectLabel = "Release to Connect" backgroundColor: theme.palette.inputColor, borderRadius: theme.palette.borderRadius, }} - sx={{ - '& .MuiInputLabel-root': { - transition: 'none', // Disable the animation for the label - }, - }} {...params} label="Find your workflow" variant="outlined" @@ -13414,11 +13396,6 @@ const releaseToConnectLabel = "Release to Connect" backgroundColor: theme.palette.inputColor, borderRadius: theme.palette.borderRadius, }} - sx={{ - '& .MuiInputLabel-root': { - transition: 'none', // Disable the animation for the label - }, - }} {...params} label="Select a start-node (optional)" variant="outlined" @@ -13481,7 +13458,7 @@ const releaseToConnectLabel = "Release to Connect" }} /> - + { @@ -13503,23 +13480,15 @@ const releaseToConnectLabel = "Release to Connect" fullWidth color="primary" placeholder="Some execution data" - // defaultValue={ - // workflow?.triggers[selectedTriggerIndex]?.parameters[1]?.value - // } - value={subflowExec} - onChange={(e) => { - // handleSubflowExecChange(e) - setSubflowExec(e.target.value) - // workflow.triggers[selectedTriggerIndex].parameters[1].value = e.target.value - // setWorkflow(workflow) + defaultValue={ + workflow?.triggers[selectedTriggerIndex]?.parameters[1]?.value + } + onBlur={(e) => { + workflow.triggers[selectedTriggerIndex].parameters[1].value = e.target.value + setWorkflow(workflow) + setLastSaved(false) }} - // onBlur={(e) => { - // setLastSaved(false) - - // // workflow.triggers[selectedTriggerIndex].parameters[1].value = e.target.value - // // setWorkflow(workflow) - // }} /> {!showDropdown ? null : Date: Wed, 17 Jul 2024 15:46:46 +0530 Subject: [PATCH 8/9] Added expandWindow button and actionList in UserInput and added parent node name change feature in that --- frontend/src/components/ParsedAction.jsx | 2 +- frontend/src/views/AngularWorkflow.jsx | 360 ++++++++++++++++++++++- 2 files changed, 360 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/ParsedAction.jsx b/frontend/src/components/ParsedAction.jsx index 4fec9a67..9d583b31 100755 --- a/frontend/src/components/ParsedAction.jsx +++ b/frontend/src/components/ParsedAction.jsx @@ -1899,7 +1899,7 @@ const ParsedAction = (props) => { for (let [subkey, subkeyval] in Object.entries(params)) { const param = workflow.triggers[key].parameters[subkey]; - if(param.name === "argument"){ + if(param.name === "argument" || param.name === "alertinfo"){ if (!param.value.includes("$")) { continue } diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index e9bb7b4c..631d9c0c 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -12978,6 +12978,19 @@ const releaseToConnectLabel = "Release to Connect" setWorkflow(workflow) } + if(selectedTrigger.name === "User Input"){ + const toComplete = selectedTrigger.parameters[0].value + "$" + values[0].autocomplete + // selectedTrigger.parameters[1].value = toComplete + workflow.triggers[selectedTriggerIndex].parameters[0].value = toComplete + const foundfield = document.getElementById("userinput_info") + if (foundfield !== undefined && foundfield !== null) { + foundfield.value = toComplete + } + // setSelectedTrigger(selectedTrigger) + // setSubflowExec(toComplete) + setWorkflow(workflow) + } + setUpdate(Math.random()); setShowDropdown(false); setMenuPosition(null); @@ -14098,6 +14111,7 @@ const releaseToConnectLabel = "Release to Connect" ) { workflow.triggers[selectedTriggerIndex].parameters = []; workflow.triggers[selectedTriggerIndex].parameters[0] = { + id:"userinput_info", name: "alertinfo", value: "Do you want to continue the workflow? Start parameters: $exec", }; @@ -15003,6 +15017,7 @@ const releaseToConnectLabel = "Release to Connect"
+ + + { + event.preventDefault() + // setFieldCount(count) + setCodeEditorModalOpen(true) + setActiveDialog("codeeditor") + //setcodedata(data.value) + var parsedvalue = workflow?.triggers[selectedTriggerIndex]?.parameters[0]?.value + // if (parsedvalue === undefined || parsedvalue === null) { + // parsedvalue = "" + // } + console.log("Data sending to codeeditor: ",{ + "name": workflow.triggers[selectedTriggerIndex].parameters[0].name, + "value": parsedvalue, + "field_number": 0, + "actionlist": subflowActionList, + "field_id": "userinput_info", + }) + setEditorData({ + "name": workflow.triggers[selectedTriggerIndex].parameters[0].name, + "value": parsedvalue, + "field_number": 0, + "actionlist": subflowActionList, + "field_id": "userinput_info", + }) + }} + /> + + + { + setMenuPosition({ + top: event.pageY + 10, + left: event.pageX + 10, + }); + //setShowDropdownNumber(3) + setShowDropdown(true); + }} + /> + + + + ), }} fullWidth - rows="4" + rows="6" multiline defaultValue={ workflow.triggers !== undefined && workflow.triggers !== null && workflow.triggers[selectedTriggerIndex].parameters !== undefined && workflow.triggers[selectedTriggerIndex].parameters.length > 0 && workflow.triggers[selectedTriggerIndex].parameters[0] !== undefined && workflow.triggers[selectedTriggerIndex].parameters[0].value !== undefined ? workflow.triggers[selectedTriggerIndex].parameters[0].value : "" @@ -15023,6 +15087,300 @@ const releaseToConnectLabel = "Release to Connect" setTriggerTextInformationWrapper(e.target.value); }} /> + {!showDropdown ? null : + { + handleMenuClose(); + }} + open={!!menuPosition} + style={{ + border: `2px solid #f85a3e`, + color: "white", + marginTop: 2, + }} + > + {subflowActionList.map((innerdata) => { + const icon = + innerdata.type === "action" ? ( + + ) : innerdata.type === "workflow_variable" || + innerdata.type === "execution_variable" ? ( + + ) : ( + + ); + + const handleExecArgumentHover = (inside) => { + var exec_text_field = document.getElementById( + "execution_argument_input_field" + ); + if (exec_text_field !== null) { + if (inside) { + exec_text_field.style.border = "2px solid #f85a3e"; + } else { + exec_text_field.style.border = ""; + } + } + + // Also doing arguments + if ( + workflow.triggers !== undefined && + workflow.triggers !== null && + workflow.triggers.length > 0 + ) { + for (let triggerkey in workflow.triggers) { + const item = workflow.triggers[triggerkey]; + + if (cy !== undefined) { + var node = cy.getElementById(item.id); + if (node.length > 0) { + if (inside) { + node.addClass("shuffle-hover-highlight"); + } else { + node.removeClass("shuffle-hover-highlight"); + } + } + } + } + } + } + + const handleActionHover = (inside, actionId) => { + if (cy !== undefined) { + var node = cy.getElementById(actionId); + if (node.length > 0) { + if (inside) { + node.addClass("shuffle-hover-highlight"); + } else { + node.removeClass("shuffle-hover-highlight"); + } + } + } + }; + + const handleMouseover = () => { + if (innerdata.type === "Execution Argument") { + handleExecArgumentHover(true); + } else if (innerdata.type === "action") { + handleActionHover(true, innerdata.id); + } + }; + + const handleMouseOut = () => { + if (innerdata.type === "Execution Argument") { + handleExecArgumentHover(false); + } else if (innerdata.type === "action") { + handleActionHover(false, innerdata.id); + } + }; + + var parsedPaths = []; + console.log("Found example data: ", innerdata.example) + if (typeof innerdata.example === "object") { + parsedPaths = GetParsedPaths(innerdata.example, ""); + } + + const coverColor = "#82ccc3" + + return parsedPaths.length > 0 ? ( + + {/* + + {icon} {innerdata.name} + + } + parentMenuOpen={!!menuPosition} + style={{ + backgroundColor: theme.palette.inputColor, + color: "white", + minWidth: 250, + }} + onClick={() => { + handleItemClick([innerdata]); + }} + > + {parsedPaths.map((pathdata, index) => { + // FIXME: Should be recursive in here + const icon = + pathdata.type === "value" ? ( + + ) : pathdata.type === "list" ? ( + + ) : ( + + ) + + return ( + { }} + onClick={() => { + handleItemClick([innerdata, pathdata]); + }} + > + +
+ {icon} {pathdata.name} +
+
+
+ ); + })} +
+ */} + + + {icon} {innerdata.name} + + } + parentMenuOpen={!!menuPosition} + style={{ + color: "white", + minWidth: 250, + maxWidth: 250, + maxHeight: 50, + overflow: "hidden", + }} + onClick={() => { + console.log("CLICKED: ", innerdata); + console.log(innerdata.example) + handleItemClick([innerdata]); + }} + > + + + { + //console.log("HOVER: ", pathdata); + }} + onClick={() => { + handleItemClick([innerdata]); + }} + > + + {innerdata.name} + + + + {parsedPaths.map((pathdata, index) => { + // FIXME: Should be recursive in here + // + 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 ( + { + //console.log("HOVER: ", pathdata); + }} + onClick={() => { + handleItemClick([innerdata, pathdata]); + }} + > + +
+ {Array(indentation_count).fill().map((subdata, subindex) => { + return ( + baseIndent + ) + })} + {icon} {newname} + {pathdata.type === "list" ? { + + }} /> : null} +
+
+
+ ); + })} + + + + ) : ( + handleMouseover()} + onMouseOut={() => { + handleMouseOut(); + }} + onClick={() => { + handleItemClick([innerdata]); + }} + > + +
+ {icon} {innerdata.name} +
+
+
+ ); + })} +
+ }
Date: Thu, 18 Jul 2024 14:56:24 +0530 Subject: [PATCH 9/9] Fixed that blank screen issue --- frontend/src/views/AngularWorkflow.jsx | 1865 ++++++++++++------------ 1 file changed, 939 insertions(+), 926 deletions(-) diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index 631d9c0c..3347d1cc 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -12796,61 +12796,6 @@ const releaseToConnectLabel = "Release to Connect" ); }; - if (Object.getOwnPropertyNames(selectedTrigger).length > 0) { - if (workflow.triggers[selectedTriggerIndex] === undefined) { - return null; - } - - if ( - workflow.triggers[selectedTriggerIndex].parameters === undefined || - workflow.triggers[selectedTriggerIndex].parameters === null || - workflow.triggers[selectedTriggerIndex].parameters.length === 0 - ) { - workflow.triggers[selectedTriggerIndex].parameters = []; - workflow.triggers[selectedTriggerIndex].parameters[0] = { - name: "workflow", - value: "", - }; - workflow.triggers[selectedTriggerIndex].parameters[1] = { - name: "argument", - value: "", - id:"subflow_field" - }; - workflow.triggers[selectedTriggerIndex].parameters[2] = { - name: "user_apikey", - value: "", - }; - workflow.triggers[selectedTriggerIndex].parameters[3] = { - name: "startnode", - value: "", - }; - workflow.triggers[selectedTriggerIndex].parameters[4] = { - name: "check_result", - value: "false", - }; - workflow.triggers[selectedTriggerIndex].parameters[5] = { - name: "auth_override", - value: "", - }; - - /* - // API-key has been replaced by auth key for the execution. - // Parents can now automatically execute children without auth from a user, as long as the subflow in question is owned by the same org and the subflow is actually referencing it during checkin. - console.log("SETTINGS: ", userSettings); - if ( - userSettings !== undefined && - userSettings !== null && - userSettings.apikey !== null && - userSettings.apikey !== undefined && - userSettings.apikey.length > 0 - ) { - workflow.triggers[selectedTriggerIndex].parameters[2] = { - name: "user_apikey", - value: userSettings.apikey, - }; - } - */ - } var handleSubflowStartnodeSelection = (e) => { setSubworkflowStartnode(e.target.value); @@ -12925,7 +12870,6 @@ const releaseToConnectLabel = "Release to Connect" setWorkflow(workflow); }; - } var subflowtypes = [ @@ -12996,862 +12940,7 @@ const releaseToConnectLabel = "Release to Connect" setMenuPosition(null); }; - const SubflowSidebar = Object.getOwnPropertyNames(selectedTrigger).length === 0 || workflow.triggers[selectedTriggerIndex] === undefined || selectedTrigger.trigger_type !== "SUBFLOW" ? null : -
- -

- {selectedTrigger.app_name} -

- - - -
- - What are subflows? - - -
-
- Name - -
-
-
- - - 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) - }} - /> - - -
-
-
- { - const newvalue = workflow.triggers[selectedTriggerIndex].parameters[4] === undefined || workflow.triggers[selectedTriggerIndex].parameters[4].value === "false"? "true" : "false"; - workflow.triggers[selectedTriggerIndex].parameters[4] = { - name: "check_result", - value: newvalue, - }; - - setWorkflow(workflow); - setUpdate(Math.random()); - }} - color="primary" - value="Wait for results" - /> - } - style={{ marginTop: 10 }} - label={
Wait for results
} - /> -
-
-
-
-
- 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 : ( - - option.id === value.id} - getOptionLabel={(option) => { - if ( - option === undefined || - option === null || - option.name === undefined || - option.name === null - ) { - return "No Workflow Selected"; - } - - const newname = ( - option.name.charAt(0).toUpperCase() + option.name.substring(1) - ).replaceAll("_", " "); - return newname; - }} - options={workflows} - fullWidth - style={{ - backgroundColor: theme.palette.inputColor, - height: 50, - borderRadius: theme.palette.borderRadius, - }} - onChange={(event, newValue) => { - setLastSaved(false) - console.log("Found value: ", newValue) - - var parsedinput = { target: { value: newValue } } - - // For variables - if (typeof newValue === 'string' && newValue.startsWith("$")) { - parsedinput = { - target: { - value: { - "name": newValue, - "id": newValue, - "actions": [], - "triggers": [], - } - } - } - } - - handleWorkflowSelectionUpdate(parsedinput) - }} - renderOption={(props, data, state) => { - if (data.id === workflow.id) { - data = workflow; - } - - //key={index} - return ( - - {data.image !== undefined && data.image !== null && data.image.length > 0 ? - {data.name} - : null} - - Choose Subflow '{data.name}' - - - }> - { - getWorkflowApps(data.id); - handleWorkflowSelectionUpdate({ - target: { - value: data - } - }) - document.activeElement.blur(); - }} - > - - {data.name} - - - ) - }} - renderInput={(params) => { - return ( - - ); - }} - /> - )} - - {subworkflow === undefined || - subworkflow === null || - subworkflow.id === undefined || - subworkflow.actions === null || - subworkflow.actions === undefined || - subworkflow.actions.length === 0 ? null : ( - -
-
- Select the Startnode -
-
- option.id === value.id} - getOptionLabel={(option) => { - if (option === undefined || option === null || option.label === undefined || option.label === null) { - if (option.length === 36) { - - } - - return "TMP"; - } - - const newname = ( - option.label.charAt(0).toUpperCase() + option.label.substring(1) - ).replaceAll("_", " "); - return newname; - }} - options={subworkflow.actions} - fullWidth - style={{ - backgroundColor: theme.palette.inputColor, - height: 50, - borderRadius: theme.palette.borderRadius, - }} - onChange={(event, newValue) => { - setLastSaved(false) - handleSubflowStartnodeSelection({ target: { value: newValue } }) - }} - renderOption={(props, action, state) => { - const isParent = getParents(selectedTrigger).find( - (parent) => parent.id === action.id - ) - - return ( - { - if (subworkflow.id === workflow.id) { - handleActionHover(true, action.id) - } - }} - onMouseOut={() => { - if (subworkflow.id === workflow.id) { - handleActionHover(false, action.id) - } - }} - disabled={isCloud && isParent} - onClick={() => { - handleSubflowStartnodeSelection({ - target: { - value: action - } - }) - document.activeElement.blur(); - }} - style={{ - backgroundColor: theme.palette.inputColor, - color: isParent ? "red" : "white", - }} - value={action} - > - {action.label} - - ); - }} - renderInput={(params) => { - return ( - - ); - }} - /> -
- )} -
-
- Execution Argument -
-
- - - - { - event.preventDefault() - // setFieldCount(count) - setCodeEditorModalOpen(true) - setActiveDialog("codeeditor") - //setcodedata(data.value) - var parsedvalue = workflow?.triggers[selectedTriggerIndex]?.parameters[1]?.value - // if (parsedvalue === undefined || parsedvalue === null) { - // parsedvalue = "" - // } - console.log("Data sending to codeeditor: ",{ - "name": workflow.triggers[selectedTriggerIndex].parameters[1].name, - "value": parsedvalue, - "field_number": 1, - "actionlist": subflowActionList, - "field_id": "subflow_field", - }) - setEditorData({ - "name": workflow.triggers[selectedTriggerIndex].parameters[1].name, - "value": parsedvalue, - "field_number": 1, - "actionlist": subflowActionList, - "field_id": "subflow_field", - }) - }} - /> - - - { - setMenuPosition({ - top: event.pageY + 10, - left: event.pageX + 10, - }); - //setShowDropdownNumber(3) - setShowDropdown(true); - }} - /> - - - - ), - }} - rows="6" - multiline - fullWidth - color="primary" - placeholder="Some execution data" - defaultValue={ - workflow?.triggers[selectedTriggerIndex]?.parameters[1]?.value - } - onBlur={(e) => { - workflow.triggers[selectedTriggerIndex].parameters[1].value = e.target.value - setWorkflow(workflow) - setLastSaved(false) - - }} - /> - {!showDropdown ? null : - { - handleMenuClose(); - }} - open={!!menuPosition} - style={{ - border: `2px solid #f85a3e`, - color: "white", - marginTop: 2, - }} - > - {subflowActionList.map((innerdata) => { - const icon = - innerdata.type === "action" ? ( - - ) : innerdata.type === "workflow_variable" || - innerdata.type === "execution_variable" ? ( - - ) : ( - - ); - - const handleExecArgumentHover = (inside) => { - var exec_text_field = document.getElementById( - "execution_argument_input_field" - ); - if (exec_text_field !== null) { - if (inside) { - exec_text_field.style.border = "2px solid #f85a3e"; - } else { - exec_text_field.style.border = ""; - } - } - - // Also doing arguments - if ( - workflow.triggers !== undefined && - workflow.triggers !== null && - workflow.triggers.length > 0 - ) { - for (let triggerkey in workflow.triggers) { - const item = workflow.triggers[triggerkey]; - - if (cy !== undefined) { - var node = cy.getElementById(item.id); - if (node.length > 0) { - if (inside) { - node.addClass("shuffle-hover-highlight"); - } else { - node.removeClass("shuffle-hover-highlight"); - } - } - } - } - } - } - - const handleActionHover = (inside, actionId) => { - if (cy !== undefined) { - var node = cy.getElementById(actionId); - if (node.length > 0) { - if (inside) { - node.addClass("shuffle-hover-highlight"); - } else { - node.removeClass("shuffle-hover-highlight"); - } - } - } - }; - - const handleMouseover = () => { - if (innerdata.type === "Execution Argument") { - handleExecArgumentHover(true); - } else if (innerdata.type === "action") { - handleActionHover(true, innerdata.id); - } - }; - - const handleMouseOut = () => { - if (innerdata.type === "Execution Argument") { - handleExecArgumentHover(false); - } else if (innerdata.type === "action") { - handleActionHover(false, innerdata.id); - } - }; - - var parsedPaths = []; - console.log("Found example data: ", innerdata.example) - if (typeof innerdata.example === "object") { - parsedPaths = GetParsedPaths(innerdata.example, ""); - } - - const coverColor = "#82ccc3" - - return parsedPaths.length > 0 ? ( - - {/* - - {icon} {innerdata.name} -
- } - parentMenuOpen={!!menuPosition} - style={{ - backgroundColor: theme.palette.inputColor, - color: "white", - minWidth: 250, - }} - onClick={() => { - handleItemClick([innerdata]); - }} - > - {parsedPaths.map((pathdata, index) => { - // FIXME: Should be recursive in here - const icon = - pathdata.type === "value" ? ( - - ) : pathdata.type === "list" ? ( - - ) : ( - - ) - - return ( - { }} - onClick={() => { - handleItemClick([innerdata, pathdata]); - }} - > - -
- {icon} {pathdata.name} -
-
-
- ); - })} - - */} - - - {icon} {innerdata.name} -
- } - parentMenuOpen={!!menuPosition} - style={{ - color: "white", - minWidth: 250, - maxWidth: 250, - maxHeight: 50, - overflow: "hidden", - }} - onClick={() => { - console.log("CLICKED: ", innerdata); - console.log(innerdata.example) - handleItemClick([innerdata]); - }} - > - - - { - //console.log("HOVER: ", pathdata); - }} - onClick={() => { - handleItemClick([innerdata]); - }} - > - - {innerdata.name} - - - - {parsedPaths.map((pathdata, index) => { - // FIXME: Should be recursive in here - // - 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 ( - { - //console.log("HOVER: ", pathdata); - }} - onClick={() => { - handleItemClick([innerdata, pathdata]); - }} - > - -
- {Array(indentation_count).fill().map((subdata, subindex) => { - return ( - baseIndent - ) - })} - {icon} {newname} - {pathdata.type === "list" ? { - - }} /> : null} -
-
-
- ); - })} - - - - ) : ( - handleMouseover()} - onMouseOut={() => { - handleMouseOut(); - }} - onClick={() => { - handleItemClick([innerdata]); - }} - > - -
- {icon} {innerdata.name} -
-
-
- ); - })} - - } - {/* -
-
- API-key -
-
- { - workflow.triggers[selectedTriggerIndex].parameters[2].value = - e.target.value; - setWorkflow(workflow); - }} - /> - */} -
-
- -
-
-
-
-
- Authentication Override -
-
- -
-
- -
-
-
-
-
-
+ const CommentSidebar = () => { if (Object.getOwnPropertyNames(selectedComment).length > 0) { @@ -14038,20 +13127,32 @@ const releaseToConnectLabel = "Release to Connect" // Special SCHEDULE handler var trigger_header_auth = "" - if (Object.getOwnPropertyNames(selectedTrigger).length > 0 && workflow.triggers !== null && workflow.triggers !== undefined && workflow.triggers.length >= selectedTriggerIndex && workflow.triggers[selectedTriggerIndex] !== undefined ) { - if (selectedTrigger.trigger_type === "SCHEDULE" && workflow.triggers[selectedTriggerIndex].parameters === undefined || workflow.triggers[selectedTriggerIndex].parameters === null) { - console.log("Autofixing schedule") - workflow.triggers[selectedTriggerIndex].parameters = []; - workflow.triggers[selectedTriggerIndex].parameters[0] = { - name: "cron", - value: isCloud ? "*/25 * * * *" : "60", - }; - workflow.triggers[selectedTriggerIndex].parameters[1] = { - name: "execution_argument", - value: '{"example": {"json": "is cool"}}', - }; - setWorkflow(workflow); + if (Object.getOwnPropertyNames(selectedTrigger).length > 0 && workflow.triggers !== null && workflow.triggers !== undefined && workflow.triggers.length >= selectedTriggerIndex && workflow.triggers[selectedTriggerIndex] !== undefined ) { + + if (selectedTrigger.trigger_type === "SCHEDULE") { + if (workflow.triggers[selectedTriggerIndex] === undefined) { + return null; + } + + if ( + workflow.triggers[selectedTriggerIndex].parameters === undefined || + workflow.triggers[selectedTriggerIndex].parameters === null || + workflow.triggers[selectedTriggerIndex].parameters.length === 0 + ) { + console.log("Autofixing schedule") + + workflow.triggers[selectedTriggerIndex].parameters = []; + workflow.triggers[selectedTriggerIndex].parameters[0] = { + name: "cron", + value: isCloud ? "*/25 * * * *" : "60", + }; + workflow.triggers[selectedTriggerIndex].parameters[1] = { + name: "execution_argument", + value: '{"example": {"json": "is cool"}}', + }; + setWorkflow(workflow); + } } else if (selectedTrigger.trigger_type === "WEBHOOK") { if (workflow.triggers[selectedTriggerIndex] === undefined) { return null; @@ -14143,9 +13244,63 @@ const releaseToConnectLabel = "Release to Connect" setWorkflow(workflow); } + }else if(selectedTrigger.trigger_type === "SUBFLOW"){ + + if ( + workflow.triggers[selectedTriggerIndex].parameters === undefined || + workflow.triggers[selectedTriggerIndex].parameters === null || + workflow.triggers[selectedTriggerIndex].parameters.length === 0 + ) { + workflow.triggers[selectedTriggerIndex].parameters = []; + workflow.triggers[selectedTriggerIndex].parameters[0] = { + name: "workflow", + value: "", + }; + workflow.triggers[selectedTriggerIndex].parameters[1] = { + name: "argument", + value: "", + id:"subflow_field" + }; + workflow.triggers[selectedTriggerIndex].parameters[2] = { + name: "user_apikey", + value: "", + }; + workflow.triggers[selectedTriggerIndex].parameters[3] = { + name: "startnode", + value: "", + }; + workflow.triggers[selectedTriggerIndex].parameters[4] = { + name: "check_result", + value: "false", + }; + workflow.triggers[selectedTriggerIndex].parameters[5] = { + name: "auth_override", + value: "", + }; + setWorkflow(workflow) + /* + // API-key has been replaced by auth key for the execution. + // Parents can now automatically execute children without auth from a user, as long as the subflow in question is owned by the same org and the subflow is actually referencing it during checkin. + console.log("SETTINGS: ", userSettings); + if ( + userSettings !== undefined && + userSettings !== null && + userSettings.apikey !== null && + userSettings.apikey !== undefined && + userSettings.apikey.length > 0 + ) { + workflow.triggers[selectedTriggerIndex].parameters[2] = { + name: "user_apikey", + value: userSettings.apikey, + }; + } + */ + } } } + console.log(selectedTrigger) + const WebhookSidebar = Object.getOwnPropertyNames(selectedTrigger).length === 0 || workflow.triggers[selectedTriggerIndex] === undefined || selectedTrigger.trigger_type !== "WEBHOOK" ? null :

@@ -15689,7 +14844,8 @@ const releaseToConnectLabel = "Release to Connect" }

- const PipelineSidebar = Object.getOwnPropertyNames(selectedTrigger).length === 0 || workflow.triggers[selectedTriggerIndex] === undefined && selectedTrigger.trigger_type !== "SCHEDULE" ? null : + + const PipelineSidebar = Object.getOwnPropertyNames(selectedTrigger).length === 0 || workflow.triggers[selectedTriggerIndex] === undefined && selectedTrigger.trigger_type !== "PIPELINE" ? null :

{selectedTrigger.app_name}: {selectedTrigger.status} @@ -16194,6 +15350,863 @@ const releaseToConnectLabel = "Release to Connect"

+ const SubflowSidebar = Object.getOwnPropertyNames(selectedTrigger).length === 0 || workflow.triggers[selectedTriggerIndex] === undefined || selectedTrigger.trigger_type !== "SUBFLOW" ? null : +
+ +

+ {selectedTrigger.app_name} +

+ + + +
+ + What are subflows? + + +
+
+ Name + +
+
+
+ + + 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) + }} + /> + + +
+
+
+ { + const newvalue = workflow.triggers[selectedTriggerIndex].parameters[4] === undefined || workflow.triggers[selectedTriggerIndex].parameters[4].value === "false"? "true" : "false"; + workflow.triggers[selectedTriggerIndex].parameters[4] = { + name: "check_result", + value: newvalue, + }; + + setWorkflow(workflow); + setUpdate(Math.random()); + }} + color="primary" + value="Wait for results" + /> + } + style={{ marginTop: 10 }} + label={
Wait for results
} + /> +
+
+
+
+
+ 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 : ( + + option.id === value.id} + getOptionLabel={(option) => { + if ( + option === undefined || + option === null || + option.name === undefined || + option.name === null + ) { + return "No Workflow Selected"; + } + + const newname = ( + option.name.charAt(0).toUpperCase() + option.name.substring(1) + ).replaceAll("_", " "); + return newname; + }} + options={workflows} + fullWidth + style={{ + backgroundColor: theme.palette.inputColor, + height: 50, + borderRadius: theme.palette.borderRadius, + }} + onChange={(event, newValue) => { + setLastSaved(false) + console.log("Found value: ", newValue) + + var parsedinput = { target: { value: newValue } } + + // For variables + if (typeof newValue === 'string' && newValue.startsWith("$")) { + parsedinput = { + target: { + value: { + "name": newValue, + "id": newValue, + "actions": [], + "triggers": [], + } + } + } + } + + handleWorkflowSelectionUpdate(parsedinput) + }} + renderOption={(props, data, state) => { + if (data.id === workflow.id) { + data = workflow; + } + + //key={index} + return ( + + {data.image !== undefined && data.image !== null && data.image.length > 0 ? + {data.name} + : null} + + Choose Subflow '{data.name}' + + + }> + { + getWorkflowApps(data.id); + handleWorkflowSelectionUpdate({ + target: { + value: data + } + }) + document.activeElement.blur(); + }} + > + + {data.name} + + + ) + }} + renderInput={(params) => { + return ( + + ); + }} + /> + )} + + {subworkflow === undefined || + subworkflow === null || + subworkflow.id === undefined || + subworkflow.actions === null || + subworkflow.actions === undefined || + subworkflow.actions.length === 0 ? null : ( + +
+
+ Select the Startnode +
+
+ option.id === value.id} + getOptionLabel={(option) => { + if (option === undefined || option === null || option.label === undefined || option.label === null) { + if (option.length === 36) { + + } + + return "TMP"; + } + + const newname = ( + option.label.charAt(0).toUpperCase() + option.label.substring(1) + ).replaceAll("_", " "); + return newname; + }} + options={subworkflow.actions} + fullWidth + style={{ + backgroundColor: theme.palette.inputColor, + height: 50, + borderRadius: theme.palette.borderRadius, + }} + onChange={(event, newValue) => { + setLastSaved(false) + handleSubflowStartnodeSelection({ target: { value: newValue } }) + }} + renderOption={(props, action, state) => { + const isParent = getParents(selectedTrigger).find( + (parent) => parent.id === action.id + ) + + return ( + { + if (subworkflow.id === workflow.id) { + handleActionHover(true, action.id) + } + }} + onMouseOut={() => { + if (subworkflow.id === workflow.id) { + handleActionHover(false, action.id) + } + }} + disabled={isCloud && isParent} + onClick={() => { + handleSubflowStartnodeSelection({ + target: { + value: action + } + }) + document.activeElement.blur(); + }} + style={{ + backgroundColor: theme.palette.inputColor, + color: isParent ? "red" : "white", + }} + value={action} + > + {action.label} + + ); + }} + renderInput={(params) => { + return ( + + ); + }} + /> +
+ )} +
+
+ Execution Argument +
+
+ + + + { + event.preventDefault() + // setFieldCount(count) + setCodeEditorModalOpen(true) + setActiveDialog("codeeditor") + //setcodedata(data.value) + var parsedvalue = workflow?.triggers[selectedTriggerIndex]?.parameters[1]?.value + // if (parsedvalue === undefined || parsedvalue === null) { + // parsedvalue = "" + // } + console.log("Data sending to codeeditor: ",{ + "name": workflow.triggers[selectedTriggerIndex].parameters[1].name, + "value": parsedvalue, + "field_number": 1, + "actionlist": subflowActionList, + "field_id": "subflow_field", + }) + setEditorData({ + "name": workflow.triggers[selectedTriggerIndex].parameters[1].name, + "value": parsedvalue, + "field_number": 1, + "actionlist": subflowActionList, + "field_id": "subflow_field", + }) + }} + /> + + + { + setMenuPosition({ + top: event.pageY + 10, + left: event.pageX + 10, + }); + //setShowDropdownNumber(3) + setShowDropdown(true); + }} + /> + + + + ), + }} + rows="6" + multiline + fullWidth + color="primary" + placeholder="Some execution data" + defaultValue={ + workflow?.triggers[selectedTriggerIndex]?.parameters[1]?.value + } + onBlur={(e) => { + workflow.triggers[selectedTriggerIndex].parameters[1].value = e.target.value + setWorkflow(workflow) + setLastSaved(false) + + }} + /> + {!showDropdown ? null : + { + handleMenuClose(); + }} + open={!!menuPosition} + style={{ + border: `2px solid #f85a3e`, + color: "white", + marginTop: 2, + }} + > + {subflowActionList.map((innerdata) => { + const icon = + innerdata.type === "action" ? ( + + ) : innerdata.type === "workflow_variable" || + innerdata.type === "execution_variable" ? ( + + ) : ( + + ); + + const handleExecArgumentHover = (inside) => { + var exec_text_field = document.getElementById( + "execution_argument_input_field" + ); + if (exec_text_field !== null) { + if (inside) { + exec_text_field.style.border = "2px solid #f85a3e"; + } else { + exec_text_field.style.border = ""; + } + } + + // Also doing arguments + if ( + workflow.triggers !== undefined && + workflow.triggers !== null && + workflow.triggers.length > 0 + ) { + for (let triggerkey in workflow.triggers) { + const item = workflow.triggers[triggerkey]; + + if (cy !== undefined) { + var node = cy.getElementById(item.id); + if (node.length > 0) { + if (inside) { + node.addClass("shuffle-hover-highlight"); + } else { + node.removeClass("shuffle-hover-highlight"); + } + } + } + } + } + } + + const handleActionHover = (inside, actionId) => { + if (cy !== undefined) { + var node = cy.getElementById(actionId); + if (node.length > 0) { + if (inside) { + node.addClass("shuffle-hover-highlight"); + } else { + node.removeClass("shuffle-hover-highlight"); + } + } + } + }; + + const handleMouseover = () => { + if (innerdata.type === "Execution Argument") { + handleExecArgumentHover(true); + } else if (innerdata.type === "action") { + handleActionHover(true, innerdata.id); + } + }; + + const handleMouseOut = () => { + if (innerdata.type === "Execution Argument") { + handleExecArgumentHover(false); + } else if (innerdata.type === "action") { + handleActionHover(false, innerdata.id); + } + }; + + var parsedPaths = []; + console.log("Found example data: ", innerdata.example) + if (typeof innerdata.example === "object") { + parsedPaths = GetParsedPaths(innerdata.example, ""); + } + + const coverColor = "#82ccc3" + + return parsedPaths.length > 0 ? ( + + {/* + + {icon} {innerdata.name} +
+ } + parentMenuOpen={!!menuPosition} + style={{ + backgroundColor: theme.palette.inputColor, + color: "white", + minWidth: 250, + }} + onClick={() => { + handleItemClick([innerdata]); + }} + > + {parsedPaths.map((pathdata, index) => { + // FIXME: Should be recursive in here + const icon = + pathdata.type === "value" ? ( + + ) : pathdata.type === "list" ? ( + + ) : ( + + ) + + return ( + { }} + onClick={() => { + handleItemClick([innerdata, pathdata]); + }} + > + +
+ {icon} {pathdata.name} +
+
+
+ ); + })} + + */} + + + {icon} {innerdata.name} +
+ } + parentMenuOpen={!!menuPosition} + style={{ + color: "white", + minWidth: 250, + maxWidth: 250, + maxHeight: 50, + overflow: "hidden", + }} + onClick={() => { + console.log("CLICKED: ", innerdata); + console.log(innerdata.example) + handleItemClick([innerdata]); + }} + > + + + { + //console.log("HOVER: ", pathdata); + }} + onClick={() => { + handleItemClick([innerdata]); + }} + > + + {innerdata.name} + + + + {parsedPaths.map((pathdata, index) => { + // FIXME: Should be recursive in here + // + 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 ( + { + //console.log("HOVER: ", pathdata); + }} + onClick={() => { + handleItemClick([innerdata, pathdata]); + }} + > + +
+ {Array(indentation_count).fill().map((subdata, subindex) => { + return ( + baseIndent + ) + })} + {icon} {newname} + {pathdata.type === "list" ? { + + }} /> : null} +
+
+
+ ); + })} + + + + ) : ( + handleMouseover()} + onMouseOut={() => { + handleMouseOut(); + }} + onClick={() => { + handleItemClick([innerdata]); + }} + > + +
+ {icon} {innerdata.name} +
+
+
+ ); + })} + + } + {/* +
+
+ API-key +
+
+ { + workflow.triggers[selectedTriggerIndex].parameters[2].value = + e.target.value; + setWorkflow(workflow); + }} + /> + */} +
+
+ +
+
+
+
+
+ Authentication Override +
+
+ +
+
+ +
+
+
+
+
+ + const cytoscapeViewWidths = isMobile ? 50 : 950; const bottomBarStyle = { position: "fixed",