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:37:49 -04:00
parent c5364f49bd
commit eff4100092
9 changed files with 115 additions and 31 deletions

View File

@@ -0,0 +1,3 @@
.Inventories-hostStatus {
margin-left: 5px;
}

View File

@@ -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)',

View File

@@ -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
]; ];

View File

@@ -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){

View File

@@ -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

View File

@@ -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',

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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;