mirror of
https://github.com/ansible/awx.git
synced 2026-03-24 20:35:02 -02:30
Inventory refactor: add job status summary fly-out on host status. Click on a status and a second dialog appears for the specific job. Dialog can be resized and moved- built using jquery and styled to match TB dialog. Fixed home/groups and home/hosts pages to appear more inventory edit page. Home/groups page now allows you to start and inventory sync as well. Fixed tool-tip consistency. Click page forward/back now employs the spinner and should stop overclicking, which was resulting in page numbers < 0.
This commit is contained in:
@@ -51,9 +51,85 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
|
||||
|
||||
}
|
||||
}])
|
||||
|
||||
.factory('SetStatus', ['SetEnabledMsg', 'Empty', function(SetEnabledMsg, Empty) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var host = params.host;
|
||||
var html, title;
|
||||
|
||||
function setMsg(host) {
|
||||
if (host.has_active_failures == true || (host.has_active_failures == false && host.last_job !== null)) {
|
||||
if (host.has_active_failures === true) {
|
||||
host.badgeToolTip = 'Most recent job failed. Click to view jobs.';
|
||||
host.active_failures = 'failed';
|
||||
}
|
||||
else {
|
||||
host.badgeToolTip = "Most recent job successful. Click to view jobs.";
|
||||
host.active_failures = 'success';
|
||||
}
|
||||
if (host.summary_fields.recent_jobs.length > 0) {
|
||||
// build html table of job status info
|
||||
var jobs = host.summary_fields.recent_jobs.sort(
|
||||
function(a,b) {
|
||||
// reverse numerical order
|
||||
return -1 * (a - b);
|
||||
});
|
||||
title = "Recent Jobs";
|
||||
html = "<table class=\"table table-condensed\">\n";
|
||||
html += "<thead>\n";
|
||||
html += "<tr>\n";
|
||||
html += "<th>ID</td>\n";
|
||||
html += "<th>Status</td>\n";
|
||||
html += "<th>Name</td>\n";
|
||||
html += "</tr>\n";
|
||||
html += "</thead>\n";
|
||||
html += "<tbody>\n";
|
||||
for (var j=0; j < jobs.length; j++) {
|
||||
var job = jobs[j];
|
||||
html += "<tr>\n";
|
||||
html += "<td><a href=\"/#/jobs/" + job.id + "\">" + job.id + "</a></td>\n";
|
||||
html += "<td><a ng-click=\"showJobSummary(" + job.id + ")\"><i class=\"fa icon-job-" + job.status + "\"></i> " + job.status + "</a></td>\n";
|
||||
html += "<td>" + job.name + "</td>\n";
|
||||
html += "</tr>\n";
|
||||
}
|
||||
html += "</tbody>\n";
|
||||
html += "</table>\n";
|
||||
}
|
||||
else {
|
||||
title = 'No job data';
|
||||
html = '<p>No recent job data available for this host.</p>';
|
||||
}
|
||||
}
|
||||
else if (host.has_active_failures == false && host.last_job == null) {
|
||||
host.has_active_failures = 'none';
|
||||
host.badgeToolTip = "No job data available.";
|
||||
host.active_failures = 'n/a';
|
||||
}
|
||||
host.job_status_html = html;
|
||||
host.job_status_title = title;
|
||||
}
|
||||
|
||||
if (!Empty(host)) {
|
||||
// update single host
|
||||
setMsg(host);
|
||||
SetEnabledMsg(host);
|
||||
}
|
||||
else {
|
||||
// update all hosts
|
||||
for (var i=0; i < scope.hosts.length; i++) {
|
||||
setMsg(scope.hosts[i]);
|
||||
SetEnabledMsg(scope.hosts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}])
|
||||
|
||||
.factory('HostsReload', [ '$routeParams', 'Empty', 'InventoryHosts', 'GetBasePath', 'SearchInit', 'PaginateInit', 'Wait', 'SetHostStatus',
|
||||
function($routeParams, Empty, InventoryHosts, GetBasePath, SearchInit, PaginateInit, Wait, SetHostStatus) {
|
||||
.factory('HostsReload', [ '$routeParams', 'Empty', 'InventoryHosts', 'GetBasePath', 'SearchInit', 'PaginateInit', 'Wait',
|
||||
'SetHostStatus', 'SetStatus',
|
||||
function($routeParams, Empty, InventoryHosts, GetBasePath, SearchInit, PaginateInit, Wait, SetHostStatus, SetStatus) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
@@ -74,9 +150,9 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
|
||||
for (var i=0; i < scope.hosts.length; i++) {
|
||||
//Set tooltip for host enabled flag
|
||||
scope.hosts[i].enabled_flag = scope.hosts[i].enabled;
|
||||
//SetEnabledMsg(scope.hosts[i]);
|
||||
SetHostStatus(scope.hosts[i]);
|
||||
//SetHostStatus(scope.hosts[i]);
|
||||
}
|
||||
SetStatus({ scope: scope });
|
||||
Wait('stop');
|
||||
scope.$emit('HostReloadComplete');
|
||||
});
|
||||
@@ -347,9 +423,9 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
|
||||
|
||||
|
||||
.factory('HostsEdit', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'HostForm', 'GenerateForm',
|
||||
'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait', 'Find', 'SetEnabledMsg',
|
||||
'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait', 'Find', 'SetStatus',
|
||||
function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, GenerateForm, Prompt, ProcessErrors,
|
||||
GetBasePath, HostsReload, ParseTypeChange, Wait, Find, SetEnabledMsg) {
|
||||
GetBasePath, HostsReload, ParseTypeChange, Wait, Find, SetStatus) {
|
||||
return function(params) {
|
||||
|
||||
var parent_scope = params.scope;
|
||||
@@ -371,7 +447,6 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
|
||||
scope.parseType = 'yaml';
|
||||
ParseTypeChange(scope);
|
||||
|
||||
$('#form-modal .btn-none').removeClass('btn-none').addClass('btn-success');
|
||||
|
||||
if (scope.hostLoadedRemove) {
|
||||
scope.hostLoadedRemove();
|
||||
@@ -441,7 +516,7 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
|
||||
host.name = scope.name;
|
||||
host.enabled = scope.enabled;
|
||||
host.enabled_flag = scope.enabled;
|
||||
SetEnabledMsg(host);
|
||||
SetStatus({ scope: parent_scope, host: host });
|
||||
// Close modal
|
||||
Wait('stop');
|
||||
$('#form-modal').modal('hide');
|
||||
|
||||
@@ -423,7 +423,9 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
|
||||
Wait('stop');
|
||||
Alert('Update Started', 'Your request to start the inventory sync process was submitted. Monitor progress ' +
|
||||
'by clicking the <i class="fa fa-refresh fa-lg"></i> button.', 'alert-info');
|
||||
scope.removeHostReloadComplete();
|
||||
if (scope.removeHostReloadComplete) {
|
||||
scope.removeHostReloadComplete();
|
||||
}
|
||||
});
|
||||
|
||||
if (scope.removeUpdateSubmitted) {
|
||||
@@ -431,10 +433,14 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
|
||||
}
|
||||
scope.removeUpdateSubmitted = scope.$on('UpdateSubmitted', function(e, action) {
|
||||
if (action == 'started') {
|
||||
// Cancel the update process
|
||||
scope.selected_tree_id = tree_id;
|
||||
scope.selected_group_id = group_id;
|
||||
scope.refreshGroups();
|
||||
if (scope.refreshGroups) {
|
||||
scope.selected_tree_id = tree_id;
|
||||
scope.selected_group_id = group_id;
|
||||
scope.refreshGroups();
|
||||
}
|
||||
else {
|
||||
scope.$emit('HostReloadComplete');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('JobsHelper', [ ])
|
||||
angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinition'])
|
||||
|
||||
.factory('JobStatusToolTip', [ function() {
|
||||
return function(status) {
|
||||
var toolTip;
|
||||
@@ -37,4 +38,97 @@ angular.module('JobsHelper', [ ])
|
||||
}
|
||||
return toolTip;
|
||||
}
|
||||
}]);
|
||||
}])
|
||||
|
||||
.factory('ShowJobSummary', ['Rest', 'Wait', 'GetBasePath', 'FormatDate', 'ProcessErrors', 'GenerateForm', 'JobSummary',
|
||||
function(Rest, Wait, GetBasePath, FormatDate, ProcessErrors, GenerateForm, JobSummary) {
|
||||
return function(params) {
|
||||
// Display status info in a modal dialog- called from inventory edit page
|
||||
|
||||
var job_id = params.job_id;
|
||||
|
||||
var generator = GenerateForm;
|
||||
var form = JobSummary;
|
||||
|
||||
// Using jquery dialog for its expandable property
|
||||
var html = "<div id=\"status-modal-dialog\" title=\"Job " + job_id + "\"><div id=\"form-container\" style=\"width: 100%;\"></div></div>\n";
|
||||
$('#inventory-modal-container').empty().append(html);
|
||||
var scope = generator.inject(form, { mode: 'edit', id: 'form-container', breadCrumbs: false, related: false });
|
||||
|
||||
// Set modal dimensions based on viewport width
|
||||
var ww = $(document).width();
|
||||
var wh = $('body').height();
|
||||
var x, y, maxrows;
|
||||
if (ww > 1199) {
|
||||
// desktop
|
||||
x = 675;
|
||||
y = (750 > wh) ? wh - 20 : 750;
|
||||
maxrows = 20;
|
||||
}
|
||||
else if (ww <= 1199 && ww >= 768) {
|
||||
x = 550;
|
||||
y = (620 > wh) ? wh - 15 : 620;
|
||||
maxrows = 15;
|
||||
}
|
||||
else {
|
||||
x = (ww - 20);
|
||||
y = (500 > wh) ? wh : 500;
|
||||
maxrows = 10;
|
||||
}
|
||||
// Create the modal
|
||||
$('#status-modal-dialog').dialog({
|
||||
buttons: { "OK": function() { $( this ).dialog( "close" ); } },
|
||||
modal: true,
|
||||
width: x,
|
||||
height: y,
|
||||
autoOpen: false,
|
||||
create: function (e, ui) {
|
||||
// fix the close button
|
||||
$('.ui-dialog[aria-describedby="status-modal-dialog"]').find('.ui-dialog-titlebar button').empty().attr({ 'class': 'close' }).text('x');
|
||||
// fix the OK button
|
||||
$('.ui-dialog[aria-describedby="status-modal-dialog"]').find('.ui-dialog-buttonset button:first')
|
||||
.attr({ 'class': 'btn btn-primary' });
|
||||
},
|
||||
resizeStop: function(e, ui) {
|
||||
// for some reason, after resizing dialog the form and fields (the content) doesn't expand to 100%
|
||||
var dialog = $('.ui-dialog[aria-describedby="status-modal-dialog"]');
|
||||
var content = dialog.find('#status-modal-dialog');
|
||||
content.width( dialog.width() - 28 );
|
||||
},
|
||||
close: function(e, ui) {
|
||||
// Destroy on close
|
||||
$('#status-modal-dialog').dialog('destroy');
|
||||
$('#inventory-modal-container').empty();
|
||||
}
|
||||
});
|
||||
|
||||
function calcRows (content) {
|
||||
var n = content.match(/\n/g);
|
||||
var rows = (n) ? n.length : 1;
|
||||
return (rows > maxrows) ? 20 : rows;
|
||||
}
|
||||
|
||||
Wait('start');
|
||||
var url = GetBasePath('jobs') + job_id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
scope.id = data.id;
|
||||
scope.name = data.name;
|
||||
scope.status = data.status;
|
||||
scope.result_stdout = data.result_stdout;
|
||||
scope.result_traceback = data.result_traceback;
|
||||
scope['stdout_rows'] = calcRows(scope['result_stdout']);
|
||||
scope['traceback_rows'] = calcRows(scope['result_traceback']);
|
||||
var cDate = new Date(data.created);
|
||||
scope.created = FormatDate(cDate);
|
||||
Wait('stop');
|
||||
$('#status-modal-dialog').dialog('open');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, null,
|
||||
{ hdr: 'Error!', msg: 'Attempt to load job failed. GET returned status: ' + status });
|
||||
});
|
||||
}
|
||||
}]);
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('PaginateHelper', ['RefreshHelper', 'ngCookies'])
|
||||
.factory('PaginateInit', [ 'Refresh', '$cookieStore', function(Refresh, $cookieStore) {
|
||||
angular.module('PaginateHelper', ['RefreshHelper', 'ngCookies', 'Utilities'])
|
||||
.factory('PaginateInit', [ 'Refresh', '$cookieStore', 'Wait', function(Refresh, $cookieStore, Wait) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
@@ -51,6 +51,7 @@ angular.module('PaginateHelper', ['RefreshHelper', 'ngCookies'])
|
||||
scope.nextSet = function(set, iterator) {
|
||||
if (scope[iterator + 'NextUrl']) {
|
||||
scope[iterator + 'Page']++;
|
||||
Wait('start');
|
||||
Refresh({ scope: scope, set: set, iterator: iterator, url: scope[iterator + 'NextUrl'] });
|
||||
}
|
||||
};
|
||||
@@ -58,6 +59,7 @@ angular.module('PaginateHelper', ['RefreshHelper', 'ngCookies'])
|
||||
scope.prevSet = function(set, iterator) {
|
||||
if (scope[iterator + 'PrevUrl']) {
|
||||
scope[iterator + 'Page']--;
|
||||
Wait('start');
|
||||
Refresh({ scope: scope, set: set, iterator: iterator, url: scope[iterator + 'PrevUrl'] });
|
||||
}
|
||||
};
|
||||
@@ -70,11 +72,10 @@ angular.module('PaginateHelper', ['RefreshHelper', 'ngCookies'])
|
||||
|
||||
scope[iterator + 'Page'] = 0;
|
||||
var new_url = url.replace(/\?page_size\=\d+/,'');
|
||||
console.log('new_url: ' + new_url);
|
||||
var connect = (/\/$/.test(new_url)) ? '?' : '&';
|
||||
new_url += (scope[iterator + 'SearchParams']) ? connect + scope[iterator + 'SearchParams'] + '&page_size=' + scope[iterator + 'PageSize' ] :
|
||||
connect + 'page_size=' + scope[iterator + 'PageSize' ];
|
||||
console.log('new_url: ' + new_url);
|
||||
Wait('start');
|
||||
Refresh({ scope: scope, set: set, iterator: iterator, url: new_url });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ angular.module('RefreshRelatedHelper', ['RestServices', 'Utilities'])
|
||||
}
|
||||
})
|
||||
.error ( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
//scope[iterator + 'SearchSpin'] = true;
|
||||
ProcessErrors(scope, data, status, null,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve ' + set + '. GET returned status: ' + status });
|
||||
|
||||
@@ -41,7 +41,6 @@ angular.module('RefreshHelper', ['RestServices', 'Utilities'])
|
||||
scope.$emit('PostRefresh');
|
||||
})
|
||||
.error ( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
//scope[iterator + 'SearchSpin'] = false;
|
||||
scope[iterator + 'HoldInput'] = false;
|
||||
ProcessErrors(scope, data, status, null,
|
||||
|
||||
Reference in New Issue
Block a user