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..7ecd631182 100644 --- a/awx/ui/client/src/teams/edit/teams-edit.controller.js +++ b/awx/ui/client/src/teams/edit/teams-edit.controller.js @@ -33,9 +33,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..c495416ae2 100644 --- a/awx/ui/client/src/teams/list/teams-list.controller.js +++ b/awx/ui/client/src/teams/list/teams-list.controller.js @@ -6,21 +6,23 @@ 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() { + const canEdit = me.get('summary_fields.user_capabilities.edit'); $scope.canAdd = false; rbacUiControlService.canAdd('teams') .then(function(params) { - $scope.canAdd = params.canAdd; + $scope.canAdd = params.canAdd && canEdit; }); // search init $scope.list = list; diff --git a/awx/ui/client/src/teams/main.js b/awx/ui/client/src/teams/main.js index f0ac982c7f..df9e15894c 100644 --- a/awx/ui/client/src/teams/main.js +++ b/awx/ui/client/src/teams/main.js @@ -41,6 +41,17 @@ angular.module('Teams', []) activityStream: true, activityStreamTarget: 'team' }, + resolve: { + 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..0b76cca634 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: '!user_is_system_auditor && !canAdd', + 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/users/edit/users-edit.controller.js b/awx/ui/client/src/users/edit/users-edit.controller.js index 0accb1bdcf..b268e619f3 100644 --- a/awx/ui/client/src/users/edit/users-edit.controller.js +++ b/awx/ui/client/src/users/edit/users-edit.controller.js @@ -30,6 +30,7 @@ export default ['$scope', '$rootScope', '$stateParams', 'UserForm', 'Rest', init(); function init() { + $scope.canAdd = true; $scope.isCurrentlyLoggedInUser = (parseInt(id) === $rootScope.current_user.id); $scope.hidePagination = false; $scope.hideSmartSearch = false; @@ -68,9 +69,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..9b95081a49 100644 --- a/awx/ui/client/src/users/list/users-list.controller.js +++ b/awx/ui/client/src/users/list/users-list.controller.js @@ -14,26 +14,28 @@ 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() { + const canEdit = me.get('summary_fields.user_capabilities.edit'); $scope.canAdd = false; rbacUiControlService.canAdd('users') .then(function(params) { - $scope.canAdd = params.canAdd; + $scope.canAdd = params.canAdd && canEdit; }); // search init diff --git a/awx/ui/client/src/users/main.js b/awx/ui/client/src/users/main.js index 5168262f3c..9f4937bf4b 100644 --- a/awx/ui/client/src/users/main.js +++ b/awx/ui/client/src/users/main.js @@ -43,6 +43,17 @@ angular.module('Users', []) activityStream: true, activityStreamTarget: 'user' }, + resolve: { + 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..925ec999b6 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: '!user_is_system_auditor && !canAdd', + 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'),