1
0
mirror of https://github.com/ansible/awx.git synced 2024-11-01 08:21:15 +03:00

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: {
status: {
label: '',
columnClass: 'col-md-1 col-sm-2 col-xs-2 List-staticColumn--smallStatus',
columnClass: 'List-staticColumn--mediumStatus',
nosort: true,
ngClick: "null",
iconOnly: true,
excludeModal: true,
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 }}",
awToolTip: false,
ngClick: "showHostSummary($event, inventory.id)",
ngClass: ""
ngClass: "inventory.host_status_class"
}]
},
name: {
@ -83,6 +89,13 @@ export default ['i18n', function(i18n) {
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: {
label: i18n._('Edit'),
ngClick: 'editInventory(inventory.id)',

View File

@ -12,7 +12,8 @@
function InventoriesList($scope, $rootScope, $location,
$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,
defaultUrl = GetBasePath('inventory');
@ -37,15 +38,16 @@ function InventoriesList($scope, $rootScope, $location,
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
$rootScope.flashMessage = null;
}
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 + ' groups with sync failures. Click for details';
inventory.syncTip = inventory.inventory_sources_with_failures + ' sources with sync failures. Click for details';
}
else {
inventory.syncStatus = 'successful';
@ -57,6 +59,7 @@ function InventoriesList($scope, $rootScope, $location,
inventory.syncTip = 'Not configured for inventory sync.';
inventory.launch_class = "btn-disabled";
}
if (inventory.has_active_failures) {
inventory.hostsStatus = 'error';
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);
});
if ($scope.removeGroupSummaryReady) {
$scope.removeGroupSummaryReady();
if ($scope.removeSourceSummaryReady) {
$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;
Wait('stop');
@ -153,7 +156,7 @@ function InventoriesList($scope, $rootScope, $location,
html += "<tr>";
html += "<th>Status</th>";
html += "<th>Last Sync</th>";
html += "<th>Group</th>";
html += "<th>Source</th>";
html += "</tr>";
html += "</thead>\n";
html += "<tbody>\n";
@ -162,14 +165,14 @@ function InventoriesList($scope, $rootScope, $location,
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.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";
}
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.summary_fields.group.name)) + "</a></td>";
html += "<td><a href=\"\">" + $filter('sanitize')(ellipsis(row.name)) + "</a></td>";
html += "</tr>\n";
}
});
@ -179,7 +182,7 @@ function InventoriesList($scope, $rootScope, $location,
attachElem(event, html, title);
});
$scope.showGroupSummary = function(event, id) {
$scope.showSourceSummary = function(event, id) {
try{
var elem = $(event.target).parent();
// 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 });
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.setUrl(inventory.related.inventory_sources + '?order_by=-last_job_run&page_size=5');
Rest.get()
.success(function(data) {
$scope.$emit('GroupSummaryReady', event, inventory, data);
$scope.$emit('SourceSummaryReady', event, inventory, data);
})
.error(function(data, status) {
ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
@ -300,9 +303,18 @@ function InventoriesList($scope, $rootScope, $location,
$scope.viewFailedJobs = function (id) {
$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',
'$compile', '$filter', 'Rest', 'InventoryList',
'Prompt', 'ProcessErrors', 'GetBasePath', 'Wait', 'Find', 'Empty', '$state', 'rbacUiControlService', 'Dataset', InventoriesList
'$compile', '$filter', 'Rest', 'InventoryList', 'Prompt',
'ProcessErrors', 'GetBasePath', 'Wait', 'Find', 'Empty',
'$state', 'rbacUiControlService', 'Dataset', 'InventoryUpdate', InventoriesList
];

View File

@ -8,12 +8,12 @@
'InventoryUpdate', 'GroupManageService', 'CancelSourceUpdate',
'ViewUpdateStatus', 'rbacUiControlService', 'GetBasePath',
'GetSyncStatusMsg', 'Dataset', 'Find', 'QuerySet',
'inventoryData', '$filter', 'Prompt', 'Wait', 'SourcesService',
'inventoryData', '$filter', 'Prompt', 'Wait', 'SourcesService', 'inventorySourceOptions',
function($scope, $rootScope, $state, $stateParams, SourcesListDefinition,
InventoryUpdate, GroupManageService, CancelSourceUpdate,
ViewUpdateStatus, rbacUiControlService, GetBasePath, GetSyncStatusMsg,
Dataset, Find, qs, inventoryData, $filter, Prompt,
Wait, SourcesService){
Wait, SourcesService, inventorySourceOptions){
let list = SourcesListDefinition;
@ -36,6 +36,7 @@
$scope.inventory_id = $stateParams.inventory_id;
_.forEach($scope[list.name], buildStatusIndicators);
optionsRequestDataProcessing();
$scope.$on(`ws-jobs`, function(e, data){
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.name] = $scope[`${list.iterator}_dataset`].results;
_.forEach($scope[list.name], buildStatusIndicators);
optionsRequestDataProcessing();
});
} else {
var status = GetSyncStatusMsg({
@ -64,6 +66,28 @@
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){

View File

@ -42,6 +42,9 @@ export default {
}
},
resolve: {
inventorySourceOptions: ['SourcesService', (SourcesService) => {
return SourcesService.options().then(res => res.data.actions.GET);
}],
Dataset: ['SourcesListDefinition', 'QuerySet', '$stateParams', 'GetBasePath', '$interpolate', '$rootScope',
(list, qs, $stateParams, GetBasePath, $interpolate, $rootScope) => {
// allow related list definitions to use interpolated $rootScope / $stateParams in basePath field

View File

@ -33,8 +33,13 @@ export default {
label: 'Sources',
key: true,
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',
},
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: {
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: {
//label: 'Sync',

View File

@ -54,6 +54,13 @@ export default
.error(this.error.bind(this))
.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){
Wait('start');
this.url = GetBasePath('credentials') + id;

View File

@ -43,19 +43,33 @@ export default
Rest.setUrl(url);
Rest.get()
.success(function (data) {
inventory_source = data;
if (data.can_update) {
if (data.passwords_needed_to_update) {
Wait('stop');
scope.$emit('PromptForPasswords');
}
else {
if(params.updateAllSources) {
let userCanUpdateAllSources = true;
_.forEach(data, function(inventory_source){
if (!inventory_source.can_update) {
userCanUpdateAllSources = false;
}
});
if(userCanUpdateAllSources) {
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');
}
else {
inventory_source = data;
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) {

View File

@ -134,6 +134,9 @@ angular.module('GeneratorHelpers', [systemStatus.name])
case 'group_update':
icon = 'fa-refresh';
break;
case 'inventory_update':
icon = 'fa-refresh';
break;
case 'scm_update':
icon = 'fa-cloud-download';
break;