From 135d4db94beaa75dd2640e3923a58845853aa99a Mon Sep 17 00:00:00 2001 From: chouseknecht Date: Wed, 5 Jun 2013 15:02:27 -0400 Subject: [PATCH] Users can now be added from the Users tab. --- .../ui/static/js/controllers/Inventories.js | 2 +- .../ui/static/js/controllers/Teams.js | 17 ++--- .../ui/static/js/controllers/Users.js | 67 ++++++++++++++----- .../ui/static/js/forms/Organizations.js | 20 ++++-- ansibleworks/ui/static/js/forms/Users.js | 10 +++ ansibleworks/ui/static/js/lists/Users.js | 4 +- .../ui/static/lib/ansible/form-generator.js | 2 +- .../ui/static/lib/ansible/list-generator.js | 2 +- 8 files changed, 88 insertions(+), 36 deletions(-) diff --git a/ansibleworks/ui/static/js/controllers/Inventories.js b/ansibleworks/ui/static/js/controllers/Inventories.js index 9f758dbec9..ab0b8a82a7 100644 --- a/ansibleworks/ui/static/js/controllers/Inventories.js +++ b/ansibleworks/ui/static/js/controllers/Inventories.js @@ -62,7 +62,7 @@ function InventoriesList ($scope, $rootScope, $location, $log, $routeParams, Res } scope.lookupOrganization = function(organization_id) { - Rest.setUrl('/api/v1/organization/' + organization_id + '/'); + Rest.setUrl(GetBasePath('organizations') + organization_id + '/'); Rest.get() .success( function(data, status, headers, config) { return data.name; diff --git a/ansibleworks/ui/static/js/controllers/Teams.js b/ansibleworks/ui/static/js/controllers/Teams.js index 9eb0ba66b4..d794a4f916 100644 --- a/ansibleworks/ui/static/js/controllers/Teams.js +++ b/ansibleworks/ui/static/js/controllers/Teams.js @@ -12,12 +12,12 @@ function TeamsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, TeamList, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, - ClearScope, ProcessErrors, SetTeamListeners) + ClearScope, ProcessErrors, SetTeamListeners, GetBasePath) { ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior //scope. var list = TeamList; - var defaultUrl = '/api/v1/teams/'; + var defaultUrl = GetBasePath('teams'); var view = GenerateList; var paths = $location.path().replace(/^\//,'').split('/'); var mode = (paths[0] == 'teams') ? 'edit' : 'select'; // if base path 'teams', we're here to add/edit teams @@ -73,7 +73,7 @@ function TeamsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Ale } scope.lookupOrganization = function(organization_id) { - Rest.setUrl('/api/v1/organization/' + organization_id + '/'); + Rest.setUrl(GetBasePath('organizations') + organization_id + '/'); Rest.get() .success( function(data, status, headers, config) { return data.name; @@ -81,7 +81,7 @@ function TeamsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Ale } scope.finishSelection = function() { - Rest.setUrl('/api/v1' + $location.path() + '/'); // We're assuming the path matches the api path. + Rest.setUrl(GetBasePath('base') + $location.path() + '/'); // We're assuming the path matches the api path. // Will this always be true?? scope.queue = []; @@ -160,18 +160,19 @@ function TeamsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Ale TeamsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'TeamList', 'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors', - 'SetTeamListeners' ]; + 'SetTeamListeners', 'GetBasePath' ]; function TeamsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm, GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, - GenerateList, OrganizationList, SearchInit, PaginateInit, TeamLookUpOrganizationInit) + GenerateList, OrganizationList, SearchInit, PaginateInit, TeamLookUpOrganizationInit, + GetBasePath) { ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior //scope. // Inject dynamic view - var defaultUrl = '/api/v1/teams/'; + var defaultUrl = GetBasePath('teams'); var form = TeamForm; var generator = GenerateForm; var scope = generator.inject(form, {mode: 'add', related: false}); @@ -205,7 +206,7 @@ function TeamsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, TeamsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'TeamForm', 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList', - 'OrganizationList', 'SearchInit', 'PaginateInit', 'TeamLookUpOrganizationInit' ]; + 'OrganizationList', 'SearchInit', 'PaginateInit', 'TeamLookUpOrganizationInit', 'GetBasePath']; function TeamsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm, diff --git a/ansibleworks/ui/static/js/controllers/Users.js b/ansibleworks/ui/static/js/controllers/Users.js index f1799873b7..3318f4a523 100644 --- a/ansibleworks/ui/static/js/controllers/Users.js +++ b/ansibleworks/ui/static/js/controllers/Users.js @@ -24,7 +24,7 @@ function UsersList ($scope, $rootScope, $location, $log, $routeParams, Rest, var mode = (base == 'users') ? 'edit' : 'select'; // if base path 'users', we're here to add/edit users var scope = view.inject(UserList, { mode: mode }); // Inject our view scope.selected = []; - + $rootScope.flashMessage = null; SearchInit({ scope: scope, set: 'users', list: list, url: defaultUrl }); PaginateInit({ scope: scope, list: list, url: defaultUrl }); scope.search(list.iterator); @@ -140,13 +140,14 @@ UsersList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams function UsersAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm, - GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope) + GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, + GetBasePath, LookUpInit, OrganizationList) { ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior //scope. // Inject dynamic view - var defaultUrl = '/api/v1/organizations/'; + var defaultUrl = GetBasePath('organizations'); var form = UserForm; var generator = GenerateForm; var scope = generator.inject(form, {mode: 'add', related: false}); @@ -154,20 +155,50 @@ function UsersAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, LoadBreadCrumbs(); + // Configure the lookup dialog. If we're adding a user through the Organizations tab, + // default the Organization value. + LookUpInit({ + scope: scope, + form: form, + current_item: ($routeParams.organization_id !== undefined) ? $routeParams.organization_id : null, + list: OrganizationList, + field: 'organization' + }); + + if ($routeParams.organization_id) { + scope.organization = $routeParams.organization_id; + Rest.setUrl(GetBasePath('organizations') + $routeParams.organization_id + '/'); + Rest.get() + .success( function(data, status, headers, config) { + scope['organization_name'] = data.name; + }) + .error( function(data, status, headers, config) { + ProcessErrors(scope, data, status, form, + { hdr: 'Error!', msg: 'Failed to lookup Organization: ' + data.id + '. GET returned status: ' + status }); + }); + } + // Save scope.formSave = function() { - Rest.setUrl(defaultUrl + $routeParams.organization_id + '/users/'); + Rest.setUrl(defaultUrl + scope.organization + '/users/'); var data = {} for (var fld in form.fields) { data[fld] = scope[fld]; } Rest.post(data) .success( function(data, status, headers, config) { - ReturnToCaller(1); + var base = $location.path().replace(/^\//,'').split('/')[0]; + if (base == 'users') { + $rootScope.flashMessage = 'New user successfully created!'; + $location.path('/users/' + data.id); + } + else { + ReturnToCaller(1); + } }) .error( function(data, status, headers, config) { ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to add new user. Post returned status: ' + status }); + { hdr: 'Error!', msg: 'Failed to add new user. POST returned status: ' + status }); }); }; @@ -186,7 +217,8 @@ function UsersAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, } UsersAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'UserForm', 'GenerateForm', - 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope']; + 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GetBasePath', + 'LookUpInit', 'OrganizationList' ]; function UsersEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm, @@ -194,7 +226,7 @@ function UsersEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, RelatedPaginateInit, ReturnToCaller, ClearScope, GetBasePath) { ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. + //scope. var defaultUrl=GetBasePath('users'); var generator = GenerateForm; @@ -206,8 +238,6 @@ function UsersEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, var id = $routeParams.user_id; var relatedSets = {}; - console.log('here!'); - // After the Organization is loaded, retrieve each related set scope.$on('userLoaded', function() { for (var set in relatedSets) { @@ -222,13 +252,13 @@ function UsersEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, LoadBreadCrumbs({ path: '/users/' + id, title: data.username }); for (var fld in form.fields) { if (data[fld]) { - if (fld == 'is_superuser') { - scope[fld] = (data[fld] == 'true' || data[fld] == true) ? 'true' : 'false'; - } - else { - scope[fld] = data[fld]; - } - master[fld] = scope[fld]; + if (fld == 'is_superuser') { + scope[fld] = (data[fld] == 'true' || data[fld] == true) ? 'true' : 'false'; + } + else { + scope[fld] = data[fld]; + } + master[fld] = scope[fld]; } } var related = data.related; @@ -237,6 +267,7 @@ function UsersEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, relatedSets[set] = { url: related[set], iterator: form.related[set].iterator }; } } + // 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 }); @@ -267,6 +298,7 @@ function UsersEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, // Cancel scope.formReset = function() { + $rootScope.flashMessage = null; generator.reset(); for (var fld in master) { scope[fld] = master[fld]; @@ -278,6 +310,7 @@ function UsersEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, // If password value changes, make sure password_confirm must be re-entered scope[fld] = ''; scope[form.name + '_form'][fld].$setValidity('awpassmatch', false); + $rootScope.flashMessage = null; } diff --git a/ansibleworks/ui/static/js/forms/Organizations.js b/ansibleworks/ui/static/js/forms/Organizations.js index 8fc0c036ff..75ce7806dd 100644 --- a/ansibleworks/ui/static/js/forms/Organizations.js +++ b/ansibleworks/ui/static/js/forms/Organizations.js @@ -58,7 +58,9 @@ angular.module('OrganizationFormDefinition', []) actions: { add: { ngClick: "add('users')", - icon: 'icon-plus' + label: 'Add', + icon: 'icon-plus', + awToolTip: 'Add a new user' }, }, @@ -80,13 +82,15 @@ angular.module('OrganizationFormDefinition', []) label: 'Edit', ngClick: "edit('users', \{\{ user.id \}\}, '\{\{ user.username \}\}')", icon: 'icon-edit', - class: 'btn-success' + class: 'btn-success', + awToolTip: 'Edit user' }, delete: { label: 'Delete', ngClick: "delete('users', \{\{ user.id \}\}, '\{\{ user.username \}\}', 'users')", icon: 'icon-remove', - class: 'btn-danger' + class: 'btn-danger', + awToolTip: 'Remove user' } } }, @@ -100,7 +104,9 @@ angular.module('OrganizationFormDefinition', []) actions: { // Actions displayed top right of list add: { ngClick: "add('admins')", - icon: 'icon-plus' + icon: 'icon-plus', + label: 'Add', + awToolTip: 'Add new administrator' } }, fields: { @@ -120,13 +126,15 @@ angular.module('OrganizationFormDefinition', []) label: 'Edit', ngClick: "edit('users', \{\{ admin.id \}\}, '\{\{ admin.username \}\}')", icon: 'icon-edit', - class: 'btn-success' + class: 'btn-success', + awToolTip: 'Edit administrator' }, delete: { label: 'Delete', ngClick: "delete('admins', \{\{ admin.id \}\}, '\{\{ admin.username \}\}', 'administrators')", icon: 'icon-remove', - class: 'btn-danger' + class: 'btn-danger', + awToolTip: 'Remove administrator' } } } diff --git a/ansibleworks/ui/static/js/forms/Users.js b/ansibleworks/ui/static/js/forms/Users.js index 818dc4e7c0..57cd658a51 100644 --- a/ansibleworks/ui/static/js/forms/Users.js +++ b/ansibleworks/ui/static/js/forms/Users.js @@ -42,6 +42,16 @@ angular.module('UserFormDefinition', []) addRequired: true, editRequired: true }, + organization: { + label: 'Organization', + type: 'lookup', + sourceModel: 'organization', + sourceField: 'name', + addRequired: true, + editRequired: true, + ngClick: 'lookUpOrganization()', + excludeMode: 'edit' + }, password: { label: 'Password', type: 'password', diff --git a/ansibleworks/ui/static/js/lists/Users.js b/ansibleworks/ui/static/js/lists/Users.js index 3c166d11b4..b0c904bbd7 100644 --- a/ansibleworks/ui/static/js/lists/Users.js +++ b/ansibleworks/ui/static/js/lists/Users.js @@ -35,9 +35,9 @@ angular.module('UserListDefinition', []) add: { label: 'Add', icon: 'icon-plus', - mode: 'select', // One of: edit, select, all + mode: 'all', // One of: edit, select, all ngClick: 'addUser()', - basePaths: ['organizations'], // base path must be in list, or action not available + basePaths: ['organizations','users'], // base path must be in list, or action not available class: 'btn-success btn-small', awToolTip: 'Create a new user' } diff --git a/ansibleworks/ui/static/lib/ansible/form-generator.js b/ansibleworks/ui/static/lib/ansible/form-generator.js index 60d3315375..6130e4d5a0 100644 --- a/ansibleworks/ui/static/lib/ansible/form-generator.js +++ b/ansibleworks/ui/static/lib/ansible/form-generator.js @@ -377,7 +377,7 @@ angular.module('FormGenerator', ['GeneratorHelpers']) } //lookup type fields - if (field.type == 'lookup') { + if (field.type == 'lookup' && (field.excludeMode == undefined || field.excludeMode != options.mode)) { html += "
\n"; for (action in list.actions) { if (list.actions[action].mode == 'all' || list.actions[action].mode == options.mode) {