diff --git a/backend/app_sdk/app_base.py b/backend/app_sdk/app_base.py
index a7e0d4f8..415f1e94 100755
--- a/backend/app_sdk/app_base.py
+++ b/backend/app_sdk/app_base.py
@@ -97,6 +97,7 @@ def md5_base64(a):
a = str(a)
foundhash = hashlib.md5(a.encode('utf-8')).hexdigest()
return base64.b64encode(foundhash.encode('utf-8'))
+
@shuffle_filters.register
def base64_encode(a):
@@ -107,6 +108,17 @@ def base64_encode(a):
except:
return base64.b64encode(a).decode()
+@shuffle_filters.register
+def random_element(a):
+ # Choose a random item from an array
+ a = list(a)
+
+ if len(a) == 0:
+ return ""
+
+ return random.choice(a)
+
+
@shuffle_filters.register
def base64_decode(a):
a = str(a)
diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx
index f7d6227d..5f472183 100755
--- a/frontend/src/views/AngularWorkflow.jsx
+++ b/frontend/src/views/AngularWorkflow.jsx
@@ -2011,6 +2011,13 @@ const releaseToConnectLabel = "Release to Connect"
headers["Org-Id"] = useworkflow.org_id
}
+ // Realtime makes the workflow if it doesn't exist
+ /*
+ if (duplicationOrg !== undefined && duplicationOrg !== null && duplicationOrg.length > 0) {
+ headers["Org-Id"] = duplicationOrg
+ }
+ */
+
setLastSaved(true);
fetch(`${globalUrl}/api/v1/workflows/${useworkflow.id}`, {
method: "PUT",
@@ -2032,7 +2039,8 @@ const releaseToConnectLabel = "Release to Connect"
return response.json();
})
.then((responseJson) => {
- if (duplicationOrg !== undefined && duplicationOrg !== null && duplicationOrg.length > 0) {
+ if (useworkflow.id === originalWorkflow.id && duplicationOrg !== undefined && duplicationOrg !== null && duplicationOrg.length > 0) {
+ //duplicateParentWorkflow(useworkflow, duplicationOrg, true)
duplicateParentWorkflow(useworkflow, duplicationOrg, true)
}
@@ -3233,15 +3241,19 @@ const releaseToConnectLabel = "Release to Connect"
};
const getChildWorkflows = (parentWorkflowId) => {
- if (workflow.suborg_distribution === undefined || workflow.suborg_distribution === null || workflow.suborg_distribution.length === 0) {
+ if (originalWorkflow.suborg_distribution === undefined || originalWorkflow.suborg_distribution === null || originalWorkflow.suborg_distribution.length === 0) {
+ console.log("No suborg distribution")
return
}
+ const orgId = originalWorkflow.org_id === undefined || originalWorkflow.org_id === null || originalWorkflow.org_id === "" ? "" : originalWorkflow.org_id
+
fetch(`${globalUrl}/api/v1/workflows/${parentWorkflowId}/child_workflows`, {
method: "GET",
headers: {
"Content-Type": "application/json",
- Accept: "application/json",
+ "Accept": "application/json",
+ "Org-Id": orgId,
},
credentials: "include",
})
@@ -3317,6 +3329,10 @@ const releaseToConnectLabel = "Release to Connect"
getChildWorkflows(responseJson.id)
}
+ if (responseJson.parentorg_workflow !== undefined && responseJson.parentorg_workflow !== null && responseJson.parentorg_workflow.length > 0) {
+ getChildWorkflows(responseJson.parentorg_workflow)
+ }
+
// Not sure why this is necessary.
if (responseJson.isValid === undefined) {
responseJson.isValid = true;
@@ -8523,6 +8539,525 @@ const releaseToConnectLabel = "Release to Connect"
)
}
+
+
+ const TriggersView = () => {
+ const triggersViewStyle = {
+ marginLeft: 10,
+ marginRight: 10,
+ display: "flex",
+ flexDirection: "column",
+ }
+
+ // Predefined hurr
+ return (
+
+
+ {triggers.map((trigger, index) => {
+
+ /*
+ if (trigger.trigger_type === "PIPELINE") {
+ if (userdata.support !== true) {
+ return null
+ }
+ }
+ */
+
+ // Hiding since March 2024
+ if (trigger.trigger_type === "EMAIL") {
+ return null
+ }
+
+ const imagesize = isMobile ? 40 : trigger.large_image.includes("svg") ? 50 : 50
+ var imageline = trigger.large_image.length === 0 ?
![]()
+ :
+

+
+ const title = trigger.trigger_type === "WEBHOOK" ? "Workflow starters" : trigger.trigger_type === "SUBFLOW" ? "Mid-Workflow" : ""
+
+ const color = trigger.is_valid ? green : yellow;
+ return (
+
+ {title.length > 0 ?
+
+ {title}
+
+ : null}
+
+ {
+ handleTriggerDrag(e, trigger);
+ }}
+ onStop={(e) => {
+ handleDragStop(e);
+ }}
+ dragging={false}
+ position={{
+ x: 0,
+ y: 0,
+ }}
+ >
+ { }}>
+
+
+
+ {imageline}
+
+ {isMobile ? null :
+
+
+
+ {trigger.name}
+
+
+
+
+ {trigger.description}
+
+
+
+ }
+
+
+
+
+ );
+ })}
+
+
+ );
+ };
+
+ var newNodeId = "";
+ var parsedApp = {};
+ const handleTriggerDrag = (e, data) => {
+ const cycontainer = cy.container();
+ // Chrome lol
+ if (
+ e.pageX > cycontainer.offsetLeft &&
+ e.pageX < cycontainer.offsetLeft + cycontainer.offsetWidth &&
+ e.pageY > cycontainer.offsetTop &&
+ e.pageY < cycontainer.offsetTop + cycontainer.offsetHeight
+ ) {
+ if (newNodeId.length > 0) {
+ var currentnode = cy.getElementById(newNodeId);
+ if (currentnode.length === 0) {
+ return;
+ }
+
+ currentnode[0].renderedPosition("x", e.pageX - cycontainer.offsetLeft);
+ currentnode[0].renderedPosition("y", e.pageY - cycontainer.offsetTop);
+ } else {
+ if (workflow.start === "" || workflow.start === undefined) {
+ toast("Define a starting action first.");
+ return;
+ }
+
+ const triggerLabel = getNextActionName(data.name);
+
+ newNodeId = uuidv4();
+ const newposition = {
+ x: e.pageX - cycontainer.offsetLeft,
+ y: e.pageY - cycontainer.offsetTop,
+ };
+
+ const newAppData = {
+ app_name: data.name,
+ app_version: "1.0.0",
+ environment: isCloud ? "cloud" : data.environment,
+ description: data.description,
+ long_description: data.long_description,
+ errors: [],
+ id_: newNodeId,
+ _id_: newNodeId,
+ id: newNodeId,
+ finished: false,
+ label: triggerLabel,
+ type: data.type,
+ is_valid: true,
+ trigger_type: data.trigger_type,
+ large_image: data.large_image,
+ status: "uninitialized",
+ name: data.name,
+ isStartNode: false,
+ position: newposition,
+ };
+
+ // Can all the data be in here? hmm
+ const nodeToBeAdded = {
+ group: "nodes",
+ data: newAppData,
+ renderedPosition: newposition,
+ };
+
+ cy.add(nodeToBeAdded);
+ parsedApp = nodeToBeAdded;
+ return;
+ }
+ }
+ };
+
+ const handleDragStop = (e, app) => {
+ var currentnode = cy.getElementById(newNodeId);
+ if (
+ currentnode === undefined ||
+ currentnode === null ||
+ currentnode.length === 0
+ ) {
+ return;
+ }
+
+ if (parsedApp === undefined || parsedApp === null || parsedApp.data === undefined || parsedApp.data === null) {
+ toast("Failed to add trigger. Please try again.")
+ return
+ }
+
+ // Using remove & replace, as this triggers the function
+ // onNodeAdded() with this node after it's added
+
+ currentnode.remove();
+ parsedApp.data.finished = true;
+ parsedApp.data.position = currentnode.renderedPosition();
+ parsedApp.position = currentnode.renderedPosition();
+ parsedApp.renderedPosition = currentnode.renderedPosition();
+
+ var newAppData = parsedApp.data;
+ if (newAppData.type === "ACTION") {
+
+ //const activateApp = (appid) => {
+ if (newAppData.activated === false) {
+ activateApp(newAppData.app_id, false)
+ }
+
+ // AUTHENTICATION
+ if (app.authentication !== undefined && app.authentication !== null && app.authentication.required === true) {
+
+ // Setup auth here :)
+ const authenticationOptions = [];
+ var findAuthId = "";
+ if (
+ newAppData.authentication_id !== null &&
+ newAppData.authentication_id !== undefined &&
+ newAppData.authentication_id.length > 0
+ ) {
+ findAuthId = newAppData.authentication_id;
+ }
+
+ const tmpAuth = JSON.parse(JSON.stringify(appAuthentication));
+ for (let authkey in tmpAuth) {
+ if (authkey === undefined) {
+ continue
+ }
+
+ var item = tmpAuth[authkey];
+ const newfields = {};
+ for (let fieldkey in item.fields) {
+ if (item.fields[fieldkey] === undefined) {
+ console.log("Problem with filterkey in Node select", fieldkey)
+ continue
+ }
+
+ const filterkey = item.fields[fieldkey]["key"]
+ if (filterkey === null || filterkey === undefined) {
+ console.log("Problem with filterkey 2. Null or undefined 3")
+ continue
+ }
+
+ newfields[filterkey] = item.fields[fieldkey]["value"];
+ }
+
+ item.fields = newfields;
+ if (item.app.id === app.id || item.app.name === app.name) {
+ authenticationOptions.push(item);
+
+ if (item.id === findAuthId) {
+ newAppData.selectedAuthentication = item
+ newAppData.authentication_id = item.id
+
+ } else if (findAuthId === "") {
+ // Will always be set to the last one if one isn't found.
+ // Last = timestamp too
+ newAppData.selectedAuthentication = item
+ newAppData.authentication_id = item.id
+ }
+ }
+ }
+
+ if (
+ authenticationOptions !== undefined &&
+ authenticationOptions !== null &&
+ authenticationOptions.length > 0
+ ) {
+ for (let authkey in authenticationOptions) {
+ const option = authenticationOptions[authkey];
+
+ if (option.active && newAppData.authentication_id === "") {
+ newAppData.selectedAuthentication = option;
+ newAppData.authentication_id = option.id;
+ break;
+ }
+ }
+ }
+ } else {
+ newAppData.authentication = [];
+ newAppData.authentication_id = "";
+ newAppData.selectedAuthentication = {};
+ }
+
+ parsedApp.data = newAppData;
+ cy.add(parsedApp);
+ } else if (newAppData.type === "TRIGGER") {
+ cy.add(parsedApp);
+ }
+
+ newNodeId = "";
+ parsedApp = {};
+ };
+
+ const barHeight = bodyHeight - appBarSize - 50;
+ const appScrollStyle = {
+ overflow: "scroll",
+ maxHeight: isMobile ? bodyHeight - appBarSize * 4 : barHeight,
+ minHeight: isMobile ? bodyHeight - appBarSize * 4 : barHeight,
+ marginTop: 1,
+ overflowY: "auto",
+ overflowX: "hidden",
+ }
+
+ const handleAppDrag = (e, app) => {
+ const cycontainer = cy.container();
+
+
+ if (app.type === "TRIGGER") {
+ handleTriggerDrag(e, app)
+ return
+ }
+
+ //console.log("e: ", e)
+ //console.log("Offset: ", cycontainer)
+
+ // Chrome lol
+ if (
+ e.pageX > cycontainer.offsetLeft &&
+ e.pageX < cycontainer.offsetLeft + cycontainer.offsetWidth &&
+ e.pageY > cycontainer.offsetTop &&
+ e.pageY < cycontainer.offsetTop + cycontainer.offsetHeight
+ ) {
+ if (newNodeId.length > 0) {
+ var currentnode = cy.getElementById(newNodeId);
+ if (
+ currentnode === undefined ||
+ currentnode === null ||
+ currentnode.length === 0
+ ) {
+ return;
+ }
+
+ currentnode[0].renderedPosition("x", e.pageX - cycontainer.offsetLeft)
+ currentnode[0].renderedPosition("y", e.pageY - cycontainer.offsetTop)
+ } else {
+ if (workflow.public) {
+ console.log("workflow is public - not adding")
+ return;
+ }
+
+ if (app.actions === undefined || app.actions === null) {
+ app.actions = []
+ }
+
+ /*
+ if (app.actions === undefined || app.actions === null || app.actions.length === 0) {
+ toast("App " + app.name + " currently has no actions to perform. Please go to https://shuffler.io/apps to edit it.")
+
+ return
+ }
+ */
+
+ newNodeId = uuidv4();
+ const actionType = "ACTION";
+ const actionLabel = getNextActionName(app.name);
+ //console.log("Next action name: ", actionLabel)
+ var parameters = null;
+ var example = "";
+ var description = ""
+
+ const startIndex = app.actions.findIndex((action) => action.category_label !== undefined && action.category_label !== null && action.category_label.length > 0)
+ const actionIndex = startIndex < 0 ? 0 : startIndex
+
+ // Make the first action the most relevant one for them based on previous use
+ if (
+ app.actions[actionIndex].parameters !== undefined &&
+ app.actions[actionIndex].parameters !== null &&
+ app.actions[actionIndex].parameters.length > 0
+ ) {
+ parameters = app.actions[actionIndex].parameters;
+ for (let paramkey in parameters) {
+ // Check if parameter.name == "headers" and if it includes "=undefined". If it does, set the value to example if it exists, otherwise empty
+ if (parameters[paramkey].name === "headers" && parameters[paramkey].value.includes("=undefined")) {
+ if (parameters[paramkey].example !== undefined && parameters[paramkey].example !== null && parameters[paramkey].example.length > 0) {
+ parameters[paramkey].value = parameters[paramkey].example
+ } else {
+ parameters[paramkey].value = ""
+ }
+ }
+ }
+
+ //parameters = app.actions[0].parameters;
+ }
+
+ if (
+ app.actions[actionIndex].returns !== undefined &&
+ app.actions[actionIndex].returns !== null &&
+ app.actions[actionIndex].returns.example !== undefined &&
+ app.actions[actionIndex].returns.example !== null &&
+ app.actions[actionIndex].returns.example.length > 0
+ ) {
+ example = app.actions[actionIndex].returns.example;
+ }
+
+ if (
+ app.actions[actionIndex].description !== undefined &&
+ app.actions[actionIndex].description !== null &&
+ app.actions[actionIndex].description.length > 0
+ ) {
+ description = app.actions[actionIndex].description
+ }
+
+ var parsedEnvironments =
+ environments === null || environments === []
+ ? "cloud"
+ : environments[defaultEnvironmentIndex] === undefined
+ ? "cloud"
+ : environments[defaultEnvironmentIndex].Name
+
+ // Basic automatic auth mapping
+ var authId = ""
+ if (appAuthentication !== undefined && appAuthentication !== null && appAuthentication.length > 0) {
+ const appname = app.name.toLowerCase().replace(" ", "_")
+ for (var key in appAuthentication) {
+ const authKey = appAuthentication[key]
+ if (authKey.app.id === app.id) {
+ authId = authKey.id
+ break
+ }
+
+ const appauthname = authKey.app.name.toLowerCase().replace(" ", "_")
+ if (appauthname === appname) {
+ authId = authKey.id
+ }
+ }
+ }
+
+ // List other nodes in the workflow and see if they have an environment set. If they do, use that as the default
+ if (cy !== undefined && cy !== null) {
+ const foundnodes = cy.nodes().jsons()
+ if (foundnodes !== undefined && foundnodes !== null && foundnodes.length > 0) {
+ // As they should all be the same, this is just an override
+ for (let nodekey in foundnodes) {
+ const curnode = foundnodes[nodekey]
+ if (curnode.data.environment !== undefined && curnode.data.environment !== null && curnode.data.environment.length > 0) {
+ parsedEnvironments = curnode.data.environment
+ break
+ }
+ }
+ }
+ }
+
+ const newAppData = {
+ name: app.actions[actionIndex].name,
+ label: actionLabel,
+ app_name: app.name,
+ app_version: app.app_version,
+ app_id: app.id,
+ sharing: app.sharing,
+ private_id: app.private_id,
+ description: description,
+ environment: parsedEnvironments,
+ errors: [],
+ finished: false,
+ id_: newNodeId,
+ _id_: newNodeId,
+ id: newNodeId,
+ is_valid: true,
+ type: actionType,
+ parameters: parameters,
+ isStartNode: false,
+ large_image: app.large_image,
+ run_magic_output: false,
+ authentication: [],
+ execution_variable: undefined,
+ example: example,
+ required_body_fields: app.actions[actionIndex].required_body_fields,
+ category:
+ app.categories !== null &&
+ app.categories !== undefined &&
+ app.categories.length > 0
+ ? app.categories[0]
+ : "",
+ authentication_id: authId,
+ finished: false,
+ template: app.template === true ? true : false,
+ };
+
+ // FIXME: overwrite category if the ACTION chosen has a different category
+ //
+
+ if (!isCloud && (!app.is_valid || (!app.activated && app.generated))) {
+ console.log("NOT VALID: Activate!")
+
+ activateApp(app.id, false)
+ }
+
+ // const image = "url("+app.large_image+")"
+ // FIXME - find the cytoscape offset position
+ // Can this be done with zoom calculations?
+ const nodeToBeAdded = {
+ group: "nodes",
+ data: newAppData,
+ renderedPosition: {
+ x: e.pageX - cycontainer.offsetLeft,
+ y: e.pageY - cycontainer.offsetTop,
+ },
+ };
+
+ parsedApp = nodeToBeAdded;
+ cy.add(nodeToBeAdded);
+ return;
+ }
+ }
+ };
+
const AppView = (props) => {
const { allApps, prioritizedApps, filteredApps, extraApps } = props;
// console.log("AppView Rendered!")
@@ -9181,501 +9716,6 @@ const releaseToConnectLabel = "Release to Connect"
);
}
- const TriggersView = () => {
- console.log("TriggerView Rendered!")
- const triggersViewStyle = {
- marginLeft: 10,
- marginRight: 10,
- display: "flex",
- flexDirection: "column",
- }
-
- // Predefined hurr
- return (
-
-
- {triggers.map((trigger, index) => {
-
- /*
- if (trigger.trigger_type === "PIPELINE") {
- if (userdata.support !== true) {
- return null
- }
- }
- */
-
- // Hiding since March 2024
- if (trigger.trigger_type === "EMAIL") {
- return null
- }
-
- const imagesize = isMobile ? 40 : trigger.large_image.includes("svg") ? 50 : 50
- var imageline = trigger.large_image.length === 0 ?
![]()
- :
-

-
- const title = trigger.trigger_type === "WEBHOOK" ? "Workflow starters" : trigger.trigger_type === "SUBFLOW" ? "Mid-Workflow" : ""
-
- const color = trigger.is_valid ? green : yellow;
- return (
-
- {title.length > 0 ?
-
- {title}
-
- : null}
-
- {
- handleTriggerDrag(e, trigger);
- }}
- onStop={(e) => {
- handleDragStop(e);
- }}
- dragging={false}
- position={{
- x: 0,
- y: 0,
- }}
- >
- { }}>
-
-
-
- {imageline}
-
- {isMobile ? null :
-
-
-
- {trigger.name}
-
-
-
-
- {trigger.description}
-
-
-
- }
-
-
-
-
- );
- })}
-
-
- );
- }
-
- var newNodeId = "";
- var parsedApp = {};
- const handleTriggerDrag = (e, data) => {
- const cycontainer = cy.container();
- // Chrome lol
- if (
- e.pageX > cycontainer.offsetLeft &&
- e.pageX < cycontainer.offsetLeft + cycontainer.offsetWidth &&
- e.pageY > cycontainer.offsetTop &&
- e.pageY < cycontainer.offsetTop + cycontainer.offsetHeight
- ) {
- if (newNodeId.length > 0) {
- var currentnode = cy.getElementById(newNodeId);
- if (currentnode.length === 0) {
- return;
- }
-
- currentnode[0].renderedPosition("x", e.pageX - cycontainer.offsetLeft);
- currentnode[0].renderedPosition("y", e.pageY - cycontainer.offsetTop);
- } else {
- if (workflow.start === "" || workflow.start === undefined) {
- toast("Define a starting action first.");
- return;
- }
-
- const triggerLabel = getNextActionName(data.name);
-
- newNodeId = uuidv4();
- const newposition = {
- x: e.pageX - cycontainer.offsetLeft,
- y: e.pageY - cycontainer.offsetTop,
- };
-
- const newAppData = {
- app_name: data.name,
- app_version: "1.0.0",
- environment: isCloud ? "cloud" : data.environment,
- description: data.description,
- long_description: data.long_description,
- errors: [],
- id_: newNodeId,
- _id_: newNodeId,
- id: newNodeId,
- finished: false,
- label: triggerLabel,
- type: data.type,
- is_valid: true,
- trigger_type: data.trigger_type,
- large_image: data.large_image,
- status: "uninitialized",
- name: data.name,
- isStartNode: false,
- position: newposition,
- };
-
- // Can all the data be in here? hmm
- const nodeToBeAdded = {
- group: "nodes",
- data: newAppData,
- renderedPosition: newposition,
- };
-
- cy.add(nodeToBeAdded);
- parsedApp = nodeToBeAdded;
- return;
- }
- }
- };
-
- const handleDragStop = (e, app) => {
- var currentnode = cy.getElementById(newNodeId);
- if (
- currentnode === undefined ||
- currentnode === null ||
- currentnode.length === 0
- ) {
- return;
- }
-
- // Using remove & replace, as this triggers the function
- // onNodeAdded() with this node after it's added
-
- currentnode.remove();
- parsedApp.data.finished = true;
- parsedApp.data.position = currentnode.renderedPosition();
- parsedApp.position = currentnode.renderedPosition();
- parsedApp.renderedPosition = currentnode.renderedPosition();
-
- var newAppData = parsedApp.data;
- if (newAppData.type === "ACTION") {
-
- //const activateApp = (appid) => {
- if (newAppData.activated === false) {
- activateApp(newAppData.app_id, false)
- }
-
- // AUTHENTICATION
- if (app.authentication !== undefined && app.authentication !== null && app.authentication.required === true) {
-
- // Setup auth here :)
- const authenticationOptions = [];
- var findAuthId = "";
- if (
- newAppData.authentication_id !== null &&
- newAppData.authentication_id !== undefined &&
- newAppData.authentication_id.length > 0
- ) {
- findAuthId = newAppData.authentication_id;
- }
-
- const tmpAuth = JSON.parse(JSON.stringify(appAuthentication));
- for (let authkey in tmpAuth) {
- if (authkey === undefined) {
- continue
- }
-
- var item = tmpAuth[authkey];
- const newfields = {};
- for (let fieldkey in item.fields) {
- if (item.fields[fieldkey] === undefined) {
- console.log("Problem with filterkey in Node select", fieldkey)
- continue
- }
-
- const filterkey = item.fields[fieldkey]["key"]
- if (filterkey === null || filterkey === undefined) {
- console.log("Problem with filterkey 2. Null or undefined 3")
- continue
- }
-
- newfields[filterkey] = item.fields[fieldkey]["value"];
- }
-
- item.fields = newfields;
- if (item.app.id === app.id || item.app.name === app.name) {
- authenticationOptions.push(item);
-
- if (item.id === findAuthId) {
- newAppData.selectedAuthentication = item
- newAppData.authentication_id = item.id
-
- } else if (findAuthId === "") {
- // Will always be set to the last one if one isn't found.
- // Last = timestamp too
- newAppData.selectedAuthentication = item
- newAppData.authentication_id = item.id
- }
- }
- }
-
- if (
- authenticationOptions !== undefined &&
- authenticationOptions !== null &&
- authenticationOptions.length > 0
- ) {
- for (let authkey in authenticationOptions) {
- const option = authenticationOptions[authkey];
-
- if (option.active && newAppData.authentication_id === "") {
- newAppData.selectedAuthentication = option;
- newAppData.authentication_id = option.id;
- break;
- }
- }
- }
- } else {
- newAppData.authentication = [];
- newAppData.authentication_id = "";
- newAppData.selectedAuthentication = {};
- }
-
- parsedApp.data = newAppData;
- cy.add(parsedApp);
- } else if (newAppData.type === "TRIGGER") {
- cy.add(parsedApp);
- }
-
- newNodeId = "";
- parsedApp = {};
- };
-
- const barHeight = bodyHeight - appBarSize - 50;
- const appScrollStyle = {
- overflow: "scroll",
- maxHeight: isMobile ? bodyHeight - appBarSize * 4 : barHeight,
- minHeight: isMobile ? bodyHeight - appBarSize * 4 : barHeight,
- marginTop: 1,
- overflowY: "auto",
- overflowX: "hidden",
- }
-
- const handleAppDrag = (e, app) => {
- const cycontainer = cy.container();
-
-
- if (app.type === "TRIGGER") {
- handleTriggerDrag(e, app)
- return
- }
-
- //console.log("e: ", e)
- //console.log("Offset: ", cycontainer)
-
- // Chrome lol
- if (
- e.pageX > cycontainer.offsetLeft &&
- e.pageX < cycontainer.offsetLeft + cycontainer.offsetWidth &&
- e.pageY > cycontainer.offsetTop &&
- e.pageY < cycontainer.offsetTop + cycontainer.offsetHeight
- ) {
- if (newNodeId.length > 0) {
- var currentnode = cy.getElementById(newNodeId);
- if (
- currentnode === undefined ||
- currentnode === null ||
- currentnode.length === 0
- ) {
- return;
- }
-
- currentnode[0].renderedPosition("x", e.pageX - cycontainer.offsetLeft)
- currentnode[0].renderedPosition("y", e.pageY - cycontainer.offsetTop)
- } else {
- if (workflow.public) {
- console.log("workflow is public - not adding")
- return;
- }
-
- if (app.actions === undefined || app.actions === null) {
- app.actions = []
- }
-
- /*
- if (app.actions === undefined || app.actions === null || app.actions.length === 0) {
- toast("App " + app.name + " currently has no actions to perform. Please go to https://shuffler.io/apps to edit it.")
-
- return
- }
- */
-
- newNodeId = uuidv4();
- const actionType = "ACTION";
- const actionLabel = getNextActionName(app.name);
- //console.log("Next action name: ", actionLabel)
- var parameters = null;
- var example = "";
- var description = ""
-
- const startIndex = app.actions.findIndex((action) => action.category_label !== undefined && action.category_label !== null && action.category_label.length > 0)
- const actionIndex = startIndex < 0 ? 0 : startIndex
-
- // Make the first action the most relevant one for them based on previous use
- if (
- app.actions[actionIndex].parameters !== undefined &&
- app.actions[actionIndex].parameters !== null &&
- app.actions[actionIndex].parameters.length > 0
- ) {
- parameters = app.actions[actionIndex].parameters;
- for (let paramkey in parameters) {
- // Check if parameter.name == "headers" and if it includes "=undefined". If it does, set the value to example if it exists, otherwise empty
- if (parameters[paramkey].name === "headers" && parameters[paramkey].value.includes("=undefined")) {
- if (parameters[paramkey].example !== undefined && parameters[paramkey].example !== null && parameters[paramkey].example.length > 0) {
- parameters[paramkey].value = parameters[paramkey].example
- } else {
- parameters[paramkey].value = ""
- }
- }
- }
-
- //parameters = app.actions[0].parameters;
- }
-
- if (
- app.actions[actionIndex].returns !== undefined &&
- app.actions[actionIndex].returns !== null &&
- app.actions[actionIndex].returns.example !== undefined &&
- app.actions[actionIndex].returns.example !== null &&
- app.actions[actionIndex].returns.example.length > 0
- ) {
- example = app.actions[actionIndex].returns.example;
- }
-
- if (
- app.actions[actionIndex].description !== undefined &&
- app.actions[actionIndex].description !== null &&
- app.actions[actionIndex].description.length > 0
- ) {
- description = app.actions[actionIndex].description
- }
-
- var parsedEnvironments =
- environments === null || environments === []
- ? "cloud"
- : environments[defaultEnvironmentIndex] === undefined
- ? "cloud"
- : environments[defaultEnvironmentIndex].Name;
-
- // List other nodes in the workflow and see if they have an environment set. If they do, use that as the default
- if (cy !== undefined && cy !== null) {
- const foundnodes = cy.nodes().jsons()
- if (foundnodes !== undefined && foundnodes !== null && foundnodes.length > 0) {
- // As they should all be the same, this is just an override
- for (let nodekey in foundnodes) {
- const curnode = foundnodes[nodekey]
- if (curnode.data.environment !== undefined && curnode.data.environment !== null && curnode.data.environment.length > 0) {
- parsedEnvironments = curnode.data.environment
- break
- }
- }
- }
- }
-
- const newAppData = {
- name: app.actions[actionIndex].name,
- label: actionLabel,
- app_name: app.name,
- app_version: app.app_version,
- app_id: app.id,
- sharing: app.sharing,
- private_id: app.private_id,
- description: description,
- environment: parsedEnvironments,
- errors: [],
- finished: false,
- id_: newNodeId,
- _id_: newNodeId,
- id: newNodeId,
- is_valid: true,
- type: actionType,
- parameters: parameters,
- isStartNode: false,
- large_image: app.large_image,
- run_magic_output: false,
- authentication: [],
- execution_variable: undefined,
- example: example,
- required_body_fields: app.actions[actionIndex].required_body_fields,
- category:
- app.categories !== null &&
- app.categories !== undefined &&
- app.categories.length > 0
- ? app.categories[0]
- : "",
- authentication_id: "",
- finished: false,
- template: app.template === true ? true : false,
- };
-
- // FIXME: overwrite category if the ACTION chosen has a different category
- //
-
- if (!isCloud && (!app.is_valid || (!app.activated && app.generated))) {
- console.log("NOT VALID: Activate!")
-
- activateApp(app.id, false)
- }
-
- // const image = "url("+app.large_image+")"
- // FIXME - find the cytoscape offset position
- // Can this be done with zoom calculations?
- const nodeToBeAdded = {
- group: "nodes",
- data: newAppData,
- renderedPosition: {
- x: e.pageX - cycontainer.offsetLeft,
- y: e.pageY - cycontainer.offsetTop,
- },
- };
-
- parsedApp = nodeToBeAdded;
- cy.add(nodeToBeAdded);
- return;
- }
- }
- };
const getNextActionName = (appName) => {
@@ -13601,7 +13641,7 @@ const releaseToConnectLabel = "Release to Connect"
// Special SCHEDULE handler
var trigger_header_auth = ""
- if (Object.getOwnPropertyNames(selectedTrigger).length > 0 && workflow.triggers[selectedTriggerIndex] !== undefined ) {
+ if (Object.getOwnPropertyNames(selectedTrigger).length > 0 && workflow.triggers !== null && workflow.triggers !== undefined && workflow.triggers.length >= selectedTriggerIndex && workflow.triggers[selectedTriggerIndex] !== undefined ) {
if (selectedTrigger.trigger_type === "SCHEDULE" && workflow.triggers[selectedTriggerIndex].parameters === undefined || workflow.triggers[selectedTriggerIndex].parameters === null) {
console.log("Autofixing schedule")
@@ -15495,34 +15535,49 @@ const releaseToConnectLabel = "Release to Connect"
View Suborg workflow