You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by nc...@apache.org on 2017/11/30 14:25:04 UTC
[10/50] [abbrv] ambari git commit: AMBARI-22508 Ambari 3.0: Implement
new design for Admin View: User Management. (atkach)
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UsersListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UsersListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UsersListCtrl.js
new file mode 100644
index 0000000..abe1780
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UsersListCtrl.js
@@ -0,0 +1,178 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+'use strict';
+
+angular.module('ambariAdminConsole')
+.controller('UsersListCtrl',
+['$scope', 'User', '$modal', '$rootScope', 'UserConstants', '$translate', 'Cluster', 'View', 'ConfirmationModal', 'Settings',
+function($scope, User, $modal, $rootScope, UserConstants, $translate, Cluster, View, ConfirmationModal, Settings) {
+ var $t = $translate.instant;
+ $scope.constants = {
+ admin: $t('users.ambariAdmin'),
+ users: $t('common.users').toLowerCase()
+ };
+ $scope.minRowsToShowPagination = Settings.minRowsToShowPagination;
+ $scope.isLoading = false;
+ $scope.users = [];
+ $scope.usersPerPage = 10;
+ $scope.currentPage = 1;
+ $scope.totalUsers = 0;
+ $scope.filters = {
+ name: '',
+ status: null,
+ type: null
+ };
+ $scope.maxVisiblePages = 20;
+ $scope.tableInfo = {
+ total: 0,
+ showed: 0
+ };
+ $scope.isNotEmptyFilter = true;
+
+ $scope.pageChanged = function() {
+ $scope.loadUsers();
+ };
+ $scope.usersPerPageChanges = function() {
+ $scope.resetPagination();
+ };
+
+ $scope.loadUsers = function(){
+ $scope.isLoading = true;
+ User.list({
+ currentPage: $scope.currentPage,
+ usersPerPage: $scope.usersPerPage,
+ searchString: $scope.filters.name,
+ user_type: $scope.filters.type.value,
+ active: $scope.filters.status.value
+ }).then(function(data) {
+ $scope.isLoading = false;
+ $scope.totalUsers = data.data.itemTotal;
+ $scope.users = data.data.items.map(User.makeUser);
+ $scope.tableInfo.showed = data.data.items.length;
+ $scope.tableInfo.total = data.data.itemTotal;
+ });
+ };
+
+ $scope.resetPagination = function() {
+ $scope.currentPage = 1;
+ $scope.loadUsers();
+ };
+
+ $scope.activeFilterOptions = [
+ {label: $t('common.all'), value: '*'},
+ {label: $t('users.active'), value: true},
+ {label: $t('users.inactive'), value:false}
+ ];
+ $scope.filters.status = $scope.activeFilterOptions[0];
+
+ $scope.typeFilterOptions = [{ label: $t('common.all'), value: '*'}]
+ .concat(Object.keys(UserConstants.TYPES).map(function(key) {
+ return {
+ label: $t(UserConstants.TYPES[key].LABEL_KEY),
+ value: UserConstants.TYPES[key].VALUE
+ };
+ }));
+
+ $scope.filters.type = $scope.typeFilterOptions[0];
+
+ $scope.clearFilters = function () {
+ $scope.filters.name = '';
+ $scope.filters.type = $scope.typeFilterOptions[0];
+ $scope.filters.status = $scope.activeFilterOptions[0];
+ $scope.resetPagination();
+ };
+
+ $scope.loadUsers();
+
+ $scope.$watch(
+ function (scope) {
+ return Boolean(scope.filters.name || (scope.filters.status && scope.filters.status.value !== '*')
+ || (scope.filters.type && scope.filters.type.value !== '*'));
+ },
+ function (newValue, oldValue, scope) {
+ scope.isNotEmptyFilter = newValue;
+ }
+ );
+
+ $rootScope.$watch(function(scope) {
+ return scope.LDAPSynced;
+ }, function(LDAPSynced) {
+ if(LDAPSynced === true){
+ $rootScope.LDAPSynced = false;
+ $scope.loadUsers();
+ }
+ });
+
+ $scope.createUser = function () {
+ var modalInstance = $modal.open({
+ templateUrl: 'views/userManagement/modals/userCreate.html',
+ controller: 'UserCreateCtrl',
+ backdrop: 'static'
+ });
+
+ modalInstance.result.finally($scope.loadUsers);
+ };
+
+ $scope.deleteUser = function(user) {
+ ConfirmationModal.show(
+ $t('common.delete', {
+ term: $t('common.user')
+ }),
+ $t('common.deleteConfirmation', {
+ instanceType: $t('common.user').toLowerCase(),
+ instanceName: '"' + user.user_name + '"'
+ })
+ ).then(function() {
+ Cluster.getPrivilegesForResource({
+ nameFilter : user.user_name,
+ typeFilter : {value: 'USER'}
+ }).then(function(data) {
+ var clusterPrivilegesIds = [];
+ var viewsPrivileges = [];
+ if (data.items && data.items.length) {
+ angular.forEach(data.items[0].privileges, function(privilege) {
+ if (privilege.PrivilegeInfo.principal_type === 'USER') {
+ if (privilege.PrivilegeInfo.type === 'VIEW') {
+ viewsPrivileges.push({
+ id: privilege.PrivilegeInfo.privilege_id,
+ view_name: privilege.PrivilegeInfo.view_name,
+ version: privilege.PrivilegeInfo.version,
+ instance_name: privilege.PrivilegeInfo.instance_name
+ });
+ } else {
+ clusterPrivilegesIds.push(privilege.PrivilegeInfo.privilege_id);
+ }
+ }
+ });
+ }
+ User.delete(user.user_name).then(function() {
+ if (clusterPrivilegesIds.length) {
+ Cluster.getAllClusters().then(function (clusters) {
+ var clusterName = clusters[0].Clusters.cluster_name;
+ Cluster.deleteMultiplePrivileges(clusterName, clusterPrivilegesIds);
+ });
+ }
+ angular.forEach(viewsPrivileges, function(privilege) {
+ View.deletePrivilege(privilege);
+ });
+ $scope.loadUsers();
+ });
+ });
+ });
+ };
+}]);
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersCreateCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersCreateCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersCreateCtrl.js
deleted file mode 100644
index bcb7bfc..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersCreateCtrl.js
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-'use strict';
-
-angular.module('ambariAdminConsole')
-.controller('UsersCreateCtrl',['$scope', '$routeParams', 'User', '$location', 'Alert', 'UnsavedDialog', '$translate', function($scope, $routeParams, User, $location, Alert, UnsavedDialog, $translate) {
- var $t = $translate.instant;
- $scope.user = {
- active: true
- };
- var targetUrl = '/users';
-
- $scope.createUser = function() {
- $scope.form.submitted = true;
- if ($scope.form.$valid){
- User.create({
- 'Users/user_name': $scope.user.user_name,
- 'Users/password': $scope.user.password,
- 'Users/active': !!$scope.user.active,
- 'Users/admin': !!$scope.user.admin
- }).then(function() {
- Alert.success($t('users.alerts.userCreated', {
- userName: $scope.user.user_name,
- encUserName: encodeURIComponent($scope.user.user_name)
- }));
- $scope.form.$setPristine();
- $location.path(targetUrl);
- }).catch(function(data) {
- Alert.error($t('users.alerts.userCreationError'), data.data.message);
- });
- }
- };
-
- $scope.cancel = function() {
- $scope.form.$setPristine();
- $location.path('/users');
- };
-
- $scope.$on('$locationChangeStart', function(event, __targetUrl) {
-
- if( $scope.form.$dirty ){
- UnsavedDialog().then(function(action) {
- targetUrl = __targetUrl.split('#').pop();
- switch(action){
- case 'save':
- $scope.createUser();
- break;
- case 'discard':
- $scope.form.$setPristine();
- $location.path(targetUrl);
- break;
- case 'cancel':
- targetUrl = '/users';
- break;
- }
- });
- event.preventDefault();
- }
- });
-}]);
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersListCtrl.js
deleted file mode 100644
index 8146163..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersListCtrl.js
+++ /dev/null
@@ -1,122 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-'use strict';
-
-angular.module('ambariAdminConsole')
- .controller('UsersListCtrl',['$scope', 'User', '$modal', '$rootScope', 'UserConstants', '$translate', 'Settings', function($scope, User, $modal, $rootScope, UserConstants, $translate, Settings) {
- var $t = $translate.instant;
- $scope.constants = {
- admin: $t('users.ambariAdmin'),
- users: $t('common.users').toLowerCase()
- };
- $scope.isLoading = false;
- $scope.users = [];
- $scope.usersPerPage = 10;
- $scope.currentPage = 1;
- $scope.totalUsers = 1;
- $scope.currentNameFilter = '';
- $scope.maxVisiblePages=20;
- $scope.tableInfo = {
- total: 0,
- showed: 0
- };
- $scope.isNotEmptyFilter = true;
-
- $scope.pageChanged = function() {
- $scope.loadUsers();
- };
- $scope.usersPerPageChanges = function() {
- $scope.resetPagination();
- };
-
- $scope.loadUsers = function(){
- $scope.isLoading = true;
- User.list({
- currentPage: $scope.currentPage,
- usersPerPage: $scope.usersPerPage,
- searchString: $scope.currentNameFilter,
- user_type: $scope.currentTypeFilter.value,
- active: $scope.currentActiveFilter.value,
- admin: $scope.adminFilter
- }).then(function(data) {
- $scope.isLoading = false;
- $scope.totalUsers = data.data.itemTotal;
- $scope.users = data.data.items.map(User.makeUser);
- $scope.tableInfo.showed = data.data.items.length;
- $scope.tableInfo.total = data.data.itemTotal;
- });
- };
-
- $scope.resetPagination = function() {
- $scope.currentPage = 1;
- $scope.loadUsers();
- };
-
- $scope.activeFilterOptions = [
- {label: $t('common.all'), value: '*'},
- {label: $t('users.active'), value: true},
- {label: $t('users.inactive'), value:false}
- ];
- $scope.currentActiveFilter = $scope.activeFilterOptions[0];
-
- $scope.typeFilterOptions = [{ label: $t('common.all'), value: '*'}]
- .concat(Object.keys(UserConstants.TYPES).map(function(key) {
- return {
- label: $t(UserConstants.TYPES[key].LABEL_KEY),
- value: UserConstants.TYPES[key].VALUE
- };
- }));
-
- $scope.currentTypeFilter = $scope.typeFilterOptions[0];
-
- $scope.adminFilter = false;
- $scope.toggleAdminFilter = function() {
- $scope.adminFilter = !$scope.adminFilter;
- $scope.resetPagination();
- $scope.loadUsers();
- };
-
- $scope.clearFilters = function () {
- $scope.currentNameFilter = '';
- $scope.currentTypeFilter = $scope.typeFilterOptions[0];
- $scope.currentActiveFilter = $scope.activeFilterOptions[0];
- $scope.adminFilter = false;
- $scope.resetPagination();
- };
-
- $scope.loadUsers();
-
- $scope.$watch(
- function (scope) {
- return Boolean(scope.currentNameFilter || (scope.currentActiveFilter && scope.currentActiveFilter.value !== '*')
- || (scope.currentTypeFilter && scope.currentTypeFilter.value !== '*') || $scope.adminFilter);
- },
- function (newValue, oldValue, scope) {
- scope.isNotEmptyFilter = newValue;
- }
- );
-
- $rootScope.$watch(function(scope) {
- return scope.LDAPSynced;
- }, function(LDAPSynced) {
- if(LDAPSynced === true){
- $rootScope.LDAPSynced = false;
- $scope.loadUsers();
- }
- });
-}]);
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersShowCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersShowCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersShowCtrl.js
deleted file mode 100644
index 200872e..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersShowCtrl.js
+++ /dev/null
@@ -1,290 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-'use strict';
-
-angular.module('ambariAdminConsole')
-.controller('UsersShowCtrl', ['$scope', '$routeParams', 'Cluster', 'User', 'View', '$modal', '$location', 'ConfirmationModal', 'Alert', 'Auth', 'getDifference', 'Group', '$q', 'UserConstants', '$translate', function($scope, $routeParams, Cluster, User, View, $modal, $location, ConfirmationModal, Alert, Auth, getDifference, Group, $q, UserConstants, $translate) {
-
- var $t = $translate.instant;
-
- $scope.constants = {
- user: $t('common.user'),
- status: $t('users.status'),
- admin: $t('users.admin'),
- password: $t('users.password'),
- view: $t('common.view').toLowerCase(),
- cluster: $t('common.cluster').toLowerCase()
- };
-
- function loadUserInfo(){
- User.get($routeParams.id).then(function(data) {
- $scope.user = User.makeUser(data).Users;
- $scope.isCurrentUser = $scope.user.user_name === Auth.getCurrentUser();
- $scope.editingGroupsList = angular.copy($scope.user.groups);
- });
- }
-
- loadUserInfo();
- $scope.user;
- $scope.isCurrentUser = true;
- $scope.dataLoaded = false;
-
- $scope.isGroupEditing = false;
- $scope.enableGroupEditing = function() {
- $scope.isGroupEditing = true;
- $scope.editingGroupsList = angular.copy($scope.user.groups);
- };
-
- $scope.$watch(function() {
- return $scope.editingGroupsList;
- }, function(newValue) {
- if(newValue){
- if( !angular.equals(newValue, $scope.user.groups) ){
- $scope.updateGroups();
- }
- }
- }, true);
-
- $scope.updateGroups = function() {
- var groups = $scope.editingGroupsList.toString().split(',').filter(function(item) {return item.trim();}).map(function(item) {return item.trim()});
- var diff = getDifference($scope.user.groups, groups);
- var promises = [];
- // Remove user from groups
- angular.forEach(diff.del, function(groupName) {
- promises.push(Group.removeMemberFromGroup(groupName, $scope.user.user_name).catch(function(data) {
- Alert.error($t('users.alerts.removeUserError'), data.data.message);
- }));
- });
- // Add user to groups
- angular.forEach(diff.add, function(groupName) {
- promises.push(Group.addMemberToGroup(groupName, $scope.user.user_name).catch(function(data) {
- Alert.error($t('users.alerts.cannotAddUser'), data.data.message);
- }));
- });
- $q.all(promises).then(function() {
- loadUserInfo();
- });
- $scope.isGroupEditing = false;
- };
-
- $scope.getUserMembership = function(userType) {
- if(userType) {
- return $t(UserConstants.TYPES[userType].LABEL_KEY) + " " + $t('users.groupMembership');
- }
- };
-
- $scope.cancelUpdate = function() {
- $scope.isGroupEditing = false;
- $scope.editingGroupsList = '';
- };
-
- $scope.openChangePwdDialog = function() {
- var modalInstance = $modal.open({
- templateUrl: 'views/users/modals/changePassword.html',
- resolve: {
- userName: function() {
- return $scope.user.user_name;
- }
- },
- controller: ['$scope', 'userName', function($scope, userName) {
- $scope.passwordData = {
- password: '',
- currentUserPassword: ''
- };
-
- $scope.form = {};
- $scope.userName = userName;
-
- $scope.ok = function() {
- $scope.form.passwordChangeForm.submitted = true;
- if($scope.form.passwordChangeForm.$valid){
-
- modalInstance.close({
- password: $scope.passwordData.password,
- currentUserPassword: $scope.passwordData.currentUserPassword
- });
- }
- };
- $scope.cancel = function() {
- modalInstance.dismiss('cancel');
- };
- }]
- });
-
- modalInstance.result.then(function(data) {
- User.setPassword($scope.user, data.password, data.currentUserPassword).then(function() {
- Alert.success($t('users.alerts.passwordChanged'));
- }).catch(function(data) {
- Alert.error($t('users.alerts.cannotChangePassword'), data.data.message);
- });
- });
- };
-
- $scope.toggleUserActive = function() {
- if(!$scope.isCurrentUser){
- var newStatusKey = $scope.user.active ? 'inactive' : 'active',
- newStatus = $t('users.' + newStatusKey).toLowerCase();
- ConfirmationModal.show(
- $t('users.changeStatusConfirmation.title'),
- $t('users.changeStatusConfirmation.message', {
- userName: $scope.user.user_name,
- status: newStatus
- })
- ).then(function() {
- User.setActive($scope.user.user_name, $scope.user.active)
- .catch(function(data) {
- Alert.error($t('common.alerts.cannotUpdateStatus'), data.data.message);
- $scope.user.active = !$scope.user.active;
- });
- })
- .catch(function() {
- $scope.user.active = !$scope.user.active;
- });
- }
- };
- $scope.toggleUserAdmin = function() {
- if(!$scope.isCurrentUser){
- var action = $scope.user.admin ?
- $t('users.changePrivilegeConfirmation.revoke') : $t('users.changePrivilegeConfirmation.grant');
- ConfirmationModal.show(
- $t('users.changePrivilegeConfirmation.title'),
- $t('users.changePrivilegeConfirmation.message', {
- action: action,
- userName: $scope.user.user_name
- })
- ).then(function() {
- User.setAdmin($scope.user.user_name, $scope.user.admin)
- .then(function() {
- loadPrivileges();
- })
- .catch(function (data) {
- Alert.error($t('common.alerts.cannotUpdateAdminStatus'), data.data.message);
- $scope.user.admin = !$scope.user.admin;
- });
- })
- .catch(function() {
- $scope.user.admin = !$scope.user.admin;
- });
-
- }
- };
-
- $scope.removePrivilege = function(name, privilege) {
- var privilegeObject = {
- id: privilege.privilege_id,
- view_name: privilege.view_name,
- version: privilege.version,
- instance_name: name
- };
- View.deletePrivilege(privilegeObject).then(function() {
- loadPrivileges();
- });
- };
-
- $scope.deleteUser = function() {
- ConfirmationModal.show(
- $t('common.delete', {
- term: $t('common.user')
- }),
- $t('common.deleteConfirmation', {
- instanceType: $t('common.user').toLowerCase(),
- instanceName: '"' + $scope.user.user_name + '"'
- })
- ).then(function() {
- Cluster.getPrivilegesForResource({
- nameFilter : $scope.user.user_name,
- typeFilter : {value: 'USER'}
- }).then(function(data) {
- var clusterPrivilegesIds = [];
- var viewsPrivileges = [];
- if (data.items && data.items.length) {
- angular.forEach(data.items[0].privileges, function(privilege) {
- if (privilege.PrivilegeInfo.principal_type === 'USER') {
- if (privilege.PrivilegeInfo.type === 'VIEW') {
- viewsPrivileges.push({
- id: privilege.PrivilegeInfo.privilege_id,
- view_name: privilege.PrivilegeInfo.view_name,
- version: privilege.PrivilegeInfo.version,
- instance_name: privilege.PrivilegeInfo.instance_name
- });
- } else {
- clusterPrivilegesIds.push(privilege.PrivilegeInfo.privilege_id);
- }
- }
- });
- }
- User.delete($scope.user.user_name).then(function() {
- $location.path('/users');
- if (clusterPrivilegesIds.length) {
- Cluster.getAllClusters().then(function (clusters) {
- var clusterName = clusters[0].Clusters.cluster_name;
- Cluster.deleteMultiplePrivileges(clusterName, clusterPrivilegesIds);
- });
- }
- angular.forEach(viewsPrivileges, function(privilege) {
- View.deletePrivilege(privilege);
- });
- });
- });
- });
- };
-
- // Load privileges
- function loadPrivileges(){
- User.getPrivileges($routeParams.id).then(function(data) {
- var privileges = {
- clusters: {},
- views: {}
- };
- angular.forEach(data.data.items, function(privilege) {
- privilege = privilege.PrivilegeInfo;
- if(privilege.type === 'CLUSTER'){
- // This is cluster
- if (privileges.clusters[privilege.cluster_name]) {
- var preIndex = Cluster.orderedRoles.indexOf(privileges.clusters[privilege.cluster_name].permission_name);
- var curIndex = Cluster.orderedRoles.indexOf(privilege.permission_name);
- // replace when cur is a more powerful role
- if (curIndex < preIndex) {
- privileges.clusters[privilege.cluster_name] = privilege;
- }
- } else {
- privileges.clusters[privilege.cluster_name] = privilege;
- }
- } else if ( privilege.type === 'VIEW'){
- privileges.views[privilege.instance_name] = privileges.views[privilege.instance_name] || { privileges:[]};
- privileges.views[privilege.instance_name].version = privilege.version;
- privileges.views[privilege.instance_name].view_name = privilege.view_name;
- privileges.views[privilege.instance_name].privilege_id = privilege.privilege_id;
- if (privileges.views[privilege.instance_name].privileges.indexOf(privilege.permission_label) == -1) {
- privileges.views[privilege.instance_name].privileges.push(privilege.permission_label);
- }
- }
- });
-
- $scope.privileges = data.data.items.length ? privileges : null;
- $scope.noClusterPriv = $.isEmptyObject(privileges.clusters);
- $scope.noViewPriv = $.isEmptyObject(privileges.views);
- $scope.hidePrivileges = $scope.noClusterPriv && $scope.noViewPriv;
- $scope.dataLoaded = true;
-
- }).catch(function(data) {
- Alert.error($t('common.alerts.cannotLoadPrivileges'), data.data.message);
- });
- }
- loadPrivileges();
-}]);
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
index 1967dfa..de3968d 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
@@ -101,6 +101,7 @@ angular.module('ambariAdminConsole')
'common.admin': 'Admin',
'common.actions': 'Actions',
'common.error': 'Error',
+ 'common.select': 'Select',
'common.clusterNameChangeConfirmation.title': 'Confirm Cluster Name Change',
'common.clusterNameChangeConfirmation.message': 'Are you sure you want to change the cluster name to {{clusterName}}?',
@@ -276,6 +277,8 @@ angular.module('ambariAdminConsole')
'groups.createLocal': 'Add Groups',
'groups.name': 'Group name',
+ 'groups.role': 'Add roles to this group',
+ 'groups.addUsers': 'Add users to this group',
'groups.members': 'Members',
'groups.membersPlural': '{{n}} member{{n == 1 ? "" : "s"}}',
@@ -285,7 +288,7 @@ angular.module('ambariAdminConsole')
'groups.alerts.getGroupsListError': 'Get groups list error',
'users.username': 'Username',
- 'users.userName': 'User name',
+ 'users.user.name': 'User name',
'users.admin': 'Admin',
'users.ambariAdmin': 'Ambari Admin',
'users.ambariClusterURL': 'Ambari Cluster URL',
@@ -300,7 +303,11 @@ angular.module('ambariAdminConsole')
'users.inactive': 'Inactive',
'users.status': 'Status',
'users.password': 'Password',
+ 'users.role': 'Add roles for this user (Cluster Operator/Service Admin)',
+ 'users.confirmPassword': 'Confirm Password',
'users.passwordConfirmation': 'Password сonfirmation',
+ 'users.isAmbariAdmin': 'Is this user an Ambari Admin?',
+ 'users.isActive': 'Deactivate this user?',
'users.userIsAdmin': 'This user is an Ambari Admin and has all privileges.',
'users.showAll': 'Show all users',
'users.showAdmin': 'Show only admin users',
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js
index dabc57a..c8d0e96 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js
@@ -38,51 +38,25 @@ angular.module('ambariAdminConsole')
controller: 'LoginActivitiesMainCtrl'
}
},
- users: {
- list: {
- url: '/users',
- templateUrl: 'views/users/list.html',
- controller: 'UsersListCtrl',
+ userManagement: {
+ main: {
+ url: '/userManagement',
+ templateUrl: 'views/userManagement/main.html',
+ controller: 'UserManagementCtrl',
label: 'Users'
},
- edit: {
+ editUser: {
url: '/users/:id/edit',
- templateUrl: 'views/users/create.html',
- controller: 'UsersCreateCtrl',
+ templateUrl: 'views/userManagement/userEdit.html',
+ controller: 'UserEditCtrl',
label: 'Users'
},
- create: {
- url: '/users/new',
- templateUrl: 'views/users/create.html',
- controller: 'UsersCreateCtrl',
- label: 'Users'
- },
- show: {
- url: '/users/:id*',
- templateUrl: 'views/users/show.html',
- controller: 'UsersShowCtrl',
- label: 'Users'
- }
- },
- groups: {
- list: {
- url: '/groups',
- templateUrl: 'views/groups/list.html',
- controller: 'GroupsListCtrl',
- label: 'Groups'
- },
- edit: {
+ editGroup: {
url: '/groups/:id/edit',
- templateUrl: 'views/groups/edit.html',
- controller: 'GroupsEditCtrl',
+ templateUrl: 'views/userManagement/groupEdit.html',
+ controller: 'GroupEditCtrl',
label: 'Groups'
},
- create: {
- url: '/groups/new',
- templateUrl: 'views/groups/create.html',
- controller: 'GroupsCreateCtrl',
- label: 'Groups'
- }
},
views: {
list: {
@@ -157,20 +131,9 @@ angular.module('ambariAdminConsole')
}
},
clusters: {
- manageAccess: {
- url: '/clusters/:id/manageAccess',
- templateUrl: 'views/clusters/manageAccess.html',
- controller: 'ClustersManageAccessCtrl',
- label: 'Roles'
- },
- userAccessList: {
- url: '/clusters/:id/userAccessList',
- templateUrl: 'views/clusters/userAccessList.html',
- controller: 'UserAccessListCtrl'
- },
clusterInformation: {
url: '/clusterInformation',
- templateUrl: 'views/clusterInformation.html',
+ templateUrl: 'views/clusters/clusterInformation.html',
controller: 'ClusterInformationCtrl',
label: 'Cluster Information'
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js
index ac50653..47015d1 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js
@@ -94,9 +94,10 @@ angular.module('ambariAdminConsole')
* @returns {Object}
*/
makeUser: function(user) {
- user.Users.encoded_name = encodeURIComponent(user.Users.user_name);
+ user.Users.encodedName = encodeURIComponent(user.Users.user_name);
user.Users.userTypeName = $t(UserConstants.TYPES[user.Users.user_type].LABEL_KEY);
- user.Users.ldap_user = user.Users.user_type === UserConstants.TYPES.LDAP.VALUE;
+ user.Users.ldapUser = user.Users.user_type === UserConstants.TYPES.LDAP.VALUE;
+ user.Users.role = user.privileges.length ? user.privileges[0].PrivilegeInfo.privilege_id : null;
return user;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css b/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
index 94bdf11..91b2fb1 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
@@ -247,6 +247,9 @@ a.gotoinstance{
.hide-soft{
display: none;
}
+.nowrap {
+ white-space: nowrap;
+}
.visible{
display: block;
}
@@ -386,16 +389,6 @@ a.gotoinstance{
.search-container input {
font-weight: normal;
}
-.groups-pane .search-container .close{
- top: 32px;
-}
-
-.groups-pane table thead th{
- border-top: 0;
-}
-.groups-pane table thead tr:first-child th{
- border: 0;
-}
ul.nav li > a{
cursor: pointer;
@@ -464,16 +457,6 @@ table.no-border tr td{
margin-top: 0;
}
-.groups-pane table ul{
- list-style-type: none;
- margin: 0;
- padding: 0;
-}
-.groups-pane table ul li {
- margin: 0;
- padding: 0;
-}
-
.property-form label{
word-wrap: break-word;
text-overflow: ellipsis;
@@ -539,6 +522,7 @@ button.btn.btn-xs{
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
+ height: 24px;
}
a.btn-primary, a.btn-primary:focus {
@@ -617,13 +601,13 @@ a.alert-link, a.alert-link:hover, a.alert-link:visited{
box-sizing: border-box;
}
-.fix-bottom{
+.fix-bottom th {
border-bottom: none !important;;
border-top: none !important;
border-width: 0;
}
-.fix-top{
+.fix-top th {
border-top: none !important;
border-width: 0;
}
@@ -1334,3 +1318,21 @@ body {
.navigation-bar-fit-height {
z-index: 1001;
}
+
+.entity-actions a {
+ color: inherit;
+ font-size: 16px;
+ cursor: pointer;
+ padding: 0 5px;
+}
+
+td.entity-actions,
+th.entity-actions {
+ width: 10%;
+}
+
+.entity-actions a:hover,
+.entity-actions a:visited:hover,
+.entity-actions a:focus:hover {
+ text-decoration: none;
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/styles/user-management.css
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/styles/user-management.css b/ambari-admin/src/main/resources/ui/admin-web/app/styles/user-management.css
new file mode 100644
index 0000000..77c94ac
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/styles/user-management.css
@@ -0,0 +1,30 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#user-management .table th {
+ vertical-align: baseline;
+}
+
+#user-management .nav.nav-tabs {
+ margin-bottom: 0;
+}
+
+#user-management .users-pane,
+#user-management .groups-pane {
+ margin-top: -35px;
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css b/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css
index 58583de..9bb84df 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css
@@ -16,24 +16,6 @@
* limitations under the License.
*/
-.view-instance-actions a {
- color: inherit;
- font-size: 16px;
- cursor: pointer;
- padding: 0 5px;
-}
-
-td.view-instance-actions,
-th.view-instance-actions {
- width: 10%;
-}
-
-.view-instance-actions a:hover,
-.view-instance-actions a:visited:hover,
-.view-instance-actions a:focus:hover {
- text-decoration: none;
-}
-
#create-instance-form i {
cursor: pointer;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/viewsList.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/viewsList.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/viewsList.html
index 2ff0fc4..04901f1 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/viewsList.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/viewsList.html
@@ -29,24 +29,24 @@
<table class="table table-striped table-hover">
<thead>
<tr class="fix-bottom">
- <th class="fix-bottom col-md-2">
+ <th class="col-md-2">
<span>{{'common.name' | translate}}</span>
</th>
- <th class="fix-bottom col-md-3">
+ <th class="col-md-3">
<span>{{'urls.url' | translate}}</span>
</th>
- <th class="fix-bottom col-md-2">
+ <th class="col-md-2">
<span>{{'views.table.viewType' | translate}}</span>
</th>
- <th class="fix-bottom col-md-2">
+ <th class="col-md-2">
<span>{{'urls.viewInstance' | translate}}</span>
</th>
- <th class="fix-bottom col-md-2 view-instance-actions">
+ <th class="col-md-2 entity-actions">
<span>{{'common.actions' | translate}}</span>
</th>
</tr>
- <tr>
- <th class="fix-top">
+ <tr class="fix-top">
+ <th>
<div class="search-container">
<input type="text" class="form-control" placeholder="{{'common.any' | translate}}"
ng-model="instanceNameFilter" ng-change="filterInstances()">
@@ -57,7 +57,7 @@
</button>
</div>
</th>
- <th class="fix-top">
+ <th>
<div class="search-container">
<input type="text" class="form-control" placeholder="{{'common.any' | translate}}"
ng-model="instanceUrlFilter" ng-change="filterInstances()">
@@ -68,17 +68,15 @@
</button>
</div>
</th>
- <th class="fix-top">
+ <th>
<select class="form-control typefilter v-small-input"
ng-model="instanceTypeFilter"
ng-options="item.label for item in typeFilterOptions"
ng-change="filterInstances()">
</select>
</th>
- <th class="fix-top">
- </th>
- <th class="fix-top">
- </th>
+ <th></th>
+ <th></th>
</tr>
</thead>
@@ -98,7 +96,7 @@
<td>
<span>{{instance.instance_name}}</span>
</td>
- <td class="view-instance-actions" ng-switch="instance.versionObj.status">
+ <td class="entity-actions" ng-switch="instance.versionObj.status">
<span ng-switch-when="PENDING">
<i class="viewstatus pending"></i>
{{'views.pending' | translate}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/clusterInformation.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusterInformation.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/clusterInformation.html
deleted file mode 100644
index ead73c3..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusterInformation.html
+++ /dev/null
@@ -1,87 +0,0 @@
-<!--
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
--->
-
-<div id="cluster-information">
- <div ng-show="cluster.Clusters.provisioning_state !== 'INSTALLED'">
- <div class="welcome-header">
- <h1>{{'main.title' | translate}}</h1>
- <span>{{'main.noClusterDescription' | translate}}</span>
- </div>
- <div class="create-cluster-section">
- <h2>{{'main.createCluster.title' | translate}}</h2>
- <div>
- <span>
- {{'main.createCluster.description' | translate}}
- </span>
- </div>
- <div><i class="fa fa-cloud" aria-hidden="true"></i></div>
- <div>
- <a href="{{fromSiteRoot('/#/installer/step0')}}" class="btn btn-primary">
- {{'main.createCluster.launchInstallWizard' | translate}}
- </a>
- </div>
- </div>
- </div>
-
- <div ng-show="cluster.Clusters.provisioning_state === 'INSTALLED'">
- <form class="row" name="editClusterNameForm" ng-submit="confirmClusterNameChange()">
- <div class="form-group col-xs-4 cluster-name"
- ng-class="{'has-error': editClusterNameForm.clusterName.$invalid}">
- <label for="clusterName">{{'views.clusterName' | translate}}*</label>
- <input type="text"
- class="form-control"
- id="clusterName"
- name="clusterName"
- ng-change="toggleSaveButton()"
- ng-model="edit.clusterName"
- required
- autofocus
- ng-pattern="/^\w*$/"
- ng-maxlength="80"
- tooltip="{{'common.renameClusterTip' | translate}}"
- tooltip-trigger="focus"
- tooltip-placement="bottom"
- ng-class="{edited: isClusterNameEdited}">
- <button
- type="submit"
- ng-class="{'disabled': editClusterNameForm.clusterName.$invalid}"
- class="btn btn-default pull-right"
- ng-show="isClusterNameEdited">
- {{'common.controls.save' | translate}}
- </button>
- </div>
- </form>
- <div>
- <div class="row dev-blueprint">
- <div class="col-sm-11"><span>{{'clusters.devBlueprint' | translate}}</span></div>
- <div class="col-sm-1">
- <div class="btn btn-default pull-right" ng-click="downloadBlueprint()">{{"common.download" | translate}}
- </div>
- </div>
- </div>
- <textarea type="text"
- rows="20"
- class="form-control"
- name="blueprint_text"
- ng-model="blueprint"
- ng-disabled="true"
- ng-readonly="true">
- </textarea>
- </div>
- </div>
-</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/clusterInformation.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/clusterInformation.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/clusterInformation.html
new file mode 100644
index 0000000..ead73c3
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/clusterInformation.html
@@ -0,0 +1,87 @@
+<!--
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+-->
+
+<div id="cluster-information">
+ <div ng-show="cluster.Clusters.provisioning_state !== 'INSTALLED'">
+ <div class="welcome-header">
+ <h1>{{'main.title' | translate}}</h1>
+ <span>{{'main.noClusterDescription' | translate}}</span>
+ </div>
+ <div class="create-cluster-section">
+ <h2>{{'main.createCluster.title' | translate}}</h2>
+ <div>
+ <span>
+ {{'main.createCluster.description' | translate}}
+ </span>
+ </div>
+ <div><i class="fa fa-cloud" aria-hidden="true"></i></div>
+ <div>
+ <a href="{{fromSiteRoot('/#/installer/step0')}}" class="btn btn-primary">
+ {{'main.createCluster.launchInstallWizard' | translate}}
+ </a>
+ </div>
+ </div>
+ </div>
+
+ <div ng-show="cluster.Clusters.provisioning_state === 'INSTALLED'">
+ <form class="row" name="editClusterNameForm" ng-submit="confirmClusterNameChange()">
+ <div class="form-group col-xs-4 cluster-name"
+ ng-class="{'has-error': editClusterNameForm.clusterName.$invalid}">
+ <label for="clusterName">{{'views.clusterName' | translate}}*</label>
+ <input type="text"
+ class="form-control"
+ id="clusterName"
+ name="clusterName"
+ ng-change="toggleSaveButton()"
+ ng-model="edit.clusterName"
+ required
+ autofocus
+ ng-pattern="/^\w*$/"
+ ng-maxlength="80"
+ tooltip="{{'common.renameClusterTip' | translate}}"
+ tooltip-trigger="focus"
+ tooltip-placement="bottom"
+ ng-class="{edited: isClusterNameEdited}">
+ <button
+ type="submit"
+ ng-class="{'disabled': editClusterNameForm.clusterName.$invalid}"
+ class="btn btn-default pull-right"
+ ng-show="isClusterNameEdited">
+ {{'common.controls.save' | translate}}
+ </button>
+ </div>
+ </form>
+ <div>
+ <div class="row dev-blueprint">
+ <div class="col-sm-11"><span>{{'clusters.devBlueprint' | translate}}</span></div>
+ <div class="col-sm-1">
+ <div class="btn btn-default pull-right" ng-click="downloadBlueprint()">{{"common.download" | translate}}
+ </div>
+ </div>
+ </div>
+ <textarea type="text"
+ rows="20"
+ class="form-control"
+ name="blueprint_text"
+ ng-model="blueprint"
+ ng-disabled="true"
+ ng-readonly="true">
+ </textarea>
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/manageAccess.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/manageAccess.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/manageAccess.html
deleted file mode 100644
index a399eff..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/manageAccess.html
+++ /dev/null
@@ -1,63 +0,0 @@
-<!--
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
--->
-
-<div class="cluster-manage-access-pane">
- <div class="clearfix">
- <ol class="breadcrumb pull-left">
- <li class="active">{{clusterName}} {{'common.roles' | translate}}</li>
- </ol>
- </div>
- <hr>
- <div class="pull-right">
- <div class="layout-switch-icon-wrapper">
- <i class="glyphicon glyphicon-th-large layout-switch-icon"></i>
- <p class="label-block">{{'common.blockViewLabel' | translate}}</p>
- </div>
- <div class="layout-switch-icon-wrapper disabled">
- <i class="glyphicon glyphicon-list layout-switch-icon" ng-click="switchToList()" tooltip-html-unsafe="{{'clusters.switchToList' | translate}}"></i>
- <p class="label-list">{{'common.listViewLabel' | translate}}</p>
- </div>
- </div>
- <table class="table">
- <thead>
- <tr>
- <th class="col-sm-2" width="20%">
- <label>{{'common.roles' | translate}}</label>
- <i class="glyphicon glyphicon-question-sign green-icon cursor-pointer" ng-click="showHelpPage()"></i>
- </th>
- <th class="col-sm-5" width="40%"><label>{{'clusters.assignRoles' | translate: '{term: getConstant("common.users")}'}}</label></th>
- <th class="col-sm-5" width="40%"><label>{{'clusters.assignRoles' | translate: '{term: getConstant("common.groups")}'}}</label></th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="permission in permissions">
- <td><label class="" tooltip="{{permission.PermissionInfo.permission_name}}">{{permission.PermissionInfo.permission_label}}</label></td>
- <td>
- <div class="" ng-switch="isEditMode">
- <editable-list items-source="permissionsEdit[permission.PermissionInfo.permission_name].USER" resource-type="User" editable="true"></editable-list>
- </div>
- </td>
- <td>
- <div class="" ng-switch="isEditMode">
- <editable-list items-source="permissionsEdit[permission.PermissionInfo.permission_name].GROUP" resource-type="Group" editable="true"></editable-list>
- </div>
- </td>
- </tr>
- </tbody>
- </table>
-</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/userAccessList.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/userAccessList.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/userAccessList.html
deleted file mode 100644
index 8b29157..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/userAccessList.html
+++ /dev/null
@@ -1,102 +0,0 @@
-<!--
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
--->
-
-<div class="users-pane">
- <div class="clearfix">
- <ol class="breadcrumb pull-left">
- <li class="active">{{clusterId}} {{'common.roles' | translate}}</li>
- </ol>
- </div>
- <hr>
- <div class="pull-right">
- <div class="layout-switch-icon-wrapper disabled">
- <i class="glyphicon glyphicon-th-large layout-switch-icon" ng-click="switchToBlock()" tooltip-html-unsafe="{{'clusters.switchToBlock' | translate}}"></i>
- <p class="label-block">{{'common.blockViewLabel' | translate}}</p>
- </div>
- <div class="layout-switch-icon-wrapper">
- <i class="glyphicon glyphicon-list layout-switch-icon"></i>
- <p class="label-list">{{'common.listViewLabel' | translate}}</p>
- </div>
- </div>
- <ul class="nav nav-pills">
- <li ng-class="{'active': isUserActive}"><a ng-click="switchToUser()">{{'common.users' | translate}}</a></li>
- <li ng-class="{'active': !isUserActive}"><a ng-click="switchToGroup()">{{'common.groups' | translate}}</a></li>
- </ul>
- <br/>
- <table class="table table-striped table-hover">
- <thead>
- <tr>
- <th class="role-name-column">
- <div class="search-container">
- <label for="">{{'common.name' | translate}}</label>
- <input type="text" class="form-control namefilter" placeholder="{{'common.any' | translate}}" ng-model="currentNameFilter" ng-change="resetPagination()">
- <button type="button" class="close clearfilter" ng-show="currentNameFilter" ng-click="currentNameFilter=''; resetPagination()">
- <span aria-hidden="true">×</span><span class="sr-only">{{'common.controls.close' | translate}}</span>
- </button>
- </div>
- </th>
- <th>
- <label for="">{{'clusters.role' | translate}}</label>
- <i class="glyphicon glyphicon-question-sign green-icon cursor-pointer" ng-click="showHelpPage()"></i>
- <select class="form-control statusfilter"
- ng-model="currentRoleFilter"
- ng-options="item.label for item in roleFilterOptions"
- ng-change="resetPagination()">
- </select>
- </th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="user in users">
- <td>
- <a href="#/{{user.url}}">{{user.principal_name}}</a>
- </td>
- <td>
- <div ng-show="!user.editable">{{user.permission_label}}</div>
- <select class="form-control role-select" ng-show="user.editable" ng-model="user.permission_name"
- ng-options="role.permission_name as role.permission_label for role in roleValueOptions">
- </select>
- <span ng-show="user.principal_type != $parent.currentTypeFilter.value"> {{'common.fromGroupMark' | translate}}</span>
- <span ng-show="user.permission_name != user.original_perm">
- <button class="btn btn-default btn-xs cancel" ng-click="cancel(user)">
- <span class="glyphicon glyphicon-remove cancel"></span>
- </button>
- <button class="btn btn-primary btn-xs" ng-click="save(user)">
- <span class="glyphicon glyphicon-ok"></span>
- </button>
- </span>
- </td>
- </tr>
- </tbody>
- </table>
- <div class="alert alert-info col-sm-12" ng-show="!users.length">
- {{'common.alerts.nothingToDisplay' | translate: '{term: (isUserActive ? constants.users : constants.groups)}'}}
- </div>
- <div class="col-sm-12 table-bar">
- <div class="pull-left filtered-info">
- <span>{{'common.filterInfo' | translate: '{showed: tableInfo.showed, total: tableInfo.total, term: (isUserActive ? constants.users : constants.groups)}'}}</span>
- <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">{{'common.controls.clearFilters' | translate}}</a></span>
- </div>
- <div class="pull-right left-margin">
- <pagination class="paginator" total-items="totalUsers" max-size="maxVisiblePages" items-per-page="usersPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
- </div>
- <div class="pull-right">
- <select class="form-control" ng-model="usersPerPage" ng-change="usersPerPageChanges()" ng-options="currOption for currOption in [10, 25, 50, 100]"></select>
- </div>
- </div>
-</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/create.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/create.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/create.html
deleted file mode 100644
index 9a0e0fb..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/create.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!--
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
--->
-<ol class="breadcrumb">
- <li><a href="#/groups">{{'common.groups' | translate}}</a></li>
- <li class="active">{{'groups.createLocal' | translate}}</li>
-</ol>
-<hr>
-<form class="form-horizontal" role="form" novalidate name="form" autocomplete="off">
- <div class="form-group" ng-class="{'has-error' : (form.group_name.$error.required || form.group_name.$error.pattern) && form.submitted}">
- <label for="groupname" class="col-sm-2 control-label">{{'groups.name' | translate}}</label>
- <div class="col-sm-10">
- <input type="text" id="groupname" class="form-control groupname-input" name="group_name" placeholder="{{'groups.name' | translate}}" ng-model="group.group_name" required ng-pattern="/^([a-zA-Z0-9._\s]+)$/" autocomplete="off">
- <div class="alert alert-danger top-margin" ng-show="form.group_name.$error.required && form.submitted">
- {{'common.alerts.fieldIsRequired' | translate}}
- </div>
- <div class="alert alert-danger top-margin" ng-show="form.group_name.$error.pattern && form.submitted">
- {{'common.alerts.onlySimpleChars' | translate}}
- </div>
- </div>
- </div>
- <div class="form-group">
- <div class="col-sm-offset-2 col-sm-10">
- <button class="btn btn-primary groupcreate-btn pull-right left-margin" ng-click="createGroup()">{{'common.controls.save' | translate}}</button>
- <a href ng-click="cancel()" class="btn btn-default pull-right cancel-button">{{'common.controls.cancel' | translate}}</a>
- </div>
- </div>
-
-</form>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/edit.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/edit.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/edit.html
deleted file mode 100644
index 1aafd03..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/edit.html
+++ /dev/null
@@ -1,98 +0,0 @@
-<!--
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
--->
-
-<div class="clearfix">
- <ol class="breadcrumb pull-left">
- <li><a href="#/groups">{{'common.groups' | translate}}</a></li>
- <li class="active">{{group.group_name}}</li>
- </ol>
- <div class="pull-right top-margin-4">
- <div ng-switch="group.group_type != 'LOCAL'">
- <button ng-switch-when="true" class="btn disabled deletegroup-btn deleteuser-btn" tooltip="{{'common.cannotDelete' | translate: '{term: constants.group}'}}">{{'common.delete' | translate: '{term: constants.group}'}}</button>
- <button ng-switch-when="false" class="btn btn-danger deletegroup-btn" ng-click="deleteGroup(group)">{{'common.delete' | translate: '{term: constants.group}'}}</button>
- </div>
-
- </div>
-</div>
-<hr>
-<form class="form-horizontal group-edit" role="form" novalidate name="form" >
- <div class="form-group">
- <label for="" class="col-sm-2 control-label">{{'common.type' | translate}}</label>
- <div class="col-sm-10">
- <label for="" class="control-label">{{group.groupTypeName | translate}}</label>
- </div>
- </div>
- <div class="form-group">
- <label for="members" class="col-sm-2 control-label">{{group.groupTypeName | translate}} {{'groups.members' | translate}}</label>
- <div class="col-sm-10">
- <editable-list items-source="group.editingUsers" resource-type="User" editable="group.group_type == 'LOCAL'"></editable-list>
- </div>
- </div>
-
- <div class="form-group">
- <label for="" class="col-sm-2 control-label">{{'common.privileges' | translate}}</label>
- <div class="col-sm-10">
- <table class="table" ng-hide="hidePrivileges">
- <thead>
- <tr>
- <th>{{'common.cluster' | translate}}</th>
- <th>{{'common.clusterRole' | translate}}</th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="(name, privilege) in privileges.clusters">
- <td>
- <span class="glyphicon glyphicon-cloud"></span>
- <a href="#/clusters/{{name}}/manageAccess">{{name}}</a>
- </td>
- <td>
- <span tooltip="{{item}}" ng-repeat="item in privilege">{{item | translate}}{{$last ? '' : ', '}}</span>
- </td>
- </tr>
- <tr>
- <td ng-show="noClusterPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.cluster}'}}</td>
- </tr>
- </tbody>
- <thead class="view-permission-header">
- <tr>
- <th>{{'common.view' | translate}}</th>
- <th>{{'common.viewPermissions' | translate}}</th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="(name, privilege) in privileges.views">
- <td>
- <span class="glyphicon glyphicon-th"></span>
- <a href="#/views/{{privilege.view_name}}/versions/{{privilege.version}}/instances/{{name}}/edit">{{name}}</a>
- </td>
- <td>
- <span tooltip="{{item}}" ng-repeat="item in privilege.privileges">{{item | translate}}{{$last ? '' : ', '}}</span>
- </td>
- <td>
- <i class="fa fa-trash-o" aria-hidden="true" ng-click="removePrivilege(name, privilege);"></i>
- </td>
- </tr>
- <tr>
- <td ng-show="noViewPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.view}'}}</td>
- </tr>
- </tbody>
- </table>
- <div class="alert alert-info hide-soft" ng-class="{'visible' : !privileges}">{{'common.alerts.noPrivilegesDescription' | translate: '{term: constants.group.toLowerCase()}'}}</div>
- </div>
- </div>
-</form>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/list.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/list.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/list.html
deleted file mode 100644
index b39f55d..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/list.html
+++ /dev/null
@@ -1,80 +0,0 @@
-<!--
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
--->
-<div class="groups-pane">
- <div class="clearfix">
- <ol class="breadcrumb pull-left">
- <li class="active">{{'common.groups' | translate}}</li>
- </ol>
- <div class="pull-right top-margin-4">
- <link-to route="groups.create" class="btn btn-default creategroup-btn">
- {{'groups.createLocal' | translate}}
- </link-to>
- </div>
- </div>
- <table class="table table-striped table-hover col-sm-12">
- <thead>
- <tr>
- <th class="col-sm-8">
- <div class="search-container">
- <label for="">{{'groups.name' | translate}}</label>
- <input type="text" class="form-control namefilter" placeholder="{{'common.any' | translate}}" ng-model="currentNameFilter" ng-change="resetPagination()">
- <button type="button" class="close" ng-show="currentNameFilter" ng-click="currentNameFilter=''; resetPagination()"><span aria-hidden="true">×</span><span class="sr-only">{{'common.controls.close' | translate}}</span></button>
- </div>
- </th>
- <th class="col-sm-2">
- <label for="">{{'common.type' | translate}}</label>
- <select class="form-control typefilter"
- ng-model="currentTypeFilter"
- ng-options="item.label for item in typeFilterOptions"
- ng-change="resetPagination();">
- </select>
- </th>
- <th class="col-sm-2 vertical-top">
- <label for="">{{'groups.members' | translate}}</label>
- </th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="group in groups">
- <td class="col-sm-8">
- <link-to route="groups.edit" class="link-to-group" id="{{group.group_name}}">{{group.group_name}}</link-to>
- </td>
- <td class="col-sm-2">{{group.groupTypeName | translate}}</td>
- <td class="col-sm-2">{{'groups.membersPlural' | translate: '{n: group.members && group.members.length || 0}'}}</td>
- </tr>
- </tbody>
- </table>
- <div ng-if="isLoading" class="spinner-container">
- <i class="fa fa-2x fa-spinner fa-spin" aria-hidden="true"></i>
- </div>
- <div class="alert empty-table-alert col-sm-12" ng-show="!groups.length && !isLoading">
- {{'common.alerts.nothingToDisplay' | translate: '{term: constants.groups}'}}
- </div>
- <div class="col-sm-12 table-bar">
- <div class="pull-left filtered-info">
- <span>{{'common.filterInfo' | translate: '{showed: tableInfo.showed, total: tableInfo.total, term: constants.groups}'}}</span>
- <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">{{'common.controls.clearFilters' | translate}}</a></span>
- </div>
- <div class="pull-right left-margin">
- <pagination class="paginator" total-items="totalGroups" max-size="maxVisiblePages" items-per-page="groupsPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
- </div>
- <div class="pull-right">
- <select class="form-control" ng-model="groupsPerPage" ng-change="groupsPerPageChanges()" ng-options="currOption for currOption in [10, 25, 50, 100]"></select>
- </div>
- </div>
-</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/sideNav.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/sideNav.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/sideNav.html
index 97dc5d3..98a95cd 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/sideNav.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/sideNav.html
@@ -59,25 +59,11 @@
</li>
</ul>
</li>
- <li class="mainmenu-li dropdown has-sub-menu">
- <a title="{{'common.userManagement' | translate}}" rel="tooltip" data-placement="right" data-toggle="collapse-sub-menu">
- <span class="toggle-icon glyphicon glyphicon-menu-down pull-right"></span>
+ <li class="mainmenu-li" ng-class="{active: isActive('userManagement.main')}">
+ <link-to route="userManagement.main" class="userslist-link" title="{{'common.users' | translate}}" rel="tooltip" data-placement="right">
<i class="navigation-icon fa fa-users" aria-hidden="true"></i>
- <span class="navigation-menu-item">{{'common.userManagement' | translate}}</span>
- </a>
- <ul class="sub-menu nav nav-pills nav-stacked">
- <li class="submenu-li"
- ng-class="{active: isActive('clusters.manageAccess') || isActive('clusters.userAccessList')}"
- ng-show="cluster.Clusters.provisioning_state === 'INSTALLED'">
- <a href="#/clusters/{{cluster.Clusters.cluster_name}}/manageAccess" class="roles">{{'common.roles' | translate}}</a>
- </li>
- <li class="submenu-li" ng-class="{active: isActive('users.list')}">
- <link-to route="users.list" class="userslist-link">{{'common.users' | translate}}</link-to>
- </li>
- <li class="submenu-li" ng-class="{active: isActive('groups.list')}">
- <link-to route="groups.list" class="groupslist-link">{{'common.groups' | translate}}</link-to>
- </li>
- </ul>
+ <span class="navigation-menu-item">{{'common.users' | translate}}</span>
+ </link-to>
</li>
<li class="mainmenu-li" ng-class="{active: isActive('views.list')}">
<link-to route="views.list" class="viewslist-link" title="{{'common.views' | translate}}" rel="tooltip" data-placement="right">
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupEdit.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupEdit.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupEdit.html
new file mode 100644
index 0000000..90a1907
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupEdit.html
@@ -0,0 +1,99 @@
+<!--
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+-->
+
+<div class="clearfix">
+ <div class="pull-right">
+ <div ng-switch="group.group_type != 'LOCAL'">
+ <button
+ ng-switch-when="true"
+ class="btn disabled deletegroup-btn"
+ tooltip="{{'common.cannotDelete' | translate: '{term: constants.group}'}}">
+ {{'common.delete' | translate: '{term: constants.group}'}}
+ </button>
+ <button ng-switch-when="false" class="btn btn-danger deletegroup-btn" ng-click="deleteGroup(group)">
+ {{'common.delete' | translate: '{term: constants.group}'}}
+ </button>
+ </div>
+ </div>
+</div>
+<form class="form-horizontal group-edit" role="form" novalidate name="form" >
+ <div class="form-group">
+ <label class="col-sm-2 control-label">{{'common.type' | translate}}</label>
+ <div class="col-sm-10">
+ <label class="control-label">{{group.groupTypeName | translate}}</label>
+ </div>
+ </div>
+ <div class="form-group">
+ <label class="col-sm-2 control-label">{{group.groupTypeName | translate}} {{'groups.members' | translate}}</label>
+ <div class="col-sm-10">
+ <editable-list items-source="group.editingUsers" resource-type="User" editable="group.group_type == 'LOCAL'"></editable-list>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label class="col-sm-2 control-label">{{'common.privileges' | translate}}</label>
+ <div class="col-sm-10">
+ <table class="table" ng-hide="hidePrivileges">
+ <thead>
+ <tr>
+ <th>{{'common.cluster' | translate}}</th>
+ <th>{{'common.clusterRole' | translate}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="(name, privilege) in privileges.clusters">
+ <td>
+ <span class="glyphicon glyphicon-cloud"></span>
+ <a href="#/clusters/{{name}}/manageAccess">{{name}}</a>
+ </td>
+ <td>
+ <span tooltip="{{item}}" ng-repeat="item in privilege">{{item | translate}}{{$last ? '' : ', '}}</span>
+ </td>
+ </tr>
+ <tr>
+ <td ng-show="noClusterPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.cluster}'}}</td>
+ </tr>
+ </tbody>
+ <thead class="view-permission-header">
+ <tr>
+ <th>{{'common.view' | translate}}</th>
+ <th>{{'common.viewPermissions' | translate}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="(name, privilege) in privileges.views">
+ <td>
+ <span class="glyphicon glyphicon-th"></span>
+ <a href="#/views/{{privilege.view_name}}/versions/{{privilege.version}}/instances/{{name}}/edit">{{name}}</a>
+ </td>
+ <td>
+ <span tooltip="{{item}}" ng-repeat="item in privilege.privileges">{{item | translate}}{{$last ? '' : ', '}}</span>
+ </td>
+ <td>
+ <i class="fa fa-trash-o" aria-hidden="true" ng-click="removePrivilege(name, privilege);"></i>
+ </td>
+ </tr>
+ <tr>
+ <td ng-show="noViewPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.view}'}}</td>
+ </tr>
+ </tbody>
+ </table>
+ <div class="alert alert-info hide-soft" ng-class="{'visible' : !privileges}">{{'common.alerts.noPrivilegesDescription' | translate: '{term: constants.group.toLowerCase()}'}}</div>
+ </div>
+ </div>
+</form>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupsList.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupsList.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupsList.html
new file mode 100644
index 0000000..d79d14e
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupsList.html
@@ -0,0 +1,94 @@
+<!--
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+-->
+<div class="groups-pane">
+ <div class="clearfix panel">
+ <button class="btn btn-default creategroup-btn pull-right" ng-click="createGroup()">
+ {{'groups.createLocal' | translate}}
+ </button>
+ </div>
+ <table class="table table-striped table-hover col-sm-12">
+ <thead>
+ <tr>
+ <th class="col-sm-6">
+ <span>{{'groups.name' | translate}}</span>
+ </th>
+ <th class="col-sm-2">
+ <span>{{'common.type' | translate}}</span>
+ </th>
+ <th class="col-sm-2">
+ <span>{{'groups.members' | translate}}</span>
+ </th>
+ <th class="col-sm-2">
+ <span>{{'common.actions' | translate}}</span>
+ </th>
+ </tr>
+ <tr>
+ <th class="col-sm-6">
+ <div class="search-container">
+ <input type="text" class="form-control namefilter" placeholder="{{'common.any' | translate}}" ng-model="filter.name" ng-change="resetPagination()">
+ <button type="button" class="close" ng-show="filter.name" ng-click="filter.name=''; resetPagination()"><span aria-hidden="true">×</span><span class="sr-only">{{'common.controls.close' | translate}}</span></button>
+ </div>
+ </th>
+ <th class="col-sm-2">
+ <select class="form-control typefilter"
+ ng-model="filter.type"
+ ng-options="item.label for item in typeFilterOptions"
+ ng-change="resetPagination();">
+ </select>
+ </th>
+ <th class="col-sm-2"></th>
+ <th class="col-sm-2"></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="group in groups">
+ <td class="col-sm-8">
+ <span>{{group.group_name}}</span>
+ </td>
+ <td class="col-sm-2">{{group.groupTypeName | translate}}</td>
+ <td class="col-sm-2">{{'groups.membersPlural' | translate: '{n: group.members && group.members.length || 0}'}}</td>
+ <td class="entity-actions">
+ <link-to route="userManagement.editGroup" class="link-to-group" id="{{group.group_name}}">
+ <i class="fa fa-pencil"></i>
+ </link-to>
+ <a href ng-click="deleteGroup(group)">
+ <i class="fa fa-trash-o"></i>
+ </a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <div ng-if="isLoading" class="spinner-container">
+ <i class="fa fa-2x fa-spinner fa-spin" aria-hidden="true"></i>
+ </div>
+ <div class="alert empty-table-alert col-sm-12" ng-show="!groups.length && !isLoading">
+ {{'common.alerts.nothingToDisplay' | translate: '{term: constants.groups}'}}
+ </div>
+ <div class="col-sm-12 table-bar" ng-show="totalGroups > minRowsToShowPagination">
+ <div class="pull-left filtered-info">
+ <span>{{'common.filterInfo' | translate: '{showed: tableInfo.showed, total: tableInfo.total, term: constants.groups}'}}</span>
+ <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">{{'common.controls.clearFilters' | translate}}</a></span>
+ </div>
+ <div class="pull-right left-margin">
+ <pagination class="paginator" total-items="totalGroups" max-size="maxVisiblePages" items-per-page="groupsPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
+ </div>
+ <div class="pull-right">
+ <select class="form-control" ng-model="groupsPerPage" ng-change="groupsPerPageChanges()" ng-options="currOption for currOption in [10, 25, 50, 100]"></select>
+ </div>
+ </div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/main.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/main.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/main.html
new file mode 100644
index 0000000..079eefb
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/main.html
@@ -0,0 +1,36 @@
+<!--
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+-->
+
+<div id="user-management">
+ <ul class="nav nav-tabs">
+ <li ng-class="{active: activeTab === 'USERS'}">
+ <a ng-click="activeTab = 'USERS'">{{'common.users' | translate}}</a>
+ </li>
+ <li ng-class="{active: activeTab === 'GROUPS'}">
+ <a ng-click="activeTab = 'GROUPS'">{{'common.groups' | translate}}</a>
+ </li>
+ </ul>
+ <div>
+ <div class="users" ng-if="activeTab === 'USERS'">
+ <div ng-include="'views/userManagement/usersList.html'" ng-controller="UsersListCtrl"></div>
+ </div>
+ <div class="groups" ng-if="activeTab === 'GROUPS'">
+ <div ng-include="'views/userManagement/groupsList.html'" ng-controller="GroupsListCtrl"></div>
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/changePassword.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/changePassword.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/changePassword.html
new file mode 100644
index 0000000..f29d315
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/changePassword.html
@@ -0,0 +1,46 @@
+<!--
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+-->
+<div class="modal-header">
+ <h3 class="modal-title">{{'users.changePasswordFor' | translate: '{userName: userName}'}}</h3>
+</div>
+<div class="modal-body">
+ <form class="form-horizontal" novalidate name="form.passwordChangeForm" role="form" >
+ <div class="form-group" ng-class="{'has-error' : (form.passwordChangeForm.currentPassword.$error.required && form.passwordChangeForm.submitted)}">
+ <label for="" class="col-sm-4 control-label" >{{'users.yourPassword' | translate}}</label>
+ <div class="col-sm-8">
+ <input type="password" name="currentPassword" class="form-control bottom-margin" placeholder="{{'users.yourPassword' | translate}}" required ng-model="passwordData.currentUserPassword" autocomplete="off">
+ <div class="alert alert-danger no-margin-bottom" ng-show='form.passwordChangeForm.password.$error.required && form.passwordChangeForm.submitted'>{{'users.alerts.passwordRequired' | translate}}</div>
+ </div>
+ </div>
+ <div class="form-group no-margin-bottom" ng-class="{'has-error' : (form.passwordChangeForm.password.$error.required && form.passwordChangeForm.submitted) || form.passwordChangeForm.confirmPassword.$error.passwordVerify}">
+ <label for="" class="col-sm-4 control-label">{{'users.newPassword' | translate}}:</label>
+ <div class="col-sm-8">
+ <input type="password" class="form-control bottom-margin" name="password" placeholder="{{'users.newPassword' | translate}}" required ng-model="passwordData.password" autocomplete="off">
+ <input type="password" class="form-control bottom-margin" name="confirmPassword" placeholder="{{'users.newPasswordConfirmation' | translate}}" required ng-model="passwordData.passwordConfirmation"
+ password-verify="passwordData.password" autocomplete="off">
+ <div class="alert alert-danger no-margin-bottom" ng-show='form.passwordChangeForm.confirmPassword.$error.passwordVerify'>{{'users.alerts.wrongPassword' | translate}}</div>
+ <div class="alert alert-danger no-margin-bottom" ng-show='form.passwordChangeForm.password.$error.required && form.passwordChangeForm.submitted'>{{'users.alerts.passwordRequired' | translate}}</div>
+ </div>
+
+ </div>
+ </form>
+</div>
+<div class="modal-footer">
+ <button class="btn btn-default" ng-click="cancel()">{{'common.controls.cancel' | translate}}</button>
+ <button class="btn btn-primary" ng-click="ok()">{{'common.controls.ok' | translate}}</button>
+</div>
\ No newline at end of file