mirror of
https://github.com/ansible/awx.git
synced 2026-01-15 20:00:43 -03:30
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:
parent
61fb3eb390
commit
05f4d94db2
@ -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 parent’s 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();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -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, {
|
||||
|
||||
@ -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)"
|
||||
|
||||
@ -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
|
||||
};
|
||||
|
||||
@ -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"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user