mirror of
https://github.com/ansible/awx.git
synced 2026-01-17 12:41:19 -03:30
Add component-based stdout for host modal
This commit is contained in:
parent
21e74fc5eb
commit
a7f29aac3a
@ -1,3 +1,3 @@
|
||||
@import 'credentials/_index';
|
||||
@import 'jobs/_index';
|
||||
@import 'output/_index';
|
||||
@import 'users/tokens/_index';
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<div class="container-fluid">
|
||||
<div class="col-md-4">
|
||||
<at-panel>
|
||||
<p>left</p>
|
||||
<p></p>
|
||||
</at-panel>
|
||||
</div>
|
||||
|
||||
@ -31,5 +31,8 @@
|
||||
</at-panel>
|
||||
</div>
|
||||
|
||||
<at-modal></at-modal>
|
||||
<at-modal>
|
||||
<br />
|
||||
<at-output-stdout state="vm.host"></at-output-stdout>
|
||||
</at-modal>
|
||||
</div>
|
||||
|
||||
@ -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)
|
||||
|
||||
105
awx/ui/client/lib/components/output/stdout.directive.js
Normal file
105
awx/ui/client/lib/components/output/stdout.directive.js
Normal 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;
|
||||
19
awx/ui/client/lib/components/output/stdout.partial.html
Normal file
19
awx/ui/client/lib/components/output/stdout.partial.html
Normal 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>
|
||||
@ -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;
|
||||
|
||||
19
awx/ui/client/lib/models/JobEvent.js
Normal file
19
awx/ui/client/lib/models/JobEvent.js
Normal 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;
|
||||
@ -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;
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user