Fixed serveral bugs including credential prompting. Added logic to bring links/nodes to the forefront when you hover over them in case there's some overlap

This commit is contained in:
mabashian 2018-11-09 09:15:42 -05:00
parent 61fb3eb390
commit 05f4d94db2
5 changed files with 215 additions and 209 deletions

View File

@ -9,7 +9,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
return {
scope: {
treeState: '=',
graphState: '=',
readOnly: '<',
addNodeWithoutChild: '&',
addNodeWithChild: '&',
@ -55,6 +55,11 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
function init() {
force = d3.layout.force()
// .gravity(0)
// .linkStrength(2)
// .friction(0.4)
// .charge(-4000)
// .linkDistance(300)
.gravity(0)
.charge(-300)
.linkDistance(300)
@ -206,7 +211,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
function update() {
if(scope.dimensionsSet) {
let links = svgGroup.selectAll(".WorkflowChart-link")
.data(scope.treeState.arrayOfLinksForChart, function(d) { return `${d.source.id}-${d.target.id}`; });
.data(scope.graphState.arrayOfLinksForChart, function(d) { return `${d.source.id}-${d.target.id}`; });
// Remove any stale links
links.exit().remove();
@ -217,7 +222,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
baseSvg.selectAll(".WorkflowChart-linkPath")
.attr("class", function(d) {
return (d.source.isNodeBeingAdded || d.target.isNodeBeingAdded) ? "WorkflowChart-linkPath WorkflowChart-isNodeBeingAdded" : "WorkflowChart-linkPath";
return (d.source.id === scope.graphState.nodeBeingAdded || d.target.id === scope.graphState.nodeBeingAdded) ? "WorkflowChart-linkPath WorkflowChart-isNodeBeingAdded" : "WorkflowChart-linkPath";
})
.attr('stroke', function(d) {
let edgeType = d.edgeType;
@ -241,7 +246,11 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
.attr("id", function(d){return "link-" + d.source.id + "-" + d.target.id + "-overlay";})
.attr("class", function(d) {
let linkClasses = ["WorkflowChart-linkOverlay"];
if (d.isLinkBeingEdited) {
if (
scope.graphState.linkBeingEdited &&
d.source.id === scope.graphState.linkBeingEdited.source &&
d.target.id === scope.graphState.linkBeingEdited.target
) {
linkClasses.push("WorkflowChart-link--active");
}
return linkClasses.join(' ');
@ -249,10 +258,10 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
baseSvg.selectAll(".WorkflowChart-circleBetweenNodes")
.attr("id", function(d){return "link-" + d.source.id + "-" + d.target.id + "-add";})
.style("display", function(d) { return (scope.treeState.isLinkMode || d.source.isNodeBeingAdded || d.target.isNodeBeingAdded || scope.readOnly) ? "none" : null; });
.style("display", function(d) { return (scope.graphState.isLinkMode || d.source.id === scope.graphState.nodeBeingAdded || d.target.id === scope.graphState.nodeBeingAdded || scope.readOnly) ? "none" : null; });
baseSvg.selectAll(".WorkflowChart-betweenNodesIcon")
.style("display", function(d) { return (scope.treeState.isLinkMode || d.source.isNodeBeingAdded || d.target.isNodeBeingAdded || scope.readOnly) ? "none" : null; });
.style("display", function(d) { return (scope.graphState.isLinkMode || d.source.id === scope.graphState.nodeBeingAdded || d.target.id === scope.graphState.nodeBeingAdded || scope.readOnly) ? "none" : null; });
// Add any new links
@ -263,7 +272,11 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
linkEnter.append("polygon", "g")
.attr("class", function(d) {
let linkClasses = ["WorkflowChart-linkOverlay"];
if (d.isLinkBeingEdited) {
if (
scope.graphState.linkBeingEdited &&
d.source.id === scope.graphState.linkBeingEdited.source &&
d.target.id === scope.graphState.linkBeingEdited.target
) {
linkClasses.push("WorkflowChart-link--active");
}
return linkClasses.join(' ');
@ -271,8 +284,9 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
.attr("id", function(d){return "link-" + d.source.id + "-" + d.target.id + "-overlay";})
.call(edit_link)
.on("mouseover", function(d) {
if(!scope.treeState.isLinkMode && !d.source.isStartNode && !d.source.isNodeBeingAdded && !d.target.isNodeBeingAdded && scope.mode !== 'details') {
d3.select("#link-" + d.source.id + "-" + d.target.id)
if(!scope.graphState.isLinkMode && !d.source.isStartNode && d.source.id !== scope.graphState.nodeBeingAdded && d.target.id !== scope.graphState.nodeBeingAdded && scope.mode !== 'details') {
$(`#link-${d.source.id}-${d.target.id}`).appendTo(`#aw-workflow-chart-g`);
d3.select(`#link-${d.source.id}-${d.target.id}`)
.classed("WorkflowChart-linkHovering", true);
let xPos, yPos, arrowClass;
@ -314,7 +328,8 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
})
.on("mouseout", function(d){
if(!d.source.isStartNode && !d.target.isNodeBeingAdded && scope.mode !== 'details') {
if(!d.source.isStartNode && d.target.id !== scope.graphState.nodeBeingAdded && scope.mode !== 'details') {
$(`#aw-workflow-chart-g`).prepend($(`#link-${d.source.id}-${d.target.id}`));
d3.select("#link-" + d.source.id + "-" + d.target.id)
.classed("WorkflowChart-linkHovering", false);
}
@ -324,11 +339,12 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
// Add entering links in the parents old position.
linkEnter.append("line")
.attr("class", function(d) {
return (d.source.isNodeBeingAdded || d.target.isNodeBeingAdded) ? "WorkflowChart-linkPath WorkflowChart-isNodeBeingAdded" : "WorkflowChart-linkPath";
return (d.source.id === scope.graphState.nodeBeingAdded || d.target.id === scope.graphState.nodeBeingAdded) ? "WorkflowChart-linkPath WorkflowChart-isNodeBeingAdded" : "WorkflowChart-linkPath";
})
.call(edit_link)
.on("mouseenter", function(d) {
if(!scope.treeState.isLinkMode && !d.source.isStartNode && !d.source.isNodeBeingAdded && !d.target.isNodeBeingAdded && scope.mode !== 'details') {
if(!scope.graphState.isLinkMode && !d.source.isStartNode && d.source.id !== scope.graphState.nodeBeingAdded && d.target.id !== scope.graphState.nodeBeingAdded && scope.mode !== 'details') {
$(`#link-${d.source.id}-${d.target.id}`).appendTo(`#aw-workflow-chart-g`);
d3.select("#link-" + d.source.id + "-" + d.target.id)
.classed("WorkflowChart-linkHovering", true);
@ -370,7 +386,8 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
}
})
.on("mouseleave", function(d){
if(!d.source.isStartNode && !d.target.isNodeBeingAdded && scope.mode !== 'details') {
if(!d.source.isStartNode && d.target.id !== scope.graphState.nodeBeingAdded && scope.mode !== 'details') {
$(`#aw-workflow-chart-g`).prepend($(`#link-${d.source.id}-${d.target.id}`));
d3.select("#link-" + d.source.id + "-" + d.target.id)
.classed("WorkflowChart-linkHovering", false);
}
@ -398,13 +415,15 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
.attr("id", function(d){return "link-" + d.source.id + "-" + d.target.id + "-add";})
.attr("r", 10)
.attr("class", "WorkflowChart-addCircle WorkflowChart-circleBetweenNodes")
.style("display", function(d) { return (scope.treeState.isLinkMode || d.source.isNodeBeingAdded || d.target.isNodeBeingAdded || scope.readOnly) ? "none" : null; })
.style("display", function(d) { return (scope.graphState.isLinkMode || d.source.id === scope.graphState.nodeBeingAdded || d.target.id === scope.graphState.nodeBeingAdded || scope.readOnly) ? "none" : null; })
.call(add_node_with_child)
.on("mouseover", function(d) {
$(`#link-${d.source.id}-${d.target.id}`).appendTo(`#aw-workflow-chart-g`);
d3.select("#link-" + d.source.id + "-" + d.target.id)
.classed("WorkflowChart-addHovering", true);
})
.on("mouseout", function(d){
$(`#aw-workflow-chart-g`).prepend($(`#link-${d.source.id}-${d.target.id}`));
d3.select("#link-" + d.source.id + "-" + d.target.id)
.classed("WorkflowChart-addHovering", false);
});
@ -416,13 +435,15 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
.size(60)
.type("cross")
)
.style("display", function(d) { return (scope.treeState.isLinkMode || d.source.isNodeBeingAdded || d.target.isNodeBeingAdded || scope.readOnly) ? "none" : null; })
.style("display", function(d) { return (scope.graphState.isLinkMode || d.source.id === scope.graphState.nodeBeingAdded || d.target.id === scope.graphState.nodeBeingAdded || scope.readOnly) ? "none" : null; })
.call(add_node_with_child)
.on("mouseover", function(d) {
$(`#link-${d.source.id}-${d.target.id}`).appendTo(`#aw-workflow-chart-g`);
d3.select("#link-" + d.source.id + "-" + d.target.id)
.classed("WorkflowChart-addHovering", true);
})
.on("mouseout", function(d){
$(`#aw-workflow-chart-g`).prepend($(`#link-${d.source.id}-${d.target.id}`));
d3.select("#link-" + d.source.id + "-" + d.target.id)
.classed("WorkflowChart-addHovering", false);
});
@ -435,29 +456,29 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
let linkAddBetweenIcon = svgGroup.selectAll(".WorkflowChart-betweenNodesIcon");
let nodes = svgGroup.selectAll('.WorkflowChart-node')
.data(scope.treeState.arrayOfNodesForChart, function(d) { return d.id; });
.data(scope.graphState.arrayOfNodesForChart, function(d) { return d.id; });
// Remove any stale nodes
nodes.exit().remove();
// Update existing nodes
baseSvg.selectAll(".WorkflowChart-nodeAddCircle")
.style("display", function(d) { return scope.treeState.isLinkMode || d.isNodeBeingAdded || scope.readOnly ? "none" : null; });
.style("display", function(d) { return scope.graphState.isLinkMode || d.id === scope.graphState.nodeBeingAdded || scope.readOnly ? "none" : null; });
baseSvg.selectAll(".WorkflowChart-nodeAddIcon")
.style("display", function(d) { return scope.treeState.isLinkMode || d.isNodeBeingAdded || scope.readOnly ? "none" : null; });
.style("display", function(d) { return scope.graphState.isLinkMode || d.id === scope.graphState.nodeBeingAdded || scope.readOnly ? "none" : null; });
baseSvg.selectAll(".WorkflowChart-linkCircle")
.style("display", function(d) { return scope.treeState.isLinkMode || d.isNodeBeingAdded || scope.readOnly ? "none" : null; });
.style("display", function(d) { return scope.graphState.isLinkMode || d.id === scope.graphState.nodeBeingAdded || scope.readOnly ? "none" : null; });
baseSvg.selectAll(".WorkflowChart-nodeLinkIcon")
.style("display", function(d) { return scope.treeState.isLinkMode || d.isNodeBeingAdded || scope.readOnly ? "none" : null; });
.style("display", function(d) { return scope.graphState.isLinkMode || d.id === scope.graphState.nodeBeingAdded || scope.readOnly ? "none" : null; });
baseSvg.selectAll(".WorkflowChart-nodeRemoveCircle")
.style("display", function(d) { return scope.treeState.isLinkMode || d.isNodeBeingAdded || scope.readOnly ? "none" : null; });
.style("display", function(d) { return scope.graphState.isLinkMode || d.id === scope.graphState.nodeBeingAdded || scope.readOnly ? "none" : null; });
baseSvg.selectAll(".WorkflowChart-nodeRemoveIcon")
.style("display", function(d) { return scope.treeState.isLinkMode || d.isNodeBeingAdded || scope.readOnly ? "none" : null; });
.style("display", function(d) { return scope.graphState.isLinkMode || d.id === scope.graphState.nodeBeingAdded || scope.readOnly ? "none" : null; });
baseSvg.selectAll(".WorkflowChart-rect")
.attr('stroke', function(d) {
@ -477,7 +498,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
}
})
.attr("class", function(d) {
let classString = d.isNodeBeingAdded ? "WorkflowChart-rect WorkflowChart-isNodeBeingAdded" : "WorkflowChart-rect";
let classString = d.id === scope.graphState.nodeBeingAdded ? "WorkflowChart-rect WorkflowChart-isNodeBeingAdded" : "WorkflowChart-rect";
classString += !d.unifiedJobTemplate ? " WorkflowChart-dashedNode" : "";
return classString;
});
@ -561,17 +582,17 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
.style("display", function(d){ return d.job && d.job.status && d.job.id ? null : "none"; });
baseSvg.selectAll(".WorkflowChart-deletedText")
.style("display", function(d){ return d.unifiedJobTemplate || d.isNodeBeingAdded ? "none" : null; });
.style("display", function(d){ return d.unifiedJobTemplate || d.id === scope.graphState.nodeBeingAdded ? "none" : null; });
baseSvg.selectAll(".WorkflowChart-activeNode")
.style("display", function(d) { return d.isNodeBeingEdited ? null : "none"; });
.style("display", function(d) { return d.id === scope.graphState.nodeBeingEdited ? null : "none"; });
baseSvg.selectAll(".WorkflowChart-elapsed")
.style("display", function(d) { return (d.job && d.job.elapsed) ? null : "none"; });
baseSvg.selectAll(".WorkflowChart-addLinkCircle")
.attr("fill", function(d) { return scope.treeState.addLinkSource === d.id ? "#337AB7" : "#D7D7D7"; })
.style("display", function(d) { return scope.treeState.isLinkMode && !d.isInvalidLinkTarget ? null : "none"; });
.attr("fill", function(d) { return scope.graphState.addLinkSource === d.id ? "#337AB7" : "#D7D7D7"; })
.style("display", function(d) { return scope.graphState.isLinkMode && !d.isInvalidLinkTarget ? null : "none"; });
// Add new nodes
const nodeEnter = nodes
@ -619,7 +640,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
.attr("cx", nodeW)
.attr("r", 8)
.attr("class", "WorkflowChart-addLinkCircle")
.style("display", function() { return scope.treeState.isLinkMode ? null : "none"; });
.style("display", function() { return scope.graphState.isLinkMode ? null : "none"; });
thisNode.append("rect")
.attr("width", nodeW)
.attr("height", nodeH)
@ -643,7 +664,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
})
.attr('stroke-width', "2px")
.attr("class", function(d) {
let classString = d.isNodeBeingAdded ? "WorkflowChart-rect WorkflowChart-isNodeBeingAdded" : "WorkflowChart-rect";
let classString = d.id === scope.graphState.nodeBeingAdded ? "WorkflowChart-rect WorkflowChart-isNodeBeingAdded" : "WorkflowChart-rect";
classString += !_.get(d, 'unifiedJobTemplate.name') ? " WorkflowChart-dashedNode" : "";
return classString;
});
@ -651,7 +672,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
thisNode.append("path")
.attr("d", rounded_rect(1, 0, 5, nodeH, 5, 1, 0, 1, 0))
.attr("class", "WorkflowChart-activeNode")
.style("display", function(d) { return d.isNodeBeingEdited ? null : "none"; });
.style("display", function(d) { return d.id === scope.graphState.nodeBeingEdited ? null : "none"; });
thisNode.append("text")
.attr("x", function(d){ return (scope.mode === 'details' && d.job && d.job.status) ? 20 : nodeW / 2; })
@ -673,7 +694,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
.html(function () {
return `<span>${TemplatesStrings.get('workflow_maker.DELETED')}</span>`;
})
.style("display", function(d) { return d.unifiedJobTemplate || d.isNodeBeingAdded ? "none" : null; });
.style("display", function(d) { return d.unifiedJobTemplate || d.id === scope.graphState.nodeBeingAdded ? "none" : null; });
thisNode.append("circle")
.attr("cy", nodeH)
@ -738,6 +759,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
.call(node_click)
.on("mouseover", function(d) {
if(!d.isStartNode) {
$(`#node-${d.id}`).appendTo(`#aw-workflow-chart-g`);
let resourceName = (d.unifiedJobTemplate && d.unifiedJobTemplate.name) ? d.unifiedJobTemplate.name : "";
if(resourceName && resourceName.length > maxNodeTextLength) {
// When the graph is initially rendered all the links come after the nodes (when you look at the dom).
@ -773,8 +795,8 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
});
}
if (scope.treeState.isLinkMode && !d.isInvalidLinkTarget && scope.treeState.addLinkSource !== d.id) {
let sourceNode = d3.select(`#node-${scope.treeState.addLinkSource}`);
if (scope.graphState.isLinkMode && !d.isInvalidLinkTarget && scope.graphState.addLinkSource !== d.id) {
let sourceNode = d3.select(`#node-${scope.graphState.addLinkSource}`);
const sourceNodeX = d3.transform(sourceNode.attr("transform")).translate[0];
const sourceNodeY = d3.transform(sourceNode.attr("transform")).translate[1];
@ -821,7 +843,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
.attr("cx", nodeW)
.attr("r", 10)
.attr("class", "WorkflowChart-addCircle WorkflowChart-nodeAddCircle")
.style("display", function(d) { return d.isNodeBeingAdded || scope.readOnly ? "none" : null; })
.style("display", function(d) { return d.id === scope.graphState.nodeBeingAdded || scope.readOnly ? "none" : null; })
.call(add_node_without_child)
.on("mouseover", function(d) {
d3.select("#node-" + d.id)
@ -843,7 +865,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
.size(60)
.type("cross")
)
.style("display", function(d) { return d.isNodeBeingAdded || scope.readOnly ? "none" : null; })
.style("display", function(d) { return d.id === scope.graphState.nodeBeingAdded || scope.readOnly ? "none" : null; })
.call(add_node_without_child)
.on("mouseover", function(d) {
d3.select("#node-" + d.id)
@ -863,7 +885,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
.attr("cy", nodeH/2)
.attr("r", 10)
.attr("class", "WorkflowChart-linkCircle")
.style("display", function(d) { return d.isNodeBeingAdded || scope.readOnly ? "none" : null; })
.style("display", function(d) { return d.id === scope.graphState.nodeBeingAdded || scope.readOnly ? "none" : null; })
.call(add_link)
.on("mouseover", function(d) {
d3.select("#node-" + d.id)
@ -877,8 +899,6 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
d3.select("#node-" + d.id + "-link")
.classed("WorkflowChart-linkButtonHovering", false);
});
// TODO: clean up the placement of this icon... this works but it's not
// clean
thisNode.append("foreignObject")
.attr("x", nodeW - 6)
.attr("y", nodeH/2 - 9)
@ -887,7 +907,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
return `<span class="fa fa-link" />`;
})
.attr("class", "WorkflowChart-nodeLinkIcon")
.style("display", function(d) { return d.isNodeBeingAdded || scope.readOnly ? "none" : null; })
.style("display", function(d) { return d.id === scope.graphState.nodeBeingAdded || scope.readOnly ? "none" : null; })
.call(add_link)
.on("mouseover", function(d) {
d3.select("#node-" + d.id)
@ -907,7 +927,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
.attr("cy", nodeH)
.attr("r", 10)
.attr("class", "WorkflowChart-nodeRemoveCircle")
.style("display", function(d) { return (d.isStartNode || d.isNodeBeingAdded || scope.readOnly) ? "none" : null; })
.style("display", function(d) { return (d.isStartNode || d.id === scope.graphState.nodeBeingAdded || scope.readOnly) ? "none" : null; })
.call(remove_node)
.on("mouseover", function(d) {
d3.select("#node-" + d.id)
@ -929,7 +949,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
.size(60)
.type("cross")
)
.style("display", function(d) { return (d.isStartNode || d.isNodeBeingAdded || scope.readOnly) ? "none" : null; })
.style("display", function(d) { return (d.isStartNode || d.id === scope.graphState.nodeBeingAdded || scope.readOnly) ? "none" : null; })
.call(remove_node)
.on("mouseover", function(d) {
d3.select("#node-" + d.id)
@ -1004,7 +1024,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
});
// TODO: this
// if(scope.treeState.arrayOfNodesForChart && scope.treeState.arrayOfNodesForChart > 1 && !graphLoaded) {
// if(scope.graphState.arrayOfNodesForChart && scope.graphState.arrayOfNodesForChart > 1 && !graphLoaded) {
// zoomToFitChart();
// }
@ -1017,7 +1037,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
let tick = () => {
linkLines
.each(function(d) {
d.target.y = scope.treeState.depthMap[d.target.id] * 300;
d.target.y = scope.graphState.depthMap[d.target.id] * 300;
})
.attr("x1", function(d) { return d.target.y; })
.attr("y1", function(d) { return d.target.x + (nodeH/2); })
@ -1068,8 +1088,8 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
};
force
.nodes(scope.treeState.arrayOfNodesForChart)
.links(scope.treeState.arrayOfLinksForChart)
.nodes(scope.graphState.arrayOfNodesForChart)
.links(scope.graphState.arrayOfLinksForChart)
.on("tick", tick)
.start();
}
@ -1086,7 +1106,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
function add_node_without_child() {
this.on("click", function(d) {
if(!scope.readOnly && !scope.treeState.isLinkMode) {
if(!scope.readOnly && !scope.graphState.isLinkMode) {
scope.addNodeWithoutChild({
parent: d
});
@ -1096,7 +1116,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
function add_node_with_child() {
this.on("click", function(d) {
if(!scope.readOnly && !scope.treeState.isLinkMode) {
if(!scope.readOnly && !scope.graphState.isLinkMode) {
scope.addNodeWithChild({
link: d
});
@ -1106,7 +1126,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
function remove_node() {
this.on("click", function(d) {
if(!d.isStartNode && !scope.readOnly && !scope.treeState.isLinkMode) {
if(!d.isStartNode && !scope.readOnly && !scope.graphState.isLinkMode) {
scope.deleteNode({
nodeToDelete: d
});
@ -1116,13 +1136,13 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
function node_click() {
this.on("click", function(d) {
if(!d.isStartNode && !scope.readOnly){
if(scope.treeState.isLinkMode && !d.isInvalidLinkTarget) {
if(d.id !== scope.graphState.nodeBeingAdded && !scope.readOnly){
if(scope.graphState.isLinkMode && !d.isInvalidLinkTarget) {
$('.WorkflowChart-potentialLink').remove();
scope.selectNodeForLinking({
nodeToStartLink: d
});
} else if(!scope.treeState.isLinkMode) {
} else if(!scope.graphState.isLinkMode) {
scope.editNode({
nodeToEdit: d
});
@ -1134,7 +1154,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
function edit_link() {
this.on("click", function(d) {
if(!scope.treeState.isLinkMode && !d.source.isStartNode && !d.source.isNodeBeingAdded && !d.target.isNodeBeingAdded && scope.mode !== 'details'){
if(!scope.graphState.isLinkMode && !d.source.isStartNode && d.source.id !== scope.graphState.nodeBeingAdded && d.target.id !== scope.graphState.nodeBeingAdded && scope.mode !== 'details'){
scope.editLink({
linkToEdit: d
});
@ -1144,7 +1164,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
function add_link() {
this.on("click", function(d) {
if (!scope.readOnly && !scope.treeState.isLinkMode) {
if (!scope.readOnly && !scope.graphState.isLinkMode) {
scope.selectNodeForLinking({
nodeToStartLink: d
});
@ -1198,7 +1218,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
}
scope.$on('refreshWorkflowChart', function(){
if(scope.treeState) {
if(scope.graphState) {
update();
}
});
@ -1219,12 +1239,12 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
zoomToFitChart();
});
let clearWatchTreeState = scope.$watch('treeState.arrayOfNodesForChart', function(newVal) {
let clearWatchgraphState = scope.$watch('graphState.arrayOfNodesForChart', function(newVal) {
if(newVal) {
// scope.treeState.arrayOfNodesForChart
// scope.graphState.arrayOfNodesForChart
update();
clearWatchTreeState();
clearWatchgraphState();
}
});

View File

@ -12,11 +12,8 @@ export default ['$scope', 'TemplatesService',
Empty, PromptService, Rest, TemplatesStrings, WorkflowChartService) {
$scope.strings = TemplatesStrings;
// TODO: I don't think this needs to be on scope but changing it will require changes to
// all the prompt places
$scope.preventCredsWithPasswords = true;
let credentialRequests = [];
let deletedNodeIds = [];
let workflowMakerNodeIdCounter = 1;
let nodeIdToChartNodeIdMapping = {};
@ -87,15 +84,16 @@ export default ['$scope', 'TemplatesService',
$scope.closeWorkflowMaker = function() {
// Revert the data to the master which was created when the dialog was opened
$scope.treeState.nodeTree = angular.copy($scope.treeStateMaster);
$scope.graphState.nodeTree = angular.copy($scope.graphStateMaster);
$scope.closeDialog();
};
$scope.saveWorkflowMaker = function () {
if ($scope.treeState.arrayOfNodesForChart.length > 1) {
if ($scope.graphState.arrayOfNodesForChart.length > 1) {
let addPromises = [];
let editPromises = [];
let credentialsToPost = [];
Object.keys(nodeRef).map((workflowMakerNodeId) => {
if (nodeRef[workflowMakerNodeId].isNew) {
@ -104,27 +102,26 @@ export default ['$scope', 'TemplatesService',
data: buildSendableNodeData(nodeRef[workflowMakerNodeId])
}).then(({data}) => {
nodeRef[workflowMakerNodeId].originalNodeObject = data;
// TODO: do we need this?
nodeIdToChartNodeIdMapping[data.id] = parseInt(workflowMakerNodeId);
// if (_.get(params, 'node.promptData.launchConf.ask_credential_on_launch')) {
// // This finds the credentials that were selected in the prompt but don't occur
// // in the template defaults
// let credentialsToPost = params.node.promptData.prompts.credentials.value.filter(function (credFromPrompt) {
// let defaultCreds = _.get(params, 'node.promptData.launchConf.defaults.credentials', []);
// return !defaultCreds.some(function (defaultCred) {
// return credFromPrompt.id === defaultCred.id;
// });
// });
//
// credentialsToPost.forEach((credentialToPost) => {
// credentialRequests.push({
// id: data.data.id,
// data: {
// id: credentialToPost.id
// }
// });
// });
// }
if (_.get(nodeRef[workflowMakerNodeId], 'promptData.launchConf.ask_credential_on_launch')) {
// This finds the credentials that were selected in the prompt but don't occur
// in the template defaults
let credentialIdsToPost = nodeRef[workflowMakerNodeId].promptData.prompts.credentials.value.filter(function (credFromPrompt) {
let defaultCreds = _.get(nodeRef[workflowMakerNodeId], 'promptData.launchConf.defaults.credentials', []);
return !defaultCreds.some(function (defaultCred) {
return credFromPrompt.id === defaultCred.id;
});
});
credentialIdsToPost.forEach((credentialToPost) => {
credentialsToPost.push({
id: data.id,
data: {
id: credentialToPost.id
}
});
});
}
}));
} else if (nodeRef[workflowMakerNodeId].isEdited) {
editPromises.push(TemplatesService.editWorkflowNode({
@ -146,9 +143,9 @@ export default ['$scope', 'TemplatesService',
let linkMap = {};
// Build a link map for easy access
$scope.treeState.arrayOfLinksForChart.forEach(link => {
// link.source.index of 0 is our artificial start node
if (link.source.index !== 0) {
$scope.graphState.arrayOfLinksForChart.forEach(link => {
// link.source.id of 1 is our artificial start node
if (link.source.id !== 1) {
const sourceNodeId = nodeRef[link.source.id].originalNodeObject.id;
const targetNodeId = nodeRef[link.target.id].originalNodeObject.id;
if (!linkMap[sourceNodeId]) {
@ -219,13 +216,13 @@ export default ['$scope', 'TemplatesService',
Object.keys(linkMap).map((sourceNodeId) => {
Object.keys(linkMap[sourceNodeId]).map((targetNodeId) => {
const foo = nodeIdToChartNodeIdMapping[sourceNodeId];
const bar = nodeIdToChartNodeIdMapping[targetNodeId];
const sourceChartNodeId = nodeIdToChartNodeIdMapping[sourceNodeId];
const targetChartNodeId = nodeIdToChartNodeIdMapping[targetNodeId];
switch(linkMap[sourceNodeId][targetNodeId]) {
case "success":
if (
!nodeRef[foo].originalNodeObject.success_nodes ||
!nodeRef[foo].originalNodeObject.success_nodes.includes(nodeRef[bar].id)
!nodeRef[sourceChartNodeId].originalNodeObject.success_nodes ||
!nodeRef[sourceChartNodeId].originalNodeObject.success_nodes.includes(nodeRef[targetChartNodeId].id)
) {
associatePromises.push(
TemplatesService.associateWorkflowNode({
@ -238,8 +235,8 @@ export default ['$scope', 'TemplatesService',
break;
case "failure":
if (
!nodeRef[foo].originalNodeObject.failure_nodes ||
!nodeRef[foo].originalNodeObject.failure_nodes.includes(nodeRef[bar].id)
!nodeRef[sourceChartNodeId].originalNodeObject.failure_nodes ||
!nodeRef[sourceChartNodeId].originalNodeObject.failure_nodes.includes(nodeRef[targetChartNodeId].id)
) {
associatePromises.push(
TemplatesService.associateWorkflowNode({
@ -252,8 +249,8 @@ export default ['$scope', 'TemplatesService',
break;
case "always":
if (
!nodeRef[foo].originalNodeObject.always_nodes ||
!nodeRef[foo].originalNodeObject.always_nodes.includes(nodeRef[bar].id)
!nodeRef[sourceChartNodeId].originalNodeObject.always_nodes ||
!nodeRef[sourceChartNodeId].originalNodeObject.always_nodes.includes(nodeRef[targetChartNodeId].id)
) {
associatePromises.push(
TemplatesService.associateWorkflowNode({
@ -270,9 +267,7 @@ export default ['$scope', 'TemplatesService',
$q.all(disassociatePromises)
.then(function () {
// TODO: don't forget about this....
let credentialPromises = credentialRequests.map(function (request) {
let credentialPromises = credentialsToPost.map(function (request) {
return TemplatesService.postWorkflowNodeCredential({
id: request.id,
data: request.data
@ -291,8 +286,6 @@ export default ['$scope', 'TemplatesService',
});
});
// TODO: handle the case where the user deletes all the nodes
} else {
let deletePromises = deletedNodeIds.map(function (nodeId) {
@ -314,18 +307,19 @@ export default ['$scope', 'TemplatesService',
$scope.cancelNodeForm();
}
$scope.treeState.arrayOfNodesForChart.push({
index: $scope.treeState.arrayOfNodesForChart.length,
$scope.graphState.arrayOfNodesForChart.push({
index: $scope.graphState.arrayOfNodesForChart.length,
id: workflowMakerNodeIdCounter,
isNodeBeingAdded: true,
unifiedJobTemplate: null
});
chartNodeIdToIndexMapping[workflowMakerNodeIdCounter] = $scope.treeState.arrayOfNodesForChart.length - 1;
$scope.graphState.nodeBeingAdded = workflowMakerNodeIdCounter;
$scope.treeState.arrayOfLinksForChart.push({
source: $scope.treeState.arrayOfNodesForChart[parent.index],
target: $scope.treeState.arrayOfNodesForChart[chartNodeIdToIndexMapping[workflowMakerNodeIdCounter]],
chartNodeIdToIndexMapping[workflowMakerNodeIdCounter] = $scope.graphState.arrayOfNodesForChart.length - 1;
$scope.graphState.arrayOfLinksForChart.push({
source: $scope.graphState.arrayOfNodesForChart[parent.index],
target: $scope.graphState.arrayOfNodesForChart[chartNodeIdToIndexMapping[workflowMakerNodeIdCounter]],
edgeType: "placeholder"
});
@ -337,7 +331,7 @@ export default ['$scope', 'TemplatesService',
workflowMakerNodeIdCounter++;
$scope.treeState.depthMap = WorkflowChartService.generateDepthMap($scope.treeState.arrayOfLinksForChart);
$scope.graphState.depthMap = WorkflowChartService.generateDepthMap($scope.graphState.arrayOfLinksForChart);
$scope.$broadcast("refreshWorkflowChart");
@ -349,38 +343,39 @@ export default ['$scope', 'TemplatesService',
$scope.cancelNodeForm();
}
$scope.treeState.arrayOfNodesForChart.push({
index: $scope.treeState.arrayOfNodesForChart.length,
$scope.graphState.arrayOfNodesForChart.push({
index: $scope.graphState.arrayOfNodesForChart.length,
id: workflowMakerNodeIdCounter,
isNodeBeingAdded: true,
unifiedJobTemplate: null
});
chartNodeIdToIndexMapping[workflowMakerNodeIdCounter] = $scope.treeState.arrayOfNodesForChart.length - 1;
$scope.graphState.nodeBeingAdded = workflowMakerNodeIdCounter;
$scope.treeState.arrayOfLinksForChart.push({
source: $scope.treeState.arrayOfNodesForChart[link.source.index],
target: $scope.treeState.arrayOfNodesForChart[chartNodeIdToIndexMapping[workflowMakerNodeIdCounter]],
chartNodeIdToIndexMapping[workflowMakerNodeIdCounter] = $scope.graphState.arrayOfNodesForChart.length - 1;
$scope.graphState.arrayOfLinksForChart.push({
source: $scope.graphState.arrayOfNodesForChart[link.source.index],
target: $scope.graphState.arrayOfNodesForChart[chartNodeIdToIndexMapping[workflowMakerNodeIdCounter]],
edgeType: "placeholder"
});
$scope.nodeConfig = {
mode: "add",
nodeId: workflowMakerNodeIdCounter,
newNodeIsRoot: link.source.index === 0
newNodeIsRoot: link.source.id === 1
};
// Search for the link that used to exist between source and target and shift it to
// go from our new node to the target
$scope.treeState.arrayOfLinksForChart.forEach((foo) => {
$scope.graphState.arrayOfLinksForChart.forEach((foo) => {
if (foo.source.id === link.source.id && foo.target.id === link.target.id) {
foo.source = $scope.treeState.arrayOfNodesForChart[chartNodeIdToIndexMapping[workflowMakerNodeIdCounter]];
foo.source = $scope.graphState.arrayOfNodesForChart[chartNodeIdToIndexMapping[workflowMakerNodeIdCounter]];
}
});
workflowMakerNodeIdCounter++;
$scope.treeState.depthMap = WorkflowChartService.generateDepthMap($scope.treeState.arrayOfLinksForChart);
$scope.graphState.depthMap = WorkflowChartService.generateDepthMap($scope.graphState.arrayOfLinksForChart);
$scope.$broadcast("refreshWorkflowChart");
@ -391,17 +386,16 @@ export default ['$scope', 'TemplatesService',
const nodeIndex = chartNodeIdToIndexMapping[$scope.nodeConfig.nodeId];
if ($scope.nodeConfig.mode === "add") {
if (selectedTemplate && edgeType && edgeType.value) {
// TODO: do we need to clone prompt data?
nodeRef[$scope.nodeConfig.nodeId] = {
fullUnifiedJobTemplateObject: selectedTemplate,
promptData: _.cloneDeep(promptData),
promptData,
isNew: true
};
$scope.treeState.arrayOfNodesForChart[nodeIndex].unifiedJobTemplate = selectedTemplate;
$scope.treeState.arrayOfNodesForChart[nodeIndex].isNodeBeingAdded = false;
$scope.graphState.arrayOfNodesForChart[nodeIndex].unifiedJobTemplate = selectedTemplate;
$scope.graphState.nodeBeingAdded = null;
$scope.treeState.arrayOfLinksForChart.map( (link) => {
$scope.graphState.arrayOfLinksForChart.map( (link) => {
if (link.target.index === nodeIndex) {
link.edgeType = edgeType.value;
}
@ -412,8 +406,8 @@ export default ['$scope', 'TemplatesService',
nodeRef[$scope.nodeConfig.nodeId].fullUnifiedJobTemplateObject = selectedTemplate;
nodeRef[$scope.nodeConfig.nodeId].promptData = _.cloneDeep(promptData);
nodeRef[$scope.nodeConfig.nodeId].isEdited = true;
$scope.treeState.arrayOfNodesForChart[nodeIndex].unifiedJobTemplate = selectedTemplate;
$scope.treeState.arrayOfNodesForChart[nodeIndex].isNodeBeingEdited = false;
$scope.graphState.arrayOfNodesForChart[nodeIndex].unifiedJobTemplate = selectedTemplate;
$scope.graphState.nodeBeingEdited = null;
}
}
@ -427,15 +421,15 @@ export default ['$scope', 'TemplatesService',
const nodeIndex = chartNodeIdToIndexMapping[$scope.nodeConfig.nodeId];
if ($scope.nodeConfig.mode === "add") {
// Remove the placeholder node from the array
$scope.treeState.arrayOfNodesForChart.splice(nodeIndex, 1);
$scope.graphState.arrayOfNodesForChart.splice(nodeIndex, 1);
// Update the links
let parents = [];
let children = [];
// Remove any links that reference this node
for( let i = $scope.treeState.arrayOfLinksForChart.length; i--; ){
const link = $scope.treeState.arrayOfLinksForChart[i];
for( let i = $scope.graphState.arrayOfLinksForChart.length; i--; ){
const link = $scope.graphState.arrayOfLinksForChart[i];
if (link.source.index === nodeIndex || link.target.index === nodeIndex) {
if (link.source.index === nodeIndex) {
@ -445,7 +439,7 @@ export default ['$scope', 'TemplatesService',
const sourceIndex = link.source.index < nodeIndex ? link.source.index : link.source.index - 1;
parents.push(sourceIndex);
}
$scope.treeState.arrayOfLinksForChart.splice(i, 1);
$scope.graphState.arrayOfLinksForChart.splice(i, 1);
} else {
if (link.source.index > nodeIndex) {
link.source.index--;
@ -462,9 +456,9 @@ export default ['$scope', 'TemplatesService',
if (parentIndex === 0) {
child.edgeType = "always";
}
$scope.treeState.arrayOfLinksForChart.push({
source: $scope.treeState.arrayOfNodesForChart[parentIndex],
target: $scope.treeState.arrayOfNodesForChart[child.index],
$scope.graphState.arrayOfLinksForChart.push({
source: $scope.graphState.arrayOfNodesForChart[parentIndex],
target: $scope.graphState.arrayOfNodesForChart[child.index],
edgeType: child.edgeType
});
});
@ -478,13 +472,9 @@ export default ['$scope', 'TemplatesService',
}
}
$scope.treeState.depthMap = WorkflowChartService.generateDepthMap($scope.treeState.arrayOfLinksForChart);
$scope.graphState.depthMap = WorkflowChartService.generateDepthMap($scope.graphState.arrayOfLinksForChart);
} else if ($scope.nodeConfig.mode === "edit") {
$scope.treeState.arrayOfNodesForChart.map( (node) => {
if (node.index === $scope.nodeConfig.nodeId) {
node.isNodeBeingEdited = false;
}
});
$scope.graphState.nodeBeingEdited = null;
}
$scope.formState.showNodeForm = false;
$scope.nodeConfig = null;
@ -509,11 +499,7 @@ export default ['$scope', 'TemplatesService',
node: nodeRef[nodeToEdit.id]
};
$scope.treeState.arrayOfNodesForChart.map( (node) => {
if (node.index === nodeToEdit.index) {
node.isNodeBeingEdited = true;
}
});
$scope.graphState.nodeBeingEdited = nodeToEdit.id;
$scope.formState.showNodeForm = true;
}
@ -526,18 +512,19 @@ export default ['$scope', 'TemplatesService',
$scope.startEditLink = (linkToEdit) => {
const setupLinkEdit = () => {
linkToEdit.isLinkBeingEdited = true;
// Determine whether or not this link can be removed
// TODO: we already (potentially) loop across this array below
// and we should combine
let numberOfParents = 0;
$scope.treeState.arrayOfLinksForChart.forEach((link) => {
$scope.graphState.arrayOfLinksForChart.forEach((link) => {
if (link.target.id === linkToEdit.target.id) {
numberOfParents++;
}
});
$scope.graphState.linkBeingEdited = {
source: linkToEdit.source.id,
target: linkToEdit.target.id
};
$scope.linkConfig = {
mode: "edit",
parent: {
@ -564,12 +551,9 @@ export default ['$scope', 'TemplatesService',
if ($scope.linkConfig.parent.id !== linkToEdit.source.id || $scope.linkConfig.child.id !== linkToEdit.target.id) {
// User is going from editing one link to editing another
if ($scope.linkConfig.mode === "add") {
$scope.treeState.arrayOfLinksForChart.splice($scope.treeState.arrayOfLinksForChart.length-1, 1);
$scope.treeState.depthMap = WorkflowChartService.generateDepthMap($scope.treeState.arrayOfLinksForChart);
$scope.graphState.arrayOfLinksForChart.splice($scope.graphState.arrayOfLinksForChart.length-1, 1);
$scope.graphState.depthMap = WorkflowChartService.generateDepthMap($scope.graphState.arrayOfLinksForChart);
}
$scope.treeState.arrayOfLinksForChart.forEach((link) => {
link.isLinkBeingEdited = false;
});
setupLinkEdit();
}
} else {
@ -587,29 +571,33 @@ export default ['$scope', 'TemplatesService',
};
$scope.linkConfig.edgeType = "success";
$scope.treeState.arrayOfNodesForChart.forEach((node) => {
$scope.graphState.arrayOfNodesForChart.forEach((node) => {
node.isInvalidLinkTarget = false;
});
$scope.treeState.arrayOfLinksForChart.push({
target: $scope.treeState.arrayOfNodesForChart[node.index],
source: $scope.treeState.arrayOfNodesForChart[chartNodeIdToIndexMapping[$scope.linkConfig.parent.id]],
edgeType: "placeholder",
isLinkBeingEdited: true
$scope.graphState.arrayOfLinksForChart.push({
target: $scope.graphState.arrayOfNodesForChart[node.index],
source: $scope.graphState.arrayOfNodesForChart[chartNodeIdToIndexMapping[$scope.linkConfig.parent.id]],
edgeType: "placeholder"
});
$scope.treeState.arrayOfLinksForChart.forEach((link, index) => {
$scope.graphState.linkBeingEdited = {
source: $scope.graphState.arrayOfNodesForChart[node.index].id,
target: $scope.graphState.arrayOfNodesForChart[chartNodeIdToIndexMapping[$scope.linkConfig.parent.id]].id
};
$scope.graphState.arrayOfLinksForChart.forEach((link, index) => {
if (link.source.id === 1 && link.target.id === node.id) {
$scope.treeState.arrayOfLinksForChart.splice(index, 1);
$scope.graphState.arrayOfLinksForChart.splice(index, 1);
}
});
$scope.treeState.depthMap = WorkflowChartService.generateDepthMap($scope.treeState.arrayOfLinksForChart);
$scope.graphState.depthMap = WorkflowChartService.generateDepthMap($scope.graphState.arrayOfLinksForChart);
$scope.treeState.isLinkMode = false;
$scope.graphState.isLinkMode = false;
} else {
// This is the first node selected
$scope.treeState.addLinkSource = node.id;
$scope.graphState.addLinkSource = node.id;
$scope.linkConfig = {
mode: "add",
parent: {
@ -622,7 +610,7 @@ export default ['$scope', 'TemplatesService',
let invalidLinkTargetIds = [];
// Find and mark any ancestors as disabled to prevent cycles
$scope.treeState.arrayOfLinksForChart.forEach((link) => {
$scope.graphState.arrayOfLinksForChart.forEach((link) => {
// id=1 is our artificial root node so we don't care about that
if (link.source.id !== 1) {
if (link.source.id === node.id) {
@ -649,10 +637,10 @@ export default ['$scope', 'TemplatesService',
// Filter out the duplicates
invalidLinkTargetIds.filter((element, index, array) => index === array.indexOf(element)).forEach((ancestorId) => {
$scope.treeState.arrayOfNodesForChart[chartNodeIdToIndexMapping[ancestorId]].isInvalidLinkTarget = true;
$scope.graphState.arrayOfNodesForChart[chartNodeIdToIndexMapping[ancestorId]].isInvalidLinkTarget = true;
});
$scope.treeState.isLinkMode = true;
$scope.graphState.isLinkMode = true;
$scope.formState.showLinkForm = true;
}
@ -661,22 +649,20 @@ export default ['$scope', 'TemplatesService',
};
$scope.confirmLinkForm = (newEdgeType) => {
$scope.treeState.arrayOfLinksForChart.forEach((link) => {
$scope.graphState.arrayOfLinksForChart.forEach((link) => {
if (link.source.id === $scope.linkConfig.parent.id && link.target.id === $scope.linkConfig.child.id) {
link.source.isLinkEditParent = false;
link.target.isLinkEditChild = false;
link.edgeType = newEdgeType;
link.isLinkBeingEdited = false;
}
});
if ($scope.linkConfig.mode === "add") {
$scope.treeState.arrayOfNodesForChart.forEach((node) => {
$scope.graphState.arrayOfNodesForChart.forEach((node) => {
node.isInvalidLinkTarget = false;
});
}
$scope.treeState.addLinkSource = null;
$scope.graphState.linkBeingEdited = null;
$scope.graphState.addLinkSource = null;
$scope.formState.showLinkForm = false;
$scope.linkConfig = null;
$scope.$broadcast("refreshWorkflowChart");
@ -684,15 +670,15 @@ export default ['$scope', 'TemplatesService',
$scope.unlink = () => {
// Remove the link
for( let i = $scope.treeState.arrayOfLinksForChart.length; i--; ){
const link = $scope.treeState.arrayOfLinksForChart[i];
for( let i = $scope.graphState.arrayOfLinksForChart.length; i--; ){
const link = $scope.graphState.arrayOfLinksForChart[i];
if (link.source.id === $scope.linkConfig.parent.id && link.target.id === $scope.linkConfig.child.id) {
$scope.treeState.arrayOfLinksForChart.splice(i, 1);
$scope.graphState.arrayOfLinksForChart.splice(i, 1);
}
}
$scope.treeState.depthMap = WorkflowChartService.generateDepthMap($scope.treeState.arrayOfLinksForChart);
$scope.graphState.depthMap = WorkflowChartService.generateDepthMap($scope.graphState.arrayOfLinksForChart);
$scope.formState.showLinkForm = false;
$scope.linkConfig = null;
@ -701,32 +687,30 @@ export default ['$scope', 'TemplatesService',
$scope.cancelLinkForm = () => {
if ($scope.linkConfig.mode === "add" && $scope.linkConfig.child) {
$scope.treeState.arrayOfLinksForChart.splice($scope.treeState.arrayOfLinksForChart.length-1, 1);
$scope.graphState.arrayOfLinksForChart.splice($scope.graphState.arrayOfLinksForChart.length-1, 1);
let targetIsOrphaned = true;
$scope.treeState.arrayOfLinksForChart.forEach((link) => {
$scope.graphState.arrayOfLinksForChart.forEach((link) => {
if (link.target.id === $scope.linkConfig.child.id) {
targetIsOrphaned = false;
}
});
if (targetIsOrphaned) {
// Link it to the start node
$scope.treeState.arrayOfLinksForChart.push({
source: $scope.treeState.arrayOfNodesForChart[0],
target: $scope.treeState.arrayOfNodesForChart[chartNodeIdToIndexMapping[$scope.linkConfig.child.id]],
$scope.graphState.arrayOfLinksForChart.push({
source: $scope.graphState.arrayOfNodesForChart[0],
target: $scope.graphState.arrayOfNodesForChart[chartNodeIdToIndexMapping[$scope.linkConfig.child.id]],
edgeType: "always"
});
}
$scope.treeState.depthMap = WorkflowChartService.generateDepthMap($scope.treeState.arrayOfLinksForChart);
$scope.graphState.depthMap = WorkflowChartService.generateDepthMap($scope.graphState.arrayOfLinksForChart);
}
$scope.treeState.addLinkSource = null;
$scope.treeState.isLinkMode = false;
$scope.formState.showLinkForm = false;
$scope.treeState.arrayOfNodesForChart.forEach((node) => {
$scope.graphState.linkBeingEdited = null;
$scope.graphState.addLinkSource = null;
$scope.graphState.isLinkMode = false;
$scope.graphState.arrayOfNodesForChart.forEach((node) => {
node.isInvalidLinkTarget = false;
});
$scope.treeState.arrayOfLinksForChart.forEach((link) => {
link.isLinkBeingEdited = false;
});
$scope.formState.showLinkForm = false;
$scope.linkConfig = null;
$scope.$broadcast("refreshWorkflowChart");
};
@ -752,15 +736,15 @@ export default ['$scope', 'TemplatesService',
}
// Remove the node from the array
$scope.treeState.arrayOfNodesForChart.splice(nodeIndex, 1);
$scope.graphState.arrayOfNodesForChart.splice(nodeIndex, 1);
// Update the links
let parents = [];
let children = [];
// Remove any links that reference this node
for( let i = $scope.treeState.arrayOfLinksForChart.length; i--; ){
const link = $scope.treeState.arrayOfLinksForChart[i];
for( let i = $scope.graphState.arrayOfLinksForChart.length; i--; ){
const link = $scope.graphState.arrayOfLinksForChart[i];
if (link.source.index === nodeIndex || link.target.index === nodeIndex) {
if (link.source.index === nodeIndex) {
@ -770,14 +754,14 @@ export default ['$scope', 'TemplatesService',
const sourceIndex = link.source.index < nodeIndex ? link.source.index : link.source.index - 1;
parents.push(sourceIndex);
}
$scope.treeState.arrayOfLinksForChart.splice(i, 1);
$scope.graphState.arrayOfLinksForChart.splice(i, 1);
} else {
if (link.source.index > nodeIndex) {
link.source = link.source.index - 1;
}
if (link.target.index > nodeIndex) {
link.target = link.target.index - 1;
}
// if (link.source.index > nodeIndex) {
// link.source.index = link.source.index - 1;
// }
// if (link.target.index > nodeIndex) {
// link.target.index = link.target.index - 1;
// }
}
}
@ -787,9 +771,9 @@ export default ['$scope', 'TemplatesService',
if (parentIndex === 0) {
child.edgeType = "always";
}
$scope.treeState.arrayOfLinksForChart.push({
source: $scope.treeState.arrayOfNodesForChart[parentIndex],
target: $scope.treeState.arrayOfNodesForChart[child.index],
$scope.graphState.arrayOfLinksForChart.push({
source: $scope.graphState.arrayOfNodesForChart[parentIndex],
target: $scope.graphState.arrayOfNodesForChart[child.index],
edgeType: child.edgeType
});
});
@ -807,7 +791,9 @@ export default ['$scope', 'TemplatesService',
}
}
$scope.treeState.depthMap = WorkflowChartService.generateDepthMap($scope.treeState.arrayOfLinksForChart);
$scope.deleteOverlayVisible = false;
$scope.graphState.depthMap = WorkflowChartService.generateDepthMap($scope.graphState.arrayOfLinksForChart);
$scope.nodeToBeDeleted = null;
$scope.deleteOverlayVisible = false;
@ -869,7 +855,7 @@ export default ['$scope', 'TemplatesService',
let depthMap = WorkflowChartService.generateDepthMap(arrayOfLinksForChart);
$scope.treeState = { arrayOfNodesForChart, arrayOfLinksForChart, depthMap };
$scope.graphState = { arrayOfNodesForChart, arrayOfLinksForChart, depthMap };
}
}, function ({ data, status, config }) {
ProcessErrors($scope, data, status, null, {

View File

@ -74,7 +74,7 @@
</div>
<div class="WorkflowLegend-maker--right">
<span class="WorkflowMaker-totalJobs">{{strings.get('workflow_maker.TOTAL_TEMPLATES')}}</span>
<span class="badge List-titleBadge" ng-bind="treeState.arrayOfNodesForChart.length-1"></span>
<span class="badge List-titleBadge" ng-bind="graphState.arrayOfNodesForChart.length-1"></span>
<i ng-class="{'WorkflowMaker-manualControlsIcon--active': showManualControls}" class="fa fa-cog WorkflowMaker-manualControlsIcon" aria-hidden="true" alt="Controls" ng-click="toggleManualControls()"></i>
<div ng-show="showManualControls" class="WorkflowMaker-manualControls noselect">
<workflow-controls class="WorkflowControls" pan-chart="panChart(direction)" zoom-chart="zoomChart(zoom)" reset-chart="resetChart()" zoom-to-fit-chart="zoomToFitChart()"></workflow-controls>
@ -83,7 +83,7 @@
</div>
<workflow-chart
ng-if="modalOpen"
tree-state="treeState"
graph-state="graphState"
add-node-without-child="startAddNodeWithoutChild(parent)"
add-node-with-child="startAddNodeWithChild(link)"
edit-node="startEditNode(nodeToEdit)"

View File

@ -177,7 +177,7 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
let depthMap = WorkflowChartService.generateDepthMap(arrayOfLinksForChart);
$scope.treeState = { arrayOfNodesForChart, arrayOfLinksForChart, depthMap };
$scope.graphState = { arrayOfNodesForChart, arrayOfLinksForChart, depthMap };
}
$scope.toggleStdoutFullscreen = function() {
@ -277,7 +277,7 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
runTimeElapsedTimer = workflowResultsService.createOneSecondTimer(moment(), updateWorkflowJobElapsedTimer);
}
$scope.treeState.arrayOfNodesForChart[chartNodeIdToIndexMapping[nodeIdToChartNodeIdMapping[data.workflow_node_id]]].job = {
$scope.graphState.arrayOfNodesForChart[chartNodeIdToIndexMapping[nodeIdToChartNodeIdMapping[data.workflow_node_id]]].job = {
id: data.unified_job_id,
status: data.status
};

View File

@ -364,7 +364,7 @@
</div>
</div>
<workflow-chart
tree-state="treeState"
graph-state="graphState"
workflow-zoomed="workflowZoomed(zoom)"
can-add-workflow-job-template="canAddWorkflowJobTemplate"
mode="details"