diff --git a/awx/ui/static/js/app.js b/awx/ui/static/js/app.js index 7450b28805..2949170ea0 100644 --- a/awx/ui/static/js/app.js +++ b/awx/ui/static/js/app.js @@ -60,7 +60,8 @@ angular.module('ansible', [ 'EventsHelper', 'ProjectPathHelper', 'md5Helper', - 'AccessHelper' + 'AccessHelper', + 'SelectionHelper' ]) .config(['$routeProvider', function($routeProvider) { $routeProvider. diff --git a/awx/ui/static/js/controllers/Credentials.js b/awx/ui/static/js/controllers/Credentials.js index c9cf9d0334..0898fce615 100644 --- a/awx/ui/static/js/controllers/Credentials.js +++ b/awx/ui/static/js/controllers/Credentials.js @@ -12,7 +12,7 @@ function CredentialsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, CredentialList, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, - ClearScope, ProcessErrors, GetBasePath) + ClearScope, ProcessErrors, GetBasePath, SelectionInit) { ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior //scope. @@ -24,16 +24,7 @@ function CredentialsList ($scope, $rootScope, $location, $log, $routeParams, Res var scope = view.inject(list, { mode: mode }); // Inject our view scope.selected = []; - if (scope.PostRefreshRemove) { - scope.PostRefreshRemove(); - } - scope.PostRefreshRemove = scope.$on('PostRefresh', function() { - $("tr.success").each(function(index) { - // Make sure no rows have a green background - var ngc = $(this).attr('ng-class'); - scope[ngc] = ""; - }); - }); + SelectionInit({ scope: scope, list: list }); SearchInit({ scope: scope, set: 'credentials', list: list, url: defaultUrl }); PaginateInit({ scope: scope, list: list, url: defaultUrl }); @@ -125,28 +116,11 @@ function CredentialsList ($scope, $rootScope, $location, $log, $routeParams, Res ReturnToCaller(); } } - - scope.toggle_credential = 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); - } - } - } } CredentialsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'CredentialList', 'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors', - 'GetBasePath']; + 'GetBasePath', 'SelectionInit']; function CredentialsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm, diff --git a/awx/ui/static/js/controllers/Inventories.js b/awx/ui/static/js/controllers/Inventories.js index 845e98ace4..e2fdc8b115 100644 --- a/awx/ui/static/js/controllers/Inventories.js +++ b/awx/ui/static/js/controllers/Inventories.js @@ -294,7 +294,7 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP LookUpInit({ scope: scope, form: form, - current_item: (scope.organization) ? scope.organization : null, + current_item: (scope.organization !== undefined) ? scope.organization : null, list: OrganizationList, field: 'organization' }); diff --git a/awx/ui/static/js/controllers/JobTemplates.js b/awx/ui/static/js/controllers/JobTemplates.js index ebb9443625..3fde23f012 100644 --- a/awx/ui/static/js/controllers/JobTemplates.js +++ b/awx/ui/static/js/controllers/JobTemplates.js @@ -25,18 +25,6 @@ function JobTemplatesList ($scope, $rootScope, $location, $log, $routeParams, Re var scope = view.inject(list, { mode: mode }); $rootScope.flashMessage = null; scope.selected = []; - - if (scope.PostRefreshRemove) { - scope.PostRefreshRemove(); - } - scope.PostRefreshRemove = scope.$on('PostRefresh', function() { - $("tr.success").each(function(index) { - // Make sure no rows have a green background - var ngc = $(this).attr('ng-class'); - scope[ngc] = ""; - }); - }); - SearchInit({ scope: scope, set: 'job_templates', list: list, url: defaultUrl }); PaginateInit({ scope: scope, list: list, url: defaultUrl }); @@ -129,23 +117,6 @@ function JobTemplatesList ($scope, $rootScope, $location, $log, $routeParams, Re } } - scope.toggle_job_template = 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.submitJob = function(id) { SubmitJob({ scope: scope, id: id }); } @@ -347,6 +318,9 @@ function JobTemplatesEdit ($scope, $rootScope, $compile, $location, $log, $route for (var i=0; i < data.length; i++) { scope.playbook_options.push(data[i]); } + if (!scope.$$phase) { + scope.$digest(); + } }) .error( function(data, status, headers, config) { ProcessErrors(scope, data, status, form, diff --git a/awx/ui/static/js/controllers/Organizations.js b/awx/ui/static/js/controllers/Organizations.js index 9d98196bdf..86ff5b82cb 100644 --- a/awx/ui/static/js/controllers/Organizations.js +++ b/awx/ui/static/js/controllers/Organizations.js @@ -27,18 +27,7 @@ function OrganizationsList ($scope, $rootScope, $location, $log, Rest, Alert, Lo $rootScope.flashMessage = null; LoadBreadCrumbs(); - - if (scope.PostRefreshRemove) { - scope.PostRefreshRemove(); - } - scope.PostRefreshRemove = scope.$on('PostRefresh', function() { - $("tr.success").each(function(index) { - // Make sure no rows have a green background - var ngc = $(this).attr('ng-class'); - scope[ngc] = ""; - }); - }); - + // Initialize search and paginate pieces and load data SearchInit({ scope: scope, set: list.name, list: list, url: defaultUrl }); PaginateInit({ scope: scope, list: list, url: defaultUrl }); @@ -76,23 +65,6 @@ function OrganizationsList ($scope, $rootScope, $location, $log, Rest, Alert, Lo action: action }); } - - scope.toggle_organization = 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); - } - } - } } OrganizationsList.$inject=[ '$scope', '$rootScope', '$location', '$log', 'Rest', 'Alert', 'LoadBreadCrumbs', 'Prompt', diff --git a/awx/ui/static/js/controllers/Projects.js b/awx/ui/static/js/controllers/Projects.js index b395e94d69..86062fea79 100644 --- a/awx/ui/static/js/controllers/Projects.js +++ b/awx/ui/static/js/controllers/Projects.js @@ -12,7 +12,7 @@ function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, ProjectList, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, - ClearScope, ProcessErrors, GetBasePath) + ClearScope, ProcessErrors, GetBasePath, SelectionInit) { ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior //scope. @@ -25,16 +25,7 @@ function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest, scope.selected = []; $rootScope.flashMessage = null; - if (scope.PostRefreshRemove) { - scope.PostRefreshRemove(); - } - scope.PostRefreshRemove = scope.$on('PostRefresh', function() { - $("tr.success").each(function(index) { - // Make sure no rows have a green background - var ngc = $(this).attr('ng-class'); - scope[ngc] = ""; - }); - }); + SelectionInit({ scope: scope, list: list }); SearchInit({ scope: scope, set: 'projects', list: list, url: defaultUrl }); PaginateInit({ scope: scope, list: list, url: defaultUrl }); @@ -128,28 +119,11 @@ function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest, ReturnToCaller(1); } } - - scope.toggle_project = 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); - } - } - } } ProjectsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'ProjectList', 'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors', - 'GetBasePath' ]; + 'GetBasePath', 'SelectionInit']; function ProjectsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, ProjectsForm, diff --git a/awx/ui/static/js/controllers/Teams.js b/awx/ui/static/js/controllers/Teams.js index a9f0113a32..1a0292eabb 100644 --- a/awx/ui/static/js/controllers/Teams.js +++ b/awx/ui/static/js/controllers/Teams.js @@ -12,7 +12,7 @@ function TeamsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, TeamList, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, - ClearScope, ProcessErrors, SetTeamListeners, GetBasePath) + ClearScope, ProcessErrors, SetTeamListeners, GetBasePath, SelectionInit) { ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior //scope. @@ -23,7 +23,9 @@ function TeamsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Ale var mode = (paths[0] == 'teams') ? 'edit' : 'select'; // if base path 'teams', we're here to add/edit teams var scope = view.inject(list, { mode: mode }); // Inject our view scope.selected = []; - + + SelectionInit({ scope: scope, list: list }); + if (scope.PostRefreshRemove) { scope.PostRefreshRemove(); } @@ -32,12 +34,6 @@ function TeamsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Ale for( var i=0; i < scope.teams.length; i++) { scope.teams[i].organization_name = scope.teams[i].summary_fields.organization.name; } - - $("tr.success").each(function(index) { - // Make sure no rows have a green background - var ngc = $(this).attr('ng-class'); - scope[ngc] = ""; - }); }); //SetTeamListeners({ scope: scope, set: 'teams', iterator: list.iterator }); @@ -145,28 +141,11 @@ function TeamsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Ale ReturnToCaller(); } } - - scope.toggle_team = 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); - } - } - } } TeamsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'TeamList', 'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors', - 'SetTeamListeners', 'GetBasePath' ]; + 'SetTeamListeners', 'GetBasePath', 'SelectionInit']; function TeamsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm, diff --git a/awx/ui/static/js/controllers/Users.js b/awx/ui/static/js/controllers/Users.js index 8a5e0a15b2..6c204c4de4 100644 --- a/awx/ui/static/js/controllers/Users.js +++ b/awx/ui/static/js/controllers/Users.js @@ -12,7 +12,7 @@ function UsersList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, UserList, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, - ReturnToCaller, ClearScope, ProcessErrors, GetBasePath) + ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, SelectionInit) { ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior //scope. @@ -30,18 +30,9 @@ function UsersList ($scope, $rootScope, $location, $log, $routeParams, Rest, PaginateInit({ scope: scope, list: list, url: defaultUrl }); scope.search(list.iterator); - LoadBreadCrumbs(); - if (scope.PostRefreshRemove) { - scope.PostRefreshRemove(); - } - scope.PostRefreshRemove = scope.$on('PostRefresh', function() { - // Remove the 'success' class, which makes green or selected rows, from each row - for (var i=0; i < scope[list.name].length; i++) { - scope[list.iterator + '_' + scope[list.name][i].id + '_class'] = ''; - } - }); + SelectionInit({ scope: scope, list: list }); scope.addUser = function() { $location.path($location.path() + '/add'); @@ -88,7 +79,6 @@ function UsersList ($scope, $rootScope, $location, $log, $routeParams, Rest, // 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++) { @@ -133,27 +123,11 @@ function UsersList ($scope, $rootScope, $location, $log, $routeParams, Rest, } } - scope.toggle_user = 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); - } - } - } } UsersList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'UserList', 'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors', - 'GetBasePath' ]; + 'GetBasePath', 'SelectionInit']; function UsersAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm, diff --git a/awx/ui/static/js/helpers/Lookup.js b/awx/ui/static/js/helpers/Lookup.js index dab316a453..b287946d11 100644 --- a/awx/ui/static/js/helpers/Lookup.js +++ b/awx/ui/static/js/helpers/Lookup.js @@ -43,7 +43,7 @@ angular.module('LookUpHelper', [ 'RestServices', 'Utilities', 'SearchHelper', 'P var found = false; var name; for (var i=0; i < listScope[list.name].length; i++) { - if (listScope[list.iterator + "_" + listScope[list.name][i].id + "_class"] == "success") { + if (listScope[list.name][i]['checked'] == '1') { found = true; scope[field] = listScope[list.name][i].id; if (scope[form.name + '_form'] && form.fields[field] && form.fields[field].sourceModel) { @@ -72,23 +72,31 @@ angular.module('LookUpHelper', [ 'RestServices', 'Utilities', 'SearchHelper', 'P } listScope['toggle_' + list.iterator] = function(id) { - // when user clicks a row, remove 'success' class from all rows except clicked-on row - if (listScope[list.name]) { - for (var i=0; i < listScope[list.name].length; i++) { - listScope[list.iterator + "_" + listScope[list.name][i].id + "_class"] = ""; - } - } - if (id != null && id != undefined) { - listScope[list.iterator + "_" + id + "_class"] = "success"; + for (var i=0; i < scope[list.name].length; i++) { + if (listScope[list.name][i]['id'] == id) { + listScope[list.name][i]['checked'] = '1'; + listScope[list.name][i]['success_class'] = 'success'; + } + else { + listScope[list.name][i]['checked'] = '0'; + listScope[list.name][i]['success_class'] = ''; + } } } SearchInit({ scope: listScope, set: list.name, list: list, url: defaultUrl }); PaginateInit({ scope: listScope, list: list, url: defaultUrl, mode: 'lookup' }); - listScope.search(list.iterator); - if (current_item) { - listScope['toggle_' + list.iterator](current_item); + + // If user made a selection previously, mark it as selected when modal loads + if (listScope.lookupPostRefreshRemove) { + listScope.lookupPostRefreshRemove(); } + listScope.lookupPostRefreshRemove = scope.$on('PostRefresh', function() { + listScope['toggle_' + list.iterator](scope[field]); + }); + + listScope.search(list.iterator); + } } }]); diff --git a/awx/ui/static/js/helpers/Selection.js b/awx/ui/static/js/helpers/Selection.js new file mode 100644 index 0000000000..e5aba47ac6 --- /dev/null +++ b/awx/ui/static/js/helpers/Selection.js @@ -0,0 +1,60 @@ +/********************************************* + * Copyright (c) 2013 AnsibleWorks, Inc. + * + * SelectionHelper + * Used in list controllers where the list might also be used as a selection list. + * + * SelectionInit( { + * scope: , + * list: + * }) + */ + +angular.module('SelectionHelper', []) + .factory('SelectionInit', [ function() { + return function(params) { + + var scope = params.scope; // form scope + var list = params.list; // list object + + scope.selected = []; //array of selected row IDs + + // toggle row selection + scope['toggle_' + list.iterator] = function(id) { + for (var i=0; i < scope[list.name].length; i++) { + if (scope[list.name][i]['id'] == id) { + if (scope[list.name][i]['checked'] == '0') { + // select the row + scope[list.name][i]['checked'] = '1'; + scope[list.name][i]['success_class'] = 'success'; + if (scope.selected.indexOf(id) == -1) { + // add id to the array + scope.selected.push(id); + } + } + else { + // unselect the row + scope[list.name][i]['checked'] = '0'; + scope[list.name][i]['success_class'] = ''; + if (scope.selected.indexOf(id) > -1) { + // remove id from the array + scope.selected.splice(scope.selected.indexOf(id),1); + } + } + } + } + } + + // Initialize our data set after a refresh + if (scope.SelectPostRefreshRemove) { + scope.SelectPostRefreshRemove(); + } + scope.SelectPostRefreshRemove = scope.$on('PostRefresh', function() { + scope.selected = []; + for (var i=0; i < scope[list.name].length; i++) { + scope[list.name][i]['checked'] = '0'; + scope[list.name][i]['success_class'] = ''; + } + }); + } + }]); \ No newline at end of file diff --git a/awx/ui/static/lib/ansible/list-generator.js b/awx/ui/static/lib/ansible/list-generator.js index 4c87d398c4..ce124d9b6c 100644 --- a/awx/ui/static/lib/ansible/list-generator.js +++ b/awx/ui/static/lib/ansible/list-generator.js @@ -201,7 +201,7 @@ angular.module('ListGenerator', ['GeneratorHelpers']) html += "\n"; } } - if (options.mode == 'select') { + if (options.mode == 'select' || options.mode == 'lookup') { html += "Select"; } else if (options.mode == 'edit') { @@ -213,7 +213,7 @@ angular.module('ListGenerator', ['GeneratorHelpers']) // table body html += "\n"; html += ""; + if (options.mode == 'select' || options.mode == 'lookup') { + //html += ""; + + html += ""; + //ng-click=\"toggle_" + list.iterator + // "({{ " + list.iterator + ".id }}, true)\" } diff --git a/awx/ui/templates/ui/index.html b/awx/ui/templates/ui/index.html index c9f02f0076..f34a2364a2 100644 --- a/awx/ui/templates/ui/index.html +++ b/awx/ui/templates/ui/index.html @@ -87,6 +87,7 @@ + {% endif %}