Inventory page, group status now working.

This commit is contained in:
Chris Houseknecht
2014-04-04 03:34:18 -04:00
parent 748e82cc8a
commit 5a6bbfee8e
9 changed files with 184 additions and 85 deletions

View File

@@ -10,9 +10,9 @@
'use strict'; 'use strict';
function InventoriesList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, InventoryList, GenerateList, function InventoriesList($scope, $rootScope, $location, $log, $routeParams, $compile, $filter, Rest, Alert, InventoryList, GenerateList,
LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, Wait, Stream, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, Wait, Stream,
EditInventoryProperties, Find) { EditInventoryProperties, Find, Empty, LogViewer) {
//ClearScope(); //ClearScope();
@@ -22,7 +22,7 @@ function InventoriesList($scope, $rootScope, $location, $log, $routeParams, Rest
paths = $location.path().replace(/^\//, '').split('/'), paths = $location.path().replace(/^\//, '').split('/'),
mode = (paths[0] === 'inventories') ? 'edit' : 'select'; mode = (paths[0] === 'inventories') ? 'edit' : 'select';
view.inject(InventoryList, { mode: mode, $scope: $scope }); view.inject(InventoryList, { mode: mode, scope: $scope });
$rootScope.flashMessage = null; $rootScope.flashMessage = null;
SearchInit({ SearchInit({
@@ -82,30 +82,6 @@ function InventoriesList($scope, $rootScope, $location, $log, $routeParams, Rest
LoadBreadCrumbs(); LoadBreadCrumbs();
if ($scope.removeBuildPopover) {
$scope.removeBuildPopover();
}
$scope.removeBuildPopover = $scope.$on('BuildPopover', function(e, data) {
var inventory, html = '';
if (data.count) {
inventory = Find({ list: $scope.inventories, key: 'id', val: data.results[0].inventory });
html += "<table class=\"table table-condensed flyout\" style=\"width: 100%\">" +
"<thead>" +
"<tr><th>Group</th><th>Source</th><th>Last Run</th><th>Status</th></tr>" +
"</thead>" +
"<tbody>";
data.results.forEach(function(row) {
html += "<tr><td>" + row.summary_fields.group.name + "</td>" +
"<td>" + row.source + "</td>" +
"<td>" + row.last_update + "</td>" +
"<td><i class=\"fa icon-job-" + row.status + "</i></td></tr>";
});
html += "</tbody></table>\n";
html += "<div class=\"popover-footer\"><span class=\"key\">esc</span> or click to close</div>\n";
inventory.syncPopOver = "bob was here!"; //html;
}
});
if ($scope.removePostRefresh) { if ($scope.removePostRefresh) {
$scope.removePostRefresh(); $scope.removePostRefresh();
} }
@@ -141,14 +117,6 @@ function InventoriesList($scope, $rootScope, $location, $log, $routeParams, Rest
$scope.inventories[idx].hostsStatus = 'successful'; $scope.inventories[idx].hostsStatus = 'successful';
$scope.inventories[idx].hostsTip = 'No hosts with failures. Click for details.'; $scope.inventories[idx].hostsTip = 'No hosts with failures. Click for details.';
} }
if (inventory.has_inventory_sources) {
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('BuildPopover', data);
});
}
}); });
}); });
@@ -160,6 +128,92 @@ function InventoriesList($scope, $rootScope, $location, $log, $routeParams, Rest
$scope.search(list.iterator); $scope.search(list.iterator);
}); });
if ($scope.removeGroupSummaryReady) {
$scope.removeGroupSummaryReady();
}
$scope.removeGroupSummaryReady = $scope.$on('GroupSummaryReady', function(e, event, inventory, data) {
var j, elem, html, title, row;
function ellipsis(a) {
if (a.length > 20) {
return a.substr(0,20) + '...';
}
return a;
}
if (data.count) {
html = "<table class=\"table table-condensed flyout\" style=\"width: 100%\">\n";
html += "<thead>\n";
html += "<tr>\n";
html += "<th>Status</th>\n";
html += "<th>Group</th>\n";
html += "<th>Last Sync</th>\n";
html += "</tr>\n";
html += "</thead>\n";
html += "<tbody>\n";
for (j=0; j < data.results.length; j++) {
row = data.results[j];
html += "<tr>";
html += "<td><a href=\"\" ng-click=\"viewJob('" + row.related.last_update + "')\" aw-tool-tip=\"Click to view details\" aw-tip-placement=\"top\"><i class=\"fa icon-job-" + row.status + "\"></i></a></td>";
html += "<td><a href=\"\" ng-click=\"viewJob('" + row.related.last_update + "')\" aw-tool-tip=\"Click to view details\" aw-tip-placement=\"top\">" + ellipsis(row.summary_fields.group.name) + "</a></td>";
html += "<td>" + $filter('date')(row.last_updated,'MM/dd HH:mm:ss') + "</td>";
html += "</tr>\n";
}
html += "</tbody>\n";
html += "</table>\n";
html += "<div class=\"popover-footer\"><span class=\"key\">esc</span> or click to close</div>\n";
title = "Sync Status";
elem = $(event.target).parent();
try {
elem.tooltip('hide');
elem.popover('destroy');
}
catch(err) {
//ignore
}
elem.attr({ "aw-pop-over": html, "data-title": title, "data-placement": "right" });
Wait('stop');
$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() {
elem.popover('hide');
});
});
elem.popover('show');
}
});
$scope.showGroupSummary = function(event, id) {
var inventory;
if (!Empty(id)) {
inventory = Find({ list: $scope.inventories, key: 'id', val: id });
if (inventory.syncStatus !== 'na') {
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.viewJob = function(url) {
LogViewer({
scope: $scope,
url: url
});
};
$scope.showActivity = function () { $scope.showActivity = function () {
Stream({ scope: $scope }); Stream({ scope: $scope });
}; };
@@ -190,7 +244,6 @@ function InventoriesList($scope, $rootScope, $location, $log, $routeParams, Rest
$scope.search(list.iterator); $scope.search(list.iterator);
}) })
.error(function (data, status) { .error(function (data, status) {
Wait('stop');
ProcessErrors( $scope, data, status, null, { hdr: 'Error!', ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status
}); });
@@ -199,7 +252,7 @@ function InventoriesList($scope, $rootScope, $location, $log, $routeParams, Rest
Prompt({ Prompt({
hdr: 'Delete', hdr: 'Delete',
body: '<div class=\"alert alert-info\">Are you sure you want to delete ' + name + '?</div>', body: '<div class=\"alert alert-info\">Delete inventory ' + name + '?</div>',
action: action action: action
}); });
}; };
@@ -223,9 +276,9 @@ function InventoriesList($scope, $rootScope, $location, $log, $routeParams, Rest
}; };
} }
InventoriesList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'InventoryList', 'GenerateList', InventoriesList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', '$compile', '$filter', 'Rest', 'Alert', 'InventoryList', 'GenerateList',
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
'GetBasePath', 'Wait', 'Stream', 'EditInventoryProperties', 'Find' 'GetBasePath', 'Wait', 'Stream', 'EditInventoryProperties', 'Find', 'Empty', 'LogViewer'
]; ];
@@ -340,7 +393,7 @@ function InventoriesEdit($scope, $location, $routeParams, $compile, GenerateList
GetSyncStatusMsg, InjectHosts, HostsReload, GroupsEdit, GroupsDelete, Breadcrumbs, LoadBreadCrumbs, Empty, Rest, ProcessErrors, GetSyncStatusMsg, InjectHosts, HostsReload, GroupsEdit, GroupsDelete, Breadcrumbs, LoadBreadCrumbs, Empty, Rest, ProcessErrors,
InventoryUpdate, Alert, ToggleChildren, ViewUpdateStatus, GroupsCancelUpdate, Find, EditInventoryProperties, HostsEdit, InventoryUpdate, Alert, ToggleChildren, ViewUpdateStatus, GroupsCancelUpdate, Find, EditInventoryProperties, HostsEdit,
HostsDelete, ToggleHostEnabled, CopyMoveGroup, CopyMoveHost, Stream, GetBasePath, ShowJobSummary, ApplyEllipsis, WatchInventoryWindowResize, HostsDelete, ToggleHostEnabled, CopyMoveGroup, CopyMoveHost, Stream, GetBasePath, ShowJobSummary, ApplyEllipsis, WatchInventoryWindowResize,
HelpDialog, InventoryGroupsHelp, Store) { HelpDialog, InventoryGroupsHelp, Store, ViewJob) {
ClearScope(); ClearScope();
@@ -665,6 +718,10 @@ function InventoriesEdit($scope, $location, $routeParams, $compile, GenerateList
HelpDialog(opts); HelpDialog(opts);
}; };
$scope.viewJob = function(id) {
ViewJob({ scope: $scope, id: id });
};
//Load tree data for the first time //Load tree data for the first time
BuildTree({ BuildTree({
scope: $scope, scope: $scope,
@@ -678,5 +735,6 @@ InventoriesEdit.$inject = ['$scope', '$location', '$routeParams', '$compile', 'G
'BuildTree', 'Wait', 'GetSyncStatusMsg', 'InjectHosts', 'HostsReload', 'GroupsEdit', 'GroupsDelete', 'Breadcrumbs', 'BuildTree', 'Wait', 'GetSyncStatusMsg', 'InjectHosts', 'HostsReload', 'GroupsEdit', 'GroupsDelete', 'Breadcrumbs',
'LoadBreadCrumbs', 'Empty', 'Rest', 'ProcessErrors', 'InventoryUpdate', 'Alert', 'ToggleChildren', 'ViewUpdateStatus', 'GroupsCancelUpdate', 'LoadBreadCrumbs', 'Empty', 'Rest', 'ProcessErrors', 'InventoryUpdate', 'Alert', 'ToggleChildren', 'ViewUpdateStatus', 'GroupsCancelUpdate',
'Find', 'EditInventoryProperties', 'HostsEdit', 'HostsDelete', 'ToggleHostEnabled', 'CopyMoveGroup', 'CopyMoveHost', 'Find', 'EditInventoryProperties', 'HostsEdit', 'HostsDelete', 'ToggleHostEnabled', 'CopyMoveGroup', 'CopyMoveHost',
'Stream', 'GetBasePath', 'ShowJobSummary', 'ApplyEllipsis', 'WatchInventoryWindowResize', 'HelpDialog', 'InventoryGroupsHelp', 'Store' 'Stream', 'GetBasePath', 'ShowJobSummary', 'ApplyEllipsis', 'WatchInventoryWindowResize', 'HelpDialog', 'InventoryGroupsHelp', 'Store',
'ViewJob'
]; ];

View File

@@ -414,7 +414,13 @@ ToggleSchedule, DeleteSchedule, GetBasePath, SchedulesListInit) {
schedule_scope.search(list.iterator); schedule_scope.search(list.iterator);
}); });
schedule_scope.toggleSchedule = function(id) { schedule_scope.toggleSchedule = function(event, id) {
try {
$(event.target).tooltip('hide');
}
catch(e) {
// ignore
}
ToggleSchedule({ ToggleSchedule({
scope: schedule_scope, scope: schedule_scope,
id: id, id: id,

View File

@@ -14,7 +14,7 @@
angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'HostListDefinition', angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'HostListDefinition',
'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'AuthService', 'HostsHelper', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'AuthService', 'HostsHelper',
'InventoryHelper', 'RelatedSearchHelper', 'InventoryFormDefinition', 'SelectionHelper', 'InventoryHelper', 'RelatedSearchHelper', 'InventoryFormDefinition', 'SelectionHelper',
'HostGroupsFormDefinition', 'VariablesHelper', 'ModalDialog' 'HostGroupsFormDefinition', 'VariablesHelper', 'ModalDialog', 'LogViewerHelper'
]) ])
.factory('SetEnabledMsg', [ function() { .factory('SetEnabledMsg', [ function() {
@@ -69,16 +69,23 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
return a; return a;
} }
function noRecentJobs() {
title = 'No job data';
html = "<p>No recent job data available for this host.</p>\n" +
"<div class=\"popover-footer\"><span class=\"key\">esc</span> or click to close</div>\n";
}
function setMsg(host) { function setMsg(host) {
var j, job, jobs; var j, job, jobs;
if (host.has_active_failures === true || (host.has_active_failures === false && host.last_job !== null)) { if (host.has_active_failures === true || (host.has_active_failures === false && host.last_job !== null)) {
if (host.has_active_failures === true) { if (host.has_active_failures === true) {
host.badgeToolTip = 'Most recent job failed. Click to view jobs.'; host.badgeToolTip = 'Most recent job failed. Click to view jobs.';
host.active_failures = 'failed'; host.active_failures = 'error';
} }
else { else {
host.badgeToolTip = "Most recent job successful. Click to view jobs."; host.badgeToolTip = "Most recent job successful. Click to view jobs.";
host.active_failures = 'success'; host.active_failures = 'successful';
} }
if (host.summary_fields.recent_jobs.length > 0) { if (host.summary_fields.recent_jobs.length > 0) {
// build html table of job status info // build html table of job status info
@@ -101,7 +108,7 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
for (j=0; j < jobs.length; j++) { for (j=0; j < jobs.length; j++) {
job = jobs[j]; job = jobs[j];
html += "<tr>\n"; html += "<tr>\n";
html += "<td><a href=\"/#/jobs/" + job.id + "\">" + job.id + "</a></td>\n"; html += "<td><a href=\"\" ng-click=\"viewJob(" + job.id + ")\">" + job.id + "</a></td>\n";
html += "<td class=\"text-center\"><a ng-click=\"showJobSummary(" + job.id + ")\" " + html += "<td class=\"text-center\"><a ng-click=\"showJobSummary(" + job.id + ")\" " +
"aw-tool-tip=\"" + job.status.charAt(0).toUpperCase() + job.status.slice(1) + "aw-tool-tip=\"" + job.status.charAt(0).toUpperCase() + job.status.slice(1) +
". Click for details\" data-placement=\"top\"><i class=\"fa icon-job-" + ". Click for details\" data-placement=\"top\"><i class=\"fa icon-job-" +
@@ -116,15 +123,13 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
html += "<div class=\"popover-footer\"><span class=\"key\">esc</span> or click to close</div>\n"; html += "<div class=\"popover-footer\"><span class=\"key\">esc</span> or click to close</div>\n";
} }
else { else {
title = 'No job data'; noRecentJobs();
html = '<p>No recent job data available for this host.</p>';
html += "<div class=\"popover-footer\"><span class=\"key\">esc</span> or click to close</div>\n";
} }
} }
else if (host.has_active_failures === false && host.last_job === null) { else if (host.has_active_failures === false && host.last_job === null) {
host.has_active_failures = 'none';
host.badgeToolTip = "No job data available."; host.badgeToolTip = "No job data available.";
host.active_failures = 'n/a'; host.active_failures = 'none';
noRecentJobs();
} }
host.job_status_html = html; host.job_status_html = html;
host.job_status_title = title; host.job_status_title = title;
@@ -146,6 +151,17 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
}; };
}]) }])
.factory('ViewJob', ['LogViewer', 'GetBasePath', function(LogViewer, GetBasePath) {
return function(params) {
var scope = params.scope,
id = params.id;
LogViewer({
scope: scope,
url: GetBasePath('jobs') + id + '/'
});
};
}])
.factory('HostsReload', [ '$routeParams', 'Empty', 'InventoryHosts', 'GetBasePath', 'SearchInit', 'PaginateInit', 'Wait', .factory('HostsReload', [ '$routeParams', 'Empty', 'InventoryHosts', 'GetBasePath', 'SearchInit', 'PaginateInit', 'Wait',
'SetHostStatus', 'SetStatus', 'ApplyEllipsis', 'SetHostStatus', 'SetStatus', 'ApplyEllipsis',
function($routeParams, Empty, InventoryHosts, GetBasePath, SearchInit, PaginateInit, Wait, SetHostStatus, SetStatus, function($routeParams, Empty, InventoryHosts, GetBasePath, SearchInit, PaginateInit, Wait, SetHostStatus, SetStatus,
@@ -252,9 +268,8 @@ function(GetBasePath, Rest, Wait, ProcessErrors, Alert, Find, SetEnabledMsg) {
}); });
} }
else { else {
Alert('Action Not Allowed', 'This host is part of a cloud inventory. It can only be disabled in the cloud.' + Alert('Action Not Allowed', 'This host is managed by an external cloud source. Disable it at the external source, ' +
' After disabling it, run an inventory sync to see the new status reflected here.', 'and then run an inventory sync to update Tower with the new status.', 'alert-info');
'alert-info');
} }
}; };
}]) }])

View File

@@ -33,6 +33,25 @@ angular.module('LogViewerHelper', ['ModalDialog', 'Utilities', 'FormGenerator',
scope.removeJobReady = scope.$on('JobReady', function(e, data) { scope.removeJobReady = scope.$on('JobReady', function(e, data) {
var key, resizeText, elem; var key, resizeText, elem;
$('#status-form-container').empty();
$('#options-form-container').empty();
$('#stdout-form-container').empty();
$('#traceback-form-container').empty();
$('#variables-container').empty();
$('#source-container').empty();
$('#logview-tabs li:eq(1)').hide();
$('#logview-tabs li:eq(2)').hide();
$('#logview-tabs li:eq(4)').hide();
$('#logview-tabs li:eq(5)').hide();
// Make sure subsequenct scope references don't bubble up to the parent
for (key in LogViewerStatusForm.fields) {
scope[key] = '';
}
for (key in LogViewerOptionsForm.fields) {
scope[key] = '';
}
for (key in data) { for (key in data) {
scope[key] = data[key]; scope[key] = data[key];
} }
@@ -47,9 +66,6 @@ angular.module('LogViewerHelper', ['ModalDialog', 'Utilities', 'FormGenerator',
val: data.result_stdout val: data.result_stdout
}); });
} }
else {
$('#logview-tabs li:eq(1)').hide();
}
if (data.result_traceback) { if (data.result_traceback) {
$('#logview-tabs li:eq(2)').show(); $('#logview-tabs li:eq(2)').show();
@@ -58,9 +74,6 @@ angular.module('LogViewerHelper', ['ModalDialog', 'Utilities', 'FormGenerator',
val: data.result_traceback val: data.result_traceback
}); });
} }
else {
$('#logview-tabs li:eq(2)').hide();
}
/*if (data.job_env) { /*if (data.job_env) {
EnvTable({ EnvTable({
@@ -77,9 +90,6 @@ angular.module('LogViewerHelper', ['ModalDialog', 'Utilities', 'FormGenerator',
val: ParseVariableString(data.extra_vars) val: ParseVariableString(data.extra_vars)
}); });
} }
else {
$('#logview-tabs li:eq(4)').hide();
}
if (data.source_vars) { if (data.source_vars) {
$('#logview-tabs li:eq(5)').show(); $('#logview-tabs li:eq(5)').show();
@@ -89,9 +99,6 @@ angular.module('LogViewerHelper', ['ModalDialog', 'Utilities', 'FormGenerator',
val: ParseVariableString(data.source_vars) val: ParseVariableString(data.source_vars)
}); });
} }
else {
$('#logview-tabs li:eq(5)').hide();
}
if (!Empty(scope.source)) { if (!Empty(scope.source)) {
if (scope.removeChoicesReady) { if (scope.removeChoicesReady) {
@@ -179,6 +186,7 @@ angular.module('LogViewerHelper', ['ModalDialog', 'Utilities', 'FormGenerator',
onResizeStop: resizeText, onResizeStop: resizeText,
onOpen: function() { onOpen: function() {
$('#logview-tabs a:first').tab('show'); $('#logview-tabs a:first').tab('show');
$('#dialog-ok-button').focus();
resizeText(); resizeText();
} }
}); });

View File

@@ -342,12 +342,12 @@ angular.module('SchedulesHelper', [ 'Utilities', 'RestServices', 'SchedulesHelpe
Rest.setUrl(url); Rest.setUrl(url);
Rest.get() Rest.get()
.success(function(data) { .success(function(data) {
scope.$emit('ScheduleFound', data); scope.$emit('ScheduleFound', data);
}) })
.error(function(data,status){ .error(function(data,status){
ProcessErrors(scope, data, status, null, { hdr: 'Error!', ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve schedule ' + id + ' GET returned: ' + status }); msg: 'Failed to retrieve schedule ' + id + ' GET returned: ' + status });
}); });
}; };
}]) }])
@@ -390,7 +390,12 @@ angular.module('SchedulesHelper', [ 'Utilities', 'RestServices', 'SchedulesHelpe
scope.$emit(callback, id); scope.$emit(callback, id);
}) })
.error(function (data, status) { .error(function (data, status) {
$('#prompt-modal').modal('hide'); try {
$('#prompt-modal').modal('hide');
}
catch(e) {
// ignore
}
ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url + ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url +
' failed. DELETE returned: ' + status }); ' failed. DELETE returned: ' + status });
}); });

View File

@@ -32,14 +32,12 @@ angular.module('InventoriesListDefinition', [])
icon: "{{ 'icon-cloud-' + inventory.syncStatus }}", icon: "{{ 'icon-cloud-' + inventory.syncStatus }}",
awToolTip: "{{ inventory.syncTip }}", awToolTip: "{{ inventory.syncTip }}",
awTipPlacement: "top", awTipPlacement: "top",
awPopOver: "{{ inventory.syncPopOver }}", ngClick: "showGroupSummary($event, inventory.id)"
dataPlacement: "right"
},{ },{
icon: "{{ 'icon-job-' + inventory.hostsStatus }}", icon: "{{ 'icon-job-' + inventory.hostsStatus }}",
awToolTip: "{{ inventory.hostsTip }}", awToolTip: "{{ inventory.hostsTip }}",
awTipPlacement: "top", awTipPlacement: "top",
awPopOver: "{{ inventory.hostsPopOver }}", ngClick: "showHostSummary($event, inventory.id)"
dataPlacement: "right"
}] }]
}, },
name: { name: {
@@ -106,7 +104,7 @@ angular.module('InventoriesListDefinition', [])
}, },
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "deleteInventory(inventory.id, inventory.names)", ngClick: "deleteInventory(inventory.id, inventory.name)",
awToolTip: 'Delete inventory', awToolTip: 'Delete inventory',
dataPlacement: 'top' dataPlacement: 'top'
} }

View File

@@ -63,7 +63,7 @@ angular.module('InventoryHostsDefinition', [])
awToolTip: "{{ host.badgeToolTip }}", awToolTip: "{{ host.badgeToolTip }}",
awTipPlacement: 'top', awTipPlacement: 'top',
dataPlacement: 'left', dataPlacement: 'left',
iconClass: "{{ 'fa icon-failures-' + host.has_active_failures }}", iconClass: "{{ 'fa icon-job-' + host.active_failures }}",
id: 'active-failutes-action' id: 'active-failutes-action'
}, },
edit: { edit: {

View File

@@ -137,6 +137,14 @@ angular.module('ModalDialog', ['Utilities', 'ParseHelper'])
} }
}, },
open: function () { open: function () {
$('.tooltip').each(function () {
// Remove any lingering tooltip <div> elements
$(this).remove();
});
$('.popover').each(function () {
// remove lingering popover <div> elements
$(this).remove();
});
if (onOpen) { if (onOpen) {
onOpen(); onOpen();
} }

View File

@@ -1,3 +1,4 @@
<div class="tab-pane" id="inventories"> <div class="tab-pane" id="inventories">
<div ng-cloak id="htmlTemplate"></div> <div ng-cloak id="htmlTemplate"></div>
<div ng-include="'/static/partials/logviewer.html'"></div>
</div> </div>