Inventory refactoring: added All Hosts, group delete now works, view inventory sync status works, group add now refreshes the group view correctly.

This commit is contained in:
Chris Houseknecht
2014-01-08 23:38:00 +00:00
parent 255dead521
commit 9930c6d356
9 changed files with 263 additions and 202 deletions

View File

@@ -276,7 +276,7 @@ function InventoriesAdd ($scope, $rootScope, $compile, $location, $log, $routePa
Rest.put(json_data) Rest.put(json_data)
.success( function(data, status, headers, config) { .success( function(data, status, headers, config) {
Wait('stop'); Wait('stop');
$location.path('/inventories/' + inventory_id + '/groups'); $location.path('/inventories/' + inventory_id + '/');
}) })
.error( function(data, status, headers, config) { .error( function(data, status, headers, config) {
Wait('stop'); Wait('stop');
@@ -286,7 +286,7 @@ function InventoriesAdd ($scope, $rootScope, $compile, $location, $log, $routePa
} }
else { else {
Wait('stop'); Wait('stop');
$location.path('/inventories/' + inventory_id + '/groups'); $location.path('/inventories/' + inventory_id + '/');
} }
}) })
.error( function(data, status, headers, config) { .error( function(data, status, headers, config) {
@@ -317,8 +317,8 @@ InventoriesAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$lo
function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateList, ClearScope, InventoryGroups, InventoryHosts, BuildTree, Wait, function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateList, ClearScope, InventoryGroups, InventoryHosts, BuildTree, Wait,
GetSyncStatusMsg, InjectHosts, HostsReload, GroupsAdd, GroupsEdit, Breadcrumbs, LoadBreadCrumbs, Empty, Rest, GetSyncStatusMsg, InjectHosts, HostsReload, GroupsAdd, GroupsEdit, GroupsDelete, Breadcrumbs, LoadBreadCrumbs, Empty,
ProcessErrors, InventoryUpdate, Alert, ToggleChildren) Rest, ProcessErrors, InventoryUpdate, Alert, ToggleChildren, ViewUpdateStatus)
{ {
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope. //scope.
@@ -331,37 +331,61 @@ function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateLis
LoadBreadCrumbs(); LoadBreadCrumbs();
if ($scope.removeSearchTreeReady) { if ($scope.removeGroupTreeLoaded) {
$scope.removeSearchTreeReady(); $scope.removeGroupTreeLoaded();
} }
$scope.removeSearchTreeReady = $scope.$on('searchTreeReady', function(e, inventory_name, groups) { $scope.removeGroupTreeLoaded = $scope.$on('groupTreeLoaded', function(e, inventory_name, groups) {
// After the tree data loads, generate the groups list // After the tree data loads, generate the groups list
// Add breadcrumbs // Add breadcrumbs
var e = angular.element(document.getElementById('breadcrumbs')); var e = angular.element(document.getElementById('breadcrumbs'));
e.html(Breadcrumbs({ list: list, mode: 'edit' })); e.html(Breadcrumbs({ list: list, mode: 'edit' }));
$compile(e)($scope); $compile(e)($scope);
// Add groups
// Add groups view
generator.inject(list, { mode: 'edit', id: 'groups-container', breadCrumbs: false, searchSize: 'col-lg-5 col-md-5 col-sm-5' }); generator.inject(list, { mode: 'edit', id: 'groups-container', breadCrumbs: false, searchSize: 'col-lg-5 col-md-5 col-sm-5' });
$scope.groups = groups; $scope.groups = groups;
$scope.inventory_name = inventory_name; $scope.inventory_name = inventory_name;
// Add hosts
InjectHosts({ scope: $scope, inventory_id: $scope.inventory_id }); // Default the selected group to the first node
if ($scope.groups.length > 0) {
$scope.selected_tree_id = $scope.groups[0].id;
$scope.selected_group_id = $scope.groups[0].group_id;
}
else {
$scope.selected_tree_id = null;
$scope.selected_group_id = null;
}
// Add hosts view
InjectHosts({ scope: $scope, inventory_id: $scope.inventory_id, tree_id: $scope.selected_tree_id, group_id: $scope.selected_group_id });
Wait('stop'); Wait('stop');
}); });
if ($scope.removeGroupTreeRefreshed) {
$scope.removeGroupTreeRefreshed();
}
$scope.removeGroupTreeRefreshed = $scope.$on('groupTreeRefreshed', function(e, inventory_name, groups) {
// Called after tree data is reloaded on refresh button click.
// Reselect the preveiously selected group node, causing host view to refresh.
$scope.showHosts($scope.selected_tree_id, $scope.selected_group_id);
});
if ($scope.removeGroupDeleteCompleted) {
$scope.removeGroupDeleteCompleted();
}
$scope.removeGroupDeleteCompleted = $scope.$on('groupDeleteCompleted', function(e) {
// Group was deleted. Now we need to refresh the group view.
BuildTree({ scope: $scope, inventory_id: $scope.inventory_id, refresh: true });
});
$scope.showHosts = function(tree_id, group_id) { $scope.showHosts = function(tree_id, group_id) {
// Clicked on group // Clicked on group
//$scope.groups[tree_id].selected_class = 'selected'; if (tree_id !== null) {
$scope.selected_tree_id = tree_id; $scope.selected_tree_id = tree_id;
$scope.selected_group_id = group_id; $scope.selected_group_id = group_id;
for (var i=0; i < $scope.groups.length; i++) { HostsReload({ scope: $scope, group_id: group_id, tree_id: tree_id, inventory_id: $scope.inventory_id });
$scope.groups[i].selected_class = ($scope.groups[i].id == tree_id) ? 'selected' : '';
if ($scope.groups[i].id == tree_id) {
$scope.selected_group_name = $scope.groups[i].name;
}
} }
$scope.search_place_holder='Search ' + $scope.selected_group_name;
HostsReload({ scope: $scope, group_id: group_id, inventory_id: $scope.inventory_id });
} }
$scope.createGroup = function() { $scope.createGroup = function() {
@@ -407,20 +431,32 @@ function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateLis
} }
} }
// Expand/collapse nodes
$scope.toggle = function(id) { $scope.toggle = function(id) {
ToggleChildren({ // Expand/collapse nodes
scope: $scope, ToggleChildren({ scope: $scope, list: list, id: id });
list: list,
id: id,
});
} }
BuildTree({ scope: $scope, inventory_id: $scope.inventory_id }); $scope.refreshGroups = function() {
// Refresh the tree data when refresh button cicked
BuildTree({ scope: $scope, inventory_id: $scope.inventory_id, refresh: true });
}
$scope.viewUpdateStatus = function(id) {
ViewUpdateStatus({ scope: $scope, tree_id: id });
}
$scope.deleteGroup = function(id) {
GroupsDelete({ scope: $scope, tree_id: id, inventory_id: $scope.inventory_id });
}
//Load tree data for the first time
BuildTree({ scope: $scope, inventory_id: $scope.inventory_id, refresh: false });
} }
InventoriesEdit.$inject = [ '$scope', '$location', '$routeParams', '$compile', 'GenerateList', 'ClearScope', 'InventoryGroups', 'InventoryHosts', InventoriesEdit.$inject = [ '$scope', '$location', '$routeParams', '$compile', 'GenerateList', 'ClearScope', 'InventoryGroups', 'InventoryHosts',
'BuildTree', 'Wait', 'GetSyncStatusMsg', 'InjectHosts', 'HostsReload', 'GroupsAdd', 'GroupsEdit', 'Breadcrumbs', 'BuildTree', 'Wait', 'GetSyncStatusMsg', 'InjectHosts', 'HostsReload', 'GroupsAdd', 'GroupsEdit', 'GroupsDelete',
'LoadBreadCrumbs', 'Empty', 'Rest', 'ProcessErrors', 'InventoryUpdate', 'Alert', 'ToggleChildren' 'Breadcrumbs', 'LoadBreadCrumbs', 'Empty', 'Rest', 'ProcessErrors', 'InventoryUpdate', 'Alert', 'ToggleChildren',
'ViewUpdateStatus'
]; ];

View File

@@ -109,7 +109,7 @@ angular.module('GroupFormDefinition', [])
type: 'textarea', type: 'textarea',
addRequired: false, addRequired: false,
editRequird: false, editRequird: false,
rows: 10, rows: 6,
'default': '---', 'default': '---',
parseTypeName: 'envParseType', parseTypeName: 'envParseType',
dataTitle: 'Source Variables', dataTitle: 'Source Variables',

View File

@@ -82,12 +82,12 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
} }
}]) }])
.factory('ViewUpdateStatus', [ 'Rest', 'ProcessErrors', 'GetBasePath', 'ShowUpdateStatus', 'Alert', 'Wait', .factory('ViewUpdateStatus', [ 'Rest', 'ProcessErrors', 'GetBasePath', 'ShowUpdateStatus', 'Alert', 'Wait', 'Empty',
function(Rest, ProcessErrors, GetBasePath, ShowUpdateStatus, Alert, Wait) { function(Rest, ProcessErrors, GetBasePath, ShowUpdateStatus, Alert, Wait, Empty) {
return function(params) { return function(params) {
var scope = params.scope; var scope = params.scope;
var id = params.group_id; var id = params.tree_id;
var found = false; var found = false;
var group; var group;
for (var i=0; i < scope.groups.length; i++) { for (var i=0; i < scope.groups.length; i++) {
@@ -97,14 +97,13 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
} }
} }
if (found) { if (found) {
if (group.summary_fields.inventory_source.source == "" || group.summary_fields.inventory_source.source == null) { if (Empty(group.source)) {
Alert('Missing Configuration', 'The selected group is not configured for inventory updates. ' + Alert('Missing Configuration', 'The selected group is not configured for inventory sync. ' +
'You must first edit the group, provide Source settings, and then run an update.', 'alert-info'); 'You must first edit the group, provide Source settings, and then run the sync process.', 'alert-info');
} }
else if (group.summary_fields.inventory_source.status == "" || group.summary_fields.inventory_source.status == null || else if (Empty(group.status) || group.status == "never updated") {
group.summary_fields.inventory_source.status == "never updated") { Alert('No Status Available', 'An inventory sync has not been performed for the selected group. Start the process by ' +
Alert('No Status Available', 'The inventory update process has not run for the selected group. Start the process by ' + 'clicking the <i class="fa fa-exchange"></i> button.', 'alert-info');
'clicking the Update button.', 'alert-info');
} }
else { else {
Wait('start'); Wait('start');
@@ -115,7 +114,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
ShowUpdateStatus({ ShowUpdateStatus({
group_name: data.summary_fields.group.name, group_name: data.summary_fields.group.name,
last_update: url, last_update: url,
license_error: [ (data.summary_fields.last_update && data.summary_fields.last_update.license_error) ? true : false ] license_error: (data.summary_fields.last_update && data.summary_fields.last_update.license_error) ? true : false
}); });
}) })
.error( function(data, status, headers, config) { .error( function(data, status, headers, config) {
@@ -167,7 +166,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
// many hosts with 0 failures // many hosts with 0 failures
tip = "All " + total_hosts + " hosts in this group are happy! None of them have " + tip = "All " + total_hosts + " hosts in this group are happy! None of them have " +
" a recent job failure. Click to view the hosts."; " a recent job failure. Click to view the hosts.";
links = '/#/inventories/' + inventory_id + '/hosts/?group=' + group_id; link = '/#/inventories/' + inventory_id + '/hosts/?group=' + group_id;
html_class = 'false'; html_class = 'false';
} }
} }
@@ -596,15 +595,53 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
} }
} }
} }
} }
}]) }])
.factory('SourceChange', [ 'GetBasePath', 'CredentialList', 'LookUpInit',
function(GetBasePath, CredentialList, LookUpInit){
return function(params) {
var scope = params.scope;
var form = params.form;
if (scope['source'].value == 'file') {
scope.sourcePathRequired = true;
}
else {
scope.sourcePathRequired = false;
// reset fields
scope.source_path = '';
scope[form.name + '_form']['source_path'].$setValidity('required',true);
}
if (scope['source'].value == 'rax') {
scope['source_region_choices'] = scope['rax_regions'];
//$('#s2id_group_source_regions').select2('data', []);
$('#s2id_group_source_regions').select2('data', [{ id: 'all', text: 'All' }]);
}
else if (scope['source'].value == 'ec2') {
scope['source_region_choices'] = scope['ec2_regions'];
//$('#s2id_group_source_regions').select2('data', []);
$('#s2id_group_source_regions').select2('data', [{ id: 'all', text: 'All' }]);
}
var kind = (scope.source.value == 'rax') ? 'rax' : 'aws';
var url = GetBasePath('credentials') + '?cloud=true&kind=' + kind;
LookUpInit({
url: url,
scope: scope,
form: form,
list: CredentialList,
field: 'credential'
});
}
}])
.factory('GroupsAdd', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm', .factory('GroupsAdd', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'ParseTypeChange', 'GroupsEdit', 'ClickNode', 'Wait', 'GetChoices', 'Prompt', 'ProcessErrors', 'GetBasePath', 'ParseTypeChange', 'GroupsEdit', 'ClickNode', 'Wait', 'GetChoices',
'GetSourceTypeOptions', 'CredentialList', 'LookUpInit', 'BuildTree', 'GetSourceTypeOptions', 'LookUpInit', 'BuildTree', 'SourceChange',
function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors, function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,
GetBasePath, ParseTypeChange, GroupsEdit, ClickNode, Wait, GetChoices, GetSourceTypeOptions, CredentialList, GetBasePath, ParseTypeChange, GroupsEdit, ClickNode, Wait, GetChoices, GetSourceTypeOptions, LookUpInit, BuildTree,
LookUpInit, BuildTree) { SourceChange) {
return function(params) { return function(params) {
var inventory_id = params.inventory_id; var inventory_id = params.inventory_id;
@@ -635,12 +672,13 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
generator.reset(); generator.reset();
var master={}; var master={};
if (scope.removeSearchTreeReady) { if (scope.removeAddTreeRefreshed) {
scope.removeSearchTreeReady(); scope.removeAddTreeRefreshed();
} }
scope.removeSearchTreeReady = scope.$on('searchTreeReady', function(e) { scope.removeAddTreeRefreshed = scope.$on('groupTreeRefreshed', function(e) {
Wait('stop'); Wait('stop');
$('#form-modal').modal('hide'); $('#form-modal').modal('hide');
scope.removeAddTreeRefreshed();
}); });
if (scope.removeSaveComplete) { if (scope.removeSaveComplete) {
@@ -650,7 +688,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
if (!error) { if (!error) {
scope.formModalActionDisabled = false; scope.formModalActionDisabled = false;
scope.showGroupHelp = false; //get rid of the Hint scope.showGroupHelp = false; //get rid of the Hint
BuildTree({ scope: inventory_scope, inventory_id: inventory_id }); BuildTree({ scope: inventory_scope, inventory_id: inventory_id, refresh: true });
} }
}); });
@@ -671,15 +709,15 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
if (scope.source.value !== null && scope.source.value !== '') { if (scope.source.value !== null && scope.source.value !== '') {
var data = { var data = {
group: group_id, group: group_id,
source: scope['source'].value, source: scope['source'].value,
source_path: scope['source_path'], source_path: scope['source_path'],
credential: scope['credential'], credential: scope['credential'],
overwrite: scope['overwrite'], overwrite: scope['overwrite'],
overwrite_vars: scope['overwrite_vars'], overwrite_vars: scope['overwrite_vars'],
update_on_launch: scope['update_on_launch'] update_on_launch: scope['update_on_launch']
//update_interval: scope['update_interval'].value //update_interval: scope['update_interval'].value
}; };
// Create a string out of selected list of regions // Create a string out of selected list of regions
var regions = $('#s2id_group_source_regions').select2("data"); var regions = $('#s2id_group_source_regions').select2("data");
@@ -793,32 +831,18 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
} }
} }
scope.sourceChange = function() { scope.sourceChange = function() {
if (scope['source'].value == 'rax') { SourceChange({
scope['source_region_choices'] = scope['rax_regions']; scope: scope,
//$('#s2id_group_source_regions').select2('data', []); form: GroupForm
$('#s2id_group_source_regions').select2('data', [{ id: 'all', text: 'All' }]); });
} }
else if (scope['source'].value == 'ec2') {
scope['source_region_choices'] = scope['ec2_regions'];
//$('#s2id_group_source_regions').select2('data', []);
$('#s2id_group_source_regions').select2('data', [{ id: 'all', text: 'All' }]);
}
LookUpInit({
url: GetBasePath('credentials') +
'?cloud=true&kind=' + [ (scope.source.value == 'rax') ? 'rax' : 'aws' ],
scope: scope,
form: form,
list: CredentialList,
field: 'credential'
});
}
// Cancel // Cancel
scope.formReset = function() { scope.formReset = function() {
// Defaults // Defaults
generator.reset(); generator.reset();
}; };
var choicesReady = 0; var choicesReady = 0;
@@ -860,10 +884,10 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
.factory('GroupsEdit', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm', .factory('GroupsEdit', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'SetNodeName', 'ParseTypeChange', 'GetSourceTypeOptions', 'InventoryUpdate', 'Prompt', 'ProcessErrors', 'GetBasePath', 'SetNodeName', 'ParseTypeChange', 'GetSourceTypeOptions', 'InventoryUpdate',
'GetUpdateIntervalOptions', 'ClickNode', 'LookUpInit', 'CredentialList', 'Empty', 'Wait', 'GetChoices', 'UpdateGroup', 'GetUpdateIntervalOptions', 'ClickNode', 'LookUpInit', 'Empty', 'Wait', 'GetChoices', 'UpdateGroup', 'SourceChange',
function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors, function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,
GetBasePath, SetNodeName, ParseTypeChange, GetSourceTypeOptions, InventoryUpdate, GetUpdateIntervalOptions, ClickNode, GetBasePath, SetNodeName, ParseTypeChange, GetSourceTypeOptions, InventoryUpdate, GetUpdateIntervalOptions, ClickNode,
LookUpInit, CredentialList, Empty, Wait, GetChoices, UpdateGroup) { LookUpInit, Empty, Wait, GetChoices, UpdateGroup, SourceChange) {
return function(params) { return function(params) {
var group_id = params.group_id; var group_id = params.group_id;
@@ -995,15 +1019,6 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
} }
} }
LookUpInit({
url: GetBasePath('credentials') +
'?cloud=true&kind=' + (scope.source.value == 'rax') ? 'rax' : 'aws',
scope: scope,
form: form,
list: CredentialList,
field: 'credential'
});
scope.sourceChange(); //set defaults that rely on source value scope.sourceChange(); //set defaults that rely on source value
if (data['source_regions']) { if (data['source_regions']) {
@@ -1262,36 +1277,6 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
} }
}; };
scope.sourceChange = function() {
if (scope['source'].value == 'file') {
scope.sourcePathRequired = true;
}
else {
scope.sourcePathRequired = false;
// reset fields
scope.source_path = '';
scope[form.name + '_form']['source_path'].$setValidity('required',true);
}
if (scope['source'].value == 'rax') {
scope['source_region_choices'] = scope['rax_regions'];
//$('#s2id_group_source_regions').select2('data', []);
$('#s2id_group_source_regions').select2('data', [{ id: 'all', text: 'All' }]);
}
else if (scope['source'].value == 'ec2') {
scope['source_region_choices'] = scope['ec2_regions'];
//$('#s2id_group_source_regions').select2('data', []);
$('#s2id_group_source_regions').select2('data', [{ id: 'all', text: 'All' }]);
}
LookUpInit({
url: GetBasePath('credentials') +
'?cloud=true&kind=' + (scope.source.value == 'rax') ? 'rax' : 'aws',
scope: scope,
form: form,
list: CredentialList,
field: 'credential'
});
}
// Start the update process // Start the update process
scope.updateGroup = function() { scope.updateGroup = function() {
if (scope.source == "" || scope.source == null) { if (scope.source == "" || scope.source == null) {
@@ -1323,6 +1308,14 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
} }
} }
// Change the lookup and regions when the source changes
scope.sourceChange = function() {
SourceChange({
scope: scope,
form: GroupForm
});
}
// Cancel // Cancel
scope.formReset = function() { scope.formReset = function() {
generator.reset(); generator.reset();
@@ -1338,20 +1331,37 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
.factory('GroupsDelete', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm', .factory('GroupsDelete', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'Wait', 'ClickNode', 'Prompt', 'ProcessErrors', 'GetBasePath', 'Wait', 'ClickNode', 'BuildTree',
function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors, function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,
GetBasePath, Wait, ClickNode) { GetBasePath, Wait, ClickNode, BuildTree) {
return function(params) { return function(params) {
// Delete the selected group node. Disassociates it from its parent. // Delete the selected group node. Disassociates it from its parent.
var scope = params.scope;
var group_id = params.group_id;
var inventory_id = params.inventory_id;
var obj = scope['selectedNode'];
var parent = obj.parent().parent();
var url;
if (parent.attr('data-group-id')) { var scope = params.scope;
url = GetBasePath('base') + 'groups/' + parent.attr('data-group-id') + '/children/'; var tree_id = params.tree_id;
var inventory_id = params.inventory_id;
var node, parent, url, parent_name;
for (var i=0; i < scope.groups.length; i++) {
if (scope.groups[i].id == tree_id) {
node = scope.groups[i];
}
}
if (node.parent != 0) {
for (var i=0; i < scope.groups.length; i++) {
if (scope.groups[i].id == node.parent) {
parent = scope.groups[i];
parent_name = scope.groups[i].name;
}
}
}
else {
parent_name = scope.inventory_name;
}
if (parent) {
url = GetBasePath('base') + 'groups/' + parent.group_id + '/children/';
} }
else { else {
url = GetBasePath('inventory') + inventory_id + '/groups/'; url = GetBasePath('inventory') + inventory_id + '/groups/';
@@ -1360,37 +1370,33 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
$('#prompt-modal').on('hidden.bs.modal', function(){ Wait('start'); }); $('#prompt-modal').on('hidden.bs.modal', function(){ Wait('start'); });
$('#prompt-modal').modal('hide'); $('#prompt-modal').modal('hide');
Rest.setUrl(url); Rest.setUrl(url);
Rest.post({ id: group_id, disassociate: 1 }) Rest.post({ id: node.group_id, disassociate: 1 })
.success( function(data, status, headers, config) { .success( function(data, status, headers, config) {
//DeleteNode({ selector: '#' + obj.attr('id') });
/*BuildTree({
scope: scope,
inventory_id: scope['inventory_id'],
emit_on_select: 'NodeSelect',
target_id: 'search-tree-container',
refresh: true,
id: parent.attr('id'),
moveable: true
});*/
$('#prompt-modal').off(); $('#prompt-modal').off();
scope.$emit('groupDeleteCompleted'); // Signal a group refresh to start
}) })
.error( function(data, status, headers, config) { .error( function(data, status, headers, config) {
Wait('stop'); Wait('stop');
ProcessErrors(scope, data, status, null, ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status }); { hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status });
}); });
}; };
Prompt({ hdr: 'Delete Group', body: '<p>Are you sure you want to remove group <em>' + node.name +
'</em> from <em>' + parent_name + '</em>?</p>', action: action_to_take,
'class': 'btn-danger' });
//Force binds to work. Not working usual way. //Force binds to work. Not working usual way.
$('#prompt-header').text('Delete Group'); //$('#prompt-header').text('Delete Group');
$('#prompt-body').html('<p>Are you sure you want to remove group <em>' + $(obj).attr('data-name') + '</em> from group <em>' + //$('#prompt-body').html('<p>Are you sure you want to remove group <em>' + $(obj).attr('data-name') + '</em> from group <em>' +
parent.attr('data-name') + '</em>?</p>'); // parent.attr('data-name') + '</em>?</p>');
$('#prompt-action-btn').addClass('btn-danger'); //$('#prompt-action-btn').addClass('btn-danger');
scope.promptAction = action_to_take; // for some reason this binds? //scope.promptAction = action_to_take; // for some reason this binds?
$('#prompt-modal').modal({ //('#prompt-modal').modal({
backdrop: 'static', // backdrop: 'static',
keyboard: true, // keyboard: true,
show: true // show: true
}); // });
} }
}]) }])

View File

@@ -20,11 +20,20 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
var scope = params.scope; var scope = params.scope;
var group_id = params.group_id; var group_id = params.group_id;
var tree_id = params.tree_id
var inventory_id = params.inventory_id; var inventory_id = params.inventory_id;
var url = ( !Empty(group_id) ) ? GetBasePath('groups') + group_id + '/all_hosts/' : var url = ( !Empty(group_id) ) ? GetBasePath('groups') + group_id + '/all_hosts/' :
GetBasePath('inventory') + inventory_id + '/hosts/'; GetBasePath('inventory') + inventory_id + '/hosts/';
for (var i=0; i < scope.groups.length; i++) {
scope.groups[i].selected_class = (scope.groups[i].id == tree_id) ? 'selected' : '';
if (scope.groups[i].id == tree_id) {
scope.selected_group_name = scope.groups[i].name;
}
}
scope.search_place_holder='Search ' + scope.selected_group_name;
SearchInit({ scope: scope, set: 'hosts', list: InventoryHosts, url: url }); SearchInit({ scope: scope, set: 'hosts', list: InventoryHosts, url: url });
PaginateInit({ scope: scope, list: InventoryHosts, url: url }); PaginateInit({ scope: scope, list: InventoryHosts, url: url });
scope.search(InventoryHosts.iterator); scope.search(InventoryHosts.iterator);
@@ -37,10 +46,12 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
var scope = params.scope; var scope = params.scope;
var inventory_id = params.inventory_id; var inventory_id = params.inventory_id;
var group_id = params.group_id;
var tree_id = params.tree_id;
var generator = GenerateList; var generator = GenerateList;
generator.inject(InventoryHosts, { mode: 'edit', id: 'hosts-container', breadCrumbs: false, searchSize: 'col-lg-6 col-md-6 col-sm-6' }); generator.inject(InventoryHosts, { mode: 'edit', id: 'hosts-container', breadCrumbs: false, searchSize: 'col-lg-6 col-md-6 col-sm-6' });
HostsReload({ scope: scope, group_id: null, inventory_id: inventory_id }); HostsReload({ scope: scope, group_id: group_id, tree_id: tree_id, inventory_id: inventory_id });
} }
}]) }])

View File

@@ -23,12 +23,13 @@ angular.module('InventoryGroupsDefinition', [])
fields: { fields: {
name: { name: {
label: 'Group', label: 'Groups',
key: true, key: true,
ngClick: "\{\{ 'showHosts(' + group.id + ',' + group.group_id + ')' \}\}", ngClick: "\{\{ 'showHosts(' + group.id + ',' + group.group_id + ')' \}\}",
ngClass: "group.selected_class", ngClass: "group.selected_class",
hasChildren: true, hasChildren: true,
columnClass: 'col-lg-9' columnClass: 'col-lg-9',
nosort: true
}, },
source: { source: {
label: 'Source', label: 'Source',
@@ -87,7 +88,7 @@ angular.module('InventoryGroupsDefinition', [])
refresh: { refresh: {
mode: 'all', mode: 'all',
awToolTip: "Refresh the page", awToolTip: "Refresh the page",
ngClick: "refresh()" ngClick: "refreshGroups()"
}, },
stream: { stream: {
ngClick: "showActivity()", ngClick: "showActivity()",
@@ -110,6 +111,7 @@ angular.module('InventoryGroupsDefinition', [])
sync_status: { sync_status: {
mode: 'all', mode: 'all',
ngClick: "viewUpdateStatus(\{\{ group.id \}\})", ngClick: "viewUpdateStatus(\{\{ group.id \}\})",
ngShow: "group.id > 1", // hide for all hosts
awToolTip: "\{\{ group.status_tooltip \}\}", awToolTip: "\{\{ group.status_tooltip \}\}",
ngClass: "group.status_class", ngClass: "group.status_class",
dataPlacement: "top" dataPlacement: "top"
@@ -117,6 +119,7 @@ angular.module('InventoryGroupsDefinition', [])
failed_hosts: { failed_hosts: {
mode: 'all', mode: 'all',
awToolTip: "\{\{ group.hosts_status_tip \}\}", awToolTip: "\{\{ group.hosts_status_tip \}\}",
ngShow: "group.id > 1", // hide for all hosts
dataPlacement: "top", dataPlacement: "top",
ngClick: "viewFailedHosts(\{\{ group.id \}\})", ngClick: "viewFailedHosts(\{\{ group.id \}\})",
iconClass: "\{\{ 'fa icon-failures-' + group.hosts_status_class \}\}" iconClass: "\{\{ 'fa icon-failures-' + group.hosts_status_class \}\}"
@@ -125,6 +128,7 @@ angular.module('InventoryGroupsDefinition', [])
//label: 'Sync', //label: 'Sync',
ngClick: 'updateGroup(\{\{ group.id \}\})', ngClick: 'updateGroup(\{\{ group.id \}\})',
awToolTip: "\{\{ group.launch_tooltip \}\}", awToolTip: "\{\{ group.launch_tooltip \}\}",
ngShow: "group.id > 1", // hide for all hosts
ngClass: "group.launch_class", ngClass: "group.launch_class",
dataPlacement: "top" dataPlacement: "top"
}, },
@@ -133,19 +137,21 @@ angular.module('InventoryGroupsDefinition', [])
ngClick: "cancelUpdate(\{\{ group.id \}\}, '\{\{ group.name \}\}')", ngClick: "cancelUpdate(\{\{ group.id \}\}, '\{\{ group.name \}\}')",
awToolTip: "Cancel sync process", awToolTip: "Cancel sync process",
ngClass: "group.cancel_class", ngClass: "group.cancel_class",
ngShow: "group.status == 'running' || group.status == 'pending'", ngShow: "group.id > 1 && (group.status == 'running' || group.status == 'pending')",
dataPlacement: "top" dataPlacement: "top"
}, },
edit: { edit: {
//label: 'Edit', //label: 'Edit',
ngClick: "editGroup(\{\{ group.group_id \}\})", ngClick: "editGroup(\{\{ group.group_id \}\})",
awToolTip: 'Edit group', awToolTip: 'Edit group',
ngShow: "group.id > 1", // hide for all hosts
dataPlacement: "top" dataPlacement: "top"
}, },
"delete": { "delete": {
//label: 'Delete', //label: 'Delete',
ngClick: "deleteGroup(\{\{ group.group_id \}\},'\{\{ group.name \}\}')", ngClick: "deleteGroup(\{\{ group.id \}\})",
awToolTip: 'Delete group', awToolTip: 'Delete group',
ngShow: "group.id != 1", // hide for all hosts
dataPlacement: "top" dataPlacement: "top"
} }
} }

View File

@@ -23,7 +23,7 @@ angular.module('InventoryHostsDefinition', [])
fields: { fields: {
name: { name: {
key: true, key: true,
label: 'Name', label: 'Hosts',
ngClick: "editHost(\{\{ host.id \}\}, '\{\{ host.name \}\}')", ngClick: "editHost(\{\{ host.id \}\}, '\{\{ host.name \}\}')",
searchPlaceholder: "search_place_holder" searchPlaceholder: "search_place_holder"
}, },
@@ -51,14 +51,14 @@ angular.module('InventoryHostsDefinition', [])
searchable: false, searchable: false,
showValue: false showValue: false
}, },
groups: { /*groups: {
label: 'Groups', label: 'Groups',
searchable: true, searchable: true,
sourceModel: 'groups', sourceModel: 'groups',
sourceField: 'name', sourceField: 'name',
nosort: true, nosort: true,
searchPlaceholder: "search_place_holder" searchPlaceholder: "search_place_holder"
}, },*/
enabled: { enabled: {
label: 'Disabled?', label: 'Disabled?',
searchSingleValue: true, searchSingleValue: true,
@@ -72,27 +72,28 @@ angular.module('InventoryHostsDefinition', [])
searchType: 'boolean', searchType: 'boolean',
searchValue: 'true', searchValue: 'true',
searchOnly: true searchOnly: true
}, }
/* ,
has_inventory_sources: { has_inventory_sources: {
label: 'Has external source?', label: 'Has external source?',
searchSingleValue: true, searchSingleValue: true,
searchType: 'boolean', searchType: 'boolean',
searchValue: 'true', searchValue: 'true',
searchOnly: true searchOnly: true
} }*/
}, },
fieldActions: { fieldActions: {
edit: { edit: {
label: 'Edit', label: 'Edit',
ngClick: "editGroup(\{\{ group.id \}\})", ngClick: "editGroup(\{\{ host.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
"class": 'btn-xs btn-primary', "class": 'btn-xs btn-primary',
awToolTip: 'Edit host' awToolTip: 'Edit host'
}, },
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "deleteGroup(\{\{ group.id \}\},'\{\{ group.name \}\}')", ngClick: "deleteHoust(\{\{ host.id \}\},'\{\{ host.name \}\}')",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-xs btn-primary', "class": 'btn-xs btn-primary',
awToolTip: 'Delete host' awToolTip: 'Delete host'

View File

@@ -849,16 +849,21 @@ input[type="checkbox"].checkbox-no-label {
*/ */
.icon-cloud-na, .icon-cloud-na,
.icon-cloud-never { .icon-cloud-never,
a.icon-cloud-na:hover,
a.icon-cloud-never:hover {
color: @grey; color: @grey;
} }
.icon-cloud-updating, .icon-cloud-updating,
.icon-cloud-successful { .icon-cloud-successful,
a.icon-cloud-updating:hover,
a.icon-cloud-successful:hover {
color: @green; color: @green;
} }
.icon-cloud-failed { .icon-cloud-failed,
a.icon-cloud-failed:hover {
color: @red; color: @red;
} }

View File

@@ -177,10 +177,17 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper'])
var inventory_id = params.inventory_id; var inventory_id = params.inventory_id;
var scope = params.scope; var scope = params.scope;
var refresh = params.refresh;
//var selected_id = params. //var selected_id = params.
var groups = []; var groups = [];
var id = 0; var id = 1;
var all_hosts = {
name: 'All Hosts', id: 1, group_id: null, parent: 0, description: '', show: true, ngicon: null,
has_children: false, related: {}, selected_class: '' };
groups.push(all_hosts);
function buildGroups(tree_data, parent, level) { function buildGroups(tree_data, parent, level) {
var sorted = SortNodes(tree_data); var sorted = SortNodes(tree_data);
@@ -243,7 +250,13 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper'])
.success( function(data, status, headers, config) { .success( function(data, status, headers, config) {
buildGroups(data, 0, 0); buildGroups(data, 0, 0);
//console.log(groups); //console.log(groups);
scope.$emit('searchTreeReady', inventory_name, groups); if (refresh) {
scope.groups = groups;
scope.$emit('groupTreeRefreshed');
}
else {
scope.$emit('groupTreeLoaded', inventory_name, groups);
}
}) })
.error( function(data, status, headers, config) { .error( function(data, status, headers, config) {
Wait('stop'); Wait('stop');

View File

@@ -17,18 +17,18 @@
angular.module('PromptDialog', ['Utilities']) angular.module('PromptDialog', ['Utilities'])
.factory('Prompt', ['Alert', function(Alert) { .factory('Prompt', ['Alert', function(Alert) {
return function(params) { return function(params) {
//
var dialog = angular.element(document.getElementById('prompt-modal')); var dialog = angular.element(document.getElementById('prompt-modal'));
var scope = dialog.scope(); var scope = dialog.scope();
scope.promptHeader = params.hdr; scope.promptHeader = params.hdr;
scope.promptBody = params.body; scope.promptBody = params.body;
var cls = (params['class'] == null || params['class'] == undefined) ? 'btn-danger' : params['class'];
$('#prompt_action_btn').addClass(cls); //Use jquery because django template engine conflicts with Angular's
// use of {{...}}
//scope.id = params.id;
//scope.url = params.url;
scope.promptAction = params.action; scope.promptAction = params.action;
var cls = (params['class'] == null || params['class'] == undefined) ? 'btn-danger' : params['class'];
$('#prompt_action_btn').addClass(cls); // Use jquery because django template engine conflicts with Angular's
// use of {{...}}
$(dialog).modal({ $(dialog).modal({
backdrop: 'static', backdrop: 'static',
keyboard: true, keyboard: true,
@@ -37,20 +37,3 @@ angular.module('PromptDialog', ['Utilities'])
} }
}]); }]);
<!-- Generic Modal dialog. Use to confirming an action (i.e. Delete) -->
// <div id="prompt-modal" class="modal hide">
// <div class="modal-header">
// <button type="button" class="close" data-target="#prompt-modal"
// data-dismiss="modal" aria-hidden="true">&times;</button>
// <h3 ng-bind="promptHeader"></h3>
// </div>
// <div class="modal-body" ng-bind="promptBody">
// </div>
// <div class="modal-footer">
// <a href="#" data-target="#prompt-modal" data-dismiss="modal" class="btn">No</a>
// <a href="" ng-click="promptAction()" class="btn {{ promptBtnClass }}">Yes</a>
// </div>
// </div>