mirror of
https://github.com/ansible/awx.git
synced 2026-05-10 19:07:36 -02:30
Moved a significant amount of the tree generation logic out to the workflow service
This commit is contained in:
@@ -12,7 +12,7 @@ export default
|
|||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
scope: false,
|
scope: false,
|
||||||
templateUrl: templateUrl('job-templates/labels/labelsList'),
|
templateUrl: templateUrl('templates/labels/labelsList'),
|
||||||
link: function(scope, element, attrs) {
|
link: function(scope, element, attrs) {
|
||||||
scope.showDelete = attrs.showDelete === 'true';
|
scope.showDelete = attrs.showDelete === 'true';
|
||||||
scope.seeMoreInactive = true;
|
scope.seeMoreInactive = true;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ angular.module('templates', [surveyMaker.name, templatesList.name, jobTemplatesA
|
|||||||
workflowChart.name, workflowMaker.name
|
workflowChart.name, workflowMaker.name
|
||||||
])
|
])
|
||||||
.service('TemplatesService', templatesService)
|
.service('TemplatesService', templatesService)
|
||||||
.service('WorkflowHelpService', workflowService)
|
.service('WorkflowService', workflowService)
|
||||||
.config(['$stateProvider', 'stateDefinitionsProvider', '$stateExtenderProvider',
|
.config(['$stateProvider', 'stateDefinitionsProvider', '$stateExtenderProvider',
|
||||||
function($stateProvider, stateDefinitionsProvider, $stateExtenderProvider) {
|
function($stateProvider, stateDefinitionsProvider, $stateExtenderProvider) {
|
||||||
let stateTree, addJobTemplate, editJobTemplate, addWorkflow, editWorkflow,
|
let stateTree, addJobTemplate, editJobTemplate, addWorkflow, editWorkflow,
|
||||||
|
|||||||
@@ -8,13 +8,13 @@
|
|||||||
[ '$scope', '$stateParams', 'WorkflowForm', 'GenerateForm', 'Alert', 'ProcessErrors',
|
[ '$scope', '$stateParams', 'WorkflowForm', 'GenerateForm', 'Alert', 'ProcessErrors',
|
||||||
'ClearScope', 'GetBasePath', '$q', 'ParseTypeChange', 'Wait', 'Empty',
|
'ClearScope', 'GetBasePath', '$q', 'ParseTypeChange', 'Wait', 'Empty',
|
||||||
'ToJSON', 'initSurvey', '$state', 'CreateSelect2', 'ParseVariableString',
|
'ToJSON', 'initSurvey', '$state', 'CreateSelect2', 'ParseVariableString',
|
||||||
'TemplatesService', 'OrganizationList', 'Rest',
|
'TemplatesService', 'OrganizationList', 'Rest', 'WorkflowService',
|
||||||
function(
|
function(
|
||||||
$scope, $stateParams, WorkflowForm, GenerateForm, Alert, ProcessErrors,
|
$scope, $stateParams, WorkflowForm, GenerateForm, Alert, ProcessErrors,
|
||||||
ClearScope, GetBasePath, $q, ParseTypeChange, Wait, Empty,
|
ClearScope, GetBasePath, $q, ParseTypeChange, Wait, Empty,
|
||||||
ToJSON, SurveyControllerInit, $state, CreateSelect2, ParseVariableString,
|
ToJSON, SurveyControllerInit, $state, CreateSelect2, ParseVariableString,
|
||||||
TemplatesService, OrganizationList, Rest
|
TemplatesService, OrganizationList, Rest, WorkflowService
|
||||||
) {window.state = $state;
|
) {
|
||||||
|
|
||||||
ClearScope();
|
ClearScope();
|
||||||
|
|
||||||
@@ -40,90 +40,6 @@
|
|||||||
$scope.associateRequests = [];
|
$scope.associateRequests = [];
|
||||||
$scope.disassociateRequests = [];
|
$scope.disassociateRequests = [];
|
||||||
|
|
||||||
$scope.workflowTree = {
|
|
||||||
data: {
|
|
||||||
id: 1,
|
|
||||||
canDelete: false,
|
|
||||||
canEdit: false,
|
|
||||||
canAddTo: true,
|
|
||||||
isStartNode: true,
|
|
||||||
unifiedJobTemplate: {
|
|
||||||
name: "Workflow Launch"
|
|
||||||
},
|
|
||||||
children: [],
|
|
||||||
deletedNodes: [],
|
|
||||||
totalNodes: 0
|
|
||||||
},
|
|
||||||
nextIndex: 2
|
|
||||||
};
|
|
||||||
|
|
||||||
function buildBranch(params) {
|
|
||||||
// params.nodeId
|
|
||||||
// params.parentId
|
|
||||||
// params.edgeType
|
|
||||||
// params.nodesObj
|
|
||||||
// params.isRoot
|
|
||||||
|
|
||||||
let treeNode = {
|
|
||||||
children: [],
|
|
||||||
c: "#D7D7D7",
|
|
||||||
id: $scope.workflowTree.nextIndex,
|
|
||||||
nodeId: params.nodeId,
|
|
||||||
canDelete: true,
|
|
||||||
canEdit: true,
|
|
||||||
canAddTo: true,
|
|
||||||
placeholder: false,
|
|
||||||
edgeType: params.edgeType,
|
|
||||||
unifiedJobTemplate: _.clone(params.nodesObj[params.nodeId].summary_fields.unified_job_template),
|
|
||||||
isNew: false,
|
|
||||||
edited: false,
|
|
||||||
originalEdge: params.edgeType,
|
|
||||||
originalNodeObj: _.clone(params.nodesObj[params.nodeId]),
|
|
||||||
promptValues: {},
|
|
||||||
isRoot: params.isRoot ? params.isRoot : false
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.workflowTree.data.totalNodes++;
|
|
||||||
|
|
||||||
$scope.workflowTree.nextIndex++;
|
|
||||||
|
|
||||||
if(params.parentId) {
|
|
||||||
treeNode.originalParentId = params.parentId;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop across the success nodes and add them recursively
|
|
||||||
_.forEach(params.nodesObj[params.nodeId].success_nodes, function(successNodeId) {
|
|
||||||
treeNode.children.push(buildBranch({
|
|
||||||
nodeId: successNodeId,
|
|
||||||
parentId: params.nodeId,
|
|
||||||
edgeType: "success",
|
|
||||||
nodesObj: params.nodesObj
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
// failure nodes
|
|
||||||
_.forEach(params.nodesObj[params.nodeId].failure_nodes, function(failureNodesId) {
|
|
||||||
treeNode.children.push(buildBranch({
|
|
||||||
nodeId: failureNodesId,
|
|
||||||
parentId: params.nodeId,
|
|
||||||
edgeType: "failure",
|
|
||||||
nodesObj: params.nodesObj
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
// always nodes
|
|
||||||
_.forEach(params.nodesObj[params.nodeId].always_nodes, function(alwaysNodesId) {
|
|
||||||
treeNode.children.push(buildBranch({
|
|
||||||
nodeId: alwaysNodesId,
|
|
||||||
parentId: params.nodeId,
|
|
||||||
edgeType: "always",
|
|
||||||
nodesObj: params.nodesObj
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
return treeNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
|
|
||||||
// Select2-ify the lables input
|
// Select2-ify the lables input
|
||||||
@@ -195,40 +111,8 @@
|
|||||||
TemplatesService.getWorkflowJobTemplateNodes(id)
|
TemplatesService.getWorkflowJobTemplateNodes(id)
|
||||||
.then(function(data){
|
.then(function(data){
|
||||||
|
|
||||||
let nodesArray = data.data.results;
|
$scope.workflowTree = WorkflowService.buildTree({
|
||||||
let nodesObj = {};
|
workflowNodes: data.data.results
|
||||||
let nonRootNodeIds = [];
|
|
||||||
let allNodeIds = [];
|
|
||||||
|
|
||||||
// Determine which nodes are root nodes
|
|
||||||
_.forEach(nodesArray, function(node) {
|
|
||||||
nodesObj[node.id] = _.clone(node);
|
|
||||||
|
|
||||||
allNodeIds.push(node.id);
|
|
||||||
|
|
||||||
_.forEach(node.success_nodes, function(nodeId){
|
|
||||||
nonRootNodeIds.push(nodeId);
|
|
||||||
});
|
|
||||||
_.forEach(node.failure_nodes, function(nodeId){
|
|
||||||
nonRootNodeIds.push(nodeId);
|
|
||||||
});
|
|
||||||
_.forEach(node.always_nodes, function(nodeId){
|
|
||||||
nonRootNodeIds.push(nodeId);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
let rootNodes = _.difference(allNodeIds, nonRootNodeIds);
|
|
||||||
|
|
||||||
// Loop across the root nodes and re-build the tree
|
|
||||||
_.forEach(rootNodes, function(rootNodeId) {
|
|
||||||
let branch = buildBranch({
|
|
||||||
nodeId: rootNodeId,
|
|
||||||
edgeType: "always",
|
|
||||||
nodesObj: nodesObj,
|
|
||||||
isRoot: true
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.workflowTree.data.children.push(branch);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: I think that the workflow chart directive (and eventually d3) is meddling with
|
// TODO: I think that the workflow chart directive (and eventually d3) is meddling with
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
*************************************************/
|
*************************************************/
|
||||||
|
|
||||||
export default ['$scope', 'WorkflowHelpService', 'generateList', 'TemplateList', 'ProjectList',
|
export default ['$scope', 'WorkflowService', 'generateList', 'TemplateList', 'ProjectList',
|
||||||
'GetBasePath', 'Wait', 'TemplatesService', '$state',
|
'GetBasePath', 'Wait', 'TemplatesService', '$state',
|
||||||
'ProcessErrors', 'InventorySourcesList', 'CreateSelect2', 'WorkflowMakerForm',
|
'ProcessErrors', 'InventorySourcesList', 'CreateSelect2', 'WorkflowMakerForm',
|
||||||
'GenerateForm', 'InventoryList', 'CredentialList', '$q',
|
'GenerateForm', 'InventoryList', 'CredentialList', '$q',
|
||||||
function($scope, WorkflowHelpService, GenerateList, TemplateList, ProjectList,
|
function($scope, WorkflowService, GenerateList, TemplateList, ProjectList,
|
||||||
GetBasePath, Wait, TemplatesService, $state,
|
GetBasePath, Wait, TemplatesService, $state,
|
||||||
ProcessErrors, InventorySourcesList, CreateSelect2, WorkflowMakerForm,
|
ProcessErrors, InventorySourcesList, CreateSelect2, WorkflowMakerForm,
|
||||||
GenerateForm, InventoryList, CredentialList, $q) {
|
GenerateForm, InventoryList, CredentialList, $q) {
|
||||||
@@ -78,7 +78,7 @@ export default ['$scope', 'WorkflowHelpService', 'generateList', 'TemplateList',
|
|||||||
$scope.addParent = parent;
|
$scope.addParent = parent;
|
||||||
$scope.betweenTwoNodes = betweenTwoNodes;
|
$scope.betweenTwoNodes = betweenTwoNodes;
|
||||||
|
|
||||||
$scope.placeholderNode = WorkflowHelpService.addPlaceholderNode({
|
$scope.placeholderNode = WorkflowService.addPlaceholderNode({
|
||||||
parent: parent,
|
parent: parent,
|
||||||
betweenTwoNodes: betweenTwoNodes,
|
betweenTwoNodes: betweenTwoNodes,
|
||||||
tree: $scope.treeData.data,
|
tree: $scope.treeData.data,
|
||||||
@@ -87,7 +87,7 @@ export default ['$scope', 'WorkflowHelpService', 'generateList', 'TemplateList',
|
|||||||
|
|
||||||
$scope.treeData.nextIndex++;
|
$scope.treeData.nextIndex++;
|
||||||
|
|
||||||
let siblingConnectionTypes = WorkflowHelpService.getSiblingConnectionTypes({
|
let siblingConnectionTypes = WorkflowService.getSiblingConnectionTypes({
|
||||||
tree: $scope.treeData.data,
|
tree: $scope.treeData.data,
|
||||||
parentId: betweenTwoNodes ? parent.source.id : parent.id
|
parentId: betweenTwoNodes ? parent.source.id : parent.id
|
||||||
});
|
});
|
||||||
@@ -187,7 +187,7 @@ export default ['$scope', 'WorkflowHelpService', 'generateList', 'TemplateList',
|
|||||||
$scope.cancelNodeForm = function() {
|
$scope.cancelNodeForm = function() {
|
||||||
if ($scope.workflowMakerFormConfig.nodeMode === "add") {
|
if ($scope.workflowMakerFormConfig.nodeMode === "add") {
|
||||||
// Remove the placeholder node from the tree
|
// Remove the placeholder node from the tree
|
||||||
WorkflowHelpService.removeNodeFromTree({
|
WorkflowService.removeNodeFromTree({
|
||||||
tree: $scope.treeData.data,
|
tree: $scope.treeData.data,
|
||||||
nodeToBeDeleted: $scope.placeholderNode
|
nodeToBeDeleted: $scope.placeholderNode
|
||||||
});
|
});
|
||||||
@@ -212,12 +212,12 @@ export default ['$scope', 'WorkflowHelpService', 'generateList', 'TemplateList',
|
|||||||
|
|
||||||
$scope.workflowMakerFormConfig.nodeMode = "edit";
|
$scope.workflowMakerFormConfig.nodeMode = "edit";
|
||||||
|
|
||||||
let parent = WorkflowHelpService.searchTree({
|
let parent = WorkflowService.searchTree({
|
||||||
element: $scope.treeData.data,
|
element: $scope.treeData.data,
|
||||||
matchingId: nodeToEdit.parent.id
|
matchingId: nodeToEdit.parent.id
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.nodeBeingEdited = WorkflowHelpService.searchTree({
|
$scope.nodeBeingEdited = WorkflowService.searchTree({
|
||||||
element: parent,
|
element: parent,
|
||||||
matchingId: nodeToEdit.id
|
matchingId: nodeToEdit.id
|
||||||
});
|
});
|
||||||
@@ -427,7 +427,7 @@ export default ['$scope', 'WorkflowHelpService', 'generateList', 'TemplateList',
|
|||||||
|
|
||||||
// TODO: turn this into a promise so that we can handle errors
|
// TODO: turn this into a promise so that we can handle errors
|
||||||
|
|
||||||
WorkflowHelpService.removeNodeFromTree({
|
WorkflowService.removeNodeFromTree({
|
||||||
tree: $scope.treeData.data,
|
tree: $scope.treeData.data,
|
||||||
nodeToBeDeleted: $scope.nodeToBeDeleted
|
nodeToBeDeleted: $scope.nodeToBeDeleted
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export default ['templateUrl', 'CreateDialog', 'Wait', '$state',
|
|||||||
canAddWorkflowJobTemplate: '='
|
canAddWorkflowJobTemplate: '='
|
||||||
},
|
},
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
templateUrl: templateUrl('job-templates/workflow-maker/workflow-maker'),
|
templateUrl: templateUrl('templates/workflows/workflow-maker/workflow-maker'),
|
||||||
controller: workflowMakerController,
|
controller: workflowMakerController,
|
||||||
link: function(scope) {
|
link: function(scope) {
|
||||||
CreateDialog({
|
CreateDialog({
|
||||||
|
|||||||
@@ -117,6 +117,139 @@ export default [function(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Object.keys(siblingConnectionTypes);
|
return Object.keys(siblingConnectionTypes);
|
||||||
|
},
|
||||||
|
buildTree: function(params) {
|
||||||
|
//params.workflowNodes
|
||||||
|
|
||||||
|
let _this = this;
|
||||||
|
|
||||||
|
let treeData = {
|
||||||
|
data: {
|
||||||
|
id: 1,
|
||||||
|
canDelete: false,
|
||||||
|
canEdit: false,
|
||||||
|
canAddTo: true,
|
||||||
|
isStartNode: true,
|
||||||
|
unifiedJobTemplate: {
|
||||||
|
name: "Workflow Launch"
|
||||||
|
},
|
||||||
|
children: [],
|
||||||
|
deletedNodes: [],
|
||||||
|
totalNodes: 0
|
||||||
|
},
|
||||||
|
nextIndex: 2
|
||||||
|
};
|
||||||
|
|
||||||
|
let nodesArray = params.workflowNodes;
|
||||||
|
let nodesObj = {};
|
||||||
|
let nonRootNodeIds = [];
|
||||||
|
let allNodeIds = [];
|
||||||
|
|
||||||
|
// Determine which nodes are root nodes
|
||||||
|
_.forEach(nodesArray, function(node) {
|
||||||
|
nodesObj[node.id] = _.clone(node);
|
||||||
|
|
||||||
|
allNodeIds.push(node.id);
|
||||||
|
|
||||||
|
_.forEach(node.success_nodes, function(nodeId){
|
||||||
|
nonRootNodeIds.push(nodeId);
|
||||||
|
});
|
||||||
|
_.forEach(node.failure_nodes, function(nodeId){
|
||||||
|
nonRootNodeIds.push(nodeId);
|
||||||
|
});
|
||||||
|
_.forEach(node.always_nodes, function(nodeId){
|
||||||
|
nonRootNodeIds.push(nodeId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
let rootNodes = _.difference(allNodeIds, nonRootNodeIds);
|
||||||
|
|
||||||
|
// Loop across the root nodes and re-build the tree
|
||||||
|
_.forEach(rootNodes, function(rootNodeId) {
|
||||||
|
let branch = _this.buildBranch({
|
||||||
|
nodeId: rootNodeId,
|
||||||
|
edgeType: "always",
|
||||||
|
nodesObj: nodesObj,
|
||||||
|
isRoot: true,
|
||||||
|
treeData: treeData
|
||||||
|
});
|
||||||
|
|
||||||
|
treeData.data.children.push(branch);
|
||||||
|
});
|
||||||
|
|
||||||
|
return treeData;
|
||||||
|
},
|
||||||
|
buildBranch: function(params) {
|
||||||
|
// params.nodeId
|
||||||
|
// params.parentId
|
||||||
|
// params.edgeType
|
||||||
|
// params.nodesObj
|
||||||
|
// params.isRoot
|
||||||
|
// params.treeData
|
||||||
|
|
||||||
|
let _this = this;
|
||||||
|
|
||||||
|
let treeNode = {
|
||||||
|
children: [],
|
||||||
|
c: "#D7D7D7",
|
||||||
|
id: params.treeData.nextIndex,
|
||||||
|
nodeId: params.nodeId,
|
||||||
|
canDelete: true,
|
||||||
|
canEdit: true,
|
||||||
|
canAddTo: true,
|
||||||
|
placeholder: false,
|
||||||
|
edgeType: params.edgeType,
|
||||||
|
unifiedJobTemplate: _.clone(params.nodesObj[params.nodeId].summary_fields.unified_job_template),
|
||||||
|
isNew: false,
|
||||||
|
edited: false,
|
||||||
|
originalEdge: params.edgeType,
|
||||||
|
originalNodeObj: _.clone(params.nodesObj[params.nodeId]),
|
||||||
|
promptValues: {},
|
||||||
|
isRoot: params.isRoot ? params.isRoot : false
|
||||||
|
};
|
||||||
|
|
||||||
|
params.treeData.data.totalNodes++;
|
||||||
|
|
||||||
|
params.treeData.nextIndex++;
|
||||||
|
|
||||||
|
if(params.parentId) {
|
||||||
|
treeNode.originalParentId = params.parentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop across the success nodes and add them recursively
|
||||||
|
_.forEach(params.nodesObj[params.nodeId].success_nodes, function(successNodeId) {
|
||||||
|
treeNode.children.push(_this.buildBranch({
|
||||||
|
nodeId: successNodeId,
|
||||||
|
parentId: params.nodeId,
|
||||||
|
edgeType: "success",
|
||||||
|
nodesObj: params.nodesObj,
|
||||||
|
treeData: params.treeData
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
// failure nodes
|
||||||
|
_.forEach(params.nodesObj[params.nodeId].failure_nodes, function(failureNodesId) {
|
||||||
|
treeNode.children.push(_this.buildBranch({
|
||||||
|
nodeId: failureNodesId,
|
||||||
|
parentId: params.nodeId,
|
||||||
|
edgeType: "failure",
|
||||||
|
nodesObj: params.nodesObj,
|
||||||
|
treeData: params.treeData
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
// always nodes
|
||||||
|
_.forEach(params.nodesObj[params.nodeId].always_nodes, function(alwaysNodesId) {
|
||||||
|
treeNode.children.push(_this.buildBranch({
|
||||||
|
nodeId: alwaysNodesId,
|
||||||
|
parentId: params.nodeId,
|
||||||
|
edgeType: "always",
|
||||||
|
nodesObj: params.nodesObj,
|
||||||
|
treeData: params.treeData
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
return treeNode;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}];
|
}];
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export default ['workflowData',
|
|||||||
'$scope',
|
'$scope',
|
||||||
'ParseTypeChange',
|
'ParseTypeChange',
|
||||||
'ParseVariableString',
|
'ParseVariableString',
|
||||||
|
'WorkflowService',
|
||||||
function(workflowData,
|
function(workflowData,
|
||||||
workflowResultsService,
|
workflowResultsService,
|
||||||
workflowDataOptions,
|
workflowDataOptions,
|
||||||
@@ -13,306 +14,198 @@ export default ['workflowData',
|
|||||||
workflowNodes,
|
workflowNodes,
|
||||||
$scope,
|
$scope,
|
||||||
ParseTypeChange,
|
ParseTypeChange,
|
||||||
ParseVariableString
|
ParseVariableString,
|
||||||
|
WorkflowService
|
||||||
) {
|
) {
|
||||||
var getTowerLinks = function() {
|
|
||||||
var getTowerLink = function(key) {
|
var getTowerLinks = function() {
|
||||||
if ($scope.workflow.related[key]) {
|
var getTowerLink = function(key) {
|
||||||
return '/#/' + $scope.workflow.related[key]
|
if ($scope.workflow.related[key]) {
|
||||||
.split('api/v1/')[1];
|
return '/#/' + $scope.workflow.related[key]
|
||||||
}
|
.split('api/v1/')[1];
|
||||||
else {
|
}
|
||||||
return null;
|
else {
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.workflow_template_link = '/#/templates/workflow_job_template/'+$scope.workflow.workflow_job_template;
|
||||||
|
$scope.created_by_link = getTowerLink('created_by');
|
||||||
|
$scope.cloud_credential_link = getTowerLink('cloud_credential');
|
||||||
|
$scope.network_credential_link = getTowerLink('network_credential');
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.workflow_template_link = '/#/templates/workflow_job_template/'+$scope.workflow.workflow_job_template;
|
var getTowerLabels = function() {
|
||||||
$scope.created_by_link = getTowerLink('created_by');
|
var getTowerLabel = function(key) {
|
||||||
$scope.cloud_credential_link = getTowerLink('cloud_credential');
|
if ($scope.workflowOptions && $scope.workflowOptions[key]) {
|
||||||
$scope.network_credential_link = getTowerLink('network_credential');
|
return $scope.workflowOptions[key].choices
|
||||||
};
|
.filter(val => val[0] === $scope.workflow[key])
|
||||||
|
.map(val => val[1])[0];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var getTowerLabels = function() {
|
$scope.status_label = getTowerLabel('status');
|
||||||
var getTowerLabel = function(key) {
|
$scope.type_label = getTowerLabel('job_type');
|
||||||
if ($scope.workflowOptions && $scope.workflowOptions[key]) {
|
$scope.verbosity_label = getTowerLabel('verbosity');
|
||||||
return $scope.workflowOptions[key].choices
|
};
|
||||||
.filter(val => val[0] === $scope.workflow[key])
|
|
||||||
.map(val => val[1])[0];
|
function init() {
|
||||||
} else {
|
// put initially resolved request data on scope
|
||||||
return null;
|
$scope.workflow = workflowData;
|
||||||
|
$scope.workflow_nodes = workflowNodes;
|
||||||
|
$scope.workflowOptions = workflowDataOptions.actions.GET;
|
||||||
|
$scope.labels = jobLabels;
|
||||||
|
|
||||||
|
// turn related api browser routes into tower routes
|
||||||
|
getTowerLinks();
|
||||||
|
|
||||||
|
// use options labels to manipulate display of details
|
||||||
|
getTowerLabels();
|
||||||
|
|
||||||
|
// set up a read only code mirror for extra vars
|
||||||
|
$scope.variables = ParseVariableString($scope.workflow.extra_vars);
|
||||||
|
$scope.parseType = 'yaml';
|
||||||
|
ParseTypeChange({ scope: $scope,
|
||||||
|
field_id: 'pre-formatted-variables',
|
||||||
|
readOnly: true });
|
||||||
|
|
||||||
|
// Click binding for the expand/collapse button on the standard out log
|
||||||
|
$scope.stdoutFullScreen = false;
|
||||||
|
|
||||||
|
$scope.stdoutArr = [];
|
||||||
|
|
||||||
|
$scope.treeData = WorkflowService.buildTree({
|
||||||
|
workflowNodes: workflowNodes
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: I think that the workflow chart directive (and eventually d3) is meddling with
|
||||||
|
// this treeData object and removing the children object for some reason (?)
|
||||||
|
// This happens on occasion and I think is a race condition (?)
|
||||||
|
if(!$scope.treeData.data.children) {
|
||||||
|
$scope.treeData.data.children = [];
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
$scope.status_label = getTowerLabel('status');
|
$scope.canAddWorkflowJobTemplate = false;
|
||||||
$scope.type_label = getTowerLabel('job_type');
|
|
||||||
$scope.verbosity_label = getTowerLabel('verbosity');
|
|
||||||
};
|
|
||||||
|
|
||||||
// var getTotalHostCount = function(count) {
|
|
||||||
// return Object
|
|
||||||
// .keys(count).reduce((acc, i) => acc += count[i], 0);
|
|
||||||
// };
|
|
||||||
|
|
||||||
// put initially resolved request data on scope
|
|
||||||
$scope.workflow = workflowData;
|
|
||||||
$scope.workflow_nodes = workflowNodes;
|
|
||||||
$scope.workflowOptions = workflowDataOptions.actions.GET;
|
|
||||||
$scope.labels = jobLabels;
|
|
||||||
|
|
||||||
// turn related api browser routes into tower routes
|
|
||||||
getTowerLinks();
|
|
||||||
|
|
||||||
// use options labels to manipulate display of details
|
|
||||||
getTowerLabels();
|
|
||||||
|
|
||||||
// set up a read only code mirror for extra vars
|
|
||||||
$scope.variables = ParseVariableString($scope.workflow.extra_vars);
|
|
||||||
$scope.parseType = 'yaml';
|
|
||||||
ParseTypeChange({ scope: $scope,
|
|
||||||
field_id: 'pre-formatted-variables',
|
|
||||||
readOnly: true });
|
|
||||||
|
|
||||||
// Click binding for the expand/collapse button on the standard out log
|
|
||||||
$scope.stdoutFullScreen = false;
|
|
||||||
$scope.toggleStdoutFullscreen = function() {
|
|
||||||
$scope.stdoutFullScreen = !$scope.stdoutFullScreen;
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.deleteJob = function() {
|
|
||||||
workflowResultsService.deleteJob($scope.workflow);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.cancelJob = function() {
|
|
||||||
workflowResultsService.cancelJob($scope.workflow);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.relaunchJob = function() {
|
|
||||||
workflowResultsService.relaunchJob($scope);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.stdoutArr = [];
|
|
||||||
|
|
||||||
$scope.treeData = {
|
|
||||||
data: {
|
|
||||||
id: 1,
|
|
||||||
canDelete: false,
|
|
||||||
canEdit: false,
|
|
||||||
canAddTo: true,
|
|
||||||
isStartNode: true,
|
|
||||||
unifiedJobTemplate: {
|
|
||||||
name: "Workflow Launch"
|
|
||||||
},
|
|
||||||
children: [],
|
|
||||||
deletedNodes: [],
|
|
||||||
totalNodes: 0
|
|
||||||
},
|
|
||||||
nextIndex: 2
|
|
||||||
};
|
|
||||||
|
|
||||||
function buildBranch(params) {
|
|
||||||
// params.nodeId
|
|
||||||
// params.parentId
|
|
||||||
// params.edgeType
|
|
||||||
// params.nodesObj
|
|
||||||
// params.isRoot
|
|
||||||
|
|
||||||
let treeNode = {
|
|
||||||
children: [],
|
|
||||||
c: "#D7D7D7",
|
|
||||||
id: $scope.treeData.nextIndex,
|
|
||||||
nodeId: params.nodeId,
|
|
||||||
canDelete: true,
|
|
||||||
canEdit: true,
|
|
||||||
canAddTo: true,
|
|
||||||
placeholder: false,
|
|
||||||
edgeType: params.edgeType,
|
|
||||||
unifiedJobTemplate: _.clone(params.nodesObj[params.nodeId].summary_fields.unified_job_template),
|
|
||||||
isNew: false,
|
|
||||||
edited: false,
|
|
||||||
originalEdge: params.edgeType,
|
|
||||||
originalNodeObj: _.clone(params.nodesObj[params.nodeId]),
|
|
||||||
promptValues: {},
|
|
||||||
isRoot: params.isRoot ? params.isRoot : false
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.treeData.data.totalNodes++;
|
|
||||||
|
|
||||||
$scope.treeData.nextIndex++;
|
|
||||||
|
|
||||||
if(params.parentId) {
|
|
||||||
treeNode.originalParentId = params.parentId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop across the success nodes and add them recursively
|
// var getTotalHostCount = function(count) {
|
||||||
_.forEach(params.nodesObj[params.nodeId].success_nodes, function(successNodeId) {
|
// return Object
|
||||||
treeNode.children.push(buildBranch({
|
// .keys(count).reduce((acc, i) => acc += count[i], 0);
|
||||||
nodeId: successNodeId,
|
// };
|
||||||
parentId: params.nodeId,
|
|
||||||
edgeType: "success",
|
|
||||||
nodesObj: params.nodesObj
|
$scope.toggleStdoutFullscreen = function() {
|
||||||
}));
|
$scope.stdoutFullScreen = !$scope.stdoutFullScreen;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.deleteJob = function() {
|
||||||
|
workflowResultsService.deleteJob($scope.workflow);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.cancelJob = function() {
|
||||||
|
workflowResultsService.cancelJob($scope.workflow);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.relaunchJob = function() {
|
||||||
|
workflowResultsService.relaunchJob($scope);
|
||||||
|
};
|
||||||
|
|
||||||
|
// EVENT STUFF BELOW
|
||||||
|
|
||||||
|
// just putting the event queue on scope so it can be inspected in the
|
||||||
|
// console
|
||||||
|
// $scope.event_queue = eventQueue.queue;
|
||||||
|
// $scope.defersArr = eventQueue.populateDefers;
|
||||||
|
|
||||||
|
// This is where the async updates to the UI actually happen.
|
||||||
|
// Flow is event queue munging in the service -> $scope setting in here
|
||||||
|
// var processEvent = function(event) {
|
||||||
|
// // put the event in the queue
|
||||||
|
// eventQueue.populate(event).then(mungedEvent => {
|
||||||
|
// // make changes to ui based on the event returned from the queue
|
||||||
|
// if (mungedEvent.changes) {
|
||||||
|
// mungedEvent.changes.forEach(change => {
|
||||||
|
// // we've got a change we need to make to the UI!
|
||||||
|
// // update the necessary scope and make the change
|
||||||
|
// if (change === 'startTime' && !$scope.workflow.start) {
|
||||||
|
// $scope.workflow.start = mungedEvent.startTime;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (change === 'count' && !$scope.countFinished) {
|
||||||
|
// // for all events that affect the host count,
|
||||||
|
// // update the status bar as well as the host
|
||||||
|
// // count badge
|
||||||
|
// $scope.count = mungedEvent.count;
|
||||||
|
// $scope.hostCount = getTotalHostCount(mungedEvent
|
||||||
|
// .count);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (change === 'playCount') {
|
||||||
|
// $scope.playCount = mungedEvent.playCount;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (change === 'taskCount') {
|
||||||
|
// $scope.taskCount = mungedEvent.taskCount;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (change === 'finishedTime' && !$scope.workflow.finished) {
|
||||||
|
// $scope.workflow.finished = mungedEvent.finishedTime;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (change === 'countFinished') {
|
||||||
|
// // the playbook_on_stats event actually lets
|
||||||
|
// // us know that we don't need to iteratively
|
||||||
|
// // look at event to update the host counts
|
||||||
|
// // any more.
|
||||||
|
// $scope.countFinished = true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if(change === 'stdout'){
|
||||||
|
// angular
|
||||||
|
// .element(".JobResultsStdOut-stdoutContainer")
|
||||||
|
// .append($compile(mungedEvent
|
||||||
|
// .stdout)($scope));
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // the changes have been processed in the ui, mark it in the queue
|
||||||
|
// eventQueue.markProcessed(event);
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
|
||||||
|
// PULL! grab completed event data and process each event
|
||||||
|
// TODO: implement retry logic in case one of these requests fails
|
||||||
|
// var getEvents = function(url) {
|
||||||
|
// workflowResultsService.getEvents(url)
|
||||||
|
// .then(events => {
|
||||||
|
// events.results.forEach(event => {
|
||||||
|
// // get the name in the same format as the data
|
||||||
|
// // coming over the websocket
|
||||||
|
// event.event_name = event.event;
|
||||||
|
// processEvent(event);
|
||||||
|
// });
|
||||||
|
// if (events.next) {
|
||||||
|
// getEvents(events.next);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
// getEvents($scope.job.related.job_events);
|
||||||
|
|
||||||
|
// // Processing of job_events messages from the websocket
|
||||||
|
// $scope.$on(`ws-job_events-${$scope.workflow.id}`, function(e, data) {
|
||||||
|
// processEvent(data);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// Processing of job-status messages from the websocket
|
||||||
|
$scope.$on(`ws-jobs`, function(e, data) {
|
||||||
|
if (parseInt(data.unified_job_id, 10) === parseInt($scope.workflow.id,10)) {
|
||||||
|
$scope.workflow.status = data.status;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// failure nodes
|
init();
|
||||||
_.forEach(params.nodesObj[params.nodeId].failure_nodes, function(failureNodesId) {
|
|
||||||
treeNode.children.push(buildBranch({
|
|
||||||
nodeId: failureNodesId,
|
|
||||||
parentId: params.nodeId,
|
|
||||||
edgeType: "failure",
|
|
||||||
nodesObj: params.nodesObj
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
// always nodes
|
|
||||||
_.forEach(params.nodesObj[params.nodeId].always_nodes, function(alwaysNodesId) {
|
|
||||||
treeNode.children.push(buildBranch({
|
|
||||||
nodeId: alwaysNodesId,
|
|
||||||
parentId: params.nodeId,
|
|
||||||
edgeType: "always",
|
|
||||||
nodesObj: params.nodesObj
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
return treeNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let nodesArray = $scope.workflow_nodes;
|
|
||||||
let nodesObj = {};
|
|
||||||
let nonRootNodeIds = [];
|
|
||||||
let allNodeIds = [];
|
|
||||||
|
|
||||||
// Determine which nodes are root nodes
|
|
||||||
_.forEach(nodesArray, function(node) {
|
|
||||||
nodesObj[node.id] = _.clone(node);
|
|
||||||
|
|
||||||
allNodeIds.push(node.id);
|
|
||||||
|
|
||||||
_.forEach(node.success_nodes, function(nodeId){
|
|
||||||
nonRootNodeIds.push(nodeId);
|
|
||||||
});
|
|
||||||
_.forEach(node.failure_nodes, function(nodeId){
|
|
||||||
nonRootNodeIds.push(nodeId);
|
|
||||||
});
|
|
||||||
_.forEach(node.always_nodes, function(nodeId){
|
|
||||||
nonRootNodeIds.push(nodeId);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
let rootNodes = _.difference(allNodeIds, nonRootNodeIds);
|
|
||||||
|
|
||||||
// Loop across the root nodes and re-build the tree
|
|
||||||
_.forEach(rootNodes, function(rootNodeId) {
|
|
||||||
let branch = buildBranch({
|
|
||||||
nodeId: rootNodeId,
|
|
||||||
edgeType: "always",
|
|
||||||
nodesObj: nodesObj,
|
|
||||||
isRoot: true
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.treeData.data.children.push(branch);
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: I think that the workflow chart directive (and eventually d3) is meddling with
|
|
||||||
// this treeData object and removing the children object for some reason (?)
|
|
||||||
// This happens on occasion and I think is a race condition (?)
|
|
||||||
if(!$scope.treeData.data.children) {
|
|
||||||
$scope.treeData.data.children = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.canAddWorkflowJobTemplate = false;
|
|
||||||
|
|
||||||
// EVENT STUFF BELOW
|
|
||||||
|
|
||||||
// just putting the event queue on scope so it can be inspected in the
|
|
||||||
// console
|
|
||||||
// $scope.event_queue = eventQueue.queue;
|
|
||||||
// $scope.defersArr = eventQueue.populateDefers;
|
|
||||||
|
|
||||||
// This is where the async updates to the UI actually happen.
|
|
||||||
// Flow is event queue munging in the service -> $scope setting in here
|
|
||||||
// var processEvent = function(event) {
|
|
||||||
// // put the event in the queue
|
|
||||||
// eventQueue.populate(event).then(mungedEvent => {
|
|
||||||
// // make changes to ui based on the event returned from the queue
|
|
||||||
// if (mungedEvent.changes) {
|
|
||||||
// mungedEvent.changes.forEach(change => {
|
|
||||||
// // we've got a change we need to make to the UI!
|
|
||||||
// // update the necessary scope and make the change
|
|
||||||
// if (change === 'startTime' && !$scope.workflow.start) {
|
|
||||||
// $scope.workflow.start = mungedEvent.startTime;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (change === 'count' && !$scope.countFinished) {
|
|
||||||
// // for all events that affect the host count,
|
|
||||||
// // update the status bar as well as the host
|
|
||||||
// // count badge
|
|
||||||
// $scope.count = mungedEvent.count;
|
|
||||||
// $scope.hostCount = getTotalHostCount(mungedEvent
|
|
||||||
// .count);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (change === 'playCount') {
|
|
||||||
// $scope.playCount = mungedEvent.playCount;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (change === 'taskCount') {
|
|
||||||
// $scope.taskCount = mungedEvent.taskCount;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (change === 'finishedTime' && !$scope.workflow.finished) {
|
|
||||||
// $scope.workflow.finished = mungedEvent.finishedTime;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (change === 'countFinished') {
|
|
||||||
// // the playbook_on_stats event actually lets
|
|
||||||
// // us know that we don't need to iteratively
|
|
||||||
// // look at event to update the host counts
|
|
||||||
// // any more.
|
|
||||||
// $scope.countFinished = true;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if(change === 'stdout'){
|
|
||||||
// angular
|
|
||||||
// .element(".JobResultsStdOut-stdoutContainer")
|
|
||||||
// .append($compile(mungedEvent
|
|
||||||
// .stdout)($scope));
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // the changes have been processed in the ui, mark it in the queue
|
|
||||||
// eventQueue.markProcessed(event);
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
|
|
||||||
// PULL! grab completed event data and process each event
|
|
||||||
// TODO: implement retry logic in case one of these requests fails
|
|
||||||
// var getEvents = function(url) {
|
|
||||||
// workflowResultsService.getEvents(url)
|
|
||||||
// .then(events => {
|
|
||||||
// events.results.forEach(event => {
|
|
||||||
// // get the name in the same format as the data
|
|
||||||
// // coming over the websocket
|
|
||||||
// event.event_name = event.event;
|
|
||||||
// processEvent(event);
|
|
||||||
// });
|
|
||||||
// if (events.next) {
|
|
||||||
// getEvents(events.next);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
// getEvents($scope.job.related.job_events);
|
|
||||||
|
|
||||||
// // Processing of job_events messages from the websocket
|
|
||||||
// $scope.$on(`ws-job_events-${$scope.workflow.id}`, function(e, data) {
|
|
||||||
// processEvent(data);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// Processing of job-status messages from the websocket
|
|
||||||
$scope.$on(`ws-jobs`, function(e, data) {
|
|
||||||
if (parseInt(data.unified_job_id, 10) === parseInt($scope.workflow.id,10)) {
|
|
||||||
$scope.workflow.status = data.status;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}];
|
}];
|
||||||
|
|||||||
Reference in New Issue
Block a user