Added sync button to inventory list. Added sync status icon back to inventory list (was there in previous releases. Added inventory source type to inventory source list.

This commit is contained in:
Michael Abashian
2017-05-23 17:40:30 -04:00
parent c5364f49bd
commit eff4100092
9 changed files with 115 additions and 31 deletions
@@ -0,0 +1,3 @@
.Inventories-hostStatus {
margin-left: 5px;
}
@@ -22,16 +22,22 @@ export default ['i18n', function(i18n) {
fields: { fields: {
status: { status: {
label: '', label: '',
columnClass: 'col-md-1 col-sm-2 col-xs-2 List-staticColumn--smallStatus', columnClass: 'List-staticColumn--mediumStatus',
nosort: true, nosort: true,
ngClick: "null", ngClick: "null",
iconOnly: true, iconOnly: true,
excludeModal: true, excludeModal: true,
icons: [{ icons: [{
icon: "{{ 'icon-cloud-' + inventory.syncStatus }}",
awToolTip: "{{ inventory.syncTip }}",
awTipPlacement: "right",
ngClick: "showSourceSummary($event, inventory.id)",
ngClass: "inventory.launch_class"
},{
icon: "{{ 'icon-job-' + inventory.hostsStatus }}", icon: "{{ 'icon-job-' + inventory.hostsStatus }}",
awToolTip: false, awToolTip: false,
ngClick: "showHostSummary($event, inventory.id)", ngClick: "showHostSummary($event, inventory.id)",
ngClass: "" ngClass: "inventory.host_status_class"
}] }]
}, },
name: { name: {
@@ -83,6 +89,13 @@ export default ['i18n', function(i18n) {
columnClass: 'col-md-2 col-sm-4 col-xs-4', columnClass: 'col-md-2 col-sm-4 col-xs-4',
inventory_update: {
mode: 'all',
ngClick: 'syncInventory(inventory)',
awToolTip: i18n._('Sync all inventory sources'),
ngShow: "inventory.kind === ''",
dataPlacement: "top",
},
edit: { edit: {
label: i18n._('Edit'), label: i18n._('Edit'),
ngClick: 'editInventory(inventory.id)', ngClick: 'editInventory(inventory.id)',
@@ -12,7 +12,8 @@
function InventoriesList($scope, $rootScope, $location, function InventoriesList($scope, $rootScope, $location,
$compile, $filter, Rest, InventoryList, Prompt, $compile, $filter, Rest, InventoryList, Prompt,
ProcessErrors, GetBasePath, Wait, Find, Empty, $state, rbacUiControlService, Dataset) { ProcessErrors, GetBasePath, Wait, Find, Empty, $state,
rbacUiControlService, Dataset, InventoryUpdate) {
let list = InventoryList, let list = InventoryList,
defaultUrl = GetBasePath('inventory'); defaultUrl = GetBasePath('inventory');
@@ -37,15 +38,16 @@ function InventoriesList($scope, $rootScope, $location,
$scope[list.name] = $scope[`${list.iterator}_dataset`].results; $scope[list.name] = $scope[`${list.iterator}_dataset`].results;
$rootScope.flashMessage = null; $rootScope.flashMessage = null;
} }
function buildStatusIndicators(inventory){ function buildStatusIndicators(inventory){
inventory.launch_class = ""; inventory.launch_class = "";
inventory.host_status_class = "Inventories-hostStatus";
if (inventory.has_inventory_sources) { if (inventory.has_inventory_sources) {
if (inventory.inventory_sources_with_failures > 0) { if (inventory.inventory_sources_with_failures > 0) {
inventory.syncStatus = 'error'; inventory.syncStatus = 'error';
inventory.syncTip = inventory.inventory_sources_with_failures + ' groups with sync failures. Click for details'; inventory.syncTip = inventory.inventory_sources_with_failures + ' sources with sync failures. Click for details';
} }
else { else {
inventory.syncStatus = 'successful'; inventory.syncStatus = 'successful';
@@ -57,6 +59,7 @@ function InventoriesList($scope, $rootScope, $location,
inventory.syncTip = 'Not configured for inventory sync.'; inventory.syncTip = 'Not configured for inventory sync.';
inventory.launch_class = "btn-disabled"; inventory.launch_class = "btn-disabled";
} }
if (inventory.has_active_failures) { if (inventory.has_active_failures) {
inventory.hostsStatus = 'error'; inventory.hostsStatus = 'error';
inventory.hostsTip = inventory.hosts_with_active_failures + ' hosts with failures. Click for details.'; inventory.hostsTip = inventory.hosts_with_active_failures + ' hosts with failures. Click for details.';
@@ -139,10 +142,10 @@ function InventoriesList($scope, $rootScope, $location,
attachElem(event, html, title); attachElem(event, html, title);
}); });
if ($scope.removeGroupSummaryReady) { if ($scope.removeSourceSummaryReady) {
$scope.removeGroupSummaryReady(); $scope.removeSourceSummaryReady();
} }
$scope.removeGroupSummaryReady = $scope.$on('GroupSummaryReady', function(e, event, inventory, data) { $scope.removeSourceSummaryReady = $scope.$on('SourceSummaryReady', function(e, event, inventory, data) {
var html, title; var html, title;
Wait('stop'); Wait('stop');
@@ -153,7 +156,7 @@ function InventoriesList($scope, $rootScope, $location,
html += "<tr>"; html += "<tr>";
html += "<th>Status</th>"; html += "<th>Status</th>";
html += "<th>Last Sync</th>"; html += "<th>Last Sync</th>";
html += "<th>Group</th>"; html += "<th>Source</th>";
html += "</tr>"; html += "</tr>";
html += "</thead>\n"; html += "</thead>\n";
html += "<tbody>\n"; html += "<tbody>\n";
@@ -162,14 +165,14 @@ function InventoriesList($scope, $rootScope, $location,
html += "<tr>"; 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><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>" + ($filter('longDate')(row.last_updated)).replace(/ /,'<br />') + "</td>";
html += "<td><a href=\"\" ng-click=\"viewJob('" + row.related.last_update + "')\">" + $filter('sanitize')(ellipsis(row.summary_fields.group.name)) + "</a></td>"; html += "<td><a href=\"\" ng-click=\"viewJob('" + row.related.last_update + "')\">" + $filter('sanitize')(ellipsis(row.name)) + "</a></td>";
html += "</tr>\n"; html += "</tr>\n";
} }
else { else {
html += "<tr>"; 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><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>NA</td>";
html += "<td><a href=\"\">" + $filter('sanitize')(ellipsis(row.summary_fields.group.name)) + "</a></td>"; html += "<td><a href=\"\">" + $filter('sanitize')(ellipsis(row.name)) + "</a></td>";
html += "</tr>\n"; html += "</tr>\n";
} }
}); });
@@ -179,7 +182,7 @@ function InventoriesList($scope, $rootScope, $location,
attachElem(event, html, title); attachElem(event, html, title);
}); });
$scope.showGroupSummary = function(event, id) { $scope.showSourceSummary = function(event, id) {
try{ try{
var elem = $(event.target).parent(); var elem = $(event.target).parent();
// if the popover is visible already, then exit the function here // if the popover is visible already, then exit the function here
@@ -193,10 +196,10 @@ function InventoriesList($scope, $rootScope, $location,
inventory = Find({ list: $scope.inventories, key: 'id', val: id }); inventory = Find({ list: $scope.inventories, key: 'id', val: id });
if (inventory.syncStatus !== 'na') { if (inventory.syncStatus !== 'na') {
Wait('start'); Wait('start');
Rest.setUrl(inventory.related.inventory_sources + '?or__source=ec2&or__source=rax&order_by=-last_job_run&page_size=5'); Rest.setUrl(inventory.related.inventory_sources + '?order_by=-last_job_run&page_size=5');
Rest.get() Rest.get()
.success(function(data) { .success(function(data) {
$scope.$emit('GroupSummaryReady', event, inventory, data); $scope.$emit('SourceSummaryReady', event, inventory, data);
}) })
.error(function(data, status) { .error(function(data, status) {
ProcessErrors( $scope, data, status, null, { hdr: 'Error!', ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
@@ -300,9 +303,18 @@ function InventoriesList($scope, $rootScope, $location,
$scope.viewFailedJobs = function (id) { $scope.viewFailedJobs = function (id) {
$location.url('/jobs/?inventory__int=' + id + '&status=failed'); $location.url('/jobs/?inventory__int=' + id + '&status=failed');
}; };
$scope.syncInventory = function(inventory) {
InventoryUpdate({
scope: $scope,
url: inventory.related.update_inventory_sources,
updateAllSources: true
});
};
} }
export default ['$scope', '$rootScope', '$location', export default ['$scope', '$rootScope', '$location',
'$compile', '$filter', 'Rest', 'InventoryList', '$compile', '$filter', 'Rest', 'InventoryList', 'Prompt',
'Prompt', 'ProcessErrors', 'GetBasePath', 'Wait', 'Find', 'Empty', '$state', 'rbacUiControlService', 'Dataset', InventoriesList 'ProcessErrors', 'GetBasePath', 'Wait', 'Find', 'Empty',
'$state', 'rbacUiControlService', 'Dataset', 'InventoryUpdate', InventoriesList
]; ];
@@ -8,12 +8,12 @@
'InventoryUpdate', 'GroupManageService', 'CancelSourceUpdate', 'InventoryUpdate', 'GroupManageService', 'CancelSourceUpdate',
'ViewUpdateStatus', 'rbacUiControlService', 'GetBasePath', 'ViewUpdateStatus', 'rbacUiControlService', 'GetBasePath',
'GetSyncStatusMsg', 'Dataset', 'Find', 'QuerySet', 'GetSyncStatusMsg', 'Dataset', 'Find', 'QuerySet',
'inventoryData', '$filter', 'Prompt', 'Wait', 'SourcesService', 'inventoryData', '$filter', 'Prompt', 'Wait', 'SourcesService', 'inventorySourceOptions',
function($scope, $rootScope, $state, $stateParams, SourcesListDefinition, function($scope, $rootScope, $state, $stateParams, SourcesListDefinition,
InventoryUpdate, GroupManageService, CancelSourceUpdate, InventoryUpdate, GroupManageService, CancelSourceUpdate,
ViewUpdateStatus, rbacUiControlService, GetBasePath, GetSyncStatusMsg, ViewUpdateStatus, rbacUiControlService, GetBasePath, GetSyncStatusMsg,
Dataset, Find, qs, inventoryData, $filter, Prompt, Dataset, Find, qs, inventoryData, $filter, Prompt,
Wait, SourcesService){ Wait, SourcesService, inventorySourceOptions){
let list = SourcesListDefinition; let list = SourcesListDefinition;
@@ -36,6 +36,7 @@
$scope.inventory_id = $stateParams.inventory_id; $scope.inventory_id = $stateParams.inventory_id;
_.forEach($scope[list.name], buildStatusIndicators); _.forEach($scope[list.name], buildStatusIndicators);
optionsRequestDataProcessing();
$scope.$on(`ws-jobs`, function(e, data){ $scope.$on(`ws-jobs`, function(e, data){
var inventory_source = Find({ list: $scope.inventory_sources, key: 'id', val: data.inventory_source_id }); var inventory_source = Find({ list: $scope.inventory_sources, key: 'id', val: data.inventory_source_id });
@@ -52,6 +53,7 @@
$scope[`${list.iterator}_dataset`] = searchResponse.data; $scope[`${list.iterator}_dataset`] = searchResponse.data;
$scope[list.name] = $scope[`${list.iterator}_dataset`].results; $scope[list.name] = $scope[`${list.iterator}_dataset`].results;
_.forEach($scope[list.name], buildStatusIndicators); _.forEach($scope[list.name], buildStatusIndicators);
optionsRequestDataProcessing();
}); });
} else { } else {
var status = GetSyncStatusMsg({ var status = GetSyncStatusMsg({
@@ -64,6 +66,28 @@
inventory_source.launch_class = status.launch_class; inventory_source.launch_class = status.launch_class;
} }
}); });
$scope.$watchCollection(`${$scope.list.name}`, function() {
_.forEach($scope[list.name], buildStatusIndicators);
optionsRequestDataProcessing();
});
}
function optionsRequestDataProcessing(){
if ($scope[list.name] !== undefined) {
$scope[list.name].forEach(function(item, item_idx) {
var itm = $scope[list.name][item_idx];
// Set the item source label
if (list.fields.source && inventorySourceOptions && inventorySourceOptions.hasOwnProperty('source')) {
inventorySourceOptions.source.choices.forEach(function(choice) {
if (choice[0] === item.source) {
itm.source_label = choice[1];
}
});
}
});
}
} }
function buildStatusIndicators(inventory_source){ function buildStatusIndicators(inventory_source){
@@ -42,6 +42,9 @@ export default {
} }
}, },
resolve: { resolve: {
inventorySourceOptions: ['SourcesService', (SourcesService) => {
return SourcesService.options().then(res => res.data.actions.GET);
}],
Dataset: ['SourcesListDefinition', 'QuerySet', '$stateParams', 'GetBasePath', '$interpolate', '$rootScope', Dataset: ['SourcesListDefinition', 'QuerySet', '$stateParams', 'GetBasePath', '$interpolate', '$rootScope',
(list, qs, $stateParams, GetBasePath, $interpolate, $rootScope) => { (list, qs, $stateParams, GetBasePath, $interpolate, $rootScope) => {
// allow related list definitions to use interpolated $rootScope / $stateParams in basePath field // allow related list definitions to use interpolated $rootScope / $stateParams in basePath field
@@ -33,8 +33,13 @@ export default {
label: 'Sources', label: 'Sources',
key: true, key: true,
ngClick: "editSource(inventory_source.id)", ngClick: "editSource(inventory_source.id)",
columnClass: 'col-lg-6 col-md-6 col-sm-6 col-xs-6', columnClass: 'col-lg-4 col-md-4 col-sm-4 col-xs-4',
class: 'InventoryManage-breakWord', class: 'InventoryManage-breakWord',
},
source: {
label: 'Type',
ngBind: 'inventory_source.source_label',
columnClass: 'col-lg-4 col-md-4 col-sm-4 col-xs-4'
} }
}, },
@@ -60,7 +65,7 @@ export default {
fieldActions: { fieldActions: {
columnClass: 'col-lg-6 col-md-6 col-sm-6 col-xs-6 text-right', columnClass: 'col-lg-4 col-md-4 col-sm-4 col-xs-4 text-right',
group_update: { group_update: {
//label: 'Sync', //label: 'Sync',
@@ -54,6 +54,13 @@ export default
.error(this.error.bind(this)) .error(this.error.bind(this))
.finally(Wait('stop')); .finally(Wait('stop'));
}, },
options: function(){
this.url = GetBasePath('inventory_sources');
Rest.setUrl(this.url);
return Rest.options()
.success(this.success.bind(this))
.error(this.error.bind(this));
},
getCredential: function(id){ getCredential: function(id){
Wait('start'); Wait('start');
this.url = GetBasePath('credentials') + id; this.url = GetBasePath('credentials') + id;
@@ -43,19 +43,33 @@ export default
Rest.setUrl(url); Rest.setUrl(url);
Rest.get() Rest.get()
.success(function (data) { .success(function (data) {
inventory_source = data; if(params.updateAllSources) {
if (data.can_update) { let userCanUpdateAllSources = true;
if (data.passwords_needed_to_update) { _.forEach(data, function(inventory_source){
Wait('stop'); if (!inventory_source.can_update) {
scope.$emit('PromptForPasswords'); userCanUpdateAllSources = false;
} }
else { });
if(userCanUpdateAllSources) {
scope.$emit('StartTheUpdate', {}); scope.$emit('StartTheUpdate', {});
} }
} else { }
Wait('stop'); else {
Alert('Permission Denied', 'You do not have access to run the inventory sync. Please contact your system administrator.', inventory_source = data;
'alert-danger'); if (data.can_update) {
if (data.passwords_needed_to_update) {
Wait('stop');
scope.$emit('PromptForPasswords');
}
else {
scope.$emit('StartTheUpdate', {});
}
} else {
Wait('stop');
Alert('Permission Denied', 'You do not have access to run the inventory sync. Please contact your system administrator.',
'alert-danger');
}
} }
}) })
.error(function (data, status) { .error(function (data, status) {
@@ -134,6 +134,9 @@ angular.module('GeneratorHelpers', [systemStatus.name])
case 'group_update': case 'group_update':
icon = 'fa-refresh'; icon = 'fa-refresh';
break; break;
case 'inventory_update':
icon = 'fa-refresh';
break;
case 'scm_update': case 'scm_update':
icon = 'fa-cloud-download'; icon = 'fa-cloud-download';
break; break;