Files
awx/awx/ui/client/src/workflow-results/workflow-results.controller.js
mabashian df6c453c86 Fix long name tooltip. Fixed bug adding new node before finishing adding new link.
Fixed template list column layout.  Ensure that we're getting 200 workflow nodes per GET request
2018-11-16 09:18:06 -05:00

293 lines
12 KiB
JavaScript

export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
'jobLabels', 'workflowNodes', '$scope', 'ParseTypeChange',
'ParseVariableString', 'count', '$state', 'i18n', 'WorkflowChartService', '$filter',
'moment', function(workflowData, workflowResultsService,
workflowDataOptions, jobLabels, workflowNodes, $scope, ParseTypeChange,
ParseVariableString, count, $state, i18n, WorkflowChartService, $filter,
moment) {
var runTimeElapsedTimer = null;
let nodeIdToChartNodeIdMapping = {};
let chartNodeIdToIndexMapping = {};
var getLinks = function() {
var getLink = function(key) {
if(key === 'schedule') {
if($scope.workflow.related.schedule) {
return '/#/templates/workflow_job_template/' + $scope.workflow.workflow_job_template + '/schedules' + $scope.workflow.related.schedule.split(/api\/v\d+\/schedules/)[1];
}
else {
return null;
}
}
else {
if ($scope.workflow.related[key]) {
return '/#/' + $scope.workflow.related[key]
.split(/api\/v\d+\//)[1];
} else {
return null;
}
}
};
$scope.workflow_template_link = '/#/templates/workflow_job_template/'+$scope.workflow.workflow_job_template;
$scope.created_by_link = getLink('created_by');
$scope.scheduled_by_link = getLink('schedule');
$scope.cloud_credential_link = getLink('cloud_credential');
$scope.network_credential_link = getLink('network_credential');
$scope.strings = {
tooltips: {
RELAUNCH: i18n._('Relaunch using the same parameters'),
CANCEL: i18n._('Cancel'),
DELETE: i18n._('Delete'),
EDIT_USER: i18n._('Edit the user'),
EDIT_WORKFLOW: i18n._('Edit the workflow job template'),
EDIT_SLICE_TEMPLATE: i18n._('Edit the slice job template'),
EDIT_SCHEDULE: i18n._('Edit the schedule'),
SOURCE_WORKFLOW_JOB: i18n._('View the source Workflow Job'),
TOGGLE_STDOUT_FULLSCREEN: i18n._('Expand Output'),
STATUS: '' // re-assigned elsewhere
},
labels: {
TEMPLATE: i18n._('Template'),
LAUNCHED_BY: i18n._('Launched By'),
STARTED: i18n._('Started'),
FINISHED: i18n._('Finished'),
LABELS: i18n._('Labels'),
STATUS: i18n._('Status'),
SLICE_TEMPLATE: i18n._('Slice Job Template'),
JOB_EXPLANATION: i18n._('Explanation'),
SOURCE_WORKFLOW_JOB: i18n._('Source Workflow')
},
details: {
HEADER: i18n._('DETAILS'),
NOT_FINISHED: i18n._('Not Finished'),
NOT_STARTED: i18n._('Not Started'),
SHOW_LESS: i18n._('Show Less'),
SHOW_MORE: i18n._('Show More'),
},
results: {
TOTAL_JOBS: i18n._('Total Jobs'),
ELAPSED: i18n._('Elapsed'),
},
legend: {
ON_SUCCESS: i18n._('On Success'),
ON_FAILURE: i18n._('On Failure'),
ALWAYS: i18n._('Always'),
PROJECT_SYNC: i18n._('Project Sync'),
INVENTORY_SYNC: i18n._('Inventory Sync'),
WORKFLOW: i18n._('Workflow'),
KEY: i18n._('KEY'),
}
};
};
var getLabelsAndTooltips = function() {
var getLabel = 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.workflow.statusLabel = i18n._(getLabel('status'));
$scope.strings.tooltips.STATUS = `${i18n._('Job')} ${$scope.workflow.statusLabel}`;
};
var updateWorkflowJobElapsedTimer = function(time) {
$scope.workflow.elapsed = time;
};
function init() {
// put initially resolved request data on scope
$scope.workflow = workflowData;
$scope.workflow_nodes = workflowNodes;
$scope.workflowOptions = workflowDataOptions.actions.GET;
$scope.labels = jobLabels;
$scope.showManualControls = false;
$scope.readOnly = true;
// Start elapsed time updater for job known to be running
if ($scope.workflow.started !== null && $scope.workflow.status === 'running') {
runTimeElapsedTimer = workflowResultsService.createOneSecondTimer($scope.workflow.started, updateWorkflowJobElapsedTimer);
}
if(workflowData.summary_fields && workflowData.summary_fields.workflow_job_template &&
workflowData.summary_fields.workflow_job_template.id){
$scope.workflow_job_template_link = `/#/templates/workflow_job_template/${$scope.workflow.summary_fields.workflow_job_template.id}`;
}
if(workflowData.summary_fields && workflowData.summary_fields.job_template &&
workflowData.summary_fields.job_template.id){
$scope.slice_job_template_link = `/#/templates/job_template/${$scope.workflow.summary_fields.job_template.id}`;
}
if (_.get(workflowData, 'summary_fields.source_workflow_job.id')) {
$scope.source_workflow_job_link = `/#/workflows/${workflowData.summary_fields.source_workflow_job.id}`;
}
if (workflowData.job_explanation) {
const limit = 150;
const more = workflowData.job_explanation;
const less = $filter('limitTo')(more, limit);
const showMore = false;
const hasMoreToShow = more.length > limit;
const job_explanation = {
more: more,
less: less,
showMore: showMore,
hasMoreToShow: hasMoreToShow
};
$scope.job_explanation = job_explanation;
}
// turn related api browser routes into front end routes
getLinks();
// use options labels to manipulate display of details
getLabelsAndTooltips();
// set up a read only code mirror for extra vars
$scope.variables = ParseVariableString($scope.workflow.extra_vars);
$scope.parseType = 'yaml';
$scope.varsTooltip= i18n._('Read only view of extra variables added to the workflow.');
$scope.varsLabel = i18n._('Extra Variables');
// Click binding for the expand/collapse button on the standard out log
$scope.stdoutFullScreen = false;
let arrayOfLinksForChart = [];
let arrayOfNodesForChart = [];
({arrayOfNodesForChart, arrayOfLinksForChart, chartNodeIdToIndexMapping, nodeIdToChartNodeIdMapping} = WorkflowChartService.generateArraysOfNodesAndLinks(workflowNodes));
let depthMap = WorkflowChartService.generateDepthMap(arrayOfLinksForChart);
$scope.graphState = { arrayOfNodesForChart, arrayOfLinksForChart, depthMap };
}
$scope.toggleStdoutFullscreen = function() {
$scope.$broadcast('workflowDetailsResized');
$scope.stdoutFullScreen = !$scope.stdoutFullScreen;
if ($scope.stdoutFullScreen === true) {
$scope.toggleStdoutFullscreenTooltip = i18n._("Collapse Output");
} else if ($scope.stdoutFullScreen === false) {
$scope.toggleStdoutFullscreenTooltip = i18n._("Expand Output");
}
};
$scope.deleteJob = function() {
workflowResultsService.deleteJob($scope.workflow);
};
$scope.cancelJob = function() {
workflowResultsService.cancelJob($scope.workflow);
};
$scope.relaunchJob = function() {
workflowResultsService.relaunchJob($scope);
};
$scope.toggleManualControls = function() {
$scope.showManualControls = !$scope.showManualControls;
};
$scope.lessLabels = false;
$scope.toggleLessLabels = function() {
if (!$scope.lessLabels) {
$('#workflow-results-labels').slideUp(200);
$scope.lessLabels = true;
}
else {
$('#workflow-results-labels').slideDown(200);
$scope.lessLabels = false;
}
};
$scope.panChart = function(direction) {
$scope.$broadcast('panWorkflowChart', {
direction: direction
});
};
$scope.zoomChart = function(zoom) {
$scope.$broadcast('zoomWorkflowChart', {
zoom: zoom
});
};
$scope.resetChart = function() {
$scope.$broadcast('resetWorkflowChart');
};
$scope.zoomToFitChart = function() {
$scope.$broadcast('zoomToFitChart');
};
$scope.workflowZoomed = function(zoom) {
$scope.$broadcast('workflowZoomed', {
zoom: zoom
});
};
init();
// Processing of job-status messages from the websocket
$scope.$on(`ws-jobs`, function(e, data) {
// Update the workflow job's unified job:
if (parseInt(data.unified_job_id, 10) === parseInt($scope.workflow.id,10)) {
$scope.workflow.status = data.status;
// start internval counter for job that transitioned to running
if ($scope.workflow.status === 'running') {
runTimeElapsedTimer = workflowResultsService.createOneSecondTimer(moment(), updateWorkflowJobElapsedTimer);
}
if(data.status === "successful" || data.status === "failed" || data.status === "canceled" || data.status === "error"){
$state.go('.', null, { reload: true });
}
}
// Update the jobs spawned by the workflow:
if(data.hasOwnProperty('workflow_job_id') &&
parseInt(data.workflow_job_id, 10) === parseInt($scope.workflow.id,10)){
// This check ensures that the workflow status icon doesn't get stuck in
// the waiting state due to the UI missing the initial socket message. This
// can happen if the GET request on the workflow job returns "waiting" and
// the sockets aren't established yet so we miss the event that indicates
// the workflow job has moved into a running state.
if (!_.includes(['running', 'successful', 'failed', 'error', 'canceled'], $scope.workflow.status)){
$scope.workflow.status = 'running';
runTimeElapsedTimer = workflowResultsService.createOneSecondTimer(moment(), updateWorkflowJobElapsedTimer);
}
$scope.graphState.arrayOfNodesForChart[chartNodeIdToIndexMapping[nodeIdToChartNodeIdMapping[data.workflow_node_id]]].job = {
id: data.unified_job_id,
status: data.status
};
$scope.workflow_nodes.forEach(node => {
if(parseInt(node.id) === parseInt(data.workflow_node_id)){
node.summary_fields.job = {
status: data.status
};
}
});
$scope.$broadcast("refreshWorkflowChart");
}
getLabelsAndTooltips();
});
$scope.$on('$destroy', function() {
workflowResultsService.destroyTimer(runTimeElapsedTimer);
});
}];