You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by yu...@apache.org on 2014/09/10 06:25:28 UTC
git commit: AMBARI-7235. Admin View: it is difficult and error-prone
to be typing users and groups in textarea for membership and permission
changes (implement type-ahead for user + group input fields). (yusaku)
Repository: ambari
Updated Branches:
refs/heads/trunk 364417494 -> 9cf27bf86
AMBARI-7235. Admin View: it is difficult and error-prone to be typing users and groups in textarea for membership and permission changes (implement type-ahead for user + group input fields). (yusaku)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/9cf27bf8
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/9cf27bf8
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/9cf27bf8
Branch: refs/heads/trunk
Commit: 9cf27bf86046b0061f30e5c29e16b8b7aa7ab921
Parents: 3644174
Author: Yusaku Sako <yu...@hortonworks.com>
Authored: Tue Sep 9 18:32:26 2014 -0700
Committer: Yusaku Sako <yu...@hortonworks.com>
Committed: Tue Sep 9 18:32:43 2014 -0700
----------------------------------------------------------------------
.../main/resources/ui/admin-web/app/index.html | 2 +
.../resources/ui/admin-web/app/scripts/app.js | 1 +
.../controllers/ambariViews/ViewsEditCtrl.js | 8 +
.../clusters/ClustersManageAccessCtrl.js | 8 +
.../controllers/groups/GroupsEditCtrl.js | 9 +
.../scripts/controllers/users/UsersShowCtrl.js | 13 ++
.../app/scripts/directives/editableList.js | 199 +++++++++++++++++++
.../ui/admin-web/app/scripts/services/Group.js | 6 +
.../ui/admin-web/app/scripts/services/User.js | 7 +
.../resources/ui/admin-web/app/styles/main.css | 182 +++++++++++++++++
.../admin-web/app/views/ambariViews/edit.html | 29 +--
.../app/views/clusters/manageAccess.html | 31 +--
.../app/views/directives/editableList.html | 44 ++++
.../ui/admin-web/app/views/groups/edit.html | 23 +--
.../ui/admin-web/app/views/users/show.html | 22 +-
.../src/main/resources/ui/admin-web/bower.json | 3 +-
16 files changed, 490 insertions(+), 97 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/9cf27bf8/ambari-admin/src/main/resources/ui/admin-web/app/index.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/index.html b/ambari-admin/src/main/resources/ui/admin-web/app/index.html
index 2bc520f..e7a8371 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/index.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/index.html
@@ -85,6 +85,7 @@
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="bower_components/angular/angular.js"></script>
+ <script src="bower_components/angular-animate/angular-animate.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
<script src="bower_components/lodash/dist/lodash.compat.js"></script>
@@ -126,6 +127,7 @@
<script src="scripts/directives/linkToDir.js"></script>
<script src="scripts/directives/PasswordVerify.js"></script>
<script src="scripts/directives/disabledTooltip.js"></script>
+ <script src="scripts/directives/editableList.js"></script>
<script src="scripts/services/User.js"></script>
<script src="scripts/services/Group.js"></script>
<script src="scripts/services/View.js"></script>
http://git-wip-us.apache.org/repos/asf/ambari/blob/9cf27bf8/ambari-admin/src/main/resources/ui/admin-web/app/scripts/app.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/app.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/app.js
index b9fcce2..b580da7 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/app.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/app.js
@@ -19,6 +19,7 @@
angular.module('ambariAdminConsole', [
'ngRoute',
+ 'ngAnimate',
'ui.bootstrap',
'restangular',
'angularAlert',
http://git-wip-us.apache.org/repos/asf/ambari/blob/9cf27bf8/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsEditCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsEditCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsEditCtrl.js
index d860904..4355f63 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsEditCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsEditCtrl.js
@@ -160,6 +160,14 @@ angular.module('ambariAdminConsole')
$scope.editPermissionDisabled = true;
};
+ $scope.$watch(function() {
+ return $scope.permissionsEdit;
+ }, function(newValue) {
+ if(newValue){
+ $scope.savePermissions();
+ }
+ }, true);
+
$scope.deleteInstance = function(instance) {
ConfirmationModal.show('Delete View Instance', 'Are you sure you want to delete View Instance '+ instance.ViewInstanceInfo.label +'?').then(function() {
View.deleteInstance(instance.ViewInstanceInfo.view_name, instance.ViewInstanceInfo.version, instance.ViewInstanceInfo.instance_name)
http://git-wip-us.apache.org/repos/asf/ambari/blob/9cf27bf8/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClustersManageAccessCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClustersManageAccessCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClustersManageAccessCtrl.js
index ff61f60..8999594 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClustersManageAccessCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClustersManageAccessCtrl.js
@@ -61,4 +61,12 @@ angular.module('ambariAdminConsole')
});
$scope.isEditMode = false;
};
+
+ $scope.$watch(function() {
+ return $scope.permissionsEdit;
+ }, function(newValue) {
+ if(newValue){
+ $scope.save();
+ }
+ }, true);
}]);
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/9cf27bf8/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsEditCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsEditCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsEditCtrl.js
index 0896de1..a322c1d 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsEditCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsEditCtrl.js
@@ -26,6 +26,14 @@ angular.module('ambariAdminConsole')
$scope.dataLoaded = false;
$scope.isMembersEditing = false;
+
+ $scope.$watch(function() {
+ return $scope.group.editingUsers;
+ }, function(newValue) {
+ if(newValue && !angular.equals(newValue, $scope.groupMembers)){
+ $scope.updateMembers();
+ }
+ }, true);
$scope.enableMembersEditing = function() {
$scope.isMembersEditing = true;
@@ -49,6 +57,7 @@ angular.module('ambariAdminConsole')
function loadMembers(){
$scope.group.getMembers().then(function(members) {
$scope.groupMembers = members;
+ $scope.group.editingUsers = angular.copy($scope.groupMembers);
});
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/9cf27bf8/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
index 97a7234..f3e4240 100644
--- 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
@@ -24,6 +24,7 @@ angular.module('ambariAdminConsole')
User.get($routeParams.id).then(function(data) {
$scope.user = data.Users;
$scope.isCurrentUser = $scope.user.user_name === Auth.getCurrentUser();
+ $scope.editingGroupsList = angular.copy($scope.user.groups);
});
}
@@ -38,6 +39,18 @@ angular.module('ambariAdminConsole')
$scope.editingGroupsList = angular.copy($scope.user.groups);
};
+ $scope.$watch(function() {
+ return $scope.editingGroupsList;
+ }, function(newValue) {
+ if(newValue){
+ if( !angular.equals(newValue, $scope.user.groups) ){
+ console.log('Update!');
+ $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);
http://git-wip-us.apache.org/repos/asf/ambari/blob/9cf27bf8/ambari-admin/src/main/resources/ui/admin-web/app/scripts/directives/editableList.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/directives/editableList.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/directives/editableList.js
new file mode 100644
index 0000000..5d72078
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/directives/editableList.js
@@ -0,0 +1,199 @@
+/**
+ * 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')
+.directive('editableList', ['$q', '$document', function($q, $document) {
+ return {
+ restrict: 'E',
+ templateUrl: 'views/directives/editableList.html',
+ scope: {
+ itemsSource: '=',
+ resourceType: '@',
+ editable: '='
+ },
+ link: function($scope, $elem, $attr, $ctrl) {
+ var $editBox = $elem.find('[contenteditable]');
+
+ var readInput = function() {
+ $scope.$apply(function() {
+ $scope.input = $editBox.html();
+ });
+ };
+
+ $scope.$watch(function() {
+ return $scope.input;
+ }, function(newValue) {
+ if(newValue === ''){
+ $scope.clearInput();
+ }
+ });
+
+ $scope.clearInput = function() {
+ $editBox.html('').blur();
+ };
+
+ $scope.focusOnInput = function() {
+ setTimeout(function() {
+ var elem = $editBox[0];
+ var selection = window.getSelection(),
+ range = document.createRange();
+
+ elem.innerHTML = '\u00a0';
+ range.selectNodeContents(elem);
+ selection.removeAllRanges();
+ selection.addRange(range);
+ document.execCommand('delete', false, null);
+ }, 0);
+ };
+
+ $editBox.on('input', readInput);
+ $editBox.on('keydown', function(e) {
+ switch(e.which){
+ case 27: // ESC
+ $editBox.html('').blur();
+ readInput();
+ break;
+ case 13: // Enter
+ $scope.$apply(function() {
+ $scope.addItem();
+ });
+ return false;
+ break;
+ case 40: // Down arrow
+ $scope.downArrowHandler();
+ break;
+ case 38: // Up arrow
+ $scope.upArrowHandler();
+ break;
+ }
+ });
+ },
+ controller: ['$scope', '$injector', function($scope, $injector) {
+ var $resource = $injector.get($scope.resourceType);
+
+ $scope.identity = angular.identity; // Sorting function
+
+ $scope.items = angular.copy($scope.itemsSource);
+ $scope.editMode = false;
+ $scope.input = '';
+ $scope.typeahead = [];
+ $scope.selectedTypeahed = 0;
+
+ // Watch source of items
+ $scope.$watch(function() {
+ return $scope.itemsSource;
+ }, function(newValue) {
+ $scope.items = angular.copy($scope.itemsSource);
+ }, true);
+
+ // When input has changed - load typeahead items
+ $scope.$watch(function() {
+ return $scope.input;
+ }, function(newValue) {
+ if(newValue){
+ var newValue = newValue.split(',').filter(function(i){
+ i = i.replace(' ', ''); // Sanitize from spaces
+ return !!i.trim();
+ });
+ if( newValue.length > 1){
+ // If someone paste coma separated string, then just add all items to list
+ angular.forEach(newValue, function(item) {
+ $scope.addItem(item);
+ });
+ $scope.clearInput();
+
+ } else {
+ // Load typeahed items based on current input
+ $resource.listByName(newValue).then(function(data) {
+ var items = [];
+ angular.forEach(data.data.items, function(item) {
+ var name;
+ if($scope.resourceType === 'User'){
+ name = item.Users.user_name;
+ } else if($scope.resourceType === 'Group'){
+ name = item.Groups.group_name;
+ }
+
+ if($scope.items.indexOf(name) < 0){ // Only if item not in list
+ items.push(name);
+ }
+ $scope.typeahead = items.slice(0, 5);
+ $scope.selectedTypeahed = 0;
+ });
+ });
+ }
+
+
+ } else {
+ $scope.typeahead = [];
+ $scope.selectedTypeahed = 0;
+ }
+ });
+
+ $scope.enableEditMode = function() {
+ if( $scope.editable && !$scope.editMode){
+ $scope.editMode = true;
+ if( $scope.items.length === 0){
+ $scope.focusOnInput();
+ }
+ }
+ };
+
+ $scope.cancel = function(event) {
+ $scope.editMode = false;
+ $scope.items = angular.copy($scope.itemsSource);
+ $scope.input = '';
+ event.stopPropagation();
+ };
+ $scope.save = function(event) {
+ $scope.itemsSource = $scope.items;
+ $scope.editMode = false;
+ $scope.input = '';
+ event.stopPropagation();
+ };
+
+
+ $scope.downArrowHandler = function() {
+ $scope.$apply(function() {
+ $scope.selectedTypeahed = ($scope.selectedTypeahed+1) % $scope.typeahead.length;
+ });
+ };
+ $scope.upArrowHandler = function() {
+ $scope.$apply(function() {
+ $scope.selectedTypeahed -= 1;
+ $scope.selectedTypeahed = $scope.selectedTypeahed < 0 ? $scope.typeahead.length-1 : $scope.selectedTypeahed;
+ });
+ };
+
+ $scope.addItem = function(item) {
+ item = item ? item : $scope.typeahead.length ? $scope.typeahead[$scope.selectedTypeahed] : $scope.input;
+
+ if(item && $scope.items.indexOf(item) < 0){
+ $scope.items.push(item);
+ $scope.input = '';
+ }
+ };
+
+ $scope.removeFromItems = function(item) {
+ $scope.items.splice( $scope.items.indexOf(item), 1);
+ };
+ }]
+ };
+}]);
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/9cf27bf8/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Group.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Group.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Group.js
index efe39a3..87f7831 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Group.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Group.js
@@ -174,6 +174,12 @@ angular.module('ambariAdminConsole')
return deferred.promise;
};
+ Group.listByName = function(name) {
+ return $http.get(Settings.baseUrl + '/groups?'
+ + 'Groups/group_name.matches(.*'+name+'.*)'
+ );
+ };
+
Group.getPrivilegies = function(groupId) {
return $http.get(Settings.baseUrl + '/privileges', {
params:{
http://git-wip-us.apache.org/repos/asf/ambari/blob/9cf27bf8/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 9c2e36a..40c5683 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
@@ -46,6 +46,13 @@ angular.module('ambariAdminConsole')
+ (params.admin ? '&Users/admin=true' : '')
);
},
+ listByName: function(name) {
+ return $http.get(
+ Settings.baseUrl + '/users?'
+ + 'Users/user_name.matches(.*'+name+'.*)'
+ + '&from=0&page_size=20'
+ );
+ },
get: function(userId) {
return Restangular.one('users', userId).get();
},
http://git-wip-us.apache.org/repos/asf/ambari/blob/9cf27bf8/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 e92fe1a..bfa0032 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
@@ -16,6 +16,182 @@
* limitations under the License.
*/
+
+
+/*
+ ------ START editable-list DIRECTIVE SECTION ------ -
+*/
+.editable-list-container.well{
+ padding: 10px;
+ position: relative;
+ margin-bottom: 30px;
+ cursor: pointer;
+}
+.editable-list-container.well.edit-mode{
+ cursor: default;
+}
+.editable-list-container.well.disabled{
+ background: white;
+}
+
+.editable-list-container .items-box{
+
+}
+.editable-list-container .items-box ul.items-list{
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+
+.editable-list-container .items-box ul.items-list li.item{
+ display: inline-block;
+ padding: 4px 8px;
+ margin: 0 5px 5px 2px;
+ background: white;
+ border: 1px solid #ebebeb;
+ max-width: 100%;
+ white-space: nowrap;
+ position: relative;
+}
+
+.editable-list-container.edit-mode .items-box ul.items-list li.item{
+ padding-right: 25px;
+}
+
+.editable-list-container .items-box ul.items-list li.item.ng-leave-active{
+ display: none;
+}
+.editable-list-container .items-box ul.items-list li a{
+ text-decoration: none;
+}
+
+.editable-list-container .items-box ul.items-list li.item .close{
+ margin: -2px 0 0 5px;
+ width: 13px;
+ outline: none;
+ position: absolute;
+ display: none;
+}
+.editable-list-container.edit-mode .items-box ul.items-list li.item .close{
+ display: inline-block;
+}
+
+.editable-list-container .actions-panel{
+ position: absolute;
+ right: 5px;
+ bottom: -30px;
+ padding: 2px 5px 5px 5px;
+ background: #f5f5f5;
+ border: 1px solid #e3e3e3;
+ border-top: none;
+ border-radius: 0 0 4px 4px;
+
+ -webkit-transition: all 0.3s;
+ -o-transition: all 0.3s;
+ transition: all 0.3s;
+
+ -ms-transform-origin: 0% 0%; /* IE 9 */
+ -webkit-transform-origin: 0% 0%; /* Chrome, Safari, Opera */
+ transform-origin: 0% 0%;
+
+ -webkit-transform: rotateX(0deg);
+ -ms-transform: rotateX(0deg);
+ -o-transform: rotateX(0deg);
+ transform: rotateX(0deg);
+}
+.editable-list-container .actions-panel.ng-hide{
+ -webkit-transform: rotateX(90deg);
+ -ms-transform: rotateX(90deg);
+ -o-transform: rotateX(90deg);
+ transform: rotateX(90deg);
+}
+
+.editable-list-container.edit-mode .items-box ul.items-list li.item.add-item-input.ng-hidden{
+ display: none !important;
+}
+.editable-list-container.edit-mode .items-box ul.items-list li.item.add-item-input{
+ display: inline-block!important;
+ outline: none;
+ max-width: 200px;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ position: relative;
+ padding-right: 8px;
+ -webkit-transition: none;
+ -o-transition: none;
+ transition: none;
+}
+
+.add-item-input span{
+ display: block;
+ outline: none;
+ min-width: 30px;
+ position: relative;
+ cursor: pointer;
+}
+.add-item-input span:focus{
+ cursor: default;
+}
+.editable-list-container .items-box ul.items-list li.item.add-item{
+ color: #ddd;
+}
+.add-item-input span:empty:before{
+ content: 'New';
+ position: absolute;
+ left: 0;
+ color: #ddd;
+}
+.add-item-input span:focus:before{
+ display: none;
+}
+.typeahead-box{
+ position: absolute;
+ left: 0;
+ margin-top: 5px;
+ background: white;
+ border: 1px solid #ebebeb;
+ z-index: 1000;
+ min-width: 65px;
+}
+.typeahead-box ul{
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+.typeahead-box ul li{
+ padding: 3px 5px;
+ display: block;
+ cursor: pointer;
+}
+
+.typeahead-box ul li.selected, .typeahead-box ul li:hover{
+ background: #eee;
+}
+
+.editable-list-container.disabled .pencil-box{
+ display: none;
+}
+.editable-list-container .pencil-box{
+ position: absolute;
+ right: 5px;
+ top: 5px;
+ opacity: 0;
+ -webkit-transition: all 0.3s;
+ -o-transition: all 0.3s;
+ transition: all 0.3s;
+}
+.editable-list-container:hover .pencil-box{
+ opacity: 1;
+}
+.editable-list-container.edit-mode:hover .pencil-box{
+ opacity: 0;
+}
+
+/*
+ ------ END editable-list DIRECTIVE SECTION ------ -
+*/
+
+
.instances-table{
table-layout: fixed;
}
@@ -747,6 +923,12 @@ input[type="submit"].btn.btn-mini {
*padding-bottom: 1px;
}
+button.btn.btn-xs{
+ padding: 1px 5px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
.alert-info {
background-color: #E6F1F6;
border-color: #D2D9DD;
http://git-wip-us.apache.org/repos/asf/ambari/blob/9cf27bf8/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/edit.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/edit.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/edit.html
index dbb8165..02d4f77 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/edit.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/edit.html
@@ -93,9 +93,6 @@
<div class="panel panel-default views-permissions-panel" style="">
<div class="panel-heading clearfix">
<h3 class="panel-title pull-left">Permissions</h3>
- <div class="pull-right" >
- <a ng-hide="isPermissionsEmpty" href class="permissions-edit-toggle" ng-click="editPermissionDisabled = !editPermissionDisabled" ng-show="editPermissionDisabled"> <span class="glyphicon glyphicon-pencil"></span> Edit</a>
- </div>
</div>
<div class="panel-body">
@@ -114,36 +111,14 @@
<label class="">{{permission.PermissionInfo.permission_name}}</label>
</td>
<td>
- <div class="" ng-switch="editPermissionDisabled">
- <textarea name="" id="" cols="30" rows="4" class="form-control permission-textarea-user" ng-model="permissionsEdit[permission.PermissionInfo.permission_name].USER" ng-switch-when="false"></textarea>
- <div class="well" ng-switch-when="true">
- <span ng-repeat="user in permission.USER | orderBy:identity">
- <link-to route="users.show" id="{{user}}">{{user}}</link-to>
- {{$last ? '' :', '}}
- </span>
- </div>
- </div>
+ <editable-list items-source="permissionsEdit[permission.PermissionInfo.permission_name].USER" editable="true" resource-type="User"></editable-list>
</td>
<td>
- <div class="" ng-switch="editPermissionDisabled">
- <textarea name="" id="" cols="30" rows="4" class="form-control permission-textarea-group" ng-model="permissionsEdit[permission.PermissionInfo.permission_name].GROUP" ng-switch-when="false"></textarea>
- <div class="well" ng-switch-when="true">
- <span ng-repeat="group in permission.GROUP | orderBy:identity">
- <link-to route="groups.edit" id="{{group}}" >{{group}}</link-to>
- {{$last ? '' :', '}}
- </span>
- </div>
- </div>
+ <editable-list items-source="permissionsEdit[permission.PermissionInfo.permission_name].GROUP" editable="true" resource-type="Group" ></editable-list>
</td>
</tr>
</tbody>
</table>
- <div class="form-group" ng-hide="editPermissionDisabled">
- <div class="col-sm-offset-2 col-sm-10">
- <button class="btn btn-primary pull-right left-margin permissions-save" ng-click="savePermissions()">Save</button>
- <button class="btn btn-default pull-right permissions-cancel" ng-click="cancelPermissions()">Cancel</button>
- </div>
- </div>
<div ng-show="isPermissionsEmpty">
<div class="alert alert-info">There are no permissions defined for this view.</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/9cf27bf8/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
index fe27492..6de2561 100644
--- 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
@@ -21,17 +21,14 @@
<ol class="breadcrumb pull-left">
<li class="active">{{clusterName}} Permissions</li>
</ol>
- <div class="pull-right top-margin-4">
- <a href class="btn btn-primary" ng-hide="isEditMode" ng-click="toggleEditMode()"><span class="glyphicon glyphicon-pencil"></span> Edit</a>
- </div>
</div>
<hr>
<table class="table">
<thead>
<tr>
- <th class="col-sm-2"><label>Permission</label></th>
- <th><label>Grant permission to these users</label></th>
- <th><label>Grant permission to these groups</label></th>
+ <th class="col-sm-2" width="20%"><label>Permission</label></th>
+ <th class="col-sm-5" width="40%"><label>Grant permission to these users</label></th>
+ <th class="col-sm-5" width="40%"><label>Grant permission to these groups</label></th>
</tr>
</thead>
<tbody>
@@ -39,33 +36,15 @@
<td><label class="">{{permission.PermissionInfo.permission_name}}</label></td>
<td>
<div class="" ng-switch="isEditMode">
- <textarea ng-switch-when="true" name="" id="" cols="30" rows="4" class="form-control permission-user-input" ng-model="permissionsEdit[permission.PermissionInfo.permission_name].USER"></textarea>
- <div class="well" ng-switch-default>
- <span ng-repeat="user in permission.USER | orderBy:identity">
- <link-to route="users.show" id="{{user}}" >{{user}}</link-to>
- {{$last ? '' :', '}}
- </span>
- </div>
+ <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">
- <textarea ng-switch-when="true" name="" id="" cols="30" rows="4" class="form-control permission-group-input" ng-model="permissionsEdit[permission.PermissionInfo.permission_name].GROUP | orderBy:identity"></textarea>
- <div class="well" ng-switch-default>
- <span ng-repeat="group in permission.GROUP">
- <link-to route="groups.edit" id="{{group}}">{{group}}</link-to>
- {{$last ? '' :', '}}
- </span>
- </div>
+ <editable-list items-source="permissionsEdit[permission.PermissionInfo.permission_name].GROUP" resource-type="Group" editable="true"></editable-list>
</div>
</td>
</tr>
</tbody>
</table>
- <div class="form-group" ng-show="isEditMode">
- <div class="col-sm-offset-2 col-sm-10">
- <button class="btn btn-primary pull-right permission-save left-margin" ng-click="save()">Save</button>
- <button class="btn btn-default pull-right permissions-cancel" ng-click="cancel()">Cancel</button>
- </div>
- </div>
</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/9cf27bf8/ambari-admin/src/main/resources/ui/admin-web/app/views/directives/editableList.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/directives/editableList.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/directives/editableList.html
new file mode 100644
index 0000000..5cdc148
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/directives/editableList.html
@@ -0,0 +1,44 @@
+<!--
+* 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="editable-list-container well" ng-class="{'edit-mode' : editMode, 'disabled' : !editable}" ng-click="enableEditMode()">
+ <div class="items-box">
+ <ul class="items-list">
+ <li class="item" ng-repeat="item in items | orderBy:identity"><span><a href>{{item}}</a><button ng-click="removeFromItems(item)" type="button" class="close"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button></span></li><li class="item add-item-input" ng-show="editMode">
+ <span contenteditable></span>
+ <div class="typeahead-box" ng-show="typeahead.length != 0">
+ <ul>
+ <li ng-repeat="item in typeahead" ng-click="addItem(item)" ng-class="{'selected' : $index == selectedTypeahed}">{{item}}</li>
+ </ul>
+ </div>
+ </li>
+ <li class="item add-item" ng-show="!editMode && !items.length">Add {{resourceType}}</li>
+ </ul>
+ </div>
+ <div class="actions-panel" ng-show="editMode">
+ <button class="btn btn-default btn-xs cancel" ng-click="cancel($event)">
+ <span class="glyphicon glyphicon-remove cancel"></span>
+ </button>
+ <button class="btn btn-primary btn-xs" ng-click="save($event)">
+ <span class="glyphicon glyphicon-ok"></span>
+ </button>
+ </div>
+ <div class="pencil-box">
+ <span class="glyphicon glyphicon-pencil"></span>
+ </div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/9cf27bf8/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
index d82caf6..5b90f79 100644
--- 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
@@ -40,28 +40,7 @@
<div class="form-group">
<label for="members" class="col-sm-2 control-label">{{group.ldap_group ? 'LDAP Members' : 'Local Members'}}</label>
<div class="col-sm-10">
- <div class="row" ng-hide="isMembersEditing">
- <div class="col-sm-10">
- <div class="well users">
- <span ng-repeat="member in groupMembers" >
- <link-to route='users.show' id="{{member}}">
- {{member}}
- </link-to>
- {{$last ? '' : ', '}}
- </span>
- </div>
- </div>
- <div class="col-sm-2">
- <a href ng-click="enableMembersEditing()" ng-hide="user.ldap_group"><span class="glyphicon glyphicon-pencil"></span> Edit</a>
- </div>
- </div>
- <div class="row" ng-show="isMembersEditing">
- <div class="col-sm-12">
- <textarea name="groups" id="" cols="30" rows="5" class="form-control bottom-margin usergroups" ng-model="group.editingUsers"></textarea>
- <a href class="btn btn-primary pull-right left-margin updategroups" ng-click="updateMembers()">Save</a>
- <button class="btn btn-default pull-right cancel-groups-update" ng-click="cancelUpdate()">Cancel</button>
- </div>
- </div>
+ <editable-list items-source="group.editingUsers" resource-type="User" editable="!group.ldap_group"></editable-list>
</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/9cf27bf8/ambari-admin/src/main/resources/ui/admin-web/app/views/users/show.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/show.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/users/show.html
index 88e48c9..0667200 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/show.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/users/show.html
@@ -62,27 +62,7 @@
<div class="form-group">
<label for="groups" class="col-sm-2 control-label">{{user.ldap_user ? 'LDAP Group Membership' : 'Local Group Membership'}}</label>
<div class="col-sm-10">
- <div class="row" ng-hide="isGroupEditing">
- <div class="col-sm-10">
- <div class="well">
- <span ng-repeat="group in user.groups">
- <a href="#/groups/{{group}}/edit" >{{group}}</a>
- {{$last ? '' : ', '}}
- </span>
- </div>
- </div>
- <div class="col-sm-2">
- <a href ng-click="enableGroupEditing()" ng-hide="user.ldap_user"><span class="glyphicon glyphicon-pencil"></span> Edit</a>
- </div>
- </div>
- <div class="row" ng-show="isGroupEditing">
- <div class="col-sm-12">
- <textarea name="groups" id="" cols="30" rows="5" class="form-control bottom-margin usergroups" ng-model="editingGroupsList"></textarea>
- <a href class="btn btn-primary pull-right left-margin updategroups" ng-click="updateGroups()">Save</a>
- <button class="btn btn-default pull-right cancel-groups-update" ng-click="cancelUpdate()">Cancel</button>
- </div>
-
- </div>
+ <editable-list items-source="editingGroupsList" resource-type="Group" editable="!user.ldap_user"></editable-list>
</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/9cf27bf8/ambari-admin/src/main/resources/ui/admin-web/bower.json
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/bower.json b/ambari-admin/src/main/resources/ui/admin-web/bower.json
index 0c30117..27429c2 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/bower.json
+++ b/ambari-admin/src/main/resources/ui/admin-web/bower.json
@@ -7,7 +7,8 @@
"angular-route": "~1.2.18",
"angular-bootstrap": "~0.11.0",
"restangular": "~1.4.0",
- "angular-bootstrap-toggle-switch": "~0.5.1"
+ "angular-bootstrap-toggle-switch": "~0.5.1",
+ "angular-animate": "~1.2.23"
},
"devDependencies": {}
}