mirror of
https://github.com/ansible/awx.git
synced 2026-05-09 02:17:37 -02:30
Adds the host event modal to the standard out feature
Removes old host modal code
This commit is contained in:
committed by
Jake McDermott
parent
18dc0e9066
commit
fe58b74d1e
@@ -1,3 +1,4 @@
|
|||||||
|
@import 'host-event/_index';
|
||||||
.at-Stdout {
|
.at-Stdout {
|
||||||
&-menuTop {
|
&-menuTop {
|
||||||
color: @at-gray-848992;
|
color: @at-gray-848992;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<!-- todo: styling, css etc. - disposition according to project lib conventions -->
|
<!-- todo: styling, css etc. - disposition according to project lib conventions -->
|
||||||
|
<div ui-view></div>
|
||||||
<div class="JobResults-panelHeader">
|
<div class="JobResults-panelHeader">
|
||||||
<div class="JobResults-panelHeaderText" translate> DETAILS</div>
|
<div class="JobResults-panelHeaderText" translate> DETAILS</div>
|
||||||
<!-- LEFT PANE HEADER ACTIONS -->
|
<!-- LEFT PANE HEADER ACTIONS -->
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
}
|
}
|
||||||
.HostEvent .CodeMirror{
|
.HostEvent .CodeMirror{
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
max-height: none!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.HostEvent-close:hover{
|
.HostEvent-close:hover{
|
||||||
@@ -40,19 +40,19 @@
|
|||||||
|
|
||||||
<div class="HostEvent-nav">
|
<div class="HostEvent-nav">
|
||||||
<!-- view navigation buttons -->
|
<!-- view navigation buttons -->
|
||||||
<button ui-sref="jobResult.host-event.json" type="button"
|
<button ui-sref="jobz.host-event.json" type="button"
|
||||||
class="btn btn-sm btn-default HostEvent-tab"
|
class="btn btn-sm btn-default HostEvent-tab"
|
||||||
ng-class="{'HostEvent-tab--selected' : isActiveState('jobResult.host-event.json')}">
|
ng-class="{'HostEvent-tab--selected' : isActiveState('jobz.host-event.json')}">
|
||||||
JSON
|
JSON
|
||||||
</button>
|
</button>
|
||||||
<button ng-if="stdout" ui-sref="jobResult.host-event.stdout"
|
<button ng-if="stdout" ui-sref="jobz.host-event.stdout"
|
||||||
type="button" class="btn btn-sm btn-default HostEvent-tab"
|
type="button" class="btn btn-sm btn-default HostEvent-tab"
|
||||||
ng-class="{'HostEvent-tab--selected' : isActiveState('jobResult.host-event.stdout')}">
|
ng-class="{'HostEvent-tab--selected' : isActiveState('jobz.host-event.stdout')}">
|
||||||
Standard Out
|
Standard Out
|
||||||
</button>
|
</button>
|
||||||
<button ng-if="stderr" ui-sref="jobResult.host-event.stderr"
|
<button ng-if="stderr" ui-sref="jobz.host-event.stderr"
|
||||||
type="button" class="btn btn-sm btn-default HostEvent-tab"
|
type="button" class="btn btn-sm btn-default HostEvent-tab"
|
||||||
ng-class="{'HostEvent-tab--selected' : isActiveState('jobResult.host-event.stderr')}">
|
ng-class="{'HostEvent-tab--selected' : isActiveState('jobz.host-event.stderr')}">
|
||||||
Standard Error
|
Standard Error
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
function HostEventsController (
|
||||||
|
$scope,
|
||||||
|
$state,
|
||||||
|
HostEventService,
|
||||||
|
hostEvent
|
||||||
|
) {
|
||||||
|
$scope.processEventStatus = HostEventService.processEventStatus;
|
||||||
|
$scope.processResults = processResults;
|
||||||
|
$scope.isActiveState = isActiveState;
|
||||||
|
$scope.getActiveHostIndex = getActiveHostIndex;
|
||||||
|
$scope.closeHostEvent = closeHostEvent;
|
||||||
|
|
||||||
|
function init () {
|
||||||
|
hostEvent.event_name = hostEvent.event;
|
||||||
|
$scope.event = _.cloneDeep(hostEvent);
|
||||||
|
|
||||||
|
// grab standard out & standard error if present from the host
|
||||||
|
// event's 'res' object, for things like Ansible modules. Small
|
||||||
|
// wrinkle in this implementation is that the stdout/stderr tabs
|
||||||
|
// should be shown if the `res` object has stdout/stderr keys, even
|
||||||
|
// if they're a blank string. The presence of these keys is
|
||||||
|
// potentially significant to a user.
|
||||||
|
if (_.has(hostEvent.event_data, 'task_action')) {
|
||||||
|
$scope.module_name = hostEvent.event_data.task_action;
|
||||||
|
} else if (!_.has(hostEvent.event_data, 'task_action')) {
|
||||||
|
$scope.module_name = 'No result found';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.has(hostEvent.event_data, 'res.result.stdout')) {
|
||||||
|
if (hostEvent.event_data.res.stdout === '') {
|
||||||
|
$scope.stdout = ' ';
|
||||||
|
} else {
|
||||||
|
$scope.stdout = hostEvent.event_data.res.stdout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.has(hostEvent.event_data, 'res.result.stderr')) {
|
||||||
|
if (hostEvent.event_data.res.stderr === '') {
|
||||||
|
$scope.stderr = ' ';
|
||||||
|
} else {
|
||||||
|
$scope.stderr = hostEvent.event_data.res.stderr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.has(hostEvent.event_data, 'res')) {
|
||||||
|
$scope.json = hostEvent.event_data.res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($scope.module_name === 'debug' &&
|
||||||
|
_.has(hostEvent.event_data, 'res.result.stdout')) {
|
||||||
|
$scope.stdout = hostEvent.event_data.res.result.stdout;
|
||||||
|
}
|
||||||
|
if ($scope.module_name === 'yum' &&
|
||||||
|
_.has(hostEvent.event_data, 'res.results') &&
|
||||||
|
_.isArray(hostEvent.event_data.res.results)) {
|
||||||
|
const event = hostEvent.event_data.res.results;
|
||||||
|
$scope.stdout = event[0];// eslint-disable-line prefer-destructuring
|
||||||
|
}
|
||||||
|
// instantiate Codemirror
|
||||||
|
if ($state.current.name === 'jobz.host-event.json') {
|
||||||
|
try {
|
||||||
|
if (_.has(hostEvent.event_data, 'res')) {
|
||||||
|
initCodeMirror(
|
||||||
|
'HostEvent-codemirror',
|
||||||
|
JSON.stringify($scope.json, null, 4),
|
||||||
|
{ name: 'javascript', json: true }
|
||||||
|
);
|
||||||
|
resize();
|
||||||
|
} else {
|
||||||
|
$scope.no_json = true;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// element with id HostEvent-codemirror is not the view
|
||||||
|
// controlled by this instance of HostEventController
|
||||||
|
}
|
||||||
|
} else if ($state.current.name === 'jobz.host-event.stdout') {
|
||||||
|
try {
|
||||||
|
resize();
|
||||||
|
} catch (err) {
|
||||||
|
// element with id HostEvent-codemirror is not the view
|
||||||
|
// controlled by this instance of HostEventController
|
||||||
|
}
|
||||||
|
} else if ($state.current.name === 'jobz.host-event.stderr') {
|
||||||
|
try {
|
||||||
|
resize();
|
||||||
|
} catch (err) {
|
||||||
|
// element with id HostEvent-codemirror is not the view
|
||||||
|
// controlled by this instance of HostEventController
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$('#HostEvent').modal('show');
|
||||||
|
$('.modal-content').resizable({
|
||||||
|
minHeight: 523,
|
||||||
|
minWidth: 600
|
||||||
|
});
|
||||||
|
$('.modal-dialog').draggable({
|
||||||
|
cancel: '.HostEvent-view--container'
|
||||||
|
});
|
||||||
|
|
||||||
|
function resize () {
|
||||||
|
if ($state.current.name === 'jobz.host-event.json') {
|
||||||
|
const editor = $('.CodeMirror')[0].CodeMirror;
|
||||||
|
const height = $('.modal-dialog').height() - $('.HostEvent-header').height() - $('.HostEvent-details').height() - $('.HostEvent-nav').height() - $('.HostEvent-controls').height() - 120;
|
||||||
|
editor.setSize('100%', height);
|
||||||
|
} else if ($state.current.name === 'jobz.host-event.stdout' || $state.current.name === 'jobz.host-event.stderr') {
|
||||||
|
const height = $('.modal-dialog').height() - $('.HostEvent-header').height() - $('.HostEvent-details').height() - $('.HostEvent-nav').height() - $('.HostEvent-controls').height() - 120;
|
||||||
|
$('.HostEvent-stdout').width('100%');
|
||||||
|
$('.HostEvent-stdout').height(height);
|
||||||
|
$('.HostEvent-stdoutContainer').height(height);
|
||||||
|
$('.HostEvent-numberColumnPreload').height(height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.modal-dialog').on('resize', resize);
|
||||||
|
|
||||||
|
$('#HostEvent').on('hidden.bs.modal', $scope.closeHostEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
function processResults (value) {
|
||||||
|
if (typeof value === 'object') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initCodeMirror (el, data, mode) {
|
||||||
|
const container = document.getElementById(el);
|
||||||
|
const options = {};
|
||||||
|
options.lineNumbers = true;
|
||||||
|
options.mode = mode;
|
||||||
|
options.readOnly = true;
|
||||||
|
options.scrollbarStyle = null;
|
||||||
|
const editor = CodeMirror.fromTextArea(// eslint-disable-line no-undef
|
||||||
|
container,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
editor.setSize('100%', 200);
|
||||||
|
editor.getDoc().setValue(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isActiveState (name) {
|
||||||
|
return $state.current.name === name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getActiveHostIndex () {
|
||||||
|
function hostResultfilter (obj) {
|
||||||
|
return obj.id === $scope.event.id;
|
||||||
|
}
|
||||||
|
const result = $scope.hostResults.filter(hostResultfilter);
|
||||||
|
return $scope.hostResults.indexOf(result[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeHostEvent () {
|
||||||
|
// Unbind the listener so it doesn't fire when we close the modal via navigation
|
||||||
|
$('#HostEvent').off('hidden.bs.modal');
|
||||||
|
$('#HostEvent').modal('hide');
|
||||||
|
$state.go('jobz');
|
||||||
|
}
|
||||||
|
$scope.init = init;
|
||||||
|
$scope.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
HostEventsController.$inject = [
|
||||||
|
'$scope',
|
||||||
|
'$state',
|
||||||
|
'HostEventService',
|
||||||
|
'hostEvent',
|
||||||
|
];
|
||||||
|
|
||||||
|
module.exports = HostEventsController;
|
||||||
72
awx/ui/client/features/output/host-event/host-event.route.js
Normal file
72
awx/ui/client/features/output/host-event/host-event.route.js
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
const HostEventModalTemplate = require('~features/output/host-event/host-event-modal.partial.html');
|
||||||
|
const HostEventCodeMirrorTemplate = require('~features/output/host-event/host-event-codemirror.partial.html');
|
||||||
|
const HostEventStdoutTemplate = require('~features/output/host-event/host-event-stdout.partial.html');
|
||||||
|
const HostEventStderrTemplate = require('~features/output/host-event/host-event-stderr.partial.html');
|
||||||
|
|
||||||
|
function exit () {
|
||||||
|
// close the modal
|
||||||
|
// using an onExit event to handle cases where the user navs away
|
||||||
|
// using the url bar / back and not modal "X"
|
||||||
|
$('#HostEvent').modal('hide');
|
||||||
|
// hacky way to handle user browsing away via URL bar
|
||||||
|
$('.modal-backdrop').remove();
|
||||||
|
$('body').removeClass('modal-open');
|
||||||
|
}
|
||||||
|
|
||||||
|
function HostEventResolve (HostEventService, $stateParams) {
|
||||||
|
return HostEventService.getRelatedJobEvents($stateParams.id, {
|
||||||
|
id: $stateParams.eventId
|
||||||
|
}).then((response) => response.data.results[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
HostEventResolve.$inject = [
|
||||||
|
'HostEventService',
|
||||||
|
'$stateParams',
|
||||||
|
];
|
||||||
|
|
||||||
|
const hostEventModal = {
|
||||||
|
name: 'jobz.host-event',
|
||||||
|
url: '/host-event/:eventId',
|
||||||
|
controller: 'HostEventsController',
|
||||||
|
templateUrl: HostEventModalTemplate,
|
||||||
|
abstract: false,
|
||||||
|
ncyBreadcrumb: {
|
||||||
|
skip: true
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
hostEvent: HostEventResolve
|
||||||
|
},
|
||||||
|
onExit: exit
|
||||||
|
};
|
||||||
|
|
||||||
|
const hostEventJson = {
|
||||||
|
name: 'jobz.host-event.json',
|
||||||
|
url: '/json',
|
||||||
|
controller: 'HostEventsController',
|
||||||
|
templateUrl: HostEventCodeMirrorTemplate,
|
||||||
|
ncyBreadcrumb: {
|
||||||
|
skip: true
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const hostEventStdout = {
|
||||||
|
name: 'jobz.host-event.stdout',
|
||||||
|
url: '/stdout',
|
||||||
|
controller: 'HostEventsController',
|
||||||
|
templateUrl: HostEventStdoutTemplate,
|
||||||
|
ncyBreadcrumb: {
|
||||||
|
skip: true
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const hostEventStderr = {
|
||||||
|
name: 'jobz.host-event.stderr',
|
||||||
|
url: '/stderr',
|
||||||
|
controller: 'HostEventsController',
|
||||||
|
templateUrl: HostEventStderrTemplate,
|
||||||
|
ncyBreadcrumb: {
|
||||||
|
skip: true
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export { hostEventJson, hostEventModal, hostEventStdout, hostEventStderr };
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
function HostEventService (
|
||||||
|
Rest,
|
||||||
|
ProcessErrors,
|
||||||
|
GetBasePath,
|
||||||
|
$rootScope
|
||||||
|
) {
|
||||||
|
// GET events related to a job run
|
||||||
|
// e.g.
|
||||||
|
// ?event=playbook_on_stats
|
||||||
|
// ?parent=206&event__startswith=runner&page_size=200&order=host_name,counter
|
||||||
|
this.getRelatedJobEvents = (id, params) => {
|
||||||
|
let url = GetBasePath('jobs');
|
||||||
|
url = `${url}${id}/job_events/?${this.stringifyParams(params)}`;
|
||||||
|
Rest.setUrl(url);
|
||||||
|
return Rest.get()
|
||||||
|
.then(response => response)
|
||||||
|
.catch(({ data, status }) => {
|
||||||
|
ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: `Call to ${url}. GET returned: ${status}` });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.stringifyParams = params => {
|
||||||
|
function reduceFunction (result, value, key) {
|
||||||
|
return `${result}${key}=${value}&`;
|
||||||
|
}
|
||||||
|
return _.reduce(params, reduceFunction, '');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate a helper class for job_event statuses
|
||||||
|
// the stack for which status to display is
|
||||||
|
// unreachable > failed > changed > ok
|
||||||
|
// uses the API's runner events and convenience properties .failed .changed to determine status.
|
||||||
|
// see: job_event_callback.py for more filters to support
|
||||||
|
this.processEventStatus = event => {
|
||||||
|
const obj = {};
|
||||||
|
if (event.event === 'runner_on_unreachable') {
|
||||||
|
obj.class = 'HostEvent-status--unreachable';
|
||||||
|
obj.status = 'unreachable';
|
||||||
|
}
|
||||||
|
// equiv to 'runner_on_error' && 'runner on failed'
|
||||||
|
if (event.failed) {
|
||||||
|
obj.class = 'HostEvent-status--failed';
|
||||||
|
obj.status = 'failed';
|
||||||
|
}
|
||||||
|
// catch the changed case before ok, because both can be true
|
||||||
|
if (event.changed) {
|
||||||
|
obj.class = 'HostEvent-status--changed';
|
||||||
|
obj.status = 'changed';
|
||||||
|
}
|
||||||
|
if (event.event === 'runner_on_ok' || event.event === 'runner_on_async_ok') {
|
||||||
|
obj.class = 'HostEvent-status--ok';
|
||||||
|
obj.status = 'ok';
|
||||||
|
}
|
||||||
|
if (event.event === 'runner_on_skipped') {
|
||||||
|
obj.class = 'HostEvent-status--skipped';
|
||||||
|
obj.status = 'skipped';
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
HostEventService.$inject = [
|
||||||
|
'Rest',
|
||||||
|
'ProcessErrors',
|
||||||
|
'GetBasePath',
|
||||||
|
'$rootScope'
|
||||||
|
];
|
||||||
|
export default HostEventService;
|
||||||
26
awx/ui/client/features/output/host-event/index.js
Normal file
26
awx/ui/client/features/output/host-event/index.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import {
|
||||||
|
hostEventModal,
|
||||||
|
hostEventJson,
|
||||||
|
hostEventStdout,
|
||||||
|
hostEventStderr
|
||||||
|
} from './host-event.route';
|
||||||
|
import controller from './host-event.controller';
|
||||||
|
import service from './host-event.service';
|
||||||
|
|
||||||
|
const MODULE_NAME = 'hostEvents';
|
||||||
|
|
||||||
|
function hostEventRun ($stateExtender) {
|
||||||
|
$stateExtender.addState(hostEventModal);
|
||||||
|
$stateExtender.addState(hostEventJson);
|
||||||
|
$stateExtender.addState(hostEventStdout);
|
||||||
|
$stateExtender.addState(hostEventStderr);
|
||||||
|
}
|
||||||
|
hostEventRun.$inject = [
|
||||||
|
'$stateExtender'
|
||||||
|
];
|
||||||
|
|
||||||
|
angular.module(MODULE_NAME, [])
|
||||||
|
.controller('HostEventsController', controller)
|
||||||
|
.service('HostEventService', service)
|
||||||
|
.run(hostEventRun);
|
||||||
|
export default MODULE_NAME;
|
||||||
@@ -12,6 +12,7 @@ import StatusService from '~features/output/status.service';
|
|||||||
import DetailsDirective from '~features/output/details.directive';
|
import DetailsDirective from '~features/output/details.directive';
|
||||||
import SearchDirective from '~features/output/search.directive';
|
import SearchDirective from '~features/output/search.directive';
|
||||||
import StatsDirective from '~features/output/stats.directive';
|
import StatsDirective from '~features/output/stats.directive';
|
||||||
|
import HostEvent from './host-event/index';
|
||||||
|
|
||||||
const Template = require('~features/output/index.view.html');
|
const Template = require('~features/output/index.view.html');
|
||||||
|
|
||||||
@@ -211,7 +212,8 @@ JobsRun.$inject = ['$stateRegistry'];
|
|||||||
angular
|
angular
|
||||||
.module(MODULE_NAME, [
|
.module(MODULE_NAME, [
|
||||||
atLibModels,
|
atLibModels,
|
||||||
atLibComponents
|
atLibComponents,
|
||||||
|
HostEvent
|
||||||
])
|
])
|
||||||
.service('JobStrings', Strings)
|
.service('JobStrings', Strings)
|
||||||
.service('JobPageService', PageService)
|
.service('JobPageService', PageService)
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ function JobRenderService ($q, $sce, $window) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (current.isHost) {
|
if (current.isHost) {
|
||||||
tdEvent = `<td class="at-Stdout-event--host" ng-click="vm.showHostDetails('${current.id}')">${content}</td>`;
|
tdEvent = `<td class="at-Stdout-event--host" ui-sref="jobz.host-event.json({eventId: ${current.id}, taskUuid: '${current.uuid}' })">${content}</td>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current.time && current.line === ln) {
|
if (current.time && current.line === ln) {
|
||||||
@@ -251,6 +251,7 @@ function JobRenderService ($q, $sce, $window) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.compile = html => {
|
this.compile = html => {
|
||||||
|
html = $(this.el);
|
||||||
this.hooks.compile(html);
|
this.hooks.compile(html);
|
||||||
|
|
||||||
return this.requestAnimationFrame();
|
return this.requestAnimationFrame();
|
||||||
|
|||||||
@@ -81,7 +81,6 @@
|
|||||||
@import '../../src/inventories-hosts/inventories/inventories.block.less';
|
@import '../../src/inventories-hosts/inventories/inventories.block.less';
|
||||||
@import '../../src/inventories-hosts/shared/associate-groups/associate-groups.block.less';
|
@import '../../src/inventories-hosts/shared/associate-groups/associate-groups.block.less';
|
||||||
@import '../../src/inventories-hosts/shared/associate-hosts/associate-hosts.block.less';
|
@import '../../src/inventories-hosts/shared/associate-hosts/associate-hosts.block.less';
|
||||||
@import '../../src/job-results/host-event/host-event.block.less';
|
|
||||||
@import '../../src/job-results/host-status-bar/host-status-bar.block.less';
|
@import '../../src/job-results/host-status-bar/host-status-bar.block.less';
|
||||||
@import '../../src/job-results/job-results-stdout/job-results-stdout.block.less';
|
@import '../../src/job-results/job-results-stdout/job-results-stdout.block.less';
|
||||||
@import '../../src/job-results/job-results.block.less';
|
@import '../../src/job-results/job-results.block.less';
|
||||||
|
|||||||
@@ -1,143 +0,0 @@
|
|||||||
/*************************************************
|
|
||||||
* Copyright (c) 2016 Ansible, Inc.
|
|
||||||
*
|
|
||||||
* All Rights Reserved
|
|
||||||
*************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
export default
|
|
||||||
['$scope', '$state', 'jobResultsService', 'hostEvent',
|
|
||||||
function($scope, $state, jobResultsService, hostEvent){
|
|
||||||
|
|
||||||
$scope.processEventStatus = jobResultsService.processEventStatus;
|
|
||||||
$scope.processResults = function(value){
|
|
||||||
if (typeof value === 'object'){return false;}
|
|
||||||
else {return true;}
|
|
||||||
};
|
|
||||||
|
|
||||||
var initCodeMirror = function(el, data, mode){
|
|
||||||
var container = document.getElementById(el);
|
|
||||||
var editor = CodeMirror.fromTextArea(container, { // jshint ignore:line
|
|
||||||
lineNumbers: true,
|
|
||||||
mode: mode,
|
|
||||||
readOnly: true,
|
|
||||||
scrollbarStyle: null
|
|
||||||
});
|
|
||||||
editor.setSize("100%", 200);
|
|
||||||
editor.getDoc().setValue(data);
|
|
||||||
};
|
|
||||||
/*ignore jslint end*/
|
|
||||||
$scope.isActiveState = function(name){
|
|
||||||
return $state.current.name === name;
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.getActiveHostIndex = function(){
|
|
||||||
var result = $scope.hostResults.filter(function( obj ) {
|
|
||||||
return obj.id === $scope.event.id;
|
|
||||||
});
|
|
||||||
return $scope.hostResults.indexOf(result[0]);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.closeHostEvent = function() {
|
|
||||||
// Unbind the listener so it doesn't fire when we close the modal via navigation
|
|
||||||
$('#HostEvent').off('hidden.bs.modal');
|
|
||||||
$('#HostEvent').modal('hide');
|
|
||||||
$state.go('jobResult');
|
|
||||||
};
|
|
||||||
|
|
||||||
var init = function(){
|
|
||||||
hostEvent.event_name = hostEvent.event;
|
|
||||||
$scope.event = _.cloneDeep(hostEvent);
|
|
||||||
|
|
||||||
// grab standard out & standard error if present from the host
|
|
||||||
// event's "res" object, for things like Ansible modules. Small
|
|
||||||
// wrinkle in this implementation is that the stdout/stderr tabs
|
|
||||||
// should be shown if the `res` object has stdout/stderr keys, even
|
|
||||||
// if they're a blank string. The presence of these keys is
|
|
||||||
// potentially significant to a user.
|
|
||||||
try{
|
|
||||||
$scope.module_name = hostEvent.event_data.task_action || "No result found";
|
|
||||||
$scope.stdout = hostEvent.event_data.res.stdout ? hostEvent.event_data.res.stdout : hostEvent.event_data.res.stdout === "" ? " " : undefined;
|
|
||||||
$scope.stderr = hostEvent.event_data.res.stderr ? hostEvent.event_data.res.stderr : hostEvent.event_data.res.stderr === "" ? " " : undefined;
|
|
||||||
$scope.json = hostEvent.event_data.res;
|
|
||||||
}
|
|
||||||
catch(err){
|
|
||||||
// do nothing, no stdout/stderr for this module
|
|
||||||
}
|
|
||||||
if($scope.module_name === "debug" &&
|
|
||||||
_.has(hostEvent.event_data, "res.result.stdout")){
|
|
||||||
$scope.stdout = hostEvent.event_data.res.result.stdout;
|
|
||||||
}
|
|
||||||
if($scope.module_name === "yum" &&
|
|
||||||
_.has(hostEvent.event_data, "res.results") &&
|
|
||||||
_.isArray(hostEvent.event_data.res.results)){
|
|
||||||
$scope.stdout = hostEvent.event_data.res.results[0];
|
|
||||||
}
|
|
||||||
// instantiate Codemirror
|
|
||||||
// try/catch pattern prevents the abstract-state controller from complaining about element being null
|
|
||||||
if ($state.current.name === 'jobResult.host-event.json'){
|
|
||||||
try{
|
|
||||||
if(_.has(hostEvent.event_data, "res")){
|
|
||||||
initCodeMirror('HostEvent-codemirror', JSON.stringify($scope.json, null, 4), {name: "javascript", json: true});
|
|
||||||
resize();
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
$scope.no_json = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
catch(err){
|
|
||||||
// element with id HostEvent-codemirror is not the view controlled by this instance of HostEventController
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ($state.current.name === 'jobResult.host-event.stdout'){
|
|
||||||
try{
|
|
||||||
resize();
|
|
||||||
}
|
|
||||||
catch(err){
|
|
||||||
// element with id HostEvent-codemirror is not the view controlled by this instance of HostEventController
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ($state.current.name === 'jobResult.host-event.stderr'){
|
|
||||||
try{
|
|
||||||
resize();
|
|
||||||
}
|
|
||||||
catch(err){
|
|
||||||
// element with id HostEvent-codemirror is not the view controlled by this instance of HostEventController
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$('#HostEvent').modal('show');
|
|
||||||
$('.modal-content').resizable({
|
|
||||||
minHeight: 523,
|
|
||||||
minWidth: 600
|
|
||||||
});
|
|
||||||
$('.modal-dialog').draggable({
|
|
||||||
cancel: '.HostEvent-view--container'
|
|
||||||
});
|
|
||||||
|
|
||||||
function resize(){
|
|
||||||
if ($state.current.name === 'jobResult.host-event.json'){
|
|
||||||
let editor = $('.CodeMirror')[0].CodeMirror;
|
|
||||||
let height = $('.modal-dialog').height() - $('.HostEvent-header').height() - $('.HostEvent-details').height() - $('.HostEvent-nav').height() - $('.HostEvent-controls').height() - 120;
|
|
||||||
editor.setSize("100%", height);
|
|
||||||
}
|
|
||||||
else if($state.current.name === 'jobResult.host-event.stdout' || $state.current.name === 'jobResult.host-event.stderr'){
|
|
||||||
let height = $('.modal-dialog').height() - $('.HostEvent-header').height() - $('.HostEvent-details').height() - $('.HostEvent-nav').height() - $('.HostEvent-controls').height() - 120;
|
|
||||||
$(".HostEvent-stdout").width("100%");
|
|
||||||
$(".HostEvent-stdout").height(height);
|
|
||||||
$(".HostEvent-stdoutContainer").height(height);
|
|
||||||
$(".HostEvent-numberColumnPreload").height(height);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
$('.modal-dialog').on('resize', function(){
|
|
||||||
resize();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#HostEvent').on('hidden.bs.modal', function () {
|
|
||||||
$scope.closeHostEvent();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
init();
|
|
||||||
}];
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
/*************************************************
|
|
||||||
* Copyright (c) 2016 Ansible, Inc.
|
|
||||||
*
|
|
||||||
* All Rights Reserved
|
|
||||||
*************************************************/
|
|
||||||
|
|
||||||
import { templateUrl } from '../../shared/template-url/template-url.factory';
|
|
||||||
|
|
||||||
var hostEventModal = {
|
|
||||||
name: 'jobResult.host-event',
|
|
||||||
url: '/host-event/:eventId',
|
|
||||||
controller: 'HostEventController',
|
|
||||||
templateUrl: templateUrl('job-results/host-event/host-event-modal'),
|
|
||||||
'abstract': false,
|
|
||||||
ncyBreadcrumb: {
|
|
||||||
skip: true
|
|
||||||
},
|
|
||||||
resolve: {
|
|
||||||
hostEvent: ['jobResultsService', '$stateParams', function(jobResultsService, $stateParams) {
|
|
||||||
return jobResultsService.getRelatedJobEvents($stateParams.id, {
|
|
||||||
id: $stateParams.eventId
|
|
||||||
}).then((response) => response.data.results[0]);
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
onExit: function() {
|
|
||||||
// close the modal
|
|
||||||
// using an onExit event to handle cases where the user navs away using the url bar / back and not modal "X"
|
|
||||||
$('#HostEvent').modal('hide');
|
|
||||||
// hacky way to handle user browsing away via URL bar
|
|
||||||
$('.modal-backdrop').remove();
|
|
||||||
$('body').removeClass('modal-open');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var hostEventJson = {
|
|
||||||
name: 'jobResult.host-event.json',
|
|
||||||
url: '/json',
|
|
||||||
controller: 'HostEventController',
|
|
||||||
templateUrl: templateUrl('job-results/host-event/host-event-codemirror'),
|
|
||||||
ncyBreadcrumb: {
|
|
||||||
skip: true
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
var hostEventStdout = {
|
|
||||||
name: 'jobResult.host-event.stdout',
|
|
||||||
url: '/stdout',
|
|
||||||
controller: 'HostEventController',
|
|
||||||
templateUrl: templateUrl('job-results/host-event/host-event-stdout'),
|
|
||||||
ncyBreadcrumb: {
|
|
||||||
skip: true
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
var hostEventStderr = {
|
|
||||||
name: 'jobResult.host-event.stderr',
|
|
||||||
url: '/stderr',
|
|
||||||
controller: 'HostEventController',
|
|
||||||
templateUrl: templateUrl('job-results/host-event/host-event-stderr'),
|
|
||||||
ncyBreadcrumb: {
|
|
||||||
skip: true
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export { hostEventJson, hostEventModal, hostEventStdout, hostEventStderr };
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
/*************************************************
|
|
||||||
* Copyright (c) 2016 Ansible, Inc.
|
|
||||||
*
|
|
||||||
* All Rights Reserved
|
|
||||||
*************************************************/
|
|
||||||
|
|
||||||
import {hostEventModal,
|
|
||||||
hostEventJson, hostEventStdout, hostEventStderr} from './host-event.route';
|
|
||||||
import controller from './host-event.controller';
|
|
||||||
|
|
||||||
export default
|
|
||||||
angular.module('jobResults.hostEvent', [])
|
|
||||||
.controller('HostEventController', controller)
|
|
||||||
|
|
||||||
.run(['$stateExtender', function($stateExtender){
|
|
||||||
$stateExtender.addState(hostEventModal);
|
|
||||||
$stateExtender.addState(hostEventJson);
|
|
||||||
$stateExtender.addState(hostEventStdout);
|
|
||||||
$stateExtender.addState(hostEventStderr);
|
|
||||||
}]);
|
|
||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
import hostStatusBar from './host-status-bar/main';
|
import hostStatusBar from './host-status-bar/main';
|
||||||
import jobResultsStdOut from './job-results-stdout/main';
|
import jobResultsStdOut from './job-results-stdout/main';
|
||||||
import hostEvent from './host-event/main';
|
|
||||||
|
|
||||||
import route from './job-results.route.js';
|
import route from './job-results.route.js';
|
||||||
|
|
||||||
@@ -17,7 +16,7 @@ import eventQueueService from './event-queue.service';
|
|||||||
import parseStdoutService from './parse-stdout.service';
|
import parseStdoutService from './parse-stdout.service';
|
||||||
|
|
||||||
export default
|
export default
|
||||||
angular.module('jobResults', [hostStatusBar.name, jobResultsStdOut.name, hostEvent.name, 'angularMoment'])
|
angular.module('jobResults', [hostStatusBar.name, jobResultsStdOut.name, 'angularMoment'])
|
||||||
.run(['$stateExtender', function($stateExtender) {
|
.run(['$stateExtender', function($stateExtender) {
|
||||||
$stateExtender.addState(route);
|
$stateExtender.addState(route);
|
||||||
}])
|
}])
|
||||||
|
|||||||
Reference in New Issue
Block a user