Add component-based stdout for host modal

This commit is contained in:
gconsidine
2017-12-12 16:26:12 -05:00
committed by Jake McDermott
parent 21e74fc5eb
commit a7f29aac3a
11 changed files with 189 additions and 37 deletions

View File

@@ -1,3 +1,3 @@
@import 'credentials/_index'; @import 'credentials/_index';
@import 'jobs/_index'; @import 'output/_index';
@import 'users/tokens/_index'; @import 'users/tokens/_index';

View File

@@ -3,6 +3,7 @@ import hasAnsi from 'has-ansi';
let vm; let vm;
let ansi; let ansi;
let jobEvent;
let $timeout; let $timeout;
let $sce; let $sce;
let $compile; let $compile;
@@ -26,19 +27,19 @@ const TIME_EVENTS = [
EVENT_STATS_PLAY EVENT_STATS_PLAY
]; ];
function JobsIndexController (job, _$sce_, _$timeout_, _$scope_, _$compile_) { function JobsIndexController (job, JobEventModel, _$sce_, _$timeout_, _$scope_, _$compile_) {
$timeout = _$timeout_; $timeout = _$timeout_;
$sce = _$sce_; $sce = _$sce_;
$compile = _$compile_; $compile = _$compile_;
$scope = _$scope_; $scope = _$scope_;
ansi = new Ansi(); ansi = new Ansi();
jobEvent = new JobEventModel();
const events = job.get('related.job_events.results'); const events = job.get('related.job_events.results');
const html = $sce.trustAsHtml(parseEvents(events)); const html = $sce.trustAsHtml(parseEvents(events));
vm = this || {}; vm = this || {}; $scope.ns = 'jobs';
$scope.ns = 'jobs';
$scope.jobs = { $scope.jobs = {
modal: {} modal: {}
}; };
@@ -256,7 +257,17 @@ function getTime (created) {
} }
function showHostDetails (id) { 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) { 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; module.exports = JobsIndexController;

View File

@@ -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 JobsStrings from '~features/output/jobs.strings';
import IndexController from '~features/output/index.controller'; import IndexController from '~features/output/index.controller';
@@ -24,7 +29,7 @@ function JobsRun ($stateExtender, strings) {
} }
}, },
resolve: { resolve: {
job: ['JobsModel', '$stateParams', (Jobs, $stateParams) => { job: ['JobModel', '$stateParams', (Jobs, $stateParams) => {
const { id } = $stateParams; const { id } = $stateParams;
return new Jobs('get', id) return new Jobs('get', id)
@@ -42,7 +47,10 @@ function JobsRun ($stateExtender, strings) {
JobsRun.$inject = ['$stateExtender', 'JobsStrings']; JobsRun.$inject = ['$stateExtender', 'JobsStrings'];
angular angular
.module(MODULE_NAME, []) .module(MODULE_NAME, [
atLibModels,
atLibComponents
])
.controller('indexController', IndexController) .controller('indexController', IndexController)
.service('JobsStrings', JobsStrings) .service('JobsStrings', JobsStrings)
.run(JobsRun); .run(JobsRun);

View File

@@ -1,7 +1,7 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="col-md-4"> <div class="col-md-4">
<at-panel> <at-panel>
<p>left</p> <p></p>
</at-panel> </at-panel>
</div> </div>
@@ -31,5 +31,8 @@
</at-panel> </at-panel>
</div> </div>
<at-modal></at-modal> <at-modal>
<br />
<at-output-stdout state="vm.host"></at-output-stdout>
</at-modal>
</div> </div>

View File

@@ -20,6 +20,7 @@ import launchTemplate from '~components/launchTemplateButton/launchTemplateButto
import layout from '~components/layout/layout.directive'; import layout from '~components/layout/layout.directive';
import list from '~components/list/list.directive'; import list from '~components/list/list.directive';
import modal from '~components/modal/modal.directive'; import modal from '~components/modal/modal.directive';
import outputStdout from '~components/output/stdout.directive';
import panel from '~components/panel/panel.directive'; import panel from '~components/panel/panel.directive';
import panelBody from '~components/panel/body.directive'; import panelBody from '~components/panel/body.directive';
import panelHeading from '~components/panel/heading.directive'; import panelHeading from '~components/panel/heading.directive';
@@ -68,6 +69,7 @@ angular
.directive('atRowItem', rowItem) .directive('atRowItem', rowItem)
.directive('atRowAction', rowAction) .directive('atRowAction', rowAction)
.directive('atModal', modal) .directive('atModal', modal)
.directive('atOutputStdout', outputStdout)
.directive('atPanel', panel) .directive('atPanel', panel)
.directive('atPanelBody', panelBody) .directive('atPanelBody', panelBody)
.directive('atPanelHeading', panelHeading) .directive('atPanelHeading', panelHeading)

View File

@@ -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 `
<tr>
<td class="at-Stdout-line">${ln}</td>
<td class="at-Stdout-event">${content}</td>
</tr>`;
}
function atOutputStdout () {
return {
restrict: 'E',
transclude: true,
replace: true,
require: 'atOutputStdout',
templateUrl,
controller: AtOutputStdoutController,
controllerAs: 'vm',
link: atOutputStdoutLink,
scope: {
state: '=',
}
};
}
export default atOutputStdout;

View File

@@ -0,0 +1,19 @@
<div class="at-Stdout">
<div ng-if="state.menu" class="at-Stdout-menuTop">
<div class="pull-right" ng-click="vm.scroll('bottom')">
<i class="at-Stdout-menuIcon fa fa-arrow-down"></i>
</div>
<div class="at-u-clear"></div>
</div>
<pre class="at-Stdout-container"><table><thead><tr><th class="at-Stdout-line"></th><th class="at-Stdout-event"></th></tr></thead><tbody id="atStdoutTBody"></tbody></table></pre>
<div ng-if="state-menu" class="at-Stdout-menuBottom">
<div class="pull-right" ng-click="vm.scroll('top')">
<i class="at-Stdout-menuIcon fa fa-arrow-up"></i>
</div>
<div class="at-u-clear"></div>
</div>
</div>

View File

@@ -1,5 +1,5 @@
let Base;
let $http; let $http;
let BaseModel;
function getRelaunch (params) { function getRelaunch (params) {
const req = { const req = {
@@ -24,7 +24,7 @@ function postRelaunch (params) {
} }
function JobModel (method, resource, config) { function JobModel (method, resource, config) {
Base.call(this, 'jobs'); BaseModel.call(this, 'jobs');
this.Constructor = JobModel; this.Constructor = JobModel;
this.postRelaunch = postRelaunch.bind(this); this.postRelaunch = postRelaunch.bind(this);
@@ -33,8 +33,8 @@ function JobModel (method, resource, config) {
return this.create(method, resource, config); return this.create(method, resource, config);
} }
function JobModelLoader (BaseModel, _$http_) { function JobModelLoader (_BaseModel_, _$http_) {
Base = BaseModel; BaseModel = _BaseModel_;
$http = _$http_; $http = _$http_;
return JobModel; return JobModel;

View File

@@ -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;

View File

@@ -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;

View File

@@ -12,10 +12,10 @@ import Inventory from '~models/Inventory';
import InventoryScript from '~models/InventoryScript'; import InventoryScript from '~models/InventoryScript';
import InventorySource from '~models/InventorySource'; import InventorySource from '~models/InventorySource';
import Job from '~models/Job'; import Job from '~models/Job';
import JobEvent from '~models/JobEvent';
import JobTemplate from '~models/JobTemplate'; import JobTemplate from '~models/JobTemplate';
import Jobs from '~models/Jobs'; import Jobs from '~models/Jobs';
import Me from '~models/Me'; import Me from '~models/Me';
import ModelsStrings from '~models/models.strings';
import NotificationTemplate from '~models/NotificationTemplate'; import NotificationTemplate from '~models/NotificationTemplate';
import Organization from '~models/Organization'; import Organization from '~models/Organization';
import Project from '~models/Project'; import Project from '~models/Project';
@@ -26,6 +26,8 @@ import WorkflowJobTemplate from '~models/WorkflowJobTemplate';
import WorkflowJobTemplateNode from '~models/WorkflowJobTemplateNode'; import WorkflowJobTemplateNode from '~models/WorkflowJobTemplateNode';
import UnifiedJob from '~models/UnifiedJob'; import UnifiedJob from '~models/UnifiedJob';
import ModelsStrings from '~models/models.strings';
const MODULE_NAME = 'at.lib.models'; const MODULE_NAME = 'at.lib.models';
angular angular
@@ -43,11 +45,11 @@ angular
.service('InventoryModel', Inventory) .service('InventoryModel', Inventory)
.service('InventoryScriptModel', InventoryScript) .service('InventoryScriptModel', InventoryScript)
.service('InventorySourceModel', InventorySource) .service('InventorySourceModel', InventorySource)
.service('JobEventModel', JobEvent)
.service('JobModel', Job) .service('JobModel', Job)
.service('JobTemplateModel', JobTemplate) .service('JobTemplateModel', JobTemplate)
.service('JobsModel', Jobs) .service('JobsModel', Jobs)
.service('MeModel', Me) .service('MeModel', Me)
.service('ModelsStrings', ModelsStrings)
.service('NotificationTemplate', NotificationTemplate) .service('NotificationTemplate', NotificationTemplate)
.service('OrganizationModel', Organization) .service('OrganizationModel', Organization)
.service('ProjectModel', Project) .service('ProjectModel', Project)
@@ -56,6 +58,8 @@ angular
.service('UnifiedJobTemplateModel', UnifiedJobTemplate) .service('UnifiedJobTemplateModel', UnifiedJobTemplate)
.service('WorkflowJobModel', WorkflowJob) .service('WorkflowJobModel', WorkflowJob)
.service('WorkflowJobTemplateModel', WorkflowJobTemplate) .service('WorkflowJobTemplateModel', WorkflowJobTemplate)
.service('WorkflowJobTemplateNodeModel', WorkflowJobTemplateNode); .service('WorkflowJobTemplateNodeModel', WorkflowJobTemplateNode)
.service('WorkflowJobTemplateNodeModel', WorkflowJobTemplateNode)
.service('ModelsStrings', ModelsStrings);
export default MODULE_NAME; export default MODULE_NAME;