From 1373bac875bbb38e1902948f9d80c2692850e54a Mon Sep 17 00:00:00 2001 From: Frikky Date: Tue, 28 Nov 2023 03:09:46 +0100 Subject: [PATCH] More header, notifications & debugger fixes --- frontend/src/components/NewHeader.jsx | 66 +++---- frontend/src/components/ParsedAction.jsx | 10 +- frontend/src/components/RuntimeDebugger.jsx | 86 +++++--- frontend/src/components/ShuffleCodeEditor.jsx | 35 +++- frontend/src/defaultCytoscapeStyle.jsx | 5 +- frontend/src/views/AngularWorkflow.jsx | 186 ++++++++++++++---- 6 files changed, 271 insertions(+), 117 deletions(-) diff --git a/frontend/src/components/NewHeader.jsx b/frontend/src/components/NewHeader.jsx index 004b3132..f6f663b3 100644 --- a/frontend/src/components/NewHeader.jsx +++ b/frontend/src/components/NewHeader.jsx @@ -294,49 +294,26 @@ const Header = (props) => { borderBottom: "1px solid rgba(255,255,255,0.4)", }} > - {/* - {new Date(data.updated_at).toISOString()} - */} - {data.reference_url !== undefined && - data.reference_url !== null && - data.reference_url.length > 0 ? ( - - {data.title} - - ) : ( - - {data.title} - - )} + {data.reference_url !== undefined && data.reference_url !== null && data.reference_url.length > 0 ? + + + {data.title} ({data.amount}) + + + : + + {data.title} + + } - {data.image !== undefined && - data.image !== null && - data.image.length > 0 ? ( - {data.title} - ) : null} - {data.description} - {/*data.tags !== undefined && data.tags !== null && data.tags.length > 0 ? - data.tags.map((tag, index) => { - return ( - { - }} - variant="outlined" - color="primary" - /> - ) - }) - : null */} + {data.image !== undefined && data.image !== null && data.image.length > 0 ? + {data.title} + : + null + } + + {data.description} +
{data.read === false ? (
- Notifications are made by Shuffle to help you discover issues or - improvements. + Notifications generated made by Shuffle to help you discover issues or + improvements. + Learn more {notifications.map((data, index) => { diff --git a/frontend/src/components/ParsedAction.jsx b/frontend/src/components/ParsedAction.jsx index 53f40b79..558fb983 100755 --- a/frontend/src/components/ParsedAction.jsx +++ b/frontend/src/components/ParsedAction.jsx @@ -170,6 +170,7 @@ const ParsedAction = (props) => { setEditorData, setcodedata, + setAiQueryModalOpen, } = props; const classes = useStyles(); @@ -2913,14 +2914,17 @@ const ParsedAction = (props) => { }} disabled={autoCompleting} onClick={() => { - // aiSubmit(aiMsg, undefined, undefined, newSelectedAction) - aiSubmit("Fill based on previous values", undefined, undefined, selectedAction) + //if (setAiQueryModalOpen !== undefined) { + // setAiQueryModalOpen(true) + //} else { + aiSubmit("Fill based on previous values", undefined, undefined, selectedAction) + //} setAutocompleting(true) }} > {autoCompleting ? diff --git a/frontend/src/components/RuntimeDebugger.jsx b/frontend/src/components/RuntimeDebugger.jsx index 47462d2b..ff2706f6 100644 --- a/frontend/src/components/RuntimeDebugger.jsx +++ b/frontend/src/components/RuntimeDebugger.jsx @@ -46,11 +46,6 @@ const RuntimeDebugger = (props) => { const classes = useStyles(); - //const [workflowId, setWorkflowId] = useState(""); - //const [status, setStatus] = useState("FINISHED"); - //const [endTime, setEndTime] = useState(dayjs().subtract(0, 'day')) - //const [startTime, setStartTime] = useState(dayjs().subtract(30, 'day')) - const [workflowId, setWorkflowId] = useState("") const [status, setStatus] = useState("") const [endTime, setEndTime] = useState("") @@ -75,7 +70,7 @@ const RuntimeDebugger = (props) => { const submitSearch = (workflowId, status, startTime, endTime, cursor, limit) => { - setResultRows([]) + //setResultRows([]) setSearchLoading(true) const fetchData = { workflow_id: workflowId, @@ -107,22 +102,29 @@ const RuntimeDebugger = (props) => { //data.runs[key].endTimestamp = data.runs[key].ended_at.toISOString().slice(0, 19).replace('T', ' ') const startTimestamp = new Date(data.runs[key].started_at*1000) data.runs[key].startTimestamp = startTimestamp.toISOString().slice(0, 19).replace('T', ' ') + const endTimestamp = new Date(data.runs[key].completed_at*1000) data.runs[key].endTimestamp = endTimestamp.toISOString().slice(0, 19).replace('T', ' ') + if (data.runs[key].completed_at === 0 || data.runs[key].completed_at === null) { + data.runs[key].endTimestamp = "" + } } // Add 20 empty rows to the end of the resultRows array // This is to make sure that the scrollbar is always visible setResultRows(data.runs) + } else { + toast("No results found. Keeping old runs") } } else { - console.error("Search error: ", data.reason) + toast("Failed to search for runs. Please try again.") } }) .catch((error) => { setSearchLoading(false) console.error("Error:", error); + toast("Failed to search for runs. Please try again (2)") }) } @@ -315,27 +317,63 @@ const RuntimeDebugger = (props) => { ) }, }, - { field: 'startTimestamp', headerName: 'Start time (UTC)', width: 160, }, + { field: 'startTimestamp', headerName: 'Start time (UTC)', width: 160, + renderCell: (params) => { + const hasError = params.row.completed_at-params.row.started_at > 300 + + return ( + + { + console.log("Zoom in on end timestamp is this one: ", params.row.endTimestamp) + //setEndTimestamp(params.row.endTimestamp) + + // Make a new Date() from params.row.startTimestamp and set it in the endTime + const newEndTime = new Date(params.row.startTimestamp) + if (newEndTime !== null && newEndTime !== undefined && newEndTime !== "" && newEndTime !== "Invalid Date") { + // Translate newEndTime to UTC no matter what timezone we are in. Based it on local() + // Plus 1 minute to make sure it comes in + setEndTime(dayjs(newEndTime.setMinutes(newEndTime.getMinutes()+1))) + + // Use dayjs to translate it into something useful + + // Remove 5 minutes from it and set startTime + //newEndTime.setMinutes(newEndTime.getMinutes()-5) + //setStartTime(dayjs(newEndTime)) + } + }}> + {params.row.startTimestamp} + + + ) + } + }, { field: 'endTimestamp', headerName: 'End time (UTC)', width: 160, }, { field: 'id', headerName: 'Explore', width: 65, - renderCell: (params) => ( - - {params.row.result !== null && params.row.result !== undefined && params.row.result !== "" ? - params.row.result - : - null - } - - } > - - - - - ), + renderCell: (params) => { + const parsedResult = params.row.result === null || params.row.result === undefined || params.row.result === "" ? null : params.row.result + const hasError = parsedResult !== null && parsedResult !== undefined && parsedResult !== "" ? parsedResult.includes("{%") && parsedResult.includes("%}") : false + + return ( + + {params.row.result !== null && params.row.result !== undefined && params.row.result !== "" ? + params.row.result + : + null + } + + }> + + + + + + + ) + } }, ] @@ -522,6 +560,7 @@ const RuntimeDebugger = (props) => { minWidth: 240, maxWidth: 240, }} + ampm={false} label="Search from" format="YYYY-MM-DD HH:mm:ss" value={startTime} @@ -535,6 +574,7 @@ const RuntimeDebugger = (props) => { minWidth: 240, maxWidth: 240, }} + ampm={false} label="Search until" format="YYYY-MM-DD HH:mm:ss" value={endTime} diff --git a/frontend/src/components/ShuffleCodeEditor.jsx b/frontend/src/components/ShuffleCodeEditor.jsx index 91db5f49..3053083c 100644 --- a/frontend/src/components/ShuffleCodeEditor.jsx +++ b/frontend/src/components/ShuffleCodeEditor.jsx @@ -550,7 +550,6 @@ const CodeEditor = (props) => { var code_lines = localcodedata.split('\n') for (var i = 0; i < code_lines.length; i++){ var current_code_line = code_lines[i] - console.log("Codeline: ", current_code_line) var variable_occurence = current_code_line.match(/[\\]{0,1}[$]{1}([a-zA-Z0-9_-]+\.?){1}([a-zA-Z0-9#_-]+\.?){0,}/g) @@ -612,8 +611,6 @@ const CodeEditor = (props) => { const fixedVariable = fixVariable(variable_occurence[occ]) var correctVariable = availableVariables.includes(fixedVariable) if(!correctVariable) { - console.log("Line: ", i, "ch: ", dollar_occurence[occ]) - value.markText({line:i, ch:dollar_occurence[occ]}, {line:i, ch:dollar_occurence_len[occ]+dollar_occurence[occ]}, {"css": "background-color: rgb(248, 106, 62, 0.9); padding-top: 2px; padding-bottom: 2px; color: white"}) } else { value.markText({line:i, ch:dollar_occurence[occ]}, {line:i, ch:dollar_occurence_len[occ]+dollar_occurence[occ]}, {"css": "background-color: #8b8e26; padding-top: 2px; padding-bottom: 2px; color: white"}) @@ -664,6 +661,23 @@ const CodeEditor = (props) => { setlocalcodedata(updatedCode) } + const fixStringInput = (new_input) => { + // Newline fixes + new_input = new_input.replace(/\r\n/g, "\\n") + new_input = new_input.replace(/\n/g, "\\n") + + // Quote fixes + new_input = new_input.replace(/\\"/g, '"') + new_input = new_input.replace(/"/g, '\\"') + + new_input = new_input.replace(/\\'/g, "'") + new_input = new_input.replace(/'/g, "\\'") + + + return new_input + } + + const expectedOutput = (input) => { //const found = input.match(/[$]{1}([a-zA-Z0-9_-]+\.?){1}([a-zA-Z0-9#_-]+\.?){0,}/g) @@ -687,20 +701,26 @@ const CodeEditor = (props) => { valuefound = true + console.log("Here. Checking if we got an example?") try { if (typeof actionlist[j].example === "object") { + input = input.replace(found[i], JSON.stringify(actionlist[j].example), -1); } else if (actionlist[j].example.trim().startsWith("{") || actionlist[j].example.trim().startsWith("[")) { input = input.replace(found[i], JSON.stringify(actionlist[j].example), -1); } else { - input = input.replace(found[i], actionlist[j].example, -1) + console.log("This?") + + const newExample = fixStringInput(actionlist[j].example) + input = input.replace(found[i], newExample, -1) } } catch (e) { input = input.replace(found[i], actionlist[j].example, -1) } } + //if (!valuefound) { // console.log("Couldn't find value "+fixedVariable) //} @@ -736,7 +756,10 @@ const CodeEditor = (props) => { new_input = JSON.stringify(new_input) } else { if (typeof new_input === "string") { - new_input = new_input + // Check if it contains any newlines, and replace them with raw newlines + new_input = fixStringInput(new_input) + + // Replace quotes with nothing } else { console.log("NO TYPE? ", typeof new_input) try { @@ -747,7 +770,6 @@ const CodeEditor = (props) => { } } - //console.log("FOUND2: ", fixedVariable, actionlist[j].example) input = input.replace(fixedVariable, new_input, -1) input = input.replace(found[i], new_input, -1) @@ -1430,7 +1452,6 @@ const CodeEditor = (props) => { highlight_variables(value) }} onChange={(value, viewUpdate) => { - console.log("Value: ", value, viewUpdate) setlocalcodedata(value) expectedOutput(value) diff --git a/frontend/src/defaultCytoscapeStyle.jsx b/frontend/src/defaultCytoscapeStyle.jsx index 01c389f8..7e7132fd 100644 --- a/frontend/src/defaultCytoscapeStyle.jsx +++ b/frontend/src/defaultCytoscapeStyle.jsx @@ -4,11 +4,10 @@ const data = [ css: { label: "data(label)", "text-valign": "center", - "font-family": - "Segoe UI, Tahoma, Geneva, Verdana, sans-serif, sans-serif", + "font-family": "Segoe UI, Tahoma, Geneva, Verdana, sans-serif, sans-serif", "font-weight": "lighter", - "margin-right": "10px", "font-size": "18px", + "margin-right": "10px", width: "80px", height: "80px", color: "white", diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index 65038a5b..d596ffe2 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -112,6 +112,7 @@ import { AutoFixHigh as AutoFixHighIcon, Polyline as PolylineIcon, QueryStats as QueryStatsIcon, + AutoAwesome as AutoAwesomeIcon, } from "@mui/icons-material"; @@ -438,6 +439,7 @@ const AngularWorkflow = (defaultprops) => { const [appAuthentication, setAppAuthentication] = React.useState(undefined); const [variablesModalOpen, setVariablesModalOpen] = React.useState(false); + const [aiQueryModalOpen, setAiQueryModalOpen] = React.useState(false) const [executionVariablesModalOpen, setExecutionVariablesModalOpen] = React.useState(false); const [authenticationModalOpen, setAuthenticationModalOpen] = React.useState(false); @@ -592,17 +594,22 @@ const AngularWorkflow = (defaultprops) => { const [elements, setElements] = useState([]); const [loopRunning, setLoopRunning] = useState(false) + var loopRunning2 = loopRunning const stop = () => { setLoopRunning(false) + loopRunning2 = false } const start = () => { setLoopRunning(true) + loopRunning2 = true } useEffect(() => { - //console.log("In useeffect for loopRunning: ", loopRunning) - if (loopRunning) { + // Current variable + future state controlled + // This is so that the loop can stop itself as well + console.log("In useeffect for loopRunning: ", loopRunning, loopRunning2) + if (loopRunning && loopRunning2) { const intervalId = setInterval(() => { if (!loopRunning) { clearInterval(intervalId); @@ -983,19 +990,21 @@ const AngularWorkflow = (defaultprops) => { return response.json(); }) .then((responseJson) => { - if (responseJson !== undefined && responseJson !== null && responseJson.executions !== undefined && responseJson.executions !== null && responseJson.executions.length > 0) { + console.log("GOT A RESPONSE??") + if (responseJson !== undefined && responseJson !== null && responseJson.executions !== undefined && responseJson.executions !== null) { // - means it's opposite const newkeys = sortByKey(responseJson.executions, "-started_at"); setWorkflowExecutions(newkeys); const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search; - var tmpView = new URLSearchParams(cursearch).get("execution_id"); if (execution_id !== undefined && execution_id !== null && execution_id.length > 0 && (tmpView === undefined || tmpView === null || tmpView.length === 0)) { tmpView = execution_id; } + console.log("EXECUTION ID: ", tmpView) + // Compare with currently selected item if (tmpView !== undefined && tmpView !== null && tmpView.length > 0) { // Don't clean up if it's already open @@ -1046,7 +1055,21 @@ const AngularWorkflow = (defaultprops) => { }, 5000); } } - } + } else { + const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search; + var tmpView = new URLSearchParams(cursearch).get("execution_id"); + console.log("Alertnative execution id check: ", tmpView) + + if (tmpView === undefined || tmpView === null || tmpView.length === 0) { + const execution_id = tmpView; + setExecutionModalView(1); + setExecutionRequest({ + execution_id: execution_id, + }); + + start() + } + } }) .catch((error) => { //toast(error.toString()); @@ -1067,8 +1090,14 @@ const AngularWorkflow = (defaultprops) => { }) .then((response) => { if (response.status !== 200) { - console.log("Status not 200 for stream results :O!"); stop(); + setExecutionModalView(0); + toast("Failed loading the workflow run") + console.log("Status not 200 for stream results :O!"); + + //const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search; + //const newitem = removeParam("execution_id", cursearch); + //navigate(curpath + newitem) } return response.json(); @@ -1247,10 +1276,11 @@ const AngularWorkflow = (defaultprops) => { // Controls the colors and direction of execution results. // Style is in defaultCytoscapeStyle.js const handleUpdateResults = (responseJson, executionRequest) => { - if (responseJson === undefined || responseJson === null || responseJson.success === false) { - return - } - //console.log(responseJson) + if (responseJson === undefined || responseJson === null || responseJson.success === false) { + stop() + return + } +//console.log(responseJson) // Loop nodes and find results // Update on every interval? idk @@ -1263,7 +1293,8 @@ const AngularWorkflow = (defaultprops) => { //console.log("Updating data!") setExecutionData(responseJson) } else { - if (responseJson.status === "ABORTED" || responseJson.status === "STOPPED" || responseJson.status === "FAILURE" || responseJson.status === "WAITING") { + if (responseJson.status === "ABORTED" || responseJson.status === "STOPPED" || responseJson.status === "FAILURE" || responseJson.status === "WAITING" || responseJson.status === "FINISHED") { + console.log("DONE!") stop() } @@ -1321,6 +1352,7 @@ const AngularWorkflow = (defaultprops) => { }) }; + var streamDisabled2 = false const sendStreamRequest = (body) => { //console.log("Stream not activated yet.") if (!isCloud) { @@ -1356,6 +1388,9 @@ const AngularWorkflow = (defaultprops) => { .then((response) => { setSavingState(0); if (response.status !== 200) { + + setStreamDisabled(true) + streamDisabled2 = true //console.log("Status not 200 for stream :O!"); } @@ -1367,6 +1402,7 @@ const AngularWorkflow = (defaultprops) => { .catch((error) => { console.log("Stream send error: ", error.toString()) setStreamDisabled(true) + streamDisabled2 = true }) } @@ -2537,6 +2573,17 @@ const AngularWorkflow = (defaultprops) => { try { var chunkJson = JSON.parse(chunk) + if (chunkJson.success === false) { + console.log("Chunk failed: ", chunkJson) + + if (!streamDisabled) { + setStreamDisabled(true) + streamDisabled2 = true + } + return + } + + if (chunkJson.item !== undefined && chunkJson.item !== null && chunkJson.item !== "") { if (chunkJson.item === "node") { if (chunkJson.type === "move") { @@ -2561,6 +2608,13 @@ const AngularWorkflow = (defaultprops) => { } } catch (e) { console.log("Chunk JSON error: ", e) + + if (!streamDisabled) { + setStreamDisabled(true) + streamDisabled2 = true + } + + return } //data.push(chunk) @@ -2619,7 +2673,7 @@ const AngularWorkflow = (defaultprops) => { const streamUrl = "https://stream.shuffler.io" const url = `${streamUrl}/api/v1/workflows/${workflowId}/stream` while (true) { - if (streamDisabled) { + if (streamDisabled === true || streamDisabled2 === true) { break } @@ -3021,7 +3075,7 @@ const AngularWorkflow = (defaultprops) => { sendStreamRequest({ "item": "node", "type": "unselect", - "userid": userdata.id, + "id": workflow.id, }) //}, 150) }; @@ -4071,7 +4125,6 @@ const AngularWorkflow = (defaultprops) => { "item": "node", "type": "select", "id": data.id, - "userid": userdata.id, "location": { "x": event.target.position("x"), "y": event.target.position("y"), @@ -5985,10 +6038,10 @@ const AngularWorkflow = (defaultprops) => { const xParsed = destinationnodePosition.x - sourcenodePosition.x const yParsed = destinationnodePosition.y - sourcenodePosition.y - const z = Math.sqrt(xParsed * xParsed + yParsed * yParsed); - const costheta = xParsed / z; - const alpha = 0.25; - var controlPointDistance = [-alpha * yParsed * costheta, alpha * yParsed * costheta]; + const z = Math.sqrt(xParsed * xParsed + yParsed * yParsed) + const costheta = xParsed / z + const alpha = 0.3 + var controlPointDistance = [-alpha * yParsed * costheta, alpha * yParsed * costheta] var controlPointWeight = [alpha, 1 - alpha] //'control-point-weight': ['0.33', '0.66'], @@ -6151,8 +6204,18 @@ const AngularWorkflow = (defaultprops) => { const foundtriggers = inputworkflow.triggers.map((trigger) => { const node = {}; node.position = trigger.position; - node.data = trigger; + if (trigger.large_image === undefined || trigger.large_image === null || trigger.large_image.length === 0) { + + // Search triggers array for it where the name is matching and set image + var foundTrigger = triggers.find((t) => t.name === trigger.name) + if (foundTrigger !== undefined && foundTrigger !== null) { + console.log("Autofilled missing trigger image") + trigger.large_image = foundTrigger.large_image + } + } + + node.data = trigger; node.data._id = trigger["id"]; node.data.id = trigger["id"]; node.data.type = "TRIGGER"; @@ -6394,13 +6457,13 @@ const AngularWorkflow = (defaultprops) => { sendStreamRequest({ "item": "workflow", "type": "enter", - "userid": userdata.id, + "id": workflow.id, }) } const fetchRecommendations = (inputWorkflow) => { - //console.log("Disabled recommendations") - //return + console.log("Disabled recommendations as they were too inaccurate") + return const parsedWorkflow = JSON.parse(JSON.stringify(inputWorkflow)) @@ -6500,6 +6563,11 @@ const AngularWorkflow = (defaultprops) => { return response.json(); }) .then((responseJson) => { + if (responseJson === null) { + console.log("No revisions found") + return + } + if (responseJson.success === false) { console.log("Error getting workflow revisions: ", responseJson) return @@ -6553,13 +6621,16 @@ const AngularWorkflow = (defaultprops) => { } // App length necessary cus of cy initialization - if (elements.length === 0 && workflow.actions !== undefined && !graphSetup && Object.getOwnPropertyNames(workflow).length > 0 && workflowRecommendations !== undefined) { + // Not using recommendations, so skipping this for now + //if (elements.length === 0 && workflow.actions !== undefined && !graphSetup && Object.getOwnPropertyNames(workflow).length > 0 && workflowRecommendations !== undefined) { + if (elements.length === 0 && workflow.actions !== undefined && !graphSetup && Object.getOwnPropertyNames(workflow).length > 0) { setGraphSetup(true); setupGraph(workflow); console.log("In graph setup") // 2nd load - configures cytoscape - } else if (!established && cy !== undefined && ((apps !== null && apps !== undefined && apps.length > 0) || workflow.public === true) && Object.getOwnPropertyNames(workflow).length > 0 && appAuthentication !== undefined && workflowRecommendations !== undefined) { + //} else if (!established && cy !== undefined && ((apps !== null && apps !== undefined && apps.length > 0) || workflow.public === true) && Object.getOwnPropertyNames(workflow).length > 0 && appAuthentication !== undefined && workflowRecommendations !== undefined) { + } else if (!established && cy !== undefined && ((apps !== null && apps !== undefined && apps.length > 0) || workflow.public === true) && Object.getOwnPropertyNames(workflow).length > 0 && appAuthentication !== undefined) { console.log("In POST graph setup!") @@ -9086,6 +9157,33 @@ const AngularWorkflow = (defaultprops) => { backgroundColor: theme.palette.inputColor, }; + const aiQueryModal = + { + }} + > + + Condition + + + + const conditionsModal = ( { }} onChange={(event, newValue) => { // Workaround with event lol - console.log(event, newValue) + console.log("CHANGE: ", event, newValue) if (newValue !== undefined && newValue !== null) { var parsedvalue = JSON.parse(JSON.stringify(newValue)) parsedvalue.actions = [] @@ -11772,6 +11870,7 @@ const AngularWorkflow = (defaultprops) => { > { + console.log("CLICK: ", app) const newValue = app if (newValue !== undefined && newValue !== null) { @@ -13856,6 +13955,7 @@ const AngularWorkflow = (defaultprops) => { expansionModalOpen={codeEditorModalOpen} setExpansionModalOpen={setCodeEditorModalOpen} setEditorData={setEditorData} + setAiQueryModalOpen={setAiQueryModalOpen} /> } else if (Object.getOwnPropertyNames(selectedComment).length > 0) { @@ -14403,6 +14503,13 @@ const AngularWorkflow = (defaultprops) => { style={{ width: size, height: size }} /> ); + } else if (execution.execution_source === "ShuffleGPT") { + return ( + + ); } if ( @@ -15484,19 +15591,23 @@ const AngularWorkflow = (defaultprops) => { width: 30, }} onClick={() => { - const oldstartnode = cy.getElementById(data.action.id); - //console.log("FOUND NODe: ", oldstartnode) - if (oldstartnode !== undefined && oldstartnode !== null) { - const foundname = oldstartnode.data("label") - if (foundname !== undefined && foundname !== null) { - data.action.label = foundname - } - } + if (cy !== undefined) { + const oldstartnode = cy.getElementById(data.action.id); + //console.log("FOUND NODe: ", oldstartnode) + if (oldstartnode !== undefined && oldstartnode !== null) { + const foundname = oldstartnode.data("label") + if (foundname !== undefined && foundname !== null) { + data.action.label = foundname + } + } - //console.log("Click data: ", data) - //data.action.label = "" - setSelectedResult(data); - setCodeModalOpen(true); + //console.log("Click data: ", data) + //data.action.label = "" + setSelectedResult(data); + setCodeModalOpen(true); + } else { + toast("Please wait until the workflow is loaded and try again") + } }} > { {newView} + {aiQueryModal} {conditionsModal} {authenticationModal} {codePopoutModal}