diff --git a/awx/ui/client/src/helpers/JobDetail.js b/awx/ui/client/src/helpers/JobDetail.js deleted file mode 100644 index ad049ed481..0000000000 --- a/awx/ui/client/src/helpers/JobDetail.js +++ /dev/null @@ -1,1198 +0,0 @@ -/************************************************* - * Copyright (c) 2015 Ansible, Inc. - * - * All Rights Reserved - *************************************************/ - - /** - * @ngdoc function - * @name helpers.function:JobDetail - * @description helper moduler for jobdetails controller - # Playbook events will be structured to form the following hierarchy: - # - playbook_on_start (once for each playbook file) - # - playbook_on_vars_prompt (for each play, but before play starts, we - # currently don't handle responding to these prompts) - # - playbook_on_play_start (once for each play) - # - playbook_on_import_for_host - # - playbook_on_not_import_for_host - # - playbook_on_no_hosts_matched - # - playbook_on_no_hosts_remaining - # - playbook_on_setup - # - runner_on* - # - playbook_on_task_start (once for each task within a play) - # - runner_on_failed - # - runner_on_ok - # - runner_on_error - # - runner_on_skipped - # - runner_on_unreachable - # - runner_on_no_hosts - # - runner_on_async_poll - # - runner_on_async_ok - # - runner_on_async_failed - # - runner_on_file_diff - # - playbook_on_notify (once for each notification from the play) - # - playbook_on_stats - -*/ - - -export default - angular.module('JobDetailHelper', ['Utilities', 'RestServices', 'ModalDialog']) - - .factory('DigestEvent', ['$rootScope', '$log', 'UpdatePlayStatus', 'UpdateHostStatus', 'AddHostResult', - 'GetElapsed', 'UpdateTaskStatus', 'JobIsFinished', 'AddNewTask', 'AddNewPlay', - function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, GetElapsed, - UpdateTaskStatus, JobIsFinished, AddNewTask, AddNewPlay) { - return function(params) { - - var scope = params.scope, - event = params.event, - msg; - - $log.debug('processing event: ' + event.id); - $log.debug(event); - - function getMsg(event) { - var msg = ''; - if (event.event_data && event.event_data.res) { - if (typeof event.event_data.res === 'object') { - msg = event.event_data.res.msg; - } else { - msg = event.event_data.res; - } - } - return msg; - } - - switch (event.event) { - case 'playbook_on_start': - if (!JobIsFinished(scope)) { - scope.job_status.started = event.created; - scope.job_status.status = 'running'; - } - break; - - case 'playbook_on_play_start': - AddNewPlay({ scope: scope, event: event }); - break; - - case 'playbook_on_setup': - AddNewTask({ scope: scope, event: event }); - break; - - case 'playbook_on_task_start': - AddNewTask({ scope: scope, event: event }); - break; - - case 'runner_on_ok': - case 'runner_on_async_ok': - msg = getMsg(event); - UpdateHostStatus({ - scope: scope, - name: event.host_name, - host_id: event.host, - task_id: event.parent, - status: ( (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful' ), - id: event.id, - created: event.created, - modified: event.modified, - message: msg, - counter: event.counter, - item: (event.event_data && event.event_data.res) ? event.event_data.res.item : '' - }); - break; - - case 'playbook_on_no_hosts_matched': - UpdatePlayStatus({ - scope: scope, - play_id: event.parent, - failed: false, - changed: false, - modified: event.modified, - no_hosts: true - }); - break; - - case 'runner_on_unreachable': - msg = getMsg(event); - UpdateHostStatus({ - scope: scope, - name: event.host_name, - host_id: event.host, - task_id: event.parent, - status: 'unreachable', - id: event.id, - created: event.created, - modified: event.modified, - message: msg, - counter: event.counter, - item: (event.event_data && event.event_data.res) ? event.event_data.res.item : '' - }); - break; - - case 'runner_on_error': - case 'runner_on_async_failed': - msg = getMsg(event); - UpdateHostStatus({ - scope: scope, - name: event.host_name, - host_id: event.host, - task_id: event.parent, - status: 'failed', - id: event.id, - created: event.created, - modified: event.modified, - message: msg, - counter: event.counter, - item: (event.event_data && event.event_data.res) ? event.event_data.res.item : '' - }); - break; - - case 'runner_on_no_hosts': - UpdateTaskStatus({ - scope: scope, - failed: event.failed, - changed: event.changed, - task_id: event.parent, - modified: event.modified, - no_hosts: true - }); - break; - - case 'runner_on_skipped': - msg = getMsg(event); - UpdateHostStatus({ - scope: scope, - name: event.host_name, - host_id: event.host, - task_id: event.parent, - status: 'skipped', - id: event.id, - created: event.created, - modified: event.modified, - message: msg, - counter: event.counter, - item: (event.event_data && event.event_data.res) ? event.event_data.res.item : '' - }); - } - }; - }]) - - .factory('JobIsFinished', [ function() { - return function(scope) { - return (scope.job_status.status === 'failed' || scope.job_status.status === 'canceled' || - scope.job_status.status === 'error' || scope.job_status.status === 'successful'); - }; - }]) - - .factory('GetElapsed', [function() { - return function(params) { - var start = params.start, - end = params.end, - dt1, dt2, sec, hours, min; - dt1 = new Date(start); - dt2 = new Date(end); - if ( dt2.getTime() !== dt1.getTime() ) { - sec = Math.floor( (dt2.getTime() - dt1.getTime()) / 1000 ); - hours = Math.floor(sec / 3600); - sec = sec - (hours * 3600); - if (('' + hours).length < 2) { - hours = ('00' + hours).substr(-2, 2); - } - min = Math.floor(sec / 60); - sec = sec - (min * 60); - min = ('00' + min).substr(-2,2); - sec = ('00' + sec).substr(-2,2); - return hours + ':' + min + ':' + sec; - } - else { - return '00:00:00'; - } - }; - }]) - - .factory('SetActivePlay', [ function() { - return function(params) { - //find the most recent task in the list of 'active' tasks - - var scope = params.scope, - activeList = [], - newActivePlay, - key; - - for (key in scope.jobData.plays) { - if (scope.jobData.plays[key].taskCount > 0) { - activeList.push(key); - } - } - - if (activeList.length > 0) { - newActivePlay = scope.jobData.plays[activeList[activeList.length - 1]].id; - if (newActivePlay && scope.activePlay && newActivePlay !== scope.activePlay) { - scope.jobData.plays[scope.activePlay].tasks = {}; - scope.jobData.plays[scope.activePlay].playActiveClass = ''; - scope.activeTask = null; - } - if (newActivePlay) { - scope.activePlay = newActivePlay; - scope.jobData.plays[scope.activePlay].playActiveClass = 'JobDetail-tableRow--selected'; - } - } - }; - }]) - - .factory('SetActiveTask', [ function() { - return function(params) { - //find the most recent task in the list of 'active' tasks - var scope = params.scope, - key, - newActiveTask, - activeList = []; - - for (key in scope.jobData.plays[scope.activePlay].tasks) { - if (scope.jobData.plays[scope.activePlay].tasks[key].reportedHosts > 0 || scope.jobData.plays[scope.activePlay].tasks[key].status === 'no-matching-hosts') { - activeList.push(key); - } - } - - if (activeList.length > 0) { - newActiveTask = scope.jobData.plays[scope.activePlay].tasks[activeList[activeList.length - 1]].id; - if (newActiveTask && scope.activeTask && newActiveTask !== scope.activeTask) { - if (scope.activeTask && scope.jobData.plays[scope.activePlay].tasks[scope.activeTask] !== undefined) { - scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].taskActiveClass = ''; - scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].hostResults = {}; - } - } - if (newActiveTask) { - scope.activeTask = newActiveTask; - scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].taskActiveClass = 'JobDetail-tableRow--selected'; - } - } - }; - }]) - - .factory('AddNewPlay', ['SetActivePlay', function(SetActivePlay) { - return function(params) { - var scope = params.scope, - event = params.event, - status, status_text; - - status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful'; - status_text = (event.failed) ? 'Failed' : (event.changed) ? 'Changed' : 'OK'; - - scope.jobData.plays[event.id] = { - id: event.id, - name: event.play, - created: event.created, - status: status, - status_text: status_text, - elapsed: '00:00:00', - hostCount: 0, - taskCount: 0, - fistTask: null, - unreachableCount: 0, - status_tip: "Event ID: " + event.id + "
Status: " + status_text, - tasks: {} - }; - - SetActivePlay({ scope: scope }); - }; - }]) - - .factory('AddNewTask', ['UpdatePlayStatus', 'SetActivePlay', 'SetActiveTask', function(UpdatePlayStatus, SetActivePlay, SetActiveTask) { - return function(params) { - var scope = params.scope, - event = params.event, - status, status_text; - - status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful'; - status_text = (event.failed) ? 'Failed' : (event.changed) ? 'Changed' : 'OK'; - - scope.jobData.plays[event.parent].tasks[event.id] = { - id: event.id, - play_id: event.parent, - name: (event.task) ? event.task : event.event_display, - status: status, - status_text: status_text, - status_tip: "Event ID: " + event.id + "
Status: " + status_text, - created: event.created, - modified: event.modified, - hostCount: (scope.jobData.plays[event.parent]) ? scope.jobData.plays[event.parent].hostCount : 0, - reportedHosts: 0, - successfulCount: 0, - failedCount: 0, - changedCount: 0, - skippedCount: 0, - unreachableCount: 0, - successfulStyle: { display: 'none'}, - failedStyle: { display: 'none' }, - changedStyle: { display: 'none' }, - skippedStyle: { display: 'none' }, - unreachableStyle: { display: 'none' }, - hostResults: {} - }; - - if (scope.jobData.plays[event.parent].firstTask === undefined || scope.jobData.plays[event.parent].firstTask === null) { - scope.jobData.plays[event.parent].firstTask = event.id; - } - scope.jobData.plays[event.parent].taskCount++; - - SetActivePlay({ scope: scope }); - - SetActiveTask({ scope: scope }); - - UpdatePlayStatus({ - scope: scope, - play_id: event.parent, - failed: event.failed, - changed: event.changed, - modified: event.modified - }); - }; - }]) - - .factory('UpdateJobStatus', ['GetElapsed', 'Empty', 'JobIsFinished', 'longDateFilter', function(GetElapsed, Empty, JobIsFinished, longDateFilter) { - return function(params) { - var scope = params.scope, - failed = params.failed, - modified = params.modified, - started = params.started, - finished = params.finished; - - if (failed && scope.job_status.status !== 'failed' && scope.job_status.status !== 'error' && - scope.job_status.status !== 'canceled') { - scope.job_status.status = 'failed'; - } - if (JobIsFinished(scope) && !Empty(modified)) { - scope.job_status.finished = longDateFilter(modified); - } - if (!Empty(started) && Empty(scope.job_status.started)) { - scope.job_status.started = longDateFilter(modified); - } - if (!Empty(scope.job_status.finished) && !Empty(scope.job_status.started)) { - scope.job_status.elapsed = GetElapsed({ - start: started, - end: finished - }); - } - }; - }]) - - // Update the status of a play - .factory('UpdatePlayStatus', ['GetElapsed', 'UpdateJobStatus', function(GetElapsed, UpdateJobStatus) { - return function(params) { - var scope = params.scope, - failed = params.failed, - changed = params.changed, - id = params.play_id, - modified = params.modified, - no_hosts = params.no_hosts, - play; - - if (scope.jobData.plays[id] !== undefined) { - play = scope.jobData.plays[id]; - if (failed) { - play.status = 'failed'; - play.status_text = 'Failed'; - } - else if (play.status !== 'changed' && play.status !== 'failed') { - // once the status becomes 'changed' or 'failed' don't modify it - if (no_hosts) { - play.status = 'no-matching-hosts'; - play.status_text = 'No matching hosts'; - } else { - play.status = (changed) ? 'changed' : (failed) ? 'failed' : 'successful'; - play.status_text = (changed) ? 'Changed' : (failed) ? 'Failed' : 'OK'; - } - } - play.taskCount = (play.taskCount > 0) ? play.taskCount : 1; // set to a minimum of 1 to force drawing - play.status_tip = "Event ID: " + play.id + "
Status: " + play.status_text; - play.finished = modified; - play.elapsed = GetElapsed({ - start: play.created, - end: modified - }); - //play.status_text = (status_text) ? status_text : play.status; - } - - UpdateJobStatus({ - scope: scope, - failed: null, - modified: modified - }); - }; - }]) - - .factory('UpdateTaskStatus', ['UpdatePlayStatus', 'GetElapsed', function(UpdatePlayStatus, GetElapsed) { - return function(params) { - var scope = params.scope, - failed = params.failed, - changed = params.changed, - id = params.task_id, - modified = params.modified, - no_hosts = params.no_hosts, - play, task; - - // find the task in our hierarchy - for (play in scope.jobData.plays) { - if (scope.jobData.plays[play].tasks[id]) { - task = scope.jobData.plays[play].tasks[id]; - } - } - - if (task) { - if (no_hosts){ - task.status = 'no-matching-hosts'; - task.status_text = 'No matching hosts'; - } - else if (failed) { - task.status = 'failed'; - task.status_text = 'Failed'; - } - else if (task.status !== 'changed' && task.status !== 'failed') { - // once the status becomes 'changed' or 'failed' don't modify it - task.status = (failed) ? 'failed' : (changed) ? 'changed' : 'successful'; - task.status_text = (failed) ? 'Failed' : (changed) ? 'Changed' : 'OK'; - } - task.status_tip = "Event ID: " + task.id + "
Status: " + task.status_text; - task.finished = params.modified; - task.elapsed = GetElapsed({ - start: task.created, - end: modified - }); - - UpdatePlayStatus({ - scope: scope, - failed: failed, - changed: changed, - play_id: task.play_id, - modified: modified, - no_hosts: no_hosts - }); - } - }; - }]) - - // Each time a runner event is received update host summary totals and the parent task - .factory('UpdateHostStatus', ['UpdateTaskStatus', 'AddHostResult', function(UpdateTaskStatus, AddHostResult) { - return function(params) { - var scope = params.scope, - status = params.status, // successful, changed, unreachable, failed, skipped - name = params.name, - event_id = params.id, - host_id = params.host_id, - task_id = params.task_id, - modified = params.modified, - created = params.created, - msg = params.message, - item = params.item, - counter = params.counter; - - if (scope.jobData.hostSummaries[host_id] !== undefined) { - scope.jobData.hostSummaries[host_id].ok += (status === 'successful') ? 1 : 0; - scope.jobData.hostSummaries[host_id].changed += (status === 'changed') ? 1 : 0; - scope.jobData.hostSummaries[host_id].unreachable += (status === 'unreachable') ? 1 : 0; - scope.jobData.hostSummaries[host_id].failed += (status === 'failed') ? 1 : 0; - if (status === 'failed' || status === 'unreachable') { - scope.jobData.hostSummaries[host_id].status = 'failed'; - } - } - else { - scope.jobData.hostSummaries[host_id] = { - id: host_id, - name: name, - ok: (status === 'successful') ? 1 : 0, - changed: (status === 'changed') ? 1 : 0, - unreachable: (status === 'unreachable') ? 1 : 0, - failed: (status === 'failed') ? 1 : 0, - status: (status === 'failed' || status === 'unreachable') ? 'failed' : 'successful' - }; - } - UpdateTaskStatus({ - scope: scope, - task_id: task_id, - failed: ((status === 'failed' || status === 'unreachable') ? true :false), - changed: ((status === 'changed') ? true : false), - modified: modified - }); - - AddHostResult({ - scope: scope, - task_id: task_id, - host_id: host_id, - event_id: event_id, - status: status, - name: name, - created: created, - counter: counter, - message: msg, - item: item - }); - }; - }]) - - // Add a new host result - .factory('AddHostResult', ['SetTaskStyles', 'SetActivePlay', 'SetActiveTask', function(SetTaskStyles, SetActivePlay, SetActiveTask) { - return function(params) { - var scope = params.scope, - task_id = params.task_id, - host_id = params.host_id, - event_id = params.event_id, - status = params.status, - created = params.created, - counter = params.counter, - name = params.name, - msg = params.message, - item = params.item, - status_text = '', - task, play, play_id; - - switch(status) { - case "successful": - status_text = 'OK'; - break; - case "changed": - status_text = "Changed"; - break; - case "failed": - status_text = "Failed"; - break; - case "unreachable": - status_text = "Unreachable"; - break; - case "skipped": - status_text = "Skipped"; - } - - if (typeof item === "object") { - item = JSON.stringify(item); - } - - for (play in scope.jobData.plays) { - for (task in scope.jobData.plays[play].tasks) { - if (parseInt(task,10) === parseInt(task_id,10)) { - play_id = parseInt(play,10); - } - } - } - - if (play_id) { - scope.jobData.plays[play_id].tasks[task_id].hostResults[event_id] = { - id: event_id, - status: status, - status_text: status_text, - host_id: host_id, - task_id: task_id, - name: name, - created: created, - counter: counter, - msg: msg, - item: item - }; - - // increment the unreachable count on the play - if (status === 'unreachable') { - scope.jobData.plays[play_id].unreachableCount++; - } - - // update the task status bar - task = scope.jobData.plays[play_id].tasks[task_id]; - - if (task_id === scope.jobData.plays[play_id].firstTask) { - scope.jobData.plays[play_id].hostCount++; - task.hostCount++; - } - - task.reportedHosts += 1; - task.failedCount += (status === 'failed') ? 1 : 0; - task.changedCount += (status === 'changed') ? 1 : 0; - task.successfulCount += (status === 'successful') ? 1 : 0; - task.skippedCount += (status === 'skipped') ? 1 : 0; - task.unreachableCount += (status === 'unreachable') ? 1 : 0; - - SetTaskStyles({ - task: task - }); - - SetActivePlay({ scope: scope }); - - SetActiveTask({ scope: scope }); - } - }; - }]) - - .factory('SetTaskStyles', [ function() { - return function(params) { - var task = params.task, - diff; - - task.missingCount = task.hostCount - (task.failedCount + task.changedCount + task.skippedCount + task.successfulCount + - task.unreachableCount); - if(task.missingCount<0){ - task.hostCount = (task.failedCount + task.changedCount + task.skippedCount + task.successfulCount + - task.unreachableCount); - } - task.missingPct = (task.hostCount > 0) ? Math.ceil((100 * (task.missingCount / task.hostCount))) : 0; - task.failedPct = (task.hostCount > 0) ? Math.ceil((100 * (task.failedCount / task.hostCount))) : 0; - task.changedPct = (task.hostCount > 0) ? Math.ceil((100 * (task.changedCount / task.hostCount))) : 0; - task.skippedPct = (task.hostCount > 0) ? Math.ceil((100 * (task.skippedCount / task.hostCount))) : 0; - task.successfulPct = (task.hostCount > 0) ? Math.ceil((100 * (task.successfulCount / task.hostCount))) : 0; - task.unreachablePct = (task.hostCount > 0) ? Math.ceil((100 * (task.unreachableCount / task.hostCount))) : 0; - - // cap % at 100 - task.missingPct = (task.missingPct > 100) ? 100 : task.missingPct; - task.failedPct = (task.failedPct > 100) ? 100 : task.failedPct; - task.changedPct = (task.changedPct > 100) ? 100 : task.changedPct; - task.skippedPct = (task.skippedPct > 100) ? 100 : task.skippedPct; - task.successfulPct = ( task.successfulPct > 100) ? 100 : task.successfulPct; - task.unreachablePct = (task.unreachablePct > 100) ? 100 : task.unreachablePct; - - diff = (task.failedPct + task.changedPct + task.skippedPct + task.successfulPct + task.unreachablePct + task.missingPct) - 100; - if (diff > 0) { - if (task.failedPct > diff) { - task.failedPct = task.failedPct - diff; - } - else if (task.changedPct > diff) { - task.changedPct = task.changedPct - diff; - } - else if (task.skippedPct > diff) { - task.skippedPct = task.skippedPct - diff; - } - else if (task.successfulPct > diff) { - task.successfulPct = task.successfulPct - diff; - } - else if (task.unreachablePct > diff) { - task.unreachablePct = task.unreachablePct - diff; - } - else if (task.missingPct > diff) { - task.missingPct = task.missingPct - diff; - } - } - task.successfulStyle = (task.successfulPct > 0) ? { 'display': 'inline-block' }: { 'display': 'none' }; - task.changedStyle = (task.changedPct > 0) ? { 'display': 'inline-block'} : { 'display': 'none' }; - task.skippedStyle = (task.skippedPct > 0) ? { 'display': 'inline-block' } : { 'display': 'none' }; - task.failedStyle = (task.failedPct > 0) ? { 'display': 'inline-block' } : { 'display': 'none' }; - task.unreachableStyle = (task.unreachablePct > 0) ? { 'display': 'inline-block' } : { 'display': 'none' }; - task.missingStyle = (task.missingPct > 0) ? { 'display': 'inline-block' } : { 'display': 'none' }; - }; - }]) - - .factory('LoadPlays', ['Rest', 'ProcessErrors', 'GetElapsed', 'SelectPlay', 'JobIsFinished', - function(Rest, ProcessErrors, GetElapsed, SelectPlay, JobIsFinished) { - return function(params) { - var scope = params.scope, - callback = params.callback, - url; - - scope.plays = []; - - scope.playsLoading = true; - Rest.setUrl(url); - Rest.get() - .success(function(data) { - scope.next_plays = data.next; - scope.plays = []; - data.results.forEach(function(event, idx) { - var status, status_text, start, end, elapsed; - - status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful'; - status_text = (event.failed) ? 'Failed' : (event.changed) ? 'Changed' : 'OK'; - start = event.started; - - if (idx < data.results.length - 1) { - // end date = starting date of the next event - end = data.results[idx + 1].started; - } - else if (JobIsFinished(scope)) { - // this is the last play and the job already finished - end = scope.job_status.finished; - } - if (end) { - elapsed = GetElapsed({ - start: start, - end: end - }); - } - else { - elapsed = '00:00:00'; - } - - scope.plays.push({ - id: event.id, - name: event.play, - created: start, - finished: end, - status: status, - status_text: status_text, - status_tip: "Event ID: " + event.id + "
Status: " + status_text, - elapsed: elapsed, - hostCount: 0, - fistTask: null, - playActiveClass: '', - unreachableCount: (event.unreachable_count) ? event.unreachable_count : 0, - }); - }); - - // set the active task - SelectPlay({ - scope: scope, - id: (scope.plays.length > 0) ? scope.plays[0].id : null, - callback: callback - }); - scope.playsLoading = false; - }) - .error(function(data) { - ProcessErrors(scope, data, status, null, { hdr: 'Error!', - msg: 'Call to ' + url + '. GET returned: ' + status }); - }); - }; - }]) - - // Call when the selected Play needs to change - .factory('SelectPlay', ['LoadTasks', function(LoadTasks) { - return function(params) { - var scope = params.scope, - id = params.id, - callback = params.callback; - - scope.selectedPlay = id; - scope.plays.forEach(function(play, idx) { - if (play.id === scope.selectedPlay) { - scope.plays[idx].playActiveClass = 'JobDetail-tableRow--selected'; - } - else { - scope.plays[idx].playActiveClass = ''; - } - }); - - LoadTasks({ - scope: scope, - callback: callback, - clear: true - }); - - }; - }]) - - .factory('LoadTasks', ['Rest', 'ProcessErrors', 'GetElapsed', 'SelectTask', 'SetTaskStyles', function(Rest, ProcessErrors, GetElapsed, SelectTask, SetTaskStyles) { - return function(params) { - var scope = params.scope, - callback = params.callback, - url, play; - - scope.tasks = []; - if (scope.selectedPlay) { - url = scope.job.url + 'job_tasks/?event_id=' + scope.selectedPlay; - - scope.plays.every(function(p, idx) { - if (p.id === scope.selectedPlay) { - play = scope.plays[idx]; - return false; - } - return true; - }); - - scope.tasksLoading = true; - - Rest.setUrl(url); - Rest.get() - .success(function(data) { - scope.next_tasks = data.next; - scope.tasks = []; - data.results.forEach(function(event, idx) { - var end, elapsed, status, status_text; - - if (play.firstTask === undefined || play.firstTask === null) { - play.firstTask = event.id; - play.hostCount = (event.host_count) ? event.host_count : 0; - } - - if (idx < data.results.length - 1) { - // end date = starting date of the next event - end = data.results[idx + 1].created; - } - else { - // no next event (task), get the end time of the play - scope.plays.every(function(play) { - if (play.id === scope.selectedPlay) { - end = play.finished; - return false; - } - return true; - }); - } - - if (end) { - elapsed = GetElapsed({ - start: event.created, - end: end - }); - } - else { - elapsed = '00:00:00'; - } - - status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful'; - status_text = (event.failed) ? 'Failed' : (event.changed) ? 'Changed' : 'OK'; - - scope.tasks.push({ - id: event.id, - play_id: scope.selectedPlay, - name: event.name, - status: status, - status_text: status_text, - status_tip: "Event ID: " + event.id + "
Status: " + status_text, - created: event.created, - modified: event.modified, - finished: end, - elapsed: elapsed, - hostCount: (event.host_count) ? event.host_count : 0, - reportedHosts: (event.reported_hosts) ? event.reported_hosts : 0, - successfulCount: (event.successful_count) ? event.successful_count : 0, - failedCount: (event.failed_count) ? event.failed_count : 0, - changedCount: (event.changed_count) ? event.changed_count : 0, - skippedCount: (event.skipped_count) ? event.skipped_count : 0, - unreachableCount: (event.unreachable_count) ? event.unreachable_count : 0, - taskActiveClass: '' - }); - - if (play.firstTask !== event.id) { - // this is not the first task - scope.tasks[scope.tasks.length - 1].hostCount = play.hostCount; - } - - SetTaskStyles({ - task: scope.tasks[scope.tasks.length - 1] - }); - }); - - // set the active task - SelectTask({ - scope: scope, - id: (scope.tasks.length > 0) ? scope.tasks[0].id : null, - callback: callback - }); - - scope.tasksLoading = false; - - }) - .error(function(data) { - ProcessErrors(scope, data, status, null, { hdr: 'Error!', - msg: 'Call to ' + url + '. GET returned: ' + status }); - }); - } - else { - SelectTask({ - scope: scope, - id: null, - callback: callback - }); - } - }; - }]) - - // Call when the selected task needs to change - .factory('SelectTask', ['JobDetailService', function(JobDetailService) { - return function(params) { - var scope = params.scope, - id = params.id; - - scope.selectedTask = id; - scope.tasks.forEach(function(task, idx) { - if (task.id === scope.selectedTask) { - scope.tasks[idx].taskActiveClass = 'JobDetail-tableRow--selected'; - } - else { - scope.tasks[idx].taskActiveClass = ''; - } - }); - if (scope.selectedTask !== null){ - params = { - parent: scope.selectedTask, - event__startswith: 'runner', - page_size: scope.hostResultsMaxRows, - order: 'host_name,counter', - }; - - JobDetailService.getRelatedJobEvents(scope.job.id, params).success(function(res){ - scope.hostResults = JobDetailService.processHostEvents(res.results); - scope.hostResultsLoading = false; - }); - } - else{ - scope.hostResults = []; - scope.hostResultsLoading = false; - } - }; - }]) - - .factory('DrawGraph', ['DonutChart', function(DonutChart) { - return function(params) { - var count = params.count, - graph_data = []; - // Ready the data - if (count.ok.length > 0) { - graph_data.push({ - label: 'OK', - value: count.ok.length, - color: '#5CB85C' - }); - } - if (count.changed.length > 0) { - graph_data.push({ - label: 'CHANGED', - value: count.changed.length, - color: '#FF9900' - }); - } - if (count.unreachable.length > 0) { - graph_data.push({ - label: 'UNREACHABLE', - value: count.unreachable.length, - color: '#FF0000' - }); - } - if (count.failures.length > 0) { - graph_data.push({ - label: 'FAILED', - value: count.failures.length, - color: '#D9534F' - }); - } - DonutChart({ - data: graph_data - }); - }; - }]) - - .factory('DonutChart', [function() { - return function(params) { - var dataset = params.data, - element = $("#graph-section"), - colors, total,job_detail_chart; - - colors = _.map(dataset, function(d){ - return d.color; - }); - total = d3.sum(dataset.map(function(d) { - return d.value; - })); - job_detail_chart = nv.models.pieChart() - .margin({bottom: 15}) - .x(function(d) { - return d.label +': '+ Math.floor((d.value/total)*100) + "%"; - }) - .y(function(d) { return d.value; }) - .showLabels(false) - .showLegend(true) - .growOnHover(false) - .labelThreshold(0.01) - .tooltipContent(function(x, y) { - return '

'+x+'

'+ '

' + Math.floor(y.replace(',','')) + ' HOSTS ' + '

'; - }) - .color(colors); - job_detail_chart.legend.rightAlign(false); - job_detail_chart.legend.margin({top: 5, right: 450, left:0, bottom: 0}); - d3.select(element.find('svg')[0]) - .datum(dataset) - .transition().duration(350) - .call(job_detail_chart) - .style({ - "font-family": 'Open Sans', - "font-style": "normal", - "font-weight":400, - "src": "url(/static/assets/OpenSans-Regular.ttf)", - "width": 600, - "height": 300, - "color": '#848992' - }); - d3.select(element.find(".nv-noData")[0]) - .style({ - "text-anchor": 'start' - }); - return job_detail_chart; - }; - }]) - - - .factory('DrawPlays', [function() { - return function(params) { - var scope = params.scope, - idx = 0, - result = [], - newKeys = [], - //plays = JSON.parse(JSON.stringify(scope.jobData.plays)), - plays = scope.jobData.plays, - filteredListX = [], - filteredListB = [], - key, - keys; - - function listSort(a,b) { - if (parseInt(a,10) < parseInt(b,10)) { - return -1; - } - if (parseInt(a,10) > parseInt(b,10)) { - return 1; - } - return 0; - } - - // Only draw plays that are in the 'active' list - for (key in plays) { - if (plays[key].taskCount > 0) { - filteredListX[key] = plays[key]; - } - } - - keys = Object.keys(filteredListB); - keys.sort(function(a,b) { return listSort(a,b); }).reverse(); - for (idx=0; idx < scope.playsMaxRows && idx < keys.length; idx++) { - newKeys.push(keys[idx]); - } - newKeys.sort(function(a,b) { return listSort(a,b); }); - idx = 0; - while (idx < newKeys.length) { - result.push(filteredListB[newKeys[idx]]); - idx++; - } - setTimeout( function() { - scope.$apply( function() { - scope.plays = result; - scope.selectedPlay = scope.activePlay; - if (scope.liveEventProcessing) { - $('#plays-table-detail').scrollTop($('#plays-table-detail').prop("scrollHeight")); - } - }); - }); - }; - }]) - - .factory('DrawTasks', [ function() { - return function(params) { - var scope = params.scope, - result = [], - filteredListX = [], - filteredListB = [], - idx, key, keys, newKeys, tasks, t; - - function listSort(a,b) { - if (parseInt(a,10) < parseInt(b,10)) { - return -1; - } - if (parseInt(a,10) > parseInt(b,10)) { - return 1; - } - return 0; - } - - if (scope.activePlay && scope.jobData.plays[scope.activePlay]) { - - //tasks = JSON.parse(JSON.stringify(scope.jobData.plays[scope.activePlay].tasks)); - tasks = scope.jobData.plays[scope.activePlay].tasks; - - // Only draw tasks that are in the 'active' list - for (key in tasks) { - t = tasks[key]; - if (t.reportedHosts > 0 || t.hostCount > 0 || t.successfulCount >0 || t.failedCount > 0 || - t.changedCount > 0 || t.skippedCount > 0 || t.unreachableCount > 0) { - filteredListX[key] = tasks[key]; - } - } - - keys = Object.keys(filteredListB); - keys.sort(function(a,b) { return listSort(a,b); }).reverse(); - newKeys = []; - for (idx=0; result.length < scope.tasksMaxRows && idx < keys.length; idx++) { - newKeys.push(keys[idx]); - } - newKeys.sort(function(a,b) { return listSort(a,b); }); - idx = 0; - while (idx < newKeys.length) { - result.push(filteredListB[newKeys[idx]]); - idx++; - } - } - - setTimeout( function() { - scope.$apply( function() { - scope.tasks = result; - scope.selectedTask = scope.activeTask; - if (scope.liveEventProcessing) { - $('#tasks-table-detail').scrollTop($('#tasks-table-detail').prop("scrollHeight")); - } - }); - }); - - }; - }]) - - .factory('DrawHostResults', [ function() { - return function(params) { - var scope = params.scope, - result = [], - filteredListB = [], - idx = 0, - hostResults, - keys; - - if (scope.activePlay && scope.activeTask && scope.jobData.plays[scope.activePlay] && - scope.jobData.plays[scope.activePlay].tasks[scope.activeTask]) { - - hostResults = scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].hostResults; - - keys = Object.keys(filteredListB); - keys.sort(function compare(a, b) { - if (filteredListB[a].name === filteredListB[b].name) { - if (filteredListB[a].counter < filteredListB[b].counter) { - return -1; - } - if (filteredListB[a].counter >filteredListB[b].counter) { - return 1; - } - } else { - if (filteredListB[a].name < filteredListB[b].name) { - return -1; - } - if (filteredListB[a].name > filteredListB[b].name) { - return 1; - } - } - // a must be equal to b - return 0; - }); - while (idx < keys.length && result.length < scope.hostResultsMaxRows) { - result.push(filteredListB[keys[idx]]); - idx++; - } - } - - setTimeout( function() { - scope.$apply( function() { - scope.hostResults = result; - if (scope.liveEventProcessing) { - $('#hosts-table-detail').scrollTop($('#hosts-table-detail').prop("scrollHeight")); - } - }); - }); - - }; - }]) - - .factory('UpdateDOM', ['DrawPlays', 'DrawTasks', 'DrawHostResults', - function(DrawPlays, DrawTasks, DrawHostResults) { - return function(params) { - var scope = params.scope; - if (!scope.pauseLiveEvents) { - DrawPlays({ scope: scope }); - DrawTasks({ scope: scope }); - DrawHostResults({ scope: scope }); - } - - setTimeout(function() { - scope.playsLoading = false; - scope.tasksLoading = false; - scope.hostResultsLoading = false; - },100); - }; - }]); diff --git a/awx/ui/client/src/job-detail/host-events/host-events.block.less b/awx/ui/client/src/job-detail/host-events/host-events.block.less deleted file mode 100644 index df52944cf0..0000000000 --- a/awx/ui/client/src/job-detail/host-events/host-events.block.less +++ /dev/null @@ -1,93 +0,0 @@ -@import "./client/src/shared/branding/colors.less"; -@import "./client/src/shared/branding/colors.default.less"; - -.HostEvents .CodeMirror{ - border: none; -} -.HostEvents .modal-footer{ - border: 0; - margin-top: 0px; - padding: 0px 20px 20px 20px; -} -button.HostEvents-close{ - width: 70px; - color: #FFFFFF!important; - text-transform: uppercase; - padding-left: 15px; - padding-right: 15px; - background-color: @default-link; - border-color: @default-link; - &:hover{ - background-color: @default-link-hov; - border-color: @default-link-hov; - } -} -.HostEvents-status--ok{ - color: @green; -} -.HostEvents-status--unreachable{ - color: @unreachable; -} -.HostEvents-status--changed{ - color: @changed; -} -.HostEvents-status--failed{ - color: @default-err; -} -.HostEvents-status--skipped{ - color: @skipped; -} - -.HostEvents-filter--form{ - padding-top: 15px; - padding-bottom: 15px; - float: right; - display: inline-block; -} -.HostEvents .modal-body{ - padding: 20px; -} -.HostEvents .select2-container{ - text-transform: capitalize; - max-width: 220px; - float: right; -} -.HostEvents-form--container{ - padding-top: 15px; - padding-bottom: 15px; -} -.HostEvents-title{ - text-transform: uppercase; - color: @default-interface-txt; - font-weight: 600; -} -.HostEvents-status i { - padding-right: 10px; -} -.HostEvents-table--header { - height: 30px; - font-size: 14px; - font-weight: normal; - text-transform: uppercase; - color: @default-interface-txt; - background-color: @default-list-header-bg; - padding-left: 15px; - padding-right: 15px; - border-bottom-width: 0px; -} -.HostEvents-table--header:first-of-type{ - border-top-left-radius: 5px; -} -.HostEvents-table--header:last-of-type{ - border-top-right-radius: 5px; -} -.HostEvents-table--row{ - color: @default-data-txt; - border: 0 !important; -} -.HostEvents-table--row:nth-child(odd){ - background: @default-tertiary-bg; -} -.HostEvents-table--cell{ - border: 0 !important; -} diff --git a/awx/ui/client/src/job-detail/host-events/host-events.controller.js b/awx/ui/client/src/job-detail/host-events/host-events.controller.js deleted file mode 100644 index 5664c89877..0000000000 --- a/awx/ui/client/src/job-detail/host-events/host-events.controller.js +++ /dev/null @@ -1,48 +0,0 @@ -/************************************************* - * Copyright (c) 2016 Ansible, Inc. - * - * All Rights Reserved - *************************************************/ - - export default - ['$stateParams', '$scope', '$rootScope', '$state', 'Wait', - 'JobDetailService', 'CreateSelect2', 'hosts', - function($stateParams, $scope, $rootScope, $state, Wait, - JobDetailService, CreateSelect2, hosts){ - - // pagination not implemented yet, but it'll depend on this - $scope.page_size = $stateParams.page_size; - - $scope.processEventStatus = JobDetailService.processEventStatus; - $scope.activeFilter = $stateParams.filter || null; - - $scope.filters = ['all', 'changed', 'failed', 'ok', 'unreachable', 'skipped']; - - // watch select2 for changes - $('.HostEvents-select').on("select2:select", function () { - $scope.activeFilter = $('.HostEvents-select').val(); - }); - - var init = function(){ - $scope.hostName = $stateParams.hostName; - // create filter dropdown - CreateSelect2({ - element: '.HostEvents-select', - multiple: false - }); - // process the filter if one was passed - if ($stateParams.filter){ - $scope.activeFilter = $stateParams.filter; - - $('#HostEvents').modal('show'); - } - else{ - $scope.results = hosts.data.results; - $('#HostEvents').modal('show'); - } - }; - - - init(); - - }]; diff --git a/awx/ui/client/src/job-detail/host-events/host-events.partial.html b/awx/ui/client/src/job-detail/host-events/host-events.partial.html deleted file mode 100644 index 00bacf066c..0000000000 --- a/awx/ui/client/src/job-detail/host-events/host-events.partial.html +++ /dev/null @@ -1,52 +0,0 @@ - diff --git a/awx/ui/client/src/job-detail/host-summary/host-summary.controller.js b/awx/ui/client/src/job-detail/host-summary/host-summary.controller.js deleted file mode 100644 index cd5a241622..0000000000 --- a/awx/ui/client/src/job-detail/host-summary/host-summary.controller.js +++ /dev/null @@ -1,131 +0,0 @@ -/************************************************* - * Copyright (c) 2016 Ansible, Inc. - * - * All Rights Reserved - *************************************************/ - - export default - ['$scope', '$rootScope', '$stateParams', 'Wait', 'JobDetailService', 'DrawGraph', function($scope, $rootScope, $stateParams, Wait, JobDetailService, DrawGraph){ - - var page_size = 200; - $scope.loading = $scope.hosts.length > 0 ? false : true; - $scope.filter = 'all'; - - var buildGraph = function(hosts){ - // status waterfall: unreachable > failed > changed > ok > skipped - var count; - count = { - ok : _.filter(hosts, function(o){ - return o.failures === 0 && o.changed === 0 && o.ok > 0; - }), - skipped : _.filter(hosts, function(o){ - return o.skipped > 0; - }), - unreachable : _.filter(hosts, function(o){ - return o.dark > 0; - }), - failures : _.filter(hosts, function(o){ - return o.failed === true; - }), - changed : _.filter(hosts, function(o){ - return o.changed > 0; - }) - }; - return count; - }; - var init = function(){ - Wait('start'); - JobDetailService.getJobHostSummaries($stateParams.id, {page_size: page_size, order_by: 'host_name'}) - .success(function(res){ - $scope.hosts = res.results; - $scope.next = res.next; - $scope.count = buildGraph(res.results); - Wait('stop'); - DrawGraph({count: $scope.count, resize:true}); - }); - JobDetailService.getJob({id: $stateParams.id}) - .success(function(res){ - $scope.status = res.results[0].status; - }); - }; - if ($rootScope.removeJobSummaryComplete) { - $rootScope.removeJobSummaryComplete(); - } - // emitted by the API in the same function used to persist host summary data - // JobEvent.update_host_summary_from_stats() from /awx/main.models.jobs.py - $scope.$on('ws-jobs-summary', function(e, data) { - // discard socket msgs we don't care about in this context - if (parseInt($stateParams.id) === data.unified_job_id){ - init(); - } - }); - - $scope.$on('ws-jobs', function(e, data) { - if (parseInt($stateParams.id) === data.unified_job_id){ - $scope.status = data.status; - } - }); - - - $scope.buildTooltip = function(n, status){ - var grammar = function(n, status){ - var dict = { - 0: 'No host events were ', - 1: ' host event was ', - 2: ' host events were ' - }; - if (n >= 2){ - return n + dict[2] + status; - } - else{ - return n !== 0 ? n + dict[n] + status : dict[n] + status; - } - }; - return grammar(n, status); - }; - $scope.getNextPage = function(){ - if ($scope.next){ - JobDetailService.getNextPage($scope.next).success(function(res){ - res.results.forEach(function(key, index){ - $scope.hosts.push(res.results[index]); - }); - $scope.hosts.push(res.results); - $scope.next = res.next; - }); - } - }; - - $scope.setFilter = function(filter){ - $scope.filter = filter; - var getAll = function(){ - Wait('start'); - JobDetailService.getJobHostSummaries($stateParams.id, { - page_size: page_size, - order_by: 'host_name' - }).success(function(res){ - Wait('stop'); - $scope.hosts = res.results; - $scope.next = res.next; - }); - }; - var getFailed = function(){ - Wait('start'); - JobDetailService.getJobHostSummaries($stateParams.id, { - page_size: page_size, - failed: true, - order_by: 'host_name' - }).success(function(res){ - Wait('stop'); - $scope.hosts = res.results; - $scope.next = res.next; - }); - }; - $scope.get = filter === 'all' ? getAll() : getFailed(); - }; - - init(); - // calling the init routine twice will size the d3 chart correctly - no idea why - // instantiating the graph inside a setTimeout() SHOULD have the same effect, but it doesn't - // instantiating the graph further down the promise chain e.g. .then() or .finally() also does not work - init(); - }]; diff --git a/awx/ui/client/src/job-detail/job-detail.controller.js b/awx/ui/client/src/job-detail/job-detail.controller.js deleted file mode 100644 index c3479e397b..0000000000 --- a/awx/ui/client/src/job-detail/job-detail.controller.js +++ /dev/null @@ -1,1027 +0,0 @@ -/************************************************* - * Copyright (c) 2016 Ansible, Inc. - * - * All Rights Reserved - *************************************************/ - -/** - * @ngdoc function - * @name controllers.function:JobDetail - * @description This controller's for the Job Detail Page -*/ - -export default - [ '$location', '$rootScope', '$filter', '$scope', '$compile', '$state', '$stateParams', '$log', 'ClearScope', - 'GetBasePath', 'Wait', 'ProcessErrors', 'SelectPlay', 'SelectTask', 'GetElapsed', 'JobIsFinished', - 'SetTaskStyles', 'DigestEvent', 'UpdateDOM', 'DeleteJob', 'RelaunchPlaybook', 'LoadPlays', 'LoadTasks', - 'ParseVariableString', 'GetChoices', 'fieldChoices', 'fieldLabels', 'EditSchedule', - 'ParseTypeChange', 'JobDetailService', - function( - $location, $rootScope, $filter, $scope, $compile, $state, $stateParams, $log, ClearScope, - GetBasePath, Wait, ProcessErrors, SelectPlay, SelectTask, GetElapsed, JobIsFinished, - SetTaskStyles, DigestEvent, UpdateDOM, DeleteJob, RelaunchPlaybook, LoadPlays, LoadTasks, - ParseVariableString, GetChoices, fieldChoices, fieldLabels, EditSchedule, - ParseTypeChange, JobDetailService - ) { - ClearScope(); - - var job_id = $stateParams.id, - scope = $scope, - api_complete = false, - refresh_count = 0, - lastEventId = 0, - verbosity_options, - job_type_options; - - scope.plays = []; - scope.parseType = 'yaml'; - scope.previousTaskFailed = false; - $scope.stdoutFullScreen = false; - - scope.$watch('job_status', function(job_status) { - if (job_status && job_status.explanation && job_status.explanation.split(":")[0] === "Previous Task Failed") { - scope.previousTaskFailed = true; - var taskObj = JSON.parse(job_status.explanation.substring(job_status.explanation.split(":")[0].length + 1)); - // return a promise from the options request with the permission type choices (including adhoc) as a param - var fieldChoice = fieldChoices({ - scope: $scope, - url: 'api/v1/unified_jobs/', - field: 'type' - }); - - // manipulate the choices from the options request to be set on - // scope and be usable by the list form - fieldChoice.then(function (choices) { - choices = - fieldLabels({ - choices: choices - }); - scope.explanation_fail_type = choices[taskObj.job_type]; - scope.explanation_fail_name = taskObj.job_name; - scope.explanation_fail_id = taskObj.job_id; - scope.task_detail = scope.explanation_fail_type + " failed for " + scope.explanation_fail_name + " with ID " + scope.explanation_fail_id + "."; - }); - } else { - scope.previousTaskFailed = false; - } - }, true); - - scope.$watch('plays', function(plays) { - for (var play in plays) { - if (plays[play].elapsed) { - plays[play].finishedTip = "Play completed at " + $filter("longDate")(plays[play].finished) + "."; - } else { - plays[play].finishedTip = "Play not completed."; - } - } - }); - scope.hosts = []; - scope.tasks = []; - scope.$watch('tasks', function(tasks) { - for (var task in tasks) { - if (tasks[task].elapsed) { - tasks[task].finishedTip = "Task completed at " + $filter("longDate")(tasks[task].finished) + "."; - } else { - tasks[task].finishedTip = "Task not completed."; - } - if (tasks[task].successfulCount) { - tasks[task].successfulCountTip = tasks[task].successfulCount; - tasks[task].successfulCountTip += (tasks[task].successfulCount === 1) ? " host event was" : " host events were"; - tasks[task].successfulCountTip += " ok."; - } else { - tasks[task].successfulCountTip = "No host events were ok."; - } - if (tasks[task].changedCount) { - tasks[task].changedCountTip = tasks[task].changedCount; - tasks[task].changedCountTip += (tasks[task].changedCount === 1) ? " host event" : " host events"; - tasks[task].changedCountTip += " changed."; - } else { - tasks[task].changedCountTip = "No host events changed."; - } - if (tasks[task].skippedCount) { - tasks[task].skippedCountTip = tasks[task].skippedCount; - tasks[task].skippedCountTip += (tasks[task].skippedCount === 1) ? " host event was" : " hosts events were"; - tasks[task].skippedCountTip += " skipped."; - } else { - tasks[task].skippedCountTip = "No host events were skipped."; - } - if (tasks[task].failedCount) { - tasks[task].failedCountTip = tasks[task].failedCount; - tasks[task].failedCountTip += (tasks[task].failedCount === 1) ? " host event" : " host events"; - tasks[task].failedCountTip += " failed."; - } else { - tasks[task].failedCountTip = "No host events failed."; - } - if (tasks[task].unreachableCount) { - tasks[task].unreachableCountTip = tasks[task].unreachableCount; - tasks[task].unreachableCountTip += (tasks[task].unreachableCount === 1) ? " host event was" : " hosts events were"; - tasks[task].unreachableCountTip += " unreachable."; - } else { - tasks[task].unreachableCountTip = "No host events were unreachable."; - } - if (tasks[task].missingCount) { - tasks[task].missingCountTip = tasks[task].missingCount; - tasks[task].missingCountTip += (tasks[task].missingCount === 1) ? " host event was" : " host events were"; - tasks[task].missingCountTip += " missing."; - } else { - tasks[task].missingCountTip = "No host events were missing."; - } - } - }); - scope.hostResults = []; - - scope.hostResultsMaxRows = 200; - scope.tasksMaxRows = 200; - scope.playsMaxRows = 200; - - // Set the following to true when 'Loading...' message desired - scope.playsLoading = true; - scope.tasksLoading = true; - scope.hostResultsLoading = true; - - // Turn on the 'Waiting...' message until events begin arriving - scope.waiting = true; - - scope.liveEventProcessing = true; // true while job is active and live events are arriving - scope.pauseLiveEvents = false; // control play/pause state of event processing - - scope.job_status = {}; - scope.job_id = job_id; - scope.auto_scroll = false; - - scope.haltEventQueue = false; - scope.processing = false; - scope.lessStatus = false; - scope.lessDetail = false; - // pops the event summary panel open if we're in the host summary child state - //scope.lessEvents = ($state.current.name === 'jobDetail.host-summary' || $state.current.name === 'jobDetail.host-events') ? false : true; - if ($state.current.name === 'jobDetail.host-summary' ){ - scope.lessEvents = false; - } - else{ - scope.lessEvents = true; - } - scope.jobData = {}; - scope.jobData.hostSummaries = {}; - - verbosity_options = [ - { value: 0, label: 'Default' }, - { value: 1, label: 'Verbose' }, - { value: 3, label: 'Debug' } - ]; - - job_type_options = [ - { value: 'run', label: 'Run' }, - { value: 'check', label: 'Check' } - ]; - - GetChoices({ - scope: scope, - url: GetBasePath('unified_jobs'), - field: 'status', - variable: 'status_choices', - }); - - scope.eventsHelpText = "

Successful

\n" + - "

Changed

\n" + - "

Unreachable

\n" + - "

Failed

\n"; - - scope.$on(`ws-job_events-${job_id}`, function(e, data) { - // update elapsed time on each event received - scope.job_status.elapsed = GetElapsed({ - start: scope.job.created, - end: Date.now() - }); - if (api_complete && data.id > lastEventId) { - scope.waiting = false; - data.event = data.event_name; - DigestEvent({ scope: scope, event: data }); - } - UpdateDOM({ scope: scope }); - }); - - scope.$on(`ws-jobs`, function(e, data) { - // if we receive a status change event for the current job indicating the job - // is finished, stop event queue processing and reload - if (parseInt(data.unified_job_id, 10) === parseInt(job_id,10)) { - if (data.status === 'failed' || data.status === 'canceled' || - data.status === 'error' || data.status === 'successful' || data.status === 'running') { - $scope.liveEventProcessing = false; - if (!scope.pauseLiveEvents) { - $scope.$emit('LoadJob'); //this is what is used for the refresh - } - } - } - }); - - scope.$on('ws-jobs-summary', function() { - // the job host summary should now be available from the API - $log.debug('Trigging reload of job_host_summaries'); - scope.$emit('InitialLoadComplete'); - }); - - if (scope.removeInitialLoadComplete) { - scope.removeInitialLoadComplete(); - } - scope.removeInitialLoadComplete = scope.$on('InitialLoadComplete', function() { - Wait('stop'); - - if (JobIsFinished(scope)) { - scope.liveEventProcessing = false; // signal that event processing is over and endless scroll - scope.pauseLiveEvents = false; // should be enabled - var params = { - event: 'playbook_on_stats' - }; - JobDetailService.getRelatedJobEvents(scope.job.id, params) - .success(function() { - UpdateDOM({ scope: scope }); - }) - .error(function(data, status) { - ProcessErrors(scope, data, status, null, { hdr: 'Error!', - msg: 'Call failed. GET returned: ' + status }); - }); - $log.debug('Job completed!'); - $log.debug(scope.jobData); - } - else { - api_complete = true; //trigger events to start processing - UpdateDOM({ scope: scope}); - } - }); - - if (scope.removeLoadHosts) { - scope.removeLoadHosts(); - } - scope.removeLoadHosts = scope.$on('LoadHosts', function() { - if (scope.activeTask) { - - var play = scope.jobData.plays[scope.activePlay], - task; - if(play){ - task = play.tasks[scope.activeTask]; - } - if (play && task) { - var params = { - parent: task.id, - event__startswith: 'runner', - page_size: scope.hostResultsMaxRows - }; - JobDetailService.getRelatedJobEvents(scope.job.id, params) - .success(function(data) { - if (data.results.length > 0) { - lastEventId = data.results[0].id; - } - scope.next_host_results = data.next; - task.hostResults = JobDetailService.processHostEvents(data.results); - scope.$emit('InitialLoadComplete'); - }); - } else { - scope.$emit('InitialLoadComplete'); - } - } else { - scope.$emit('InitialLoadComplete'); - } - }); - - if (scope.removeLoadTasks) { - scope.removeLoadTasks(); - } - scope.removeLoadTasks = scope.$on('LoadTasks', function() { - if (scope.activePlay) { - var play = scope.jobData.plays[scope.activePlay]; - - if (play) { - var params = { - event_id: play.id, - page_size: scope.tasksMaxRows, - order: 'id' - }; - JobDetailService.getJobTasks(scope.job.id, params) - .success(function(data) { - scope.next_tasks = data.next; - if (data.results.length > 0) { - lastEventId = data.results[data.results.length - 1].id; - if (scope.liveEventProcessing) { - scope.activeTask = data.results[data.results.length - 1].id; - } - else { - scope.activeTask = data.results[0].id; - } - scope.selectedTask = scope.activeTask; - } - data.results.forEach(function(event, idx) { - var end, elapsed, status, status_text; - - if (play.firstTask === undefined || play.firstTask === null) { - play.firstTask = event.id; - play.hostCount = (event.host_count) ? event.host_count : 0; - } - - if (idx < data.results.length - 1) { - // end date = starting date of the next event - end = data.results[idx + 1].created; - } - else { - // no next event (task), get the end time of the play - if(scope.jobData.plays[scope.activePlay]){ - end = scope.jobData.plays[scope.activePlay].finished; - } - } - - if (end) { - elapsed = GetElapsed({ - start: event.created, - end: end - }); - } - else { - elapsed = '00:00:00'; - } - - status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful'; - status_text = (event.failed) ? 'Failed' : (event.changed) ? 'Changed' : 'OK'; - - play.tasks[event.id] = { - id: event.id, - play_id: scope.activePlay, - name: event.name, - status: status, - status_text: status_text, - status_tip: "Event ID: " + event.id + "
Status: " + status_text, - created: event.created, - modified: event.modified, - finished: end, - elapsed: elapsed, - hostCount: (event.host_count) ? event.host_count : 0, - reportedHosts: (event.reported_hosts) ? event.reported_hosts : 0, - successfulCount: (event.successful_count) ? event.successful_count : 0, - failedCount: (event.failed_count) ? event.failed_count : 0, - changedCount: (event.changed_count) ? event.changed_count : 0, - skippedCount: (event.skipped_count) ? event.skipped_count : 0, - unreachableCount: (event.unreachable_count) ? event.unreachable_count : 0, - taskActiveClass: '', - hostResults: {} - }; - if (play.firstTask !== event.id) { - // this is not the first task - play.tasks[event.id].hostCount = play.tasks[play.firstTask].hostCount; - } - if (play.tasks[event.id].reportedHosts === 0 && play.tasks[event.id].successfulCount === 0 && - play.tasks[event.id].failedCount === 0 && play.tasks[event.id].changedCount === 0 && - play.tasks[event.id].skippedCount === 0 && play.tasks[event.id].unreachableCount === 0) { - play.tasks[event.id].status = 'no-matching-hosts'; - play.tasks[event.id].status_text = 'No matching hosts'; - play.tasks[event.id].status_tip = "Event ID: " + event.id + "
Status: No matching hosts"; - } - play.taskCount++; - SetTaskStyles({ - task: play.tasks[event.id] - }); - }); - if (scope.activeTask && scope.jobData.plays[scope.activePlay] && scope.jobData.plays[scope.activePlay].tasks[scope.activeTask]) { - scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].taskActiveClass = 'JobDetail-tableRow--selected'; - } - scope.$emit('LoadHosts'); - }) - .error(function(data) { - ProcessErrors(scope, data, status, null, { hdr: 'Error!', - msg: 'Call failed. GET returned: ' + status }); - }); - } else { - scope.$emit('InitialLoadComplete'); - } - } else { - scope.$emit('InitialLoadComplete'); - } - }); - - if (scope.removeLoadPlays) { - scope.removeLoadPlays(); - } - scope.removeLoadPlays = scope.$on('LoadPlays', function(e, events_url) { - scope.jobData.plays = {}; - var params = { - order_by: 'id' - }; - - JobDetailService.getJobPlays(scope.job.id, params) - .success( function(data) { - scope.next_plays = data.next; - if (data.results.length > 0) { - lastEventId = data.results[data.results.length - 1].id; - if (scope.liveEventProcessing) { - scope.activePlay = data.results[data.results.length - 1].id; - } - else { - scope.activePlay = data.results[0].id; - } - scope.selectedPlay = scope.activePlay; - } else { - // if we are here, there are no plays and the job has failed, let the user know they may want to consult stdout - if ( (scope.job_status.status === 'failed' || scope.job_status.status === 'error') && - (!scope.job_status.explanation)) { - scope.job_status.explanation = "See standard out for more details"; - } - } - data.results.forEach(function(event, idx) { - var status, status_text, start, end, elapsed, ok, changed, failed, skipped; - - status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful'; - status_text = (event.failed) ? 'Failed' : (event.changed) ? 'Changed' : 'OK'; - start = event.started; - - if (idx < data.results.length - 1) { - // end date = starting date of the next event - end = data.results[idx + 1].started; - } - else if (JobIsFinished(scope)) { - // this is the last play and the job already finished - end = scope.job_status.finished; - } - if (end) { - elapsed = GetElapsed({ - start: start, - end: end - }); - } - else { - elapsed = '00:00:00'; - } - - scope.jobData.plays[event.id] = { - id: event.id, - name: event.play, - created: start, - finished: end, - status: status, - status_text: status_text, - status_tip: "Event ID: " + event.id + "
Status: " + status_text, - elapsed: elapsed, - hostCount: 0, - fistTask: null, - taskCount: 0, - playActiveClass: '', - unreachableCount: (event.unreachable_count) ? event.unreachable_count : 0, - tasks: {} - }; - - ok = (event.ok_count) ? event.ok_count : 0; - changed = (event.changed_count) ? event.changed_count : 0; - failed = (event.failed_count) ? event.failed_count : 0; - skipped = (event.skipped_count) ? event.skipped_count : 0; - - scope.jobData.plays[event.id].hostCount = ok + changed + failed + skipped; - - if (scope.jobData.plays[event.id].hostCount > 0 || event.unreachable_count > 0 || scope.job_status.status === 'successful' || - scope.job_status.status === 'failed' || scope.job_status.status === 'error' || scope.job_status.status === 'canceled') { - // force the play to be on the 'active' list - scope.jobData.plays[event.id].taskCount = 1; - } - - if (scope.jobData.plays[event.id].hostCount === 0 && event.unreachable_count === 0) { - scope.jobData.plays[event.id].status = 'no-matching-hosts'; - scope.jobData.plays[event.id].status_text = 'No matching hosts'; - scope.jobData.plays[event.id].status_tip = "Event ID: " + event.id + "
Status: No matching hosts"; - } - }); - if (scope.activePlay && scope.jobData.plays[scope.activePlay]) { - scope.jobData.plays[scope.activePlay].playActiveClass = 'JobDetail-tableRow--selected'; - } - scope.$emit('LoadTasks', events_url); - }); - }); - - - if (scope.removeLoadJob) { - scope.removeLoadJob(); - } - scope.removeLoadJobRow = scope.$on('LoadJob', function() { - Wait('start'); - scope.job_status = {}; - - scope.playsLoading = true; - scope.tasksLoading = true; - scope.hostResultsLoading = true; - - // Load the job record - JobDetailService.getJob({id: job_id}) - .success(function(res) { - var i, - data = res.results[0]; - scope.job = data; - scope.job_template_name = data.name; - scope.project_name = (data.summary_fields.project) ? data.summary_fields.project.name : ''; - scope.inventory_name = (data.summary_fields.inventory) ? data.summary_fields.inventory.name : ''; - scope.job_template_url = '/#/templates/' + data.unified_job_template; - scope.inventory_url = (scope.inventory_name && data.inventory) ? '/#/inventories/' + data.inventory : ''; - scope.project_url = (scope.project_name && data.project) ? '/#/projects/' + data.project : ''; - scope.credential_url = (data.credential) ? '/#/credentials/' + data.credential : ''; - scope.cloud_credential_url = (data.cloud_credential) ? '/#/credentials/' + data.cloud_credential : ''; - scope.playbook = data.playbook; - scope.credential = data.credential; - scope.cloud_credential = data.cloud_credential; - scope.forks = data.forks; - scope.limit = data.limit; - scope.verbosity = data.verbosity; - scope.job_tags = data.job_tags; - scope.variables = ParseVariableString(data.extra_vars); - - // If we get created_by back from the server then use it. This means that the job was kicked - // off by a user and not a schedule AND that the user still exists in the system. - if(data.summary_fields.created_by) { - scope.users_url = '/#/users/' + data.summary_fields.created_by.id; - scope.created_by = data.summary_fields.created_by.username; - } - else { - if(data.summary_fields.schedule) { - // Build the Launched By link to point to the schedule that kicked it off - scope.scheduled_by = (data.summary_fields.schedule.name) ? data.summary_fields.schedule.name.toString() : ''; - } - // If there is no schedule or created_by then we can assume that the job was - // created by a deleted user - } - - if (data.summary_fields.credential) { - scope.credential_name = data.summary_fields.credential.name; - scope.credential_url = data.related.credential - .replace('api/v1', '#'); - } else { - scope.credential_name = ""; - } - - if (data.summary_fields.cloud_credential) { - scope.cloud_credential_name = data.summary_fields.cloud_credential.name; - scope.cloud_credential_url = data.related.cloud_credential - .replace('api/v1', '#'); - } else { - scope.cloud_credential_name = ""; - } - - if (data.summary_fields.network_credential) { - scope.network_credential_name = data.summary_fields.network_credential.name; - scope.network_credential_url = data.related.network_credential - .replace('api/v1', '#'); - } else { - scope.network_credential_name = ""; - } - - for (i=0; i < verbosity_options.length; i++) { - if (verbosity_options[i].value === data.verbosity) { - scope.verbosity = verbosity_options[i].label; - } - } - - for (i=0; i < job_type_options.length; i++) { - if (job_type_options[i].value === data.job_type) { - scope.job_type = job_type_options[i].label; - } - } - - // In the case the job is already completed, or an error already happened, - // populate scope.job_status info - scope.job_status.status = (data.status === 'waiting' || data.status === 'new') ? 'pending' : data.status; - scope.job_status.started = data.started; - scope.job_status.status_class = ((data.status === 'error' || data.status === 'failed') && data.job_explanation) ? "alert alert-danger" : ""; - scope.job_status.explanation = data.job_explanation; - if(data.result_traceback) { - scope.job_status.traceback = data.result_traceback.trim().split('\n').join('
'); - } - if (data.status === 'successful' || data.status === 'failed' || data.status === 'error' || data.status === 'canceled') { - scope.job_status.finished = data.finished; - scope.liveEventProcessing = false; - scope.pauseLiveEvents = false; - scope.waiting = false; - scope.playsLoading = false; - scope.tasksLoading = false; - scope.hostResultsLoading = false; - } - else { - scope.job_status.finished = null; - } - - if (data.started && data.finished) { - scope.job_status.elapsed = GetElapsed({ - start: data.started, - end: data.finished - }); - } - else { - scope.job_status.elapsed = '00:00:00'; - } - scope.status_choices.every(function(status) { - if (status.value === scope.job.status) { - scope.job_status.status_label = status.label; - return false; - } - return true; - }); - //scope.setSearchAll('host'); - ParseTypeChange({ scope: scope, field_id: 'pre-formatted-variables', readOnly: true }); - scope.$emit('LoadPlays', data.related.job_events); - }) - .error(function(data, status) { - ProcessErrors(scope, data, status, null, { hdr: 'Error!', - msg: 'Failed to retrieve job: ' + $stateParams.id + '. GET returned: ' + status }); - }); - }); - - - if (scope.removeRefreshCompleted) { - scope.removeRefreshCompleted(); - } - scope.removeRefreshCompleted = scope.$on('RefreshCompleted', function() { - refresh_count++; - if (refresh_count === 1) { - // First time. User just loaded page. - scope.$emit('LoadJob'); - } - }); - - scope.adjustSize = function() { - var height, ww = $(window).width(); - if (ww < 1024) { - $('#job-summary-container').hide(); - $('#job-detail-container').css({ "width": "100%", "padding-right": "15px" }); - $('#summary-button').show(); - } - else { - $('.overlay').hide(); - $('#summary-button').hide(); - $('#hide-summary-button').hide(); - $('#job-summary-container .job_well').css({ - 'box-shadow': 'none', - 'height': 'auto' - }); - $('#job-summary-container').css({ - "width": "41.66666667%", - "padding-left": "7px", - "padding-right": "15px", - "z-index": 0 - }); - setTimeout(function() { $('#job-summary-container .job_well').height($('#job-detail-container').height() - 18); }, 500); - $('#job-summary-container').show(); - } - - scope.lessStatus = false; // close the view more status option - - - height = $(window).height() - $('#main-menu-container .navbar').outerHeight() - - $('#job-detail-container').outerHeight() - 20; - scope.$emit('RefreshCompleted'); - }; - - setTimeout(function() { scope.adjustSize(); }, 500); - - // Use debounce for the underscore library to adjust after user resizes window. - $(window).resize(_.debounce(function(){ - scope.adjustSize(); - }, 500)); - - function flashPlayTip() { - setTimeout(function(){ - $('#play-help').popover('show'); - },500); - setTimeout(function() { - $('#play-help').popover('hide'); - }, 5000); - } - - scope.selectPlay = function(id) { - if (scope.liveEventProcessing && !scope.pauseLiveEvents) { - scope.pauseLiveEvents = true; - flashPlayTip(); - } - SelectPlay({ - scope: scope, - id: id - }); - }; - - scope.selectTask = function(id) { - if (scope.liveEventProcessing && !scope.pauseLiveEvents) { - scope.pauseLiveEvents = true; - flashPlayTip(); - } - SelectTask({ - scope: scope, - id: id - }); - }; - - scope.togglePlayButton = function() { - if (scope.pauseLiveEvents) { - scope.pauseLiveEvents = false; - scope.$emit('LoadJob'); - } - }; - - scope.objectIsEmpty = function(obj) { - if (angular.isObject(obj)) { - return (Object.keys(obj).length > 0) ? false : true; - } - return true; - }; - - scope.toggleLessEvents = function() { - if (!scope.lessEvents) { - $('#events-summary').slideUp(0); - scope.lessEvents = true; - } - else { - $('#events-summary').slideDown(0); - scope.lessEvents = false; - } - }; - - scope.toggleLessStatus = function() { - if (!scope.lessStatus) { - $('#job-status-form').slideUp(200); - scope.lessStatus = true; - } - else { - $('#job-status-form').slideDown(200); - scope.lessStatus = false; - } - }; - - scope.toggleLessDetail = function() { - if (!scope.lessDetail) { - $('#job-detail-details').slideUp(200); - scope.lessDetail = true; - } - else { - $('#job-detail-details').slideDown(200); - scope.lessDetail = false; - } - }; - - if (scope.removeDeleteFinished) { - scope.removeDeleteFinished(); - } - scope.removeDeleteFinished = scope.$on('DeleteFinished', function(e, action) { - Wait('stop'); - if (action !== 'cancel') { - Wait('stop'); - $location.url('/jobs'); - } - }); - - scope.deleteJob = function() { - DeleteJob({ - scope: scope, - id: scope.job.id, - job: scope.job, - callback: 'DeleteFinished' - }); - }; - - scope.relaunchJob = function() { - RelaunchPlaybook({ - scope: scope, - id: scope.job.id - }); - }; - - scope.playsScrollDown = function() { - // check for more plays when user scrolls to bottom of play list... - if (((!scope.liveEventProcessing) || (scope.liveEventProcessing && scope.pauseLiveEvents)) && scope.next_plays) { - $('#playsMoreRows').fadeIn(); - scope.playsLoading = true; - JobDetailService.getNextPage(scope.next_plays) - .success( function(data) { - scope.next_plays = data.next; - data.results.forEach(function(event, idx) { - var status, status_text, start, end, elapsed, ok, changed, failed, skipped; - - status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful'; - status_text = (event.failed) ? 'Failed' : (event.changed) ? 'Changed' : 'OK'; - start = event.started; - - if (idx < data.results.length - 1) { - // end date = starting date of the next event - end = data.results[idx + 1].started; - } - else if (JobIsFinished(scope)) { - // this is the last play and the job already finished - end = scope.job_status.finished; - } - if (end) { - elapsed = GetElapsed({ - start: start, - end: end - }); - } - else { - elapsed = '00:00:00'; - } - - scope.plays.push({ - id: event.id, - name: event.play, - created: start, - finished: end, - status: status, - status_text: status_text, - status_tip: "Event ID: " + event.id + "
Status: " + status_text, - elapsed: elapsed, - hostCount: 0, - fistTask: null, - playActiveClass: '', - unreachableCount: (event.unreachable_count) ? event.unreachable_count : 0, - }); - - ok = (event.ok_count) ? event.ok_count : 0; - changed = (event.changed_count) ? event.changed_count : 0; - failed = (event.failed_count) ? event.failed_count : 0; - skipped = (event.skipped_count) ? event.skipped_count : 0; - - scope.plays[scope.plays.length - 1].hostCount = ok + changed + failed + skipped; - scope.playsLoading = false; - }); - $('#playsMoreRows').fadeOut(400); - }) - .error( function(data, status) { - ProcessErrors(scope, data, status, null, { hdr: 'Error!', - msg: 'Call to ' + scope.next_plays + '. GET returned: ' + status }); - }); - } - }; - - scope.tasksScrollDown = function() { - // check for more tasks when user scrolls to bottom of task list... - if (((!scope.liveEventProcessing) || (scope.liveEventProcessing && scope.pauseLiveEvents)) && scope.next_tasks) { - $('#tasksMoreRows').fadeIn(); - scope.tasksLoading = true; - JobDetailService.getNextPage(scope.next_tasks) - .success(function(data) { - scope.next_tasks = data.next; - data.results.forEach(function(event, idx) { - var end, elapsed, status, status_text; - if (idx < data.results.length - 1) { - // end date = starting date of the next event - end = data.results[idx + 1].created; - } - else { - // no next event (task), get the end time of the play - scope.plays.every(function(p, j) { - if (p.id === scope.selectedPlay) { - end = scope.plays[j].finished; - return false; - } - return true; - }); - } - if (end) { - elapsed = GetElapsed({ - start: event.created, - end: end - }); - } - else { - elapsed = '00:00:00'; - } - - status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful'; - status_text = (event.failed) ? 'Failed' : (event.changed) ? 'Changed' : 'OK'; - - scope.tasks.push({ - id: event.id, - play_id: scope.selectedPlay, - name: event.name, - status: status, - status_text: status_text, - status_tip: "Event ID: " + event.id + "
Status: " + status_text, - created: event.created, - modified: event.modified, - finished: end, - elapsed: elapsed, - hostCount: event.host_count, // hostCount, - reportedHosts: event.reported_hosts, - successfulCount: event.successful_count, - failedCount: event.failed_count, - changedCount: event.changed_count, - skippedCount: event.skipped_count, - taskActiveClass: '' - }); - SetTaskStyles({ - task: scope.tasks[scope.tasks.length - 1] - }); - }); - $('#tasksMoreRows').fadeOut(400); - scope.tasksLoading = false; - }) - .error(function(data, status) { - $('#tasksMoreRows').fadeOut(400); - ProcessErrors(scope, data, status, null, { hdr: 'Error!', - msg: 'Call to ' + scope.next_tasks + '. GET returned: ' + status }); - }); - } - }; - - scope.hostResultsScrollDown = function() { - // check for more hosts when user scrolls to bottom of host results list... - if (((!scope.liveEventProcessing) || (scope.liveEventProcessing && scope.pauseLiveEvents)) && scope.next_host_results) { - $('#hostResultsMoreRows').fadeIn(); - scope.hostResultsLoading = true; - JobDetailService.getNextPage(scope.next_host_results) - .success(function(data) { - scope.next_host_results = data.next; - data.results.forEach(function(row) { - var status, status_text, item, msg; - if (row.event === "runner_on_skipped") { - status = 'skipped'; - } - else if (row.event === "runner_on_unreachable") { - status = 'unreachable'; - } - else { - status = (row.failed) ? 'failed' : (row.changed) ? 'changed' : 'successful'; - } - switch(status) { - case "successful": - status_text = 'OK'; - break; - case "changed": - status_text = "Changed"; - break; - case "failed": - status_text = "Failed"; - break; - case "unreachable": - status_text = "Unreachable"; - break; - case "skipped": - status_text = "Skipped"; - } - if (row.event_data && row.event_data.res) { - item = row.event_data.res.item; - if (typeof item === "object") { - item = JSON.stringify(item); - } - } - msg = ''; - if (row.event_data && row.event_data.res) { - if (typeof row.event_data.res === 'object') { - msg = row.event_data.res.msg; - } else { - msg = row.event_data.res; - } - } - scope.hostResults.push({ - id: row.id, - status: status, - status_text: status_text, - host_id: row.host, - task_id: row.parent, - name: row.event_data.host, - created: row.created, - msg: (row.event_data && row.event_data.res) ? row.event_data.res.msg : '', - item: item - }); - scope.hostResultsLoading = false; - }); - $('#hostResultsMoreRows').fadeOut(400); - }) - .error(function(data, status) { - $('#hostResultsMoreRows').fadeOut(400); - ProcessErrors(scope, data, status, null, { hdr: 'Error!', - msg: 'Call to ' + scope.next_host_results + '. GET returned: ' + status }); - }); - } - }; - - scope.refresh = function(){ - $scope.$emit('LoadJob'); - }; - - // Click binding for the expand/collapse button on the standard out log - $scope.toggleStdoutFullscreen = function() { - $scope.stdoutFullScreen = !$scope.stdoutFullScreen; - }; - - scope.editSchedule = function() { - // We need to get the schedule's ID out of the related links - // An example of the related schedule link looks like /api/v1/schedules/5 - // where 5 is the ID we are trying to capture - var regex = /\/api\/v1\/schedules\/(\d+)\//; - var id = scope.job.related.schedule.match(regex)[1]; - - if(scope.job.job_template && id) { - $state.go('jobTemplateSchedules.edit', {id: scope.job.job_template, schedule_id: id}); - } - }; - - // SchedulesRefresh is the callback string that we passed to the edit schedule modal - // When the modal successfully updates the schedule it will emit this event and pass - // the updated schedule object - if (scope.removeSchedulesRefresh) { - scope.removeSchedulesRefresh(); - } - scope.$on('SchedulesRefresh', function(e, data) { - if (data) { - scope.scheduled_by = data.name; - } - }); - } -];