+
-
+
+
Publishing
+
+
- Publishing is related to making the workflow itself public. When publishing a workflow, all the details (except sensitive info) become available to everyone. The details below will help a user understand this better. When a workflow is published, you keep the original, and a copy enters the workflow search, and is associated with your creator account, if you have one. You can always unpublish the workflow after. When ready to publish, click the three dots next to a workflow on the main workflow screen. After publishing, you can find it in the Shuffle search engine.
+ Publishing is related to making this workflow itself public. When publishing a workflow, all the details (except sensitive info) become available to anyone. The fields below will help a user and Shuffle's system understand your workflow better. When a workflow is published, you keep the original, and a copy enters the Shuffle workflow search, and is associated with your creator or partner account, if you have one. You can always unpublish the workflow after. When ready to publish, click the three dots next to a workflow on the main workflow page.
+
+ You can always unpublish a workflow after.
+
{
console.log('escape pressed')
setRenderTextBox(false);
}
-
}
const changeDistribution = (id, selectedSubOrg) => {
@@ -1051,6 +1050,7 @@ const Files = memo((props) => {
) : null}
+
{renderTextBox ?
diff --git a/frontend/src/components/WorkflowValidationTimeline.jsx b/frontend/src/components/WorkflowValidationTimeline.jsx
index 14661ebf..b02b295d 100644
--- a/frontend/src/components/WorkflowValidationTimeline.jsx
+++ b/frontend/src/components/WorkflowValidationTimeline.jsx
@@ -28,7 +28,16 @@ import { validateJson, GetIconInfo } from "../views/Workflows.jsx";
import theme from "../theme.jsx";
const itemHeight = 24
-export const getParentNodes = (workflow, action) => {
+export const getParentNodes = (workflow, action, count) => {
+ if (count === undefined) {
+ count = 0
+ }
+
+ // 50 levels of parent nodes
+ if (count > 50) {
+ return []
+ }
+
if (action === undefined || action === null) {
return []
}
@@ -81,8 +90,7 @@ export const getParentNodes = (workflow, action) => {
continue;
}
- // FIXME: This part is only handling first level,
- // but needs to recurse
+ // FIXME: recursion
var incomingEdges = []
for (var branchkey in workflow.branches) {
const branch = workflow.branches[branchkey]
@@ -90,13 +98,19 @@ export const getParentNodes = (workflow, action) => {
continue
}
- // Go up in the levels
+ // FIXME: Go up in the levels
+ // This somehow creates infinite recursion for now, so
+ // we are skipping it.
+ // This function is also not used for cytoscape recursion,
+ // so it doesn't matter much (yet)
+ /*
const parents = getParentNodes(workflow, {
id: branch.source_id,
- })
+ }, count+1)
if (parents.length > 0) {
incomingEdges = incomingEdges.concat(parents)
}
+ */
incomingEdges.push(branch)
}
@@ -215,8 +229,6 @@ const WorkflowValidationTimeline = (props) => {
}
}
- //const parents = getParentNodes(workflow, action)
- //console.log("PARENTS", key, parents)
if (parents !== undefined && parents !== null && parents.length > 0) {
const parentfound = parents.find((element) => element.id === startnodeId)
if (parentfound !== undefined) {
diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx
index bb46004d..ce607d45 100755
--- a/frontend/src/views/AngularWorkflow.jsx
+++ b/frontend/src/views/AngularWorkflow.jsx
@@ -574,7 +574,7 @@ const AngularWorkflow = (defaultprops) => {
}, [editWorkflowModalOpen])
useEffect(() => {
- if (selectedTrigger !== undefined && selectedTrigger.parameters !== undefined && selectedTrigger.parameters !== undefined && selectedTrigger.parameters.length > 1) {
+ if (selectedTrigger !== undefined && selectedTrigger?.parameters !== undefined && selectedTrigger?.parameters !== null && selectedTrigger?.parameters?.length > 1) {
// Right now just setting for the subflow
setSelectedTriggerValue(selectedTrigger?.parameters[1]?.value)
}
@@ -4916,7 +4916,7 @@ const AngularWorkflow = (defaultprops) => {
if (!branchFound) {
var relevantNodes = []
- const minDistance = 225
+ const minDistance = 185
const draggedNode = event.target
const allnodes = cy.nodes().jsons()
for (var nodekey in allnodes) {
@@ -5481,6 +5481,7 @@ const AngularWorkflow = (defaultprops) => {
// https://stackoverflow.com/questions/16677856/cy-onselect-callback-only-once
// onNodeClick
const onNodeSelect = (event, newAppAuth) => {
+
// Forces all states to update at the same time,
// Otherwise everything is SUPER slow
@@ -5654,7 +5655,14 @@ const AngularWorkflow = (defaultprops) => {
}
ReactDOM.unstable_batchedUpdates(() => {
+ const selectedNodes = cy.$(':selected')
if (data.isButton) {
+ if (selectedNodes?.length > 1) {
+ event.target.unselect()
+ //console.log(": ", selectedNodes.length)
+ return
+ }
+
if (data.buttonType === "suggestion") {
if (cy === undefined) {
console.log("Cy not defined yet")
@@ -5894,6 +5902,14 @@ const AngularWorkflow = (defaultprops) => {
}
if (data.type === "ACTION") {
+ if (selectedNodes?.length > 1) {
+ console.log("Unselecting ACTION due to multiple nodes selected")
+ setSelectedAction({})
+ setSelectedApp({})
+ setSelectedComment({})
+ return
+ }
+
setSelectedComment({})
// FIXME: is this what is mapping it an actual action in the workflow? wtf?
@@ -6241,6 +6257,14 @@ const AngularWorkflow = (defaultprops) => {
setSelectedActionEnvironment(env);
}
} else if (data.type === "TRIGGER") {
+ if (selectedNodes?.length > 1) {
+ console.log("Unselecting ACTION due to multiple nodes selected")
+ setSelectedAction({})
+ setSelectedApp({})
+ setSelectedComment({})
+ return
+ }
+
setSelectedComment({})
if (workflow.triggers === null) {
workflow.triggers = []
@@ -6442,6 +6466,14 @@ const AngularWorkflow = (defaultprops) => {
//setSelectedActionEnvironment(data.env)
}, 25)
} else if (data.type === "COMMENT") {
+ if (selectedNodes?.length > 1) {
+ console.log("Unselecting ACTION due to multiple nodes selected")
+ setSelectedAction({})
+ setSelectedApp({})
+ setSelectedComment({})
+ return
+ }
+
setSelectedComment(data);
} else {
toast("Can't handle node type " + data.type);
@@ -7450,26 +7482,21 @@ const AngularWorkflow = (defaultprops) => {
};
const handlePaste = (event) => {
- //console.log("EV: ", event)
if (
event.path !== undefined &&
event.path !== null &&
event.path.length > 0
) {
- //console.log("PATH: ", event.path[0])
if (event.path[0].localName !== "body") {
- //console.log("Skipping because body is not targeted")
return;
}
}
- //console.log("PATH2: ", event.target)
if (
event.target !== undefined &&
event.target !== null
) {
if (event.target.localName !== "body") {
- //console.log("Skipping because body is not targeted")
return;
}
}
@@ -7479,12 +7506,10 @@ const AngularWorkflow = (defaultprops) => {
const clipboard = (event.originalEvent || event).clipboardData.getData(
"text/plain"
);
- //console.log("Text: ", clipboard)
- //window.document.execCommand('insertText', false, text);
- //
+
try {
+ const allnodes = cy.nodes().jsons()
var parsedjson = JSON.parse(clipboard);
- // Check if array
if (!Array.isArray(parsedjson)) {
console.log("Not array! Adding to array.")
parsedjson = [parsedjson]
@@ -7492,7 +7517,6 @@ const AngularWorkflow = (defaultprops) => {
for (let jsonkey in parsedjson) {
var item = parsedjson[jsonkey];
- console.log("Adding: ", item);
if (item.data === undefined || item.data === null) {
console.log("Appending from here")
@@ -7512,13 +7536,31 @@ const AngularWorkflow = (defaultprops) => {
item.data.isStartNode = false
}
+ // Find a cy.data() label with the same name
+ const foundnodes = allnodes.filter((data) => {
+ //console.log("COMP: ", data.data.label, item.data.label)
+ if (data.data.label === undefined || data.data.label === null) {
+ return false
+ }
+
+ return data.data.label === item.data.label
+ })
+
+ if (foundnodes !== undefined && foundnodes !== null && foundnodes.length > 0) {
+ // Weird naming copy lol
+ item.data.label = item.data.label + "_copy_" + allnodes.length
+ }
+
item.data.id = uuidv4()
cy.add({
group: item.group,
data: item.data,
- position: item.position,
- });
+ position: {
+ x: item.position.x+20,
+ y: item.position.y+20,
+ },
+ })
}
} catch (e) {
console.log("Error pasting: ", e);
@@ -9591,7 +9633,12 @@ const AngularWorkflow = (defaultprops) => {
console.log("Error fitting cytoscape (4): ", error)
}
+
cy.on("boxselect", "node", (e) => {
+ e.preventDefault()
+ e.stopPropagation()
+
+ console.log("BOXSELECT: ", e.boxSelectElements)
if (e.target.data("isButton") || e.target.data("isDescriptor") || e.target.data("isSuggestion")) {
e.target.unselect();
}
@@ -9601,10 +9648,15 @@ const AngularWorkflow = (defaultprops) => {
cy.on("boxstart", (e) => {
console.log("START");
+ e.preventDefault()
+ e.stopPropagation()
});
cy.on("boxend", (e) => {
- console.log("END: ", cy)
+ e.preventDefault()
+ e.stopPropagation()
+
+ console.log("END: ", e.target, cy)
var cydata = cy.$(":selected").jsons();
if (cydata !== undefined && cydata !== null && cydata.length > 0) {
// Unselect all nodes
@@ -17404,11 +17456,11 @@ const AngularWorkflow = (defaultprops) => {
selectedTrigger.status === "running"
}
defaultValue={
- selectedTrigger?.parameters === undefined || selectedTrigger?.parameters === null || selectedTrigger?.parameters?.length === 0 ? isCloud || selectedTrigger?.environment === "cloud" ? "*/25 * * * *" : "60" : selectedTrigger.parameters[0]?.value
+ selectedTrigger?.parameters === undefined || selectedTrigger?.parameters === null || selectedTrigger?.parameters?.length === 0 ? isCloud || selectedTrigger?.environment === "cloud" ? "*/25 * * * *" : "60" : selectedTrigger?.parameters[0]?.value
}
color="primary"
placeholder={
- selectedTrigger.parameters === undefined ? isCloud || selectedTrigger?.environment === "cloud" ? "*/25 * * * *" : "60" : selectedTrigger.parameters[0]?.value
+ selectedTrigger.parameters === undefined || selectedTrigger?.parameters === null || selectedTrigger?.parameters?.length === 0 ? isCloud || selectedTrigger?.environment === "cloud" ? "*/25 * * * *" : "60" : selectedTrigger?.parameters[0]?.value
}
onBlur={(e) => {
setTriggerCronWrapper(e.target.value);
@@ -21602,10 +21654,8 @@ const AngularWorkflow = (defaultprops) => {
const checked = validateJson(data.value.trim())
if (data.name === "shuffle_action_logs" && data.value !== undefined && data.value !== null && data.value.length > 0 && data.value.includes("add env SHUFFLE_LOGS_DISABLED")) {
- data.value = `Logs for this action are not available without an onprem environment with the SHUFFLE_LOGS_DISABLED environment variable set to false: SHUFFLE_LOGS_DISABLED=false. Logs are enabled by default, except in scale mode.`
- /*
return (
-
+
{
Action Logs
+ More log details for this action are not available without an onprem environment with the SHUFFLE_LOGS_DISABLED environment variable set to false: SHUFFLE_LOGS_DISABLED=false. Logs are enabled by default, except in scale mode.