- {top_text === "Base Cloud Access" && userdata.has_card_available === true ?
+ {top_text === "Base Cloud Access" && userdata.has_card_available === true && !isScale ?
{
"While you have a card attached to your account, Shuffle will no longer prevent workflows from running. Billing will occur at the start of each month."
:
isCloud ?
- `You are not subscribed to any plan and are using the free plan with max 10,000 app runs per month. Upgrade to deactivate this limit.`
+ userdata?.app_execution_limit && userdata?.app_execution_limit >= 300000 ?
+ "You have subscribed to the Enterprise plan, which includes " + (userdata?.app_execution_limit/1000) + "K app runs/month. You can increase the limit by upgrading current plan. Contact support@shuffler.io for more information." :
+ `You are not subscribed to any plan and are using the free plan with max 10,000 app runs per month. Upgrade to deactivate this limit.`
+
:
`You are not subscribed to any plan and are using the free, open source plan. This plan has no enforced limits, but scale issues may occur due to CPU congestion.`
}
@@ -699,8 +716,33 @@ const LicencePopup = (props) => {
setCalculatedCost("$960")
setSelectedValue(8)
} else {
- setCalculatedCost("$960")
- setSelectedValue(300)
+ if (userdata && userdata?.app_execution_limit) {
+ if (userdata.app_execution_limit >= 300000 && userdata.app_execution_limit < 400000) {
+ setSelectedValue(400)
+ setCalculatedCost("$1280")
+ }else if (userdata?.app_execution_limit >= 400000 && userdata?.app_execution_limit < 500000) {
+ setSelectedValue(500)
+ setCalculatedCost("$1600")
+ } else if (userdata?.app_execution_limit >= 500000 && userdata?.app_execution_limit < 600000) {
+ setSelectedValue(600)
+ setCalculatedCost("$1920")
+ } else if (userdata?.app_execution_limit >= 600000 && userdata?.app_execution_limit < 700000) {
+ setSelectedValue(700)
+ setCalculatedCost("$2240")
+ } else if (userdata?.app_execution_limit >= 700000 && userdata?.app_execution_limit < 800000) {
+ setSelectedValue(800)
+ setCalculatedCost("$2560")
+ } else if (userdata?.app_execution_limit >= 800000 && userdata?.app_execution_limit < 900000) {
+ setSelectedValue(900)
+ setCalculatedCost("$2880")
+ }else {
+ setCalculatedCost("$960")
+ setSelectedValue(300)
+ }
+ }else {
+ setCalculatedCost("$960")
+ setSelectedValue(300)
+ }
}
}, [shuffleVariant])
@@ -977,7 +1019,7 @@ const LicencePopup = (props) => {
: null}
- {isCloud &&
+ {/* {isCloud &&
selectedOrganization.subscriptions !== undefined &&
selectedOrganization.subscriptions !== null &&
selectedOrganization.subscriptions.length > 0 ?
@@ -998,7 +1040,7 @@ const LicencePopup = (props) => {
/>
)
})
- : null}
+ : null} */}
@@ -1006,12 +1048,12 @@ const LicencePopup = (props) => {
-
+ color="primary">Recommended }
{shuffleVariant === 1 ? "Scale" : "Enterprise"}
diff --git a/frontend/src/components/Navbar.jsx b/frontend/src/components/Navbar.jsx
index ebee1db5..c3cca3f8 100644
--- a/frontend/src/components/Navbar.jsx
+++ b/frontend/src/components/Navbar.jsx
@@ -47,7 +47,7 @@ const menuData = {
title: "Shuffle",
description:
"The most versatile automation engine with focus on security.",
- icon: "images/logos/orange_logo.svg",
+ icon: "images/icons/shuffleLogo.svg",
path: "/docs/about",
gaData: {
category: "navbar",
diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx
index 79a9d98a..374ce85b 100755
--- a/frontend/src/views/AngularWorkflow.jsx
+++ b/frontend/src/views/AngularWorkflow.jsx
@@ -575,11 +575,17 @@ const AngularWorkflow = (defaultprops) => {
}, [editWorkflowModalOpen])
useEffect(() => {
- if(selectedTrigger?.trigger_type === "SUBFLOW"){
+ // Check if selectedTriggerIndex is a number >= 0
+ if (isNaN(selectedTriggerIndex) || selectedTriggerIndex < 0) {
+ return
+ }
+
+ if (selectedTrigger?.trigger_type === "SUBFLOW" && selectedTriggerIndex !== undefined && selectedTriggerIndex !== null && workflow?.triggers[selectedTriggerIndex].parameters.length > 1) {
setSelectedTriggerValue(workflow.triggers[selectedTriggerIndex].parameters[1].value || "")
- } else if(selectedTrigger?.trigger_type === "USERINPUT"){
+ } else if (selectedTrigger?.trigger_type === "USERINPUT" && selectedTriggerIndex !== undefined && selectedTriggerIndex !== null && workflow?.triggers[selectedTriggerIndex].parameters.length > 0) {
setSelectedTriggerValue(workflow.triggers[selectedTriggerIndex].parameters[0].value || "Do you want to continue the workflow? Start parameters: $exec")
}
+
}, [selectedTriggerIndex, selectedTrigger, workflow])
useEffect(() => {
@@ -948,11 +954,15 @@ const AngularWorkflow = (defaultprops) => {
}
useEffect(() => {
- if (workflow.actions?.length == 1) {
- if (workflow.actions[0].app_id == "3e320a20966d33c9b7e6790b2705f0bf") {
+ if (workflow?.actions?.length == 1) {
+ if (workflow?.actions[0].app_id == "3e320a20966d33c9b7e6790b2705f0bf") {
setWorkflowAsCode(true);
}
}
+
+ if (workflow?.suborg_distribution !== undefined && workflow?.suborg_distribution !== null && workflow?.suborg_distribution.length > 0) {
+ getChildWorkflows(workflow.id)
+ }
}, [workflow]);
// Event for making sure app is correct
@@ -1495,6 +1505,8 @@ const AngularWorkflow = (defaultprops) => {
if (workflow.org_id !== undefined && workflow.org_id !== null && workflow.org_id.length > 0) {
headers["Org-Id"] = workflow.org_id
}
+
+ setWorkflows([])
fetch(globalUrl + "/api/v1/workflows?subflow=true", {
method: "GET",
@@ -1512,7 +1524,7 @@ const AngularWorkflow = (defaultprops) => {
if (responseJson !== undefined) {
// Sets up subflow trigger with the right info
- if (trigger_index > -1) {
+ if (isNaN(trigger_index) === false && trigger_index > -1) {
var baseSubflow = {}
const trigger = workflow.triggers[trigger_index];
@@ -2494,15 +2506,19 @@ const AngularWorkflow = (defaultprops) => {
if (cy !== undefined && cy !== null) {
// scale: 0.3,
// bg: "#27292d",
- if (cy.png !== undefined && cy.png !== null) {
- const cyImageData = cy.png({
- output: "base64uri",
- maxWidth: 480,
- maxHeight: 270,
- })
+ if (cy?.png !== undefined && cy?.png !== null) {
+ try {
+ const cyImageData = cy.png({
+ output: "base64uri",
+ maxWidth: 480,
+ maxHeight: 270,
+ })
- if (cyImageData !== undefined && cyImageData !== null && cyImageData.length > 0) {
- useworkflow.image = cyImageData
+ if (cyImageData !== undefined && cyImageData !== null && cyImageData.length > 0) {
+ useworkflow.image = cyImageData
+ }
+ } catch (e) {
+ console.log("Failed to get image data: ", e)
}
}
}
@@ -3914,6 +3930,10 @@ const AngularWorkflow = (defaultprops) => {
}
const findWorkflowDiff = (parentWorkflow, childWorkflow) => {
+ // Ensures new memory is used
+ parentWorkflow = JSON.parse(JSON.stringify(parentWorkflow))
+ childWorkflow = JSON.parse(JSON.stringify(childWorkflow))
+
var diff = {
"different": false,
"environment": false,
@@ -3931,9 +3951,13 @@ const AngularWorkflow = (defaultprops) => {
return diff
}
-
var parentEnvironment = ""
var childEnvironment = ""
+
+ if (parentWorkflow.triggers !== undefined && parentWorkflow.triggers !== null && parentWorkflow.triggers.length > 0) {
+ parentWorkflow.actions = parentWorkflow.actions.concat(parentWorkflow.triggers)
+ }
+
for (var parentKey in parentWorkflow.actions) {
const parentAction = parentWorkflow.actions[parentKey]
if (parentAction.environment !== undefined && parentAction.environment !== null && parentAction.environment !== "") {
@@ -3945,6 +3969,19 @@ const AngularWorkflow = (defaultprops) => {
}
var found = false
+ if (childWorkflow.triggers !== undefined && childWorkflow.triggers !== null && childWorkflow.triggers.length > 0) {
+ for (var triggerKey in childWorkflow.triggers) {
+ if (childWorkflow.triggers[triggerKey].replacement_for_trigger !== parentAction.id) {
+ continue
+ }
+
+ // Rewrapping the ID just in case
+ childWorkflow.triggers[triggerKey].id = childWorkflow.triggers[triggerKey].replacement_for_trigger
+ childWorkflow.actions.push(childWorkflow.triggers[triggerKey])
+ break
+ }
+ }
+
for (var childKey in childWorkflow.actions) {
const childAction = childWorkflow.actions[childKey]
if (childAction.environment !== undefined && childAction.environment !== null && childAction.environment !== "") {
@@ -3991,6 +4028,10 @@ const AngularWorkflow = (defaultprops) => {
continue
}
+ var parentworkflow = ""
+ var parentstartnode = ""
+ var childworkflow = ""
+ var childstartnode = ""
for (var parentParamIndex in parentAction.parameters) {
const parentParam = parentAction.parameters[parentParamIndex]
for (var childParamIndex in childAction.parameters) {
@@ -3999,20 +4040,38 @@ const AngularWorkflow = (defaultprops) => {
continue
}
+ if (childParam.name === "workflow" || childParam.name === "subflow") {
+ parentworkflow = parentParam.value
+ childworkflow = childParam.value
+ continue
+ }
+
+ if (childParam.name == "startnode") {
+ parentstartnode = parentParam.value
+ childstartnode = childParam.value
+ continue
+ }
+
if (childParam.value !== parentParam.value) {
actionDiff.parameters.push(childParam.name)
}
}
}
+
+ if (parentworkflow !== childworkflow && parentstartnode !== childstartnode) {
+ actionDiff.parameters.push("subflow")
+ }
}
if (actionDiff.parameters.length > 0) {
actionDiff.params = true
}
+ /*
if (!found) {
actionDiff.new = true
}
+ */
if (actionDiff !== undefined && actionDiff !== null && Object.keys(actionDiff).length > 1) {
actionDiff.label = parentAction.label.replaceAll("_", " ")
@@ -6305,11 +6364,15 @@ const AngularWorkflow = (defaultprops) => {
if (workflow.org_id !== undefined && workflow.org_id !== null && workflow.org_id.length > 0 && originalWorkflow.org_id !== undefined && originalWorkflow.org_id !== null && originalWorkflow.org_id.length > 0 && workflow.org_id === originalWorkflow.org_id) {
// Allows a parent workflow to control the schedule
} else if (data.replacement_for_trigger !== undefined && data.replacement_for_trigger !== null && data.replacement_for_trigger.length > 0) {
- toast.warning("This schedule is controlled by the parent workflow. If you want additional schedule control, please add a custom schedule to this workflow.", {
- autoClose: 30000,
- })
- event.target.unselect()
- return
+
+ // No custom control on cloud
+ if (isCloud) {
+ toast.warning("This schedule is controlled by the parent workflow. If you want additional schedule control, please add a custom schedule to this workflow.", {
+ autoClose: 30000,
+ })
+ event.target.unselect()
+ return
+ }
}
} else if (data.app_name === "Webhook" && trigger_index >= 0) {
@@ -6885,7 +6948,7 @@ const AngularWorkflow = (defaultprops) => {
)
if (targetnode !== -1) {
if (workflow.triggers[targetnode].app_name === "User Input" || workflow.triggers[targetnode].app_name === "Shuffle Workflow" || workflow.triggers[targetnode].app_name === "Shuffle Subflow") {
- console.log("User Input or Shuffle Workflow")
+ //console.log("User Input or Shuffle Workflow")
} else {
toast("Can't have triggers as target of branch")
event.target.remove()
@@ -9217,11 +9280,15 @@ const AngularWorkflow = (defaultprops) => {
}
insertedNodes = insertedNodes.concat(newedges);
- setWorkflow(inputworkflow);
+ setWorkflow(inputworkflow)
// Reset view for cytoscape
if (cy !== undefined && cy !== null) {
- cy.add(insertedNodes)
+ try {
+ cy.add(insertedNodes)
+ } catch (error) {
+ console.log("Error adding nodes to cytoscape (6): ", error)
+ }
try {
cy.fit(null, 250)
@@ -9300,12 +9367,6 @@ const AngularWorkflow = (defaultprops) => {
}
}
- //if (selectedNode.data("id") === selectedAction.id) {
- // setSelectedApp({});
- // setSelectedAction({});
- //setSelectedTrigger({});
- //setSelectedTriggerIndex({});
- //}
const parsedSelection = cy.$(":selected");
if (selectedNode.data().decorator === true && selectedNode.data("type") !== "COMMENT") {
toast("This node can't be deleted.");
@@ -9505,7 +9566,6 @@ const AngularWorkflow = (defaultprops) => {
if (firstrequest) {
setFirstrequest(false)
getWorkflow(props.match.params.key, {})
- getChildWorkflows(props.match.params.key)
getRevisionHistory(props.match.params.key)
loadTriggers()
getApps()
@@ -14891,12 +14951,15 @@ const AngularWorkflow = (defaultprops) => {
}}
>
- Select a workflow to execute
+ Select a workflow to run