diff --git a/awx/ui/client/src/configuration/configuration.block.less b/awx/ui/client/src/configuration/configuration.block.less index 7cba028ef9..693fd9a9d5 100644 --- a/awx/ui/client/src/configuration/configuration.block.less +++ b/awx/ui/client/src/configuration/configuration.block.less @@ -97,11 +97,19 @@ input#filePickerText { .Section-messageBar { width: 120%; margin-left: -20px; - padding: 10px; + padding: 10px 10px 10px 20px; color: @white; background-color: @default-link; } +.Section-messageBar-text { + margin-left: @at-space-2x; +} + +.Section-messageBar-warning { + color: @at-color-warning; +} + .Section-messageBar--close { position: absolute; right: 0; diff --git a/awx/ui/client/src/shared/form-generator.js b/awx/ui/client/src/shared/form-generator.js index 892b156d5c..eee1106922 100644 --- a/awx/ui/client/src/shared/form-generator.js +++ b/awx/ui/client/src/shared/form-generator.js @@ -142,10 +142,10 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat .factory('GenerateForm', ['$rootScope', '$compile', 'generateList', 'Attr', 'Icon', 'Column', 'NavigationLink', 'HelpCollapse', 'Empty', 'SelectIcon', - 'ActionButton', '$log', 'i18n', + 'ActionButton', 'MessageBar', '$log', 'i18n', function ($rootScope, $compile, GenerateList, Attr, Icon, Column, NavigationLink, HelpCollapse, - Empty, SelectIcon, ActionButton, $log, i18n) { + Empty, SelectIcon, ActionButton, MessageBar, $log, i18n) { return { setForm: function (form) { this.form = form; }, @@ -177,6 +177,7 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat else { return `
+ ${MessageBar(this.form)}
${html}
diff --git a/awx/ui/client/src/shared/generator-helpers.js b/awx/ui/client/src/shared/generator-helpers.js index f01b7110af..f365aeb042 100644 --- a/awx/ui/client/src/shared/generator-helpers.js +++ b/awx/ui/client/src/shared/generator-helpers.js @@ -766,4 +766,18 @@ angular.module('GeneratorHelpers', [systemStatus.name]) return html; }; +}) + +.factory('MessageBar', function() { + return function(options) { + let html = ''; + if (_.has(options, 'messageBar')) { + let { messageBar } = options; + html += `
+ + ${messageBar.message} +
`; + } + return html; + }; }); diff --git a/awx/ui/client/src/teams/edit/teams-edit.controller.js b/awx/ui/client/src/teams/edit/teams-edit.controller.js index 49c90c1316..41a37b19cb 100644 --- a/awx/ui/client/src/teams/edit/teams-edit.controller.js +++ b/awx/ui/client/src/teams/edit/teams-edit.controller.js @@ -5,17 +5,20 @@ *************************************************/ export default ['$scope', '$rootScope', '$stateParams', 'TeamForm', 'Rest', - 'ProcessErrors', 'GetBasePath', 'Wait', '$state', 'OrgAdminLookup', + 'ProcessErrors', 'GetBasePath', 'Wait', '$state', 'OrgAdminLookup', 'resolvedModels', function($scope, $rootScope, $stateParams, TeamForm, Rest, ProcessErrors, - GetBasePath, Wait, $state, OrgAdminLookup) { + GetBasePath, Wait, $state, OrgAdminLookup, models) { + const { me } = models; var form = TeamForm, - id = $stateParams.team_id, - defaultUrl = GetBasePath('teams') + id; + id = $stateParams.team_id, + defaultUrl = GetBasePath('teams') + id; init(); function init() { + $scope.canEdit = me.get('summary_fields.user_capabilities.edit'); + $scope.isOrgAdmin = me.get('related.admin_of_organizations.count') > 0; $scope.team_id = id; Rest.setUrl(defaultUrl); Wait('start'); @@ -33,9 +36,7 @@ export default ['$scope', '$rootScope', '$stateParams', 'TeamForm', 'Rest', }); $scope.$watch('team_obj.summary_fields.user_capabilities.edit', function(val) { - if (val === false) { - $scope.canAdd = false; - } + $scope.canAdd = (val === false) ? false : true; }); diff --git a/awx/ui/client/src/teams/list/teams-list.controller.js b/awx/ui/client/src/teams/list/teams-list.controller.js index 32b90528f8..254629d30b 100644 --- a/awx/ui/client/src/teams/list/teams-list.controller.js +++ b/awx/ui/client/src/teams/list/teams-list.controller.js @@ -6,16 +6,18 @@ export default ['$scope', 'Rest', 'TeamList', 'Prompt', 'ProcessErrors', 'GetBasePath', 'Wait', '$state', '$filter', - 'rbacUiControlService', 'Dataset', 'i18n', + 'rbacUiControlService', 'Dataset', 'resolvedModels', 'i18n', function($scope, Rest, TeamList, Prompt, ProcessErrors, - GetBasePath, Wait, $state, $filter, rbacUiControlService, Dataset, i18n) { + GetBasePath, Wait, $state, $filter, rbacUiControlService, Dataset, models, i18n) { + const { me } = models; var list = TeamList, defaultUrl = GetBasePath('teams'); init(); function init() { + $scope.canEdit = me.get('summary_fields.user_capabilities.edit'); $scope.canAdd = false; rbacUiControlService.canAdd('teams') diff --git a/awx/ui/client/src/teams/main.js b/awx/ui/client/src/teams/main.js index f0ac982c7f..7140e9aaf9 100644 --- a/awx/ui/client/src/teams/main.js +++ b/awx/ui/client/src/teams/main.js @@ -41,6 +41,26 @@ angular.module('Teams', []) activityStream: true, activityStreamTarget: 'team' }, + resolve: { + edit: { + resolvedModels: ['MeModel', '$q', function(Me, $q) { + const promises = { + me: new Me('get').then((me) => me.extend('get', 'admin_of_organizations')) + }; + + return $q.all(promises); + }] + }, + list: { + resolvedModels: ['MeModel', '$q', function(Me, $q) { + const promises = { + me: new Me('get') + }; + + return $q.all(promises); + }] + } + }, ncyBreadcrumb: { label: N_('TEAMS') } diff --git a/awx/ui/client/src/teams/teams.form.js b/awx/ui/client/src/teams/teams.form.js index 1314cbd183..855d8519d1 100644 --- a/awx/ui/client/src/teams/teams.form.js +++ b/awx/ui/client/src/teams/teams.form.js @@ -19,7 +19,10 @@ export default ['i18n', function(i18n) { // the top-most node of generated state tree stateTree: 'teams', tabs: true, - + messageBar: { + ngShow: 'isOrgAdmin && !canEdit', + message: i18n._("Contact your System Administrator to grant you the appropriate permissions to add and edit Users and Teams.") + }, fields: { name: { label: i18n._('Name'), diff --git a/awx/ui/client/src/teams/teams.list.js b/awx/ui/client/src/teams/teams.list.js index 93aab82848..1af52a8084 100644 --- a/awx/ui/client/src/teams/teams.list.js +++ b/awx/ui/client/src/teams/teams.list.js @@ -43,7 +43,7 @@ export default ['i18n', function(i18n) { awToolTip: i18n._('Create a new team'), actionClass: 'btn List-buttonSubmit', buttonContent: '+ ' + i18n._('ADD'), - ngShow: 'canAdd' + ngShow: 'canAdd && canEdit' } }, diff --git a/awx/ui/client/src/users/edit/users-edit.controller.js b/awx/ui/client/src/users/edit/users-edit.controller.js index 0accb1bdcf..82ae48af1d 100644 --- a/awx/ui/client/src/users/edit/users-edit.controller.js +++ b/awx/ui/client/src/users/edit/users-edit.controller.js @@ -14,14 +14,15 @@ const user_type_options = [ export default ['$scope', '$rootScope', '$stateParams', 'UserForm', 'Rest', 'ProcessErrors', 'GetBasePath', 'Wait', 'CreateSelect2', - '$state', 'i18n', + '$state', 'i18n', 'resolvedModels', function($scope, $rootScope, $stateParams, UserForm, Rest, ProcessErrors, - GetBasePath, Wait, CreateSelect2, $state, i18n) { + GetBasePath, Wait, CreateSelect2, $state, i18n, models) { for (var i = 0; i < user_type_options.length; i++) { user_type_options[i].label = i18n._(user_type_options[i].label); } + const { me } = models; var form = UserForm, master = {}, id = $stateParams.user_id, @@ -30,6 +31,8 @@ export default ['$scope', '$rootScope', '$stateParams', 'UserForm', 'Rest', init(); function init() { + $scope.canEdit = me.get('summary_fields.user_capabilities.edit'); + $scope.isOrgAdmin = me.get('related.admin_of_organizations.count') > 0; $scope.isCurrentlyLoggedInUser = (parseInt(id) === $rootScope.current_user.id); $scope.hidePagination = false; $scope.hideSmartSearch = false; @@ -68,9 +71,7 @@ export default ['$scope', '$rootScope', '$stateParams', 'UserForm', 'Rest', }); $scope.$watch('user_obj.summary_fields.user_capabilities.edit', function(val) { - if (val === false) { - $scope.canAdd = false; - } + $scope.canAdd = (val === false) ? false : true; }); setScopeFields(data); diff --git a/awx/ui/client/src/users/list/users-list.controller.js b/awx/ui/client/src/users/list/users-list.controller.js index f0c9022581..b684a5bbdb 100644 --- a/awx/ui/client/src/users/list/users-list.controller.js +++ b/awx/ui/client/src/users/list/users-list.controller.js @@ -14,21 +14,23 @@ const user_type_options = [ export default ['$scope', '$rootScope', 'Rest', 'UserList', 'Prompt', 'ProcessErrors', 'GetBasePath', 'Wait', '$state', '$filter', - 'rbacUiControlService', 'Dataset', 'i18n', + 'rbacUiControlService', 'Dataset', 'i18n', 'resolvedModels', function($scope, $rootScope, Rest, UserList, Prompt, ProcessErrors, GetBasePath, Wait, $state, $filter, rbacUiControlService, - Dataset, i18n) { + Dataset, i18n, models) { for (var i = 0; i < user_type_options.length; i++) { user_type_options[i].label = i18n._(user_type_options[i].label); } + const { me } = models; var list = UserList, - defaultUrl = GetBasePath('users'); + defaultUrl = GetBasePath('users'); init(); function init() { + $scope.canEdit = me.get('summary_fields.user_capabilities.edit'); $scope.canAdd = false; rbacUiControlService.canAdd('users') diff --git a/awx/ui/client/src/users/main.js b/awx/ui/client/src/users/main.js index 5168262f3c..3701d4f626 100644 --- a/awx/ui/client/src/users/main.js +++ b/awx/ui/client/src/users/main.js @@ -43,6 +43,26 @@ angular.module('Users', []) activityStream: true, activityStreamTarget: 'user' }, + resolve: { + edit: { + resolvedModels: ['MeModel', '$q', function(Me, $q) { + const promises= { + me: new Me('get').then((me) => me.extend('get', 'admin_of_organizations')) + }; + + return $q.all(promises); + }] + }, + list: { + resolvedModels: ['MeModel', '$q', function(Me, $q) { + const promises= { + me: new Me('get') + }; + + return $q.all(promises); + }] + } + }, ncyBreadcrumb: { label: N_('USERS') } diff --git a/awx/ui/client/src/users/users.form.js b/awx/ui/client/src/users/users.form.js index 78ea4f33e4..93a1264edd 100644 --- a/awx/ui/client/src/users/users.form.js +++ b/awx/ui/client/src/users/users.form.js @@ -20,7 +20,10 @@ export default ['i18n', function(i18n) { stateTree: 'users', forceListeners: true, tabs: true, - + messageBar: { + ngShow: 'isOrgAdmin && !canEdit', + message: i18n._("Contact your System Administrator to grant you the appropriate permissions to add and edit Users and Teams.") + }, fields: { first_name: { label: i18n._('First Name'), diff --git a/awx/ui/client/src/users/users.list.js b/awx/ui/client/src/users/users.list.js index c53eb79887..95ff26f5e6 100644 --- a/awx/ui/client/src/users/users.list.js +++ b/awx/ui/client/src/users/users.list.js @@ -48,7 +48,7 @@ export default ['i18n', function(i18n) { awToolTip: i18n._('Create a new user'), actionClass: 'btn List-buttonSubmit', buttonContent: '+ ' + i18n._('ADD'), - ngShow: 'canAdd' + ngShow: 'canAdd && canEdit' } },