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:02 UTC

[1/4] ambari git commit: AMBARI-14476. View display name overlaps with version if name is long and does not contain spaces (alexantonenko)

Repository: ambari
Updated Branches:
  refs/heads/trunk f2b1a89ac -> 7d6caf6cd


AMBARI-14476. View display name overlaps with version if name is long and does not contain spaces (alexantonenko)


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

Branch: refs/heads/trunk
Commit: 7d6caf6cdbfaefec8c992647a56e64e3fab3dd45
Parents: c763570
Author: Alex Antonenko <hi...@gmail.com>
Authored: Mon Dec 28 21:05:27 2015 +0200
Committer: Alex Antonenko <hi...@gmail.com>
Committed: Mon Dec 28 21:17:57 2015 +0200

----------------------------------------------------------------------
 .../src/main/resources/ui/admin-web/app/styles/main.css         | 5 ++++-
 .../resources/ui/admin-web/app/views/ambariViews/listTable.html | 4 ++--
 2 files changed, 6 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/7d6caf6c/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 e380706..895a28f 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
@@ -204,6 +204,9 @@
  .instances-table{
   table-layout: fixed;
  }
+ .instance-link{
+  word-wrap:break-word;
+ }
  .description-column{
   text-overflow: ellipsis;
   overflow: hidden;
@@ -1348,4 +1351,4 @@ accordion .panel-group .panel{
 thead.view-permission-header > tr > th {
   border-top: 0px;
   padding-top: 40px;
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d6caf6c/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/listTable.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/listTable.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/listTable.html
index 05cb1d5..d922f13 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/listTable.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/listTable.html
@@ -67,8 +67,8 @@
       <table class="table instances-table">
         <tbody>
           <tr ng-repeat="instance in view.instances">
-            <td class="col-sm-3"></td>
-            <td class="col-sm-3">
+            <td class="col-sm-1"></td>
+            <td class="col-sm-5">
               <a href="#/views/{{view.view_name}}/versions/{{instance.ViewInstanceInfo.version}}/instances/{{instance.ViewInstanceInfo.instance_name}}/edit" class="instance-link">{{instance.label}}</a>
             </td>
             <td class="col-sm-5">{{instance.ViewInstanceInfo.version}}</td>


[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)

Posted by al...@apache.org.
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);
+        });
+      });
+
+    });
+
+  });
+
+});


[3/4] ambari git commit: AMBARI-14443. In the Move Master Wizard, manual commands text scroll outside the frame when the message is long (alexantonenko)

Posted by al...@apache.org.
AMBARI-14443. In the Move Master Wizard, manual commands text scroll outside the frame when the message is long (alexantonenko)


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

Branch: refs/heads/trunk
Commit: c763570f4cbe1a41f00cfec77d599a1fdcdbb778
Parents: 4a58cd4
Author: Alex Antonenko <hi...@gmail.com>
Authored: Mon Dec 28 21:04:53 2015 +0200
Committer: Alex Antonenko <hi...@gmail.com>
Committed: Mon Dec 28 21:17:57 2015 +0200

----------------------------------------------------------------------
 ambari-web/app/styles/application.less | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/c763570f/ambari-web/app/styles/application.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less
index d80278c..381459a 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -4930,7 +4930,7 @@ i.icon-asterisks {
   font-family: Courier;
   font-size: 12px;
   padding: 4px;
-  white-space: nowrap;
+  white-space: normal;
 }
 
 @installer-container-width: 1236px;


[4/4] ambari git commit: AMBARI-14509. Handle the case when UI call to 'Install Packages' action times out (alexantonenko)

Posted by al...@apache.org.
AMBARI-14509. Handle the case when UI call to 'Install Packages' action times out
 (alexantonenko)


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

Branch: refs/heads/trunk
Commit: 23653924d6016ce6b3b52d5ea84d53298721ad6f
Parents: f2b1a89
Author: Alex Antonenko <hi...@gmail.com>
Authored: Mon Dec 28 20:42:33 2015 +0200
Committer: Alex Antonenko <hi...@gmail.com>
Committed: Mon Dec 28 21:17:57 2015 +0200

----------------------------------------------------------------------
 .../main/admin/stack_and_upgrade_controller.js        | 14 ++++++++++++++
 ambari-web/app/messages.js                            |  1 +
 .../main/admin/stack_upgrade/upgrade_version_box.hbs  |  3 +++
 .../admin/stack_upgrade/upgrade_version_box_view.js   |  8 +++++++-
 4 files changed, 25 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/23653924/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js b/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js
index 748cbc8..06ddf24 100644
--- a/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js
+++ b/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js
@@ -140,6 +140,10 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
    */
   requestInProgress: false,
   /**
+   * @type {number} repo id, request for which is currently in progress
+   */
+  requestInProgressRepoId: null,
+  /**
    * @type {boolean} true while no updated upgrade info is loaded after retry
    */
   isRetryPending: false,
@@ -1140,6 +1144,8 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
    */
   installRepoVersion: function (repo) {
     this.set('requestInProgress', true);
+    this.set('requestInProgressRepoId', repo.get('id'));
+
     var data = {
       ClusterStackVersions: {
         stack: repo.get('stackVersionType'),
@@ -1156,6 +1162,7 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
       error: 'installRepoVersionError',
       callback: function() {
         this.sender.set('requestInProgress', false);
+        this.sender.set('requestInProgressRepoId', null);
       }
     });
   },
@@ -1293,6 +1300,10 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
    * @method installStackVersionSuccess
    */
   installRepoVersionSuccess: function (data, opt, params) {
+    if(data && data.statusText == "timeout") {
+      App.showAlertPopup(Em.I18n.t('admin.stackVersions.upgrade.installPackage.fail.title'), Em.I18n.t('admin.stackVersions.upgrade.installPackage.fail.timeout'));
+      return false;
+    }
     var version = App.RepositoryVersion.find(params.id);
     App.db.set('repoVersionInstall', 'id', [data.Requests.id]);
     App.clusterStatus.setClusterStatus({
@@ -1320,6 +1331,9 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
         body = json.message;
       } catch (err) {}
     }
+    if(data && data.statusText == "timeout") {
+      body = Em.I18n.t('admin.stackVersions.upgrade.installPackage.fail.timeout');
+    }
     App.showAlertPopup(header, body);
   },
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/23653924/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index c0e1e16..2203b17 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -1451,6 +1451,7 @@ Em.I18n.translations = {
   'admin.stackVersions.filter.upgraded': "Ready to Finalize ({0})",
   'admin.stackVersions.upgrade.start.fail.title':'Upgrade could not be started',
   'admin.stackVersions.upgrade.installPackage.fail.title':'Packages could not be installed',
+  'admin.stackVersions.upgrade.installPackage.fail.timeout':'Request timed out.',
 
   'admin.stackVersions.editRepositories.info': 'Provide Base URLs for the Operating Systems you are configuring. Uncheck all other Operating Systems.',
   'admin.stackVersions.editRepositories.validation.warning': 'Some of the repositories failed validation. Make changes to the base url or skip validation if you are sure that urls are correct',

http://git-wip-us.apache.org/repos/asf/ambari/blob/23653924/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_version_box.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_version_box.hbs b/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_version_box.hbs
index 96d4544..1bc81c5 100644
--- a/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_version_box.hbs
+++ b/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_version_box.hbs
@@ -71,6 +71,9 @@
       }}
     {{/if}}
   {{/if}}
+  {{#if view.stateElement.isSpinner}}
+    <div {{bindAttr class="view.stateElement.class"}}></div>
+  {{/if}}
 </div>
 
 <div class="hosts-section">

http://git-wip-us.apache.org/repos/asf/ambari/blob/23653924/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_box_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_box_view.js b/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_box_view.js
index b6c5ad9..df588fd 100644
--- a/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_box_view.js
+++ b/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_box_view.js
@@ -114,6 +114,10 @@ App.UpgradeVersionBoxView = Em.View.extend({
       text: Em.I18n.t('admin.stackVersions.version.installNow'),
       action: 'installRepoVersionConfirmation'
     },
+    'LOADING': {
+      isSpinner: true,
+      class: 'spinner'
+    },
     'INSTALLING': {
       iconClass: 'icon-cog',
       isLink: true,
@@ -141,6 +145,7 @@ App.UpgradeVersionBoxView = Em.View.extend({
   stateElement: function () {
     var currentVersion = this.get('controller.currentVersion');
     var statePropertiesMap = this.get('statePropertiesMap');
+    var requestInProgressRepoId = this.get('controller.requestInProgressRepoId');
     var status = this.get('content.status');
     var element = Em.Object.create({
       status: status,
@@ -157,7 +162,7 @@ App.UpgradeVersionBoxView = Em.View.extend({
       element.setProperties(statePropertiesMap[status]);
     }
     else if (status === 'INIT') {
-      element.setProperties(statePropertiesMap[status]);
+      requestInProgressRepoId && requestInProgressRepoId == this.get('content.id') ? element.setProperties(statePropertiesMap['LOADING']) : element.setProperties(statePropertiesMap[status]);
       element.set('isDisabled', this.get('controller.requestInProgress') || isInstalling);
     }
     else if ((status === 'INSTALLED' && !this.get('isUpgrading')) ||
@@ -221,6 +226,7 @@ App.UpgradeVersionBoxView = Em.View.extend({
     'controller.isDowngrade',
     'isUpgrading',
     'controller.requestInProgress',
+    'controller.requestInProgressRepoId',
     'parentView.repoVersions.@each.status'
   ),