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
>
-
+ }>
+
+
+ : 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",