Workflow Action Rerun optimization
This commit is contained in:
@@ -545,6 +545,8 @@ const EditWorkflow = (props) => {
|
||||
}}
|
||||
>
|
||||
<FormControlLabel value="test" control={<Radio />} label="Test" />
|
||||
<FormControlLabel value="staging" control={<Radio />} label="Staging" />
|
||||
<FormControlLabel value="preprod" control={<Radio />} label="Pre-production" />
|
||||
<FormControlLabel value="production" control={<Radio />} label="Production" />
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
@@ -1363,6 +1363,7 @@ const Navbar = (props) => {
|
||||
sx={buttonStyles}
|
||||
onClick={() => {
|
||||
if(isCloud) {
|
||||
// navigate("/new-pricing");
|
||||
navigate("/pricing");
|
||||
ReactGA.event({
|
||||
category: "navbar",
|
||||
@@ -1370,7 +1371,7 @@ const Navbar = (props) => {
|
||||
label: "go_to_pricing",
|
||||
})
|
||||
} else {
|
||||
window.open("https://shuffler.io/pricing", '_blank');
|
||||
window.open("https://shuffler.io/pricing?env=Self-hosted", '_blank');
|
||||
return;
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -179,6 +179,7 @@ const ParsedAction = (props) => {
|
||||
|
||||
suborgWorkflows,
|
||||
originalWorkflow,
|
||||
runFromHere,
|
||||
} = props;
|
||||
|
||||
let navigate = useNavigate()
|
||||
@@ -233,11 +234,16 @@ const ParsedAction = (props) => {
|
||||
// auth, required, optional
|
||||
var changed = false
|
||||
if (selectedActionParameters === undefined || selectedActionParameters === null || selectedActionParameters.length === 0) {
|
||||
console.log("Returning because no params")
|
||||
return
|
||||
}
|
||||
|
||||
if (selectedApp !== undefined && selectedApp !== null && selectedApp.generated !== true) {
|
||||
return
|
||||
|
||||
if (isAgent || isIntegration) {
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Fixing required fields with a shitty structure :)
|
||||
@@ -346,13 +352,23 @@ const ParsedAction = (props) => {
|
||||
// 3. generated fields & all else
|
||||
|
||||
|
||||
const newparams = auth
|
||||
var newparams = auth
|
||||
.concat(bodyfield)
|
||||
.concat(required)
|
||||
.concat(generated_optional)
|
||||
.concat(special_optional)
|
||||
.concat(optional)
|
||||
|
||||
const dedupedParams = []
|
||||
for (var paramKey in newparams) {
|
||||
const param = newparams[paramKey]
|
||||
if (dedupedParams.find(item => item.name === param.name) === undefined) {
|
||||
dedupedParams.push(param)
|
||||
}
|
||||
}
|
||||
|
||||
newparams = dedupedParams
|
||||
|
||||
var newkeyorder = []
|
||||
for (let paramkey in newparams) {
|
||||
//console.log("Param: ", newparams[paramkey])
|
||||
@@ -1814,6 +1830,29 @@ const ParsedAction = (props) => {
|
||||
</Tooltip>
|
||||
</IconButton>
|
||||
|
||||
<Button
|
||||
color="secondary"
|
||||
variant="outlined"
|
||||
style={{
|
||||
marginTop: "auto",
|
||||
marginBottom: "auto",
|
||||
height: 30,
|
||||
marginLeft: 115,
|
||||
textTransform: "none",
|
||||
}}
|
||||
disabled={autoCompleting}
|
||||
onClick={() => {
|
||||
if (runFromHere !== undefined) {
|
||||
runFromHere(selectedAction)
|
||||
} else {
|
||||
toast.error("Function not available. Please contact support@shuffler.io")
|
||||
}
|
||||
}}
|
||||
>
|
||||
<PlayArrowIcon style={{marginRight: 5, }}/>
|
||||
Rerun
|
||||
</Button>
|
||||
|
||||
{(selectedAction?.generated === true && selectedAction?.app_version === "1.0.0") || (selectedAction?.app_name === "Shuffle Tools" && selectedAction?.app_version !== "1.2.0") ?
|
||||
<Button
|
||||
variant="contained"
|
||||
@@ -1875,12 +1914,12 @@ const ParsedAction = (props) => {
|
||||
toast.success("Changed version of all nodes to " + event.target.value)
|
||||
}}
|
||||
style={{
|
||||
marginTop: 10,
|
||||
position: "absolute",
|
||||
top: 10, right: 10,
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
color: "white",
|
||||
height: 35,
|
||||
marginleft: 10,
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
}}
|
||||
SelectDisplayProps={{
|
||||
@@ -4120,15 +4159,12 @@ const ParsedAction = (props) => {
|
||||
fullWidth
|
||||
id={"rightside_field_" + count}
|
||||
onChange={(e) => {
|
||||
console.log("MULTI SELECT: ", multi, e.target.value)
|
||||
|
||||
changeActionParameter(e, count, data);
|
||||
setUpdate(Math.random());
|
||||
}}
|
||||
style={{
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
color: "white",
|
||||
height: "50px",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
height: 40,
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
}}
|
||||
>
|
||||
@@ -4685,8 +4721,9 @@ const ParsedAction = (props) => {
|
||||
</Tooltip>
|
||||
: null}
|
||||
|
||||
<Tooltip title="Expand editor window" placement="top">
|
||||
|
||||
{((data.options !== undefined && data.options !== null && data.options.length > 0) || (selectedActionParameters[count].options !== undefined && selectedActionParameters[count].options !== null && selectedActionParameters[count].options.length > 0)) ? null :
|
||||
<Tooltip title="Expand editor window" placement="top">
|
||||
<OpenInFullIcon
|
||||
style={{ color: "rgba(255,255,255,0.7)", cursor: "pointer", margin: multiline ? 5 : 0, height: 20, width: 20, }}
|
||||
onMouseOver={(event) => {
|
||||
@@ -4728,6 +4765,7 @@ const ParsedAction = (props) => {
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
}
|
||||
|
||||
|
||||
</div>
|
||||
@@ -4737,6 +4775,7 @@ const ParsedAction = (props) => {
|
||||
showDropdownNumber === count &&
|
||||
data.variant === "STATIC_VALUE" &&
|
||||
jsonList.length > 0 ? (
|
||||
|
||||
<FormControl fullWidth style={{ marginTop: 0 }}>
|
||||
<InputLabel
|
||||
id="action-autocompleter"
|
||||
|
||||
@@ -46,6 +46,7 @@ import {
|
||||
DragIndicator as DragIndicatorIcon,
|
||||
RestartAlt as RestartAltIcon,
|
||||
ArrowForward as ArrowForwardIcon,
|
||||
KeyboardReturn as KeyboardReturnIcon,
|
||||
} from '@mui/icons-material';
|
||||
|
||||
|
||||
@@ -94,9 +95,12 @@ const pythonFilters = [
|
||||
{ "name": "Get full execution details", "value": `print(self.full_execution)`, "example": `` },
|
||||
{ "name": "Use files", "value": `# Create a sample file\nfiles = [{\n \"filename\": \"test.txt\",\n \"data\": \"Testdata\"\n}]\nret = self.set_files(files)\n\n# Get the content of the file from Shuffle storage\n# Originally a byte string in the \"data\" key\nfile_content = (self.get_file(ret[0])[\"data\"]).decode()\nprint(file_content)`, "example": `` },
|
||||
|
||||
{ "name": "Use datastore", "value": `key = \"testkey\"\nvalue = \"The value of the testkey\"\n\nself.set_cache(key, value)\n\n# Print the details of the key after it's been updated\n# To get the value, use self.get_cache(key)[\"value\"]\nprint(self.get_cache(key))`, "example": `` },
|
||||
{ "name": "Run an App Action", "value": `response = shuffle.run_app(app_id="app", action="action_name", auth="authentication_id", params={})\nprint(response)`, "example": ``, "disabled": true, },
|
||||
{ "name": "Run a Singul AI Action", "value": `response = singul.create_ticket(app="jira/iris/ticketingsystem", fields={"title": "Test ticket!"})\nprint(response)`, "example": ``, "disabled": true, },
|
||||
{ "name": "Use datastore", "value": `key = \"testkey\"\nvalue = \"The value of the testkey\"\n\nself.set_key(key, value)\n\n# Print the details of the key after it's been updated\n# To get the value, use self.get_key(key)[\"value\"]\nprint(self.get_key(key))`, "example": `` },
|
||||
|
||||
{ "name": "Run a Subflow", "value": `response = shuffle.run_workflow(workflow_id="", start_command="Runtime arg here!", wait=True)\nprint(response)`, "example": ``, "disabled": false, },
|
||||
{ "name": "Run an App Action", "value": `response = shuffle.run_app(app_id="app", action="action_name", auth="authentication_id", params={})\nprint(response)`, "example": ``, "disabled": false, },
|
||||
{ "name": "Run a Singul AI Action", "value": `response = singul.cases.create_ticket(app="jira", fields={"title": "Test ticket!"})\nprint(response)`, "example": ``, "disabled": false, },
|
||||
|
||||
|
||||
]
|
||||
|
||||
@@ -299,8 +303,19 @@ const CodeEditor = (props) => {
|
||||
setMainVariables(tmpVariables)
|
||||
}
|
||||
|
||||
const handleKeyDown = (event) => {
|
||||
if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {
|
||||
event.preventDefault()
|
||||
const tryItButton = document.getElementById("try-it-button")
|
||||
if (tryItButton !== undefined && tryItButton !== null) {
|
||||
tryItButton.click()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the original useEffect for actionlist since we'll update on action/trigger changes
|
||||
useEffect(() => {
|
||||
document.addEventListener("keydown", handleKeyDown)
|
||||
updateAvailableVariables(actionlist)
|
||||
}, [])
|
||||
|
||||
@@ -1721,13 +1736,13 @@ const CodeEditor = (props) => {
|
||||
color="secondary"
|
||||
style={{
|
||||
textTransform: "none",
|
||||
width: 120,
|
||||
width: 145,
|
||||
}}
|
||||
onClick={(event) => {
|
||||
setAnchorEl3(event.currentTarget);
|
||||
}}
|
||||
>
|
||||
Python Code
|
||||
Python Examples
|
||||
</Button>
|
||||
<Button
|
||||
id="basic-button"
|
||||
@@ -1762,7 +1777,12 @@ const CodeEditor = (props) => {
|
||||
>
|
||||
{pythonFilters.map((item, index) => {
|
||||
return (
|
||||
<MenuItem key={index} onClick={() => {
|
||||
<MenuItem
|
||||
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",
|
||||
|
||||
}}
|
||||
key={index} onClick={() => {
|
||||
if (item.disabled) {
|
||||
toast.error("This feature may not work in your environment until you update your Shuffle Tools app.", { autoClose: 10000 })
|
||||
}
|
||||
@@ -2270,6 +2290,7 @@ const CodeEditor = (props) => {
|
||||
<div style={{}}>
|
||||
<Tooltip title="Try it! This runs the Shuffle Tools 'repeat back to me' or 'execute python' action with what you see in the expected output window. Commonly used to test your Python scripts or Liquid filters, not requiring the full workflow to run again." placement="top">
|
||||
<Button
|
||||
id="try-it-button"
|
||||
variant="outlined"
|
||||
disabled={executing}
|
||||
color="primary"
|
||||
@@ -2283,11 +2304,13 @@ const CodeEditor = (props) => {
|
||||
zIndex: 1200,
|
||||
fontWeight: 500,
|
||||
fontSize: 14,
|
||||
textTransform: "none",
|
||||
backgroundColor: "rgba(33, 33, 33, 0.95)",
|
||||
backdropFilter: "blur(8px)",
|
||||
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08)",
|
||||
transition: "all 0.2s ease",
|
||||
borderRadius: "4px",
|
||||
paddingRight: 20,
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
"&:hover": {
|
||||
backgroundColor: "rgba(45, 45, 45, 0.95)",
|
||||
transform: "translateY(-1px)",
|
||||
@@ -2304,7 +2327,23 @@ const CodeEditor = (props) => {
|
||||
{executing ?
|
||||
<CircularProgress style={{ height: 18, width: 18, }} />
|
||||
:
|
||||
<span>{selectedAction === undefined ? "Try it" : selectedAction.name === "execute_python" ? "Run Python Code" : selectedAction.name === "execute_bash" ? "Run Bash" : "Try it"}<PlayArrowIcon style={{ height: 18, width: 18, marginBottom: -4, marginLeft: 5, }} /> </span>
|
||||
<span>
|
||||
|
||||
<PlayArrowIcon style={{ height: 18, width: 18, marginBottom: -4, marginLeft: 5, }} />
|
||||
{selectedAction === undefined ? "Try it" : selectedAction.name === "execute_python" ? "Run Python Code" : selectedAction.name === "execute_bash" ? "Run Bash" : "Try it"}
|
||||
<span
|
||||
style={{
|
||||
color: "#C8C8C8",
|
||||
fontSize: "12px",
|
||||
whiteSpace: "nowrap",
|
||||
marginLeft: 5,
|
||||
marginRight: 10,
|
||||
}}
|
||||
>
|
||||
<kbd>Ctrl</kbd> + <kbd><KeyboardReturnIcon style={{width: 13, position: "absolute", marginLeft: 3, top: 5, }}/></kbd>
|
||||
</span>
|
||||
|
||||
</span>
|
||||
}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
|
||||
+11
-11
@@ -27,7 +27,7 @@ const theme = createTheme(adaptV4Theme({
|
||||
distributionColor: "#40E0D0",
|
||||
|
||||
green: "#5cc879",
|
||||
borderRadius: 10,
|
||||
borderRadius: 8,
|
||||
defaultBorder: "1px solid rgba(255,255,255,0.3)",
|
||||
|
||||
//jsonTheme: "brewer",
|
||||
@@ -112,39 +112,39 @@ const theme = createTheme(adaptV4Theme({
|
||||
MuiCssBaseline: {
|
||||
styleOverrides: `
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-weight: 300;
|
||||
src: local('Roboto Light'), local('Roboto-Light');
|
||||
src: local('Inter Light'), local('Inter-Light');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-weight: 400;
|
||||
src: local('Roboto'), local('Roboto-Regular');
|
||||
src: local('Inter Regular'), local('Inter-Regular');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-weight: 500;
|
||||
src: local('Roboto Medium'), local('Roboto-Medium');
|
||||
src: local('Inter Medium'), local('Inter-Medium');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-weight: 600;
|
||||
src: local('Roboto SemiBold'), local('Roboto-SemiBold');
|
||||
src: local('Inter SemiBold'), local('Inter-SemiBold');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-weight: 700;
|
||||
src: local('Roboto Bold'), local('Roboto-Bold');
|
||||
src: local('Inter Bold'), local('Inter-Bold');
|
||||
}
|
||||
`,
|
||||
},
|
||||
|
||||
@@ -652,6 +652,31 @@ const AngularWorkflow = (defaultprops) => {
|
||||
],
|
||||
"multiselect": true,
|
||||
},
|
||||
{
|
||||
"name": "memory",
|
||||
"value": "",
|
||||
"required": true,
|
||||
"description": "Whether to store the conversation in memory",
|
||||
"options": [
|
||||
"Nothing",
|
||||
"Shuffle Datastore",
|
||||
],
|
||||
"multiselect": false,
|
||||
"disabled": true,
|
||||
},
|
||||
{
|
||||
"name": "knowledge",
|
||||
"value": "",
|
||||
"required": true,
|
||||
"description": "The knowledge we should inject into the context window",
|
||||
"options": [
|
||||
"Nothing",
|
||||
"Shuffle Files",
|
||||
],
|
||||
"multiselect": false,
|
||||
"disabled": true,
|
||||
},
|
||||
|
||||
]
|
||||
}],
|
||||
large_image: theme.palette.singulBlackWhite,
|
||||
@@ -772,7 +797,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
|
||||
const [loadedApps, setLoadedApps] = React.useState([])
|
||||
|
||||
const loadAppConfig = (appId, select) => {
|
||||
const loadAppConfig = (appId, select, skipAppLoad) => {
|
||||
if (appId === undefined || appId === null || appId.length === 0) {
|
||||
console.log("No appId to load")
|
||||
return
|
||||
@@ -868,7 +893,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
setSelectedApp(foundapp)
|
||||
}
|
||||
|
||||
if (apps === undefined || apps === null || apps.length === 0) {
|
||||
if ((apps === undefined || apps === null || apps.length === 0) && skipAppLoad !== true) {
|
||||
console.log("No apps to update :(")
|
||||
getApps()
|
||||
return
|
||||
@@ -2785,6 +2810,94 @@ const AngularWorkflow = (defaultprops) => {
|
||||
return true;
|
||||
};
|
||||
|
||||
const runFromHere = (curAction) => {
|
||||
if (curAction.app_id === undefined || curAction.app_id === null || curAction.app_id.length === 0) {
|
||||
toast.error("No app id found for action. Please contact support@shuffler.io if this persists")
|
||||
return
|
||||
}
|
||||
|
||||
if (workflow.id !== undefined && workflow.id !== null && workflow.id.length > 0) {
|
||||
curAction.source_workflow = workflow.id
|
||||
}
|
||||
|
||||
// Based on the previous execution id
|
||||
console.log("WORKFLOW EXEC: ", workflowExecutions)
|
||||
// Look for the "execution_id" parameter
|
||||
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
||||
const execFound = new URLSearchParams(cursearch).get("execution_id");
|
||||
if (execFound !== undefined && execFound !== null && execFound.length > 0) {
|
||||
toast.info("Rerunning based on previously watched execution id")
|
||||
curAction.source_execution = execFound
|
||||
} else if (workflowExecutions !== undefined && workflowExecutions !== null && workflowExecutions.length > 0) {
|
||||
curAction.source_execution = workflowExecutions[0].execution_id
|
||||
} else {
|
||||
toast.error("No previous execution found. Please run the workflow first.")
|
||||
return
|
||||
}
|
||||
|
||||
setExecutionRunning(true)
|
||||
setExecutionRequestStarted(true)
|
||||
var headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
}
|
||||
|
||||
if (workflow.org_id !== undefined && workflow.org_id !== null && workflow.org_id.length > 0) {
|
||||
headers["Org-Id"] = workflow.org_id
|
||||
}
|
||||
|
||||
// Rerun makes it return execution_id + authorization
|
||||
const appRunUrl = `${globalUrl}/api/v1/apps/${curAction.app_id}/run?rerun=true`
|
||||
fetch(appRunUrl, {
|
||||
method: 'POST',
|
||||
headers: headers,
|
||||
body: JSON.stringify(curAction),
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => {
|
||||
setExecutionRunning(false)
|
||||
setExecutionRequestStarted(false)
|
||||
|
||||
if (response.status !== 200) {
|
||||
console.log("Status not 200 for stream results :O!")
|
||||
}
|
||||
|
||||
return response.json()
|
||||
})
|
||||
.then((responseJson) => {
|
||||
setExecutionRequestStarted(false)
|
||||
|
||||
if (responseJson?.success === false) {
|
||||
setExecutionRunning(false)
|
||||
|
||||
if (responseJson?.reason !== undefined && responseJson?.reason !== null && responseJson?.reason.length > 0) {
|
||||
toast.error(responseJson.reason)
|
||||
} else {
|
||||
toast.error("Failed to run the action. Please try again or contact support@shuffler.io")
|
||||
}
|
||||
|
||||
return
|
||||
} else if (responseJson?.success === true && responseJson?.execution_id !== undefined && responseJson?.execution_id !== null && responseJson?.execution_id.length > 0) {
|
||||
navigate(`?execution_id=${responseJson.execution_id}`)
|
||||
setExecutionRequest({
|
||||
execution_id: responseJson.execution_id,
|
||||
authorization: responseJson.authorization,
|
||||
})
|
||||
|
||||
setExecutionData({})
|
||||
setExecutionModalOpen(true)
|
||||
setExecutionModalView(1)
|
||||
start()
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
toast.error("Failed to run the action. "+error.toString())
|
||||
|
||||
setExecutionRunning(false)
|
||||
setExecutionRequestStarted(false)
|
||||
})
|
||||
}
|
||||
|
||||
const executeWorkflow = (executionArgument, startNode, hasSaved, skip_popup) => {
|
||||
|
||||
if (hasSaved === false) {
|
||||
@@ -3203,6 +3316,13 @@ const AngularWorkflow = (defaultprops) => {
|
||||
return
|
||||
}
|
||||
|
||||
for (var key in responseJson) {
|
||||
const curapp = responseJson[key]
|
||||
if (curapp?.actions === undefined || curapp?.actions === null || curapp?.actions?.length === 0 || curapp?.actions?.length === 1) {
|
||||
loadAppConfig(curapp?.id, false, true)
|
||||
}
|
||||
}
|
||||
|
||||
// Find app with ID "794e51c3c1a8b24b89ccc573a3defc47" (gmail) to force-break it,
|
||||
// Find app with ID "3e2bdf9d5069fe3f4746c29d68785a6a" (shuffle tools) to force-break it,
|
||||
// as to ensure the autocorrect works.
|
||||
@@ -13580,14 +13700,18 @@ const AngularWorkflow = (defaultprops) => {
|
||||
setSourceValue({
|
||||
...sourceValue,
|
||||
value: value
|
||||
});
|
||||
})
|
||||
|
||||
setUpdate(Math.random())
|
||||
} else if (fieldType === "destination") {
|
||||
setDestinationValue({
|
||||
...destinationValue,
|
||||
value: value
|
||||
});
|
||||
}
|
||||
};
|
||||
})
|
||||
|
||||
setUpdate(Math.random())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const conditionsModal = (
|
||||
@@ -14763,6 +14887,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
]
|
||||
|
||||
const handleSubflowParamChange = (triggerId, triggerField, newData) => {
|
||||
var updateFail = ""
|
||||
|
||||
if (workflow !== undefined && workflow !== null) {
|
||||
// Find the trigger with matching id
|
||||
@@ -14778,9 +14903,20 @@ const AngularWorkflow = (defaultprops) => {
|
||||
setWorkflow(workflow);
|
||||
setSelectedTriggerValue(newData)
|
||||
setLastSaved(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
setUpdate(Math.random())
|
||||
} else {
|
||||
updateFail = "Parameter is undefined or null"
|
||||
}
|
||||
} else {
|
||||
updateFail = "Trigger is undefined or null"
|
||||
}
|
||||
} else {
|
||||
updateFail = "Workflow is undefined or null"
|
||||
}
|
||||
|
||||
if (updateFail !== "") {
|
||||
toast.error(updateFail + " - Failed to update subflow parameter value. Please try again.")
|
||||
}
|
||||
}
|
||||
|
||||
const SubflowSidebar = Object.getOwnPropertyNames(selectedTrigger).length === 0 || workflow.triggers[selectedTriggerIndex] === undefined || selectedTrigger.trigger_type !== "SUBFLOW" ? null :
|
||||
@@ -20801,9 +20937,9 @@ const AngularWorkflow = (defaultprops) => {
|
||||
onClose={() => {
|
||||
setExecutionModalOpen(false)
|
||||
|
||||
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
||||
const newitem = removeParam("execution_id", cursearch);
|
||||
navigate(curpath + newitem)
|
||||
//const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
||||
//const newitem = removeParam("execution_id", cursearch);
|
||||
//navigate(curpath + newitem)
|
||||
}}
|
||||
style={{
|
||||
resize: "both",
|
||||
@@ -21256,7 +21392,11 @@ const AngularWorkflow = (defaultprops) => {
|
||||
<h2>Details</h2>
|
||||
<Tooltip
|
||||
color="primary"
|
||||
title="Rerun workflow (uses same startnode as the original)"
|
||||
title={
|
||||
<Typography variant="body1">
|
||||
Rerun workflow. Uses same startnode as the original. Runs from scratch.
|
||||
</Typography>
|
||||
}
|
||||
placement="top"
|
||||
style={{ zIndex: 50000 }}
|
||||
>
|
||||
@@ -21558,7 +21698,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
</div>
|
||||
: null}
|
||||
|
||||
{userdata.support === true && executionData.workflow !== undefined && executionData.workflow !== null && executionData.status !== "EXECUTING" ?
|
||||
{userdata.support === true && executionData.workflow !== undefined && executionData.workflow !== null && executionData.status !== "EXECUTING" && executionData.status !== "ABORTED" ?
|
||||
<div style={{ marginTop: 5, marginBottom: 5, }}>
|
||||
<WorkflowValidationTimeline
|
||||
originalWorkflow={workflow}
|
||||
@@ -22857,6 +22997,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
|
||||
suborgWorkflows={suborgWorkflows}
|
||||
originalWorkflow={originalWorkflow}
|
||||
runFromHere={runFromHere}
|
||||
/>
|
||||
</div>
|
||||
</Fade>
|
||||
@@ -24731,6 +24872,8 @@ const AngularWorkflow = (defaultprops) => {
|
||||
}
|
||||
|
||||
const handleActionParamChange = (actionId, fieldName, newData) => {
|
||||
var updateFail = ""
|
||||
|
||||
if (workflow !== undefined) {
|
||||
// Find the action with matching id
|
||||
const actionIndex = workflow?.actions.findIndex(action => action.id === actionId);
|
||||
@@ -24745,9 +24888,20 @@ const AngularWorkflow = (defaultprops) => {
|
||||
// Update workflow state to trigger re-render
|
||||
setWorkflow({...workflow});
|
||||
setLastSaved(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
setUpdate(Math.random())
|
||||
} else {
|
||||
updateFail = "Parameter is undefined or null"
|
||||
}
|
||||
} else {
|
||||
updateFail = "Trigger is undefined or null"
|
||||
}
|
||||
} else {
|
||||
updateFail = "Workflow is undefined or null"
|
||||
}
|
||||
|
||||
if (updateFail !== "") {
|
||||
toast.error(updateFail + " - Failed to update subflow parameter value. Please try again.")
|
||||
}
|
||||
}
|
||||
/*
|
||||
var foundusecase = {}
|
||||
|
||||
@@ -1088,14 +1088,13 @@ const AppExplorer = (props) => {
|
||||
setNewWorkflowTags(newWorkflowTags);
|
||||
}
|
||||
|
||||
// This is annoying (:
|
||||
var securitySchemes = data.components.securityDefinitions;
|
||||
var securitySchemes = data?.components?.securityDefinitions;
|
||||
if (securitySchemes === undefined) {
|
||||
securitySchemes = data.securitySchemes;
|
||||
securitySchemes = data?.securitySchemes;
|
||||
}
|
||||
|
||||
if (securitySchemes === undefined) {
|
||||
securitySchemes = data.components.securitySchemes;
|
||||
securitySchemes = data?.components?.securitySchemes;
|
||||
}
|
||||
|
||||
const allowedfunctions = [
|
||||
@@ -1681,7 +1680,7 @@ const AppExplorer = (props) => {
|
||||
setExecutionResult({
|
||||
valid: false,
|
||||
result:
|
||||
"Couldn't finish execution (2). Please fill all the required fields, and validate the execution.",
|
||||
"Couldn't finish execution OR no result was returned (2). Please fill all the required fields, and validate the execution.",
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -343,10 +343,15 @@ const Docs = (defaultprops) => {
|
||||
return
|
||||
}
|
||||
|
||||
console.log("PROPKEY: ", propkey)
|
||||
if (location.pathname.includes("/docs/")) {
|
||||
if (propkey === "cookie_policy" || propkey === "compliance" || propkey === "privacy_policy" || propkey === "terms_of_service") {
|
||||
navigate(`/legal/${propkey}`)
|
||||
}
|
||||
|
||||
if (propkey === "app_creation") {
|
||||
navigate('/docs/apps#app-creation-introduction')
|
||||
}
|
||||
}
|
||||
}, [location]);
|
||||
|
||||
@@ -932,7 +937,7 @@ const Docs = (defaultprops) => {
|
||||
}
|
||||
|
||||
if (responseJson.reason !== undefined && responseJson.reason !== null && responseJson.reason.includes("404: Not Found") && !isArticlePage) {
|
||||
navigate("/docs")
|
||||
//navigate("/docs")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -527,6 +527,8 @@ const Settings = (props) => {
|
||||
};
|
||||
|
||||
const generateApikey = () => {
|
||||
toast.info("Generating new API key. This may take a bit.");
|
||||
|
||||
fetch(globalUrl + "/api/v1/generateapikey", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
@@ -538,7 +540,7 @@ const Settings = (props) => {
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
console.log("Status not 200 for WORKFLOW EXECUTION :O!");
|
||||
}
|
||||
}
|
||||
|
||||
return response.json();
|
||||
})
|
||||
@@ -836,7 +838,12 @@ const Settings = (props) => {
|
||||
variant="outlined"
|
||||
/>
|
||||
<Button
|
||||
style={{ width: "100%", height: "40px", marginTop: "10px" }}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "40px",
|
||||
marginTop: "10px",
|
||||
textTransform: "none",
|
||||
}}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={() => generateApikey()}
|
||||
|
||||
Reference in New Issue
Block a user