From 9cf620bfda6cd781bd02d3477917a6609f6e09ac Mon Sep 17 00:00:00 2001 From: Frikky Date: Thu, 6 Feb 2025 16:17:36 +0100 Subject: [PATCH] Fixed multiple issues for suborg workflows --- frontend/src/components/LeftSideBar.jsx | 2 +- frontend/src/components/ParsedAction.jsx | 102 ++++++++- frontend/src/theme.jsx | 1 + frontend/src/views/AngularWorkflow.jsx | 262 ++++++++++++++++++++--- frontend/src/views/Workflows2.jsx | 8 +- 5 files changed, 337 insertions(+), 38 deletions(-) diff --git a/frontend/src/components/LeftSideBar.jsx b/frontend/src/components/LeftSideBar.jsx index 31e43c28..60155384 100644 --- a/frontend/src/components/LeftSideBar.jsx +++ b/frontend/src/components/LeftSideBar.jsx @@ -524,7 +524,7 @@ useEffect(() => { - Version: 2.0.0-rc4 + Version: 2.0.0-rc5 diff --git a/frontend/src/components/ParsedAction.jsx b/frontend/src/components/ParsedAction.jsx index e3c98eab..688e265e 100755 --- a/frontend/src/components/ParsedAction.jsx +++ b/frontend/src/components/ParsedAction.jsx @@ -93,6 +93,7 @@ import { Storage as StorageIcon, Check as CheckIcon, PriorityHigh as PriorityHighIcon, + Restore as RestoreIcon, } from '@mui/icons-material'; export const useStyles = makeStyles({ @@ -175,6 +176,9 @@ const ParsedAction = (props) => { setEditorData, setcodedata, setAiQueryModalOpen, + + suborgWorkflows, + originalWorkflow, } = props; let navigate = useNavigate() @@ -199,6 +203,7 @@ const ParsedAction = (props) => { const [showAutocomplete, setShowAutocomplete] = React.useState(false); const [menuPosition, setMenuPosition] = useState(null); const [uiBox, setUiBox] = useState(null); + const [parentAction, setParentAction] = useState(null); const isIntegration = selectedAction.app_id === "integration" const isAgent = selectedAction.app_id === "shuffle_agent" const [distributeAuthToSuborgs, setDistributeAuthToSuborgs] = useState(selectedAction?.selectedAuthentication?.suborg_distributed || false) @@ -615,6 +620,26 @@ const ParsedAction = (props) => { if (!selectedVariableParameter && workflow.workflow_variables?.length > 0) { setSelectedVariableParameter(workflow.workflow_variables[0].name); } + + if (selectedAction?.parent_controlled === true && workflow?.parentorg_workflow?.length > 0 && originalWorkflow?.id !== undefined && originalWorkflow?.id !== null && originalWorkflow?.id !== workflow?.id && originalWorkflow?.actions !== undefined && originalWorkflow?.actions !== null && originalWorkflow?.actions.length > 0) { + // Due to ID remapping of actions not happening, this is easy + for (var key in originalWorkflow.actions) { + const curparentAction = originalWorkflow.actions[key] + + if (curparentAction.id === selectedAction.id) { + if (curparentAction.parameters === undefined || curparentAction.parameters === null || curparentAction.parameters.length === 0) { + console.log("Parent parameters missing!") + break + } + + if (curparentAction.id !== parentAction?.id) { + setParentAction(curparentAction) + } + + break + } + } + } }, [selectedAction, selectedApp, setNewSelectedAction, workflow, workflowExecutions, getParents]) useEffect(() => { @@ -2067,7 +2092,55 @@ const ParsedAction = (props) => { selectedAction.authentication.length > 0 ? (
- Authentication +
+ + Authentication + + + {parentAction?.authentication_id !== undefined && parentAction?.authentication_id !== null && parentAction?.authentication_id !== "" && parentAction?.authentication_id !== selectedAction?.authentication_id ? + + { + selectedAction.authentication_id = parentAction.authentication_id + + // Check if we can select the parent auth or not + console.log("Changing selected auth to parent: ", parentAction, selectedAction.authentication) + if (selectedAction.authentication !== undefined && selectedAction.authentication !== null && selectedAction.authentication.length > 0) { + var found = false + for (var key in selectedAction.authentication) { + if (selectedAction.authentication[key].id === parentAction.authentication_id) { + selectedAction.selectedAuthentication = selectedAction.authentication[key] + found = true + break + } + } + + if (!found) { + toast.error("Couldn't find parent authentication. Is it distributed to this suborg?") + } + } else { + toast.warning("No matching authentication found for this app. Is it distributed to this suborg?") + selectedAction.selectedAuthentication = { + "id": parentAction.authentication_id, + "name": "Parent auth", + "label": "Parent auth", + } + } + + setSelectedAction(selectedAction) + setUpdate(Math.random()) + }} + /> + + + : null} +
{ } } + var parentParamValue = "" + if (parentAction !== undefined && parentAction !== null && parentAction !== "" && parentAction.parameters !== undefined && parentAction.parameters !== null) { + const foundParamIndex = parentAction.parameters.findIndex((param) => param.name === data.name) + if (foundParamIndex !== -1) { + parentParamValue = parentAction.parameters[foundParamIndex].value + } + } + return (
{isFirstOptional ? : null} @@ -4450,6 +4531,25 @@ const ParsedAction = (props) => { {tmpitem} {selectedActionParameters[count].required || selectedActionParameters[count].configuration ? "*" : ""}
+ {parentParamValue !== undefined && parentParamValue !== null && parentParamValue !== "" && parentParamValue !== data.value ? + + { + selectedActionParameters[count].value = parentParamValue + selectedAction.parameters[count].value = parentParamValue + setSelectedAction(selectedAction) + setUpdate(Math.random()) + }} + /> + + : null} + { } if (curworkflow.actions === undefined || curworkflow.actions === null || curworkflow.actions.length === 0) { - console.log("Can't save without actions") + toast.error("The workflow is empty. Please add at least one action.") return } @@ -3844,7 +3844,137 @@ const AngularWorkflow = (defaultprops) => { }); return apps - }; + } + + const findWorkflowDiff = (parentWorkflow, childWorkflow) => { + var diff = { + "different": false, + "environment": false, + "actions": [], + "triggers": [], + } + + if (parentWorkflow.actions === undefined || parentWorkflow.actions === null || parentWorkflow.actions.length === 0) { + console.log("Parent workflow actions are empty") + return diff + } + + if (childWorkflow.actions === undefined || childWorkflow.actions === null || childWorkflow.actions.length === 0) { + console.log("Child workflow actions are empty") + return diff + } + + + var parentEnvironment = "" + var childEnvironment = "" + for (var parentKey in parentWorkflow.actions) { + const parentAction = parentWorkflow.actions[parentKey] + if (parentAction.environment !== undefined && parentAction.environment !== null && parentAction.environment !== "") { + parentEnvironment = parentAction.environment + } + + var actionDiff = { + parameters: [] + } + + var found = false + for (var childKey in childWorkflow.actions) { + const childAction = childWorkflow.actions[childKey] + if (childAction.environment !== undefined && childAction.environment !== null && childAction.environment !== "") { + childEnvironment = childAction.environment + } + + if (childAction.id !== parentAction.id) { + found = true + continue + } + + if (childAction.label !== parentAction.label) { + actionDiff.label_change = true + } + + /* + if (childAction.app_id !== parentAction.app_id) { + actionDiff.app_id = true + } + */ + + if (childAction.app_name !== parentAction.app_name) { + actionDiff.app_name = true + } + + if (childAction.app_version !== parentAction.app_version) { + actionDiff.app_version = true + } + + if (childAction.name !== parentAction.name) { + actionDiff.name = true + } + + // Irrelevant + //if (childAction.environment !== parentAction.environment) { + // actionDiff.environment = true + //} + + if (childAction.authentication_id !== parentAction.authentication_id) { + actionDiff.authentication_id = true + } + + if (parentAction.parameters === undefined || parentAction.parameters === null || parentAction.parameters.length === 0 || childAction.parameters === undefined || childAction.parameters === null || childAction.parameters.length === 0) { + continue + } + + for (var parentParamIndex in parentAction.parameters) { + const parentParam = parentAction.parameters[parentParamIndex] + for (var childParamIndex in childAction.parameters) { + const childParam = childAction.parameters[childParamIndex] + if (childParam.name !== parentParam.name) { + continue + } + + if (childParam.value !== parentParam.value) { + actionDiff.parameters.push(childParam.name) + } + } + } + } + + if (actionDiff.parameters.length > 0) { + actionDiff.params = true + } + + if (!found) { + actionDiff.new = true + } + + console.log("ACTIONDIFF: ", actionDiff) + if (actionDiff !== undefined && actionDiff !== null && Object.keys(actionDiff).length > 1) { + actionDiff.label = parentAction.label.replaceAll("_", " ") + actionDiff.id = parentAction.id + actionDiff.large_image = parentAction.large_image + diff.actions.push(actionDiff) + } + } + + if (childEnvironment !== parentEnvironment) { + diff.environment = true + } + + + // loop diff and find if ANY key is true + for (var key in diff) { + try { + if (diff[key] === true || diff[key].length > 0) { + diff.different = true + break + } + } catch (e) { + console.log("Error in diff: ", e) + } + } + + return diff + } const getChildWorkflows = (parentWorkflowId) => { //toast("Loading child workflows 1 (should be 2)") @@ -3875,6 +4005,14 @@ const AngularWorkflow = (defaultprops) => { }) .then((responseJson) => { if (responseJson.success !== false) { + + for (var key in responseJson) { + const diff = findWorkflowDiff(originalWorkflow, responseJson[key]) + if (diff !== undefined && diff !== null) { + responseJson[key].diff = diff + } + } + setSuborgWorkflows(responseJson) } }) @@ -5086,9 +5224,6 @@ const AngularWorkflow = (defaultprops) => { if (inputAction !== undefined) { console.log("In input action! Should check params if they match, and add suggestions") - console.log("ORIGINAL PARAMS: ", originalParams) - console.log("RESPONSE PARAMS: ", responseJson.parameters) - if (responseJson.parameters === undefined || responseJson.parameters.length === 0) { return } @@ -8699,7 +8834,6 @@ const AngularWorkflow = (defaultprops) => { if (inParent === false) { if (trigger.parent_controlled === true) { - console.log("Setting trigger as parent controlled") inParent = true } } @@ -8977,22 +9111,7 @@ const AngularWorkflow = (defaultprops) => { setSelectedEdge({}) setSelectedAction({}) } - - // An attempt at NOT unselecting when removing - /* - setTimeout(() => { - if (parsedSelection.data() !== undefined) { - if (parsedSelection.data("id") !== selectedNode.data("id")) { - console.log("SHOULD SELECT SINCE ID IS DIFFERENT") - - parsedSelection.select() - } - } - - console.log("Parsed: ", parsedSelection.data("id"), selectedNode.data("id")) - }, 2500) - */ - }; + } if (isLoaded && setupSent === false) { @@ -16941,8 +17060,8 @@ const AngularWorkflow = (defaultprops) => { pointerEvents: "auto", backgroundColor: theme.palette.inputColor, color: "white", - maxWidth: 250, - minWidth: 250, + maxWidth: 300, + minWidth: 300, borderRadius: theme.palette?.borderRadius, height: 40, }} @@ -17063,7 +17182,10 @@ const AngularWorkflow = (defaultprops) => { label="Suborg Distribution" fullWidth > - + { e.stopPropagation() }} /> {userdata.active_org.large_image}{" "} + {userdata.active_org.name} @@ -17129,13 +17252,84 @@ const AngularWorkflow = (defaultprops) => { /> ) + var orgDiff = { + different: false, + } + const foundMatchingWorkflow = suborgWorkflows?.find((workflow) => workflow.org_id === data.id) + if (foundMatchingWorkflow.diff !== undefined && foundMatchingWorkflow.diff !== null) { + orgDiff = foundMatchingWorkflow.diff + } + + //console.log("DIFF: ", orgDiff) return ( - - {image}{" "} - - {data.name} - + + + {image}{" "} + + {data.name} + + + + {orgDiff.different === true ? + + + Changes: +
+ + {orgDiff.environment === true && + - Environment
+ } + + {orgDiff?.actions?.length > 0 && + - Actions ({orgDiff.actions.length}):
+ {orgDiff.actions.map((orgDiffAction, index) => { + console.log("DIFF: ", orgDiffAction) + var formattedError = "" + + var paramchanges = "" + for (var diffActionKey in orgDiffAction) { + if (diffActionKey !== "id" && diffActionKey !== "label" && diffActionKey !== "parameters" && diffActionKey !== "params" && diffActionKey !== "large_image") { + if (formattedError.length > 0) { + formattedError += ", " + } + formattedError += diffActionKey + } + + if (diffActionKey === "parameters") { + paramchanges = orgDiffAction[diffActionKey].join(", ") + } + } + + if (paramchanges.length > 0) { + formattedError += paramchanges + } + + return ( +
  • + + {orgDiffAction.label} + + {formattedError} +
  • + ) + })} +
    + } + +
    +
    + }> + + + : null} ) })} @@ -17210,7 +17404,7 @@ const AngularWorkflow = (defaultprops) => { }} onChange={(e) => { setLastSaved(false) - const env = environments.find((a) => a.Name === e.target.value); + const env = environments.find((a) => a.Name === e.target.value) setSelectedActionEnvironment(env) selectedAction.environment = env.Name setSelectedAction(selectedAction) @@ -17881,7 +18075,7 @@ const AngularWorkflow = (defaultprops) => { setSelectedApp({}) setWorkflow(inputworkflow) - if (workflow.id === originalWorkflow.id) { + if (inputworkflow.id === originalWorkflow.id) { if (selectedActionEnvironment !== undefined && selectedActionEnvironment !== null && selectedActionEnvironment.Name !== undefined && selectedActionEnvironment.Name !== null) { setOriginalSelectedEnvironment(selectedActionEnvironment) } @@ -17890,6 +18084,7 @@ const AngularWorkflow = (defaultprops) => { if (inputworkflow.id === originalWorkflow.id && originalSelectedEnvironment !== undefined && originalSelectedEnvironment !== null && originalSelectedEnvironment.Name !== undefined && originalSelectedEnvironment.Name !== null) { setSelectedActionEnvironment(originalSelectedEnvironment) } else { + //console.log("Checking input workflow actions for env: ", inputworkflow.actions) if (inputworkflow.actions !== undefined && inputworkflow.actions !== null && inputworkflow.actions.length > 0) { for (var actionkey in inputworkflow.actions) { @@ -21410,6 +21605,9 @@ const AngularWorkflow = (defaultprops) => { setEditorData={setEditorData} setAiQueryModalOpen={setAiQueryModalOpen} fixExample={fixExample} + + suborgWorkflows={suborgWorkflows} + originalWorkflow={originalWorkflow} /> diff --git a/frontend/src/views/Workflows2.jsx b/frontend/src/views/Workflows2.jsx index b659ab7b..0c587f00 100644 --- a/frontend/src/views/Workflows2.jsx +++ b/frontend/src/views/Workflows2.jsx @@ -2479,7 +2479,7 @@ const Workflows2 = (props) => { return ( -
    +
    {selectedCategory !== "" ? @@ -2563,13 +2563,13 @@ const Workflows2 = (props) => { {(isDistributed || hasSuborgs) && (
    { aria-controls="long-menu" aria-haspopup="true" onClick={() => { - window.open(`/admin?admin_tab=notifications&workflow_id=${data.id}`, "_blank") + window.open(`/admin?admin_tab=notifications&workflow=${data.id}`, "_blank") }} style={{ padding: "0px",