mirror of
https://github.com/ansible/awx.git
synced 2026-03-20 10:27:34 -02:30
Merge pull request #3190 from jaredevantabor/notifications-popover
Fix for recent job popovers for notification templates and inventory syncs
This commit is contained in:
@@ -31,6 +31,7 @@ export default function(){
|
|||||||
awTipPlacement: 'right',
|
awTipPlacement: 'right',
|
||||||
dataPlacement: 'right',
|
dataPlacement: 'right',
|
||||||
awPopOver: '{{ host.job_status_html }}',
|
awPopOver: '{{ host.job_status_html }}',
|
||||||
|
dataTitle: '{{host.job_status_title}}',
|
||||||
ngClick:'viewHost(host.id)',
|
ngClick:'viewHost(host.id)',
|
||||||
columnClass: 'col-lg-1 col-md-1 col-sm-2 col-xs-2 List-staticColumn--smallStatus'
|
columnClass: 'col-lg-1 col-md-1 col-sm-2 col-xs-2 List-staticColumn--smallStatus'
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -50,16 +50,9 @@ function InventoriesList($scope, $rootScope, $location, $log,
|
|||||||
"aw-pop-over": html,
|
"aw-pop-over": html,
|
||||||
"data-popover-title": title,
|
"data-popover-title": title,
|
||||||
"data-placement": "right" });
|
"data-placement": "right" });
|
||||||
|
elem.removeAttr('ng-click');
|
||||||
$compile(elem)($scope);
|
$compile(elem)($scope);
|
||||||
elem.on('shown.bs.popover', function() {
|
$scope.triggerPopover(event);
|
||||||
$('.popover').each(function() {
|
|
||||||
$compile($(this))($scope); //make nested directives work!
|
|
||||||
});
|
|
||||||
$('.popover-content, .popover-title').click(function() {
|
|
||||||
elem.popover('hide');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
elem.popover('show');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
view.inject(InventoryList, { mode: mode, scope: $scope });
|
view.inject(InventoryList, { mode: mode, scope: $scope });
|
||||||
@@ -250,44 +243,62 @@ function InventoriesList($scope, $rootScope, $location, $log,
|
|||||||
});
|
});
|
||||||
|
|
||||||
$scope.showGroupSummary = function(event, id) {
|
$scope.showGroupSummary = function(event, id) {
|
||||||
var inventory;
|
try{
|
||||||
if (!Empty(id)) {
|
var elem = $(event.target).parent();
|
||||||
inventory = Find({ list: $scope.inventories, key: 'id', val: id });
|
// if the popover is visible already, then exit the function here
|
||||||
if (inventory.syncStatus !== 'na') {
|
if(elem.data()['bs.popover'].tip().hasClass('in')){
|
||||||
Wait('start');
|
return;
|
||||||
Rest.setUrl(inventory.related.inventory_sources + '?or__source=ec2&or__source=rax&order_by=-last_job_run&page_size=5');
|
}
|
||||||
Rest.get()
|
}
|
||||||
.success(function(data) {
|
catch(err){
|
||||||
$scope.$emit('GroupSummaryReady', event, inventory, data);
|
var inventory;
|
||||||
})
|
if (!Empty(id)) {
|
||||||
.error(function(data, status) {
|
inventory = Find({ list: $scope.inventories, key: 'id', val: id });
|
||||||
ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
|
if (inventory.syncStatus !== 'na') {
|
||||||
msg: 'Call to ' + inventory.related.inventory_sources + ' failed. GET returned status: ' + status
|
Wait('start');
|
||||||
|
Rest.setUrl(inventory.related.inventory_sources + '?or__source=ec2&or__source=rax&order_by=-last_job_run&page_size=5');
|
||||||
|
Rest.get()
|
||||||
|
.success(function(data) {
|
||||||
|
$scope.$emit('GroupSummaryReady', event, inventory, data);
|
||||||
|
})
|
||||||
|
.error(function(data, status) {
|
||||||
|
ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: 'Call to ' + inventory.related.inventory_sources + ' failed. GET returned status: ' + status
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.showHostSummary = function(event, id) {
|
$scope.showHostSummary = function(event, id) {
|
||||||
var url, inventory;
|
try{
|
||||||
if (!Empty(id)) {
|
var elem = $(event.target).parent();
|
||||||
inventory = Find({ list: $scope.inventories, key: 'id', val: id });
|
// if the popover is visible already, then exit the function here
|
||||||
if (inventory.total_hosts > 0) {
|
if(elem.data()['bs.popover'].tip().hasClass('in')){
|
||||||
Wait('start');
|
return;
|
||||||
url = GetBasePath('jobs') + "?type=job&inventory=" + id + "&failed=";
|
}
|
||||||
url += (inventory.has_active_failures) ? 'true' : "false";
|
}
|
||||||
url += "&order_by=-finished&page_size=5";
|
catch(err){
|
||||||
Rest.setUrl(url);
|
var url, inventory;
|
||||||
Rest.get()
|
if (!Empty(id)) {
|
||||||
.success( function(data) {
|
inventory = Find({ list: $scope.inventories, key: 'id', val: id });
|
||||||
$scope.$emit('HostSummaryReady', event, data);
|
if (inventory.total_hosts > 0) {
|
||||||
})
|
Wait('start');
|
||||||
.error( function(data, status) {
|
url = GetBasePath('jobs') + "?type=job&inventory=" + id + "&failed=";
|
||||||
ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
|
url += (inventory.has_active_failures) ? 'true' : "false";
|
||||||
msg: 'Call to ' + url + ' failed. GET returned: ' + status
|
url += "&order_by=-finished&page_size=5";
|
||||||
|
Rest.setUrl(url);
|
||||||
|
Rest.get()
|
||||||
|
.success( function(data) {
|
||||||
|
$scope.$emit('HostSummaryReady', event, data);
|
||||||
|
})
|
||||||
|
.error( function(data, status) {
|
||||||
|
ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: 'Call to ' + url + ' failed. GET returned: ' + status
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ export default
|
|||||||
Wait('stop');
|
Wait('stop');
|
||||||
if (scope.notification_templates) {
|
if (scope.notification_templates) {
|
||||||
scope.notification_templates.forEach(function(notification_template, i) {
|
scope.notification_templates.forEach(function(notification_template, i) {
|
||||||
|
setStatus(notification_template);
|
||||||
scope.notification_type_options.forEach(function(type) {
|
scope.notification_type_options.forEach(function(type) {
|
||||||
if (type.value === notification_template.notification_type) {
|
if (type.value === notification_template.notification_type) {
|
||||||
scope.notification_templates[i].notification_type = type.label;
|
scope.notification_templates[i].notification_type = type.label;
|
||||||
@@ -74,78 +75,33 @@ export default
|
|||||||
callback: 'choicesReadyNotifierList'
|
callback: 'choicesReadyNotifierList'
|
||||||
});
|
});
|
||||||
|
|
||||||
function attachElem(event, html, title) {
|
function setStatus(notification_template) {
|
||||||
var elem = $(event.target).parent();
|
var html, recent_notifications = notification_template.summary_fields.recent_notifications;
|
||||||
try {
|
if (recent_notifications.length > 0) {
|
||||||
elem.tooltip('hide');
|
html = "<table class=\"table table-condensed flyout\" style=\"width: 100%\">\n";
|
||||||
elem.popover('destroy');
|
html += "<thead>\n";
|
||||||
}
|
html += "<tr>";
|
||||||
catch(err) {
|
html += "<th>Status</th>";
|
||||||
//ignore
|
html += "<th>Time</th>";
|
||||||
}
|
html += "</tr>\n";
|
||||||
|
html += "</thead>\n";
|
||||||
|
html += "<tbody>\n";
|
||||||
|
|
||||||
$('.popover').each(function() {
|
recent_notifications.forEach(function(row) {
|
||||||
// remove lingering popover <div>. Seems to be a bug in TB3 RC1
|
html += "<tr>\n";
|
||||||
$(this).remove();
|
html += `<td><i class=\"SmartStatus-tooltip--${row.status} fa icon-job-${row.status}"></i></td>`;
|
||||||
});
|
html += "<td>" + ($filter('longDate')(row.created)).replace(/ /,'<br />') + "</td>\n";
|
||||||
$('.tooltip').each( function() {
|
html += "</tr>\n";
|
||||||
// close any lingering tool tipss
|
|
||||||
$(this).hide();
|
|
||||||
});
|
|
||||||
elem.attr({
|
|
||||||
"aw-pop-over": html,
|
|
||||||
"data-popover-title": title,
|
|
||||||
"data-placement": "right" });
|
|
||||||
$compile(elem)(scope);
|
|
||||||
elem.on('shown.bs.popover', function() {
|
|
||||||
$('.popover').each(function() {
|
|
||||||
$compile($(this))(scope); //make nested directives work!
|
|
||||||
});
|
});
|
||||||
$('.popover-content, .popover-title').click(function() {
|
html += "</tbody>\n";
|
||||||
elem.popover('hide');
|
html += "</table>\n";
|
||||||
});
|
}
|
||||||
});
|
else {
|
||||||
elem.popover('show');
|
html = "<p>No recent notifications.</p>\n";
|
||||||
|
}
|
||||||
|
notification_template.template_status_html = html;
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.showSummary = function(event, id) {
|
|
||||||
setTimeout(function(){
|
|
||||||
if (!Empty(id)) {
|
|
||||||
var recent_notifications,
|
|
||||||
html, title = "Recent Notifications";
|
|
||||||
|
|
||||||
scope.notification_templates.forEach(function(notification_template){
|
|
||||||
if(notification_template.id === id){
|
|
||||||
recent_notifications = notification_template.summary_fields.recent_notifications;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (recent_notifications.length > 0) {
|
|
||||||
html = "<table class=\"table table-condensed flyout\" style=\"width: 100%\">\n";
|
|
||||||
html += "<thead>\n";
|
|
||||||
html += "<tr>";
|
|
||||||
html += "<th>Status</th>";
|
|
||||||
html += "<th>Time</th>";
|
|
||||||
html += "</tr>\n";
|
|
||||||
html += "</thead>\n";
|
|
||||||
html += "<tbody>\n";
|
|
||||||
|
|
||||||
recent_notifications.forEach(function(row) {
|
|
||||||
html += "<tr>\n";
|
|
||||||
html += `<td><i class=\"SmartStatus-tooltip--${row.status} fa icon-job-${row.status}"></i></td>`;
|
|
||||||
html += "<td>" + ($filter('longDate')(row.created)).replace(/ /,'<br />') + "</td>\n";
|
|
||||||
html += "</tr>\n";
|
|
||||||
});
|
|
||||||
html += "</tbody>\n";
|
|
||||||
html += "</table>\n";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
html = "<p>No recent notifications.</p>\n";
|
|
||||||
}
|
|
||||||
attachElem(event, html, title);
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
};
|
|
||||||
|
|
||||||
scope.testNotification = function(){
|
scope.testNotification = function(){
|
||||||
var name = $filter('sanitize')(this.notification_template.name),
|
var name = $filter('sanitize')(this.notification_template.name),
|
||||||
pending_retries = 10;
|
pending_retries = 10;
|
||||||
|
|||||||
@@ -19,17 +19,14 @@ export default function(){
|
|||||||
fields: {
|
fields: {
|
||||||
status: {
|
status: {
|
||||||
label: '',
|
label: '',
|
||||||
columnClass: 'List-staticColumn--smallStatus',
|
iconOnly: true,
|
||||||
searchable: false,
|
searchable: false,
|
||||||
nosort: true,
|
nosort: true,
|
||||||
ngClick: "null",
|
icon: 'icon-job-{{ notification_template.status }}',
|
||||||
iconOnly: true,
|
awPopOver: '{{ notification_template.template_status_html }}',
|
||||||
excludeModal: true,
|
dataTitle: "Recent Notifications",
|
||||||
icons: [{
|
dataPlacement: 'right',
|
||||||
icon: "{{ 'icon-job-' + notification_template.status }}",
|
columnClass: 'col-lg-1 col-md-1 col-sm-2 col-xs-2 List-staticColumn--smallStatus'
|
||||||
ngClick: "showSummary($event, notification_template.id)",
|
|
||||||
ngClass: ""
|
|
||||||
}]
|
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
key: true,
|
key: true,
|
||||||
|
|||||||
@@ -576,6 +576,10 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'JobsHelper'])
|
|||||||
template = '<div id="' + element[0].id + '_popover_container" class="popover" role="tooltip"><div class="arrow"></div><h3 id="' + element[0].id + '_popover_title" class="popover-title"></h3><div id="' + element[0].id + '_popover_content" class="popover-content"></div></div>';
|
template = '<div id="' + element[0].id + '_popover_container" class="popover" role="tooltip"><div class="arrow"></div><h3 id="' + element[0].id + '_popover_title" class="popover-title"></h3><div id="' + element[0].id + '_popover_content" class="popover-content"></div></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scope.triggerPopover = function(e){
|
||||||
|
showPopover(e);
|
||||||
|
};
|
||||||
|
|
||||||
if (attrs.awPopOverWatch) {
|
if (attrs.awPopOverWatch) {
|
||||||
$(element).popover({
|
$(element).popover({
|
||||||
placement: placement,
|
placement: placement,
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ angular.module('GeneratorHelpers', [systemStatus.name])
|
|||||||
} else if (field.link || (field.key && (field.link === undefined || field.link))) {
|
} else if (field.link || (field.key && (field.link === undefined || field.link))) {
|
||||||
html += "<a href=\"#/" + base + "/{{" + list.iterator + ".id }}\" ";
|
html += "<a href=\"#/" + base + "/{{" + list.iterator + ".id }}\" ";
|
||||||
} else {
|
} else {
|
||||||
html += "<a href=\"\">";
|
html += "<a href=\"\"";
|
||||||
}
|
}
|
||||||
if (field.awDroppable) {
|
if (field.awDroppable) {
|
||||||
html += Attr(field, 'awDroppable');
|
html += Attr(field, 'awDroppable');
|
||||||
@@ -394,7 +394,7 @@ angular.module('GeneratorHelpers', [systemStatus.name])
|
|||||||
if (field.awPopOver) {
|
if (field.awPopOver) {
|
||||||
html += "aw-pop-over=\"" + field.awPopOver + "\" ";
|
html += "aw-pop-over=\"" + field.awPopOver + "\" ";
|
||||||
html += (field.dataPlacement) ? "data-placement=\"" + field.dataPlacement + "\" " : "";
|
html += (field.dataPlacement) ? "data-placement=\"" + field.dataPlacement + "\" " : "";
|
||||||
html += (field.dataTitle) ? "data-title=\"" + field.dataTitle + "\" " : "";
|
html += (field.dataTitle) ? "over-title=\"" + field.dataTitle + "\" " : "";
|
||||||
}
|
}
|
||||||
html += (field.ngClass) ? Attr(field, 'ngClass') : '';
|
html += (field.ngClass) ? Attr(field, 'ngClass') : '';
|
||||||
html += (field.ngEllipsis) ? "data-ng-bind=\"" + list.iterator + "." + fld + "\" data-ellipsis " : "";
|
html += (field.ngEllipsis) ? "data-ng-bind=\"" + list.iterator + "." + fld + "\" data-ellipsis " : "";
|
||||||
|
|||||||
Reference in New Issue
Block a user