From f8bbfb0fdb0f38294c89fc9867bd664ddbd9c19d Mon Sep 17 00:00:00 2001 From: Frikky Date: Wed, 31 Jan 2024 10:54:56 +0100 Subject: [PATCH] Fixed execution mapping problems in workflows for 1.3.2 --- backend/app_sdk/app_base.py | 18 +- frontend/src/components/ParsedAction.jsx | 219 ++++++++++---------- frontend/src/components/RuntimeDebugger.jsx | 84 +++++++- frontend/src/views/AngularWorkflow.jsx | 47 ++--- 4 files changed, 217 insertions(+), 151 deletions(-) diff --git a/backend/app_sdk/app_base.py b/backend/app_sdk/app_base.py index 3ded5fba..a29853d8 100755 --- a/backend/app_sdk/app_base.py +++ b/backend/app_sdk/app_base.py @@ -1178,7 +1178,7 @@ class AppBase: #ret = ret[0] self.logger.info("[DEBUG] DONT make list of 1 into 0!!") - self.logger.info("Return from execution: %s" % ret) + #self.logger.info("Return from execution: %s" % ret) if ret == None: results.append("") json_object = False @@ -1202,11 +1202,12 @@ class AppBase: except: results.append(ret) - if len(results) == 1: - #results = results[0] - self.logger.info("DONT MAKE LIST FROM 1 TO 0!!") + #if len(results) == 1: + # #results = results[0] + # #self.logger.info("DONT MAKE LIST FROM 1 TO 0!!") + # pass - self.logger.info("\nLOOP: %s\nRESULTS: %s" % (loop_wrapper, results)) + #self.logger.info("\nLOOP: %s\nRESULTS: %s" % (loop_wrapper, results)) return results # Downloads all files from a namespace @@ -3305,7 +3306,7 @@ class AppBase: pass - self.logger.info(f"""HANDLING BODY: {action["parameters"][counter]["value"]}""") + #self.logger.info(f"""HANDLING BODY: {action["parameters"][counter]["value"]}""") action["parameters"][counter]["value"] = recurse_cleanup_script(action["parameters"][counter]["value"]) #self.logger.info(action["parameters"]) @@ -3345,9 +3346,8 @@ class AppBase: "exception": f"Value Error: {check}", })) - if parameter["name"] == "body": - #self.logger.info(f"[INFO] Should debug field with liquid and other checks as it's BODY: {value}") - pass + #if parameter["name"] == "body": + # #self.logger.info(f"[INFO] Should debug field with liquid and other checks as it's BODY: {value}") # Custom format for ${name[0,1,2,...]}$ #submatch = "([${]{2}([0-9a-zA-Z_-]+)(\[.*\])[}$]{2})" diff --git a/frontend/src/components/ParsedAction.jsx b/frontend/src/components/ParsedAction.jsx index aef01467..68366fe4 100755 --- a/frontend/src/components/ParsedAction.jsx +++ b/frontend/src/components/ParsedAction.jsx @@ -175,8 +175,6 @@ const ParsedAction = (props) => { } = props; const classes = useStyles(); - //const alert = useAlert() - const [hideBody, setHideBody] = React.useState(true); const [activateHidingBodyButton, setActivateHidingBodyButton] = React.useState(false); @@ -185,31 +183,34 @@ const ParsedAction = (props) => { const [autoCompleting, setAutocompleting] = React.useState(false); + useEffect(() => { + if (setLastSaved !== undefined) { + setLastSaved(false) + } + }, [expansionModalOpen]) useEffect(() => { - if (setLastSaved !== undefined) { - setLastSaved(false) - } - }, [expansionModalOpen]) + if (selectedAction.parameters === null || selectedAction.parameters === undefined) { + return + } - useEffect(() => { - if (selectedAction.parameters !== null && selectedAction.parameters !== undefined) { - const paramcheck = selectedAction.parameters.find(param => param.name === "body") - //console.log("LOADED! Change hideBody based on input? Action: ", selectedAction, paramcheck) - if (paramcheck !== undefined && paramcheck !== null) { - if (paramcheck.id === "TOGGLED"){ - setHideBody(false) - setActivateHidingBodyButton(false) - } else { - setHideBody(true) + const paramcheck = selectedAction.parameters.find(param => param.name === "body") + if (paramcheck === undefined || paramcheck === null) { + return + } - if (paramcheck.id === "UNTOGGLED") { - setActivateHidingBodyButton(false) - } - } - } + // This was just opposite.. + if (paramcheck.id === "TOGGLED"){ + setHideBody(true) + } else { + setHideBody(false) + + if (paramcheck.id === "UNTOGGLED") { + setActivateHidingBodyButton(false) } - }, []) + } + + }, []) const keywords = [ "len(", @@ -1190,14 +1191,14 @@ const ParsedAction = (props) => { } return ( - ); }} @@ -1360,20 +1361,6 @@ const ParsedAction = (props) => { var disabled = false; var rows = "3"; var openApiHelperText = "This is an OpenAPI specific field"; - /* - if ( - selectedApp.generated && - data.name === "url" && - data.required && - data.configuration - ) { - //&& - //hideExtraTypes - - //console.log("GENERATED WITH DATA: ", data); - return null; - } - */ if (selectedApp.generated && data.name === "headers") { //console.log("HEADER: ", data) @@ -1386,8 +1373,9 @@ const ParsedAction = (props) => { const hideBodyButtonValue = (
{ > { color: theme.palette.primary.secondary, }} onChange={(event) => { - var tag = "TOGGLED" - if (hideBody) { - tag = "UNTOGGLED" - } + var tag = "TOGGLED" + if (hideBody) { + tag = "UNTOGGLED" + } - setHideBody(!hideBody); - + setHideBody(!hideBody) for (let paramkey in Object.entries(selectedActionParameters)) { var currentItem = selectedActionParameters[paramkey]; if (currentItem.name === "ssl_verify") { @@ -1423,21 +1410,33 @@ const ParsedAction = (props) => { } if (currentItem.name === "body") { - // FIXME: Workaround for toggling, as actions don't have IDs. - // May screw up something in the future. currentItem.id = tag } if (currentItem.description === openApiFieldDesc) { - currentItem.field_active = !hideBody; - //console.log("Changing", currentItem); + currentItem.field_active = !hideBody } } + + + // Scroll to hide_body_button + setTimeout(() => { + var element = document.getElementById("hide_body_button") + if (element !== undefined && element !== null) { + // Keep the button a little below the top + element.scrollIntoView({ + behavior: "smooth", + block: "center", + }) + } + }, 100) + + }} name="requires_unique" /> } - label={"Automatically fix body"} + label={hideBody ? "Show Body" : "Hide Body"} />
@@ -1447,6 +1446,8 @@ const ParsedAction = (props) => { const regex = /\${(\w+)}/g; const found = placeholder.match(regex); + // setActivateHidingBodyButton(false) + // hideBodyButton = hideBodyButtonValue; if (found === null || !hideBody) { if (found === null) { @@ -1455,13 +1456,13 @@ const ParsedAction = (props) => { //console.log("In found: ", found, hideBody) } } else { - //console.log("SHOW BUTTON"); rows = "1"; disabled = true; openApiHelperText = "OpenAPI spec: fill the following fields."; - //console.log("SHOULD ADD TO selectedActionParameters!: ", found, selectedActionParameters) + var changed = false; + var tempArray = [] for (let specKey in found) { const tmpitem = found[specKey]; var skip = false; @@ -1490,7 +1491,7 @@ const ParsedAction = (props) => { } } - selectedActionParameters.push({ + tempArray.push({ action_field: "", configuration: false, description: openApiFieldDesc, @@ -1506,11 +1507,39 @@ const ParsedAction = (props) => { value: "", variant: "STATIC_VALUE", field_active: true, + + autocompleted: true, }); } + + console.log("TEMP ARRAY: ", tempArray) + var required = selectedActionParameters.filter(item => item.required === true) + var notRequired = selectedActionParameters.filter(item => item.required === false) + + if (tempArray.length > 0) { + // Sort tempArray based on tempArray.required + tempArray.sort((a, b) => (a.required < b.required) ? 1 : -1) + // Add all items to the selectedActionParameters array + for (let innerkey in tempArray) { + tempArray[innerkey].id = "ADDED" + + if (tempArray[innerkey].required === true) { + required.push(tempArray[innerkey]) + } else { + notRequired.push(tempArray[innerkey]) + } + } + } + //selectedActionParameters if (changed) { - setSelectedActionParameters(selectedActionParameters); + // Sort selectedActionParameters based on selectedActionParameters.required + //selectedActionParameters.sort((a, b) => (a.required < b.required) ? 1 : -1) + // Find the "headers" and "queries" field names and put them on the first indexes anyway + var newArray = required.concat(notRequired) + + + setSelectedActionParameters(newArray) } return hideBodyButton; @@ -1523,9 +1552,6 @@ const ParsedAction = (props) => { const clickedFieldId = "rightside_field_" + count; - // 0) { baseHelperText = calculateHelpertext(data.value) @@ -1619,33 +1645,15 @@ const ParsedAction = (props) => { helperText={returnHelperText(data.name, data.value)} onClick={() => { console.log("Clicked field: ", clickedFieldId, data.name) + /* + setExpansionModalOpen(false); + */ - //if (data.name === "file_id") { - // console.log("show file video?") - // if (setShowVideo !== undefined) { - // setShowVideo("https://www.youtube.com/embed/DPYowyTbsSk") - // } - //} - //(data.name.toLowerCase().includes("api") || - /* - setExpansionModalOpen(false); - if ( - setScrollConfig !== undefined && - scrollConfig !== null && - scrollConfig !== undefined && - scrollConfig.selected !== clickedFieldId - ) { - scrollConfig.selected = clickedFieldId; - setScrollConfig(scrollConfig); - //console.log("Change field id!") - } - */ - - //console.log("Clicked field: ", clickedFieldId) if (setScrollConfig !== undefined && scrollConfig !== null && scrollConfig !== undefined && scrollConfig.selected !== clickedFieldId) { + console.log("IN SCROLL CONFIG!") + scrollConfig.selected = clickedFieldId setScrollConfig(scrollConfig) - //console.log("Change field id!") } }} id={clickedFieldId} @@ -2476,19 +2484,19 @@ const ParsedAction = (props) => { ) : null} - {hasAutocomplete === true ? - - - - : - null} + {hasAutocomplete === true ? + + + + : + null}
{ const parsedBaseLabel = "$"+baselabel.toLowerCase().replaceAll(" ", "_") const newname = "$"+name.toLowerCase().replaceAll(" ", "_") - console.log("NAME: ", name) - // Check if it's the same as the current name in use //if (name === selectedAction.label) { // console.log("Returning from name thing") @@ -3352,9 +3358,8 @@ const ParsedAction = (props) => { No selection {selectedAction.authentication.map((data) => { - console.log("AUTH DATA: ", data) if (data.last_modified === true) { - console.log("LAST MODIFIED: ", data.label) + //console.log("LAST MODIFIED: ", data.label) } return ( @@ -3736,9 +3741,12 @@ const ParsedAction = (props) => { return ( { backgroundColor: theme.palette.inputColor, borderRadius: theme.palette.borderRadius, }} - {...params} label="Find Actions" variant="outlined" + name={`disable_autocomplete_${Math.random()}`} + /> ); }} diff --git a/frontend/src/components/RuntimeDebugger.jsx b/frontend/src/components/RuntimeDebugger.jsx index 570778df..01bb345c 100644 --- a/frontend/src/components/RuntimeDebugger.jsx +++ b/frontend/src/components/RuntimeDebugger.jsx @@ -54,6 +54,7 @@ const RuntimeDebugger = (props) => { const [status, setStatus] = useState("") const [endTime, setEndTime] = useState("") const [startTime, setStartTime] = useState("") + const [totalCount, setTotalCount] = useState(0) const [workflow, setWorkflow] = useState({}) const [ignoreOrg, setIgnoreOrg] = useState(false) @@ -65,16 +66,80 @@ const RuntimeDebugger = (props) => { const [workflows, setWorkflows] = useState([ {"id": "", "name": "All Workflows",} ]) - /* - [ - {id: "1", execution_id: "1", status: "FINISHED", startTimestamp: "2021-10-01 12:00:00", endTimestamp: "2021-10-01 12:00:00", workflow: {"id": "1234", "name": "what",}}, - {id: "2", execution_id: "2", status: "WAITING", startTimestamp: "2021-10-01 12:00:00", endTimestamp: "2021-10-01 12:00:00", workflow: {"id": "1234", "name": "what",}}, - {id: "3", execution_id: "3", status: "EXECUTING",startTimestamp: "2021-10-01 12:00:00", endTimestamp: "2021-10-01 12:00:00", workflow: {"id": "1234", "name": "what",}}, - {id: "4", execution_id: "4", status: "ABORTED", startTimestamp: "2021-10-01 12:00:00", endTimestamp: "2021-10-01 12:00:00", workflow: {"id": "1234", "name": "what",}}, - ]); - */ + + // Shitty workflow search on purpose :) + const handleWorkflowUsageCount = (workflows) => { + if (workflows === undefined || workflows === null || workflows.length === 0) { + return + } + + setTotalCount(0) + + var count = 0 + var starttime = startTime === undefined || startTime === null || startTime === "" ? "" : new Date(startTime).toISOString() + var endtime = endTime === undefined || endTime === null || endTime == "" ? "" : new Date(endTime).toISOString() + + var maxworkflows = 5 + + console.log("Looking for MAX this amount of workflows: ", maxworkflows) + for (let key in workflows) { + if (key > maxworkflows) { + break + } + + const workflowId = workflows[key].id + // Fetch the data for the workflow + var url = `${globalUrl}/api/v1/workflows/${workflowId}/executions/count` + if (starttime !== "") { + url += `?start_time=${starttime}` + } + + if (endtime !== "") { + if (starttime !== "") { + url += `&end_time=${endtime}` + } else { + url += `?end_time=${endtime}` + } + } + + fetch(url, { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for workflows :O!"); + return; + } + + return response.json() + }) + .then((data) => { + if (data.success) { + if (data.count !== undefined && data.count !== null) { + count += data.count + } + } else { + console.log("Failed to get workflow usage count: ", data) + } + }) + .catch((error) => { + console.error("Error:", error); + }) + } + + setTimeout(() => { + console.log("Setting total count: ", count) + setTotalCount(count) + }, maxworkflows*300) + } const submitSearch = (workflowId, status, startTime, endTime, cursor, limit) => { + handleWorkflowUsageCount(workflows) //setResultRows([]) setSearchLoading(true) @@ -135,6 +200,7 @@ const RuntimeDebugger = (props) => { }) } + const getAvailableWorkflows = () => { fetch(globalUrl + "/api/v1/workflows", { method: "GET", @@ -624,7 +690,7 @@ const RuntimeDebugger = (props) => {
-

Workflow Run Debugger

+

Workflow Run Debugger {totalCount !== 0 ? ` (~${totalCount})` : ""}

{selectedWorkflowExecutions.length > 0 ? diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index ed968653..92a57baa 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -1393,7 +1393,7 @@ const AngularWorkflow = (defaultprops) => { } if (streamDisabled) { - console.log("Stream disabled") + console.log("Stream disabled - send") return } @@ -2739,7 +2739,7 @@ const AngularWorkflow = (defaultprops) => { } if (streamDisabled) { - console.log("Stream disabled") + console.log("Stream listener disabled") return } @@ -2751,6 +2751,7 @@ const AngularWorkflow = (defaultprops) => { const url = `${streamUrl}/api/v1/workflows/${workflowId}/stream` while (true) { if (streamDisabled === true || streamDisabled2 === true) { + console.log("Stream disabled, breaking") break } @@ -3731,6 +3732,10 @@ const AngularWorkflow = (defaultprops) => { return } else if (data.buttonType === "set_startnode" && data.type !== "TRIGGER") { + //console.log("STARTNODE") + //event.preventDefault() + //event.stopPropagation() + const parentNode = cy.getElementById(data.attachedTo); if (parentNode !== null && parentNode !== undefined) { var oldstartnode = cy.getElementById(workflow.start); @@ -3967,8 +3972,6 @@ const AngularWorkflow = (defaultprops) => { //} curaction.app_id = curapp.id - console.log("CURAPP: ", curapp.authentication) - setAuthenticationType( curapp.authentication.type === "oauth2" && curapp.authentication.redirect_uri !== undefined && curapp.authentication.redirect_uri !== null ? { type: "oauth2", @@ -4000,7 +4003,6 @@ const AngularWorkflow = (defaultprops) => { } const tmpAuth = JSON.parse(JSON.stringify(newAppAuth)); - //console.log("FOUND AUTH OPTIONS: ", tmpAuth) const curappName = curapp.name.toLowerCase() for (let tmpAuthKey in tmpAuth) { @@ -4036,7 +4038,6 @@ const AngularWorkflow = (defaultprops) => { } } - console.log("OPTIONS: ", authenticationOptions) // Find with authenticationOption (authenticationOptions) has the highest .edited time. In this index, set the "last_modified" to true var latesttime = 0 @@ -4044,7 +4045,6 @@ const AngularWorkflow = (defaultprops) => { for (var i = 0; i < authenticationOptions.length; i++) { const authopt = authenticationOptions[i] - console.log("AUTHOPT: ", authopt) if (authopt.edited > latesttime) { latesttime = authopt.edited @@ -4052,7 +4052,6 @@ const AngularWorkflow = (defaultprops) => { } } - console.log("LATEST INDEX: ", latestindex) if (latestindex !== -1) { authenticationOptions[latestindex].last_modified = true } @@ -5933,7 +5932,7 @@ const AngularWorkflow = (defaultprops) => { if (workflow.actions.length < 4) { addSuggestionButtons(nodedata, event); } else { - console.log("Too many actions to suggest (for now)") + //console.log("Too many actions to suggest (for now)") } } } @@ -14666,6 +14665,7 @@ const AngularWorkflow = (defaultprops) => { } } + return (
{ } } + const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search; + const chosenNodeId = new URLSearchParams(cursearch).get("node"); + const highlightNode = chosenNodeId !== null && chosenNodeId !== undefined && chosenNodeId !== "" && chosenNodeId === data.action.id return (
{ ); // Awful way of handling scroll - if ( - scrollConfig !== undefined && - setScrollConfig !== undefined && - Object.getOwnPropertyNames(selectedAction).length !== 0 - ) { + if (scrollConfig !== undefined && setScrollConfig !== undefined && Object.getOwnPropertyNames(selectedAction).length !== 0) { const rightSideActionView = document.getElementById("rightside_actions"); if (rightSideActionView !== undefined && rightSideActionView !== null) { - if ( - scrollConfig.top !== 0 && - scrollConfig.top !== undefined && - scrollConfig.top !== 0 - ) { + if (scrollConfig.top !== null && scrollConfig.top !== undefined && scrollConfig.top !== 0) { setTimeout(() => { - if ( - scrollConfig.selected !== undefined && - scrollConfig.selected !== null - ) { - const selectedField = document.getElementById( - scrollConfig.selected - ); + if (scrollConfig.selected !== undefined && scrollConfig.selected !== null) { + const selectedField = document.getElementById(scrollConfig.selected) if (selectedField !== undefined && selectedField !== null) { - selectedField.focus(); + selectedField.focus() } } }, 5);