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/08/07 01:50:49 UTC

[2/2] git commit: AMBARI-6763. Admin View: E2E integration. (yusaku)

AMBARI-6763. Admin View: E2E integration. (yusaku)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/3e1ad2a4
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/3e1ad2a4
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/3e1ad2a4

Branch: refs/heads/trunk
Commit: 3e1ad2a4a1abc818ce331a7c233a9fa674d50a8c
Parents: abf09ef
Author: Yusaku Sako <yu...@hortonworks.com>
Authored: Wed Aug 6 16:35:08 2014 -0700
Committer: Yusaku Sako <yu...@hortonworks.com>
Committed: Wed Aug 6 16:35:08 2014 -0700

----------------------------------------------------------------------
 .../main/resources/ui/admin-web/app/index.html  |  58 +--
 .../resources/ui/admin-web/app/scripts/app.js   |   5 +-
 .../app/scripts/controllers/LDAPModalCtrl.js    |  10 +-
 .../app/scripts/controllers/NavbarCtrl.js       |  22 +-
 .../ambariViews/CreateViewInstanceCtrl.js       |  88 ++--
 .../ambariViews/EditViewInstanceCtrl.js         | 154 +++++++
 .../controllers/ambariViews/ViewsEditCtrl.js    |  97 +++--
 .../controllers/ambariViews/ViewsListCtrl.js    |  95 +++--
 .../clusters/ClustersManageAccessCtrl.js        |  77 ++--
 .../controllers/groups/GroupsCreateCtrl.js      |   6 +-
 .../controllers/groups/GroupsEditCtrl.js        |  50 ++-
 .../controllers/groups/GroupsListCtrl.js        |  35 +-
 .../controllers/users/UsersCreateCtrl.js        |   5 +-
 .../scripts/controllers/users/UsersShowCtrl.js  |  21 +-
 .../ui/admin-web/app/scripts/routes.js          |   4 +-
 .../admin-web/app/scripts/services/Cluster.js   |  64 +++
 .../app/scripts/services/ConfirmationModal.js   |  46 ++
 .../ui/admin-web/app/scripts/services/Group.js  |  14 +-
 .../app/scripts/services/PermissionLoader.js    |  62 +++
 .../app/scripts/services/PermissionsSaver.js    | 126 ++++++
 .../ui/admin-web/app/scripts/services/View.js   |  78 +++-
 .../admin-web/app/scripts/services/uiAlert.js   |  98 +++++
 .../resources/ui/admin-web/app/styles/main.css  | 425 ++++++++++++++++++-
 .../admin-web/app/views/ambariViews/create.html | 129 ++++++
 .../admin-web/app/views/ambariViews/edit.html   |  58 ++-
 .../admin-web/app/views/ambariViews/list.html   |  19 +-
 .../app/views/ambariViews/modals/create.html    |   4 +-
 .../app/views/ambariViews/modals/edit.html      | 138 ++++++
 .../app/views/clusters/manageAccess.html        |  47 +-
 .../ui/admin-web/app/views/groups/create.html   |   8 +-
 .../ui/admin-web/app/views/groups/edit.html     |  15 +-
 .../ui/admin-web/app/views/groups/list.html     |  31 +-
 .../ui/admin-web/app/views/leftNavbar.html      |  12 +-
 .../app/views/modals/ConfirmationModal.html     |  27 ++
 .../ui/admin-web/app/views/users/create.html    |  10 +-
 .../ui/admin-web/app/views/users/list.html      |   3 +
 .../app/views/users/modals/changePassword.html  |   2 +-
 .../users/modals/deleteUserConfirmation.html    |  24 --
 .../ui/admin-web/app/views/users/show.html      |  10 +-
 .../src/main/resources/ui/admin-web/gulpfile.js |   2 +-
 40 files changed, 1850 insertions(+), 329 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/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 c4fa38c..f201d06 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
@@ -40,30 +40,36 @@
       <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
     <![endif]-->
 
-    <header class="navbar navbar-static-top navbar-inverse">
-      <div class="navbar-inner">
-        <div class="container">
-          <div class="navbar-header">
-            <a href="#/" class="navbar-brand">Ambari Admin Console</a>
-          </div>  
-          <ul class="nav navbar-nav navbar-right">
-            <li>
-              <div class="btn-group" dropdown is-open="status.isopen">
-              <button type="button" class="btn btn-default dropdown-toggle navbar-btn" ng-disabled="disabled">
-                  Admin <span class="caret"></span>
-                </button>
-                <ul class="dropdown-menu" role="menu">
-                  <li><a href="#">About</a></li>
-                  <li class="divider"></li>
-                  <li><a href="#">Sign Out</a></li>
-                </ul>
-              </div>
-            </li>
-          </ul>
-        </div>        
-      </div>
-        
-    </header>
+    <div id="top-nav">
+      <header class="navbar navbar-static-top navbar-inverse">
+        <div class="navbar-inner">
+          <div class="container">
+            <a href="#/" class="logo"><img src="/img/logo-white.png" alt="Apache Ambari" title="Apache Ambari"></a>
+            <a href="#/" class="brand" title="Apache Ambari">Ambari</a>
+            <a href="" class="brand cluster-name">Ambari Admin Console</a>
+            <!-- <div class="navbar-header">
+              <a href="#/" class="navbar-brand">Ambari Admin Console</a>
+            </div>   -->
+            <ul class="nav navbar-nav navbar-right">
+              <li>
+                <div class="btn-group" dropdown is-open="status.isopen">
+                <button type="button" class="btn btn-default dropdown-toggle navbar-btn" ng-disabled="disabled">
+                    Admin <span class="caret"></span>
+                  </button>
+                  <ul class="dropdown-menu" role="menu">
+                    <li><a href="#">About</a></li>
+                    <li class="divider"></li>
+                    <li><a href="#">Sign Out</a></li>
+                  </ul>
+                </div>
+              </li>
+            </ul>
+          </div>        
+        </div>
+      </header>
+    </div>
+      
+
     <div class="container">
       <div class="row">
         <div class="col-sm-3">
@@ -126,6 +132,10 @@
     <script src="scripts/services/View.js"></script>
     <script src="scripts/services/ldap.js"></script>
     <script src="scripts/services/Cluster.js"></script>
+    <script src="scripts/services/uiAlert.js"></script>
+    <script src="scripts/services/PermissionLoader.js"></script>
+    <script src="scripts/services/PermissionsSaver.js"></script>
+    <script src="scripts/services/ConfirmationModal.js"></script>
     <!-- endbuild -->
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/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 9fdfe8a..c7d2478 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
@@ -20,7 +20,8 @@
 angular.module('ambariAdminConsole', [
   'ngRoute',
   'ui.bootstrap',
-  'restangular'
+  'restangular',
+  'angularAlert'
 ])
 .constant('Settings',{
 	baseUrl: '/api/v1'
@@ -78,4 +79,4 @@ angular.module('ambariAdminConsole', [
     }];
     return $delegate;
   }]);
-}]);
\ No newline at end of file
+}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/LDAPModalCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/LDAPModalCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/LDAPModalCtrl.js
index 18d2f9b..3698e16 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/LDAPModalCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/LDAPModalCtrl.js
@@ -18,7 +18,7 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('LDAPModalCtrl',['$scope', 'LDAP', 'resourceType', '$modalInstance', function($scope, LDAP, resourceType, $modalInstance) {
+.controller('LDAPModalCtrl',['$scope', 'LDAP', 'resourceType', '$modalInstance', 'uiAlert', function($scope, LDAP, resourceType, $modalInstance, uiAlert) {
   $scope.resourceType = resourceType;
   $scope.isConfigured = false;
   $scope.isDataLoaded = false;
@@ -31,6 +31,9 @@ angular.module('ambariAdminConsole')
     $scope.isConfigured = data['LDAP']['configured'];
     $scope.items = data['LDAP'][resourceType];
     $scope.isDataLoaded = true;
+  }).catch(function(data) {
+    uiAlert.danger(data.data.status, data.data.message);
+    $modalInstance.dismiss();
   });
 
   $scope.sync = function() {
@@ -41,6 +44,9 @@ angular.module('ambariAdminConsole')
 
       LDAP.sync(resourceType, itemsToSync).then(function() {
         $modalInstance.close();
+      }).catch(function(data) {
+        uiAlert.danger(data.data.status, data.data.message);
+        $modalInstance.close();
       });
     }
   };
@@ -48,4 +54,4 @@ angular.module('ambariAdminConsole')
   $scope.cancel = function() {
     $modalInstance.dismiss();
   };
-}]);
\ No newline at end of file
+}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/NavbarCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/NavbarCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/NavbarCtrl.js
index b751b72..0e0c5c8 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/NavbarCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/NavbarCtrl.js
@@ -18,9 +18,21 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('NavbarCtrl',['$scope', 'Cluster', function($scope, Cluster) {
-	$scope.cluster = null;
-	Cluster.getStatus().then(function(cluster) {
-		$scope.cluster = cluster;
-	});
+.controller('NavbarCtrl',['$scope', 'Cluster', '$location', 'uiAlert', 'ROUTES', function($scope, Cluster, $location, uiAlert, ROUTES) {
+  $scope.cluster = null;
+  Cluster.getStatus().then(function(cluster) {
+    $scope.cluster = cluster;
+  }).catch(function(data) {
+  	uiAlert.danger(data.status, data.message);
+  });
+
+  // console.log($state);
+  $scope.isActive = function(path) {
+  	var route = ROUTES;
+  	angular.forEach(path.split('.'), function(routeObj) {
+  		route = route[routeObj];
+  	});
+  	var r = new RegExp( route.url.replace(/(:\w+)/, '\\w+'));
+  	return r.test($location.path());
+  };
 }]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/CreateViewInstanceCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/CreateViewInstanceCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/CreateViewInstanceCtrl.js
index fdf9211..44e2807 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/CreateViewInstanceCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/CreateViewInstanceCtrl.js
@@ -18,53 +18,57 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('CreateViewInstanceCtrl',['$scope', 'View', '$modalInstance', 'viewVersion', function($scope, View, $modalInstance, viewVersion) {
-	$scope.form = {};
+.controller('CreateViewInstanceCtrl',['$scope', 'View', 'uiAlert', '$routeParams', '$location', function($scope, View, uiAlert, $routeParams, $location) {
+  $scope.form = {};
 
-	$scope.view = viewVersion;
-	$scope.isAdvancedClosed = true;
-	$scope.instanceExists = false;
+  View.getMeta($routeParams.viewId, $routeParams.version).then(function(data) {
+    var viewVersion = data.data;
+    $scope.view = viewVersion;
 
+    $scope.instance = {
+      view_name: viewVersion.ViewVersionInfo.view_name,
+      version: viewVersion.ViewVersionInfo.version,
+      instance_name: '',
+      label: '',
+      visible: true,
+      icon_path: '',
+      icon64_path: '',
+      properties: viewVersion.ViewVersionInfo.parameters
+    };    
+  });
 
-	$scope.instance = {
-		view_name: viewVersion.ViewVersionInfo.view_name,
-		version: viewVersion.ViewVersionInfo.version,
-		instance_name: '',
-		label: '',
-		visible: true,
-		icon_path: '',
-		icon64_path: '',
-		properties: viewVersion.ViewVersionInfo.parameters
-	};
+  // $scope.view = viewVersion;
+  $scope.isAdvancedClosed = true;
+  $scope.instanceExists = false;
 
-	$scope.nameValidationPattern = /^\s*\w*\s*$/;
 
-	$scope.save = function() {
-		window.f = $scope.form.isntanceCreateForm;
-		$scope.form.isntanceCreateForm.submitted = true;
-		if($scope.form.isntanceCreateForm.$valid){
-			View.getInstance($scope.instance.view_name, $scope.instance.version, $scope.instance.instance_name)
-			.then(function(data) {
-				if (data.ViewInstanceInfo) {
-					$scope.instanceExists = true;
-				} else {
-					View.createInstance($scope.instance)
-					.then(function(data) {
-						$modalInstance.close();
-					})
-					.catch(function(data) {
-						console.log(data);
-					});
-				}
-			})
-			.catch(function() {
-				console.log('Error');
-			});
-		}
-	};
+  $scope.nameValidationPattern = /^\s*\w*\s*$/;
 
-	$scope.cancel = function() {
-		$modalInstance.dismiss();
-	};
+  $scope.save = function() {
+    $scope.form.isntanceCreateForm.submitted = true;
+    if($scope.form.isntanceCreateForm.$valid){
+      View.getInstance($scope.instance.view_name, $scope.instance.version, $scope.instance.instance_name)
+      .then(function(data) {
+        if (data.ViewInstanceInfo) {
+          $scope.instanceExists = true;
+        } else {
+          View.createInstance($scope.instance)
+          .then(function(data) {
+            $location.path('/views');
+          })
+          .catch(function(data) {
+            uiAlert.danger(data.data.status, data.data.message);
+          });
+        }
+      })
+      .catch(function(data) {
+        uiAlert.danger(data.data.status, data.data.message);
+      });
+    }
+  };
+
+  $scope.cancel = function() {
+    $modalInstance.dismiss();
+  };
 
 }]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/EditViewInstanceCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/EditViewInstanceCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/EditViewInstanceCtrl.js
new file mode 100644
index 0000000..e63fe14
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/EditViewInstanceCtrl.js
@@ -0,0 +1,154 @@
+/**
+ * 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('EditViewInstanceCtrl', ['$scope', 'View', 'uiAlert', 'PermissionLoader', 'PermissionSaver', 'instance', '$modalInstance', '$modal', function($scope, View, uiAlert, PermissionLoader, PermissionSaver, instance, $modalInstance, $modal) {
+
+  $scope.instance = instance;
+  $scope.settings = {
+    'visible': $scope.instance.ViewInstanceInfo.visible,
+    'label': $scope.instance.ViewInstanceInfo.label
+  };
+  $scope.configuration = angular.copy($scope.instance.ViewInstanceInfo.properties);
+  
+  function reloadViewPrivilegies(){
+    PermissionLoader.getViewPermissions({
+      viewName: $scope.instance.ViewInstanceInfo.view_name,
+      version: $scope.instance.ViewInstanceInfo.version,
+      instanceId: $scope.instance.ViewInstanceInfo.instance_name
+    })
+    .then(function(permissions) {
+      // Refresh data for rendering
+      $scope.permissionsEdit = permissions;
+      $scope.permissions = angular.copy(permissions);
+    })
+    .catch(function(data) {
+      uiAlert.danger(data.data.status, data.data.message);
+    });
+  }
+
+  $scope.permissions = [];
+  
+  reloadViewPrivilegies();
+
+  $scope.edit = {};
+  $scope.edit.editSettingsDisabled = true;
+  
+
+  $scope.saveSettings = function() {
+    View.updateInstance($scope.instance.ViewInstanceInfo.view_name, $scope.instance.ViewInstanceInfo.version, $scope.instance.ViewInstanceInfo.instance_name, {
+      'ViewInstanceInfo':{
+        'visible': $scope.settings.visible,
+        'label': $scope.settings.label
+      }
+    })
+    .success(function() {
+      $scope.edit.editSettingsDisabled = true;
+    })
+    .catch(function(data) {
+      uiAlert.danger(data.data.status, data.data.message);
+    });
+  };
+
+  $scope.cancelSettings = function() {
+    $scope.settings = {
+      'visible': $scope.instance.ViewInstanceInfo.visible,
+      'label': $scope.instance.ViewInstanceInfo.label
+    };
+    $scope.edit.editSettingsDisabled = true;
+  };
+
+  $scope.edit.editConfigurationDisabled = true;
+
+  $scope.saveConfiguration = function() {
+    View.updateInstance($scope.instance.ViewInstanceInfo.view_name, $scope.instance.ViewInstanceInfo.version, $scope.instance.ViewInstanceInfo.instance_name, {
+      'ViewInstanceInfo':{
+        'properties': $scope.configuration
+      }
+    })
+    .success(function() {
+      $scope.edit.editConfigurationDisabled = true;
+    })
+    .catch(function(data) {
+      uiAlert.danger(data.data.status, data.data.message);
+    });
+  };
+  $scope.cancelConfiguration = function() {
+    $scope.configuration = angular.copy($scope.instance.ViewInstanceInfo.properties);
+    $scope.edit.editConfigurationDisabled = true;
+  };
+
+  // Permissions edit
+  $scope.edit.editPermissionDisabled = true;
+  $scope.cancelPermissions = function() {
+    $scope.permissionsEdit = angular.copy($scope.permissions); // Reset textedit areaes
+    $scope.edit.editPermissionDisabled = true;
+  };
+
+  $scope.savePermissions = function() {
+    PermissionSaver.saveViewPermissions(
+      $scope.permissions,
+      $scope.permissionsEdit,
+      {
+        view_name: $scope.instance.ViewInstanceInfo.view_name,
+        version: $scope.instance.ViewInstanceInfo.version,
+        instance_name: $scope.instance.ViewInstanceInfo.instance_name
+      }
+    )
+    .then(reloadViewPrivilegies)
+    .catch(function(data) {
+      reloadViewPrivilegies();
+      uiAlert.danger(data.data.status, data.data.message);
+    });
+    $scope.edit.editPermissionDisabled = true;
+  };
+
+  $scope.removePermission = function(permissionName, principalType, principalName) {
+    var modalInstance = $modal.open({
+      templateUrl: 'views/ambariViews/modals/create.html',
+      size: 'lg',
+      controller: 'CreateViewInstanceCtrl',
+      resolve: {
+        viewVersion: function(){
+          return '';
+        }
+      }
+    });
+
+
+
+    View.deletePrivilege({
+      view_name: $scope.instance.ViewInstanceInfo.view_name,
+      version: $scope.instance.ViewInstanceInfo.version,
+      instance_name: $scope.instance.ViewInstanceInfo.instance_name,
+      permissionName: permissionName,
+      principalType: principalType,
+      principalName: principalName
+    })
+    .then(reloadViewPrivilegies)
+    .catch(function(data) {
+      reloadViewPrivilegies();
+      uiAlert.danger(data.data.status, data.data.message);
+    });
+  };
+
+  $scope.close = function() {
+    $modalInstance.close();
+  };
+}]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/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 1e8b2d7..5c988e8 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
@@ -18,27 +18,9 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('ViewsEditCtrl', ['$scope', '$routeParams' , 'View', '$http', function($scope, $routeParams, View, $http) {
-
-  /*
-    Perissions structure
-  */
-  $scope.permissions = [];
-  View.getPermissions($routeParams.viewId, $routeParams.version)
-  .then(function(permissionData) {
-    $scope.permissions = permissionData.data.ViewVersionInfo.permissions;
-    var permissionsObject = {};
-    // Fill permissions with empty arrays
-    angular.forEach(permissionData.data.ViewVersionInfo.permissions, function(permission) {
-      var permissionLabel = permission.PermissionInfo.permission_name.replace('VIEW.', '');
-      permissionsObject[permission.PermissionInfo.permission_name] = {
-        name: permission.PermissionInfo.permission_name,
-        label: permissionLabel,
-        user: [],
-        group: []
-      };
-    });
+.controller('ViewsEditCtrl', ['$scope', '$routeParams' , 'View', 'uiAlert', 'PermissionLoader', 'PermissionSaver', function($scope, $routeParams, View, uiAlert, PermissionLoader, PermissionSaver) {
 
+  function reloadViewInfo(){
     // Load instance data, after View permissions meta loaded
     View.getInstance($routeParams.viewId, $routeParams.version, $routeParams.instanceId)
     .then(function(instance) {
@@ -47,15 +29,34 @@ angular.module('ambariAdminConsole')
         'visible': $scope.instance.ViewInstanceInfo.visible,
         'label': $scope.instance.ViewInstanceInfo.label
       };
+
       $scope.configuration = angular.copy($scope.instance.ViewInstanceInfo.properties);
-      angular.forEach(instance.privileges, function(privilegie) {
-        permissionsObject[privilegie.Privileges.permission_name][privilegie.Privileges.principal_type] = privilegie.Privileges.principal_name;
-      });
+    })
+    .catch(function(data) {
+      uiAlert.danger(data.data.status, data.data.message);
     });
+  }
 
-  });
+  function reloadViewPrivilegies(){
+    PermissionLoader.getViewPermissions({
+      viewName: $routeParams.viewId,
+      version: $routeParams.version,
+      instanceId: $routeParams.instanceId
+    })
+    .then(function(permissions) {
+      // Refresh data for rendering
+      $scope.permissionsEdit = permissions;
+      $scope.permissions = angular.copy(permissions);
+    })
+    .catch(function(data) {
+      uiAlert.danger(data.data.status, data.data.message);
+    });
+  }
 
-    
+  $scope.permissions = [];
+  
+  reloadViewInfo();  
+  reloadViewPrivilegies();
 
   $scope.editSettingsDisabled = true;
   
@@ -69,6 +70,9 @@ angular.module('ambariAdminConsole')
     })
     .success(function() {
       $scope.editSettingsDisabled = true;
+    })
+    .catch(function(data) {
+      uiAlert.danger(data.data.status, data.data.message);
     });
   };
   $scope.cancelSettings = function() {
@@ -89,6 +93,9 @@ angular.module('ambariAdminConsole')
     })
     .success(function() {
       $scope.editConfigurationDisabled = true;
+    })
+    .catch(function(data) {
+      uiAlert.danger(data.data.status, data.data.message);
     });
   };
   $scope.cancelConfiguration = function() {
@@ -96,6 +103,44 @@ angular.module('ambariAdminConsole')
     $scope.editConfigurationDisabled = true;
   };
 
-  
+  // Permissions edit
+  $scope.editPermissionDisabled = true;
+  $scope.cancelPermissions = function() {
+    $scope.permissionsEdit = angular.copy($scope.permissions); // Reset textedit areaes
+    $scope.editPermissionDisabled = true;
+  };
 
+  $scope.savePermissions = function() {
+    PermissionSaver.saveViewPermissions(
+      $scope.permissions,
+      $scope.permissionsEdit,
+      {
+        view_name: $routeParams.viewId,
+        version: $routeParams.version,
+        instance_name: $routeParams.instanceId,
+      }
+    )
+    .then(reloadViewPrivilegies)
+    .catch(function(data) {
+      reloadViewPrivilegies();
+      uiAlert.danger(data.data.status, data.data.message);
+    });
+    $scope.editPermissionDisabled = true;
+  };
+
+  $scope.removePermission = function(permissionName, principalType, principalName) {
+    View.deletePrivilege({
+      view_name: $routeParams.viewId,
+      version: $routeParams.version,
+      instance_name: $routeParams.instanceId,
+      permissionName: permissionName,
+      principalType: principalType,
+      principalName: principalName
+    })
+    .then(reloadViewPrivilegies)
+    .catch(function(data) {
+      reloadViewPrivilegies();
+      uiAlert.danger(data.data.status, data.data.message);
+    });
+  };
 }]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js
index dc63954..512b0c2 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js
@@ -18,37 +18,74 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('ViewsListCtrl',['$scope', 'View', '$modal', function($scope, View, $modal) {
-	function loadViews(){
-		View.all().then(function(views) {
-			$scope.views = views;
-		});
-	}
+.controller('ViewsListCtrl',['$scope', 'View', '$modal', 'uiAlert', 'ConfirmationModal', function($scope, View, $modal, uiAlert, ConfirmationModal) {
+  function loadViews(){
+    View.all().then(function(views) {
+      $scope.views = views;
+      $scope.getFilteredViews();
+    }).catch(function(data) {
+      uiAlert.danger(data.data.status, data.data.message);
+    });
+  }
 
-	loadViews();
+  loadViews();
 
-	$scope.createInstance = function(view) {
-		var modalInstance = $modal.open({
-			templateUrl: 'views/ambariViews/modals/create.html',
-			size: 'lg',
-			controller: 'CreateViewInstanceCtrl',
-			resolve: {
-				viewVersion: function(){
-					return view.versionsList[ view.versionsList.length-1];
-				}
-			}
-		});
+  $scope.createInstance = function(view) {
+    var modalInstance = $modal.open({
+      templateUrl: 'views/ambariViews/modals/create.html',
+      size: 'lg',
+      controller: 'CreateViewInstanceCtrl',
+      resolve: {
+        viewVersion: function(){
+          return view.versionsList[ view.versionsList.length-1];
+        }
+      }
+    });
 
-		modalInstance.result.then(loadViews);
-	};
+    modalInstance.result.then(loadViews);
+  };
 
-	$scope.deleteInstance = function(instance) {
-		View.deleteInstance(instance.ViewInstanceInfo.view_name, instance.ViewInstanceInfo.version, instance.ViewInstanceInfo.instance_name)
-		.then(function() {
-			loadViews();
-		})
-		.catch(function(data) {
-			console.error(data);
-		});
-	};
+  $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)
+      .then(function() {
+        loadViews();
+      })
+      .catch(function(data) {
+        uiAlert.danger(data.data.status, data.data.message);
+      });
+    });
+  };
+
+  $scope.viewsFilter = '';
+  $scope.filteredViews = [];
+  $scope.getFilteredViews = function(views) {
+    var result = [];
+    var filter = $scope.viewsFilter.toLowerCase();
+    if(!filter){  // if no filter return all views
+      result = $scope.views;
+    } else {
+      result = $scope.views.map(function(view) {
+        if(view.view_name.toLowerCase().indexOf(filter) >= 0){
+          return view; // if filter matched with view name -- return whole view
+        } else {
+          var instances = [];
+          angular.forEach(view.instances, function(instance) {
+            if(instance.ViewInstanceInfo.label.toLowerCase().indexOf(filter) >= 0){
+              instances.push(instance);
+            }
+          });
+          if( instances.length ){ // If inside view exists instances with matched filter - show only this instances
+            var v = angular.copy(view);
+            v.instances = instances;
+            return v;
+          }
+        }
+      }).filter(function(view) {
+        return !!view; // Remove 'undefined'
+      });
+    }
+
+    $scope.filteredViews = result;
+  };
 }]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/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 edb6e52..c880052 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
@@ -18,44 +18,55 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('ClustersManageAccessCtrl', ['$scope', function($scope) {
+.controller('ClustersManageAccessCtrl', ['$scope', 'Cluster', '$routeParams', 'uiAlert', 'PermissionLoader', 'PermissionSaver', function($scope, Cluster, $routeParams, uiAlert, PermissionLoader, PermissionSaver) {
+  function reloadClusterData(){
+    PermissionLoader.getClusterPermissions({
+      clusterId: $routeParams.id
+    }).then(function(permissions) {
+      // Refresh data for rendering
+      $scope.permissionsEdit = permissions;
+      $scope.permissions = angular.copy(permissions);
+    })
+    .catch(function(data) {
+      uiAlert.danger(data.data.status, data.data.message);
+    });;
+  }
+ 
+  reloadClusterData();
   $scope.isEditMode = false;
-  $scope.permissions = {
-    read:{
-      users: ['bill', 'kat'],
-      groups: ['users', 'contractors']
-    },
-    operate:{
-      users: ['jeff', 'tom', 'john', 'mike', 'steve'],
-      groups: ['sysadmins', 'hadoopadmins']
-    }
+  $scope.permissions = {};
+  $scope.clusterName = $routeParams.id;
+  
+
+  $scope.toggleEditMode = function() {
+    $scope.isEditMode = !$scope.isEditMode;
   };
 
-  var processInput = function(obj) {
-    var result = [], item;
-    if(typeof obj === 'string'){
-      obj = obj.split(',');
-    } else if(!Array.isArray(obj)){
-      throw 'processInput:: argument must be Array or string!';
-    }
-    // Remove doubles
-    for(var i=0, max = obj.length; i < max; i++){
-      item = obj[i];
-      if(item != false && result.indexOf(item) < 0){
-        result.push(item);
-      }
-    }
-    return result;
+  $scope.cancel = function() {
+    $scope.isEditMode = false;
+    $scope.permissionsEdit = angular.copy($scope.permissions); // Reset textedit areaes
   };
 
-  $scope.toggleEditMode = function() {
-    if($scope.isEditMode){
-      $scope.permissions.read.users = processInput($scope.permissions.read.users);
-      $scope.permissions.read.groups = processInput($scope.permissions.read.groups);
+  $scope.save = function() {
+    PermissionSaver.saveClusterPermissions(
+      $scope.permissions,
+      $scope.permissionsEdit,
+      {
+        clusterId: $routeParams.id,
+      }
+    ).then(reloadClusterData)
+    .catch(function(data) {
+      uiAlert.danger(data.data.status, data.data.message);
+      reloadClusterData();
+    });
+    $scope.isEditMode = false;
+  };
 
-      $scope.permissions.operate.users = processInput($scope.permissions.operate.users);
-      $scope.permissions.operate.groups = processInput($scope.permissions.operate.groups);
-    }
-    $scope.isEditMode = !$scope.isEditMode;
+  $scope.removePermission = function(permissionName, principalType, principalName) {
+    Cluster.deletePrivilege($routeParams.id, permissionName, principalType, principalName)
+    .then(reloadClusterData)
+    .catch(function(data) {
+      uiAlert.danger(data.data.status, data.data.message);
+    });
   };
 }]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsCreateCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsCreateCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsCreateCtrl.js
index 5e6887c..d1c4542 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsCreateCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsCreateCtrl.js
@@ -18,7 +18,7 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('GroupsCreateCtrl',['$scope', 'Group', '$location', function($scope, Group, $location) {
+.controller('GroupsCreateCtrl',['$scope', 'Group', '$location', 'uiAlert', function($scope, Group, $location, uiAlert) {
   $scope.group = new Group();
 
   $scope.createGroup = function() {
@@ -26,6 +26,10 @@ angular.module('ambariAdminConsole')
     if ($scope.form.$valid){
       $scope.group.save().then(function() {
         $location.path('/groups');
+      })
+      .catch(function(data) {
+      	data = data.data;
+        uiAlert.danger(data.status, data.message);
       });
     }
   };

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/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 fe8ba1c..a386b62 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
@@ -18,42 +18,50 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('GroupsEditCtrl',['$scope', 'Group', '$routeParams', function($scope, Group, $routeParams) {
+.controller('GroupsEditCtrl',['$scope', 'Group', '$routeParams', 'uiAlert', 'ConfirmationModal', '$location', function($scope, Group, $routeParams, uiAlert, ConfirmationModal, $location) {
   $scope.editMode = false;
   $scope.group = new Group($routeParams.id);
-  $scope.group.editingUsers = "";
+  $scope.group.editingUsers = [];
+  $scope.groupMembers = [];
 
-    
-  $scope.group.getMembers();
+
+  function loadMembers(){
+    $scope.group.getMembers().then(function(members) {
+      $scope.groupMembers = members;
+    });
+  }    
+  
+  loadMembers();
   
   $scope.removeMember = function(member) {
     $scope.group.removeMember(member).finally(function() {
-      $scope.group.getMembers();
+      loadMembers();
     });
   };
 
   $scope.toggleEditMode = function() {
     $scope.editMode = !$scope.editMode;
+
     if( $scope.editMode ){
-      $scope.group.editingUsers = $scope.group.members.join(', ');
+      // $scope.group.editingUsers = $scope.group.members.join(', ');
+      $scope.group.editingUsers = $scope.groupMembers;
     } else {
-      var oldMembers = $scope.group.members;
-      $scope.group.members = [];
-      var members = $scope.group.editingUsers.split(',');
-      var member;
-      angular.forEach(members,function(member) {
-        if(member && $scope.group.members.indexOf(member) < 0){
-          $scope.group.members.push(member.trim());
-        }
+      var newMembers = $scope.group.editingUsers.toString().split(',').filter(function(item) {return item.trim();}).map(function(item) {return item.trim()});
+      $scope.group.members = newMembers;
+      $scope.group.saveMembers().then(loadMembers)
+      .catch(function(data) {
+        uiAlert.danger(data.status, data.message);
       });
-
-      if(!angular.equals(oldMembers, $scope.group.members)){
-        $scope.group.saveMembers().finally(function() {
-          $scope.group.getMembers();
-        });
-      }
     }
   };
 
+  $scope.deleteGroup = function(group) {
+    ConfirmationModal.show('Delete Group', 'Are you sure you want to delete group "'+ group.group_name +'"?').then(function() {
+      group.destroy().then(function() {
+        $location.path('/groups');
+      });
+    });
+  };
+
 
-}]);
\ No newline at end of file
+}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsListCtrl.js
index 5cb9a6d..eb6c869 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsListCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsListCtrl.js
@@ -18,23 +18,30 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('GroupsListCtrl',['$scope', 'Group', '$modal', function($scope, Group, $modal) {
-	$scope.groups = [];
+.controller('GroupsListCtrl',['$scope', 'Group', '$modal', 'ConfirmationModal', function($scope, Group, $modal, ConfirmationModal) {
+  $scope.groups = [];
 
-	Group.all().then(function(groups) {
-		$scope.groups = groups;	
-	})
-	.catch(function(data) {
-		console.error('Get groups list error');
-	});
+  $scope.typeFilterOptions = ['All', 'Local', 'LDAP'];
+  $scope.currentTypeFilter = 'All';
+  $scope.typeFilter = function(group) {
+    var tf = $scope.currentTypeFilter;
+    if (tf === 'All') {
+      return group;
+    } else if(tf === 'Local' && !group.ldap_group){
+      return group;
+    } else if(tf === 'LDAP' && group.ldap_group){
+      return group;
+    }
+  };
 
-	$scope.deleteGroup = function(group) {
-		group.destroy().then(function() {
-			$scope.groups.splice( $scope.groups.indexOf(group), 1);
-		});
-	};
+  Group.all().then(function(groups) {
+    $scope.groups = groups; 
+  })
+  .catch(function(data) {
+    console.error('Get groups list error');
+  });
 
-	$scope.syncLDAP = function() {
+  $scope.syncLDAP = function() {
     var modaInstance = $modal.open({
       templateUrl: 'views/ldapModal.html',
       controller: 'LDAPModalCtrl',

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/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
index 6765ce1..e41115a 100644
--- 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
@@ -18,7 +18,7 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('UsersCreateCtrl',['$scope', '$routeParams', 'User', '$location', function($scope, $routeParams, User, $location) {
+.controller('UsersCreateCtrl',['$scope', '$routeParams', 'User', '$location', 'uiAlert', function($scope, $routeParams, User, $location, uiAlert) {
   $scope.user = {};
 
   $scope.createUser = function() {
@@ -29,6 +29,9 @@ angular.module('ambariAdminConsole')
         'Users/password': $scope.user.password
       }).then(function() {
         $location.path('/users');
+      }).catch(function(data) {;
+        data = data.data;
+        uiAlert.danger(data.status, data.message);
       });
     }
   };

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/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 c918c29..75f7095 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
@@ -18,7 +18,7 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('UsersShowCtrl', ['$scope', '$routeParams', 'User', '$modal', '$location', function($scope, $routeParams, User, $modal, $location) {
+.controller('UsersShowCtrl', ['$scope', '$routeParams', 'User', '$modal', '$location', 'ConfirmationModal', function($scope, $routeParams, User, $modal, $location, ConfirmationModal) {
   $scope.user = {};
 
   $scope.isGroupEditing = false;
@@ -35,7 +35,7 @@ angular.module('ambariAdminConsole')
   $scope.openChangePwdDialog = function() {
     var modalInstance = $modal.open({
       templateUrl: 'views/users/modals/changePassword.html',
-      controller: function($scope) {
+      controller: ['$scope', function($scope) {
         $scope.passwordData = {
           password: ''
         };
@@ -51,7 +51,7 @@ angular.module('ambariAdminConsole')
         $scope.cancel = function() {
           modalInstance.dismiss('cancel');
         };
-      }
+      }]
     });
 
     modalInstance.result.then(function(newPassword, currentUserPassword) {
@@ -69,20 +69,7 @@ angular.module('ambariAdminConsole')
   });
 
   $scope.deleteUser = function() {
-    var modalInstance = $modal.open({
-      templateUrl: 'views/users/modals/deleteUserConfirmation.html',
-      controller: function($scope) {
-        $scope.delete = function() {
-          modalInstance.close();
-        };
-
-        $scope.cancel = function() {
-          modalInstance.dismiss('cancel');
-        };
-      }
-    });
-
-    modalInstance.result.then(function() {
+    ConfirmationModal.show('Delete User', 'Are you sure you want to delete user "'+ $scope.user.user_name +'"?').then(function() {
       User.delete($scope.user.user_name).then(function() {
         $location.path('/users');
       });

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/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 a4776a5..3acc315 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
@@ -75,9 +75,9 @@ angular.module('ambariAdminConsole')
       controller: 'ViewsEditCtrl'
     },
     create: {
-      url: '/views/new',
+      url: '/views/:viewId/versions/:version/new',
       templateUrl: 'views/ambariViews/create.html',
-      controller: 'ViewsCreateCtrl'
+      controller: 'CreateViewInstanceCtrl'
     }
   },
   clusters:{

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Cluster.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Cluster.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Cluster.js
index 828e17f..bfc983e 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Cluster.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Cluster.js
@@ -32,6 +32,70 @@ angular.module('ambariAdminConsole')
       });
 
       return deferred.promise;
+    },
+    getPermissions: function() {
+      var deferred = $q.defer();
+
+      $http({
+        method: 'GET',
+        url: Settings.baseUrl + '/permissions',
+        params: {
+          fields: 'PermissionInfo',
+          'PermissionInfo/resource_name': 'CLUSTER'
+        }
+      })
+      .success(function(data) {
+        deferred.resolve(data.items);
+      })
+      .catch(function(data) {
+        deferred.reject(data);
+      });
+
+      return deferred.promise;
+    },
+    getPrivileges: function(params) {
+      var deferred = $q.defer();
+
+      $http({
+        method: 'GET',
+        url: Settings.baseUrl + '/clusters/'+params.clusterId,
+        params : {
+          'fields': 'privileges/PrivilegeInfo'
+        }
+      })
+      .success(function(data) {
+        deferred.resolve(data.privileges);
+      })
+      .catch(function(data) {
+        deferred.reject(data);
+      });
+
+      return deferred.promise;
+    },
+    createPrivileges: function(params, data) {
+      return $http({
+        method: 'POST',
+        url: Settings.baseUrl + '/clusters/'+params.clusterId+'/privileges',
+        data: data
+      });
+    },
+    deletePrivileges: function(params, data) {
+      return $http({
+        method: 'DELETE',
+        url: Settings.baseUrl + '/clusters/'+params.clusterId+'/privileges',
+        data: data
+      });
+    },
+    deletePrivilege: function(clusterId, permissionName, principalType, principalName) {
+      return $http({
+        method: 'DELETE',
+        url: Settings.baseUrl + '/clusters/'+clusterId+'/privileges',
+        params: {
+          'PrivilegeInfo/principal_type': principalType,
+          'PrivilegeInfo/principal_name': principalName,
+          'PrivilegeInfo/permission_name': permissionName
+        }
+      });
     }
   };
 }]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/ConfirmationModal.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/ConfirmationModal.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/ConfirmationModal.js
new file mode 100644
index 0000000..a26f1df
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/ConfirmationModal.js
@@ -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.
+ */
+'use strict';
+
+angular.module('ambariAdminConsole')
+.factory('ConfirmationModal', ['$modal', '$q', function($modal, $q) {
+
+	return {
+		show: function(header, body) {
+			var deferred = $q.defer();
+
+			var modalInstance = $modal.open({
+				templateUrl: 'views/modals/ConfirmationModal.html',
+				controller: ['$scope', '$modalInstance', function($scope, $modalInstance) {
+					$scope.header = header;
+					$scope.body = body;
+
+					$scope.ok = function() {
+						$modalInstance.close();
+						deferred.resolve();
+					};
+					$scope.cancel = function() {
+						$modalInstance.dismiss();
+						deferred.reject();
+					}
+				}]
+			});
+			return deferred.promise;
+		}
+	};
+}]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/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 8127d26..5f67233 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
@@ -29,23 +29,13 @@ angular.module('ambariAdminConsole')
   }
 
   Group.prototype.save = function() {
-    var deferred = $q.defer();
-
-    $http({
+    return $http({
       method : 'POST',
       url: Settings.baseUrl + '/groups',
       data:{
         'Groups/group_name': this.group_name
       }
-    })
-    .success(function(data) {
-      deferred.resolve();
-    })
-    .error(function(data) {
-      deferred.reject(data);
     });
-
-    return deferred.promise;
   };
 
   Group.prototype.destroy = function() {
@@ -157,4 +147,4 @@ angular.module('ambariAdminConsole')
   };
 
   return Group;
-}]);
\ No newline at end of file
+}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionLoader.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionLoader.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionLoader.js
new file mode 100644
index 0000000..29138d5
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionLoader.js
@@ -0,0 +1,62 @@
+/**
+ * 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')
+.factory('PermissionLoader', ['Cluster', 'View', '$q', function(Cluster, View, $q) {
+  
+  function getPermissionsFor(resource, params){
+    var deferred = $q.defer();
+    resource.getPermissions(params).then(function(permissions) {
+      var permissionsInner = {}; // Save object into closure, until it completely fills to prevent blinkong
+      angular.forEach(permissions, function(permission) {
+        permission.GROUP = [];
+        permission.USER = [];
+        permissionsInner[permission.PermissionInfo.permission_name] = permission;
+      });
+
+      // Now we can get privilegies
+      resource.getPrivileges(params).then(function(privilegies) {
+        angular.forEach(privilegies, function(privilegie) {
+          permissionsInner[privilegie.PrivilegeInfo.permission_name][privilegie.PrivilegeInfo.principal_type].push(privilegie.PrivilegeInfo.principal_name);
+        });
+
+        // After all builded - return object
+        deferred.resolve(permissionsInner);
+      }).
+      catch(function(data) {
+        deferred.reject(data);
+      });
+
+    })
+    .catch(function(data) {
+      deferred.reject(data);
+    });
+
+    return deferred.promise;
+  }
+
+  return {
+    getClusterPermissions: function(params) {
+      return getPermissionsFor(Cluster, params);
+    },
+    getViewPermissions: function(params) {
+      return getPermissionsFor(View, params);
+    }
+  };
+}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionsSaver.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionsSaver.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionsSaver.js
new file mode 100644
index 0000000..e9aeec5
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/PermissionsSaver.js
@@ -0,0 +1,126 @@
+/**
+ * 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')
+.factory('PermissionSaver', ['Cluster', 'View', '$q', function(Cluster, View, $q) {
+  var getDifference = function(oldArr, newArr) {
+    var result = {
+      add: [],
+      del: []
+    };
+    angular.forEach(newArr, function(item) {
+      var itemIndex = oldArr.indexOf(item);
+      if(itemIndex >= 0){
+        oldArr.splice(itemIndex, 1);
+      } else {
+        result.add.push(item);
+      }
+    });
+
+    result.del = oldArr;
+
+    return result;
+  };
+  
+  function savePermissionsFor(resource, oldPermissions, newPermissions, params){
+    var deferred = $q.defer();
+
+    var addArr = [];
+    var delArr = [];
+    angular.forEach(newPermissions, function(permission) {
+      // Sanitize input
+      var users = permission.USER.toString().split(',').filter(function(item) {return item.trim();}).map(function(item) {return item.trim()});
+      var groups = permission.GROUP.toString().split(',').filter(function(item) {return item.trim();}).map(function(item) {return item.trim()});
+
+      var userObj = getDifference(angular.copy(oldPermissions[permission.PermissionInfo.permission_name].USER) , users);
+      var groupObj = getDifference(angular.copy(oldPermissions[permission.PermissionInfo.permission_name].GROUP) , groups);
+
+      // Build Add array
+      addArr = addArr.concat(userObj.add.map(function(user) {
+        return {
+          'PrivilegeInfo':{
+            'permission_name': permission.PermissionInfo.permission_name,
+            'principal_name': user,
+            'principal_type': 'USER'
+          }
+        }
+      }));
+      addArr = addArr.concat(groupObj.add.map(function(group) {
+        return {
+          'PrivilegeInfo':{
+            'permission_name': permission.PermissionInfo.permission_name,
+            'principal_name': group,
+            'principal_type': 'GROUP'
+          }
+        }
+      }));
+
+      // Build del array
+      delArr = delArr.concat(userObj.del.map(function(user) {
+        return {
+          'PrivilegeInfo':{
+            'permission_name': permission.PermissionInfo.permission_name,
+            'principal_name': user,
+            'principal_type': 'USER'
+          }
+        }
+      }));
+      delArr = delArr.concat(groupObj.del.map(function(group) {
+        return {
+          'PrivilegeInfo':{
+            'permission_name': permission.PermissionInfo.permission_name,
+            'principal_name': group,
+            'principal_type': 'GROUP'
+          }
+        }
+      }));
+    });
+
+    if(addArr.length){
+      resource.createPrivileges(params, addArr)
+      .then(function() {
+        deferred.resolve();
+      })
+      .catch(function(data) {
+        deferred.reject(data);
+      });
+    }
+
+    if(delArr.length){
+      resource.deletePrivileges(params, delArr)
+      .then(function() {
+        deferred.resolve();
+      })
+      .catch(function(data) {
+        deferred.resolve(data);
+      });
+    }
+
+    return deferred.promise;
+  }
+
+  return {
+    saveClusterPermissions: function(oldPermissions, newPermissions, params) {
+      return savePermissionsFor(Cluster, oldPermissions, newPermissions, params);
+    },
+    saveViewPermissions: function(oldPermissions, newPermissions, params) {
+      return savePermissionsFor(View, oldPermissions, newPermissions, params);
+    }
+  };
+}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/View.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/View.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/View.js
index 4eba747..2b7656a 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/View.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/View.js
@@ -86,13 +86,48 @@ angular.module('ambariAdminConsole')
     });
   };
 
-  View.getPermissions = function(viewName, version) {
-    return $http({
+  View.getPermissions = function(params) {
+    var deferred = $q.defer();
+
+    var fields = [
+      'permissions/PermissionInfo/permission_name'
+    ];
+    $http({
       method: 'GET',
-      url: Settings.baseUrl + '/views/' + viewName + '/versions/'+ version
+      url: Settings.baseUrl + '/views/' + params.viewName + '/versions/'+ params.version,
+      params: {
+        'fields': fields.join(',')
+      }
+    }).success(function(data) {
+      deferred.resolve(data.permissions);
+    })
+    .catch(function(data) {
+      deferred.reject(data);
     });
+
+    return deferred.promise;
   };
 
+  View.getPrivileges = function(params) {
+    var deferred = $q.defer();
+
+    $http({
+      method: 'GET',
+      url: Settings.baseUrl + '/views/' + params.viewName + '/versions/' + params.version + '/instances/' + params.instanceId,
+      params: {
+        fields: 'privileges/PrivilegeInfo'
+      }
+    })
+    .success(function(data) {
+      deferred.resolve(data.privileges);
+    })
+    .catch(function(data) {
+      deferred.reject(data);
+    });
+
+    return deferred.promise;
+  }
+
   View.createInstance = function(instanceInfo) {
     var deferred = $q.defer();
     var properties = {};
@@ -125,6 +160,41 @@ angular.module('ambariAdminConsole')
     return deferred.promise;
   };
 
+  View.createPrivileges = function(params, data) {
+    return $http({
+      method: 'POST',
+      url: Settings.baseUrl + '/views/' + params.view_name +'/versions/'+params.version+'/instances/'+params.instance_name+'/privileges',
+      data: data
+    });
+  };
+
+  View.deletePrivileges = function(params, data) {
+    return $http({
+      method: 'DELETE',
+      url: Settings.baseUrl + '/views/' + params.view_name +'/versions/'+params.version+'/instances/'+params.instance_name+'/privileges',
+      data: data
+    });
+  };
+
+  View.deletePrivilege = function(params) {
+    return $http({
+      method: 'DELETE',
+      url: Settings.baseUrl + '/views/' + params.view_name +'/versions/'+params.version+'/instances/'+params.instance_name+'/privileges',
+      params: {
+        'PrivilegeInfo/principal_type': params.principalType,
+        'PrivilegeInfo/principal_name': params.principalName,
+        'PrivilegeInfo/permission_name': params.permissionName
+      }
+    });
+  };
+
+  View.getMeta = function(view_name, version) {
+    return $http({
+      method: 'GET',
+      url: Settings.baseUrl + '/views/'+view_name+'/versions/'+version
+    });
+  };
+
   View.all = function() {
     var deferred = $q.defer();
     var fields = [
@@ -153,4 +223,4 @@ angular.module('ambariAdminConsole')
     return deferred.promise;
   };
   return View;
-}]);
\ No newline at end of file
+}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/uiAlert.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/uiAlert.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/uiAlert.js
new file mode 100644
index 0000000..0856ad8
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/uiAlert.js
@@ -0,0 +1,98 @@
+/**
+ * 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('angularAlert',[])
+.factory('uiAlert', [function() {
+  var alerts = [];
+  var isRunning = false;
+
+  var alertBoxGenerator = function(title, message, type) {
+    var elem = angular.element('<div/>').addClass('alert');
+    elem.css({
+      'position': 'fixed',
+      'left': '50%',
+      'z-index': '10000',
+      'opacity': '1',
+      WebkitTransition : 'all .5s ease-in-out',
+      MozTransition    : 'all .5s ease-in-out',
+      MsTransition     : 'all .5s ease-in-out',
+      OTransition      : 'all .5s ease-in-out',
+      transition       : 'all .5s ease-in-out',
+      '-webkit-transform': 'translateX(-50%)',
+      '-ms-transform': 'translateX(-50%)',
+      '-o-transform': 'translateX(-50%)',
+      'transform': 'translateX(-50%)'
+    });
+    if(!message){
+      elem.html(title);
+    } else {
+      elem.html('<strong>' + title + '</strong> ' + message);
+    }
+
+    elem.addClass('alert-' + (type ? type : 'info') );
+    elem.appendTo('body');
+
+    // return elem;
+    alerts.push(elem);
+    resetAlertsPositions();
+  };
+
+  var resetAlertsPositions = function() {
+    var top = 10, height=0;
+    for(var i = 0 ; i < alerts.length; i++){
+      alerts[i].css('top', top);
+      height = alerts[i].css('height').replace('px', '') * 1;
+      top += height + 10;
+    }
+
+    if(!isRunning && alerts.length){
+      isRunning = true;
+      setTimeout(function() {
+        alerts.shift().css('opacity', '0').one('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd', function() {
+          isRunning = false;
+          this.remove();
+          resetAlertsPositions();
+        });
+      }, 5000);
+    }
+  };
+
+  var Alert = function(title, message, type) {
+    alertBoxGenerator(title, message, type);
+  };
+
+  Alert.success = function(title, message) {
+    alertBoxGenerator(title, message, 'success');
+  };
+
+  Alert.info = function(title, message) {
+    alertBoxGenerator(title, message, 'info');
+  };
+
+  Alert.warning = function(title, message) {
+    alertBoxGenerator(title, message, 'warning');
+  };
+
+
+  Alert.danger = function(title, message) {
+    alertBoxGenerator(title, message, 'danger');
+  };
+
+  return Alert;
+}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/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 fb81166..8771ca3 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
@@ -17,6 +17,76 @@
  */
 
 
+/*
+  Style topnav menu
+*/
+#top-nav .navbar.navbar-static-top{
+  min-height: 40px;
+}
+#top-nav .navbar-inverse{
+  background: none;
+  border: none;
+}
+#top-nav .navbar.navbar-static-top .navbar-inner {
+  background-image: -moz-linear-gradient(top, #555555, #333333);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#555555), to(#333333));
+  background-image: -webkit-linear-gradient(top, #555555, #333333);
+  background-image: -o-linear-gradient(top, #555555, #333333);
+  background-image: linear-gradient(to bottom, #555555, #333333);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#555555, endColorstr=#333333);
+  -webkit-box-shadow: inset 0 0 0 rgba(0, 0, 0, 0.1), 0 1px 10px rgba(0, 0, 0, 0.1);
+  -moz-box-shadow: inset 0 0 0 rgba(0, 0, 0, 0.1), 0 1px 10px rgba(0, 0, 0, 0.1);
+  box-shadow: inset 0 0 0 rgba(0, 0, 0, 0.1), 0 1px 10px rgba(0, 0, 0, 0.1);
+  max-height: 40px;
+  height: 40px;
+}
+#top-nav .dropdown-toggle.navbar-btn{
+  margin: 4px 0 0 0;
+}
+#top-nav .navbar.navbar-static-top .logo {
+  float: left;
+  padding-top: 2px;
+}
+#top-nav .navbar.navbar-static-top .logo img {
+  height: 32px;
+}
+#top-nav .navbar.navbar-static-top .brand {
+  color: #ffffff;
+  font-size: 16px;
+  font-weight: normal;
+  line-height: 32px;
+  margin-left: 0;
+  padding: 2px 5px 0 10px;
+  text-shadow: 0 1px 0 #555555;
+  display: block;
+  float: left;
+  text-decoration: none;
+  
+}
+
+.create-view-form{
+  padding-bottom: 50px;
+}
+
+.create-view-form .description{
+  display: inline-block;
+  vertical-align: middle;
+  padding-left: 20px;
+}
+.create-view-form .view-header{
+  margin-bottom: 20px;
+}
+
+.container{
+  padding-left: 0;
+  width: 940px;
+}
+@media (min-width: 1200px) {
+  .container{
+    width: 1130px;
+  }
+}
+
 ul.nav li > a{
   cursor: pointer;
 }
@@ -51,6 +121,9 @@ ul.nav li > a{
 .padding-top-7{
   padding-top: 7px;
 }
+.padding-left-30{
+  padding-left: 30px;
+}
 .no-margin-bottom{
   margin-bottom: 0!important;
 }
@@ -80,10 +153,358 @@ table.no-border tr td{
   vertical-align: middle;
 }
 
-.group-edit .users button.close{
+.group-edit .users button.close , .remove-button{
   float: none;
   -webkit-transform: translateY(1px);
   -ms-transform: translateY(1px);
   -o-transform: translateY(1px);
   transform: translateY(1px);
-}
\ No newline at end of file
+}
+
+.cluster-manage-access-pane .well, .views-permissions-panel .well{
+  min-height: 63px;
+}
+
+.views-list-pane accordion .panel-group .panel-heading{
+  cursor: pointer;
+}
+
+
+
+.btn {
+  display: inline-block;
+  *display: inline;
+  padding: 4px 14px;
+  margin-bottom: 0;
+  *margin-left: .3em;
+  font-size: 14px;
+  line-height: 20px;
+  *line-height: 20px;
+  color: #333333;
+  text-align: center;
+  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
+  vertical-align: middle;
+  cursor: pointer;
+  background-color: #f5f5f5;
+  *background-color: #e6e6e6;
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
+  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
+  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
+  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
+  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
+  background-repeat: repeat-x;
+  border: 1px solid #bbbbbb;
+  *border: 0;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  border-color: #e6e6e6 #e6e6e6 #bfbfbf;
+  border-bottom-color: #a2a2a2;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+  filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
+  filter: progid:dximagetransform.microsoft.gradient(enabled=false);
+  *zoom: 1;
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.btn:hover,
+.btn:active,
+.btn.active,
+.btn.disabled,
+.btn[disabled] {
+  color: #333333;
+  background-color: #e6e6e6;
+  *background-color: #d9d9d9;
+}
+
+.btn:active,
+.btn.active {
+  background-color: #cccccc \9;
+}
+
+.btn:first-child {
+  *margin-left: 0;
+}
+
+.btn:hover {
+  color: #333333;
+  text-decoration: none;
+  background-color: #e6e6e6;
+  *background-color: #d9d9d9;
+  /* Buttons in IE7 don't get borders, so darken on hover */
+
+  background-position: 0 -15px;
+  -webkit-transition: background-position 0.1s linear;
+     -moz-transition: background-position 0.1s linear;
+       -o-transition: background-position 0.1s linear;
+          transition: background-position 0.1s linear;
+}
+
+.btn:focus {
+  outline: thin dotted #333;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+.btn.active,
+.btn:active {
+  background-color: #e6e6e6;
+  background-color: #d9d9d9 \9;
+  background-image: none;
+  outline: 0;
+  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.btn.disabled,
+.btn[disabled] {
+  cursor: default;
+  background-color: #e6e6e6;
+  background-image: none;
+  opacity: 0.65;
+  filter: alpha(opacity=65);
+  -webkit-box-shadow: none;
+     -moz-box-shadow: none;
+          box-shadow: none;
+}
+
+
+
+.btn-primary.active,
+.btn-warning.active,
+.btn-danger.active,
+.btn-success.active,
+.btn-info.active,
+.btn-inverse.active {
+  color: rgba(255, 255, 255, 0.75);
+}
+
+.btn {
+  border-color: #c5c5c5;
+  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);
+}
+
+.btn-primary {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #006dcc;
+  *background-color: #0044cc;
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
+  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
+  background-image: -o-linear-gradient(top, #0088cc, #0044cc);
+  background-image: linear-gradient(to bottom, #0088cc, #0044cc);
+  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
+  background-repeat: repeat-x;
+  border-color: #0044cc #0044cc #002a80;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);
+  filter: progid:dximagetransform.microsoft.gradient(enabled=false);
+}
+
+.btn-primary:hover,
+.btn-primary:active,
+.btn-primary.active,
+.btn-primary.disabled,
+.btn-primary[disabled] {
+  color: #ffffff;
+  background-color: #0044cc;
+  *background-color: #003bb3;
+}
+
+.btn-primary:active,
+.btn-primary.active {
+  background-color: #003399 \9;
+}
+
+.btn-warning {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #faa732;
+  *background-color: #f89406;
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
+  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
+  background-image: -o-linear-gradient(top, #fbb450, #f89406);
+  background-image: linear-gradient(to bottom, #fbb450, #f89406);
+  background-image: -moz-linear-gradient(top, #fbb450, #f89406);
+  background-repeat: repeat-x;
+  border-color: #f89406 #f89406 #ad6704;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:dximagetransform.microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
+  filter: progid:dximagetransform.microsoft.gradient(enabled=false);
+}
+
+.btn-warning:hover,
+.btn-warning:active,
+.btn-warning.active,
+.btn-warning.disabled,
+.btn-warning[disabled] {
+  color: #ffffff;
+  background-color: #f89406;
+  *background-color: #df8505;
+}
+
+.btn-warning:active,
+.btn-warning.active {
+  background-color: #c67605 \9;
+}
+
+.btn-danger {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #da4f49;
+  *background-color: #bd362f;
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));
+  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);
+  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);
+  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);
+  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);
+  background-repeat: repeat-x;
+  border-color: #bd362f #bd362f #802420;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);
+  filter: progid:dximagetransform.microsoft.gradient(enabled=false);
+}
+
+.btn-danger:hover,
+.btn-danger:active,
+.btn-danger.active,
+.btn-danger.disabled,
+.btn-danger[disabled] {
+  color: #ffffff;
+  background-color: #bd362f;
+  *background-color: #a9302a;
+}
+
+.btn-danger:active,
+.btn-danger.active {
+  background-color: #942a25 \9;
+}
+
+.btn-success {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #5bb75b;
+  *background-color: #51a351;
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));
+  background-image: -webkit-linear-gradient(top, #62c462, #51a351);
+  background-image: -o-linear-gradient(top, #62c462, #51a351);
+  background-image: linear-gradient(to bottom, #62c462, #51a351);
+  background-image: -moz-linear-gradient(top, #62c462, #51a351);
+  background-repeat: repeat-x;
+  border-color: #51a351 #51a351 #387038;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);
+  filter: progid:dximagetransform.microsoft.gradient(enabled=false);
+}
+
+.btn-success:hover,
+.btn-success:active,
+.btn-success.active,
+.btn-success.disabled,
+.btn-success[disabled] {
+  color: #ffffff;
+  background-color: #51a351;
+  *background-color: #499249;
+}
+
+.btn-success:active,
+.btn-success.active {
+  background-color: #408140 \9;
+}
+
+.btn-info {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #49afcd;
+  *background-color: #2f96b4;
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));
+  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);
+  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);
+  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);
+  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);
+  background-repeat: repeat-x;
+  border-color: #2f96b4 #2f96b4 #1f6377;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);
+  filter: progid:dximagetransform.microsoft.gradient(enabled=false);
+}
+
+.btn-info:hover,
+.btn-info:active,
+.btn-info.active,
+.btn-info.disabled,
+.btn-info[disabled] {
+  color: #ffffff;
+  background-color: #2f96b4;
+  *background-color: #2a85a0;
+}
+
+.btn-info:active,
+.btn-info.active {
+  background-color: #24748c \9;
+}
+
+.btn-inverse {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #363636;
+  *background-color: #222222;
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));
+  background-image: -webkit-linear-gradient(top, #444444, #222222);
+  background-image: -o-linear-gradient(top, #444444, #222222);
+  background-image: linear-gradient(to bottom, #444444, #222222);
+  background-image: -moz-linear-gradient(top, #444444, #222222);
+  background-repeat: repeat-x;
+  border-color: #222222 #222222 #000000;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);
+  filter: progid:dximagetransform.microsoft.gradient(enabled=false);
+}
+
+.btn-inverse:hover,
+.btn-inverse:active,
+.btn-inverse.active,
+.btn-inverse.disabled,
+.btn-inverse[disabled] {
+  color: #ffffff;
+  background-color: #222222;
+  *background-color: #151515;
+}
+
+.btn-inverse:active,
+.btn-inverse.active {
+  background-color: #080808 \9;
+}
+
+button.btn,
+input[type="submit"].btn {
+  *padding-top: 3px;
+  *padding-bottom: 3px;
+}
+
+button.btn::-moz-focus-inner,
+input[type="submit"].btn::-moz-focus-inner {
+  padding: 0;
+  border: 0;
+}
+
+button.btn.btn-large,
+input[type="submit"].btn.btn-large {
+  *padding-top: 7px;
+  *padding-bottom: 7px;
+}
+
+button.btn.btn-small,
+input[type="submit"].btn.btn-small {
+  *padding-top: 3px;
+  *padding-bottom: 3px;
+}
+
+button.btn.btn-mini,
+input[type="submit"].btn.btn-mini {
+  *padding-top: 1px;
+  *padding-bottom: 1px;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e1ad2a4/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/create.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/create.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/create.html
new file mode 100644
index 0000000..216018f
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/create.html
@@ -0,0 +1,129 @@
+<!--
+* 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="#/views">Views</a></li>
+  <li class="active">Create instance</li>
+</ol>
+<h2>Create View Instance</h2>
+<hr>
+<form class="form-horizontal create-view-form" role="form" name="form.isntanceCreateForm" novalidate>
+  <div class="view-header">
+    <img src="http://placehold.it/64x64" alt="" class="icon-big">
+    <img src="http://placehold.it/32x32" alt="" class="icon-small">
+    <div class="description">
+      <h3>{{view.ViewVersionInfo.view_name}}</h3>
+      <span>{{view.ViewVersionInfo.label}} | Version: {{view.ViewVersionInfo.version}}</span>
+    </div>
+  </div>
+  
+  <div class="panel panel-default">
+    <div class="panel-heading">
+      <h3 class="panel-title">Details</h3>
+    </div>
+    <div class="panel-body">
+      <div class="form-group" 
+      ng-class="{'has-error' : ( (form.isntanceCreateForm.instanceNameInput.$error.required || form.isntanceCreateForm.instanceNameInput.$error.pattern) && form.isntanceCreateForm.submitted) || instanceExists }"
+      >
+        <label for="" class="control-labe col-sm-2">Instance name</label>
+        <div class="col-sm-10">
+          <input type="text" class="form-control" name="instanceNameInput" ng-pattern="nameValidationPattern" required ng-model="instance.instance_name">
+
+          <div class="alert alert-danger no-margin-bottom top-margin" ng-show='form.isntanceCreateForm.instanceNameInput.$error.required && form.isntanceCreateForm.submitted'>
+            Field requried!
+          </div>
+          <div class="alert alert-danger no-margin-bottom top-margin" ng-show='form.isntanceCreateForm.instanceNameInput.$error.pattern && form.isntanceCreateForm.submitted'>
+            Must no contain special characters!
+          </div>
+          <div class="alert alert-danger no-margin-bottom top-margin" ng-show='instanceExists'>
+            Instance with this name already exists.
+          </div>
+        </div>
+      </div>
+      <div class="form-group"
+      ng-class="{'has-error' : ( (form.isntanceCreateForm.displayLabel.$error.required || form.isntanceCreateForm.displayLabel.$error.pattern) && form.isntanceCreateForm.submitted)}">
+        <label for="" class="control-labe col-sm-2">Display label</label>
+        <div class="col-sm-10">
+          <input type="text" class="form-control" name="displayLabel" ng-model="instance.label" required ng-pattern="nameValidationPattern">
+
+          <div class="alert alert-danger no-margin-bottom top-margin" ng-show='form.isntanceCreateForm.displayLabel.$error.required && form.isntanceCreateForm.submitted'>
+            Field requried!
+          </div>
+          <div class="alert alert-danger no-margin-bottom top-margin" ng-show='form.isntanceCreateForm.displayLabel.$error.pattern && form.isntanceCreateForm.submitted'>
+            Must no contain special characters!
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="form-group">
+        <div class="col-sm-10 col-sm-offset-2">
+          <button class="btn btn-default" ng-click="isAdvancedClosed = !isAdvancedClosed">Advanced</button>
+        </div>
+    </div>
+    <div collapse="isAdvancedClosed">
+      <div class="form-group">
+        <div class="col-sm-10 col-sm-offset-2">
+          <div class="checkbox">
+            <label>
+              <input type="checkbox" ng-model='instance.visible'> Visible
+            </label>
+          </div>
+        </div>
+      </div>
+      <div class="form-group">
+        <div class="col-sm-10 col-sm-offset-2">
+          <label for="" class="control-label col-sm-2">Icon</label>
+          <div class="col-sm-10">
+            <input type="text" class="form-control" name="iconUrl" ng-model="instance.icon_path">
+          </div>
+        </div>
+      </div>
+      <div class="form-group">
+        <div class="col-sm-10 col-sm-offset-2">
+          <label for="" class="control-label col-sm-2">Icon64</label>
+          <div class="col-sm-10">
+            <input type="text" class="form-control" name="icon64Url" ng-model="instance.icon64_path">
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+
+  <div class="panel panel-default">
+    <div class="panel-heading">
+      <h3 class="panel-title">Configuration</h3>
+    </div>
+    <div class="panel-body">
+    <div class="form-group" ng-repeat="parameter in instance.properties"
+      ng-class="{'has-error' : (form.isntanceCreateForm[parameter.name].$error.required && form.isntanceCreateForm.submitted)}" >
+      <label for="" class="col-sm-3 control-label">{{parameter.description}}</label>
+      <div class="col-sm-9">
+        <input type="text" class="form-control"  name="{{parameter.name}}" ng-required="parameter.required" ng-model="parameter.value">
+        <div class="alert alert-danger no-margin-bottom top-margin" ng-show='form.isntanceCreateForm[parameter.name].$error.required && form.isntanceCreateForm.submitted'>
+          Field requried!
+        </div>
+      </div>
+    </div>
+    </div>
+  </div>
+  
+  <div class="col-sm-12 ">
+    <button class="btn btn-primary pull-right left-margin" ng-click="save()" type="submit">Save</button>
+    <a href="#/views/" class="btn btn-default pull-right">Cancel</a>
+  </div>
+    
+</form>
\ No newline at end of file