diff --git a/awx/ui/client/src/job-detail/host-event/host-event-codemirror.partial.html b/awx/ui/client/src/job-detail/host-event/host-event-codemirror.partial.html
new file mode 100644
index 0000000000..7c744d2169
--- /dev/null
+++ b/awx/ui/client/src/job-detail/host-event/host-event-codemirror.partial.html
@@ -0,0 +1,2 @@
+
diff --git a/awx/ui/client/src/job-detail/host-event/host-event-json.partial.html b/awx/ui/client/src/job-detail/host-event/host-event-json.partial.html
deleted file mode 100644
index a574043dbd..0000000000
--- a/awx/ui/client/src/job-detail/host-event/host-event-json.partial.html
+++ /dev/null
@@ -1,2 +0,0 @@
-
\ No newline at end of file
diff --git a/awx/ui/client/src/job-detail/host-event/host-event-modal.partial.html b/awx/ui/client/src/job-detail/host-event/host-event-modal.partial.html
index 1660de1b57..a48f9de95e 100644
--- a/awx/ui/client/src/job-detail/host-event/host-event-modal.partial.html
+++ b/awx/ui/client/src/job-detail/host-event/host-event-modal.partial.html
@@ -14,6 +14,8 @@
+
+
diff --git a/awx/ui/client/src/job-detail/host-event/host-event.block.less b/awx/ui/client/src/job-detail/host-event/host-event.block.less
index 6a3b6d637d..4df56a4d8c 100644
--- a/awx/ui/client/src/job-detail/host-event/host-event.block.less
+++ b/awx/ui/client/src/job-detail/host-event/host-event.block.less
@@ -7,6 +7,9 @@
width: 700px;
}
}
+.HostEvent .CodeMirror{
+ overflow-x: hidden;
+}
.HostEvent-controls button.HostEvent-close{
color: #FFFFFF;
text-transform: uppercase;
@@ -78,7 +81,7 @@
.HostEvent-field--label{
text-transform: uppercase;
flex: 0 1 80px;
- margin-right: 20px;
+ max-width: 80px;
font-size: 12px;
word-wrap: break-word;
}
diff --git a/awx/ui/client/src/job-detail/host-event/host-event.controller.js b/awx/ui/client/src/job-detail/host-event/host-event.controller.js
index 79c25dbf5f..f86452b005 100644
--- a/awx/ui/client/src/job-detail/host-event/host-event.controller.js
+++ b/awx/ui/client/src/job-detail/host-event/host-event.controller.js
@@ -6,8 +6,8 @@
export default
- ['$stateParams', '$scope', '$state', 'Wait', 'JobDetailService', 'hostEvent',
- function($stateParams, $scope, $state, Wait, JobDetailService, hostEvent){
+ ['$stateParams', '$scope', '$state', 'Wait', 'JobDetailService', 'hostEvent', 'hostResults',
+ function($stateParams, $scope, $state, Wait, JobDetailService, hostEvent, hostResults){
$scope.processEventStatus = JobDetailService.processEventStatus;
$scope.hostResults = [];
@@ -17,15 +17,20 @@
if (typeof value === 'object'){return false;}
else {return true;}
};
+ $scope.isStdOut = function(){
+ if ($state.current.name === 'jobDetails.host-event.stdout' || $state.current.name === 'jobDetaisl.histe-event.stderr'){
+ return 'StandardOut-preContainer StandardOut-preContent';
+ }
+ };
/*ignore jslint start*/
- var initCodeMirror = function(el, json){
- var container = $(el)[0];
+ var initCodeMirror = function(el, data, mode){
+ var container = document.getElementById(el);
var editor = CodeMirror.fromTextArea(container, { // jshint ignore:line
lineNumbers: true,
- mode: {name: "javascript", json: true}
+ mode: mode
});
editor.setSize("100%", 300);
- editor.getDoc().setValue(JSON.stringify(json, null, 4));
+ editor.getDoc().setValue(data);
};
/*ignore jslint end*/
$scope.isActiveState = function(name){
@@ -60,26 +65,45 @@
};
var init = function(){
- $scope.event = hostEvent;
- JobDetailService.getJobEventChildren($stateParams.taskId).success(function(res){
- $scope.hostResults = res.results;
- });
- $scope.json = JobDetailService.processJson($scope.event);
- /* jshint ignore:start */
- if ($state.current.name === 'jobDetail.host-event.json'){
- initCodeMirror('#HostEvent-json', $scope.json);
+ $scope.event = _.cloneDeep(hostEvent);
+ $scope.hostResults = hostResults;
+ $scope.json = JobDetailService.processJson(hostEvent);
+
+ // grab standard out & standard error if present, and remove from the results displayed in the details panel
+ if (hostEvent.event_data.res.stdout){
+ $scope.stdout = hostEvent.event_data.res.stdout;
+ delete $scope.event.event_data.res.stdout;
}
- try {
- $scope.stdout = JobDetailService
- .processJson($scope.event.event_data.res.stdout);
- if ($state.current.name === 'jobDetail.host-event.stdout'){
- initCodeMirror('#HostEvent-stdout', $scope.stdout);
+ if (hostEvent.event_data.res.stderr){
+ $scope.stderr = hostEvent.event_data.res.stderr;
+ delete $scope.event.event_data.res.stderr;
+ }
+ // instantiate Codemirror
+ // try/catch pattern prevents the abstract-state controller from complaining about element being null
+ if ($state.current.name === 'jobDetail.host-event.json'){
+ try{
+ initCodeMirror('HostEvent-codemirror', JSON.stringify($scope.json, null, 4), {name: "javascript", json: true});
+ }
+ catch(err){
+ // element with id HostEvent-codemirror is not the view controlled by this instance of HostEventController
}
}
- catch(err){
- $scope.stdout = null;
+ else if ($state.current.name === 'jobDetail.host-event.stdout'){
+ try{
+ initCodeMirror('HostEvent-codemirror', $scope.stdout, 'shell');
+ }
+ catch(err){
+ // element with id HostEvent-codemirror is not the view controlled by this instance of HostEventController
+ }
+ }
+ else if ($state.current.name === 'jobDetail.host-event.stderr'){
+ try{
+ initCodeMirror('HostEvent-codemirror', $scope.stderr, 'shell');
+ }
+ catch(err){
+ // element with id HostEvent-codemirror is not the view controlled by this instance of HostEventController
+ }
}
- /* jshint ignore:end */
$('#HostEvent').modal('show');
};
init();
diff --git a/awx/ui/client/src/job-detail/host-event/host-event.route.js b/awx/ui/client/src/job-detail/host-event/host-event.route.js
index e734b641cf..885034b747 100644
--- a/awx/ui/client/src/job-detail/host-event/host-event.route.js
+++ b/awx/ui/client/src/job-detail/host-event/host-event.route.js
@@ -17,6 +17,9 @@ var hostEventModal = {
return JobDetailService.getRelatedJobEvents($stateParams.id, {
id: $stateParams.eventId
}).then(function(res){ return res.data.results[0];});
+ }],
+ hostResults: ['JobDetailService', '$stateParams', function(JobDetailService, $stateParams){
+ return JobDetailService.getJobEventChildren($stateParams.taskId).then(res => res.data.results);
}]
},
onExit: function() {
@@ -40,7 +43,22 @@ var hostEventModal = {
name: 'jobDetail.host-event.json',
url: '/json',
controller: 'HostEventController',
- templateUrl: templateUrl('job-detail/host-event/host-event-json')
+ templateUrl: templateUrl('job-detail/host-event/host-event-codemirror')
};
- export {hostEventDetails, hostEventJson, hostEventModal};
+ var hostEventStdout = {
+ name: 'jobDetail.host-event.stdout',
+ url: '/stdout',
+ controller: 'HostEventController',
+ templateUrl: templateUrl('job-detail/host-event/host-event-codemirror')
+ };
+
+ var hostEventStderr = {
+ name: 'jobDetail.host-event.stderr',
+ url: '/stderr',
+ controller: 'HostEventController',
+ templateUrl: templateUrl('job-detail/host-event/host-event-codemirror')
+ };
+
+
+ export {hostEventDetails, hostEventJson, hostEventModal, hostEventStdout, hostEventStderr};
diff --git a/awx/ui/client/src/job-detail/host-event/main.js b/awx/ui/client/src/job-detail/host-event/main.js
index a24bbdd5ae..4379427ff8 100644
--- a/awx/ui/client/src/job-detail/host-event/main.js
+++ b/awx/ui/client/src/job-detail/host-event/main.js
@@ -5,7 +5,7 @@
*************************************************/
import {hostEventModal, hostEventDetails,
- hostEventJson} from './host-event.route';
+ hostEventJson, hostEventStdout, hostEventStderr} from './host-event.route';
import controller from './host-event.controller';
export default
@@ -16,4 +16,6 @@
$stateExtender.addState(hostEventModal);
$stateExtender.addState(hostEventDetails);
$stateExtender.addState(hostEventJson);
+ $stateExtender.addState(hostEventStdout);
+ $stateExtender.addState(hostEventStderr);
}]);
diff --git a/awx/ui/client/src/job-detail/job-detail.service.js b/awx/ui/client/src/job-detail/job-detail.service.js
index 61b67b1035..df3033d708 100644
--- a/awx/ui/client/src/job-detail/job-detail.service.js
+++ b/awx/ui/client/src/job-detail/job-detail.service.js
@@ -8,40 +8,24 @@ export default
},
// the the API passes through Ansible's event_data response
- // we need to massage away the verbose and redundant properties
+ // we need to massage away the verbose & redundant stdout/stderr properties
processJson: function(data){
- // a deep copy
- var result = $.extend(true, {}, data);
// configure fields to ignore
var ignored = [
+ 'type',
'event_data',
'related',
'summary_fields',
'url',
'ansible_facts',
];
-
// remove ignored properties
- Object.keys(result).forEach(function(key){
- if (ignored.indexOf(key) > -1) {
- delete result[key];
+ var result = _.chain(data).cloneDeep().forEach(function(value, key, collection){
+ if (ignored.indexOf(key) > -1){
+ delete collection[key];
}
- });
-
- // flatten Ansible's passed-through response
- try{
- result.event_data = {};
- Object.keys(data.event_data.res).forEach(function(key){
- if (ignored.indexOf(key) > -1) {
- return;
- }
- else{
- result.event_data[key] = data.event_data.res[key];
- }
- });
- }
- catch(err){result.event_data = undefined;}
- return result === {} ? null : result;
+ }).value();
+ return result;
},
// Return Ansible's passed-through response msg on a job_event
processEventMsg: function(event){