You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by al...@apache.org on 2015/12/28 20:18:03 UTC

[2/4] ambari git commit: AMBARI-14510. Ambari Admin: fix 'clear filters' link display condition in Versions table and apply it to other tables. (alexantonenko)

AMBARI-14510. Ambari Admin: fix 'clear filters' link display condition in Versions table and apply it to other tables. (alexantonenko)


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

Branch: refs/heads/trunk
Commit: 4a58cd46fdfadd5deb5038db9849dd89cc289b80
Parents: 2365392
Author: Alex Antonenko <hi...@gmail.com>
Authored: Mon Dec 28 20:47:29 2015 +0200
Committer: Alex Antonenko <hi...@gmail.com>
Committed: Mon Dec 28 21:17:57 2015 +0200

----------------------------------------------------------------------
 .../controllers/clusters/UserAccessListCtrl.js  |  24 ++
 .../controllers/groups/GroupsListCtrl.js        |  22 ++
 .../stackVersions/StackVersionsListCtrl.js      |   5 +
 .../scripts/controllers/users/UsersListCtrl.js  |  27 ++-
 .../resources/ui/admin-web/app/styles/main.css  |   4 +-
 .../app/views/clusters/userAccessList.html      |   6 +-
 .../ui/admin-web/app/views/groups/list.html     |   6 +-
 .../admin-web/app/views/stackVersions/list.html |   4 +-
 .../ui/admin-web/app/views/users/list.html      |   8 +-
 .../clusters/UserAccessListCtrl_test.js         | 223 +++++++++++++++++++
 .../controllers/groups/GroupsListCtrl_test.js   | 129 +++++++++++
 .../stackVersions/StackversionsListCtrl_test.js | 119 +++++++++-
 .../controllers/users/UsersListCtrl_test.js     | 223 +++++++++++++++++++
 13 files changed, 786 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/4a58cd46/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/UserAccessListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/UserAccessListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/UserAccessListCtrl.js
index f15607b..1da4aff 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/UserAccessListCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/UserAccessListCtrl.js
@@ -29,6 +29,12 @@ function($scope, $location, Cluster, $modal, $rootScope, $routeParams, Permissio
   $scope.maxVisiblePages = 20;
   $scope.roles = [];
   $scope.clusterId = $routeParams.id;
+  $scope.tableInfo = {
+    total: 0,
+    showed: 0,
+    filtered: 0
+  };
+  $scope.isNotEmptyFilter = true;
 
   $scope.pageChanged = function() {
     $scope.loadUsers();
@@ -54,6 +60,8 @@ function($scope, $location, Cluster, $modal, $rootScope, $routeParams, Permissio
         user.PrivilegeInfo.url = type == 'user'? (type + 's/' + name) : (type + 's/' + name + '/edit');
         return user.PrivilegeInfo;
       });
+      $scope.tableInfo.total = data.itemTotal;
+      $scope.tableInfo.showed = data.items.length;
       $scope.loadRoles();
     });
   };
@@ -120,9 +128,25 @@ function($scope, $location, Cluster, $modal, $rootScope, $routeParams, Permissio
   ];
   $scope.currentTypeFilter = $scope.typeFilterOptions[0];
 
+  $scope.clearFilters = function () {
+    $scope.currentNameFilter = '';
+    $scope.currentTypeFilter = $scope.typeFilterOptions[0];
+    $scope.currentRoleFilter = $scope.roleFilterOptions[0];
+    $scope.resetPagination();
+  };
 
   $scope.loadUsers();
 
+  $scope.$watch(
+    function (scope) {
+      return Boolean(scope.currentNameFilter || (scope.currentTypeFilter && scope.currentTypeFilter.value)
+        || (scope.currentRoleFilter && scope.currentRoleFilter.value));
+    },
+    function (newValue, oldValue, scope) {
+      scope.isNotEmptyFilter = newValue;
+    }
+  );
+
   $rootScope.$watch(function(scope) {
     return scope.LDAPSynced;
   }, function(LDAPSynced) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/4a58cd46/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 df63b8c..330d3c2 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
@@ -27,6 +27,11 @@ angular.module('ambariAdminConsole')
   $scope.totalGroups = 1;
   $scope.currentNameFilter = '';
   $scope.maxVisiblePages=20;
+  $scope.tableInfo = {
+    total: 0,
+    showed: 0
+  };
+  $scope.isNotEmptyFilter = true;
 
   $scope.pageChanged = function() {
     loadGroups();
@@ -49,6 +54,8 @@ angular.module('ambariAdminConsole')
     }).then(function(groups) {
       $scope.totalGroups = groups.itemTotal;
       $scope.groups = groups;
+      $scope.tableInfo.total = groups.itemTotal;
+      $scope.tableInfo.showed = groups.length;
     })
     .catch(function(data) {
       console.error($t('groups.alerts.getGroupsListError'));
@@ -61,9 +68,24 @@ angular.module('ambariAdminConsole')
     {label: $t('common.ldap'), value:true}
   ];
   $scope.currentTypeFilter = $scope.typeFilterOptions[0];
+
+  $scope.clearFilters = function () {
+    $scope.currentNameFilter = '';
+    $scope.currentTypeFilter = $scope.typeFilterOptions[0];
+    $scope.resetPagination();
+  };
   
   loadGroups();
 
+  $scope.$watch(
+    function (scope) {
+      return Boolean(scope.currentNameFilter || (scope.currentTypeFilter && scope.currentTypeFilter.value !== '*'));
+    },
+    function (newValue, oldValue, scope) {
+      scope.isNotEmptyFilter = newValue;
+    }
+  );
+
   $rootScope.$watch(function(scope) {
     return scope.LDAPSynced;
   }, function(LDAPSynced) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/4a58cd46/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsListCtrl.js
index e3178df..583468c 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsListCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsListCtrl.js
@@ -28,6 +28,7 @@ angular.module('ambariAdminConsole')
       current: null
     }
   };
+  $scope.isNotEmptyFilter = true;
 
   $scope.pagination = {
     totalRepos: 10,
@@ -125,4 +126,8 @@ angular.module('ambariAdminConsole')
   };
 
   $scope.loadAllData();
+
+  $scope.$watch('filter', function (filter) {
+    $scope.isNotEmptyFilter = Boolean(filter.version || (filter.cluster.current && filter.cluster.current.value));
+  }, true);
 }]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/4a58cd46/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersListCtrl.js
index bde9297..dfbd008 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersListCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersListCtrl.js
@@ -26,6 +26,11 @@ angular.module('ambariAdminConsole')
   $scope.totalUsers = 1;
   $scope.currentNameFilter = '';
   $scope.maxVisiblePages=20;
+  $scope.tableInfo = {
+    total: 0,
+    showed: 0
+  };
+  $scope.isNotEmptyFilter = true;
 
   $scope.pageChanged = function() {
     $scope.loadUsers();
@@ -45,6 +50,8 @@ angular.module('ambariAdminConsole')
     }).then(function(data) {
       $scope.totalUsers = data.data.itemTotal;
       $scope.users = data.data.items.map(User.makeUser);
+      $scope.tableInfo.showed = data.data.items.length;
+      $scope.tableInfo.total = data.data.itemTotal;
     });
   };
 
@@ -53,12 +60,12 @@ angular.module('ambariAdminConsole')
     $scope.loadUsers();
   };
 
-  $scope.actvieFilterOptions = [
+  $scope.activeFilterOptions = [
     {label: $t('common.all'), value: '*'},
     {label: $t('users.active'), value: true},
     {label: $t('users.inactive'), value:false}
   ];
-  $scope.currentActiveFilter = $scope.actvieFilterOptions[0];
+  $scope.currentActiveFilter = $scope.activeFilterOptions[0];
 
   $scope.typeFilterOptions = [{ label: $t('common.all'), value: '*'}]
     .concat(Object.keys(UserConstants.TYPES).map(function(key) {
@@ -77,9 +84,25 @@ angular.module('ambariAdminConsole')
     $scope.loadUsers();
   };
 
+  $scope.clearFilters = function () {
+    $scope.currentNameFilter = '';
+    $scope.currentTypeFilter = $scope.typeFilterOptions[0];
+    $scope.currentActiveFilter = $scope.activeFilterOptions[0];
+    $scope.resetPagination();
+  };
 
   $scope.loadUsers();
 
+  $scope.$watch(
+    function (scope) {
+      return Boolean(scope.currentNameFilter || (scope.currentActiveFilter && scope.currentActiveFilter.value !== '*')
+        || (scope.currentTypeFilter && scope.currentTypeFilter.value !== '*'));
+    },
+    function (newValue, oldValue, scope) {
+      scope.isNotEmptyFilter = newValue;
+    }
+  );
+
   $rootScope.$watch(function(scope) {
     return scope.LDAPSynced;
   }, function(LDAPSynced) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/4a58cd46/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 602c56c..e380706 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
@@ -1259,13 +1259,13 @@ accordion .panel-group .panel{
   width: 30%
 }
 
-#stack-versions .table-bar {
+.table-bar {
   padding-top: 4px;
   border: 1px solid #E4E4E4;
   color: #7B7B7B;
 }
 
-#stack-versions .table-bar .filtered-info {
+.table-bar .filtered-info {
   margin-top: 8px;
 }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/4a58cd46/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/userAccessList.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/userAccessList.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/userAccessList.html
index 6ef6041..969f479 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/userAccessList.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/userAccessList.html
@@ -75,7 +75,11 @@
   <div class="alert alert-info col-sm-12" ng-show="!users.length">
     No users to display.
   </div>
-  <div class="col-sm-12">
+  <div class="col-sm-12 table-bar">
+    <div class="pull-left filtered-info">
+      <span>{{tableInfo.showed}} of {{tableInfo.total}} users showing</span>
+      <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">clear filters</a></span>
+    </div>
     <div class="pull-right left-margin">
       <pagination class="paginator" total-items="totalUsers" max-size="maxVisiblePages" items-per-page="usersPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
     </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/4a58cd46/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/list.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/list.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/list.html
index ab268d3..d0df0fa 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/list.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/list.html
@@ -61,7 +61,11 @@
   <div class="alert alert-info col-sm-12" ng-show="!groups.length">
     No groups to display.
   </div>
-  <div class="col-sm-12">
+  <div class="col-sm-12 table-bar">
+    <div class="pull-left filtered-info">
+      <span>{{tableInfo.showed}} of {{tableInfo.total}} groups showing</span>
+      <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">clear filters</a></span>
+    </div>
     <div class="pull-right left-margin">
       <pagination class="paginator" total-items="totalGroups" max-size="maxVisiblePages" items-per-page="groupsPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
     </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/4a58cd46/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/list.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/list.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/list.html
index 1fa5aed..ed014d8 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/list.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/list.html
@@ -90,8 +90,8 @@
   </div>
   <div class="col-sm-12 table-bar">
     <div class="pull-left filtered-info">
-      <span>{{tableInfo.showed}} of {{tableInfo.total}} versions showing - </span>
-      <a href ng-click="clearFilters()">clear filters</a>
+      <span>{{tableInfo.showed}} of {{tableInfo.total}} versions showing</span>
+      <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">clear filters</a></span>
     </div>
     <div class="pull-right left-margin">
       <pagination class="paginator"

http://git-wip-us.apache.org/repos/asf/ambari/blob/4a58cd46/ambari-admin/src/main/resources/ui/admin-web/app/views/users/list.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/list.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/users/list.html
index 3305306..3885978 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/list.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/users/list.html
@@ -56,7 +56,7 @@
           <label for="">Status</label>
           <select class="form-control statusfilter" 
             ng-model="currentActiveFilter"
-            ng-options="item.label for item in actvieFilterOptions"
+            ng-options="item.label for item in activeFilterOptions"
             ng-change="resetPagination()">
           </select>
         </th>
@@ -78,7 +78,11 @@
   <div class="alert alert-info col-sm-12" ng-show="!users.length">
     No users to display.
   </div>
-  <div class="col-sm-12">
+  <div class="col-sm-12 table-bar">
+    <div class="pull-left filtered-info">
+      <span>{{tableInfo.showed}} of {{tableInfo.total}} users showing</span>
+      <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">clear filters</a></span>
+    </div>
     <div class="pull-right left-margin">
       <pagination class="paginator" total-items="totalUsers" max-size="maxVisiblePages" items-per-page="usersPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
     </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/4a58cd46/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/clusters/UserAccessListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/clusters/UserAccessListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/clusters/UserAccessListCtrl_test.js
new file mode 100644
index 0000000..6f28aa5
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/clusters/UserAccessListCtrl_test.js
@@ -0,0 +1,223 @@
+/**
+ * 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.
+ */
+
+describe('#Cluster', function () {
+
+  describe('UserAccessListCtrl', function() {
+
+    var scope, ctrl, $t, $httpBackend;
+
+    beforeEach(module('ambariAdminConsole', function () {}));
+
+    beforeEach(inject(function($rootScope, $controller, _$translate_, _$httpBackend_) {
+      scope = $rootScope.$new();
+      $t = _$translate_.instant;
+      $httpBackend = _$httpBackend_;
+      ctrl = $controller('UserAccessListCtrl', {
+        $scope: scope
+      });
+    }));
+
+    describe('#clearFilters()', function () {
+
+      it('should clear filters and reset pagination', function () {
+        scope.currentPage = 2;
+        scope.currentNameFilter = 'a';
+        scope.currentRoleFilter = {
+          label: $t('users.roles.clusterUser'),
+          value: 'CLUSTER.USER'
+        };
+        scope.currentTypeFilter = {
+          label: $t('common.group'),
+          value: 'GROUP'
+        };
+        scope.clearFilters();
+        expect(scope.currentNameFilter).toEqual('');
+        expect(scope.currentRoleFilter).toEqual({
+          label: $t('common.all'),
+          value: ''
+        });
+        expect(scope.currentTypeFilter).toEqual({
+          label: $t('common.all'),
+          value: ''
+        });
+        expect(scope.currentPage).toEqual(1);
+      });
+
+    });
+
+    describe('#isNotEmptyFilter', function () {
+
+      var cases = [
+        {
+          currentNameFilter: '',
+          currentTypeFilter: null,
+          currentRoleFilter: null,
+          isNotEmptyFilter: false,
+          title: 'no filters'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: ''
+          },
+          currentRoleFilter: {
+            value: ''
+          },
+          isNotEmptyFilter: false,
+          title: 'empty filters'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: ''
+          },
+          currentRoleFilter: {
+            value: ''
+          },
+          isNotEmptyFilter: true,
+          title: 'name filter'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: ''
+          },
+          currentRoleFilter: {
+            value: ''
+          },
+          isNotEmptyFilter: true,
+          title: 'name filter with "0" as string'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: 'GROUP'
+          },
+          currentRoleFilter: {
+            value: ''
+          },
+          isNotEmptyFilter: true,
+          title: 'type filter'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: ''
+          },
+          currentRoleFilter: {
+            value: 'CLUSTER.USER'
+          },
+          isNotEmptyFilter: true,
+          title: 'role filter'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: 'GROUP'
+          },
+          currentRoleFilter: {
+            value: ''
+          },
+          isNotEmptyFilter: true,
+          title: 'name and type filters'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: ''
+          },
+          currentRoleFilter: {
+            value: 'CLUSTER.USER'
+          },
+          isNotEmptyFilter: true,
+          title: 'name and role filters'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: 'GROUP'
+          },
+          currentRoleFilter: {
+            value: ''
+          },
+          isNotEmptyFilter: true,
+          title: 'name and type filters with "0" as string'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: ''
+          },
+          currentRoleFilter: {
+            value: 'CLUSTER.USER'
+          },
+          isNotEmptyFilter: true,
+          title: 'name and role filters with "0" as string'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: 'GROUP'
+          },
+          currentRoleFilter: {
+            value: 'CLUSTER.USER'
+          },
+          isNotEmptyFilter: true,
+          title: 'type and role filters'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: 'CLUSTER.USER'
+          },
+          currentRoleFilter: {
+            value: 'GROUP'
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: 'CLUSTER.USER'
+          },
+          currentRoleFilter: {
+            value: 'GROUP'
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters with "0" as string'
+        }
+      ];
+
+      cases.forEach(function (item) {
+        it(item.title, function () {
+          $httpBackend.expectGET(/\/api\/v1\/clusters\/\w+\/privileges/).respond(200);
+          scope.currentNameFilter = item.currentNameFilter;
+          scope.currentRoleFilter = item.currentRoleFilter;
+          scope.currentTypeFilter = item.currentTypeFilter;
+          scope.$digest();
+          expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
+        });
+      });
+
+    });
+
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/4a58cd46/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/groups/GroupsListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/groups/GroupsListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/groups/GroupsListCtrl_test.js
new file mode 100644
index 0000000..8ed228b
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/groups/GroupsListCtrl_test.js
@@ -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.
+ */
+
+describe('#Cluster', function () {
+
+  describe('GroupsListCtrl', function() {
+
+    var scope, ctrl, $t, $httpBackend;
+
+    beforeEach(module('ambariAdminConsole', function () {}));
+
+    beforeEach(inject(function($rootScope, $controller, _$translate_, _$httpBackend_) {
+      scope = $rootScope.$new();
+      $t = _$translate_.instant;
+      $httpBackend = _$httpBackend_;
+      ctrl = $controller('GroupsListCtrl', {
+        $scope: scope
+      });
+    }));
+
+    describe('#clearFilters()', function () {
+
+      it('should clear filters and reset pagination', function () {
+        scope.currentPage = 2;
+        scope.currentNameFilter = 'a';
+        scope.currentTypeFilter = {
+          label: $t('common.local'),
+          value: false
+        };
+        scope.clearFilters();
+        expect(scope.currentNameFilter).toEqual('');
+        expect(scope.currentTypeFilter).toEqual({
+          label: $t('common.all'),
+          value: '*'
+        });
+        expect(scope.currentPage).toEqual(1);
+      });
+
+    });
+
+    describe('#isNotEmptyFilter', function () {
+
+      var cases = [
+        {
+          currentNameFilter: '',
+          currentTypeFilter: null,
+          isNotEmptyFilter: false,
+          title: 'no filters'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: false,
+          title: 'empty filters'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name filter'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name filter with "0" as string'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'type filter'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'both filters'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'both filters with "0" as string'
+        }
+      ];
+
+      cases.forEach(function (item) {
+        it(item.title, function () {
+          $httpBackend.expectGET(/\/api\/v1\/groups/).respond(200);
+          scope.currentNameFilter = item.currentNameFilter;
+          scope.currentTypeFilter = item.currentTypeFilter;
+          scope.$digest();
+          expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
+        });
+      });
+
+    });
+
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/4a58cd46/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/stackVersions/StackversionsListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/stackVersions/StackversionsListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/stackVersions/StackversionsListCtrl_test.js
index f7a778a..1e47c20 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/stackVersions/StackversionsListCtrl_test.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/stackVersions/StackversionsListCtrl_test.js
@@ -18,18 +18,19 @@
 
 describe('#Cluster', function () {
   describe('StackVersionsListCtrl', function() {
-    var scope, ctrl;
+    var scope, ctrl, $httpBackend;
 
     beforeEach(module('ambariAdminConsole', function($provide) {
 
     }));
 
-    beforeEach(inject(function($rootScope, $controller) {
+    beforeEach(inject(function($rootScope, $controller, _$httpBackend_) {
       scope = $rootScope.$new();
       ctrl = $controller('StackVersionsListCtrl', {$scope: scope});
+      $httpBackend = _$httpBackend_;
     }));
 
-    describe('fetchRepos()', function () {
+    describe('#fetchRepos()', function () {
 
       it('saves list of stacks', function() {
         scope.fetchRepos().then(function() {
@@ -39,7 +40,7 @@ describe('#Cluster', function () {
 
     });
 
-    describe('fillClusters()', function () {
+    describe('#fillClusters()', function () {
 
       var clusters = [
           {
@@ -81,5 +82,115 @@ describe('#Cluster', function () {
 
     });
 
+    describe('#isNotEmptyFilter', function () {
+
+      var cases = [
+        {
+          filter: {
+            version: '',
+            cluster: {
+              current: null
+            }
+          },
+          isNotEmptyFilter: false,
+          title: 'no filters'
+        },
+        {
+          filter: {
+            version: '',
+            cluster: {
+              current: {
+                value: ''
+              }
+            }
+          },
+          isNotEmptyFilter: false,
+          title: 'empty filters'
+        },
+        {
+          filter: {
+            version: 'a',
+            cluster: {
+              current: {
+                value: ''
+              }
+            }
+          },
+          isNotEmptyFilter: true,
+          title: 'version filter'
+        },
+        {
+          filter: {
+            version: '0',
+            cluster: {
+              current: {
+                value: ''
+              }
+            }
+          },
+          isNotEmptyFilter: true,
+          title: 'version filter with "0" as string'
+        },
+        {
+          filter: {
+            version: '',
+            cluster: {
+              current: {
+                value: 'a'
+              }
+            }
+          },
+          isNotEmptyFilter: true,
+          title: 'cluster filter'
+        },
+        {
+          filter: {
+            version: '',
+            cluster: {
+              current: {
+                value: '0'
+              }
+            }
+          },
+          isNotEmptyFilter: true,
+          title: 'cluster filter with "0" as string'
+        },
+        {
+          filter: {
+            version: 'a',
+            cluster: {
+              current: {
+                value: 'a'
+              }
+            }
+          },
+          isNotEmptyFilter: true,
+          title: 'both filters'
+        },
+        {
+          filter: {
+            version: '0',
+            cluster: {
+              current: {
+                value: '0'
+              }
+            }
+          },
+          isNotEmptyFilter: true,
+          title: 'both filters with "0" as string'
+        }
+      ];
+
+      cases.forEach(function (item) {
+        it(item.title, function () {
+          $httpBackend.expectGET(/\/api\/v1\/clusters\?_=\d+/).respond(200);
+          scope.filter = item.filter;
+          scope.$digest();
+          expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
+        });
+      });
+
+    });
+
   });
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/4a58cd46/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/users/UsersListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/users/UsersListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/users/UsersListCtrl_test.js
new file mode 100644
index 0000000..4b3b101
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/users/UsersListCtrl_test.js
@@ -0,0 +1,223 @@
+/**
+ * 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.
+ */
+
+describe('#Cluster', function () {
+
+  describe('UsersListCtrl', function() {
+
+    var scope, ctrl, $t, $httpBackend;
+
+    beforeEach(module('ambariAdminConsole', function () {}));
+
+    beforeEach(inject(function($rootScope, $controller, _$translate_, _$httpBackend_) {
+      scope = $rootScope.$new();
+      $t = _$translate_.instant;
+      $httpBackend = _$httpBackend_;
+      ctrl = $controller('UsersListCtrl', {
+        $scope: scope
+      });
+    }));
+
+    describe('#clearFilters()', function () {
+
+      it('should clear filters and reset pagination', function () {
+        scope.currentPage = 2;
+        scope.currentNameFilter = 'a';
+        scope.currentActiveFilter = {
+          label: $t('common.local'),
+          value: false
+        };
+        scope.currentTypeFilter = {
+          label: $t('common.local'),
+          value: 'LOCAL'
+        };
+        scope.clearFilters();
+        expect(scope.currentNameFilter).toEqual('');
+        expect(scope.currentActiveFilter).toEqual({
+          label: $t('common.all'),
+          value: '*'
+        });
+        expect(scope.currentTypeFilter).toEqual({
+          label: $t('common.all'),
+          value: '*'
+        });
+        expect(scope.currentPage).toEqual(1);
+      });
+
+    });
+
+    describe('#isNotEmptyFilter', function () {
+
+      var cases = [
+        {
+          currentNameFilter: '',
+          currentTypeFilter: null,
+          currentActiveFilter: null,
+          isNotEmptyFilter: false,
+          title: 'no filters'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: false,
+          title: 'empty filters'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name filter'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name filter with "0" as string'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'type filter'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'activity filter'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name and type filters'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'name and activity filters'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name and type filters with "0" as string'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'name and activity filters with "0" as string'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'type and activity filters'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: false
+          },
+          currentActiveFilter: {
+            value: 'LOCAL'
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: false
+          },
+          currentActiveFilter: {
+            value: 'LOCAL'
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters with "0" as string'
+        }
+      ];
+
+      cases.forEach(function (item) {
+        it(item.title, function () {
+          $httpBackend.expectGET(/\/api\/v1\/users/).respond(200);
+          scope.currentNameFilter = item.currentNameFilter;
+          scope.currentActiveFilter = item.currentActiveFilter;
+          scope.currentTypeFilter = item.currentTypeFilter;
+          scope.$digest();
+          expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
+        });
+      });
+
+    });
+
+  });
+
+});