diff --git a/awx/ui/client/features/_index.less b/awx/ui/client/features/_index.less
index 4a69120ed9..59e8e4630b 100644
--- a/awx/ui/client/features/_index.less
+++ b/awx/ui/client/features/_index.less
@@ -1,3 +1,3 @@
@import 'credentials/_index';
-@import 'jobs/_index';
+@import 'output/_index';
@import 'users/tokens/_index';
diff --git a/awx/ui/client/features/output/index.controller.js b/awx/ui/client/features/output/index.controller.js
index 3139c3a6f8..238adc11f4 100644
--- a/awx/ui/client/features/output/index.controller.js
+++ b/awx/ui/client/features/output/index.controller.js
@@ -3,6 +3,7 @@ import hasAnsi from 'has-ansi';
let vm;
let ansi;
+let jobEvent;
let $timeout;
let $sce;
let $compile;
@@ -26,19 +27,19 @@ const TIME_EVENTS = [
EVENT_STATS_PLAY
];
-function JobsIndexController (job, _$sce_, _$timeout_, _$scope_, _$compile_) {
+function JobsIndexController (job, JobEventModel, _$sce_, _$timeout_, _$scope_, _$compile_) {
$timeout = _$timeout_;
$sce = _$sce_;
$compile = _$compile_;
$scope = _$scope_;
+
ansi = new Ansi();
+ jobEvent = new JobEventModel();
const events = job.get('related.job_events.results');
const html = $sce.trustAsHtml(parseEvents(events));
- vm = this || {};
-
- $scope.ns = 'jobs';
+ vm = this || {}; $scope.ns = 'jobs';
$scope.jobs = {
modal: {}
};
@@ -256,7 +257,17 @@ function getTime (created) {
}
function showHostDetails (id) {
- $scope.jobs.modal.show('title', `test${id}`);
+ jobEvent.request('get', id)
+ .then(() => {
+ const title = jobEvent.get('host_name');
+
+ vm.host = {
+ menu: true,
+ stdout: jobEvent.get('stdout')
+ };
+
+ $scope.jobs.modal.show(title);
+ });
}
function toggle (uuid) {
@@ -280,6 +291,6 @@ function toggle (uuid) {
}
}
-JobsIndexController.$inject = ['job', '$sce', '$timeout', '$scope', '$compile'];
+JobsIndexController.$inject = ['job', 'JobEventModel', '$sce', '$timeout', '$scope', '$compile'];
module.exports = JobsIndexController;
diff --git a/awx/ui/client/features/output/index.js b/awx/ui/client/features/output/index.js
index aa98a2359a..e989329f45 100644
--- a/awx/ui/client/features/output/index.js
+++ b/awx/ui/client/features/output/index.js
@@ -1,3 +1,8 @@
+import JobsStrings from '~features/output/jobs.strings';
+import IndexController from '~features/output/index.controller';
+import atLibModels from '~models';
+import atLibComponents from '~components';
+
import JobsStrings from '~features/output/jobs.strings';
import IndexController from '~features/output/index.controller';
@@ -24,7 +29,7 @@ function JobsRun ($stateExtender, strings) {
}
},
resolve: {
- job: ['JobsModel', '$stateParams', (Jobs, $stateParams) => {
+ job: ['JobModel', '$stateParams', (Jobs, $stateParams) => {
const { id } = $stateParams;
return new Jobs('get', id)
@@ -42,7 +47,10 @@ function JobsRun ($stateExtender, strings) {
JobsRun.$inject = ['$stateExtender', 'JobsStrings'];
angular
- .module(MODULE_NAME, [])
+ .module(MODULE_NAME, [
+ atLibModels,
+ atLibComponents
+ ])
.controller('indexController', IndexController)
.service('JobsStrings', JobsStrings)
.run(JobsRun);
diff --git a/awx/ui/client/features/output/index.view.html b/awx/ui/client/features/output/index.view.html
index ba1256c5cc..0d92977ee5 100644
--- a/awx/ui/client/features/output/index.view.html
+++ b/awx/ui/client/features/output/index.view.html
@@ -1,7 +1,7 @@
-
+
+
+
+
diff --git a/awx/ui/client/lib/components/index.js b/awx/ui/client/lib/components/index.js
index 9ac933628c..339747ad67 100644
--- a/awx/ui/client/lib/components/index.js
+++ b/awx/ui/client/lib/components/index.js
@@ -20,6 +20,7 @@ import launchTemplate from '~components/launchTemplateButton/launchTemplateButto
import layout from '~components/layout/layout.directive';
import list from '~components/list/list.directive';
import modal from '~components/modal/modal.directive';
+import outputStdout from '~components/output/stdout.directive';
import panel from '~components/panel/panel.directive';
import panelBody from '~components/panel/body.directive';
import panelHeading from '~components/panel/heading.directive';
@@ -68,6 +69,7 @@ angular
.directive('atRowItem', rowItem)
.directive('atRowAction', rowAction)
.directive('atModal', modal)
+ .directive('atOutputStdout', outputStdout)
.directive('atPanel', panel)
.directive('atPanelBody', panelBody)
.directive('atPanelHeading', panelHeading)
diff --git a/awx/ui/client/lib/components/output/stdout.directive.js b/awx/ui/client/lib/components/output/stdout.directive.js
new file mode 100644
index 0000000000..880e2c6eb6
--- /dev/null
+++ b/awx/ui/client/lib/components/output/stdout.directive.js
@@ -0,0 +1,105 @@
+import Ansi from 'ansi-to-html';
+import hasAnsi from 'has-ansi';
+
+const templateUrl = require('~components/output/stdout.partial.html');
+
+let $sce;
+let $timeout;
+let ansi;
+
+function atOutputStdoutLink (scope, element, attrs, controller) {
+ controller.init(scope, element);
+}
+
+function AtOutputStdoutController (_$sce_, _$timeout_) {
+ const vm = this || {};
+
+ $timeout = _$timeout_;
+ $sce = _$sce_;
+ ansi = new Ansi();
+
+ let scope;
+ let element;
+
+ vm.init = (_scope_, _element_) => {
+ scope = _scope_;
+ element = _element_;
+
+ scope.$watch('state.stdout', curr => {
+ if (!curr) {
+ return;
+ }
+
+ render(scope.state.stdout);
+ });
+ };
+
+ vm.scroll = position => {
+ const container = element.find('.at-Stdout-container')[0];
+
+ if (position === 'bottom') {
+ container.scrollTop = container.scrollHeight;
+ } else {
+ container.scrollTop = 0;
+ }
+ };
+}
+
+AtOutputStdoutController.$inject = [
+ '$sce',
+ '$timeout',
+];
+
+function render (stdout) {
+ console.log('render');
+ const html = $sce.trustAsHtml(parseStdout(stdout));
+
+ $timeout(() => {
+ const table = $('#atStdoutTBody');
+
+ table.html($sce.getTrustedHtml(html));
+ });
+}
+
+function parseStdout (stdout) {
+ const lines = stdout.split('\r\n');
+
+ let ln = 0;
+
+ return lines.reduce((html, line) => {
+ ln++;
+
+ return `${html}${createRow(ln, line)}`;
+ }, '');
+}
+
+function createRow (ln, content) {
+ content = content || '';
+
+ if (hasAnsi(content)) {
+ content = ansi.toHtml(content);
+ }
+
+ return `
+
+ | ${ln} |
+ ${content} |
+
`;
+}
+function atOutputStdout () {
+ return {
+ restrict: 'E',
+ transclude: true,
+ replace: true,
+ require: 'atOutputStdout',
+ templateUrl,
+ controller: AtOutputStdoutController,
+ controllerAs: 'vm',
+ link: atOutputStdoutLink,
+ scope: {
+ state: '=',
+ }
+ };
+}
+
+export default atOutputStdout;
diff --git a/awx/ui/client/lib/components/output/stdout.partial.html b/awx/ui/client/lib/components/output/stdout.partial.html
new file mode 100644
index 0000000000..ca38d736f4
--- /dev/null
+++ b/awx/ui/client/lib/components/output/stdout.partial.html
@@ -0,0 +1,19 @@
+
diff --git a/awx/ui/client/lib/models/Job.js b/awx/ui/client/lib/models/Job.js
index 7d87f82330..ef80c5dafb 100644
--- a/awx/ui/client/lib/models/Job.js
+++ b/awx/ui/client/lib/models/Job.js
@@ -1,5 +1,5 @@
-let Base;
let $http;
+let BaseModel;
function getRelaunch (params) {
const req = {
@@ -24,7 +24,7 @@ function postRelaunch (params) {
}
function JobModel (method, resource, config) {
- Base.call(this, 'jobs');
+ BaseModel.call(this, 'jobs');
this.Constructor = JobModel;
this.postRelaunch = postRelaunch.bind(this);
@@ -33,8 +33,8 @@ function JobModel (method, resource, config) {
return this.create(method, resource, config);
}
-function JobModelLoader (BaseModel, _$http_) {
- Base = BaseModel;
+function JobModelLoader (_BaseModel_, _$http_) {
+ BaseModel = _BaseModel_;
$http = _$http_;
return JobModel;
diff --git a/awx/ui/client/lib/models/JobEvent.js b/awx/ui/client/lib/models/JobEvent.js
new file mode 100644
index 0000000000..1c71ba9c54
--- /dev/null
+++ b/awx/ui/client/lib/models/JobEvent.js
@@ -0,0 +1,19 @@
+let BaseModel;
+
+function JobEventModel (method, resource, config) {
+ BaseModel.call(this, 'job_events');
+
+ this.Constructor = JobEventModel;
+
+ return this.create(method, resource, config);
+}
+
+function JobEventModelLoader (_BaseModel_) {
+ BaseModel = _BaseModel_;
+
+ return JobEventModel;
+}
+
+JobEventModel.$inject = ['BaseModel'];
+
+export default JobEventModelLoader;
diff --git a/awx/ui/client/lib/models/Jobs.js b/awx/ui/client/lib/models/Jobs.js
deleted file mode 100644
index e82b3e04af..0000000000
--- a/awx/ui/client/lib/models/Jobs.js
+++ /dev/null
@@ -1,19 +0,0 @@
-let BaseModel;
-
-function JobsModel (method, resource, config) {
- BaseModel.call(this, 'jobs');
-
- this.Constructor = JobsModel;
-
- return this.create(method, resource, config);
-}
-
-function JobsModelLoader (_BaseModel_) {
- BaseModel = _BaseModel_;
-
- return JobsModel;
-}
-
-JobsModelLoader.$inject = ['BaseModel'];
-
-export default JobsModelLoader;
diff --git a/awx/ui/client/lib/models/index.js b/awx/ui/client/lib/models/index.js
index 0e5ab2c6b3..91eb3742ee 100644
--- a/awx/ui/client/lib/models/index.js
+++ b/awx/ui/client/lib/models/index.js
@@ -12,10 +12,10 @@ import Inventory from '~models/Inventory';
import InventoryScript from '~models/InventoryScript';
import InventorySource from '~models/InventorySource';
import Job from '~models/Job';
+import JobEvent from '~models/JobEvent';
import JobTemplate from '~models/JobTemplate';
import Jobs from '~models/Jobs';
import Me from '~models/Me';
-import ModelsStrings from '~models/models.strings';
import NotificationTemplate from '~models/NotificationTemplate';
import Organization from '~models/Organization';
import Project from '~models/Project';
@@ -26,6 +26,8 @@ import WorkflowJobTemplate from '~models/WorkflowJobTemplate';
import WorkflowJobTemplateNode from '~models/WorkflowJobTemplateNode';
import UnifiedJob from '~models/UnifiedJob';
+import ModelsStrings from '~models/models.strings';
+
const MODULE_NAME = 'at.lib.models';
angular
@@ -43,11 +45,11 @@ angular
.service('InventoryModel', Inventory)
.service('InventoryScriptModel', InventoryScript)
.service('InventorySourceModel', InventorySource)
+ .service('JobEventModel', JobEvent)
.service('JobModel', Job)
.service('JobTemplateModel', JobTemplate)
.service('JobsModel', Jobs)
.service('MeModel', Me)
- .service('ModelsStrings', ModelsStrings)
.service('NotificationTemplate', NotificationTemplate)
.service('OrganizationModel', Organization)
.service('ProjectModel', Project)
@@ -56,6 +58,8 @@ angular
.service('UnifiedJobTemplateModel', UnifiedJobTemplate)
.service('WorkflowJobModel', WorkflowJob)
.service('WorkflowJobTemplateModel', WorkflowJobTemplate)
- .service('WorkflowJobTemplateNodeModel', WorkflowJobTemplateNode);
+ .service('WorkflowJobTemplateNodeModel', WorkflowJobTemplateNode)
+ .service('WorkflowJobTemplateNodeModel', WorkflowJobTemplateNode)
+ .service('ModelsStrings', ModelsStrings);
export default MODULE_NAME;