diff --git a/awx/ui/client/src/access/add-rbac-resource/rbac-resource.controller.js b/awx/ui/client/src/access/add-rbac-resource/rbac-resource.controller.js index d79b22bda4..a49dba559a 100644 --- a/awx/ui/client/src/access/add-rbac-resource/rbac-resource.controller.js +++ b/awx/ui/client/src/access/add-rbac-resource/rbac-resource.controller.js @@ -119,11 +119,16 @@ export default ['$rootScope', '$scope', 'GetBasePath', 'Rest', '$q', 'Wait', 'Pr var url = GetBasePath(selectedValue.type + "s") + selectedValue.id + "/roles/"; - (selectedValue.roles || []) - .map(function(role) { - Rest.setUrl(url); - requests.push(Rest.post({ "id": role.value || role.id })); - }); + if (scope.onlyMemberRole === 'true') { + Rest.setUrl(url); + requests.push(Rest.post({ "id": scope.roles.member_role.id })); + } else { + (selectedValue.roles || []) + .map(function(role) { + Rest.setUrl(url); + requests.push(Rest.post({ "id": role.value || role.id })); + }); + } }); }); diff --git a/awx/ui/client/src/access/add-rbac-resource/rbac-resource.directive.js b/awx/ui/client/src/access/add-rbac-resource/rbac-resource.directive.js index f125c64afd..6993fee15a 100644 --- a/awx/ui/client/src/access/add-rbac-resource/rbac-resource.directive.js +++ b/awx/ui/client/src/access/add-rbac-resource/rbac-resource.directive.js @@ -12,10 +12,13 @@ export default ['templateUrl', '$state', return { restrict: 'E', scope: { + defaultParams: '=?', usersDataset: '=', teamsDataset: '=', resourceData: '=', withoutTeamPermissions: '@', + onlyMemberRole: '@', + queryPrefix: '@', title: '@' }, controller: controller, diff --git a/awx/ui/client/src/access/add-rbac-resource/rbac-resource.partial.html b/awx/ui/client/src/access/add-rbac-resource/rbac-resource.partial.html index 2ddfac5bc0..8873fc8feb 100644 --- a/awx/ui/client/src/access/add-rbac-resource/rbac-resource.partial.html +++ b/awx/ui/client/src/access/add-rbac-resource/rbac-resource.partial.html @@ -20,7 +20,7 @@
- + 1
@@ -45,13 +45,13 @@
- +
- +
@@ -110,7 +110,7 @@
diff --git a/awx/ui/client/src/access/rbac-multiselect/permissionsUsers.list.js b/awx/ui/client/src/access/rbac-multiselect/permissionsUsers.list.js index 7b1b91ab63..1e5a8193c3 100644 --- a/awx/ui/client/src/access/rbac-multiselect/permissionsUsers.list.js +++ b/awx/ui/client/src/access/rbac-multiselect/permissionsUsers.list.js @@ -15,7 +15,7 @@ multiSelectExtended: true, index: false, hover: true, - emptyListText : i18n._('No Users exist'), + emptyListText: i18n._('No Users to add'), disableRow: "{{ objectType === 'organization' && user.summary_fields.user_capabilities.edit === false }}", disableRowValue: "objectType === 'organization' && user.summary_fields.user_capabilities.edit === false", disableTooltip: { diff --git a/awx/ui/client/src/access/rbac-multiselect/rbac-multiselect-list.directive.js b/awx/ui/client/src/access/rbac-multiselect/rbac-multiselect-list.directive.js index 632219c8fe..a21497d221 100644 --- a/awx/ui/client/src/access/rbac-multiselect/rbac-multiselect-list.directive.js +++ b/awx/ui/client/src/access/rbac-multiselect/rbac-multiselect-list.directive.js @@ -17,7 +17,9 @@ export default ['addPermissionsTeamsList', 'addPermissionsUsersList', 'TemplateL allSelected: '=', view: '@', dataset: '=', - objectType: '=' + defaultParams: '=?', + objectType: '=', + queryPrefix: '@' }, template: "
", link: function(scope, element, attrs, ctrl) { @@ -34,6 +36,9 @@ export default ['addPermissionsTeamsList', 'addPermissionsUsersList', 'TemplateL Organizations: OrganizationList }; list = _.cloneDeep(listMap[scope.view]); + if (scope.queryPrefix) { + list.iterator = scope.queryPrefix; + } list.multiSelect = true; list.multiSelectExtended = true; list.listTitleBadge = false; @@ -92,7 +97,9 @@ export default ['addPermissionsTeamsList', 'addPermissionsUsersList', 'TemplateL list.fields.name.columnClass = 'col-sm-12'; break; case 'Users': - list.querySet = { order_by: 'username', page_size: '5' }; + if (!scope.queryPrefix) { + list.querySet = { order_by: 'username', page_size: '5' }; + } list.fields = { username: list.fields.username, first_name: list.fields.first_name, @@ -149,6 +156,11 @@ export default ['addPermissionsTeamsList', 'addPermissionsUsersList', 'TemplateL scope.list = list; scope[`${list.iterator}_dataset`] = scope.dataset.data; + + if (scope.defaultParams) { + scope[`${list.iterator}_default_params`] = scope.defaultParams; + } + scope[`${list.name}`] = scope[`${list.iterator}_dataset`].results; scope.$watch(list.name, function(){ diff --git a/awx/ui/client/src/inventories-hosts/shared/associate-groups/associate-groups.controller.js b/awx/ui/client/src/inventories-hosts/shared/associate-groups/associate-groups.controller.js index bfc4cda17e..03e5fe7158 100644 --- a/awx/ui/client/src/inventories-hosts/shared/associate-groups/associate-groups.controller.js +++ b/awx/ui/client/src/inventories-hosts/shared/associate-groups/associate-groups.controller.js @@ -5,9 +5,9 @@ *************************************************/ export default ['$scope', '$rootScope', 'ProcessErrors', 'GetBasePath', 'generateList', - '$state', 'Rest', '$q', 'Wait', '$window', 'QuerySet', 'GroupList', + '$state', 'Rest', '$q', 'Wait', '$window', 'QuerySet', 'GroupList', 'i18n', function($scope, $rootScope, ProcessErrors, GetBasePath, generateList, - $state, Rest, $q, Wait, $window, qs, GroupList) { + $state, Rest, $q, Wait, $window, qs, GroupList, i18n) { $scope.$on("linkLists", function() { init(); @@ -23,9 +23,14 @@ page_size: 5 }; - if($state.params.group_id) { + if ($state.params.group_id) { $scope.associate_group_default_params.not__id = $state.params.group_id; $scope.associate_group_queryset.not__id = $state.params.group_id; + $scope.associate_group_default_params.not__parents = $state.params.group_id; + $scope.associate_group_queryset.not__parents = $state.params.group_id; + } else if ($state.params.host_id) { + $scope.associate_group_default_params.not__hosts = $state.params.host_id; + $scope.associate_group_queryset.not__hosts = $state.params.host_id; } let list = _.cloneDeep(GroupList); @@ -39,6 +44,7 @@ selectedRows: 'selectedItems', availableRows: 'associate_groups' }; + list.emptyListText = i18n._('No groups to add'); delete list.actions; delete list.fieldActions; delete list.fields.failed_hosts; diff --git a/awx/ui/client/src/inventories-hosts/shared/associate-hosts/associate-hosts.controller.js b/awx/ui/client/src/inventories-hosts/shared/associate-hosts/associate-hosts.controller.js index 9a3014afcf..a72f937908 100644 --- a/awx/ui/client/src/inventories-hosts/shared/associate-hosts/associate-hosts.controller.js +++ b/awx/ui/client/src/inventories-hosts/shared/associate-hosts/associate-hosts.controller.js @@ -5,9 +5,9 @@ *************************************************/ export default ['$scope', '$rootScope', 'ProcessErrors', 'GetBasePath', 'generateList', - '$state', 'Rest', '$q', 'Wait', '$window', 'QuerySet', 'RelatedHostsListDefinition', + '$state', 'Rest', '$q', 'Wait', '$window', 'QuerySet', 'RelatedHostsListDefinition', 'i18n', function($scope, $rootScope, ProcessErrors, GetBasePath, generateList, - $state, Rest, $q, Wait, $window, qs, RelatedHostsListDefinition) { + $state, Rest, $q, Wait, $window, qs, RelatedHostsListDefinition, i18n) { $scope.$on("linkLists", function() { init(); @@ -23,6 +23,11 @@ page_size: 5 }; + if ($state.params.group_id) { + $scope.associate_host_default_params.not__groups = $state.params.group_id; + $scope.associate_host_queryset.not__groups = $state.params.group_id; + } + let list = _.cloneDeep(RelatedHostsListDefinition); list.basePath = GetBasePath('inventory') + $state.params.inventory_id + '/hosts'; list.iterator = 'associate_host'; @@ -36,6 +41,7 @@ selectedRows: 'selectedItems', availableRows: 'associate_hosts' }; + list.emptyListText = i18n._('No hosts to add'); delete list.fields.toggleHost; delete list.fields.active_failures; delete list.fields.groups; diff --git a/awx/ui/client/src/organizations/linkout/addUsers/addUsers.controller.js b/awx/ui/client/src/organizations/linkout/addUsers/addUsers.controller.js index 97f7cdd050..7e12d4b9b8 100644 --- a/awx/ui/client/src/organizations/linkout/addUsers/addUsers.controller.js +++ b/awx/ui/client/src/organizations/linkout/addUsers/addUsers.controller.js @@ -12,9 +12,9 @@ */ export default ['$scope', '$rootScope', 'ProcessErrors', 'GetBasePath', 'generateList', -'$state', 'Rest', '$q', 'Wait', '$window', 'QuerySet', 'UserList', +'$state', 'Rest', '$q', 'Wait', '$window', 'QuerySet', 'UserList', 'i18n', function($scope, $rootScope, ProcessErrors, GetBasePath, generateList, - $state, Rest, $q, Wait, $window, qs, UserList) { + $state, Rest, $q, Wait, $window, qs, UserList, i18n) { $scope.$on("linkLists", function() { if ($state.current.name.split(".")[1] === "users") { @@ -23,18 +23,30 @@ function($scope, $rootScope, ProcessErrors, GetBasePath, generateList, $scope.addType = "Administrators"; } - init(); + let notAdminAlreadyParams = {}; + + if ($scope.addType === 'Administrators') { + Rest.setUrl(GetBasePath('organizations') + `${$state.params.organization_id}/object_roles`); + Rest.get().then(({data}) => { + notAdminAlreadyParams.not__roles = data.results + .filter(({name}) => name === i18n._('Admin')) + .map(({id}) => id)[0]; + init(); + }); + } else { + init(); + } function init(){ - $scope.add_user_default_params = { + $scope.add_user_default_params = Object.assign({ order_by: 'username', page_size: 5 - }; + }, notAdminAlreadyParams); - $scope.add_user_queryset = { + $scope.add_user_queryset = Object.assign({ order_by: 'username', page_size: 5 - }; + }, notAdminAlreadyParams); let list = _.cloneDeep(UserList); list.basePath = 'users'; @@ -46,6 +58,9 @@ function($scope, $rootScope, ProcessErrors, GetBasePath, generateList, list.fields.first_name.columnClass = 'col-sm-4'; list.fields.last_name.columnClass = 'col-sm-4'; list.layoutClass = 'List-staticColumnLayout--statusOrCheckbox'; + if ($scope.addType === 'Administrators') { + list.emptyListText = i18n._('No users available to add as adminstrators'); + } delete list.actions; delete list.fieldActions; diff --git a/awx/ui/client/src/organizations/linkout/organizations-linkout.route.js b/awx/ui/client/src/organizations/linkout/organizations-linkout.route.js index 877676af62..0aa7b044e0 100644 --- a/awx/ui/client/src/organizations/linkout/organizations-linkout.route.js +++ b/awx/ui/client/src/organizations/linkout/organizations-linkout.route.js @@ -54,7 +54,7 @@ let lists = [{ OrgUsersDataset: ['OrgUserList', 'QuerySet', '$stateParams', 'GetBasePath', function(list, qs, $stateParams, GetBasePath) { let path = GetBasePath(list.basePath) || list.basePath; - return qs.search(path, $stateParams.user_search); + return qs.search(path, $stateParams.org_user_search); } ], OrgUserList: ['UserList', 'GetBasePath', '$stateParams', 'i18n', function(UserList, GetBasePath, $stateParams, i18n) { diff --git a/awx/ui/client/src/shared/stateDefinitions.factory.js b/awx/ui/client/src/shared/stateDefinitions.factory.js index 2c54e901f7..e72df8e2f9 100644 --- a/awx/ui/client/src/shared/stateDefinitions.factory.js +++ b/awx/ui/client/src/shared/stateDefinitions.factory.js @@ -581,30 +581,45 @@ function($injector, $stateExtender, $log, i18n) { states.push($stateExtender.buildDefinition({ name: `${formStateDefinition.name}.users.add`, - squashSearchUrl: true, url: '/add-user', + searchPrefix: 'add_user', params: { - user_search: { + add_user_search: { value: { order_by: 'username', page_size: '5' }, - dynamic: true, + dynamic: true } }, views: { [`modal@${formStateDefinition.name}`]: { - template: `` + template: `` } }, ncyBreadcrumb:{ skip:true }, resolve: { - usersDataset: ['addPermissionsUsersList', 'QuerySet', '$stateParams', 'GetBasePath', - function(list, qs, $stateParams, GetBasePath) { + roleToExclude: ['$stateParams', 'Rest', 'GetBasePath', 'i18n', function($stateParams, Rest, GetBasePath, i18n) { + const basePath = ($stateParams.team_id) ? GetBasePath('teams') + `${$stateParams.team_id}/object_roles` : + GetBasePath('organizations') + `${$stateParams.organization_id}/object_roles`; + Rest.setUrl(basePath); + return Rest.get().then(({data}) => { + return data.results + .filter(({name}) => name === i18n._('Member')) + .map(({id}) => id)[0]; + }); + }], + usersDataset: ['addPermissionsUsersList', 'QuerySet', '$stateParams', 'GetBasePath', 'roleToExclude', + function(list, qs, $stateParams, GetBasePath, roleToExclude) { let path = GetBasePath(list.basePath) || GetBasePath(list.name); - return qs.search(path, $stateParams.user_search); - + if (roleToExclude) { + $stateParams.add_user_search.not__roles = roleToExclude; + } + return qs.search(path, $stateParams.add_user_search); } - ] + ], + defaultParams: ['$stateParams', 'usersDataset', function($stateParams) { + return $stateParams.add_user_search; + }] }, onExit: function($state) { if ($state.transition) {