mirror of
https://github.com/ansible/awx.git
synced 2026-01-12 02:19:58 -03:30
Moved inventory detail load procedure from inventory controller to the helper so that it can be called when the detail page first loads and anytime we need to refresh tree data. Working on a way to refresh tree data, re-open previously open nodes and re-select previously active node after add/edit/delete of a group. Any change to tree data should be instantly reflect in the tree in an ajax/async fashion.
This commit is contained in:
parent
9ca489d5ab
commit
b19e1dd97a
@ -348,4 +348,8 @@
|
||||
|
||||
#hosts-title {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
#tree-view {
|
||||
min-height: 100px;
|
||||
}
|
||||
@ -49,7 +49,8 @@ angular.module('ansible', [
|
||||
'JobFormDefinition',
|
||||
'JobEventsListDefinition',
|
||||
'JobEventFormDefinition',
|
||||
'JobHostDefinition'
|
||||
'JobHostDefinition',
|
||||
'GroupsHelper'
|
||||
])
|
||||
.config(['$routeProvider', function($routeProvider) {
|
||||
$routeProvider.
|
||||
|
||||
@ -147,13 +147,13 @@ InventoriesList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$route
|
||||
|
||||
function InventoriesAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
|
||||
GenerateList, OrganizationList, SearchInit, PaginateInit, LookUpInit)
|
||||
GenerateList, OrganizationList, SearchInit, PaginateInit, LookUpInit, GetBasePath)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
// Inject dynamic view
|
||||
var defaultUrl = '/api/v1/inventories/';
|
||||
var defaultUrl = GetBasePath('inventory');
|
||||
var form = InventoryForm;
|
||||
var generator = GenerateForm;
|
||||
var scope = generator.inject(form, {mode: 'add', related: false});
|
||||
@ -197,13 +197,13 @@ function InventoriesAdd ($scope, $rootScope, $compile, $location, $log, $routePa
|
||||
|
||||
InventoriesAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryForm', 'GenerateForm',
|
||||
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList',
|
||||
'OrganizationList', 'SearchInit', 'PaginateInit', 'LookUpInit' ];
|
||||
'OrganizationList', 'SearchInit', 'PaginateInit', 'LookUpInit', 'GetBasePath' ];
|
||||
|
||||
|
||||
function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
|
||||
RelatedPaginateInit, ReturnToCaller, ClearScope, LookUpInit, Prompt,
|
||||
OrganizationList, TreeInit, GetBasePath)
|
||||
OrganizationList, TreeInit, GetBasePath, GroupsList, GroupsEdit, LoadInventory)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
@ -214,11 +214,8 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP
|
||||
var scope = generator.inject(form, {mode: 'edit', related: true});
|
||||
generator.reset();
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
var master = {};
|
||||
var id = $routeParams.id;
|
||||
var relatedSets = {};
|
||||
var hostsUrl;
|
||||
|
||||
|
||||
scope['inventory_id'] = id;
|
||||
|
||||
// Retrieve each related set and any lookups
|
||||
@ -228,47 +225,11 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP
|
||||
scope.inventoryLoadedRemove = scope.$on('inventoryLoaded', function() {
|
||||
scope.groupTitle = 'All Hosts';
|
||||
scope.createButtonShow = false;
|
||||
scope.search(relatedSets['hosts'].iterator);
|
||||
scope.search(scope.relatedSets['hosts'].iterator);
|
||||
TreeInit(scope.TreeParams);
|
||||
});
|
||||
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Rest.setUrl(defaultUrl + ':id/');
|
||||
Rest.get({ params: {id: id} })
|
||||
.success( function(data, status, headers, config) {
|
||||
LoadBreadCrumbs({ path: '/inventories/' + id, title: data.name });
|
||||
for (var fld in form.fields) {
|
||||
if (data[fld]) {
|
||||
scope[fld] = data[fld];
|
||||
master[fld] = scope[fld];
|
||||
}
|
||||
if (form.fields[fld].type == 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) {
|
||||
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
|
||||
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
|
||||
master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
|
||||
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField];
|
||||
}
|
||||
}
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: data.organization,
|
||||
list: OrganizationList,
|
||||
field: 'organization'
|
||||
});
|
||||
|
||||
// Load the tree view
|
||||
TreeInit({ scope: scope, inventory: data });
|
||||
hostsUrl = data.related.hosts;
|
||||
relatedSets['hosts'] = { url: hostsUrl, iterator: 'host' };
|
||||
RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets });
|
||||
RelatedPaginateInit({ scope: scope, relatedSets: relatedSets });
|
||||
scope.$emit('inventoryLoaded');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve inventory: ' + $routeParams.id + '. GET status: ' + status });
|
||||
});
|
||||
LoadInventory({ scope: scope });
|
||||
|
||||
// Save changes to the parent
|
||||
scope.formSave = function() {
|
||||
@ -291,8 +252,8 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
scope[fld] = master[fld];
|
||||
for (var fld in scope.master) {
|
||||
scope[fld] = scope.master[fld];
|
||||
}
|
||||
};
|
||||
|
||||
@ -419,37 +380,42 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP
|
||||
url = node.attr('all');
|
||||
scope.groupAddHide = false;
|
||||
scope.groupEditHide =false;
|
||||
scope.groupDeleteHide = false;
|
||||
scope.createButtonShow = true;
|
||||
scope.group_id = node.attr('group_id');
|
||||
scope.groupName = n.data;
|
||||
scope.groupTitle = n.data;
|
||||
scope.groupTitle += (node.attr('description')) ? ' -' + node.attr('description') : '';
|
||||
}
|
||||
else if (type == 'all-hosts-group') {
|
||||
url = node.attr('url');
|
||||
scope.createButtonShow = false;
|
||||
scope.groupName = 'All Hosts';
|
||||
scope.groupTitle = 'All Hosts';
|
||||
}
|
||||
else if (type == 'inventory') {
|
||||
url = node.attr('hosts');
|
||||
scope.groupAddHide = false;
|
||||
scope.groupEditHide =true;
|
||||
scope.groupDeleteHide = true;
|
||||
scope.createButtonShow = false;
|
||||
scope.groupName = 'All Hosts';
|
||||
scope.groupTitle = 'All Hosts';
|
||||
scope.group_id = null;
|
||||
}
|
||||
relatedSets['hosts'] = { url: url, iterator: 'host' };
|
||||
RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets });
|
||||
RelatedPaginateInit({ scope: scope, relatedSets: relatedSets });
|
||||
scope.relatedSets['hosts'] = { url: url, iterator: 'host' };
|
||||
RelatedSearchInit({ scope: scope, form: form, relatedSets: scope.relatedSets });
|
||||
RelatedPaginateInit({ scope: scope, relatedSets: scope.relatedSets });
|
||||
scope.search('host');
|
||||
scope.$digest();
|
||||
});
|
||||
|
||||
scope.addGroup = function() {
|
||||
GroupsList({ "inventory_id": id, group_id: scope.group_id });
|
||||
}
|
||||
|
||||
scope.editGroup = function() {
|
||||
GroupsEdit({ "inventory_id": id, group_id: scope.group_id });
|
||||
}
|
||||
}
|
||||
|
||||
InventoriesEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryForm',
|
||||
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
|
||||
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'LookUpInit', 'Prompt',
|
||||
'OrganizationList', 'TreeInit', 'GetBasePath'
|
||||
'OrganizationList', 'TreeInit', 'GetBasePath', 'GroupsList', 'GroupsEdit', 'LoadInventory'
|
||||
];
|
||||
|
||||
@ -13,7 +13,7 @@ angular.module('GroupFormDefinition', [])
|
||||
addTitle: 'Create Group', //Legend in add mode
|
||||
editTitle: '{{ name }}', //Legend in edit mode
|
||||
name: 'group', //Form name attribute
|
||||
well: true, //Wrap the form with TB well
|
||||
well: false, //Wrap the form with TB well
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
@ -34,7 +34,6 @@ angular.module('GroupFormDefinition', [])
|
||||
addRequired: false,
|
||||
editRequird: false,
|
||||
rows: 10,
|
||||
class: 'span12',
|
||||
default: "\{\}",
|
||||
dataTitle: 'Group Variables',
|
||||
dataPlacement: 'right',
|
||||
|
||||
381
ansibleworks/ui/static/js/helpers/Groups.js
Normal file
381
ansibleworks/ui/static/js/helpers/Groups.js
Normal file
@ -0,0 +1,381 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* InventoryHelper
|
||||
* Routines for building the tree. Everything related to the tree is here except
|
||||
* for the menu piece. The routine for building the menu is in InventoriesEdit controller
|
||||
* (controllers/Inventories.js)
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'GroupListDefinition',
|
||||
'SearchHelper', 'PaginateHelper', 'ListGenerator', 'AuthService', 'GroupsHelper',
|
||||
'InventoryHelper'
|
||||
])
|
||||
|
||||
.factory('GroupsList', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupList', 'GenerateList',
|
||||
'Prompt', 'SearchInit', 'PaginateInit', 'ProcessErrors', 'GetBasePath', 'GroupsAdd', 'RefreshTree',
|
||||
function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupList, GenerateList, LoadBreadCrumbs, SearchInit,
|
||||
PaginateInit, ProcessErrors, GetBasePath, GroupsAdd, RefreshTree) {
|
||||
return function(params) {
|
||||
|
||||
var inventory_id = params.inventory_id;
|
||||
var group_id = (params.group_id !== undefined) ? params.group_id : null;
|
||||
|
||||
var list = GroupList;
|
||||
var defaultUrl = GetBasePath('inventory') + inventory_id + '/groups/';
|
||||
var view = GenerateList;
|
||||
|
||||
var scope = view.inject(GroupList, {
|
||||
id: 'form-modal-body',
|
||||
mode: 'select',
|
||||
breadCrumbs: false,
|
||||
selectButton: false
|
||||
});
|
||||
|
||||
scope.formModalActionLabel = 'Finished'
|
||||
scope.formModalHeader = 'Add Group'
|
||||
|
||||
$('#form-modal').modal();
|
||||
|
||||
scope.selected = [];
|
||||
|
||||
if (scope.PostRefreshRemove) {
|
||||
scope.PostRefreshRemove();
|
||||
}
|
||||
scope.PostRefreshRemove = scope.$on('PostRefresh', function() {
|
||||
$("tr.success").each(function(index) {
|
||||
var ngc = $(this).attr('ng-class');
|
||||
scope[ngc] = "";
|
||||
});
|
||||
if ($routeParams.group_id) {
|
||||
// Remove the current group from the list of available groups, thus
|
||||
// preventing a group from being added to itself
|
||||
for (var i=0; i < scope.groups.length; i++) {
|
||||
if (scope.groups[i].id == $routeParams.group_id) {
|
||||
scope.groups.splice(i,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
//scope.$digest();
|
||||
});
|
||||
|
||||
SearchInit({ scope: scope, set: 'groups', list: list, url: defaultUrl });
|
||||
PaginateInit({ scope: scope, list: list, url: defaultUrl });
|
||||
scope.search(list.iterator);
|
||||
|
||||
/*LoadBreadCrumbs();*/
|
||||
|
||||
scope.editGroup = function(id) {
|
||||
$location.path($location.path() + '/' + id);
|
||||
}
|
||||
|
||||
scope.deleteGroup = function(id, name) {
|
||||
|
||||
var action = function() {
|
||||
var url = defaultUrl;
|
||||
Rest.setUrl(url);
|
||||
Rest.post({ id: id, disassociate: 1 })
|
||||
.success( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
scope.search(list.iterator);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
ProcessErrors(scope, data, status, null,
|
||||
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
Prompt({ hdr: 'Delete',
|
||||
body: 'Are you sure you want to remove group' + name + '?',
|
||||
action: action
|
||||
});
|
||||
}
|
||||
|
||||
scope.formModalAction = function() {
|
||||
var url = (group_id) ? GetBasePath('groups') + group_id + '/children/' :
|
||||
GetBasePath('inventory') + inventory_id + '/groups/';
|
||||
Rest.setUrl(url);
|
||||
scope.queue = [];
|
||||
|
||||
if (scope.callFinishedRemove) {
|
||||
scope.callFinishedRemove();
|
||||
}
|
||||
scope.callFinishedRemove = scope.$on('callFinished', function() {
|
||||
// We call the API for each selected item. We need to hang out until all the api
|
||||
// calls are finished.
|
||||
if (scope.queue.length == scope.selected.length) {
|
||||
// All the api calls finished
|
||||
$('input[type="checkbox"]').prop("checked",false);
|
||||
scope.selected = [];
|
||||
var errors = 0;
|
||||
for (var i=0; i < scope.queue.length; i++) {
|
||||
if (scope.queue[i].result == 'error') {
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
if (errors > 0) {
|
||||
Alert('Error', 'There was an error while adding one or more of the selected groups.');
|
||||
}
|
||||
else {
|
||||
$('#form-modal').modal('hide');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (scope.selected.length > 0 ) {
|
||||
var group;
|
||||
for (var i=0; i < scope.selected.length; i++) {
|
||||
group = null;
|
||||
for (var j=0; j < scope.groups.length; j++) {
|
||||
if (scope.groups[j].id == scope.selected[i]) {
|
||||
group = scope.groups[j];
|
||||
}
|
||||
}
|
||||
if (group !== null) {
|
||||
Rest.post(group)
|
||||
.success( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'success', data: data, status: status });
|
||||
scope.$emit('callFinished');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'error', data: data, status: status, headers: headers });
|
||||
scope.$emit('callFinished');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$('#form-modal').modal('hide');
|
||||
}
|
||||
}
|
||||
|
||||
scope.toggle_group = function(id) {
|
||||
if (scope[list.iterator + "_" + id + "_class"] == "success") {
|
||||
scope[list.iterator + "_" + id + "_class"] = "";
|
||||
document.getElementById('check_' + id).checked = false;
|
||||
if (scope.selected.indexOf(id) > -1) {
|
||||
scope.selected.splice(scope.selected.indexOf(id),1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
scope[list.iterator + "_" + id + "_class"] = "success";
|
||||
document.getElementById('check_' + id).checked = true;
|
||||
if (scope.selected.indexOf(id) == -1) {
|
||||
scope.selected.push(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scope.createGroup = function() {
|
||||
$('#form-modal').modal('hide');
|
||||
GroupsAdd({ inventory_id: inventory_id, group_id: group_id });
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}])
|
||||
|
||||
|
||||
|
||||
.factory('GroupsAdd', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
|
||||
'Prompt', 'ProcessErrors', 'GetBasePath',
|
||||
function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,
|
||||
GetBasePath) {
|
||||
return function(params) {
|
||||
|
||||
var inventory_id = params.inventory_id;
|
||||
var group_id = (params.group_id !== undefined) ? params.group_id : null;
|
||||
|
||||
// Inject dynamic view
|
||||
var defaultUrl = (group_id !== null) ? GetBasePath('groups') + group_id + '/children/' :
|
||||
GetBasePath('inventory') + inventory_id + '/groups/';
|
||||
var form = GroupForm;
|
||||
var generator = GenerateForm;
|
||||
var scope = generator.inject(form, {mode: 'add', modal: true, related: false});
|
||||
scope.formModalActionLabel = 'Save'
|
||||
scope.formModalHeader = 'Create Group'
|
||||
generator.reset();
|
||||
var master={};
|
||||
|
||||
// Save
|
||||
scope.formModalAction = function() {
|
||||
try {
|
||||
// Make sure we have valid JSON
|
||||
var myjson = JSON.parse(scope.variables);
|
||||
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
if (fld != 'variables') {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
}
|
||||
|
||||
if (inventory_id) {
|
||||
data['inventory'] = inventory_id;
|
||||
}
|
||||
|
||||
Rest.setUrl(defaultUrl);
|
||||
Rest.post(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
if (scope.variables) {
|
||||
Rest.setUrl(data.related.variable_data);
|
||||
Rest.put({data: scope.variables})
|
||||
.success( function(data, status, headers, config) {
|
||||
$('#form-modal').modal('hide');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to add group varaibles. PUT returned status: ' + status });
|
||||
});
|
||||
}
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to add new group. Post returned status: ' + status });
|
||||
});
|
||||
}
|
||||
catch(err) {
|
||||
Alert("Error", "Error parsing group variables. Expecting valid JSON. Parser returned " + err);
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
// Defaults
|
||||
generator.reset();
|
||||
};
|
||||
|
||||
}
|
||||
}])
|
||||
|
||||
.factory('GroupsEdit', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
|
||||
'Prompt', 'ProcessErrors', 'GetBasePath',
|
||||
function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,
|
||||
GetBasePath) {
|
||||
return function(params) {
|
||||
|
||||
var group_id = params.group_id;
|
||||
var generator = GenerateForm;
|
||||
var form = GroupForm;
|
||||
var defaultUrl = GetBasePath('groups') + group_id + '/';
|
||||
var scope = generator.inject(form, { mode: 'edit', modal: true, related: false});
|
||||
generator.reset();
|
||||
var master = {};
|
||||
var relatedSets = {};
|
||||
|
||||
scope.formModalActionLabel = 'Save'
|
||||
scope.formModalHeader = 'Edit Group'
|
||||
|
||||
// After the group record is loaded, retrieve any group variables
|
||||
if (scope.groupLoadedRemove) {
|
||||
scope.groupLoadedRemove();
|
||||
}
|
||||
scope.groupLoadedRemove = scope.$on('groupLoaded', function() {
|
||||
for (var set in relatedSets) {
|
||||
scope.search(relatedSets[set].iterator);
|
||||
}
|
||||
if (scope.variable_url) {
|
||||
Rest.setUrl(scope.variable_url);
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
if ($.isEmptyObject(data.data)) {
|
||||
scope.variables = "\{\}";
|
||||
}
|
||||
else {
|
||||
scope.variables = data.data;
|
||||
}
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
scope.variables = null;
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve host variables. GET returned status: ' + status });
|
||||
});
|
||||
}
|
||||
else {
|
||||
scope.variables = "\{\}";
|
||||
}
|
||||
});
|
||||
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Rest.setUrl(defaultUrl);
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
LoadBreadCrumbs();
|
||||
for (var fld in form.fields) {
|
||||
if (data[fld]) {
|
||||
scope[fld] = data[fld];
|
||||
master[fld] = scope[fld];
|
||||
}
|
||||
}
|
||||
var related = data.related;
|
||||
for (var set in form.related) {
|
||||
if (related[set]) {
|
||||
relatedSets[set] = { url: related[set], iterator: form.related[set].iterator };
|
||||
}
|
||||
}
|
||||
|
||||
scope.variable_url = data.related.variable_data;
|
||||
|
||||
// Initialize related search functions. Doing it here to make sure relatedSets object is populated.
|
||||
RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets });
|
||||
RelatedPaginateInit({ scope: scope, relatedSets: relatedSets });
|
||||
scope.$emit('groupLoaded');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve group: ' + id + '. GET status: ' + status });
|
||||
});
|
||||
|
||||
// Save changes to the parent
|
||||
scope.formModalAction = function() {
|
||||
try {
|
||||
// Make sure we have valid JSON
|
||||
var myjson = JSON.parse(scope.variables);
|
||||
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
|
||||
Rest.setUrl(defaultUrl);
|
||||
Rest.put(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
if (scope.variables) {
|
||||
//update group variables
|
||||
Rest.setUrl(GetBasePath('groups') + data.id + '/variable_data/');
|
||||
Rest.put({data: scope.variables})
|
||||
.success( function(data, status, headers, config) {
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
(base == 'groups') ? ReturnToCaller() : ReturnToCaller(1);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to update group varaibles. PUT returned status: ' + status });
|
||||
});
|
||||
}
|
||||
$('#form-modal').modal('hide');
|
||||
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to update group: ' + id + '. PUT status: ' + status });
|
||||
});
|
||||
}
|
||||
catch(err) {
|
||||
Alert("Error", "Error parsing group variables. Expecting valid JSON. Parser returned " + err);
|
||||
}
|
||||
};
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
scope[fld] = master[fld];
|
||||
}
|
||||
}
|
||||
}
|
||||
}]);
|
||||
|
||||
|
||||
@ -9,10 +9,12 @@
|
||||
*/
|
||||
|
||||
angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationListDefinition',
|
||||
'SearchHelper', 'PaginateHelper', 'ListGenerator', 'AuthService'
|
||||
'SearchHelper', 'PaginateHelper', 'ListGenerator', 'AuthService',
|
||||
'InventoryHelper', 'RelatedSearchHelper', 'RelatedPaginateHelper',
|
||||
'InventoryFormDefinition'
|
||||
])
|
||||
|
||||
.factory('TreeInit', ['Alert', 'Rest', 'Authorization', '$http',
|
||||
.factory('LoadTreeData', ['Alert', 'Rest', 'Authorization', '$http',
|
||||
function(Alert, Rest, Authorization, $http) {
|
||||
return function(params) {
|
||||
|
||||
@ -24,15 +26,95 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
|
||||
var inventory_url = inventory.url;
|
||||
var inventory_id = inventory.id;
|
||||
var inventory_descr = inventory.description;
|
||||
var tree_id = '#tree-view';
|
||||
var idx=0;
|
||||
var treeData = [];
|
||||
|
||||
// Ater inventory top-level hosts, load top-level groups
|
||||
if (scope.HostLoadedRemove) {
|
||||
scope.HostLoadedRemove();
|
||||
}
|
||||
scope.HostLoadedRemove = scope.$on('hostsLoaded', function() {
|
||||
Rest.setUrl(groups + '?order_by=name');
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
for (var i=0; i < data.results.length; i++) {
|
||||
treeData[0].children.push({
|
||||
data: {
|
||||
title: data.results[i].name
|
||||
},
|
||||
attr: {
|
||||
id: idx,
|
||||
group_id: data.results[i].id,
|
||||
type: 'group',
|
||||
name: data.results[i].name,
|
||||
description: data.results[i].description,
|
||||
inventory: data.results[i].inventory,
|
||||
all: data.results[i].related.all_hosts,
|
||||
children: data.results[i].related.children,
|
||||
hosts: data.results[i].related.hosts,
|
||||
variable: data.results[i].related.variable_data
|
||||
},
|
||||
state: 'closed'
|
||||
});
|
||||
idx++;
|
||||
}
|
||||
scope.$emit('buildTree', treeData, idx);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
Alert('Error', 'Failed to laod tree data. Url: ' + groups + ' GET status: ' + status);
|
||||
});
|
||||
});
|
||||
|
||||
// Setup tree_data
|
||||
Rest.setUrl(hosts + '?order_by=name');
|
||||
Rest.get()
|
||||
.success ( function(data, status, headers, config) {
|
||||
treeData =
|
||||
[{
|
||||
data: {
|
||||
title: inventory_name
|
||||
},
|
||||
attr: {
|
||||
type: 'inventory',
|
||||
id: 'inventory-node',
|
||||
url: inventory_url,
|
||||
'inventory_id': inventory_id,
|
||||
hosts: hosts,
|
||||
name: inventory_name,
|
||||
description: inventory_descr
|
||||
},
|
||||
state: 'open',
|
||||
children:[]
|
||||
}];
|
||||
scope.$emit('hostsLoaded');
|
||||
})
|
||||
.error ( function(data, status, headers, config) {
|
||||
Alert('Error', 'Failed to laod tree data. Url: ' + hosts + ' GET status: ' + status);
|
||||
});
|
||||
}
|
||||
}])
|
||||
|
||||
|
||||
.factory('TreeInit', ['Alert', 'Rest', 'Authorization', '$http', 'LoadTreeData',
|
||||
function(Alert, Rest, Authorization, $http, LoadTreeData) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var inventory = params.inventory;
|
||||
var groups = inventory.related.root_groups;
|
||||
var hosts = inventory.related.hosts;
|
||||
var inventory_name = inventory.name;
|
||||
var inventory_url = inventory.url;
|
||||
var inventory_id = inventory.id;
|
||||
var inventory_descr = inventory.description;
|
||||
var tree_id = '#tree-view';
|
||||
|
||||
// After loading the Inventory top-level data, initialize the tree
|
||||
if (scope.buildTreeRemove) {
|
||||
scope.buildTreeRemove();
|
||||
}
|
||||
scope.buildTreeRemove = scope.$on('buildTree', function() {
|
||||
scope.buildTreeRemove = scope.$on('buildTree', function(e, treeData, index) {
|
||||
var idx = index;
|
||||
$(tree_id).jstree({
|
||||
"core": { "initially_open":['inventory-node'] },
|
||||
"plugins": ['themes', 'json_data', 'ui', 'contextmenu'],
|
||||
@ -83,75 +165,73 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
|
||||
});
|
||||
|
||||
// When user clicks on a group, display the related hosts in the list view
|
||||
$(tree_id).bind("select_node.jstree", function(evt, data){
|
||||
$(tree_id).bind("select_node.jstree", function(e, data){
|
||||
//selected node object: data.inst.get_json()[0];
|
||||
//selected node text: data.inst.get_json()[0].data
|
||||
scope.$emit('NodeSelect',data.inst.get_json()[0]);
|
||||
});
|
||||
});
|
||||
|
||||
LoadTreeData(params);
|
||||
|
||||
// Ater inventory top-level hosts, load top-level groups
|
||||
if (scope.HostLoadedRemove) {
|
||||
scope.HostLoadedRemove();
|
||||
}
|
||||
scope.HostLoadedRemove = scope.$on('hostsLoaded', function() {
|
||||
Rest.setUrl(groups + '?order_by=name');
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
for (var i=0; i < data.results.length; i++) {
|
||||
treeData[0].children.push({
|
||||
data: {
|
||||
title: data.results[i].name
|
||||
},
|
||||
attr: {
|
||||
id: idx,
|
||||
group_id: data.results[i].id,
|
||||
type: 'group',
|
||||
name: data.results[i].name,
|
||||
description: data.results[i].description,
|
||||
inventory: data.results[i].inventory,
|
||||
all: data.results[i].related.all_hosts,
|
||||
children: data.results[i].related.children,
|
||||
hosts: data.results[i].related.hosts,
|
||||
variable: data.results[i].related.variable_data
|
||||
},
|
||||
state: 'closed'
|
||||
});
|
||||
idx++;
|
||||
}
|
||||
scope.$emit('buildTree');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
Alert('Error', 'Failed to laod tree data. Url: ' + groups + ' GET status: ' + status);
|
||||
});
|
||||
});
|
||||
}])
|
||||
|
||||
// Setup tree_data
|
||||
Rest.setUrl(hosts + '?order_by=name');
|
||||
|
||||
.factory('RefreshTree', ['Alert', 'Rest', 'Authorization', '$http', 'TreeInit',
|
||||
function(Alert, Rest, Authorization, $http, TreeInit) {
|
||||
return function(params) {
|
||||
|
||||
$('#tree-view').jstree('destroy');
|
||||
|
||||
TreeInit(params);
|
||||
|
||||
}
|
||||
}])
|
||||
|
||||
|
||||
.factory('LoadInventory', ['$routeParams', 'Alert', 'Rest', 'Authorization', '$http', 'RefreshTree', 'ProcessErrors',
|
||||
'RelatedSearchInit', 'RelatedPaginateInit', 'GetBasePath', 'LoadBreadCrumbs', 'InventoryForm',
|
||||
function($routeParams, Alert, Rest, Authorization, $http, RefreshTree ,ProcessErrors, RelatedSearchInit, RelatedPaginateInit,
|
||||
GetBasePath, LoadBreadCrumbs, InventoryForm) {
|
||||
return function(params) {
|
||||
|
||||
// Load inventory detail record
|
||||
|
||||
var scope = params.scope;
|
||||
var form = InventoryForm;
|
||||
scope.relatedSets = [];
|
||||
scope.master = {};
|
||||
|
||||
Rest.setUrl(GetBasePath('inventory') + $routeParams.id + '/');
|
||||
Rest.get()
|
||||
.success ( function(data, status, headers, config) {
|
||||
treeData =
|
||||
[{
|
||||
data: {
|
||||
title: inventory_name
|
||||
},
|
||||
attr: {
|
||||
type: 'inventory',
|
||||
id: 'inventory-node',
|
||||
url: inventory_url,
|
||||
'inventory_id': inventory_id,
|
||||
hosts: hosts,
|
||||
name: inventory_name,
|
||||
description: inventory_descr
|
||||
},
|
||||
state: 'open',
|
||||
children:[]
|
||||
}];
|
||||
scope.$emit('hostsLoaded');
|
||||
})
|
||||
.error ( function(data, status, headers, config) {
|
||||
Alert('Error', 'Failed to laod tree data. Url: ' + hosts + ' GET status: ' + status);
|
||||
});
|
||||
.success( function(data, status, headers, config) {
|
||||
LoadBreadCrumbs({ path: '/inventories/' + $routeParams.id, title: data.name });
|
||||
for (var fld in form.fields) {
|
||||
if (data[fld]) {
|
||||
scope[fld] = data[fld];
|
||||
scope.master[fld] = scope[fld];
|
||||
}
|
||||
if (form.fields[fld].type == 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) {
|
||||
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
|
||||
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
|
||||
scope.master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
|
||||
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField];
|
||||
}
|
||||
}
|
||||
|
||||
// Load the tree view
|
||||
scope.TreeParams = { scope: scope, inventory: data };
|
||||
scope.relatedSets['hosts'] = { url: data.related.hosts, iterator: 'host' };
|
||||
RelatedSearchInit({ scope: scope, form: form, relatedSets: scope.relatedSets });
|
||||
RelatedPaginateInit({ scope: scope, relatedSets: scope.relatedSets });
|
||||
scope.$emit('inventoryLoaded');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve inventory: ' + $routeParams.id + '. GET status: ' + status });
|
||||
});
|
||||
|
||||
}
|
||||
}]);
|
||||
|
||||
|
||||
@ -14,8 +14,9 @@ angular.module('GroupListDefinition', [])
|
||||
iterator: 'group',
|
||||
selectTitle: 'Add Group',
|
||||
editTitle: 'Groups',
|
||||
selectInstructions: 'Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> button to create a new row.',
|
||||
selectInstructions: 'Click on a row to select it, and Finished when done. Click the green <i class=\"icon-plus\"></i> Add to create a new row.',
|
||||
index: true,
|
||||
well: false,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
@ -32,7 +33,7 @@ angular.module('GroupListDefinition', [])
|
||||
label: 'Add',
|
||||
icon: 'icon-plus',
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addGroup()',
|
||||
ngClick: 'createGroup()',
|
||||
class: 'btn-success btn-small',
|
||||
awToolTip: 'Create a new group'
|
||||
}
|
||||
|
||||
@ -76,9 +76,12 @@ angular.module('FormGenerator', ['GeneratorHelpers'])
|
||||
element = angular.element(document.getElementById('form-modal-body'));
|
||||
}
|
||||
else {
|
||||
var element = angular.element(document.getElementById('htmlTemplate'));
|
||||
element = angular.element(document.getElementById('htmlTemplate'));
|
||||
}
|
||||
|
||||
this.mode = options.mode;
|
||||
this.modal = (options.modal) ? true : false;
|
||||
|
||||
this.setForm(form);
|
||||
element.html(this.build(options)); // Inject the html
|
||||
this.scope = element.scope(); // Set scope specific to the element we're compiling, avoids circular reference
|
||||
@ -94,12 +97,9 @@ angular.module('FormGenerator', ['GeneratorHelpers'])
|
||||
}
|
||||
|
||||
if (options.modal) {
|
||||
(options.mode == 'add') ? scope.formHeader = form.addTitle : form.editTitle;
|
||||
this.scope.formHeader = (options.mode == 'add') ? form.addTitle : form.editTitle;
|
||||
$('#form-modal').modal();
|
||||
}
|
||||
|
||||
this.mode = options.mode;
|
||||
this.modal = (options.modal) ? true : false;
|
||||
|
||||
return this.scope;
|
||||
},
|
||||
@ -641,8 +641,12 @@ angular.module('FormGenerator', ['GeneratorHelpers'])
|
||||
if (form.related[itm].type == 'tree') {
|
||||
html += "<div class=\"span5\">";
|
||||
html += "<div class=\"inventory-buttons pull-right\">";
|
||||
html += "<button ng-hide=\"groupAddHide\" id=\"inv-group-add\" class=\"btn btn-mini btn-success\"><i class=\"icon-plus\"></i> Add Group</button>";
|
||||
html += "<button ng-hide=\"groupEditHide\" id=\"inv-group-edit\" class=\"btn btn-mini btn-success\"><i class=\"icon-edit\"></i> Edit Group</button>";
|
||||
html += "<button ng-click=\"addGroup()\" ng-hide=\"groupAddHide\" id=\"inv-group-add\" " +
|
||||
"class=\"btn btn-mini btn-success\"><i class=\"icon-plus\"></i> Add Group</button>";
|
||||
html += "<button ng-hide=\"groupEditHide\" id=\"inv-group-edit\" class=\"btn btn-mini btn-success\">" +
|
||||
"<i class=\"icon-edit\"></i> Edit Group</button>";
|
||||
html += "<button ng-hide=\"groupDeleteHide\" id=\"inv-group-delete\" class=\"btn btn-mini btn-danger\">" +
|
||||
"<i class=\"icon-remove\"></i> Delete Group</button>";
|
||||
html += "</div>\n";
|
||||
html += "<div id=\"tree-view\"></div>\n";
|
||||
html += "</div>\n";
|
||||
|
||||
@ -67,7 +67,10 @@ angular.module('ListGenerator', ['GeneratorHelpers',])
|
||||
// For options.mode == 'lookup', include the following:
|
||||
//
|
||||
// hdr: <lookup dialog header>
|
||||
//
|
||||
//
|
||||
// Inject into a custom element using options.id: <'.selector'>
|
||||
// Control breadcrumb creation with options.breadCrumbs: <true | false>
|
||||
//
|
||||
if (options.mode == 'lookup') {
|
||||
var element = angular.element(document.getElementById('lookup-modal-body'));
|
||||
}
|
||||
@ -130,7 +133,7 @@ angular.module('ListGenerator', ['GeneratorHelpers',])
|
||||
html += "</div>\n";
|
||||
}
|
||||
|
||||
if (options.mode != 'lookup') {
|
||||
if (options.mode != 'lookup' && (list.well == undefined || list.well == 'true')) {
|
||||
html += "<div class=\"well\">\n";
|
||||
}
|
||||
|
||||
@ -161,7 +164,7 @@ angular.module('ListGenerator', ['GeneratorHelpers',])
|
||||
}
|
||||
}
|
||||
}
|
||||
if (options.mode == 'select') {
|
||||
if (options.mode == 'select' && (options.selectButton == undefined || options.selectButton == true)) {
|
||||
html += " <button class=\"btn btn-small btn-success\" aw-tool-tip=\"Complete your selection\" " +
|
||||
"ng-click=\"finishSelection()\"><i class=\"icon-ok\"></i> Finished</button>\n";
|
||||
}
|
||||
@ -272,7 +275,7 @@ angular.module('ListGenerator', ['GeneratorHelpers',])
|
||||
html += "</tbody>\n";
|
||||
html += "</table>\n";
|
||||
|
||||
if (options.mode != 'lookup') {
|
||||
if (options.mode != 'lookup' && (list.well == undefined || list.well == 'true')) {
|
||||
html += "</div>\n"; //well
|
||||
}
|
||||
|
||||
|
||||
@ -72,6 +72,7 @@
|
||||
<script src="{{ STATIC_URL }}js/helpers/teams.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/helpers/JobTemplate.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/helpers/Lookup.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/helpers/Groups.js"></script>
|
||||
<script src="{{ STATIC_URL }}lib/ansible/directives.js"></script>
|
||||
<script src="{{ STATIC_URL }}lib/ansible/filters.js"></script>
|
||||
<script src="{{ STATIC_URL }}lib/ansible/api-loader.js"></script>
|
||||
@ -165,6 +166,20 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Generic Form dialog -->
|
||||
<div id="form-modal" class="modal hide">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-target="#alert-modal"
|
||||
data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3 ng-bind="formModalHeader"></h3>
|
||||
</div>
|
||||
<div class="modal-body" id="form-modal-body"></div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" data-target="#form-modal" data-dismiss="modal" class="btn btn">Cancel</a>
|
||||
<a href="" ng-bind="formModalActionLabel" ng-click="formModalAction()" class="btn btn-success"></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Alerts/error handling dialog -->
|
||||
<div id="alert-modal" class="modal hide">
|
||||
<div class="modal-header">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user