Merge branch 'inventories-refactor' of https://github.com/mabashian/ansible-tower into mabashian-inventories-refactor

# Conflicts:
#	awx/ui/client/src/inventories/sources/add/sources-add.controller.js
#	awx/ui/client/src/inventories/sources/edit/sources-edit.controller.js
#	awx/ui/client/src/inventories/sources/list/sources-list.controller.js
This commit is contained in:
Michael Abashian 2017-05-30 15:05:35 -04:00
commit 641823e82e
40 changed files with 632 additions and 486 deletions

View File

@ -1032,12 +1032,6 @@ input[type="checkbox"].checkbox-no-label {
border-top: none;
}
/* Less padding on .table-condensed */
.table-condensed>tbody>tr>td,
.table-condensed>thead>tr>th {
padding: 0.5em 0.6em;
}
.table > tbody > tr > td{
padding: 0.5em 0.6em;
&.actions{
@ -1049,6 +1043,17 @@ input[type="checkbox"].checkbox-no-label {
}
}
/* Less padding on .table-condensed */
.table-condensed>tbody>tr>td:not(:last-child),
.table-condensed>thead>tr>th:not(:last-child) {
padding: 0.5em 20px 0.5em 0px;
}
.table-condensed>tbody>tr>td:last-child,
.table-condensed>thead>tr>th:last-child {
padding: 0.5em 0px;
}
.table.table-condensed.flyout {
thead>tr>th {
padding-left: 0;

View File

@ -7,20 +7,34 @@
export default
['$scope', '$state', '$stateParams', 'GroupManageService', 'CopyMoveGroupList', 'group', 'Dataset', '$rootScope',
function($scope, $state, $stateParams, GroupManageService, CopyMoveGroupList, group, Dataset, $rootScope){
var list = CopyMoveGroupList;
let list = CopyMoveGroupList;
function init(){
$scope.atRootLevel = $stateParams.group ? false : true;
// search init
$scope.list = list;
$scope[`${list.iterator}_dataset`] = Dataset.data;
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
$scope.item = group;
$rootScope.breadcrumb.copyMoveName = group.name;
$scope.submitMode = $stateParams.groups === undefined ? 'move' : 'copy';
}
init();
$scope.item = group;
$rootScope.breadcrumb.copyMoveName = group.name;
$scope.submitMode = $stateParams.groups === undefined ? 'move' : 'copy';
$scope.toggle_row = function(id){
// toggle off anything else currently selected
_.forEach($scope.groups, (item) => {return item.id === id ? item.checked = 1 : item.checked = null;});
// yoink the currently selected thing
$scope.selected = _.find($scope.groups, (item) => {return item.id === id;});
};
$scope.formCancel = function(){
$state.go('^');
};
$scope.formSave = function(){
switch($scope.submitMode) {
case 'copy':
@ -48,6 +62,7 @@
}
}
};
$scope.toggleTargetRootGroup = function(){
$scope.selected = !$scope.selected;
// cannot perform copy operations to root group level
@ -60,14 +75,4 @@
});
};
function init(){
$scope.atRootLevel = $stateParams.group ? false : true;
// search init
$scope.list = list;
$scope[`${list.iterator}_dataset`] = Dataset.data;
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
}
init();
}];

View File

@ -7,11 +7,21 @@
export default
['$scope', '$state', '$stateParams', 'HostManageService', 'CopyMoveGroupList', 'host', 'Dataset', '$rootScope',
function($scope, $state, $stateParams, HostManageService, CopyMoveGroupList, host, Dataset, $rootScope){
var list = CopyMoveGroupList;
let list = CopyMoveGroupList;
let init = function(){
// search init
$scope.list = list;
$scope[`${list.iterator}_dataset`] = Dataset.data;
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
$scope.item = host;
$rootScope.breadcrumb.copyMoveName = host.name;
$scope.submitMode = 'copy';
};
init();
$scope.item = host;
$rootScope.breadcrumb.copyMoveName = host.name;
$scope.submitMode = 'copy';
$scope.toggle_row = function(id){
// toggle off anything else currently selected
_.forEach($scope.groups, (item) => {return item.id === id ? item.checked = 1 : item.checked = null;});
@ -40,12 +50,4 @@
break;
}
};
var init = function(){
// search init
$scope.list = list;
$scope[`${list.iterator}_dataset`] = Dataset.data;
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
};
init();
}];

View File

@ -6,10 +6,10 @@
export default
['$scope', '$rootScope', '$state', '$stateParams', 'GroupList', 'InventoryUpdate',
'GroupManageService', 'CancelSourceUpdate', 'rbacUiControlService', 'GetBasePath',
'GetHostsStatusMsg', 'Dataset', 'Find', 'QuerySet', 'inventoryData',
'GetHostsStatusMsg', 'Dataset', 'Find', 'QuerySet', 'inventoryData', 'canAdd',
function($scope, $rootScope, $state, $stateParams, GroupList, InventoryUpdate,
GroupManageService, CancelSourceUpdate, rbacUiControlService, GetBasePath,
GetHostsStatusMsg, Dataset, Find, qs, inventoryData){
GetHostsStatusMsg, Dataset, Find, qs, inventoryData, canAdd){
let list = GroupList;
@ -18,12 +18,7 @@
function init(){
$scope.inventory_id = $stateParams.inventory_id;
$scope.canAdhoc = inventoryData.summary_fields.user_capabilities.adhoc;
$scope.canAdd = false;
rbacUiControlService.canAdd(GetBasePath('inventory') + $scope.inventory_id + "/groups")
.then(function(canAdd) {
$scope.canAdd = canAdd;
});
$scope.canAdd = canAdd;
// Search init
$scope.list = list;
@ -36,7 +31,7 @@
}
$scope.inventory_id = $stateParams.inventory_id;
$scope.$watchCollection(list.name, function(){
_.forEach($scope[list.name], buildStatusIndicators);
});

View File

@ -20,6 +20,15 @@ export default {
],
inventoryData: ['InventoryManageService', '$stateParams', function(InventoryManageService, $stateParams) {
return InventoryManageService.getInventory($stateParams.inventory_id).then(res => res.data);
}],
canAdd: ['rbacUiControlService', '$state', 'GetBasePath', '$stateParams', function(rbacUiControlService, $state, GetBasePath, $stateParams) {
return rbacUiControlService.canAdd(GetBasePath('inventory') + $stateParams.inventory_id + "/groups")
.then(function(res) {
return res.canAdd;
})
.catch(function() {
return false;
});
}]
},
params: {

View File

@ -7,11 +7,11 @@
export default ['$state', '$stateParams', '$scope', 'NestedGroupForm',
'ParseTypeChange', 'GenerateForm', 'inventoryData', 'GroupManageService',
'GetChoices', 'GetBasePath', 'CreateSelect2',
'rbacUiControlService', 'ToJSON',
'rbacUiControlService', 'ToJSON', 'canAdd',
function($state, $stateParams, $scope, NestedGroupForm, ParseTypeChange,
GenerateForm, inventoryData, GroupManageService, GetChoices,
GetBasePath, CreateSelect2, rbacUiControlService,
ToJSON) {
ToJSON, canAdd) {
let form = NestedGroupForm;
init();
@ -19,11 +19,7 @@ export default ['$state', '$stateParams', '$scope', 'NestedGroupForm',
function init() {
// apply form definition's default field values
GenerateForm.applyDefaults(form, $scope);
rbacUiControlService.canAdd(GetBasePath('inventory') + $stateParams.inventory_id + "/groups")
.then(function(canAdd) {
$scope.canAdd = canAdd;
});
$scope.canAdd = canAdd;
$scope.parseType = 'yaml';
$scope.envParseType = 'yaml';
ParseTypeChange({

View File

@ -18,5 +18,16 @@ export default {
},
controller: 'NestedGroupsAddController'
}
},
resolve: {
canAdd: ['rbacUiControlService', '$state', 'GetBasePath', '$stateParams', function(rbacUiControlService, $state, GetBasePath, $stateParams) {
return rbacUiControlService.canAdd(GetBasePath('inventory') + $stateParams.inventory_id + "/groups")
.then(function(res) {
return res.canAdd;
})
.catch(function() {
return false;
});
}]
}
};

View File

@ -6,10 +6,10 @@
export default
['$scope', '$rootScope', '$state', '$stateParams', 'NestedGroupListDefinition', 'InventoryUpdate',
'GroupManageService', 'CancelSourceUpdate', 'rbacUiControlService', 'GetBasePath',
'GetHostsStatusMsg', 'Dataset', 'Find', 'QuerySet', 'inventoryData',
'GetHostsStatusMsg', 'Dataset', 'Find', 'QuerySet', 'inventoryData', 'canAdd',
function($scope, $rootScope, $state, $stateParams, NestedGroupListDefinition, InventoryUpdate,
GroupManageService, CancelSourceUpdate, rbacUiControlService, GetBasePath,
GetHostsStatusMsg, Dataset, Find, qs, inventoryData){
GetHostsStatusMsg, Dataset, Find, qs, inventoryData, canAdd){
let list = NestedGroupListDefinition;
@ -18,12 +18,7 @@
function init(){
$scope.inventory_id = $stateParams.inventory_id;
$scope.canAdhoc = inventoryData.summary_fields.user_capabilities.adhoc;
$scope.canAdd = false;
rbacUiControlService.canAdd(GetBasePath('inventory') + $scope.inventory_id + "/groups")
.then(function(canAdd) {
$scope.canAdd = canAdd;
});
$scope.canAdd = canAdd;
// Search init
$scope.list = list;

View File

@ -59,6 +59,15 @@ export default {
inventoryData: ['InventoryManageService', '$stateParams', 'host', function(InventoryManageService, $stateParams, host) {
var id = ($stateParams.inventory_id) ? $stateParams.inventory_id : host.summary_fields.inventory.id;
return InventoryManageService.getInventory(id).then(res => res.data);
}],
canAdd: ['rbacUiControlService', '$state', 'GetBasePath', '$stateParams', function(rbacUiControlService, $state, GetBasePath, $stateParams) {
return rbacUiControlService.canAdd(GetBasePath('inventory') + $stateParams.inventory_id + "/groups")
.then(function(res) {
return res.canAdd;
})
.catch(function() {
return false;
});
}]
}
};

View File

@ -18,5 +18,16 @@ export default {
},
controller: 'RelatedHostAddController'
}
},
resolve: {
canAdd: ['rbacUiControlService', 'GetBasePath', '$stateParams', function(rbacUiControlService, GetBasePath, $stateParams) {
return rbacUiControlService.canAdd(GetBasePath('inventory') + $stateParams.inventory_id + "/hosts")
.then(function(res) {
return res.canAdd;
})
.catch(function() {
return false;
});
}]
}
};

View File

@ -6,24 +6,19 @@
export default ['$scope', 'NestedHostsListDefinition', '$rootScope', 'GetBasePath',
'rbacUiControlService', 'Dataset', '$state', '$filter', 'Prompt', 'Wait',
'HostManageService', 'SetStatus',
'HostManageService', 'SetStatus', 'canAdd',
function($scope, NestedHostsListDefinition, $rootScope, GetBasePath,
rbacUiControlService, Dataset, $state, $filter, Prompt, Wait,
HostManageService, SetStatus) {
HostManageService, SetStatus, canAdd) {
let list = NestedHostsListDefinition;
init();
function init(){
$scope.canAdd = false;
$scope.canAdd = canAdd;
$scope.enableSmartInventoryButton = false;
rbacUiControlService.canAdd('hosts')
.then(function(canAdd) {
$scope.canAdd = canAdd;
});
// Search init
$scope.list = list;
$scope[`${list.iterator}_dataset`] = Dataset.data;

View File

@ -53,6 +53,15 @@ export default {
],
inventoryData: ['InventoryManageService', '$stateParams', function(InventoryManageService, $stateParams) {
return InventoryManageService.getInventory($stateParams.inventory_id).then(res => res.data);
}],
canAdd: ['rbacUiControlService', function(rbacUiControlService) {
return rbacUiControlService.canAdd('hosts')
.then(function(res) {
return res.canAdd;
})
.catch(function() {
return false;
});
}]
}
};

View File

@ -7,21 +7,16 @@
function HostsList($scope, HostsList, $rootScope, GetBasePath,
rbacUiControlService, Dataset, $state, $filter, Prompt, Wait,
HostManageService, SetStatus) {
HostManageService, SetStatus, canAdd) {
let list = HostsList;
init();
function init(){
$scope.canAdd = false;
$scope.canAdd = canAdd;
$scope.enableSmartInventoryButton = false;
rbacUiControlService.canAdd('hosts')
.then(function(canAdd) {
$scope.canAdd = canAdd;
});
// Search init
$scope.list = list;
$scope[`${list.iterator}_dataset`] = Dataset.data;
@ -141,5 +136,5 @@ function HostsList($scope, HostsList, $rootScope, GetBasePath,
export default ['$scope', 'HostsList', '$rootScope', 'GetBasePath',
'rbacUiControlService', 'Dataset', '$state', '$filter', 'Prompt', 'Wait',
'HostManageService', 'SetStatus', HostsList
'HostManageService', 'SetStatus', 'canAdd', HostsList
];

View File

@ -29,6 +29,15 @@ export default {
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
return qs.search(path, $stateParams[`${list.iterator}_search`]);
}
]
],
canAdd: ['rbacUiControlService', function(rbacUiControlService) {
return rbacUiControlService.canAdd('inventory')
.then(function(res) {
return res.canAdd;
})
.catch(function() {
return false;
});
}]
}
};

View File

@ -27,6 +27,7 @@ export default ['i18n', function(i18n) {
ngClick: "null",
iconOnly: true,
excludeModal: true,
template: `<source-summary-popover inventory="inventory"></source-summary-popover><host-summary-popover inventory="inventory"></host-summary-popover>`,
icons: [{
icon: "{{ 'icon-cloud-' + inventory.syncStatus }}",
awToolTip: "{{ inventory.syncTip }}",
@ -85,7 +86,7 @@ export default ['i18n', function(i18n) {
ngShow: 'canAddInventory'
}
],
ngShow: 'canAddInventory || canAddSmartInventory || canAddSCMInventory'
ngShow: 'canAddInventory'
}
},

View File

@ -0,0 +1,26 @@
export default [ '$scope', 'Empty', 'Wait', 'GetBasePath', 'Rest', 'ProcessErrors',
function($scope, Empty, Wait, GetBasePath, Rest, ProcessErrors) {
$scope.gatherRecentJobs = function(event) {
if (!Empty($scope.inventory.id)) {
if ($scope.inventory.total_hosts > 0) {
Wait('start');
let url = GetBasePath('jobs') + "?type=job&inventory=" + $scope.inventory.id + "&failed=";
url += ($scope.inventory.has_active_failures) ? "true" : "false";
url += "&order_by=-finished&page_size=5";
Rest.setUrl(url);
Rest.get()
.success( function(data) {
$scope.generateTable(data, event);
})
.error( function(data, status) {
ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. GET returned: ' + status
});
});
}
}
};
}
];

View File

@ -0,0 +1,94 @@
export default ['templateUrl', 'Wait', '$filter', '$compile',
function(templateUrl, Wait, $filter, $compile) {
return {
restrict: 'E',
replace: false,
scope: {
inventory: '='
},
controller: 'HostSummaryPopoverController',
templateUrl: templateUrl('inventories/list/host-summary-popover/host-summary-popover'),
link: function(scope) {
function ellipsis(a) {
if (a.length > 20) {
return a.substr(0,20) + '...';
}
return a;
}
function attachElem(event, html, title) {
var elem = $(event.target).parent();
try {
elem.tooltip('hide');
elem.popover('destroy');
}
catch(err) {
//ignore
}
$('.popover').each(function() {
// remove lingering popover <div>. Seems to be a bug in TB3 RC1
$(this).remove();
});
$('.tooltip').each( function() {
// close any lingering tool tipss
$(this).hide();
});
elem.attr({
"aw-pop-over": html,
"data-popover-title": title,
"data-placement": "right" });
elem.removeAttr('ng-click');
$compile(elem)(scope);
scope.triggerPopover(event);
}
scope.generateTable = function(data, event){
var html, title = "Recent Jobs";
Wait('stop');
if (data.count > 0) {
html = "<table class=\"table table-condensed flyout\" style=\"width: 100%\">\n";
html += "<thead>\n";
html += "<tr>";
html += "<th>Status</th>";
html += "<th>Finished</th>";
html += "<th>Name</th>";
html += "</tr>\n";
html += "</thead>\n";
html += "<tbody>\n";
data.results.forEach(function(row) {
html += "<tr>\n";
html += "<td><a href=\"#/jobs/" + row.id + "\" " + "aw-tool-tip=\"" + row.status.charAt(0).toUpperCase() + row.status.slice(1) +
". Click for details\" aw-tip-placement=\"top\"><i class=\"fa SmartStatus-tooltip--" + row.status + " icon-job-" + row.status + "\"></i></a></td>\n";
html += "<td>" + ($filter('longDate')(row.finished)) + "</td>";
html += "<td><a href=\"#/jobs/" + row.id + "\" " + "aw-tool-tip=\"" + row.status.charAt(0).toUpperCase() + row.status.slice(1) +
". Click for details\" aw-tip-placement=\"top\">" + $filter('sanitize')(ellipsis(row.name)) + "</a></td>";
html += "</tr>\n";
});
html += "</tbody>\n";
html += "</table>\n";
}
else {
html = "<p>No recent job data available for this inventory.</p>\n";
}
attachElem(event, html, title);
};
scope.showHostSummary = function(event) {
try{
var elem = $(event.target).parent();
// if the popover is visible already, then exit the function here
if(elem.data()['bs.popover'].tip().hasClass('in')){
return;
}
}
catch(err){
scope.gatherRecentJobs(event);
}
};
}
};
}
];

View File

@ -0,0 +1,3 @@
<a href="" ng-click="showHostSummary($event, inventory.id)" ng-class="inventory.host_status_class" >
<i class="fa {{ 'icon-job-' + inventory.hostsStatus }}"></i>
</a>

View File

@ -0,0 +1,7 @@
import directive from './host-summary-popover.directive';
import controller from './host-summary-popover.controller';
export default
angular.module('HostSummaryPopoverModule', [])
.directive('hostSummaryPopover', directive)
.controller('HostSummaryPopoverController', controller);

View File

@ -10,10 +10,10 @@
* @description This controller's for the Inventory page
*/
function InventoriesList($scope, $rootScope, $location,
$compile, $filter, Rest, InventoryList, Prompt,
ProcessErrors, GetBasePath, Wait, Find, Empty, $state,
rbacUiControlService, Dataset, InventoryUpdate) {
function InventoriesList($scope,
$filter, Rest, InventoryList, Prompt,
ProcessErrors, GetBasePath, Wait, $state,
Dataset, InventoryUpdate, canAdd) {
let list = InventoryList,
defaultUrl = GetBasePath('inventory');
@ -21,12 +21,7 @@ function InventoriesList($scope, $rootScope, $location,
init();
function init(){
$scope.canAdd = false;
rbacUiControlService.canAdd('inventory')
.then(function(canAdd) {
$scope.canAddInventory = canAdd;
});
$scope.canAddInventory = canAdd;
$scope.$watchCollection(list.name, function(){
_.forEach($scope[list.name], processInventoryRow);
@ -36,230 +31,43 @@ function InventoriesList($scope, $rootScope, $location,
$scope.list = list;
$scope[`${list.iterator}_dataset`] = Dataset.data;
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
$rootScope.flashMessage = null;
}
function processInventoryRow(inventory) {
buildStatusIndicators(inventory);
buildInventoryTypeLabel(inventory);
}
inventory.launch_class = "";
inventory.host_status_class = "Inventories-hostStatus";
function buildStatusIndicators(inventory){
inventory.launch_class = "";
inventory.host_status_class = "Inventories-hostStatus";
if (inventory.has_inventory_sources) {
if (inventory.inventory_sources_with_failures > 0) {
inventory.syncStatus = 'error';
inventory.syncTip = inventory.inventory_sources_with_failures + ' sources with sync failures. Click for details';
}
else {
inventory.syncStatus = 'successful';
inventory.syncTip = 'No inventory sync failures. Click for details.';
}
if (inventory.has_inventory_sources) {
if (inventory.inventory_sources_with_failures > 0) {
inventory.syncStatus = 'error';
inventory.syncTip = inventory.inventory_sources_with_failures + ' sources with sync failures. Click for details';
}
else {
inventory.syncStatus = 'na';
inventory.syncTip = 'Not configured for inventory sync.';
inventory.launch_class = "btn-disabled";
inventory.syncStatus = 'successful';
inventory.syncTip = 'No inventory sync failures. Click for details.';
}
if (inventory.has_active_failures) {
inventory.hostsStatus = 'error';
inventory.hostsTip = inventory.hosts_with_active_failures + ' hosts with failures. Click for details.';
}
else if (inventory.total_hosts) {
inventory.hostsStatus = 'successful';
inventory.hostsTip = 'No hosts with failures. Click for details.';
}
else {
inventory.hostsStatus = 'none';
inventory.hostsTip = 'Inventory contains 0 hosts.';
}
}
function buildInventoryTypeLabel(inventory) {
inventory.kind_label = inventory.kind === '' ? 'Inventory' : (inventory.kind === 'smart' ? 'Smart Inventory': 'Inventory');
}
function ellipsis(a) {
if (a.length > 20) {
return a.substr(0,20) + '...';
}
return a;
}
function attachElem(event, html, title) {
var elem = $(event.target).parent();
try {
elem.tooltip('hide');
elem.popover('destroy');
}
catch(err) {
//ignore
}
$('.popover').each(function() {
// remove lingering popover <div>. Seems to be a bug in TB3 RC1
$(this).remove();
});
$('.tooltip').each( function() {
// close any lingering tool tipss
$(this).hide();
});
elem.attr({
"aw-pop-over": html,
"data-popover-title": title,
"data-placement": "right" });
elem.removeAttr('ng-click');
$compile(elem)($scope);
$scope.triggerPopover(event);
}
if ($scope.removeHostSummaryReady) {
$scope.removeHostSummaryReady();
}
$scope.removeHostSummaryReady = $scope.$on('HostSummaryReady', function(e, event, data) {
var html, title = "Recent Jobs";
Wait('stop');
if (data.count > 0) {
html = "<table class=\"table table-condensed flyout\" style=\"width: 100%\">\n";
html += "<thead>\n";
html += "<tr>";
html += "<th>Status</th>";
html += "<th>Finished</th>";
html += "<th>Name</th>";
html += "</tr>\n";
html += "</thead>\n";
html += "<tbody>\n";
data.results.forEach(function(row) {
html += "<tr>\n";
html += "<td><a href=\"#/jobs/" + row.id + "\" " + "aw-tool-tip=\"" + row.status.charAt(0).toUpperCase() + row.status.slice(1) +
". Click for details\" aw-tip-placement=\"top\"><i class=\"fa SmartStatus-tooltip--" + row.status + " icon-job-" + row.status + "\"></i></a></td>\n";
html += "<td>" + ($filter('longDate')(row.finished)).replace(/ /,'<br />') + "</td>";
html += "<td><a href=\"#/jobs/" + row.id + "\" " + "aw-tool-tip=\"" + row.status.charAt(0).toUpperCase() + row.status.slice(1) +
". Click for details\" aw-tip-placement=\"top\">" + $filter('sanitize')(ellipsis(row.name)) + "</a></td>";
html += "</tr>\n";
});
html += "</tbody>\n";
html += "</table>\n";
}
else {
html = "<p>No recent job data available for this inventory.</p>\n";
inventory.syncStatus = 'na';
inventory.syncTip = 'Not configured for inventory sync.';
inventory.launch_class = "btn-disabled";
}
attachElem(event, html, title);
});
if ($scope.removeSourceSummaryReady) {
$scope.removeSourceSummaryReady();
if (inventory.has_active_failures) {
inventory.hostsStatus = 'error';
inventory.hostsTip = inventory.hosts_with_active_failures + ' hosts with failures. Click for details.';
}
else if (inventory.total_hosts) {
inventory.hostsStatus = 'successful';
inventory.hostsTip = 'No hosts with failures. Click for details.';
}
else {
inventory.hostsStatus = 'none';
inventory.hostsTip = 'Inventory contains 0 hosts.';
}
inventory.kind_label = inventory.kind === '' ? 'Inventory' : (inventory.kind === 'smart' ? 'Smart Inventory': 'Inventory');
}
$scope.removeSourceSummaryReady = $scope.$on('SourceSummaryReady', function(e, event, inventory, data) {
var html, title;
Wait('stop');
// Build the html for our popover
html = "<table class=\"table table-condensed flyout\" style=\"width: 100%\">\n";
html += "<thead>\n";
html += "<tr>";
html += "<th>Status</th>";
html += "<th>Last Sync</th>";
html += "<th>Source</th>";
html += "</tr>";
html += "</thead>\n";
html += "<tbody>\n";
data.results.forEach( function(row) {
if (row.related.last_update) {
html += "<tr>";
html += `<td><a href="" ng-click="viewJob('${row.related.last_update}')" aw-tool-tip="${row.status.charAt(0).toUpperCase() + row.status.slice(1)}. Click for details" aw-tip-placement="top"><i class="SmartStatus-tooltip--${row.status} fa icon-job-${row.status}"></i></a></td>`;
html += "<td>" + ($filter('longDate')(row.last_updated)).replace(/ /,'<br />') + "</td>";
html += "<td><a href=\"\" ng-click=\"viewJob('" + row.related.last_update + "')\">" + $filter('sanitize')(ellipsis(row.name)) + "</a></td>";
html += "</tr>\n";
}
else {
html += "<tr>";
html += "<td><a href=\"\" aw-tool-tip=\"No sync data\" aw-tip-placement=\"top\"><i class=\"fa icon-job-none\"></i></a></td>";
html += "<td>NA</td>";
html += "<td><a href=\"\">" + $filter('sanitize')(ellipsis(row.name)) + "</a></td>";
html += "</tr>\n";
}
});
html += "</tbody>\n";
html += "</table>\n";
title = "Sync Status";
attachElem(event, html, title);
});
$scope.showSourceSummary = function(event, id) {
try{
var elem = $(event.target).parent();
// if the popover is visible already, then exit the function here
if(elem.data()['bs.popover'].tip().hasClass('in')){
return;
}
}
catch(err){
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 + '?order_by=-last_job_run&page_size=5');
Rest.get()
.success(function(data) {
$scope.$emit('SourceSummaryReady', 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) {
try{
var elem = $(event.target).parent();
// if the popover is visible already, then exit the function here
if(elem.data()['bs.popover'].tip().hasClass('in')){
return;
}
}
catch(err){
var url, inventory;
if (!Empty(id)) {
inventory = Find({ list: $scope.inventories, key: 'id', val: id });
if (inventory.total_hosts > 0) {
Wait('start');
url = GetBasePath('jobs') + "?type=job&inventory=" + id + "&failed=";
url += (inventory.has_active_failures) ? 'true' : "false";
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
});
});
}
}
}
};
$scope.viewJob = function(url) {
// Pull the id out of the URL
var id = url.replace(/^\//, '').split('/')[3];
$state.go('inventorySyncStdout', {id: id});
};
$scope.editInventory = function (inventory) {
if(inventory.kind && inventory.kind === 'smart') {
@ -270,12 +78,7 @@ function InventoriesList($scope, $rootScope, $location,
}
};
$scope.manageInventory = function(id){
$location.path($location.path() + '/' + id + '/manage');
};
$scope.deleteInventory = function (id, name) {
var action = function () {
var url = defaultUrl + id + '/';
Wait('start');
@ -305,15 +108,6 @@ function InventoriesList($scope, $rootScope, $location,
});
};
// Failed jobs link. Go to the jobs tabs, find all jobs for the inventory and sort by status
$scope.viewJobs = function (id) {
$location.url('/jobs/?inventory__int=' + id);
};
$scope.viewFailedJobs = function (id) {
$location.url('/jobs/?inventory__int=' + id + '&status=failed');
};
$scope.syncInventory = function(inventory) {
InventoryUpdate({
scope: $scope,
@ -323,8 +117,8 @@ function InventoriesList($scope, $rootScope, $location,
};
}
export default ['$scope', '$rootScope', '$location',
'$compile', '$filter', 'Rest', 'InventoryList', 'Prompt',
'ProcessErrors', 'GetBasePath', 'Wait', 'Find', 'Empty',
'$state', 'rbacUiControlService', 'Dataset', 'InventoryUpdate', InventoriesList
export default ['$scope',
'$filter', 'Rest', 'InventoryList', 'Prompt',
'ProcessErrors', 'GetBasePath', 'Wait',
'$state', 'Dataset', 'InventoryUpdate', 'canAdd', InventoriesList
];

View File

@ -5,7 +5,12 @@
*************************************************/
import controller from './inventory-list.controller';
import hostSummaryPopover from './host-summary-popover/main';
import sourceSummaryPopover from './source-summary-popover/main';
export default
angular.module('InventoryList', [])
angular.module('InventoryList', [
hostSummaryPopover.name,
sourceSummaryPopover.name
])
.controller('InventoryListController', controller);

View File

@ -0,0 +1,7 @@
import directive from './source-summary-popover.directive';
import controller from './source-summary-popover.controller';
export default
angular.module('SourceSummaryPopoverModule', [])
.directive('sourceSummaryPopover', directive)
.controller('SourceSummaryPopoverController', controller);

View File

@ -0,0 +1,27 @@
export default [ '$scope', 'Wait', 'Empty', 'Rest', 'ProcessErrors', '$state',
function($scope, Wait, Empty, Rest, ProcessErrors, $state) {
$scope.gatherSourceJobs = function(event) {
if (!Empty($scope.inventory.id)) {
Wait('start');
Rest.setUrl($scope.inventory.related.inventory_sources + '?order_by=-last_job_run&page_size=5');
Rest.get()
.success(function(data) {
$scope.generateTable(data, event);
})
.error(function(data, status) {
ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + $scope.inventory.related.inventory_sources + ' failed. GET returned status: ' + status
});
});
}
};
$scope.viewJob = function(url) {
// Pull the id out of the URL
var id = url.replace(/^\//, '').split('/')[3];
$state.go('inventorySyncStdout', {id: id});
};
}
];

View File

@ -0,0 +1,98 @@
export default ['templateUrl', '$compile', 'Wait', '$filter',
function(templateUrl, $compile, Wait, $filter) {
return {
restrict: 'E',
replace: false,
scope: {
inventory: '='
},
controller: 'SourceSummaryPopoverController',
templateUrl: templateUrl('inventories/list/source-summary-popover/source-summary-popover'),
link: function(scope) {
function ellipsis(a) {
if (a.length > 20) {
return a.substr(0,20) + '...';
}
return a;
}
function attachElem(event, html, title) {
var elem = $(event.target).parent();
try {
elem.tooltip('hide');
elem.popover('destroy');
}
catch(err) {
//ignore
}
$('.popover').each(function() {
// remove lingering popover <div>. Seems to be a bug in TB3 RC1
$(this).remove();
});
$('.tooltip').each( function() {
// close any lingering tool tipss
$(this).hide();
});
elem.attr({
"aw-pop-over": html,
"data-popover-title": title,
"data-placement": "right" });
elem.removeAttr('ng-click');
$compile(elem)(scope);
scope.triggerPopover(event);
}
scope.generateTable = function(data, event) {
var html, title;
Wait('stop');
// Build the html for our popover
html = "<table class=\"table table-condensed flyout\" style=\"width: 100%\">\n";
html += "<thead>\n";
html += "<tr>";
html += "<th>Status</th>";
html += "<th>Last Sync</th>";
html += "<th>Source</th>";
html += "</tr>";
html += "</thead>\n";
html += "<tbody>\n";
data.results.forEach( function(row) {
if (row.related.last_update) {
html += "<tr>";
html += `<td><a href="" ng-click="viewJob('${row.related.last_update}')" aw-tool-tip="${row.status.charAt(0).toUpperCase() + row.status.slice(1)}. Click for details" aw-tip-placement="top"><i class="SmartStatus-tooltip--${row.status} fa icon-job-${row.status}"></i></a></td>`;
html += "<td>" + ($filter('longDate')(row.last_updated)) + "</td>";
html += "<td><a href=\"\" ng-click=\"viewJob('" + row.related.last_update + "')\">" + $filter('sanitize')(ellipsis(row.name)) + "</a></td>";
html += "</tr>\n";
}
else {
html += "<tr>";
html += "<td><a href=\"\" aw-tool-tip=\"No sync data\" aw-tip-placement=\"top\"><i class=\"fa icon-job-none\"></i></a></td>";
html += "<td>NA</td>";
html += "<td><a href=\"\">" + $filter('sanitize')(ellipsis(row.name)) + "</a></td>";
html += "</tr>\n";
}
});
html += "</tbody>\n";
html += "</table>\n";
title = "Sync Status";
attachElem(event, html, title);
};
scope.showSourceSummary = function(event) {
try{
var elem = $(event.target).parent();
// if the popover is visible already, then exit the function here
if(elem.data()['bs.popover'].tip().hasClass('in')){
return;
}
}
catch(err){
scope.gatherSourceJobs(event);
}
};
}
};
}
];

View File

@ -0,0 +1,3 @@
<a href="" ng-click="showSourceSummary($event, inventory.id)" aw-tool-tip="{{ inventory.syncTip }}" aw-tip-placement="right" ng-class="inventory.launch_class" >
<i class="fa {{ 'icon-cloud-' + inventory.syncStatus }}"></i>
</a>

View File

@ -84,6 +84,19 @@ angular.module('inventory', [
form: 'InventoryForm',
controllers: {
add: 'InventoryAddController'
},
resolve: {
add: {
canAdd: ['rbacUiControlService', '$state', function(rbacUiControlService, $state) {
return rbacUiControlService.canAdd('inventory')
.then(function(res) {
return res.canAdd;
})
.catch(function() {
$state.go('inventories');
});
}]
}
}
});
@ -107,6 +120,19 @@ angular.module('inventory', [
form: 'smartInventoryForm',
controllers: {
add: 'SmartInventoryAddController'
},
resolve: {
add: {
canAdd: ['rbacUiControlService', '$state', function(rbacUiControlService, $state) {
return rbacUiControlService.canAdd('inventory')
.then(function(res) {
return res.canAdd;
})
.catch(function() {
$state.go('inventories');
});
}]
}
}
});
@ -268,6 +294,17 @@ angular.module('inventory', [
return Rest.get();
}
]
},
list: {
canAdd: ['rbacUiControlService', function(rbacUiControlService) {
return rbacUiControlService.canAdd('hosts')
.then(function(res) {
return res.canAdd;
})
.catch(function() {
return false;
});
}]
}
},
views: {

View File

@ -5,19 +5,14 @@
*************************************************/
export default ['$state', '$stateParams', '$scope', 'RelatedHostsFormDefinition', 'ParseTypeChange',
'GenerateForm', 'HostManageService', 'rbacUiControlService', 'GetBasePath', 'ToJSON',
'GenerateForm', 'HostManageService', 'rbacUiControlService', 'GetBasePath', 'ToJSON', 'canAdd',
function($state, $stateParams, $scope, RelatedHostsFormDefinition, ParseTypeChange,
GenerateForm, HostManageService, rbacUiControlService, GetBasePath, ToJSON) {
GenerateForm, HostManageService, rbacUiControlService, GetBasePath, ToJSON, canAdd) {
init();
function init() {
$scope.canAdd = false;
rbacUiControlService.canAdd(GetBasePath('inventory') + $stateParams.inventory_id + "/hosts")
.then(function(canAdd) {
$scope.canAdd = canAdd;
});
$scope.canAdd = canAdd;
$scope.parseType = 'yaml';
$scope.host = { enabled: true };
// apply form definition's default field values

View File

@ -7,24 +7,19 @@
// import HostManageService from './../hosts/host.service';
export default ['$scope', 'ListDefinition', '$rootScope', 'GetBasePath',
'rbacUiControlService', 'Dataset', '$state', '$filter', 'Prompt', 'Wait',
'HostManageService', 'SetStatus',
'HostManageService', 'SetStatus', 'canAdd',
function($scope, ListDefinition, $rootScope, GetBasePath,
rbacUiControlService, Dataset, $state, $filter, Prompt, Wait,
HostManageService, SetStatus) {
HostManageService, SetStatus, canAdd) {
let list = ListDefinition;
init();
function init(){
$scope.canAdd = false;
$scope.canAdd = canAdd;
$scope.enableSmartInventoryButton = false;
rbacUiControlService.canAdd('hosts')
.then(function(canAdd) {
$scope.canAdd = canAdd;
});
// Search init
$scope.list = list;
$scope[`${list.iterator}_dataset`] = Dataset.data;

View File

@ -69,6 +69,15 @@ export default {
}],
inventoryData: ['InventoryManageService', '$stateParams', function(InventoryManageService, $stateParams) {
return InventoryManageService.getInventory($stateParams.inventory_id).then(res => res.data);
}],
canAdd: ['rbacUiControlService', function(rbacUiControlService) {
return rbacUiControlService.canAdd('hosts')
.then(function(res) {
return res.canAdd;
})
.catch(function() {
return false;
});
}]
}
};

View File

@ -13,22 +13,9 @@
function SmartInventoryAdd($scope, $location,
GenerateForm, smartInventoryForm, rbacUiControlService, Rest, Alert, ProcessErrors,
ClearScope, GetBasePath, ParseTypeChange, Wait, ToJSON,
$state) {
$state, canAdd) {
$scope.canAdd = false;
rbacUiControlService.canAdd(GetBasePath('inventory'))
.then(function(canAdd) {
$scope.canAdd = canAdd;
});
Rest.setUrl(GetBasePath('inventory'));
Rest.options()
.success(function(data) {
if (!data.actions.POST) {
$state.go("^");
Alert('Permission Error', 'You do not have permission to add an inventory.', 'alert-info');
}
});
$scope.canAdd = canAdd;
ClearScope();
@ -104,5 +91,5 @@ function SmartInventoryAdd($scope, $location,
export default ['$scope', '$location',
'GenerateForm', 'smartInventoryForm', 'rbacUiControlService', 'Rest', 'Alert',
'ProcessErrors', 'ClearScope', 'GetBasePath', 'ParseTypeChange',
'Wait', 'ToJSON', '$state', SmartInventoryAdd
'Wait', 'ToJSON', '$state', 'canAdd', SmartInventoryAdd
];

View File

@ -5,12 +5,14 @@
*************************************************/
export default ['$state', '$stateParams', '$scope', 'SourcesFormDefinition',
'ParseTypeChange', 'GenerateForm', 'inventoryData', 'GetChoices', 'GetBasePath', 'CreateSelect2', 'GetSourceTypeOptions', 'Empty',
'rbacUiControlService', 'ToJSON', 'SourcesService', 'Wait', 'Rest', 'Alert', 'ProcessErrors',
'ParseTypeChange', 'GenerateForm', 'inventoryData', 'GroupManageService',
'GetChoices', 'GetBasePath', 'CreateSelect2', 'GetSourceTypeOptions',
'rbacUiControlService', 'ToJSON', 'SourcesService', 'canAdd', 'Empty',
'Wait', 'Rest', 'Alert', 'ProcessErrors',
function($state, $stateParams, $scope, SourcesFormDefinition, ParseTypeChange,
GenerateForm, inventoryData, GetChoices,
GetBasePath, CreateSelect2, GetSourceTypeOptions, Empty, rbacUiControlService,
ToJSON, SourcesService, Wait, Rest, Alert, ProcessErrors) {
GenerateForm, inventoryData, GroupManageService, GetChoices,
GetBasePath, CreateSelect2, GetSourceTypeOptions, rbacUiControlService,
ToJSON, SourcesService, canAdd, Empty, Wait, Rest, Alert, ProcessErrors) {
let form = SourcesFormDefinition;
init();
@ -18,12 +20,8 @@ export default ['$state', '$stateParams', '$scope', 'SourcesFormDefinition',
function init() {
// apply form definition's default field values
GenerateForm.applyDefaults(form, $scope);
rbacUiControlService.canAdd(GetBasePath('inventory') + $stateParams.inventory_id + "/inventory_sources")
.then(function(canAdd) {
$scope.canAdd = canAdd;
});
$scope.canAdd = canAdd;
$scope.envParseType = 'yaml';
initSources();
}

View File

@ -19,4 +19,15 @@ export default {
controller: 'SourcesAddController'
}
},
resolve: {
canAdd: ['rbacUiControlService', 'GetBasePath', '$stateParams', function(rbacUiControlService, GetBasePath, $stateParams) {
return rbacUiControlService.canAdd(GetBasePath('inventory') + $stateParams.inventory_id + "/inventory_sources")
.then(function(res) {
return res.canAdd;
})
.catch(function() {
return false;
});
}]
}
};

View File

@ -5,20 +5,20 @@
*************************************************/
export default ['$state', '$stateParams', '$scope', 'ParseVariableString',
'rbacUiControlService', 'ToJSON', 'ParseTypeChange', 'GetChoices', 'GetBasePath', 'CreateSelect2', 'GetSourceTypeOptions',
'inventorySourceData', 'SourcesService', 'inventoryData', 'Empty', 'Wait', 'Rest', 'Alert', 'ProcessErrors',
'rbacUiControlService', 'ToJSON', 'ParseTypeChange', 'GroupManageService',
'GetChoices', 'GetBasePath', 'CreateSelect2', 'GetSourceTypeOptions',
'inventorySourceData', 'SourcesService', 'inventoryData', 'canAdd', 'Empty',
'Wait', 'Rest', 'Alert', 'ProcessErrors',
function($state, $stateParams, $scope, ParseVariableString,
rbacUiControlService, ToJSON,ParseTypeChange, GetChoices, GetBasePath, CreateSelect2, GetSourceTypeOptions,
inventorySourceData, SourcesService, inventoryData, Empty, Wait, Rest, Alert, ProcessErrors) {
rbacUiControlService, ToJSON,ParseTypeChange, GroupManageService,
GetChoices, GetBasePath, CreateSelect2, GetSourceTypeOptions,
inventorySourceData, SourcesService, inventoryData, canAdd, Empty,
Wait, Rest, Alert, ProcessErrors) {
init();
function init() {
rbacUiControlService.canAdd(GetBasePath('inventory') + $stateParams.inventory_id + "/inventory_sources")
.then(function(canAdd) {
$scope.canAdd = canAdd;
});
$scope.canAdd = canAdd;
// instantiate expected $scope values from inventorySourceData
_.assign($scope,
{credential: inventorySourceData.credential},

View File

@ -22,6 +22,15 @@ export default {
resolve: {
inventorySourceData: ['$stateParams', 'SourcesService', function($stateParams, SourcesService) {
return SourcesService.get({id: $stateParams.inventory_source_id }).then(res => res.data.results[0]);
}],
canAdd: ['rbacUiControlService', 'GetBasePath', '$stateParams', function(rbacUiControlService, GetBasePath, $stateParams) {
return rbacUiControlService.canAdd(GetBasePath('inventory') + $stateParams.inventory_id + "/inventory_sources")
.then(function(res) {
return res.canAdd;
})
.catch(function() {
return false;
});
}]
}
};

View File

@ -8,12 +8,12 @@
'InventoryUpdate', 'CancelSourceUpdate',
'ViewUpdateStatus', 'rbacUiControlService', 'GetBasePath',
'GetSyncStatusMsg', 'Dataset', 'Find', 'QuerySet',
'inventoryData', '$filter', 'Prompt', 'Wait', 'SourcesService', 'inventorySourceOptions',
'inventoryData', '$filter', 'Prompt', 'Wait', 'SourcesService', 'inventorySourceOptions', 'canAdd',
function($scope, $rootScope, $state, $stateParams, SourcesListDefinition,
InventoryUpdate, CancelSourceUpdate,
ViewUpdateStatus, rbacUiControlService, GetBasePath, GetSyncStatusMsg,
Dataset, Find, qs, inventoryData, $filter, Prompt,
Wait, SourcesService, inventorySourceOptions){
Wait, SourcesService, inventorySourceOptions, canAdd){
let list = SourcesListDefinition;
var inventory_source;
@ -23,12 +23,7 @@
function init(){
$scope.inventory_id = $stateParams.inventory_id;
$scope.canAdhoc = inventoryData.summary_fields.user_capabilities.adhoc;
$scope.canAdd = false;
rbacUiControlService.canAdd(GetBasePath('inventory') + $scope.inventory_id + "/inventory_sources")
.then(function(canAdd) {
$scope.canAdd = canAdd;
});
$scope.canAdd = canAdd;
// Search init
$scope.list = list;

View File

@ -60,6 +60,15 @@ export default {
],
inventoryData: ['InventoryManageService', '$stateParams', function(InventoryManageService, $stateParams) {
return InventoryManageService.getInventory($stateParams.inventory_id).then(res => res.data);
}],
canAdd: ['rbacUiControlService', 'GetBasePath', '$stateParams', function(rbacUiControlService, GetBasePath, $stateParams) {
return rbacUiControlService.canAdd(GetBasePath('inventory') + $stateParams.inventory_id + "/inventory_sources")
.then(function(res) {
return res.canAdd;
})
.catch(function() {
return false;
});
}]
}
};

View File

@ -13,22 +13,9 @@
function InventoriesAdd($scope, $location,
GenerateForm, InventoryForm, rbacUiControlService, Rest, Alert, ProcessErrors,
ClearScope, GetBasePath, ParseTypeChange, Wait, ToJSON,
$state) {
$state, canAdd) {
$scope.canAdd = false;
rbacUiControlService.canAdd(GetBasePath('inventory'))
.then(function(params) {
$scope.canAdd = params.canAdd;
});
Rest.setUrl(GetBasePath('inventory'));
Rest.options()
.success(function(data) {
if (!data.actions.POST) {
$state.go("^");
Alert('Permission Error', 'You do not have permission to add an inventory.', 'alert-info');
}
});
$scope.canAdd = canAdd;
ClearScope();
@ -98,5 +85,5 @@ function InventoriesAdd($scope, $location,
export default ['$scope', '$location',
'GenerateForm', 'InventoryForm', 'rbacUiControlService', 'Rest', 'Alert',
'ProcessErrors', 'ClearScope', 'GetBasePath', 'ParseTypeChange',
'Wait', 'ToJSON', '$state', InventoriesAdd
'Wait', 'ToJSON', '$state', 'canAdd', InventoriesAdd
];

View File

@ -239,10 +239,6 @@ export default ['$scope', '$rootScope', '$location',
$state.go('inventories.edit', { inventory_id: id });
};
$scope.manageInventory = function(id) {
$location.path($location.path() + '/' + id + '/manage');
};
// Failed jobs link. Go to the jobs tabs, find all jobs for the inventory and sort by status
$scope.viewJobs = function(id) {
$location.url('/jobs/?inventory__int=' + id);

View File

@ -552,116 +552,123 @@ angular.module('GeneratorHelpers', [systemStatus.name])
html += (field.awEllipsis) ? "aw-ellipsis " : "";
html += ">\n";
// Add ngShow
html += (field.ngShow) ? "<span " + Attr(field, 'ngShow') + ">" : "";
//Add ngHide
//html += (field.ngHide) ? "<span " + Attr(field, 'ngHide') + ">" : "";
// Badge
if (options.mode !== 'lookup' && (field.badges || (field.badgeIcon && field.badgePlacement && field.badgePlacement === 'left'))) {
html += Badge(field);
if(field.template) {
html += field.template;
}
else {
// Add collapse/expand icon --used on job_events page
if (list.hasChildren && field.hasChildren) {
html += "<div class=\"level level-{{ " + list.iterator + ".event_level }}\"><a href=\"\" ng-click=\"toggle(" +
list.iterator + ".id)\"> " +
"<i class=\"{{ " + list.iterator + ".ngicon }}\"></i></a></div>";
}
// Add ngShow
html += (field.ngShow) ? "<span " + Attr(field, 'ngShow') + ">" : "";
if (list.name === 'groups') {
html += "<div class=\"group-name\">";
}
if (list.name === 'hosts') {
html += "<div class=\"host-name\">";
}
//Add ngHide
//html += (field.ngHide) ? "<span " + Attr(field, 'ngHide') + ">" : "";
// Start the Link
if ((field.key || field.link || field.linkTo || field.ngClick || field.ngHref || field.awToolTip || field.awPopOver) &&
options.mode !== 'lookup' && options.mode !== 'select' && !field.noLink && !field.ngBindHtml) {
if(field.noLink === true){
// provide an override here in case we want key=true for sorting purposes but don't want links -- see: portal mode,
// Badge
if (options.mode !== 'lookup' && (field.badges || (field.badgeIcon && field.badgePlacement && field.badgePlacement === 'left'))) {
html += Badge(field);
}
else if (field.icons) {
field.icons.forEach(function(icon, idx) {
var key, i = field.icons[idx];
for (key in i) {
field[key] = i[key];
}
// Add collapse/expand icon --used on job_events page
if (list.hasChildren && field.hasChildren) {
html += "<div class=\"level level-{{ " + list.iterator + ".event_level }}\"><a href=\"\" ng-click=\"toggle(" +
list.iterator + ".id)\"> " +
"<i class=\"{{ " + list.iterator + ".ngicon }}\"></i></a></div>";
}
if (list.name === 'groups') {
html += "<div class=\"group-name\">";
}
if (list.name === 'hosts') {
html += "<div class=\"host-name\">";
}
// Start the Link
if ((field.key || field.link || field.linkTo || field.ngClick || field.ngHref || field.awToolTip || field.awPopOver) &&
options.mode !== 'lookup' && options.mode !== 'select' && !field.noLink && !field.ngBindHtml) {
if(field.noLink === true){
// provide an override here in case we want key=true for sorting purposes but don't want links -- see: portal mode,
}
else if (field.icons) {
field.icons.forEach(function(icon, idx) {
var key, i = field.icons[idx];
for (key in i) {
field[key] = i[key];
}
html += BuildLink({
list: list,
field: field,
fld: fld,
base: field.linkBase || base
}) + ' ';
});
}
else if(field.smartStatus){
html += '<aw-smart-status></aw-smart-status>';
}
else {
html += BuildLink({
list: list,
field: field,
fld: fld,
base: field.linkBase || base
}) + ' ';
});
}
else if(field.smartStatus){
html += '<aw-smart-status></aw-smart-status>';
});
}
}
else {
html += BuildLink({
list: list,
field: field,
fld: fld,
base: field.linkBase || base
});
}
}
else {
if(field.simpleTip) {
html += `<span aw-tool-tip="${field.simpleTip.awToolTip}" data-placement=${field.simpleTip.dataPlacement}>`;
}
// Add icon:
if (field.ngShowIcon) {
html += "<i ng-show=\"" + field.ngShowIcon + "\" class=\"" + field.icon + "\"></i> ";
} else if (field.icon) {
html += Icon(field.icon) + " ";
}
// Add data binds
if (!field.ngBindHtml && !field.iconOnly && (field.showValue === undefined || field.showValue === true)) {
if (field.ngBind) {
html += "{{ " + field.ngBind;
} else {
html += "{{ " + list.iterator + "." + fld;
if(field.simpleTip) {
html += `<span aw-tool-tip="${field.simpleTip.awToolTip}" data-placement=${field.simpleTip.dataPlacement}>`;
}
if (field.filter) {
html += " | " + field.filter + " }}";
// Add icon:
if (field.ngShowIcon) {
html += "<i ng-show=\"" + field.ngShowIcon + "\" class=\"" + field.icon + "\"></i> ";
} else if (field.icon) {
html += Icon(field.icon) + " ";
}
else {
html += " }}";
// Add data binds
if (!field.ngBindHtml && !field.iconOnly && (field.showValue === undefined || field.showValue === true)) {
if (field.ngBind) {
html += "{{ " + field.ngBind;
} else {
html += "{{ " + list.iterator + "." + fld;
}
if (field.filter) {
html += " | " + field.filter + " }}";
}
else {
html += " }}";
}
}
// Add additional text:
if (field.text) {
html += field.text;
}
if(field.simpleTip) {
html += `</span>`;
}
}
// Add additional text:
if (field.text) {
html += field.text;
if (list.name === 'hosts' || list.name === 'groups') {
html += "</div>";
}
if(field.simpleTip) {
html += `</span>`;
// close ngShow
html += (field.ngShow) ? "</span>" : "";
//close ngHide
//html += (field.ngHide) ? "</span>" : "";
// Specific to Job Events page -showing event detail/results
html += (field.appendHTML) ? "<div ng-show=\"" + field.appendHTML + " !== null\" " +
"ng-bind-html=\"" + field.appendHTML + "\" " +
"class=\"level-{{ " + list.iterator + ".event_level }}-detail\" " +
"></div>\n" : "";
// Badge
if (options.mode !== 'lookup' && field.badgeIcon && field.badgePlacement && field.badgePlacement !== 'left') {
html += Badge(field);
}
}
if (list.name === 'hosts' || list.name === 'groups') {
html += "</div>";
}
// close ngShow
html += (field.ngShow) ? "</span>" : "";
//close ngHide
//html += (field.ngHide) ? "</span>" : "";
// Specific to Job Events page -showing event detail/results
html += (field.appendHTML) ? "<div ng-show=\"" + field.appendHTML + " !== null\" " +
"ng-bind-html=\"" + field.appendHTML + "\" " +
"class=\"level-{{ " + list.iterator + ".event_level }}-detail\" " +
"></div>\n" : "";
// Badge
if (options.mode !== 'lookup' && field.badgeIcon && field.badgePlacement && field.badgePlacement !== 'left') {
html += Badge(field);
}
}
return html += "</td>\n";
};

View File

@ -62,7 +62,7 @@
}
.SmartStatus-tooltip--failed{
.SmartStatus-tooltip--error, .SmartStatus-tooltip--failed{
color: @default-err;
padding-right: 0px;
text-shadow: