From 17b4b1e7a2b0b23aef2b75b359a2576911ac9384 Mon Sep 17 00:00:00 2001 From: Michael Abashian Date: Tue, 15 Nov 2016 09:51:51 -0500 Subject: [PATCH] Moved a significant amount of the tree generation logic out to the workflow service --- .../templates/labels/labelsList.directive.js | 2 +- awx/ui/client/src/templates/main.js | 2 +- .../edit-workflow/workflow-edit.controller.js | 126 +---- .../workflow-maker.controller.js | 16 +- .../workflow-maker.directive.js | 2 +- .../templates/workflows/workflow.service.js | 133 +++++ .../workflow-results.controller.js | 475 +++++++----------- 7 files changed, 333 insertions(+), 423 deletions(-) diff --git a/awx/ui/client/src/templates/labels/labelsList.directive.js b/awx/ui/client/src/templates/labels/labelsList.directive.js index c1e4669bb0..54c49ef47c 100644 --- a/awx/ui/client/src/templates/labels/labelsList.directive.js +++ b/awx/ui/client/src/templates/labels/labelsList.directive.js @@ -12,7 +12,7 @@ export default return { restrict: 'E', scope: false, - templateUrl: templateUrl('job-templates/labels/labelsList'), + templateUrl: templateUrl('templates/labels/labelsList'), link: function(scope, element, attrs) { scope.showDelete = attrs.showDelete === 'true'; scope.seeMoreInactive = true; diff --git a/awx/ui/client/src/templates/main.js b/awx/ui/client/src/templates/main.js index 06ad97905f..5e2591b3a2 100644 --- a/awx/ui/client/src/templates/main.js +++ b/awx/ui/client/src/templates/main.js @@ -24,7 +24,7 @@ angular.module('templates', [surveyMaker.name, templatesList.name, jobTemplatesA workflowChart.name, workflowMaker.name ]) .service('TemplatesService', templatesService) - .service('WorkflowHelpService', workflowService) + .service('WorkflowService', workflowService) .config(['$stateProvider', 'stateDefinitionsProvider', '$stateExtenderProvider', function($stateProvider, stateDefinitionsProvider, $stateExtenderProvider) { let stateTree, addJobTemplate, editJobTemplate, addWorkflow, editWorkflow, diff --git a/awx/ui/client/src/templates/workflows/edit-workflow/workflow-edit.controller.js b/awx/ui/client/src/templates/workflows/edit-workflow/workflow-edit.controller.js index c4cf1c13e3..b719614929 100644 --- a/awx/ui/client/src/templates/workflows/edit-workflow/workflow-edit.controller.js +++ b/awx/ui/client/src/templates/workflows/edit-workflow/workflow-edit.controller.js @@ -8,13 +8,13 @@ [ '$scope', '$stateParams', 'WorkflowForm', 'GenerateForm', 'Alert', 'ProcessErrors', 'ClearScope', 'GetBasePath', '$q', 'ParseTypeChange', 'Wait', 'Empty', 'ToJSON', 'initSurvey', '$state', 'CreateSelect2', 'ParseVariableString', - 'TemplatesService', 'OrganizationList', 'Rest', + 'TemplatesService', 'OrganizationList', 'Rest', 'WorkflowService', function( $scope, $stateParams, WorkflowForm, GenerateForm, Alert, ProcessErrors, ClearScope, GetBasePath, $q, ParseTypeChange, Wait, Empty, ToJSON, SurveyControllerInit, $state, CreateSelect2, ParseVariableString, - TemplatesService, OrganizationList, Rest - ) {window.state = $state; + TemplatesService, OrganizationList, Rest, WorkflowService + ) { ClearScope(); @@ -40,90 +40,6 @@ $scope.associateRequests = []; $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() { // Select2-ify the lables input @@ -195,40 +111,8 @@ TemplatesService.getWorkflowJobTemplateNodes(id) .then(function(data){ - let nodesArray = data.data.results; - 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.workflowTree.data.children.push(branch); + $scope.workflowTree = WorkflowService.buildTree({ + workflowNodes: data.data.results }); // TODO: I think that the workflow chart directive (and eventually d3) is meddling with diff --git a/awx/ui/client/src/templates/workflows/workflow-maker/workflow-maker.controller.js b/awx/ui/client/src/templates/workflows/workflow-maker/workflow-maker.controller.js index 2a53614137..7c7564ef40 100644 --- a/awx/ui/client/src/templates/workflows/workflow-maker/workflow-maker.controller.js +++ b/awx/ui/client/src/templates/workflows/workflow-maker/workflow-maker.controller.js @@ -4,11 +4,11 @@ * All Rights Reserved *************************************************/ -export default ['$scope', 'WorkflowHelpService', 'generateList', 'TemplateList', 'ProjectList', +export default ['$scope', 'WorkflowService', 'generateList', 'TemplateList', 'ProjectList', 'GetBasePath', 'Wait', 'TemplatesService', '$state', 'ProcessErrors', 'InventorySourcesList', 'CreateSelect2', 'WorkflowMakerForm', 'GenerateForm', 'InventoryList', 'CredentialList', '$q', - function($scope, WorkflowHelpService, GenerateList, TemplateList, ProjectList, + function($scope, WorkflowService, GenerateList, TemplateList, ProjectList, GetBasePath, Wait, TemplatesService, $state, ProcessErrors, InventorySourcesList, CreateSelect2, WorkflowMakerForm, GenerateForm, InventoryList, CredentialList, $q) { @@ -78,7 +78,7 @@ export default ['$scope', 'WorkflowHelpService', 'generateList', 'TemplateList', $scope.addParent = parent; $scope.betweenTwoNodes = betweenTwoNodes; - $scope.placeholderNode = WorkflowHelpService.addPlaceholderNode({ + $scope.placeholderNode = WorkflowService.addPlaceholderNode({ parent: parent, betweenTwoNodes: betweenTwoNodes, tree: $scope.treeData.data, @@ -87,7 +87,7 @@ export default ['$scope', 'WorkflowHelpService', 'generateList', 'TemplateList', $scope.treeData.nextIndex++; - let siblingConnectionTypes = WorkflowHelpService.getSiblingConnectionTypes({ + let siblingConnectionTypes = WorkflowService.getSiblingConnectionTypes({ tree: $scope.treeData.data, parentId: betweenTwoNodes ? parent.source.id : parent.id }); @@ -187,7 +187,7 @@ export default ['$scope', 'WorkflowHelpService', 'generateList', 'TemplateList', $scope.cancelNodeForm = function() { if ($scope.workflowMakerFormConfig.nodeMode === "add") { // Remove the placeholder node from the tree - WorkflowHelpService.removeNodeFromTree({ + WorkflowService.removeNodeFromTree({ tree: $scope.treeData.data, nodeToBeDeleted: $scope.placeholderNode }); @@ -212,12 +212,12 @@ export default ['$scope', 'WorkflowHelpService', 'generateList', 'TemplateList', $scope.workflowMakerFormConfig.nodeMode = "edit"; - let parent = WorkflowHelpService.searchTree({ + let parent = WorkflowService.searchTree({ element: $scope.treeData.data, matchingId: nodeToEdit.parent.id }); - $scope.nodeBeingEdited = WorkflowHelpService.searchTree({ + $scope.nodeBeingEdited = WorkflowService.searchTree({ element: parent, 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 - WorkflowHelpService.removeNodeFromTree({ + WorkflowService.removeNodeFromTree({ tree: $scope.treeData.data, nodeToBeDeleted: $scope.nodeToBeDeleted }); diff --git a/awx/ui/client/src/templates/workflows/workflow-maker/workflow-maker.directive.js b/awx/ui/client/src/templates/workflows/workflow-maker/workflow-maker.directive.js index 3e001d2817..cccc4f638e 100644 --- a/awx/ui/client/src/templates/workflows/workflow-maker/workflow-maker.directive.js +++ b/awx/ui/client/src/templates/workflows/workflow-maker/workflow-maker.directive.js @@ -14,7 +14,7 @@ export default ['templateUrl', 'CreateDialog', 'Wait', '$state', canAddWorkflowJobTemplate: '=' }, restrict: 'E', - templateUrl: templateUrl('job-templates/workflow-maker/workflow-maker'), + templateUrl: templateUrl('templates/workflows/workflow-maker/workflow-maker'), controller: workflowMakerController, link: function(scope) { CreateDialog({ diff --git a/awx/ui/client/src/templates/workflows/workflow.service.js b/awx/ui/client/src/templates/workflows/workflow.service.js index 65d0807424..1d2a102b1a 100644 --- a/awx/ui/client/src/templates/workflows/workflow.service.js +++ b/awx/ui/client/src/templates/workflows/workflow.service.js @@ -117,6 +117,139 @@ export default [function(){ } 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; } }; }]; diff --git a/awx/ui/client/src/workflow-results/workflow-results.controller.js b/awx/ui/client/src/workflow-results/workflow-results.controller.js index 212907e936..164ef5d35b 100644 --- a/awx/ui/client/src/workflow-results/workflow-results.controller.js +++ b/awx/ui/client/src/workflow-results/workflow-results.controller.js @@ -6,6 +6,7 @@ export default ['workflowData', '$scope', 'ParseTypeChange', 'ParseVariableString', + 'WorkflowService', function(workflowData, workflowResultsService, workflowDataOptions, @@ -13,306 +14,198 @@ export default ['workflowData', workflowNodes, $scope, ParseTypeChange, - ParseVariableString + ParseVariableString, + WorkflowService ) { - var getTowerLinks = function() { - var getTowerLink = function(key) { - if ($scope.workflow.related[key]) { - return '/#/' + $scope.workflow.related[key] - .split('api/v1/')[1]; - } - else { - return null; - } + + var getTowerLinks = function() { + var getTowerLink = function(key) { + if ($scope.workflow.related[key]) { + return '/#/' + $scope.workflow.related[key] + .split('api/v1/')[1]; + } + 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; - $scope.created_by_link = getTowerLink('created_by'); - $scope.cloud_credential_link = getTowerLink('cloud_credential'); - $scope.network_credential_link = getTowerLink('network_credential'); - }; + var getTowerLabels = function() { + var getTowerLabel = function(key) { + if ($scope.workflowOptions && $scope.workflowOptions[key]) { + return $scope.workflowOptions[key].choices + .filter(val => val[0] === $scope.workflow[key]) + .map(val => val[1])[0]; + } else { + return null; + } + }; - var getTowerLabels = function() { - var getTowerLabel = function(key) { - if ($scope.workflowOptions && $scope.workflowOptions[key]) { - return $scope.workflowOptions[key].choices - .filter(val => val[0] === $scope.workflow[key]) - .map(val => val[1])[0]; - } else { - return null; + $scope.status_label = getTowerLabel('status'); + $scope.type_label = getTowerLabel('job_type'); + $scope.verbosity_label = getTowerLabel('verbosity'); + }; + + function init() { + // 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.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.type_label = getTowerLabel('job_type'); - $scope.verbosity_label = getTowerLabel('verbosity'); - }; + $scope.canAddWorkflowJobTemplate = false; - // 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 - _.forEach(params.nodesObj[params.nodeId].success_nodes, function(successNodeId) { - treeNode.children.push(buildBranch({ - nodeId: successNodeId, - parentId: params.nodeId, - edgeType: "success", - nodesObj: params.nodesObj - })); + // var getTotalHostCount = function(count) { + // return Object + // .keys(count).reduce((acc, i) => acc += count[i], 0); + // }; + + + $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 - _.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; - } - }); + init(); }];