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..c5ee969049 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,6 +12,7 @@ export default ['templateUrl', '$state', return { restrict: 'E', scope: { + defaultParams: '=?', usersDataset: '=', teamsDataset: '=', resourceData: '=', 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..9779fc34f8 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 @@ -45,7 +45,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..602bdbcdb9 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,6 +17,7 @@ export default ['addPermissionsTeamsList', 'addPermissionsUsersList', 'TemplateL allSelected: '=', view: '@', dataset: '=', + defaultParams: '=?', objectType: '=' }, template: "
", @@ -149,6 +150,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..5f24ea6608 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(); @@ -26,6 +26,8 @@ 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; } let list = _.cloneDeep(GroupList); @@ -39,6 +41,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..7127efeed8 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,32 @@ 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__in = data.results + .filter(({name}) => name === i18n._('Admin')) + .map(({id}) => id) + .join(','); + notAdminAlreadyParams.is_superuser = 'false'; + 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 +60,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..1a445cc83d 100644 --- a/awx/ui/client/src/shared/stateDefinitions.factory.js +++ b/awx/ui/client/src/shared/stateDefinitions.factory.js @@ -584,27 +584,97 @@ function($injector, $stateExtender, $log, i18n) { squashSearchUrl: true, url: '/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) { - let path = GetBasePath(list.basePath) || GetBasePath(list.name); - return qs.search(path, $stateParams.user_search); - + orgId: ['$stateParams', 'Rest', 'GetBasePath', function($stateParams, Rest, GetBasePath) { + let id; + if ($stateParams.team_id) { + Rest.setUrl(GetBasePath('teams') + `${$stateParams.team_id}`); + id = Rest.get().then(({data}) => { + return data.summary_fields.organization.id; + }); + } else { + id = null; } - ] + return id; + }], + teamRoles: ['$stateParams', 'Rest', 'GetBasePath', 'i18n', function($stateParams, Rest, GetBasePath, i18n) { + let roles = null; + if ($stateParams.team_id) { + const basePath = GetBasePath('teams') + `${$stateParams.team_id}/object_roles`; + Rest.setUrl(basePath); + roles = Rest.get().then(({data}) => { + return data.results + .filter(({name}) => name === i18n._('Member') || name === i18n._('Admin')) + .map(({id}) => id) + .join(','); + }); + } + return roles; + }], + orgAdminRole: ['$stateParams', 'orgId', 'Rest', 'GetBasePath', 'i18n', + function($stateParams, orgId, Rest, GetBasePath, i18n) { + let orgIdToCheck = $stateParams.organization_id || orgId; + let role = null; + if (orgIdToCheck) { + const basePath = GetBasePath('organizations') + `${orgIdToCheck}/object_roles`; + Rest.setUrl(basePath); + role = Rest.get().then(({data}) => { + return data.results + .filter(({name}) => name === i18n._('Admin')) + .map(({id}) => id)[0]; + }); + } + return role; + }], + orgMemberRole: ['$stateParams', 'Rest', 'GetBasePath', 'i18n', function($stateParams, Rest, GetBasePath, i18n) { + let role = null; + if ($stateParams.organization_id) { + const basePath = GetBasePath('organizations') + `${$stateParams.organization_id}/object_roles`; + Rest.setUrl(basePath); + role = Rest.get().then(({data}) => { + return data.results + .filter(({name}) => name === i18n._('Member')) + .map(({id}) => id)[0]; + }); + } + return role; + }], + rolesToExclude: ['teamRoles', 'orgAdminRole', 'orgMemberRole', '$stateParams', + function(teamRoles, orgAdminRole, orgMemberRole, $stateParams) { + let roles = null; + if ($stateParams.team_id) { + roles = `${teamRoles},${orgAdminRole}`; + } else if ($stateParams.organization_id) { + roles = `${orgAdminRole},${orgMemberRole}`; + } + return roles; + }], + usersDataset: ['addPermissionsUsersList', 'QuerySet', '$stateParams', 'GetBasePath', 'rolesToExclude', + function(list, qs, $stateParams, GetBasePath, rolesToExclude) { + let path = GetBasePath(list.basePath) || GetBasePath(list.name); + if (rolesToExclude) { + $stateParams.add_user_search.not__roles__in = rolesToExclude; + $stateParams.add_user_search.is_superuser = 'false'; + } + return qs.search(path, $stateParams.add_user_search); + } + ], + defaultParams: ['$stateParams', 'usersDataset', function($stateParams) { + return $stateParams.add_user_search; + }] }, onExit: function($state) { if ($state.transition) {