fix: nested var ref

This commit is contained in:
yashsinghcodes
2025-12-04 14:11:01 +05:30
parent cfc7da0abb
commit eccfe01fba
+292 -288
View File
@@ -18,7 +18,7 @@ import {
Collapse, Collapse,
} from '@mui/material'; } from '@mui/material';
import { Context } from '../context/ContextApi.jsx'; import { Context } from '../context/ContextApi.jsx';
import {getTheme} from '../theme.jsx'; import { getTheme } from '../theme.jsx';
import Checkbox from '@mui/material/Checkbox'; import Checkbox from '@mui/material/Checkbox';
import { isMobile } from "react-device-detect" import { isMobile } from "react-device-detect"
import { NestedMenuItem } from "mui-nested-menu" import { NestedMenuItem } from "mui-nested-menu"
@@ -27,7 +27,7 @@ import { SetJsonDotnotation } from "../views/AngularWorkflow.jsx";
import Draggable from "react-draggable"; import Draggable from "react-draggable";
import { import {
Storage as StorageIcon, Storage as StorageIcon,
FullscreenExit as FullscreenExitIcon, FullscreenExit as FullscreenExitIcon,
Extension as ExtensionIcon, Extension as ExtensionIcon,
Apps as AppsIcon, Apps as AppsIcon,
@@ -46,7 +46,7 @@ import {
DragIndicator as DragIndicatorIcon, DragIndicator as DragIndicatorIcon,
RestartAlt as RestartAltIcon, RestartAlt as RestartAltIcon,
ArrowForward as ArrowForwardIcon, ArrowForward as ArrowForwardIcon,
KeyboardReturn as KeyboardReturnIcon, KeyboardReturn as KeyboardReturnIcon,
FormatIndentIncrease as FormatIndentIncreaseIcon, FormatIndentIncrease as FormatIndentIncreaseIcon,
Fullscreen as FullscreenIcon, Fullscreen as FullscreenIcon,
} from '@mui/icons-material'; } from '@mui/icons-material';
@@ -153,7 +153,7 @@ const CodeEditor = (props) => {
if (!content || typeof content !== 'string' || content.trim().length === 0) { if (!content || typeof content !== 'string' || content.trim().length === 0) {
return content; return content;
} }
try { try {
// Check if content looks like JSON (starts with { or [) // Check if content looks like JSON (starts with { or [)
const trimmedContent = content.trim(); const trimmedContent = content.trim();
@@ -165,7 +165,7 @@ const CodeEditor = (props) => {
return IndentJsonLikeString(content, 2); return IndentJsonLikeString(content, 2);
} }
} }
// Return original content if it doesn't look like JSON // Return original content if it doesn't look like JSON
return content; return content;
} catch (error) { } catch (error) {
@@ -179,7 +179,7 @@ const CodeEditor = (props) => {
const [localcodedata, setlocalcodedata] = React.useState(codedata === undefined || codedata === null || codedata.length === 0 ? "" : codedata); const [localcodedata, setlocalcodedata] = React.useState(codedata === undefined || codedata === null || codedata.length === 0 ? "" : codedata);
// const {codelang, setcodelang} = props // const {codelang, setcodelang} = props
const {themeMode, supportEmail} = useContext(Context) const { themeMode, supportEmail } = useContext(Context)
const theme = getTheme(themeMode) const theme = getTheme(themeMode)
const [validation, setValidation] = React.useState(false); const [validation, setValidation] = React.useState(false);
@@ -370,9 +370,9 @@ const CodeEditor = (props) => {
setMainVariables(tmpVariables) setMainVariables(tmpVariables)
} }
const handleKeyDown = (event) => { const handleKeyDown = (event) => {
if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') { if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {
event.preventDefault() event.preventDefault()
const tryItButton = document.getElementById("try-it-button") const tryItButton = document.getElementById("try-it-button")
if (tryItButton !== undefined && tryItButton !== null) { if (tryItButton !== undefined && tryItButton !== null) {
tryItButton.click() tryItButton.click()
@@ -382,7 +382,7 @@ const CodeEditor = (props) => {
// Remove the original useEffect for actionlist since we'll update on action/trigger changes // Remove the original useEffect for actionlist since we'll update on action/trigger changes
useEffect(() => { useEffect(() => {
document.addEventListener("keydown", handleKeyDown) document.addEventListener("keydown", handleKeyDown)
updateAvailableVariables(actionlist) updateAvailableVariables(actionlist)
}, []) }, [])
@@ -972,7 +972,11 @@ const CodeEditor = (props) => {
// Resolve the child paths/variables first, // Resolve the child paths/variables first,
// So that "$a.b.c" is handled before "$a.b" and then "$a" // So that "$a.b.c" is handled before "$a.b" and then "$a"
// Replace "$parent.child" before "$parent" so "$parent.child" doesn't become "parentValue.child" (which can't be matched later). // Replace "$parent.child" before "$parent" so "$parent.child" doesn't become "parentValue.child" (which can't be matched later).
found.sort((a, b) => b.length - a.length) console.log("FOUND PROD BEFORE SORT:", found)
found.sort((a, b) => {
return Number(b.length) - Number(a.length)
})
console.log("FOUND PROD AFTER SORT:", found)
//console.log("FOUND: ", found) //console.log("FOUND: ", found)
try { try {
@@ -983,19 +987,19 @@ const CodeEditor = (props) => {
var valuefound = false var valuefound = false
// First check if it's a workflow variable // First check if it's a workflow variable
if (actionlist !== undefined && actionlist.length > 0) { if (actionlist !== undefined && actionlist.length > 0) {
const workflowVar = actionlist?.find(item => const workflowVar = actionlist?.find(item =>
item.type === "workflow_variable" && item.type === "workflow_variable" &&
`$${item.autocomplete.toLowerCase()}` === fixedVariable.toLowerCase() `$${item.autocomplete.toLowerCase()}` === fixedVariable.toLowerCase()
) )
if (workflowVar && workflowVar.example) { if (workflowVar && workflowVar.example) {
valuefound = true valuefound = true
try { try {
// Try to parse the example value if it's stored as a JSON string // Try to parse the example value if it's stored as a JSON string
if (typeof workflowVar.example === "string" && if (typeof workflowVar.example === "string" &&
(workflowVar.example.startsWith("[") || workflowVar.example.startsWith("{"))) { (workflowVar.example.startsWith("[") || workflowVar.example.startsWith("{"))) {
const parsedExample = JSON.parse(workflowVar.example) const parsedExample = JSON.parse(workflowVar.example)
input = input.replace(found[i], JSON.stringify(parsedExample), -1) input = input.replace(found[i], JSON.stringify(parsedExample), -1)
} else { } else {
@@ -1029,7 +1033,7 @@ const CodeEditor = (props) => {
foundlocation = j foundlocation = j
break break
} }
// FIXME: There is something wrong here with: // FIXME: There is something wrong here with:
// $variable.# // $variable.#
// vs // vs
@@ -1069,7 +1073,7 @@ const CodeEditor = (props) => {
const replacedSlice = input.slice(foundlocation, input.length).replace(fixedVariable, newvalue, 1) const replacedSlice = input.slice(foundlocation, input.length).replace(fixedVariable, newvalue, 1)
input = input.slice(0, foundlocation) + replacedSlice input = input.slice(0, foundlocation) + replacedSlice
} }
} }
} catch (e) { } catch (e) {
console.log("Replace error: ", e) console.log("Replace error: ", e)
} }
@@ -1082,26 +1086,26 @@ const CodeEditor = (props) => {
var shouldbreak = false var shouldbreak = false
for (var k = 0; k < actionlist.length; k++) { for (var k = 0; k < actionlist.length; k++) {
var parsedPaths = [] var parsedPaths = []
// Handle both workflow variables and regular actions // Handle both workflow variables and regular actions
if (actionlist[k].type === "workflow_variable") { if (actionlist[k].type === "workflow_variable") {
// Try to parse the value if it's a string that could be JSON // Try to parse the value if it's a string that could be JSON
if (typeof actionlist[k].value === "string") { if (typeof actionlist[k].value === "string") {
try { try {
const parsedValue = JSON.parse(actionlist[k].value) const parsedValue = JSON.parse(actionlist[k].value)
if (typeof parsedValue === "object") { if (typeof parsedValue === "object") {
parsedPaths = GetParsedPaths(parsedValue, ""); parsedPaths = GetParsedPaths(parsedValue, "");
}
} catch (e) {
// Not valid JSON, use the value directly
parsedPaths = GetParsedPaths(actionlist[k].value, "");
} }
} else if (typeof actionlist[k].value === "object") { } catch (e) {
// Not valid JSON, use the value directly
parsedPaths = GetParsedPaths(actionlist[k].value, ""); parsedPaths = GetParsedPaths(actionlist[k].value, "");
} }
} else if (typeof actionlist[k].example === "object") { } else if (typeof actionlist[k].value === "object") {
parsedPaths = GetParsedPaths(actionlist[k].example, ""); parsedPaths = GetParsedPaths(actionlist[k].value, "");
} }
} else if (typeof actionlist[k].example === "object") {
parsedPaths = GetParsedPaths(actionlist[k].example, "");
}
for (var key in parsedPaths) { for (var key in parsedPaths) {
const fullpath = "$" + actionlist[k].autocomplete.toLowerCase() + parsedPaths[key].autocomplete.toLowerCase() const fullpath = "$" + actionlist[k].autocomplete.toLowerCase() + parsedPaths[key].autocomplete.toLowerCase()
@@ -1115,22 +1119,22 @@ const CodeEditor = (props) => {
var new_input = "" var new_input = ""
try { try {
const sourceData = actionlist[k].type === "workflow_variable" ? const sourceData = actionlist[k].type === "workflow_variable" ?
(() => { (() => {
// Try to parse the value if it's a JSON string // Try to parse the value if it's a JSON string
if (typeof actionlist[k].value === "string") { if (typeof actionlist[k].value === "string") {
try { try {
return JSON.parse(actionlist[k].value); return JSON.parse(actionlist[k].value);
} catch (e) { } catch (e) {
// If parsing fails, return the original string value // If parsing fails, return the original string value
return actionlist[k].value; return actionlist[k].value;
}
} }
} return actionlist[k].value;
return actionlist[k].value; })() :
})() : actionlist[k].example;
actionlist[k].example;
new_input = FindJsonPath(fullpath, sourceData)
new_input = FindJsonPath(fullpath, sourceData)
} catch (e) { } catch (e) {
console.log("ERR IN INPUT: ", e) console.log("ERR IN INPUT: ", e)
} }
@@ -1437,85 +1441,85 @@ const CodeEditor = (props) => {
return ( return (
<Draggable <Draggable
style={{ style={{
position: "absolute", position: "absolute",
zIndex: 15000, zIndex: 15000,
}} }}
onDrag={(e) => { onDrag={(e) => {
e.preventDefault() e.preventDefault()
// Check if inside div.ace_content // Check if inside div.ace_content
if (e.srcElement.className === "ace_content") { if (e.srcElement.className === "ace_content") {
// Input on the correct line. Each line is: // Input on the correct line. Each line is:
// Show some tooltip at mouse cursor that shows "Insert Action" // Show some tooltip at mouse cursor that shows "Insert Action"
// Append the text to the DOM // Append the text to the DOM
} else { } else {
//console.log("PAGEX: ", e.pageX, e.pageY) //console.log("PAGEX: ", e.pageX, e.pageY)
//console.log("OffsetX: ", e.offsetX, e.offsetY) //console.log("OffsetX: ", e.offsetX, e.offsetY)
//console.log("E: ", e) //console.log("E: ", e)
} }
if (!dragging) { if (!dragging) {
setDragging(true) setDragging(true)
} }
}} }}
onStop={(e) => { onStop={(e) => {
if (e.srcElement.className === "ace_content") { if (e.srcElement.className === "ace_content") {
console.log("DRAG STOP IN CONTENT!", e.srcElement.className) console.log("DRAG STOP IN CONTENT!", e.srcElement.className)
const usedposition = e.offsetY const usedposition = e.offsetY
if (usedposition === undefined || usedposition === null) { if (usedposition === undefined || usedposition === null) {
toast.info(`Error: LayerY is undefined or null. Please contact ${supportEmail}`) toast.info(`Error: LayerY is undefined or null. Please contact ${supportEmail}`)
return return
} }
if (usedposition === 0) { if (usedposition === 0) {
usedposition = 1 usedposition = 1
} }
const lineheight = 15 const lineheight = 15
const codedatasplit = localcodedata.split('\n') const codedatasplit = localcodedata.split('\n')
if (codedatasplit === undefined || codedatasplit === null || codedatasplit.length === 0) { if (codedatasplit === undefined || codedatasplit === null || codedatasplit.length === 0) {
return return
} }
// Int // Int
const lineposition = parseInt(usedposition/lineheight) const lineposition = parseInt(usedposition / lineheight)
// Find the correct line // Find the correct line
if (lineposition > codedatasplit.length) { if (lineposition > codedatasplit.length) {
codedatasplit[codedatasplit.length-1] += value codedatasplit[codedatasplit.length - 1] += value
} else { } else {
codedatasplit[lineposition] += value codedatasplit[lineposition] += value
} }
//e.srcElement.layerY //e.srcElement.layerY
setlocalcodedata(codedatasplit.join('\n')) setlocalcodedata(codedatasplit.join('\n'))
} }
setDragging(false) setDragging(false)
}} }}
dragging={dragging} dragging={dragging}
position={{ position={{
x: 0, x: 0,
y: 0, y: 0,
}} }}
onMouseHover={() => { onMouseHover={() => {
setHovering(true) setHovering(true)
}} }}
onMouseLeave={() => { onMouseLeave={() => {
setHovering(false) setHovering(false)
}} }}
> >
<div <div
style={{ style={{
cursor: dragging ? "grabbing" : "grab", cursor: dragging ? "grabbing" : "grab",
minWidth: 100, minWidth: 100,
border: "1px solid rgba(255,255,255,0.5)", border: "1px solid rgba(255,255,255,0.5)",
borderRadius: theme.palette.borderRadius/2, borderRadius: theme.palette.borderRadius / 2,
marginRight: 10, marginRight: 10,
padding: 5, padding: 5,
}} }}
> >
{value} {value}
@@ -1525,56 +1529,56 @@ const CodeEditor = (props) => {
} }
const IndentJsonLikeString = (input, indentSize = 2) => { const IndentJsonLikeString = (input, indentSize = 2) => {
const indent = ' '.repeat(indentSize); const indent = ' '.repeat(indentSize);
let level = 0; let level = 0;
let inString = false; let inString = false;
let escapeNext = false; let escapeNext = false;
let result = ''; let result = '';
for (let i = 0; i < input.length; i++) { for (let i = 0; i < input.length; i++) {
let char = input[i]; let char = input[i];
if (escapeNext) { if (escapeNext) {
result += char; result += char;
escapeNext = false; escapeNext = false;
continue; continue;
}
if (char === '\\') {
escapeNext = true;
result += char;
continue;
}
if (char === '"') {
inString = !inString;
result += char;
continue;
}
if (!inString) {
if (char === '{' || char === '[') {
result += char + '\n' + indent.repeat(++level);
continue;
} else if (char === '}' || char === ']') {
result += '\n' + indent.repeat(--level) + char;
continue;
} else if (char === ',') {
result += char + '\n' + indent.repeat(level);
continue;
} else if (char === ':') {
result += ': ';
continue;
} else if (char === ' ' || char === '\t' || char === '\n' || char === '\r') {
// Skip whitespace characters when not in string
continue;
}
}
result += char;
} }
if (char === '\\') { return result;
escapeNext = true;
result += char;
continue;
}
if (char === '"') {
inString = !inString;
result += char;
continue;
}
if (!inString) {
if (char === '{' || char === '[') {
result += char + '\n' + indent.repeat(++level);
continue;
} else if (char === '}' || char === ']') {
result += '\n' + indent.repeat(--level) + char;
continue;
} else if (char === ',') {
result += char + '\n' + indent.repeat(level);
continue;
} else if (char === ':') {
result += ': ';
continue;
} else if (char === ' ' || char === '\t' || char === '\n' || char === '\r') {
// Skip whitespace characters when not in string
continue;
}
}
result += char;
}
return result;
} }
@@ -1585,16 +1589,16 @@ const CodeEditor = (props) => {
return ( return (
<div style={{minHeight: 40, marginTop: 10, }}> <div style={{ minHeight: 40, marginTop: 10, }}>
<div style={{ <div style={{
cursor: "pointer", cursor: "pointer",
display: "flex", display: "flex",
position: "relative", position: "relative",
}} onClick={() => { }} onClick={() => {
setExpanded(!expanded) setExpanded(!expanded)
}}> }}>
<ValueBox name={innerdata?.name} value={innerdata?.value} /> <ValueBox name={innerdata?.name} value={innerdata?.value} />
<Typography style={{marginTop: 5, maxWidth: 150, maxHeight: 40, overflow: "hidden", }}> <Typography style={{ marginTop: 5, maxWidth: 150, maxHeight: 40, overflow: "hidden", }}>
{innerdata?.name} {innerdata?.name}
</Typography> </Typography>
</div> </div>
@@ -1622,8 +1626,8 @@ const CodeEditor = (props) => {
aria-labelledby="draggable-dialog-title" aria-labelledby="draggable-dialog-title"
// disableBackdropClick={true} // disableBackdropClick={true}
disableEnforceFocus={true} disableEnforceFocus={true}
style={{ style={{
pointerEvents: "none", pointerEvents: "none",
zIndex: activeDialog === "codeeditor" ? 1200 : 1100, zIndex: activeDialog === "codeeditor" ? 1200 : 1100,
}} }}
hideBackdrop={true} hideBackdrop={true}
@@ -1673,7 +1677,7 @@ const CodeEditor = (props) => {
</Tooltip> </Tooltip>
: null} : null}
{fullScreenModeEnabled ? null : {fullScreenModeEnabled ? null :
<Tooltip <Tooltip
color="primary" color="primary"
title={`Move window`} title={`Move window`}
@@ -1747,7 +1751,7 @@ const CodeEditor = (props) => {
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<div style={{ display: "flex" }}> <div style={{ display: "flex" }}>
{sourceDataOpen ? {sourceDataOpen ?
<div style={{ minWidth: 350, maxWidth: 350, marginLeft: 5, borderRight: "1px solid rgba(255,255,255,0.3)", paddingLeft: 5, overflow: "hidden", marginRight: 10, }}> <div style={{ minWidth: 350, maxWidth: 350, marginLeft: 5, borderRight: "1px solid rgba(255,255,255,0.3)", paddingLeft: 5, overflow: "hidden", marginRight: 10, }}>
<Typography variant="h6"> <Typography variant="h6">
Source Data Source Data
@@ -1781,7 +1785,7 @@ const CodeEditor = (props) => {
}; };
const handleActionHover = (inside, actionId) => { const handleActionHover = (inside, actionId) => {
}; };
const handleMouseover = () => { const handleMouseover = () => {
if (innerdata.type === "Execution Argument") { if (innerdata.type === "Execution Argument") {
@@ -1802,20 +1806,20 @@ const CodeEditor = (props) => {
var parsedPaths = []; var parsedPaths = [];
if (innerdata.type === "workflow_variable") { if (innerdata.type === "workflow_variable") {
// Try to parse the value if it's a string that could be JSON // Try to parse the value if it's a string that could be JSON
if (typeof innerdata.value === "string") { if (typeof innerdata.value === "string") {
try { try {
const parsedValue = JSON.parse(innerdata.value) const parsedValue = JSON.parse(innerdata.value)
if (typeof parsedValue === "object") { if (typeof parsedValue === "object") {
parsedPaths = GetParsedPaths(parsedValue, ""); parsedPaths = GetParsedPaths(parsedValue, "");
} }
} catch (e) { } catch (e) {
// Not valid JSON, use the value directly // Not valid JSON, use the value directly
parsedPaths = GetParsedPaths(innerdata.value, ""); parsedPaths = GetParsedPaths(innerdata.value, "");
} }
} else if (typeof innerdata.value === "object") { } else if (typeof innerdata.value === "object") {
parsedPaths = GetParsedPaths(innerdata.value, ""); parsedPaths = GetParsedPaths(innerdata.value, "");
} }
} else if (typeof innerdata.example === "object") { } else if (typeof innerdata.example === "object") {
parsedPaths = GetParsedPaths(innerdata.example, ""); parsedPaths = GetParsedPaths(innerdata.example, "");
} }
@@ -1830,7 +1834,7 @@ const CodeEditor = (props) => {
) )
})} })}
</div> </div>
: null} : null}
<div style={{ flex: 3, }}> <div style={{ flex: 3, }}>
{isFileEditor ? {isFileEditor ?
@@ -1858,7 +1862,7 @@ const CodeEditor = (props) => {
height: 50, height: 50,
width: 50, width: 50,
right: 25, right: 25,
top: 90, top: 90,
zIndex: 5000, zIndex: 5000,
}} }}
disabled={localcodedata === undefined || localcodedata === null || localcodedata.length === 0} disabled={localcodedata === undefined || localcodedata === null || localcodedata.length === 0}
@@ -1902,7 +1906,7 @@ const CodeEditor = (props) => {
{isFileEditor || isWorkflowEditor ? null : {isFileEditor || isWorkflowEditor ? null :
<div style={{ display: "flex", maxHeight: 40, }}> <div style={{ display: "flex", maxHeight: 40, }}>
<ButtonGroup style={{ borderRadius: theme.palette.borderRadius, }}> <ButtonGroup style={{ borderRadius: theme.palette.borderRadius, }}>
{userdata !== undefined && userdata !== null && userdata.support === true ? {userdata !== undefined && userdata !== null && userdata.support === true ?
<Button <Button
id="basic-button" id="basic-button"
aria-haspopup="true" aria-haspopup="true"
@@ -1919,9 +1923,9 @@ const CodeEditor = (props) => {
setSourceDataOpen(!sourceDataOpen) setSourceDataOpen(!sourceDataOpen)
}} }}
> >
<AddIcon /> Show Source Data <AddIcon /> Show Source Data
</Button> </Button>
: null} : null}
<Button <Button
id="basic-button" id="basic-button"
@@ -1976,7 +1980,7 @@ const CodeEditor = (props) => {
setAnchorEl3(event.currentTarget); setAnchorEl3(event.currentTarget);
}} }}
> >
Python Examples Python Examples
</Button> </Button>
<Button <Button
id="basic-button" id="basic-button"
@@ -2012,24 +2016,24 @@ const CodeEditor = (props) => {
> >
{pythonFilters.map((item, index) => { {pythonFilters.map((item, index) => {
return ( return (
<MenuItem <MenuItem
style={{ style={{
borderTop: item.name === "Use files" || (item.name.toLowerCase().includes("run") && item.name.toLowerCase().includes("subflow")) ? "2px solid rgba(255,255,255,0.3)" : "none", borderTop: item.name === "Use files" || (item.name.toLowerCase().includes("run") && item.name.toLowerCase().includes("subflow")) ? "2px solid rgba(255,255,255,0.3)" : "none",
}} }}
key={index} onClick={() => { key={index} onClick={() => {
if (item.disabled) { if (item.disabled) {
toast.error("This feature may not work in your environment until you update your Shuffle Tools app.", { autoClose: 10000 }) toast.error("This feature may not work in your environment until you update your Shuffle Tools app.", { autoClose: 10000 })
} }
if (selectedAction.name !== "execute_python") { if (selectedAction.name !== "execute_python") {
var newitem = JSON.parse(JSON.stringify(item)) var newitem = JSON.parse(JSON.stringify(item))
newitem.value = `{% python %}\n${item.value}\n{% endpython %}` newitem.value = `{% python %}\n${item.value}\n{% endpython %}`
handleClick(newitem) handleClick(newitem)
} else { } else {
handleClick(item) handleClick(item)
} }
}}>{item.name}</MenuItem> }}>{item.name}</MenuItem>
) )
})} })}
</Menu> </Menu>
@@ -2069,11 +2073,11 @@ const CodeEditor = (props) => {
) : innerdata.type === "workflow_variable" || ) : innerdata.type === "workflow_variable" ||
innerdata.type === "execution_variable" ? ( innerdata.type === "execution_variable" ? (
<FavoriteBorderIcon style={{ marginRight: 10 }} /> <FavoriteBorderIcon style={{ marginRight: 10 }} />
) : ) :
innerdata.type === "Shuffle DB" ? innerdata.type === "Shuffle DB" ?
<StorageIcon style={{ marginRight: 10, }} /> <StorageIcon style={{ marginRight: 10, }} />
: :
<ScheduleIcon style={{ marginRight: 10 }} /> <ScheduleIcon style={{ marginRight: 10 }} />
const handleExecArgumentHover = (inside) => { const handleExecArgumentHover = (inside) => {
var exec_text_field = document.getElementById( var exec_text_field = document.getElementById(
@@ -2110,20 +2114,20 @@ const CodeEditor = (props) => {
var parsedPaths = []; var parsedPaths = [];
if (innerdata.type === "workflow_variable") { if (innerdata.type === "workflow_variable") {
// Try to parse the value if it's a string that could be JSON // Try to parse the value if it's a string that could be JSON
if (typeof innerdata.value === "string") { if (typeof innerdata.value === "string") {
try { try {
const parsedValue = JSON.parse(innerdata.value) const parsedValue = JSON.parse(innerdata.value)
if (typeof parsedValue === "object") { if (typeof parsedValue === "object") {
parsedPaths = GetParsedPaths(parsedValue, ""); parsedPaths = GetParsedPaths(parsedValue, "");
} }
} catch (e) { } catch (e) {
// Not valid JSON, use the value directly // Not valid JSON, use the value directly
parsedPaths = GetParsedPaths(innerdata.value, ""); parsedPaths = GetParsedPaths(innerdata.value, "");
} }
} else if (typeof innerdata.value === "object") { } else if (typeof innerdata.value === "object") {
parsedPaths = GetParsedPaths(innerdata.value, ""); parsedPaths = GetParsedPaths(innerdata.value, "");
} }
} else if (typeof innerdata.example === "object") { } else if (typeof innerdata.example === "object") {
parsedPaths = GetParsedPaths(innerdata.example, ""); parsedPaths = GetParsedPaths(innerdata.example, "");
} }
@@ -2381,7 +2385,7 @@ const CodeEditor = (props) => {
</div> </div>
} }
<div <div
style={{ style={{
borderRadius: theme.palette?.borderRadius, borderRadius: theme.palette?.borderRadius,
position: "relative", position: "relative",
@@ -2393,7 +2397,7 @@ const CodeEditor = (props) => {
onDrop={(e) => { onDrop={(e) => {
console.log("DROP: ", e) console.log("DROP: ", e)
}} }}
> >
{(availableVariables !== undefined && availableVariables !== null && availableVariables.length > 0) || isFileEditor || isWorkflowEditor ? ( {(availableVariables !== undefined && availableVariables !== null && availableVariables.length > 0) || isFileEditor || isWorkflowEditor ? (
<AceEditor <AceEditor
id="shuffle-codeeditor" id="shuffle-codeeditor"
@@ -2421,7 +2425,7 @@ const CodeEditor = (props) => {
backgroundColor: "rgba(40,40,40,1)", backgroundColor: "rgba(40,40,40,1)",
zIndex: activeDialog === "codeeditor" ? 1200 : 1100, zIndex: activeDialog === "codeeditor" ? 1200 : 1100,
}} }}
onLoad={(editor) => { onLoad={(editor) => {
highlight_variables(localcodedata) highlight_variables(localcodedata)
@@ -2465,12 +2469,12 @@ const CodeEditor = (props) => {
</div> </div>
{isFileEditor || isWorkflowEditor ? null : {isFileEditor || isWorkflowEditor ? null :
<div style={{ <div style={{
flex: sourceDataOpen ? 1.5 : 3, flex: sourceDataOpen ? 1.5 : 3,
marginLeft: 5, marginLeft: 5,
borderLeft: "1px solid rgba(255,255,255,0.3)", borderLeft: "1px solid rgba(255,255,255,0.3)",
paddingLeft: 5, paddingLeft: 5,
overflow: "hidden", overflow: "hidden",
transitions: "all 1s ease-in-out", transitions: "all 1s ease-in-out",
}}> }}>
<div> <div>
@@ -2486,59 +2490,59 @@ const CodeEditor = (props) => {
}} }}
> >
<div> <div>
{actionId === null && triggerId === null ? {actionId === null && triggerId === null ?
<div style={{display: "flex", alignItems: "center"}}> <div style={{ display: "flex", alignItems: "center" }}>
{`Condition ${selectedEdge?.conditions?.findIndex(cond => cond.condition.id === conditionId) + 1 || "0"}`} {`Condition ${selectedEdge?.conditions?.findIndex(cond => cond.condition.id === conditionId) + 1 || "0"}`}
{/* Source node image */} {/* Source node image */}
{selectedEdge?.source ? {selectedEdge?.source ?
<img <img
src={sourceImage || ""} src={sourceImage || ""}
alt="Source" alt="Source"
style={{ style={{
width: 30, width: 30,
height: 30, height: 30,
marginRight: 10, marginRight: 10,
borderRadius: "50%", borderRadius: "50%",
marginLeft: 10, marginLeft: 10,
border: conditionField === "source" ? `3px solid #FF8544` : null, border: conditionField === "source" ? `3px solid #FF8544` : null,
}} }}
/> />
: null : null
} }
{/* Add arrow icon */} {/* Add arrow icon */}
{ {
selectedEdge && Object.keys(selectedEdge).length > 0 ? selectedEdge && Object.keys(selectedEdge).length > 0 ?
<ArrowForwardIcon style={{ <ArrowForwardIcon style={{
color: theme.palette.textPrimary, color: theme.palette.textPrimary,
fontSize: 18, fontSize: 18,
marginLeft: -5, marginLeft: -5,
marginRight: -5, marginRight: -5,
}} /> }} />
: null : null
} }
{/* Destination node image */} {/* Destination node image */}
{selectedEdge?.target ? {selectedEdge?.target ?
<img <img
src={targetImage || ""} src={targetImage || ""}
alt="Destination" alt="Destination"
style={{ style={{
width: 30, width: 30,
height: 30, height: 30,
marginLeft: 10, marginLeft: 10,
borderRadius: "50%", borderRadius: "50%",
border: conditionField === "destination" ? `3px solid #FF8544` : null, border: conditionField === "destination" ? `3px solid #FF8544` : null,
}} }}
/> />
: null : null
} }
</div> </div>
: :
<span style={{ color: theme.palette.text.primary }}> <span style={{ color: theme.palette.text.primary }}>
{selectedAction.name === "execute_python" || selectedAction.name === "execute_bash" ? {selectedAction.name === "execute_python" || selectedAction.name === "execute_bash" ?
"Code to run" : "Code to run" :
triggerId ? triggerId ?
`Output: ${triggerName?.replaceAll("_", " ").slice(0, 1).toUpperCase() + triggerName?.replaceAll("_", " ").slice(1)} (${triggerField})` : `Output: ${triggerName?.replaceAll("_", " ").slice(0, 1).toUpperCase() + triggerName?.replaceAll("_", " ").slice(1)} (${triggerField})` :
`Output: ${appName?.replaceAll("_", " ").slice(0, 1).toUpperCase() + appName?.replaceAll("_", " ").slice(1)} (${fieldName})` `Output: ${appName?.replaceAll("_", " ").slice(0, 1).toUpperCase() + appName?.replaceAll("_", " ").slice(1)} (${fieldName})`
} }
@@ -2570,7 +2574,7 @@ const CodeEditor = (props) => {
backdropFilter: "blur(8px)", backdropFilter: "blur(8px)",
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08)", boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08)",
transition: "all 0.2s ease", transition: "all 0.2s ease",
paddingRight: 20, paddingRight: 20,
color: "#FF8544", color: "#FF8544",
borderRadius: theme.palette?.borderRadius, borderRadius: theme.palette?.borderRadius,
"&:hover": { "&:hover": {
@@ -2592,18 +2596,18 @@ const CodeEditor = (props) => {
<span> <span>
<PlayArrowIcon style={{ height: 18, width: 18, marginBottom: -4, marginLeft: 5, }} /> <PlayArrowIcon style={{ height: 18, width: 18, marginBottom: -4, marginLeft: 5, }} />
{selectedAction === undefined ? <Typography style={{color: "inherit"}}>Try it</Typography> : selectedAction.name === "execute_python" ? "Run Python Code" : selectedAction.name === "execute_bash" ? "Run Bash" : "Try it"} {selectedAction === undefined ? <Typography style={{ color: "inherit" }}>Try it</Typography> : selectedAction.name === "execute_python" ? "Run Python Code" : selectedAction.name === "execute_bash" ? "Run Bash" : "Try it"}
<span <span
style={{ style={{
color: "#C8C8C8", color: "#C8C8C8",
fontSize: "12px", fontSize: "12px",
whiteSpace: "nowrap", whiteSpace: "nowrap",
marginLeft: 5, marginLeft: 5,
marginRight: 10, marginRight: 10,
}} }}
> >
<kbd>Ctrl</kbd> + <kbd><KeyboardReturnIcon style={{width: 13, position: "absolute", marginLeft: 3, top: 5, }}/></kbd> <kbd>Ctrl</kbd> + <kbd><KeyboardReturnIcon style={{ width: 13, position: "absolute", marginLeft: 3, top: 5, }} /></kbd>
</span> </span>
</span> </span>
} }
@@ -2713,7 +2717,7 @@ const CodeEditor = (props) => {
Output is based on the last VALID run of the node(s) you are referencing. Refresh the page to get updated Variable values.&nbsp; Output is based on the last VALID run of the node(s) you are referencing. Refresh the page to get updated Variable values.&nbsp;
{selectedAction?.name === "execute_python" ? {selectedAction?.name === "execute_python" ?
"For Python: exit() to stop a python script ANYWHERE." "For Python: exit() to stop a python script ANYWHERE."
: null} : null}
</Typography> </Typography>
<Typography variant="body2" style={{ maxHeight: 150, overflow: "auto", marginTop: 20, }}> <Typography variant="body2" style={{ maxHeight: 150, overflow: "auto", marginTop: 20, }}>
No test output yet. No test output yet.
@@ -2735,7 +2739,7 @@ const CodeEditor = (props) => {
</div> </div>
<div style={{ display: 'flex', width: fullScreenModeEnabled ? "92%" : isWorkflowEditor ? "90%" : "100%", }}> <div style={{ display: 'flex', width: fullScreenModeEnabled ? "92%" : isWorkflowEditor ? "90%" : "100%", }}>
<Button <Button
style={{ style={{
height: 35, height: 35,
@@ -2758,7 +2762,7 @@ const CodeEditor = (props) => {
<Button <Button
variant="contained" variant="contained"
color="primary" color="primary"
disabled={isWorkflowEditor} disabled={isWorkflowEditor}
style={{ style={{
height: 35, height: 35,
flex: 1, flex: 1,