mirror of
https://github.com/ansible/awx.git
synced 2026-03-24 12:25:01 -02:30
First pass at implementing better node placement in the workflow graph
This commit is contained in:
@@ -5,7 +5,9 @@
|
|||||||
*************************************************/
|
*************************************************/
|
||||||
|
|
||||||
import workflowChart from './workflow-chart.directive';
|
import workflowChart from './workflow-chart.directive';
|
||||||
|
import workflowChartService from './workflow-chart.service';
|
||||||
|
|
||||||
export default
|
export default
|
||||||
angular.module('workflowChart', [])
|
angular.module('workflowChart', [])
|
||||||
.directive('workflowChart', workflowChart);
|
.directive('workflowChart', workflowChart)
|
||||||
|
.service('WorkflowChartService', workflowChartService);
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
|
|||||||
function init() {
|
function init() {
|
||||||
force = d3.layout.force()
|
force = d3.layout.force()
|
||||||
.gravity(0)
|
.gravity(0)
|
||||||
.charge(-60)
|
.charge(-300)
|
||||||
.linkDistance(300)
|
.linkDistance(300)
|
||||||
.size([windowHeight, windowWidth]);
|
.size([windowHeight, windowWidth]);
|
||||||
|
|
||||||
@@ -1003,6 +1003,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: this
|
||||||
// if(scope.treeState.arrayOfNodesForChart && scope.treeState.arrayOfNodesForChart > 1 && !graphLoaded) {
|
// if(scope.treeState.arrayOfNodesForChart && scope.treeState.arrayOfNodesForChart > 1 && !graphLoaded) {
|
||||||
// zoomToFitChart();
|
// zoomToFitChart();
|
||||||
// }
|
// }
|
||||||
@@ -1010,14 +1011,14 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
|
|||||||
graphLoaded = true;
|
graphLoaded = true;
|
||||||
|
|
||||||
// This will make sure that all the link elements appear before the nodes in the dom
|
// This will make sure that all the link elements appear before the nodes in the dom
|
||||||
|
// TODO: i don't think this is working...
|
||||||
svgGroup.selectAll(".WorkflowChart-node").order();
|
svgGroup.selectAll(".WorkflowChart-node").order();
|
||||||
|
|
||||||
let tick = (e) => {
|
let tick = () => {
|
||||||
var k = 6 * e.alpha;
|
|
||||||
|
|
||||||
// TODO: replace hard-coded 60 here
|
|
||||||
linkLines
|
linkLines
|
||||||
.each(function(d) { d.source.y -= k; d.target.y += k; })
|
.each(function(d) {
|
||||||
|
d.target.y = scope.treeState.depthMap[d.target.id] * 300;
|
||||||
|
})
|
||||||
.attr("x1", function(d) { return d.target.y; })
|
.attr("x1", function(d) { return d.target.y; })
|
||||||
.attr("y1", function(d) { return d.target.x + (nodeH/2); })
|
.attr("y1", function(d) { return d.target.x + (nodeH/2); })
|
||||||
.attr("x2", function(d) { return d.source.index === 0 ? (scope.mode === 'details' ? d.source.y + 25 : d.source.y + 60) : (d.source.y + nodeW); })
|
.attr("x2", function(d) { return d.source.index === 0 ? (scope.mode === 'details' ? d.source.y + 25 : d.source.y + 60) : (d.source.y + nodeW); })
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
export default [function(){
|
||||||
|
return {
|
||||||
|
generateDepthMap: (arrayOfLinks) => {
|
||||||
|
let depthMap = {};
|
||||||
|
let nodesWithChildren = {};
|
||||||
|
|
||||||
|
let walkBranch = (nodeId, depth) => {
|
||||||
|
depthMap[nodeId] = depthMap[nodeId] ? (depth > depthMap[nodeId] ? depth : depthMap[nodeId]) : depth;
|
||||||
|
if (nodesWithChildren[nodeId]) {
|
||||||
|
_.forEach(nodesWithChildren[nodeId].children, (childNodeId) => {
|
||||||
|
walkBranch(childNodeId, depth+1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let rootNodeIds = [];
|
||||||
|
arrayOfLinks.forEach(link => {
|
||||||
|
// link.source.index of 0 is our artificial start node
|
||||||
|
if (link.source.index !== 0) {
|
||||||
|
if (!nodesWithChildren[link.source.id]) {
|
||||||
|
nodesWithChildren[link.source.id] = {
|
||||||
|
children: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
nodesWithChildren[link.source.id].children.push(link.target.id);
|
||||||
|
} else {
|
||||||
|
// Store the fact that might be a root node
|
||||||
|
rootNodeIds.push(link.target.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_.forEach(rootNodeIds, function(rootNodeId) {
|
||||||
|
walkBranch(rootNodeId, 1);
|
||||||
|
depthMap[rootNodeId] = 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
return depthMap;
|
||||||
|
},
|
||||||
|
generateArraysOfNodesAndLinks: function(allNodes) {
|
||||||
|
let nonRootNodeIds = [];
|
||||||
|
let allNodeIds = [];
|
||||||
|
let arrayOfLinksForChart = [];
|
||||||
|
let nodeIdToChartNodeIdMapping = {};
|
||||||
|
let chartNodeIdToIndexMapping = {};
|
||||||
|
let nodeRef = {};
|
||||||
|
let nodeIdCounter = 1;
|
||||||
|
let arrayOfNodesForChart = [
|
||||||
|
{
|
||||||
|
index: 0,
|
||||||
|
id: nodeIdCounter,
|
||||||
|
isStartNode: true,
|
||||||
|
unifiedJobTemplate: {
|
||||||
|
name: "START"
|
||||||
|
},
|
||||||
|
fixed: true,
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
}
|
||||||
|
];
|
||||||
|
nodeIdCounter++;
|
||||||
|
// Assign each node an ID - 0 is reserved for the start node. We need to
|
||||||
|
// make sure that we have an ID on every node including new nodes so the
|
||||||
|
// ID returned by the api won't do
|
||||||
|
allNodes.forEach((node) => {
|
||||||
|
node.workflowMakerNodeId = nodeIdCounter;
|
||||||
|
nodeRef[nodeIdCounter] = {
|
||||||
|
originalNodeObject: node
|
||||||
|
};
|
||||||
|
|
||||||
|
const nodeObj = {
|
||||||
|
index: nodeIdCounter-1,
|
||||||
|
id: nodeIdCounter
|
||||||
|
};
|
||||||
|
|
||||||
|
if(node.summary_fields.job) {
|
||||||
|
nodeObj.job = node.summary_fields.job;
|
||||||
|
}
|
||||||
|
if(node.summary_fields.unified_job_template) {
|
||||||
|
nodeObj.unifiedJobTemplate = node.summary_fields.unified_job_template;
|
||||||
|
}
|
||||||
|
|
||||||
|
arrayOfNodesForChart.push(nodeObj);
|
||||||
|
allNodeIds.push(node.id);
|
||||||
|
nodeIdToChartNodeIdMapping[node.id] = node.workflowMakerNodeId;
|
||||||
|
chartNodeIdToIndexMapping[nodeIdCounter] = nodeIdCounter-1;
|
||||||
|
nodeIdCounter++;
|
||||||
|
});
|
||||||
|
|
||||||
|
allNodes.forEach((node) => {
|
||||||
|
const sourceIndex = chartNodeIdToIndexMapping[node.workflowMakerNodeId];
|
||||||
|
node.success_nodes.forEach((nodeId) => {
|
||||||
|
const targetIndex = chartNodeIdToIndexMapping[nodeIdToChartNodeIdMapping[nodeId]];
|
||||||
|
arrayOfLinksForChart.push({
|
||||||
|
source: arrayOfNodesForChart[sourceIndex],
|
||||||
|
target: arrayOfNodesForChart[targetIndex],
|
||||||
|
edgeType: "success"
|
||||||
|
});
|
||||||
|
nonRootNodeIds.push(nodeId);
|
||||||
|
});
|
||||||
|
node.failure_nodes.forEach((nodeId) => {
|
||||||
|
const targetIndex = chartNodeIdToIndexMapping[nodeIdToChartNodeIdMapping[nodeId]];
|
||||||
|
arrayOfLinksForChart.push({
|
||||||
|
source: arrayOfNodesForChart[sourceIndex],
|
||||||
|
target: arrayOfNodesForChart[targetIndex],
|
||||||
|
edgeType: "failure"
|
||||||
|
});
|
||||||
|
nonRootNodeIds.push(nodeId);
|
||||||
|
});
|
||||||
|
node.always_nodes.forEach((nodeId) => {
|
||||||
|
const targetIndex = chartNodeIdToIndexMapping[nodeIdToChartNodeIdMapping[nodeId]];
|
||||||
|
arrayOfLinksForChart.push({
|
||||||
|
source: arrayOfNodesForChart[sourceIndex],
|
||||||
|
target: arrayOfNodesForChart[targetIndex],
|
||||||
|
edgeType: "always"
|
||||||
|
});
|
||||||
|
nonRootNodeIds.push(nodeId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
let uniqueNonRootNodeIds = Array.from(new Set(nonRootNodeIds));
|
||||||
|
|
||||||
|
let rootNodes = _.difference(allNodeIds, uniqueNonRootNodeIds);
|
||||||
|
|
||||||
|
rootNodes.forEach((rootNodeId) => {
|
||||||
|
const targetIndex = chartNodeIdToIndexMapping[nodeIdToChartNodeIdMapping[rootNodeId]];
|
||||||
|
arrayOfLinksForChart.push({
|
||||||
|
source: arrayOfNodesForChart[0],
|
||||||
|
target: arrayOfNodesForChart[targetIndex],
|
||||||
|
edgeType: "always"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
arrayOfNodesForChart,
|
||||||
|
arrayOfLinksForChart,
|
||||||
|
chartNodeIdToIndexMapping,
|
||||||
|
nodeIdToChartNodeIdMapping,
|
||||||
|
nodeRef,
|
||||||
|
workflowMakerNodeIdCounter: nodeIdCounter
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}];
|
||||||
@@ -6,10 +6,10 @@
|
|||||||
|
|
||||||
export default ['$scope', 'TemplatesService',
|
export default ['$scope', 'TemplatesService',
|
||||||
'ProcessErrors', 'CreateSelect2', '$q', 'JobTemplateModel',
|
'ProcessErrors', 'CreateSelect2', '$q', 'JobTemplateModel',
|
||||||
'Empty', 'PromptService', 'Rest', 'TemplatesStrings',
|
'Empty', 'PromptService', 'Rest', 'TemplatesStrings', 'WorkflowChartService',
|
||||||
function ($scope, TemplatesService,
|
function ($scope, TemplatesService,
|
||||||
ProcessErrors, CreateSelect2, $q, JobTemplate,
|
ProcessErrors, CreateSelect2, $q, JobTemplate,
|
||||||
Empty, PromptService, Rest, TemplatesStrings) {
|
Empty, PromptService, Rest, TemplatesStrings, WorkflowChartService) {
|
||||||
|
|
||||||
$scope.strings = TemplatesStrings;
|
$scope.strings = TemplatesStrings;
|
||||||
// TODO: I don't think this needs to be on scope but changing it will require changes to
|
// TODO: I don't think this needs to be on scope but changing it will require changes to
|
||||||
@@ -19,13 +19,10 @@ export default ['$scope', 'TemplatesService',
|
|||||||
let credentialRequests = [];
|
let credentialRequests = [];
|
||||||
let deletedNodeIds = [];
|
let deletedNodeIds = [];
|
||||||
let workflowMakerNodeIdCounter = 1;
|
let workflowMakerNodeIdCounter = 1;
|
||||||
let nodeIdToMakerIdMapping = {};
|
let nodeIdToChartNodeIdMapping = {};
|
||||||
let chartNodeIdToIndexMapping = {};
|
let chartNodeIdToIndexMapping = {};
|
||||||
let nodeRef = {};
|
let nodeRef = {};
|
||||||
|
|
||||||
// TODO: fix this
|
|
||||||
$scope.totalNodes = 0;
|
|
||||||
|
|
||||||
$scope.showKey = false;
|
$scope.showKey = false;
|
||||||
$scope.toggleKey = () => $scope.showKey = !$scope.showKey;
|
$scope.toggleKey = () => $scope.showKey = !$scope.showKey;
|
||||||
$scope.keyClassList = `{ 'Key-menuIcon--active': showKey }`;
|
$scope.keyClassList = `{ 'Key-menuIcon--active': showKey }`;
|
||||||
@@ -108,7 +105,7 @@ export default ['$scope', 'TemplatesService',
|
|||||||
}).then(({data}) => {
|
}).then(({data}) => {
|
||||||
nodeRef[workflowMakerNodeId].originalNodeObject = data;
|
nodeRef[workflowMakerNodeId].originalNodeObject = data;
|
||||||
// TODO: do we need this?
|
// TODO: do we need this?
|
||||||
nodeIdToMakerIdMapping[data.id] = parseInt(workflowMakerNodeId);
|
nodeIdToChartNodeIdMapping[data.id] = parseInt(workflowMakerNodeId);
|
||||||
// if (_.get(params, 'node.promptData.launchConf.ask_credential_on_launch')) {
|
// if (_.get(params, 'node.promptData.launchConf.ask_credential_on_launch')) {
|
||||||
// // This finds the credentials that were selected in the prompt but don't occur
|
// // This finds the credentials that were selected in the prompt but don't occur
|
||||||
// // in the template defaults
|
// // in the template defaults
|
||||||
@@ -222,8 +219,8 @@ export default ['$scope', 'TemplatesService',
|
|||||||
|
|
||||||
Object.keys(linkMap).map((sourceNodeId) => {
|
Object.keys(linkMap).map((sourceNodeId) => {
|
||||||
Object.keys(linkMap[sourceNodeId]).map((targetNodeId) => {
|
Object.keys(linkMap[sourceNodeId]).map((targetNodeId) => {
|
||||||
const foo = nodeIdToMakerIdMapping[sourceNodeId];
|
const foo = nodeIdToChartNodeIdMapping[sourceNodeId];
|
||||||
const bar = nodeIdToMakerIdMapping[targetNodeId];
|
const bar = nodeIdToChartNodeIdMapping[targetNodeId];
|
||||||
switch(linkMap[sourceNodeId][targetNodeId]) {
|
switch(linkMap[sourceNodeId][targetNodeId]) {
|
||||||
case "success":
|
case "success":
|
||||||
if (
|
if (
|
||||||
@@ -340,6 +337,8 @@ export default ['$scope', 'TemplatesService',
|
|||||||
|
|
||||||
workflowMakerNodeIdCounter++;
|
workflowMakerNodeIdCounter++;
|
||||||
|
|
||||||
|
$scope.treeState.depthMap = WorkflowChartService.generateDepthMap($scope.treeState.arrayOfLinksForChart);
|
||||||
|
|
||||||
$scope.$broadcast("refreshWorkflowChart");
|
$scope.$broadcast("refreshWorkflowChart");
|
||||||
|
|
||||||
$scope.formState.showNodeForm = true;
|
$scope.formState.showNodeForm = true;
|
||||||
@@ -381,6 +380,8 @@ export default ['$scope', 'TemplatesService',
|
|||||||
|
|
||||||
workflowMakerNodeIdCounter++;
|
workflowMakerNodeIdCounter++;
|
||||||
|
|
||||||
|
$scope.treeState.depthMap = WorkflowChartService.generateDepthMap($scope.treeState.arrayOfLinksForChart);
|
||||||
|
|
||||||
$scope.$broadcast("refreshWorkflowChart");
|
$scope.$broadcast("refreshWorkflowChart");
|
||||||
|
|
||||||
$scope.formState.showNodeForm = true;
|
$scope.formState.showNodeForm = true;
|
||||||
@@ -476,6 +477,8 @@ export default ['$scope', 'TemplatesService',
|
|||||||
chartNodeIdToIndexMapping[key]--;
|
chartNodeIdToIndexMapping[key]--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$scope.treeState.depthMap = WorkflowChartService.generateDepthMap($scope.treeState.arrayOfLinksForChart);
|
||||||
} else if ($scope.nodeConfig.mode === "edit") {
|
} else if ($scope.nodeConfig.mode === "edit") {
|
||||||
$scope.treeState.arrayOfNodesForChart.map( (node) => {
|
$scope.treeState.arrayOfNodesForChart.map( (node) => {
|
||||||
if (node.index === $scope.nodeConfig.nodeId) {
|
if (node.index === $scope.nodeConfig.nodeId) {
|
||||||
@@ -562,6 +565,7 @@ export default ['$scope', 'TemplatesService',
|
|||||||
// User is going from editing one link to editing another
|
// User is going from editing one link to editing another
|
||||||
if ($scope.linkConfig.mode === "add") {
|
if ($scope.linkConfig.mode === "add") {
|
||||||
$scope.treeState.arrayOfLinksForChart.splice($scope.treeState.arrayOfLinksForChart.length-1, 1);
|
$scope.treeState.arrayOfLinksForChart.splice($scope.treeState.arrayOfLinksForChart.length-1, 1);
|
||||||
|
$scope.treeState.depthMap = WorkflowChartService.generateDepthMap($scope.treeState.arrayOfLinksForChart);
|
||||||
}
|
}
|
||||||
$scope.treeState.arrayOfLinksForChart.forEach((link) => {
|
$scope.treeState.arrayOfLinksForChart.forEach((link) => {
|
||||||
link.isLinkBeingEdited = false;
|
link.isLinkBeingEdited = false;
|
||||||
@@ -575,7 +579,6 @@ export default ['$scope', 'TemplatesService',
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.selectNodeForLinking = (node) => {
|
$scope.selectNodeForLinking = (node) => {
|
||||||
// start here
|
|
||||||
if ($scope.linkConfig) {
|
if ($scope.linkConfig) {
|
||||||
// This is the second node selected
|
// This is the second node selected
|
||||||
$scope.linkConfig.child = {
|
$scope.linkConfig.child = {
|
||||||
@@ -595,6 +598,14 @@ export default ['$scope', 'TemplatesService',
|
|||||||
isLinkBeingEdited: true
|
isLinkBeingEdited: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$scope.treeState.arrayOfLinksForChart.forEach((link, index) => {
|
||||||
|
if (link.source.id === 1 && link.target.id === node.id) {
|
||||||
|
$scope.treeState.arrayOfLinksForChart.splice(index, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.treeState.depthMap = WorkflowChartService.generateDepthMap($scope.treeState.arrayOfLinksForChart);
|
||||||
|
|
||||||
$scope.treeState.isLinkMode = false;
|
$scope.treeState.isLinkMode = false;
|
||||||
} else {
|
} else {
|
||||||
// This is the first node selected
|
// This is the first node selected
|
||||||
@@ -681,6 +692,8 @@ export default ['$scope', 'TemplatesService',
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$scope.treeState.depthMap = WorkflowChartService.generateDepthMap($scope.treeState.arrayOfLinksForChart);
|
||||||
|
|
||||||
$scope.formState.showLinkForm = false;
|
$scope.formState.showLinkForm = false;
|
||||||
$scope.linkConfig = null;
|
$scope.linkConfig = null;
|
||||||
$scope.$broadcast("refreshWorkflowChart");
|
$scope.$broadcast("refreshWorkflowChart");
|
||||||
@@ -689,6 +702,21 @@ export default ['$scope', 'TemplatesService',
|
|||||||
$scope.cancelLinkForm = () => {
|
$scope.cancelLinkForm = () => {
|
||||||
if ($scope.linkConfig.mode === "add" && $scope.linkConfig.child) {
|
if ($scope.linkConfig.mode === "add" && $scope.linkConfig.child) {
|
||||||
$scope.treeState.arrayOfLinksForChart.splice($scope.treeState.arrayOfLinksForChart.length-1, 1);
|
$scope.treeState.arrayOfLinksForChart.splice($scope.treeState.arrayOfLinksForChart.length-1, 1);
|
||||||
|
let targetIsOrphaned = true;
|
||||||
|
$scope.treeState.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]],
|
||||||
|
edgeType: "always"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
$scope.treeState.depthMap = WorkflowChartService.generateDepthMap($scope.treeState.arrayOfLinksForChart);
|
||||||
}
|
}
|
||||||
$scope.treeState.addLinkSource = null;
|
$scope.treeState.addLinkSource = null;
|
||||||
$scope.treeState.isLinkMode = false;
|
$scope.treeState.isLinkMode = false;
|
||||||
@@ -779,6 +807,8 @@ export default ['$scope', 'TemplatesService',
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$scope.treeState.depthMap = WorkflowChartService.generateDepthMap($scope.treeState.arrayOfLinksForChart);
|
||||||
|
|
||||||
$scope.nodeToBeDeleted = null;
|
$scope.nodeToBeDeleted = null;
|
||||||
$scope.deleteOverlayVisible = false;
|
$scope.deleteOverlayVisible = false;
|
||||||
|
|
||||||
@@ -832,87 +862,14 @@ export default ['$scope', 'TemplatesService',
|
|||||||
page++;
|
page++;
|
||||||
getNodes();
|
getNodes();
|
||||||
} else {
|
} else {
|
||||||
let nonRootNodeIds = [];
|
|
||||||
let allNodeIds = [];
|
|
||||||
let arrayOfLinksForChart = [];
|
let arrayOfLinksForChart = [];
|
||||||
let arrayOfNodesForChart = [
|
let arrayOfNodesForChart = [];
|
||||||
{
|
|
||||||
index: 0,
|
|
||||||
id: workflowMakerNodeIdCounter,
|
|
||||||
isStartNode: true,
|
|
||||||
unifiedJobTemplate: {
|
|
||||||
name: "START"
|
|
||||||
},
|
|
||||||
fixed: true,
|
|
||||||
x: 0,
|
|
||||||
y: 0
|
|
||||||
}
|
|
||||||
];
|
|
||||||
workflowMakerNodeIdCounter++;
|
|
||||||
// Assign each node an ID - 0 is reserved for the start node. We need to
|
|
||||||
// make sure that we have an ID on every node including new nodes so the
|
|
||||||
// ID returned by the api won't do
|
|
||||||
allNodes.forEach((node) => {
|
|
||||||
node.workflowMakerNodeId = workflowMakerNodeIdCounter;
|
|
||||||
nodeRef[workflowMakerNodeIdCounter] = {
|
|
||||||
originalNodeObject: node
|
|
||||||
};
|
|
||||||
arrayOfNodesForChart.push({
|
|
||||||
index: workflowMakerNodeIdCounter-1,
|
|
||||||
id: workflowMakerNodeIdCounter,
|
|
||||||
unifiedJobTemplate: node.summary_fields.unified_job_template
|
|
||||||
});
|
|
||||||
allNodeIds.push(node.id);
|
|
||||||
nodeIdToMakerIdMapping[node.id] = node.workflowMakerNodeId;
|
|
||||||
chartNodeIdToIndexMapping[workflowMakerNodeIdCounter] = workflowMakerNodeIdCounter-1;
|
|
||||||
workflowMakerNodeIdCounter++;
|
|
||||||
});
|
|
||||||
|
|
||||||
allNodes.forEach((node) => {
|
({arrayOfNodesForChart, arrayOfLinksForChart, chartNodeIdToIndexMapping, nodeIdToChartNodeIdMapping, nodeRef, workflowMakerNodeIdCounter} = WorkflowChartService.generateArraysOfNodesAndLinks(allNodes));
|
||||||
const sourceIndex = chartNodeIdToIndexMapping[node.workflowMakerNodeId];
|
|
||||||
node.success_nodes.forEach((nodeId) => {
|
|
||||||
const targetIndex = chartNodeIdToIndexMapping[nodeIdToMakerIdMapping[nodeId]];
|
|
||||||
arrayOfLinksForChart.push({
|
|
||||||
source: arrayOfNodesForChart[sourceIndex],
|
|
||||||
target: arrayOfNodesForChart[targetIndex],
|
|
||||||
edgeType: "success"
|
|
||||||
});
|
|
||||||
nonRootNodeIds.push(nodeId);
|
|
||||||
});
|
|
||||||
node.failure_nodes.forEach((nodeId) => {
|
|
||||||
const targetIndex = chartNodeIdToIndexMapping[nodeIdToMakerIdMapping[nodeId]];
|
|
||||||
arrayOfLinksForChart.push({
|
|
||||||
source: arrayOfNodesForChart[sourceIndex],
|
|
||||||
target: arrayOfNodesForChart[targetIndex],
|
|
||||||
edgeType: "failure"
|
|
||||||
});
|
|
||||||
nonRootNodeIds.push(nodeId);
|
|
||||||
});
|
|
||||||
node.always_nodes.forEach((nodeId) => {
|
|
||||||
const targetIndex = chartNodeIdToIndexMapping[nodeIdToMakerIdMapping[nodeId]];
|
|
||||||
arrayOfLinksForChart.push({
|
|
||||||
source: arrayOfNodesForChart[sourceIndex],
|
|
||||||
target: arrayOfNodesForChart[targetIndex],
|
|
||||||
edgeType: "always"
|
|
||||||
});
|
|
||||||
nonRootNodeIds.push(nodeId);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
let uniqueNonRootNodeIds = Array.from(new Set(nonRootNodeIds));
|
let depthMap = WorkflowChartService.generateDepthMap(arrayOfLinksForChart);
|
||||||
|
|
||||||
let rootNodes = _.difference(allNodeIds, uniqueNonRootNodeIds);
|
$scope.treeState = { arrayOfNodesForChart, arrayOfLinksForChart, depthMap };
|
||||||
|
|
||||||
rootNodes.forEach((rootNodeId) => {
|
|
||||||
const targetIndex = chartNodeIdToIndexMapping[nodeIdToMakerIdMapping[rootNodeId]];
|
|
||||||
arrayOfLinksForChart.push({
|
|
||||||
source: arrayOfNodesForChart[0],
|
|
||||||
target: arrayOfNodesForChart[targetIndex],
|
|
||||||
edgeType: "always"
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.treeState = { arrayOfNodesForChart, arrayOfLinksForChart };
|
|
||||||
}
|
}
|
||||||
}, function ({ data, status, config }) {
|
}, function ({ data, status, config }) {
|
||||||
ProcessErrors($scope, data, status, null, {
|
ProcessErrors($scope, data, status, null, {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
|
export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
|
||||||
'jobLabels', 'workflowNodes', '$scope', 'ParseTypeChange',
|
'jobLabels', 'workflowNodes', '$scope', 'ParseTypeChange',
|
||||||
'ParseVariableString', 'count', '$state', 'i18n',
|
'ParseVariableString', 'count', '$state', 'i18n', 'WorkflowChartService',
|
||||||
'moment', function(workflowData, workflowResultsService,
|
'moment', function(workflowData, workflowResultsService,
|
||||||
workflowDataOptions, jobLabels, workflowNodes, $scope, ParseTypeChange,
|
workflowDataOptions, jobLabels, workflowNodes, $scope, ParseTypeChange,
|
||||||
ParseVariableString, count, $state, i18n, moment) {
|
ParseVariableString, count, $state, i18n, WorkflowChartService,
|
||||||
|
moment) {
|
||||||
var runTimeElapsedTimer = null;
|
var runTimeElapsedTimer = null;
|
||||||
let workflowMakerNodeIdCounter = 1;
|
let nodeIdToChartNodeIdMapping = {};
|
||||||
let nodeIdToMakerIdMapping = {};
|
|
||||||
let chartNodeIdToIndexMapping = {};
|
let chartNodeIdToIndexMapping = {};
|
||||||
|
|
||||||
var getLinks = function() {
|
var getLinks = function() {
|
||||||
@@ -170,93 +170,14 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
|
|||||||
// Click binding for the expand/collapse button on the standard out log
|
// Click binding for the expand/collapse button on the standard out log
|
||||||
$scope.stdoutFullScreen = false;
|
$scope.stdoutFullScreen = false;
|
||||||
|
|
||||||
let nonRootNodeIds = [];
|
|
||||||
let allNodeIds = [];
|
|
||||||
let arrayOfLinksForChart = [];
|
let arrayOfLinksForChart = [];
|
||||||
let arrayOfNodesForChart = [
|
let arrayOfNodesForChart = [];
|
||||||
{
|
|
||||||
index: 0,
|
|
||||||
id: workflowMakerNodeIdCounter,
|
|
||||||
isStartNode: true,
|
|
||||||
unifiedJobTemplate: {
|
|
||||||
name: "START"
|
|
||||||
},
|
|
||||||
fixed: true,
|
|
||||||
x: 0,
|
|
||||||
y: 0
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
workflowMakerNodeIdCounter++;
|
({arrayOfNodesForChart, arrayOfLinksForChart, chartNodeIdToIndexMapping, nodeIdToChartNodeIdMapping} = WorkflowChartService.generateArraysOfNodesAndLinks(workflowNodes));
|
||||||
// Assign each node an ID - 0 is reserved for the start node. We need to
|
|
||||||
// make sure that we have an ID on every node including new nodes so the
|
|
||||||
// ID returned by the api won't do
|
|
||||||
workflowNodes.forEach((node) => {
|
|
||||||
node.workflowMakerNodeId = workflowMakerNodeIdCounter;
|
|
||||||
const nodeObj = {
|
|
||||||
index: workflowMakerNodeIdCounter-1,
|
|
||||||
id: workflowMakerNodeIdCounter,
|
|
||||||
unifiedJobTemplate: node.summary_fields.unified_job_template
|
|
||||||
};
|
|
||||||
if(node.summary_fields.job) {
|
|
||||||
nodeObj.job = node.summary_fields.job;
|
|
||||||
}
|
|
||||||
if(node.summary_fields.unified_job_template) {
|
|
||||||
nodeObj.unifiedJobTemplate = node.summary_fields.unified_job_template;
|
|
||||||
}
|
|
||||||
arrayOfNodesForChart.push(nodeObj);
|
|
||||||
allNodeIds.push(node.id);
|
|
||||||
nodeIdToMakerIdMapping[node.id] = node.workflowMakerNodeId;
|
|
||||||
chartNodeIdToIndexMapping[workflowMakerNodeIdCounter] = workflowMakerNodeIdCounter-1;
|
|
||||||
workflowMakerNodeIdCounter++;
|
|
||||||
});
|
|
||||||
|
|
||||||
workflowNodes.forEach((node) => {
|
let depthMap = WorkflowChartService.generateDepthMap(arrayOfLinksForChart);
|
||||||
const sourceIndex = chartNodeIdToIndexMapping[node.workflowMakerNodeId];
|
|
||||||
node.success_nodes.forEach((nodeId) => {
|
|
||||||
const targetIndex = chartNodeIdToIndexMapping[nodeIdToMakerIdMapping[nodeId]];
|
|
||||||
arrayOfLinksForChart.push({
|
|
||||||
source: arrayOfNodesForChart[sourceIndex],
|
|
||||||
target: arrayOfNodesForChart[targetIndex],
|
|
||||||
edgeType: "success"
|
|
||||||
});
|
|
||||||
nonRootNodeIds.push(nodeId);
|
|
||||||
});
|
|
||||||
node.failure_nodes.forEach((nodeId) => {
|
|
||||||
const targetIndex = chartNodeIdToIndexMapping[nodeIdToMakerIdMapping[nodeId]];
|
|
||||||
arrayOfLinksForChart.push({
|
|
||||||
source: arrayOfNodesForChart[sourceIndex],
|
|
||||||
target: arrayOfNodesForChart[targetIndex],
|
|
||||||
edgeType: "failure"
|
|
||||||
});
|
|
||||||
nonRootNodeIds.push(nodeId);
|
|
||||||
});
|
|
||||||
node.always_nodes.forEach((nodeId) => {
|
|
||||||
const targetIndex = chartNodeIdToIndexMapping[nodeIdToMakerIdMapping[nodeId]];
|
|
||||||
arrayOfLinksForChart.push({
|
|
||||||
source: arrayOfNodesForChart[sourceIndex],
|
|
||||||
target: arrayOfNodesForChart[targetIndex],
|
|
||||||
edgeType: "always"
|
|
||||||
});
|
|
||||||
nonRootNodeIds.push(nodeId);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
let uniqueNonRootNodeIds = Array.from(new Set(nonRootNodeIds));
|
|
||||||
|
|
||||||
let rootNodes = _.difference(allNodeIds, uniqueNonRootNodeIds);
|
|
||||||
|
|
||||||
rootNodes.forEach((rootNodeId) => {
|
|
||||||
const targetIndex = chartNodeIdToIndexMapping[nodeIdToMakerIdMapping[rootNodeId]];
|
|
||||||
arrayOfLinksForChart.push({
|
|
||||||
source: arrayOfNodesForChart[0],
|
|
||||||
target: arrayOfNodesForChart[targetIndex],
|
|
||||||
edgeType: "always"
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.treeState = { arrayOfNodesForChart, arrayOfLinksForChart };
|
|
||||||
|
|
||||||
|
$scope.treeState = { arrayOfNodesForChart, arrayOfLinksForChart, depthMap };
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.toggleStdoutFullscreen = function() {
|
$scope.toggleStdoutFullscreen = function() {
|
||||||
@@ -356,12 +277,11 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
|
|||||||
runTimeElapsedTimer = workflowResultsService.createOneSecondTimer(moment(), updateWorkflowJobElapsedTimer);
|
runTimeElapsedTimer = workflowResultsService.createOneSecondTimer(moment(), updateWorkflowJobElapsedTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.treeState.arrayOfNodesForChart[chartNodeIdToIndexMapping[nodeIdToMakerIdMapping[data.workflow_node_id]]].job = {
|
$scope.treeState.arrayOfNodesForChart[chartNodeIdToIndexMapping[nodeIdToChartNodeIdMapping[data.workflow_node_id]]].job = {
|
||||||
id: data.unified_job_id,
|
id: data.unified_job_id,
|
||||||
status: data.status
|
status: data.status
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
$scope.workflow_nodes.forEach(node => {
|
$scope.workflow_nodes.forEach(node => {
|
||||||
if(parseInt(node.id) === parseInt(data.workflow_node_id)){
|
if(parseInt(node.id) === parseInt(data.workflow_node_id)){
|
||||||
node.summary_fields.job = {
|
node.summary_fields.job = {
|
||||||
|
|||||||
Reference in New Issue
Block a user