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

[1/2] ambari git commit: AMBARI-16983. Installer/ASW: Next and Back button should be disabled once its clicked (onechiporenko)

Repository: ambari
Updated Branches:
  refs/heads/trunk bd85c2815 -> 03e41db82


http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/test/views/wizard/step4_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/wizard/step4_view_test.js b/ambari-web/test/views/wizard/step4_view_test.js
index 7763c79..971e33b 100644
--- a/ambari-web/test/views/wizard/step4_view_test.js
+++ b/ambari-web/test/views/wizard/step4_view_test.js
@@ -16,27 +16,6 @@
  * limitations under the License.
  */
 
-var App = require('app');
-require('views/wizard/step4_view');
-
-var view;
-
 describe('App.WizardStep4View', function () {
 
-  beforeEach(function () {
-    view = App.WizardStep4View.create();
-  });
-
-  describe('#didInsertElement()', function () {
-    beforeEach(function () {
-      sinon.stub(App.get('router'), 'set', Em.K);
-    });
-    afterEach(function () {
-      App.get('router').set.restore();
-    });
-    it('router.transitionInProgress is set to false', function () {
-      view.didInsertElement();
-      expect(App.get('router').set.calledWith('transitionInProgress', false)).to.be.false;
-    });
-  });
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/test/views/wizard/step7_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/wizard/step7_view_test.js b/ambari-web/test/views/wizard/step7_view_test.js
index 022f1e0..c295f7d 100644
--- a/ambari-web/test/views/wizard/step7_view_test.js
+++ b/ambari-web/test/views/wizard/step7_view_test.js
@@ -17,29 +17,6 @@
  */
 
 
-var App = require('app');
-require('views/wizard/step7_view');
-var view;
-
 describe('App.WizardStep7View', function() {
 
-  beforeEach(function() {
-    view = App.WizardStep7View.create({
-      controller: App.WizardStep7Controller.create()
-    });
-  });
-
-  describe('#didInsertElement', function() {
-    beforeEach(function() {
-      sinon.stub(App.get('router'), 'set', Em.K);
-    });
-    afterEach(function() {
-      App.get('router').set.restore();
-    });
-
-    it('should call loadStep', function() {
-      view.didInsertElement();
-      expect(App.get('router').set.calledWith('transitionInProgress', false)).to.be.false;
-    });
-  });
 });


[2/2] ambari git commit: AMBARI-16983. Installer/ASW: Next and Back button should be disabled once its clicked (onechiporenko)

Posted by on...@apache.org.
AMBARI-16983. Installer/ASW: Next and Back button should be disabled once its clicked (onechiporenko)


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

Branch: refs/heads/trunk
Commit: 03e41db82ba0c115b6c09ced768b78e7db9881ce
Parents: bd85c28
Author: Oleg Nechiporenko <on...@apache.org>
Authored: Wed Jun 1 15:05:59 2016 +0300
Committer: Oleg Nechiporenko <on...@apache.org>
Committed: Thu Jun 2 09:01:49 2016 +0300

----------------------------------------------------------------------
 ambari-web/app/controllers/wizard.js            |   2 +-
 .../app/controllers/wizard/step0_controller.js  |   5 +
 .../app/controllers/wizard/step2_controller.js  |   2 +-
 .../app/controllers/wizard/step3_controller.js  |  22 ++-
 .../app/controllers/wizard/step4_controller.js  |   7 +-
 .../app/controllers/wizard/step5_controller.js  |  10 +-
 .../app/controllers/wizard/step6_controller.js  |  19 +--
 .../app/controllers/wizard/step7_controller.js  |  71 +++++-----
 .../app/controllers/wizard/step9_controller.js  |   2 +-
 .../mixins/wizard/assign_master_components.js   |  29 ++--
 ambari-web/app/router.js                        | 129 ++++++++++++++++--
 ambari-web/app/routes/add_host_routes.js        |  22 +--
 ambari-web/app/routes/add_service_routes.js     |  86 ++++++------
 ambari-web/app/routes/installer.js              |  76 ++++++-----
 .../common/assign_master_components.hbs         |  11 +-
 .../app/templates/main/host/addHost/step4.hbs   |  14 +-
 ambari-web/app/templates/wizard/step0.hbs       |   7 +-
 ambari-web/app/templates/wizard/step1.hbs       |  14 +-
 ambari-web/app/templates/wizard/step10.hbs      |   7 +-
 ambari-web/app/templates/wizard/step2.hbs       |  13 +-
 ambari-web/app/templates/wizard/step3.hbs       |  14 +-
 ambari-web/app/templates/wizard/step4.hbs       |  11 +-
 ambari-web/app/templates/wizard/step6.hbs       |  11 +-
 ambari-web/app/templates/wizard/step7.hbs       |  11 +-
 ambari-web/app/templates/wizard/step8.hbs       |  20 ++-
 ambari-web/app/templates/wizard/step9.hbs       |   8 +-
 ambari-web/app/views/wizard/step1_view.js       |   2 +-
 ambari-web/app/views/wizard/step4_view.js       |   5 +-
 ambari-web/app/views/wizard/step7_view.js       |   5 +-
 .../test/controllers/wizard/step0_test.js       |   4 +-
 .../test/controllers/wizard/step2_test.js       |   2 +-
 .../test/controllers/wizard/step3_test.js       |  17 +--
 .../test/controllers/wizard/step4_test.js       |  21 ---
 .../test/controllers/wizard/step5_test.js       |  17 +--
 .../test/controllers/wizard/step7_test.js       |   4 +-
 ambari-web/test/router_test.js                  | 135 ++++++++++++++++---
 ambari-web/test/views/wizard/step1_view_test.js |   2 +-
 ambari-web/test/views/wizard/step4_view_test.js |  21 ---
 ambari-web/test/views/wizard/step7_view_test.js |  23 ----
 39 files changed, 537 insertions(+), 344 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/controllers/wizard.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard.js b/ambari-web/app/controllers/wizard.js
index d5e946c..41837d2 100644
--- a/ambari-web/app/controllers/wizard.js
+++ b/ambari-web/app/controllers/wizard.js
@@ -60,7 +60,7 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, App.ThemesMappingM
   connectOutlet:function(name) {
     if (name !== 'loading') this.set('isStepDisabled.isLocked', false);
     App.router.setProperties({
-      transitionInProgress: false,
+      backBtnClickInProgress: false,
       nextBtnClickInProgress: false
     });
     return this._super.apply(this,arguments);

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/controllers/wizard/step0_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step0_controller.js b/ambari-web/app/controllers/wizard/step0_controller.js
index b816bd0..1ddb4fc 100644
--- a/ambari-web/app/controllers/wizard/step0_controller.js
+++ b/ambari-web/app/controllers/wizard/step0_controller.js
@@ -65,6 +65,11 @@ App.WizardStep0Controller = Em.Controller.extend({
   },
 
   /**
+   * @type {boolean}
+   */
+  isSubmitDisabled: Em.computed.or('invalidClusterName', 'App.router.btnClickInProgress'),
+
+  /**
    * Onclick handler for <code>next</code> button
    * Disable 'Next' button while it is already under process. (using Router's property 'nextBtnClickInProgress')
    * @method submit

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/controllers/wizard/step2_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step2_controller.js b/ambari-web/app/controllers/wizard/step2_controller.js
index 1ed3f69..7bbb2dd 100644
--- a/ambari-web/app/controllers/wizard/step2_controller.js
+++ b/ambari-web/app/controllers/wizard/step2_controller.js
@@ -167,7 +167,7 @@ App.WizardStep2Controller = Em.Controller.extend({
    * is Submit button disabled
    * @type {bool}
    */
-  isSubmitDisabled: Em.computed.or('hostsError', 'sshKeyError', 'sshUserError', 'sshPortError', 'agentUserError'),
+  isSubmitDisabled: Em.computed.or('hostsError', 'sshKeyError', 'sshUserError', 'sshPortError', 'agentUserError', 'App.router.btnClickInProgress'),
 
   installedHostNames: function () {
     var installedHostsName = [];

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/controllers/wizard/step3_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step3_controller.js b/ambari-web/app/controllers/wizard/step3_controller.js
index e8108ef..03912ed 100644
--- a/ambari-web/app/controllers/wizard/step3_controller.js
+++ b/ambari-web/app/controllers/wizard/step3_controller.js
@@ -113,7 +113,7 @@ App.WizardStep3Controller = Em.Controller.extend(App.ReloadPopupMixin, {
    * @return {bool}
    */
   isBackDisabled: function () {
-    return (this.get('isRegistrationInProgress') || !this.get('isWarningsLoaded')) && !this.get('isBootstrapFailed');
+    return (this.get('isRegistrationInProgress') || !this.get('isWarningsLoaded')) && !this.get('isBootstrapFailed') || App.get('router.btnClickInProgress');
   }.property('isRegistrationInProgress', 'isWarningsLoaded', 'isBootstrapFailed'),
 
   /**
@@ -1660,33 +1660,31 @@ App.WizardStep3Controller = Em.Controller.extend(App.ReloadPopupMixin, {
     }
   },
 
+  _submitProceed: function () {
+    this.set('confirmedHosts', this.get('bootHosts'));
+    App.get('router').send('next');
+  },
+
   /**
    * Submit-click handler
    * Disable 'Next' button while it is already under process. (using Router's property 'nextBtnClickInProgress')
-   * @return {App.ModalPopup|null}
+   * @return {App.ModalPopup?}
    * @method submit
    */
   submit: function () {
     var self = this;
 
-    if(App.get('router.nextBtnClickInProgress')){
+    if(App.get('router.nextBtnClickInProgress')) {
       return;
     }
     if (this.get('isHostHaveWarnings')) {
       return App.showConfirmationPopup(
         function () {
-          self.set('confirmedHosts', self.get('bootHosts'));
-          App.set('router.nextBtnClickInProgress', true);
-          App.get('router').send('next');
+          self._submitProceed();
         },
         Em.I18n.t('installer.step3.hostWarningsPopup.hostHasWarnings'));
     }
-    else {
-      this.set('confirmedHosts', this.get('bootHosts'));
-      App.set('router.nextBtnClickInProgress', true);
-      App.get('router').send('next');
-    }
-    return null;
+    this._submitProceed();
   },
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/controllers/wizard/step4_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step4_controller.js b/ambari-web/app/controllers/wizard/step4_controller.js
index 3513a1a..04e6784 100644
--- a/ambari-web/app/controllers/wizard/step4_controller.js
+++ b/ambari-web/app/controllers/wizard/step4_controller.js
@@ -47,8 +47,8 @@ App.WizardStep4Controller = Em.ArrayController.extend({
    * @type {bool}
    */
   isSubmitDisabled: function () {
-    return this.filterProperty('isSelected', true).filterProperty('isInstalled', false).length === 0;
-  }.property("@each.isSelected"),
+    return this.filterProperty('isSelected', true).filterProperty('isInstalled', false).length === 0 || App.get('router.btnClickInProgress');
+  }.property('@each.isSelected', 'App.router.btnClickInProgress'),
 
   /**
    * List of validation errors. Look to #createError method for information
@@ -137,14 +137,13 @@ App.WizardStep4Controller = Em.ArrayController.extend({
    * @method submit
    */
   submit: function () {
-    if(App.get('router.nextBtnClickInProgress')){
+    if(App.get('router.nextBtnClickInProgress')) {
       return;
     }
     if (!this.get('isSubmitDisabled')) {
       this.unSelectServices();
       this.setGroupedServices();
       if (this.validate()) {
-        App.set('router.nextBtnClickInProgress', true);
         this.set('errorStack', []);
         App.router.send('next');
       }

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/controllers/wizard/step5_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step5_controller.js b/ambari-web/app/controllers/wizard/step5_controller.js
index f800d09..5597165 100644
--- a/ambari-web/app/controllers/wizard/step5_controller.js
+++ b/ambari-web/app/controllers/wizard/step5_controller.js
@@ -20,5 +20,13 @@ var App = require('app');
 
 App.WizardStep5Controller = Em.Controller.extend(App.BlueprintMixin, App.AssignMasterComponents, {
 
-  name: "wizardStep5Controller"
+  name: "wizardStep5Controller",
+
+  _goNextStepIfValid: function () {
+    App.set('router.nextBtnClickInProgress', false);
+    if (!this.get('submitDisabled')) {
+      App.router.send('next');
+    }
+  },
+
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/controllers/wizard/step6_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step6_controller.js b/ambari-web/app/controllers/wizard/step6_controller.js
index 9e1dce9..e1d3953 100644
--- a/ambari-web/app/controllers/wizard/step6_controller.js
+++ b/ambari-web/app/controllers/wizard/step6_controller.js
@@ -69,7 +69,7 @@ App.WizardStep6Controller = Em.Controller.extend(App.BlueprintMixin, {
    * Define state for submit button
    * @type {bool}
    */
-  submitDisabled: Em.computed.alias('validationInProgress'),
+  submitDisabled: Em.computed.or('validationInProgress', 'App.router.btnClickInProgress'),
 
   /**
    * timer for validation request
@@ -144,7 +144,7 @@ App.WizardStep6Controller = Em.Controller.extend(App.BlueprintMixin, {
   anyGeneralIssues: Em.computed.or('anyGeneralErrors', 'anyGeneralWarnings'),
 
   anyHostErrors: function () {
-    return this.get('hosts').some(function(h) { return h.errorMessages ? (h.errorMessages.length > 0) : false;});
+    return this.get('hosts').some(function(h) { return h.errorMessages ? h.errorMessages.length > 0 : false;});
   }.property('hosts.@each.errorMessages'),
 
   /**
@@ -153,7 +153,7 @@ App.WizardStep6Controller = Em.Controller.extend(App.BlueprintMixin, {
   anyErrors: Em.computed.or('anyGeneralErrors', 'anyHostErrors'),
 
   anyHostWarnings: function () {
-    return this.get('hosts').some(function(h) { return h.warnMessages ? (h.warnMessages.length > 0) : false;});
+    return this.get('hosts').some(function(h) { return h.warnMessages ? h.warnMessages.length > 0 : false;});
   }.property('hosts.@each.warnMessages'),
 
   /**
@@ -631,7 +631,7 @@ App.WizardStep6Controller = Em.Controller.extend(App.BlueprintMixin, {
     }).
       then(function () {
         self.set('validationInProgress', false);
-        if (!self.get('submitDisabled') && successCallback) {
+        if (App.get('router.btnClickInProgress') && successCallback) {
           successCallback();
         }
       }
@@ -645,7 +645,6 @@ App.WizardStep6Controller = Em.Controller.extend(App.BlueprintMixin, {
    */
   updateValidationsSuccessCallback: function (data) {
     var self = this;
-    //data = JSON.parse(data); // temporary fix
 
     var clientComponents = App.get('components.clients');
 
@@ -658,7 +657,6 @@ App.WizardStep6Controller = Em.Controller.extend(App.BlueprintMixin, {
       host.checkboxes.setEach('hasWarnMessage', false);
       host.checkboxes.setEach('hasErrorMessage', false);
     });
-    var anyErrors = false;
     var anyGeneralClientErrors = false; // any error/warning for any client component (under "CLIENT" alias)
 
     var validationData = validationUtils.filterNotInstalledComponents(data);
@@ -673,16 +671,14 @@ App.WizardStep6Controller = Em.Controller.extend(App.BlueprintMixin, {
           if (checkbox.component === item['component-name'] || isClientComponent) {
             checkboxWithIssue = checkbox;
             return true;
-          } else {
-            return false;
           }
+          return false;
         });
       });
       if (host) {
         Em.set(host, 'anyMessage', true);
 
         if (item.level === 'ERROR') {
-          anyErrors = true;
           host.errorMessages.pushObject(item.message);
           Em.set(checkboxWithIssue, 'hasErrorMessage', true);
         }
@@ -711,7 +707,6 @@ App.WizardStep6Controller = Em.Controller.extend(App.BlueprintMixin, {
           }
 
           if (item.level === 'ERROR') {
-            anyErrors = true;
             self.get('generalErrorMessages').push(item.message + details);
           }
           else
@@ -721,10 +716,6 @@ App.WizardStep6Controller = Em.Controller.extend(App.BlueprintMixin, {
         }
       }
     });
-
-    // use this.set('submitDisabled', anyErrors); is validation results should block next button
-    // It's because showValidationIssuesAcceptBox allow use accept validation issues and continue
-    // this.set('submitDisabled', false);
   },
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/controllers/wizard/step7_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step7_controller.js b/ambari-web/app/controllers/wizard/step7_controller.js
index 57a993f..5b28cfa 100644
--- a/ambari-web/app/controllers/wizard/step7_controller.js
+++ b/ambari-web/app/controllers/wizard/step7_controller.js
@@ -143,8 +143,9 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E
   isSubmitDisabled: function () {
     if (!this.get('stepConfigs.length')) return true;
     if (this.get('submitButtonClicked')) return true;
+    if (App.get('router.btnClickInProgress')) return true;
     return !this.get('stepConfigs').filterProperty('showConfig', true).everyProperty('errorCount', 0) || this.get("miscModalVisible");
-  }.property('stepConfigs.@each.errorCount', 'miscModalVisible', 'submitButtonClicked'),
+  }.property('stepConfigs.@each.errorCount', 'miscModalVisible', 'submitButtonClicked', 'App.router.btnClickInProgress'),
 
   /**
    * List of selected to install service names
@@ -250,15 +251,20 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E
         Em.I18n.t('installer.step7.showingPropertiesWithIssues') : '';
   }.property('isSubmitDisabled', 'submitButtonClicked', 'filterColumns.@each.selected'),
 
+  /**
+   * @type {string}
+   */
   issuesFilterLinkText: function () {
-    if (this.get('filterColumns').findProperty('attributeName', 'hasIssues').get('selected')) {
+    var issuesAttrSelected = this.get('filterColumns').findProperty('attributeName', 'hasIssues').get('selected');
+    if (issuesAttrSelected) {
       return Em.I18n.t('installer.step7.showAllProperties');
     }
 
-    return this.get('isSubmitDisabled') && !this.get('submitButtonClicked') ?
-        this.get('filterColumns').findProperty('attributeName', 'hasIssues').get('selected') ?
-          Em.I18n.t('installer.step7.showAllProperties') : Em.I18n.t('installer.step7.showPropertiesWithIssues')
-       : '';
+    if (this.get('isSubmitDisabled') && !this.get('submitButtonClicked')) {
+      return issuesAttrSelected ?
+        Em.I18n.t('installer.step7.showAllProperties') : Em.I18n.t('installer.step7.showPropertiesWithIssues');
+    }
+    return '';
   }.property('isSubmitDisabled', 'submitButtonClicked', 'filterColumns.@each.selected'),
 
   /**
@@ -281,7 +287,7 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E
    *    <li>stepConfigs</li>
    *    <li>filter</li>
    *  </ul>
-   *  and desect all <code>filterColumns</code>
+   *  and deselect all <code>filterColumns</code>
    * @method clearStep
    */
   clearStep: function () {
@@ -353,7 +359,7 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E
         serviceConfigs = stepConfig.get('configs'),
         configGroup = App.ServiceConfigGroup.find().filterProperty('serviceName', group.service_name).findProperty('name', group.group_name);
 
-      var isEditable = self.get('canEdit') && configGroup.get('name') == stepConfig.get('selectedConfigGroup.name');
+      var isEditable = self.get('canEdit') && configGroup.get('name') === stepConfig.get('selectedConfigGroup.name');
 
       group.configurations.forEach(function (config) {
         for (var prop in config.properties) {
@@ -464,7 +470,7 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E
 
     var storedConfigs = this.get('content.serviceConfigProperties');
 
-    var configs = (storedConfigs && storedConfigs.length) ? storedConfigs : App.configsCollection.getAll();
+    var configs = storedConfigs && storedConfigs.length ? storedConfigs : App.configsCollection.getAll();
 
     this.set('groupsToDelete', this.get('wizardController').getDBProperty('groupsToDelete') || []);
     if (this.get('wizardController.name') === 'addServiceController' && !this.get('content.serviceConfigProperties.length')) {
@@ -974,19 +980,17 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E
         if (Em.isNone(mappedConfigValue)) {
           //for now ranger plugin properties are not sending by recommendations if they are missed - it should be added
           return _config.serviceName === 'MISC' || /^ranger-/.test(_config.filename);
-        } else {
-          if (_config.savedValue != mappedConfigValue) {
-            _config.savedValue = App.config.formatPropertyValue(_config, mappedConfigValue);
-          }
-          _config.value = App.config.formatPropertyValue(_config, mappedConfigValue);
-          _config.hasInitialValue = true;
-          this.updateDependencies(_config);
-          delete configsMap[type][_config.name];
-          return true;
         }
-      } else {
+        if (_config.savedValue != mappedConfigValue) {
+          _config.savedValue = App.config.formatPropertyValue(_config, mappedConfigValue);
+        }
+        _config.value = App.config.formatPropertyValue(_config, mappedConfigValue);
+        _config.hasInitialValue = true;
+        this.updateDependencies(_config);
+        delete configsMap[type][_config.name];
         return true;
       }
+      return true;
     }, this);
     //add user properties
     Em.keys(configsMap).forEach(function (filename) {
@@ -1007,10 +1011,14 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E
    * @param config
    */
   updateDependencies: function(config) {
-    if (config.name === 'hive.metastore.uris' && config.filename === 'hive-site.xml') {
-      this.get('configDependencies')['hive.metastore.uris'] = config.savedValue;
-    } else if (config.name === 'clientPort' && config.filename === 'hive-site.xml') {
-      this.get('configDependencies').clientPort = config.savedValue;
+    if (config.filename === 'hive-site.xml') {
+      if (config.name === 'hive.metastore.uris') {
+        this.get('configDependencies')['hive.metastore.uris'] = config.savedValue;
+      }
+      else
+        if (config.name === 'clientPort') {
+          this.get('configDependencies').clientPort = config.savedValue;
+        }
     }
   },
 
@@ -1050,7 +1058,7 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E
       this.set('configGroups', serviceGroups);
       this.set('selectedConfigGroup', serviceGroups.findProperty('isDefault'));
     }
-  }.observes('selectedService.configGroups.@each'),
+  }.observes('selectedService.configGroups.[]'),
 
   /**
    * load default groups for each service in case of initial load
@@ -1301,12 +1309,11 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E
    * that using MySql database too.
    *
    * @method resolveHiveMysqlDatabase
-   **/
+   */
   resolveHiveMysqlDatabase: function () {
     var hiveService = this.get('content.services').findProperty('serviceName', 'HIVE');
     if (!hiveService || !hiveService.get('isSelected') || hiveService.get('isInstalled')) {
-      this.moveNext();
-      return;
+      return this.moveNext();
     }
     var hiveDBType = this.get('stepConfigs').findProperty('serviceName', 'HIVE').configs.findProperty('name', 'hive_database').value;
     if (hiveDBType === 'New MySQL Database') {
@@ -1315,9 +1322,7 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E
         self.mySQLWarningHandler();
       });
     }
-    else {
-      this.moveNext();
-    }
+    return this.moveNext();
   },
 
   /**
@@ -1366,9 +1371,7 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E
         }
       });
     }
-    else {
-      return this.moveNext();
-    }
+    return this.moveNext();
   },
 
   checkDatabaseConnectionTest: function () {
@@ -1490,7 +1493,7 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E
    * Proceed to the next step
    **/
   moveNext: function () {
-    App.set('router.nextBtnClickInProgress', true);
+    App.set('router.nextBtnClickInProgress', false);
     App.router.send('next');
     this.set('submitButtonClicked', false);
   },

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/controllers/wizard/step9_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step9_controller.js b/ambari-web/app/controllers/wizard/step9_controller.js
index 916f9dc..015cb84 100644
--- a/ambari-web/app/controllers/wizard/step9_controller.js
+++ b/ambari-web/app/controllers/wizard/step9_controller.js
@@ -111,7 +111,7 @@ App.WizardStep9Controller = Em.Controller.extend(App.ReloadPopupMixin, {
     if (controllerName == 'addHostController' || controllerName == 'addServiceController') {
       validStates.push('INSTALL FAILED');
     }
-    return !validStates.contains(this.get('content.cluster.status'));
+    return !validStates.contains(this.get('content.cluster.status')) || App.get('router.btnClickInProgress');
   }.property('content.cluster.status'),
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/mixins/wizard/assign_master_components.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/wizard/assign_master_components.js b/ambari-web/app/mixins/wizard/assign_master_components.js
index 0e4a23d..a8b0caf 100644
--- a/ambari-web/app/mixins/wizard/assign_master_components.js
+++ b/ambari-web/app/mixins/wizard/assign_master_components.js
@@ -1144,6 +1144,14 @@ App.AssignMasterComponents = Em.Mixin.create({
     }, true);
   },
 
+  _goNextStepIfValid: function () {
+    if (!this.get('submitDisabled')) {
+      App.router.send('next');
+    }else{
+      App.set('router.nextBtnClickInProgress', false);
+    }
+  },
+
   /**
    * Submit button click handler
    * Disable 'Next' button while it is already under process. (using Router's property 'nextBtnClickInProgress')
@@ -1154,26 +1162,19 @@ App.AssignMasterComponents = Em.Mixin.create({
     if (this.get('submitDisabled')) {
       return;
     }
-    if (!this.get('submitButtonClicked') && !App.router.get('nextBtnClickInProgress')) {
+    if (!this.get('submitButtonClicked') && !App.get('router.nextBtnClickInProgress')) {
       this.set('submitButtonClicked', true);
       App.router.set('nextBtnClickInProgress', true);
 
-      var goNextStepIfValid = function () {
-        if (!self.get('submitDisabled')) {
-          App.router.send('next');
-        }else{
-          App.router.set('nextBtnClickInProgress', false);
-        }
-      };
-
       if (this.get('useServerValidation')) {
         self.recommendAndValidate(function () {
-          self.showValidationIssuesAcceptBox(goNextStepIfValid);
+          self.showValidationIssuesAcceptBox(self._goNextStepIfValid.bind(self));
         });
-      } else {
-        self.updateIsSubmitDisabled();
-        goNextStepIfValid();
-        self.set('submitButtonClicked', false);
+      }
+      else {
+        this.updateIsSubmitDisabled();
+        this._goNextStepIfValid();
+        this.set('submitButtonClicked', false);
       }
     }
   },

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/router.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/router.js b/ambari-web/app/router.js
index b7ba2cb..d3caf6a 100644
--- a/ambari-web/app/router.js
+++ b/ambari-web/app/router.js
@@ -44,20 +44,127 @@ App.WizardRoute = Em.Route.extend({
   gotoStep10: Em.Router.transitionTo('step10'),
 
   isRoutable: function() {
-    return (typeof this.get('route') === 'string' && App.router.get('loggedIn'));
+    return typeof this.get('route') === 'string' && App.router.get('loggedIn');
   }.property('App.router.loggedIn')
 
 });
 
+/**
+ * This route executes "back" and "next" handler on the next run-loop
+ * Reason: It's done like this, because in general transitions have highest priority in the Ember run-loop
+ * So, CP's and observers for <code>App.router.backBtnClickInProgress</code> and <code>App.router.nextBtnClickInProgress</code>
+ * will be triggered after "back" or "next" are complete and not before them.
+ * It's more important for "back", because usually it doesn't do any requests that may cause a little delay for run loops
+ * <code>Em.run.next</code> is used to avoid this
+ *
+ * Example:
+ * <pre>
+ *   App.Step2Route = App.StepRoute.extend({
+ *
+ *    route: '/step2',
+ *
+ *    connectOutlets: function (router, context) {
+ *      // some code
+ *    },
+ *
+ *    nextTransition: function (router) {
+ *      router.transitionTo('step3');
+ *    },
+ *
+ *    backTransition: function (router) {
+ *      router.transitionTo('step1');
+ *    }
+ *
+ *   });
+ * </pre>
+ * In this case both <code>transitionTo</code> will be executed in the next run loop after loop where "next" or "back" were called
+ * <b>IMPORTANT!</b> Flags <code>App.router.backBtnClickInProgress</code> and <code>App.router.nextBtnClickInProgress</code> are set to <code>true</code>
+ * in the "back" and "next". Be sure to set them <code>false</code> when needed
+ *
+ * @type {Em.Route}
+ */
+App.StepRoute = Em.Route.extend({
+
+  /**
+   * @type {Function}
+   */
+  backTransition: Em.K,
+
+  /**
+   * @type {Function}
+   */
+  nextTransition: Em.K,
+
+  /**
+   * Default "Back"-action
+   * Execute <code>backTransition</code> once
+   *
+   * @param {Em.Router} router
+   */
+  back: function (router) {
+    if (App.get('router.btnClickInProgress')) {
+      return;
+    }
+    App.set('router.backBtnClickInProgress', true);
+    var self = this;
+    Em.run.next(function () {
+      Em.tryInvoke(self, 'backTransition', [router]);
+    })
+  },
+
+  /**
+   * Default "Next"-action
+   * Execute <code>nextTransition</code> once
+   *
+   * @param {Em.Router} router
+   */
+  next: function (router) {
+    if (App.get('router.btnClickInProgress')) {
+      return;
+    }
+    App.set('router.nextBtnClickInProgress', true);
+    var self = this;
+    Em.run.next(function () {
+      Em.tryInvoke(self, 'nextTransition', [router]);
+    })
+  }
+
+});
+
 App.Router = Em.Router.extend({
 
   enableLogging: true,
   isFwdNavigation: true,
   backBtnForHigherStep: false,
-  transitionInProgress: false,
+
+  /**
+   * Checks if Back button is clicked
+   * Set to default value on the <code>App.WizardController.connectOutlet</code>
+   *
+   * @type {boolean}
+   * @default false
+   */
+  backBtnClickInProgress: false,
+
+  /**
+   * Checks if Next button is clicked
+   * Set to default value on the <code>App.WizardController.connectOutlet</code>
+   *
+   * @type {boolean}
+   * @default false
+   */
   nextBtnClickInProgress: false,
 
   /**
+   * Checks if Next or Back button is clicked
+   * Used in the <code>App.StepRoute</code>-instances to avoid "next"/"back" double-clicks
+   *
+   * @type {boolean}
+   * @default false
+   */
+  btnClickInProgress: Em.computed.or('backBtnClickInProgress', 'nextBtnClickInProgress'),
+
+  /**
    * Path for local login page. This page will be always accessible without
    * redirect to auth server different from ambari-server. Used in some types of
    * authorizations like knox sso.
@@ -90,9 +197,9 @@ App.Router = Em.Router.extend({
     var matches = step.match(/\d+$/);
     var newStep;
     if (matches) {
-      newStep = parseInt(matches[0]);
+      newStep = parseInt(matches[0], 10);
     }
-    var previousStep = parseInt(this.getInstallerCurrentStep());
+    var previousStep = parseInt(this.getInstallerCurrentStep(), 10);
     this.set('isFwdNavigation', newStep >= previousStep);
   },
 
@@ -399,10 +506,9 @@ App.Router = Em.Router.extend({
           this.hide();
         }
       });
-    }else{
-      this.setClusterData(data, opt, params);
-      return false;
     }
+    this.setClusterData(data, opt, params);
+    return false;
   },
 
   /**
@@ -548,13 +654,13 @@ App.Router = Em.Router.extend({
             var clusterStatusOnServer = App.clusterStatus.get('value');
             if (clusterStatusOnServer) {
               var wizardControllerRoutes = require('data/controller_route');
-              var wizardControllerRoute =  wizardControllerRoutes.findProperty('wizardControllerName', clusterStatusOnServer.wizardControllerName);
+              var wizardControllerRoute = wizardControllerRoutes.findProperty('wizardControllerName', clusterStatusOnServer.wizardControllerName);
               if (wizardControllerRoute && !App.router.get('wizardWatcherController').get('isNonWizardUser')) {
                 route = wizardControllerRoute.route;
               }
             }
-            if (wizardControllerRoute && wizardControllerRoute.wizardControllerName === 'mainAdminStackAndUpgradeController')  {
-              var clusterController =   App.router.get('clusterController');
+            if (wizardControllerRoute && wizardControllerRoute.wizardControllerName === 'mainAdminStackAndUpgradeController') {
+              var clusterController = App.router.get('clusterController');
               clusterController.loadClusterName().done(function(){
                 clusterController.restoreUpgradeState().done(function(){
                   callback(route);
@@ -699,8 +805,9 @@ App.Router = Em.Router.extend({
   initAuth: function(){
     if (App.db) {
       var auth = App.db.getAuth();
-      if(auth)
+      if(auth) {
         App.set('auth', auth);
+      }
     }
   },
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/routes/add_host_routes.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/routes/add_host_routes.js b/ambari-web/app/routes/add_host_routes.js
index ba290cd..c733a66 100644
--- a/ambari-web/app/routes/add_host_routes.js
+++ b/ambari-web/app/routes/add_host_routes.js
@@ -92,7 +92,7 @@ module.exports = App.WizardRoute.extend({
 
   },
 
-  step1: Em.Route.extend({
+  step1: App.StepRoute.extend({
     route: '/step1',
     connectOutlets: function (router) {
       var controller = router.get('addHostController');
@@ -106,7 +106,7 @@ module.exports = App.WizardRoute.extend({
       });
     },
 
-    next: function (router) {
+    nextTransition: function (router) {
       var controller = router.get('addHostController');
       controller.save('installOptions');
       //hosts was saved to content.hosts inside wizardStep2Controller
@@ -126,7 +126,7 @@ module.exports = App.WizardRoute.extend({
     }
   }),
 
-  step2: Em.Route.extend({
+  step2: App.StepRoute.extend({
     route: '/step2',
     connectOutlets: function (router) {
       var controller = router.get('addHostController');
@@ -138,13 +138,13 @@ module.exports = App.WizardRoute.extend({
         controller.connectOutlet('wizardStep3', controller.get('content'));
       });
     },
-    back: function (router) {
+    backTransition: function (router) {
       router.transitionTo('step1');
     },
     exit: function (router) {
       router.get('wizardStep3Controller').set('stopBootstrap', true);
     },
-    next: function (router, context) {
+    nextTransition: function (router, context) {
       var addHostController = router.get('addHostController');
       var wizardStep3Controller = router.get('wizardStep3Controller');
       var wizardStep6Controller = router.get('wizardStep6Controller');
@@ -170,7 +170,7 @@ module.exports = App.WizardRoute.extend({
     }
   }),
 
-  step3: Em.Route.extend({
+  step3: App.StepRoute.extend({
     route: '/step3',
     connectOutlets: function (router, context) {
       var controller = router.get('addHostController');
@@ -182,7 +182,9 @@ module.exports = App.WizardRoute.extend({
         controller.connectOutlet('wizardStep6', controller.get('content'));
       });
     },
-    back: Em.Router.transitionTo('step2'),
+    backTransition: function (router) {
+      router.transitionTo('step2');
+    },
     next: function (router) {
       App.set('router.nextBtnClickInProgress', true);
       var addHostController = router.get('addHostController');
@@ -205,7 +207,7 @@ module.exports = App.WizardRoute.extend({
     }
   }),
 
-  step4: Em.Route.extend({
+  step4: App.StepRoute.extend({
     route: '/step4',
     connectOutlets: function (router, context) {
       var controller = router.get('addHostController');
@@ -222,10 +224,10 @@ module.exports = App.WizardRoute.extend({
         });
       });
     },
-    back: function (router) {
+    backTransition: function (router) {
       router.transitionTo('step3');
     },
-    next: function (router) {
+    nextTransition: function (router) {
       var addHostController = router.get('addHostController');
       addHostController.saveServiceConfigGroups();
       router.transitionTo('step5');

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/routes/add_service_routes.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/routes/add_service_routes.js b/ambari-web/app/routes/add_service_routes.js
index 0a20ccf..4a5f565 100644
--- a/ambari-web/app/routes/add_service_routes.js
+++ b/ambari-web/app/routes/add_service_routes.js
@@ -91,7 +91,7 @@ module.exports = App.WizardRoute.extend({
 
   },
 
-  step1: Em.Route.extend({
+  step1: App.StepRoute.extend({
     route: '/step1',
     connectOutlets: function (router) {
       var controller = router.get('addServiceController');
@@ -112,7 +112,7 @@ module.exports = App.WizardRoute.extend({
         });
       });
     },
-    next: function (router) {
+    nextTransition: function (router) {
       var addServiceController = router.get('addServiceController');
       var wizardStep4Controller = router.get('wizardStep4Controller');
       addServiceController.saveServices(wizardStep4Controller);
@@ -127,7 +127,7 @@ module.exports = App.WizardRoute.extend({
     }
   }),
 
-  step2: Em.Route.extend({
+  step2: App.StepRoute.extend({
     route: '/step2',
     connectOutlets: function (router) {
       var controller = router.get('addServiceController');
@@ -142,7 +142,11 @@ module.exports = App.WizardRoute.extend({
       });
 
     },
-    back: Em.Router.transitionTo('step1'),
+
+    backTransition: function (router) {
+      router.transitionTo('step1');
+    },
+
     next: function (router) {
       var addServiceController = router.get('addServiceController');
       var wizardStep5Controller = router.get('wizardStep5Controller');
@@ -155,7 +159,7 @@ module.exports = App.WizardRoute.extend({
     }
   }),
 
-  step3: Em.Route.extend({
+  step3: App.StepRoute.extend({
     route: '/step3',
     connectOutlets: function (router) {
       var controller = router.get('addServiceController');
@@ -168,14 +172,15 @@ module.exports = App.WizardRoute.extend({
         });
       });
     },
-    back: function (router) {
+
+    backTransition: function (router) {
       var controller = router.get('addServiceController');
       if (!controller.get('content.skipMasterStep')) {
-        router.transitionTo('step2');
-      } else {
-        router.transitionTo('step1');
+        return router.transitionTo('step2');
       }
+      return router.transitionTo('step1');
     },
+
     next: function (router) {
       App.set('router.nextBtnClickInProgress', true);
       var addServiceController = router.get('addServiceController');
@@ -194,14 +199,13 @@ module.exports = App.WizardRoute.extend({
           router.get('wizardStep7Controller').set('recommendationsConfigs', null);
           router.get('wizardStep7Controller').clearAllRecommendations();
           addServiceController.setDBProperty('serviceConfigGroups', undefined);
-          App.set('router.nextBtnClickInProgress', false);
           router.transitionTo('step4');
         });
       });
     }
   }),
 
-  step4: Em.Route.extend({
+  step4: App.StepRoute.extend({
     route: '/step4',
     connectOutlets: function (router) {
       var controller = router.get('addServiceController');
@@ -221,15 +225,16 @@ module.exports = App.WizardRoute.extend({
         });
       });
     },
-    back: function (router) {
+
+    backTransition: function (router) {
       var controller = router.get('addServiceController');
       if (!controller.get('content.skipSlavesStep')) {
-        router.transitionTo('step3');
-      } else if (!controller.get('content.skipMasterStep')) {
-        router.transitionTo('step2');
-      } else {
-        router.transitionTo('step1');
+        return router.transitionTo('step3');
       }
+      if (!controller.get('content.skipMasterStep')) {
+        return router.transitionTo('step2');
+      }
+      return router.transitionTo('step1');
     },
     next: function (router) {
       var addServiceController = router.get('addServiceController');
@@ -261,21 +266,15 @@ module.exports = App.WizardRoute.extend({
     back: function (router) {
       var controller = router.get('addServiceController');
       if (!controller.get('content.skipConfigStep')) {
-        router.transitionTo('step4');
+        return router.transitionTo('step4');
       }
-      else {
-        if (!controller.get('content.skipSlavesStep')) {
-          router.transitionTo('step3');
-        }
-        else {
-          if (!controller.get('content.skipMasterStep')) {
-            router.transitionTo('step2');
-          }
-          else {
-            router.transitionTo('step1');
-          }
-        }
+      if (!controller.get('content.skipSlavesStep')) {
+        return router.transitionTo('step3');
+      }
+      if (!controller.get('content.skipMasterStep')) {
+        return router.transitionTo('step2');
       }
+      return router.transitionTo('step1');
     },
     next: function (router) {
       if (App.Cluster.find().objectAt(0).get('isKerberosEnabled')) {
@@ -289,7 +288,7 @@ module.exports = App.WizardRoute.extend({
     }
   }),
 
-  step6: Em.Route.extend({
+  step6: App.StepRoute.extend({
     route: '/step6',
     connectOutlets: function (router, context) {
       var controller = router.get('addServiceController');
@@ -305,28 +304,21 @@ module.exports = App.WizardRoute.extend({
         router.get('kerberosWizardStep5Controller').getCSVData(true);
       }
     },
-    back: function (router) {
+    backTransition: function (router) {
       var controller = router.get('addServiceController');
       if (App.get('isKerberosEnabled')) {
-        router.transitionTo('step5');
-        return;
+        return router.transitionTo('step5');
       }
       if (!controller.get('content.skipConfigStep')) {
-        router.transitionTo('step4');
+        return router.transitionTo('step4');
       }
-      else {
-        if (!controller.get('content.skipSlavesStep')) {
-          router.transitionTo('step3');
-        }
-        else {
-          if (!controller.get('content.skipMasterStep')) {
-            router.transitionTo('step2');
-          }
-          else {
-            router.transitionTo('step1');
-          }
-        }
+      if (!controller.get('content.skipSlavesStep')) {
+        return router.transitionTo('step3');
+      }
+      if (!controller.get('content.skipMasterStep')) {
+        return router.transitionTo('step2');
       }
+      return router.transitionTo('step1');
     },
     next: function (router) {
       var addServiceController = router.get('addServiceController');

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/routes/installer.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/routes/installer.js b/ambari-web/app/routes/installer.js
index 9a4534b..6aa8d8c 100644
--- a/ambari-web/app/routes/installer.js
+++ b/ambari-web/app/routes/installer.js
@@ -156,7 +156,7 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
     back: Em.Router.transitionTo('step0'),
     next: function (router) {
       console.time('step1 next');
-      if(router.get('nextBtnClickInProgress') || router.transitionInProgress){
+      if(router.get('btnClickInProgress')) {
         return;
       }
       var wizardStep1Controller = router.get('wizardStep1Controller');
@@ -164,7 +164,6 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
       installerController.validateJDKVersion(function() {
         installerController.checkRepoURL(wizardStep1Controller).done(function () {
           App.set('router.nextBtnClickInProgress', true);
-          router.set('transitionInProgress', true);
           installerController.setDBProperty('service', undefined);
           installerController.setStacks();
           installerController.clearInstallOptions();
@@ -191,8 +190,8 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
     back: Em.Router.transitionTo('step1'),
     next: function (router) {
       console.time('step2 next');
-      if (!router.transitionInProgress) {
-        router.set('transitionInProgress', true);
+      if (!router.get('btnClickInProgress')) {
+        App.set('router.nextBtnClickInProgress', true);
         var controller = router.get('installerController');
         controller.save('installOptions');
         //hosts was saved to content.hosts inside wizardStep2Controller
@@ -203,7 +202,7 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
     }
   }),
 
-  step3: Em.Route.extend({
+  step3: App.StepRoute.extend({
     route: '/step3',
     connectOutlets: function (router) {
       console.time('step3 connectOutlets');
@@ -216,13 +215,15 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
         console.timeEnd('step3 connectOutlets');
       });
     },
-    back: function (router) {
+
+    backTransition: function (router) {
       router.transitionTo('step2');
     },
+
     next: function (router, context) {
       console.time('step3 next');
-      if (!router.transitionInProgress) {
-        router.set('transitionInProgress', true);
+      if (!router.get('btnClickInProgress')) {
+        App.set('router.nextBtnClickInProgress', true);
         var installerController = router.get('installerController');
         var wizardStep3Controller = router.get('wizardStep3Controller');
         installerController.saveConfirmedHosts(wizardStep3Controller);
@@ -250,7 +251,7 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
     }
   }),
 
-  step4: Em.Route.extend({
+  step4: App.StepRoute.extend({
     route: '/step4',
     connectOutlets: function (router, context) {
       console.time('step4 connectOutlets');
@@ -264,12 +265,15 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
         console.timeEnd('step4 connectOutlets');
       });
     },
-    back: Em.Router.transitionTo('step3'),
+
+    backTransition: function(router) {
+      router.transitionTo('step3');
+    },
 
     next: function (router) {
       console.time('step4 next');
-      if (!router.transitionInProgress) {
-        router.set('transitionInProgress', true);
+      if (!router.get('btnClickInProgress')) {
+        App.set('router.nextBtnClickInProgress', true);
         var controller = router.get('installerController');
         var wizardStep4Controller = router.get('wizardStep4Controller');
         controller.saveServices(wizardStep4Controller);
@@ -286,7 +290,7 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
     }
   }),
 
-  step5: Em.Route.extend({
+  step5: App.StepRoute.extend({
     route: '/step5',
     connectOutlets: function (router, context) {
       console.time('step5 connectOutlets');
@@ -304,11 +308,13 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
         console.timeEnd('step5 connectOutlets');
       });
     },
-    back: Em.Router.transitionTo('step4'),
+    backTransition: function(router) {
+      router.transitionTo('step4');
+    },
     next: function (router) {
       console.time('step5 next');
-      if (!router.transitionInProgress) {
-        router.set('transitionInProgress', true);
+      if (!router.get('btnClickInProgress')) {
+        App.set('router.nextBtnClickInProgress', true);
         var controller = router.get('installerController');
         var wizardStep5Controller = router.get('wizardStep5Controller');
         var wizardStep6Controller = router.get('wizardStep6Controller');
@@ -324,7 +330,7 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
     }
   }),
 
-  step6: Em.Route.extend({
+  step6: App.StepRoute.extend({
     route: '/step6',
     connectOutlets: function (router, context) {
       console.time('step6 connectOutlets');
@@ -338,17 +344,18 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
         console.timeEnd('step6 connectOutlets');
       });
     },
-    back: Em.Router.transitionTo('step5'),
+    backTransition: function(router) {
+      router.transitionTo('step5');
+    },
 
     next: function (router) {
       console.time('step6 next');
-      App.set('router.nextBtnClickInProgress', true);
       var controller = router.get('installerController');
       var wizardStep6Controller = router.get('wizardStep6Controller');
       if (!wizardStep6Controller.get('submitDisabled')) {
         wizardStep6Controller.showValidationIssuesAcceptBox(function () {
-          if (!router.transitionInProgress) {
-            router.set('transitionInProgress', true);
+          if (!router.get('btnClickInProgress')) {
+            App.set('router.nextBtnClickInProgress', true);
             controller.saveSlaveComponentHosts(wizardStep6Controller);
             controller.get('content').set('serviceConfigProperties', null);
             controller.setDBProperties({
@@ -357,7 +364,6 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
               recommendationsHostGroups: wizardStep6Controller.get('content.recommendationsHostGroups'),
               recommendationsConfigs: null
             });
-            App.set('router.nextBtnClickInProgress', false);
             router.transitionTo('step7');
             console.timeEnd('step6 next');
           }
@@ -366,14 +372,16 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
     }
   }),
 
-  step7: Em.Route.extend({
+  step7: App.StepRoute.extend({
     route: '/step7',
+
     enter: function (router) {
       console.time('step7 enter');
       var controller = router.get('installerController');
       controller.setCurrentStep('7');
       console.timeEnd('step7 enter');
     },
+
     connectOutlets: function (router, context) {
       console.time('step7 connectOutlets');
       var controller = router.get('installerController');
@@ -385,7 +393,8 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
         console.timeEnd('step7 connectOutlets');
       });
     },
-    back: function (router) {
+
+    backTransition: function (router) {
       console.time('step7 back');
       var step = router.get('installerController.content.skipSlavesStep') ? 'step5' : 'step6';
       var wizardStep7Controller = router.get('wizardStep7Controller');
@@ -403,22 +412,20 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
     },
     next: function (router) {
       console.time('step7 next');
-      if (!router.transitionInProgress) {
-        router.set('transitionInProgress', true);
+      if (!router.get('btnClickInProgress')) {
         App.set('router.nextBtnClickInProgress', true);
         var controller = router.get('installerController');
         var wizardStep7Controller = router.get('wizardStep7Controller');
         controller.saveServiceConfigProperties(wizardStep7Controller);
         controller.saveServiceConfigGroups(wizardStep7Controller);
         controller.setDBProperty('recommendationsConfigs', wizardStep7Controller.get('recommendationsConfigs'));
-        App.set('router.nextBtnClickInProgress', false);
         router.transitionTo('step8');
         console.timeEnd('step7 next');
       }
     }
   }),
 
-  step8: Em.Route.extend({
+  step8: App.StepRoute.extend({
     route: '/step8',
     connectOutlets: function (router, context) {
       console.time('step8 connectOutlets');
@@ -431,15 +438,15 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
         console.timeEnd('step8 connectOutlets');
       });
     },
-    back: function (router) {
-      if(router.get('wizardStep8Controller.isBackBtnDisabled') == false){
+    backTransition: function (router) {
+      if(router.get('wizardStep8Controller.isBackBtnDisabled') == false) {
         router.transitionTo('step7');
       }
     },
     next: function (router) {
       console.time('step8 next');
-      if (!router.transitionInProgress) {
-        router.set('transitionInProgress', true);
+      if (!router.get('btnClickInProgress')) {
+        App.set('router.nextBtnClickInProgress', true);
         var installerController = router.get('installerController');
         var wizardStep8Controller = router.get('wizardStep8Controller');
         // invoke API call to install selected services
@@ -448,7 +455,6 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
           // We need to do recovery based on whether we are in Add Host or Installer wizard
           installerController.saveClusterState('CLUSTER_INSTALLING_3');
           wizardStep8Controller.set('servicesInstalled', true);
-          router.set('nextBtnClickInProgress', false);
           router.transitionTo('step9');
           console.timeEnd('step8 next');
         });
@@ -506,8 +512,8 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
     },
     next: function (router) {
       console.time('step9 next');
-      if(!router.transitionInProgress) {
-        router.set('transitionInProgress', true);
+      if(!router.get('btnClickInProgress')) {
+        App.set('router.nextBtnClickInProgress', true);
         var installerController = router.get('installerController');
         var wizardStep9Controller = router.get('wizardStep9Controller');
         installerController.saveInstalledHosts(wizardStep9Controller);

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/templates/common/assign_master_components.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/assign_master_components.hbs b/ambari-web/app/templates/common/assign_master_components.hbs
index fcdb87f..54aedd5 100644
--- a/ambari-web/app/templates/common/assign_master_components.hbs
+++ b/ambari-web/app/templates/common/assign_master_components.hbs
@@ -141,14 +141,19 @@
   {{/if}}
   <div class="btn-area">
     {{#if view.isBackButtonVisible}}
-      <a class="btn pull-left installer-back-btn" {{action back}}>&larr; {{t common.back}}</a>
+      <button type="button" class="btn pull-left installer-back-btn" {{bindAttr disabled="App.router.btnClickInProgress"}} {{action back}}>
+        &larr; {{t common.back}}
+        {{#if App.router.backBtnClickInProgress}}
+          {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+        {{/if}}
+      </button>
     {{/if}}
-    <a class="btn btn-success pull-right" {{bindAttr disabled="submitDisabled"}} {{action submit target="controller"}}>
+    <button type="button" class="btn btn-success pull-right" {{bindAttr disabled="App.router.btnClickInProgress"}} {{action submit target="controller"}}>
       {{#if App.router.nextBtnClickInProgress}}
         {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
       {{/if}}
       {{view.acceptButtonText}}
-    </a>
+    </button>
     {{#if view.isCancelButtonVisible}}
       <a class="btn pull-right mrm" {{action onCancel target="controller"}}>{{t common.cancel}}</a>
     {{/if}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/templates/main/host/addHost/step4.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/host/addHost/step4.hbs b/ambari-web/app/templates/main/host/addHost/step4.hbs
index 8bad634..132d10b 100644
--- a/ambari-web/app/templates/main/host/addHost/step4.hbs
+++ b/ambari-web/app/templates/main/host/addHost/step4.hbs
@@ -45,7 +45,17 @@
       </table>
   </div>
    <div class="btn-area">
-      <a class="btn" {{action back}}>&larr; {{t common.back}}</a>
-      <a class="btn btn-success pull-right" {{action next}}>{{t common.next}} &rarr;</a>
+      <button class="btn" {{bindAttr disabled="App.router.btnClickInProgress"}} {{action back}}>
+        &larr; {{t common.back}}
+        {{#if App.router.backBtnClickInProgress}}
+          {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+        {{/if}}
+      </button>
+      <button class="btn btn-success pull-right" {{bindAttr disabled="App.router.btnClickInProgress"}} {{action next}}>
+        {{#if App.router.nextBtnClickInProgress}}
+          {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+        {{/if}}
+        {{t common.next}} &rarr;
+      </button>
     </div>
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/templates/wizard/step0.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step0.hbs b/ambari-web/app/templates/wizard/step0.hbs
index 4971969..4b1cc49 100644
--- a/ambari-web/app/templates/wizard/step0.hbs
+++ b/ambari-web/app/templates/wizard/step0.hbs
@@ -35,7 +35,12 @@
   </div>
 
   <div class="btn-area">
-    <a class="btn btn-success pull-right" {{bindAttr disabled="invalidClusterName"}} {{action "submit" target="controller"}}>{{t common.next}} &rarr;</a>
+    <button type="button" class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action "submit" target="controller"}}>
+      {{#if App.router.nextBtnClickInProgress}}
+        {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+      {{/if}}
+      {{t common.next}} &rarr;
+    </button>
   </div>
 </div>
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/templates/wizard/step1.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step1.hbs b/ambari-web/app/templates/wizard/step1.hbs
index a7636c1..72a2099 100644
--- a/ambari-web/app/templates/wizard/step1.hbs
+++ b/ambari-web/app/templates/wizard/step1.hbs
@@ -213,6 +213,16 @@
       <a href="javascript:void(null)" {{action "retryRepoUrls" target="view"}}>{{t installer.step1.retryRepoUrls}}</a>
     </div>
   {{/if}}
-  <a class="btn pull-left installer-back-btn" {{action back}}>&larr; {{t common.back}}</a>
-  <button class="btn btn-success pull-right" {{bindAttr disabled="view.isSubmitDisabled"}} {{action next}}>{{t common.next}} &rarr;</button>
+  <button type="button" class="btn pull-left installer-back-btn" {{bindAttr disabled="App.router.btnClickInProgress"}} {{action back}}>
+    &larr; {{t common.back}}
+    {{#if App.router.backBtnClickInProgress}}
+      {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+    {{/if}}
+  </button>
+  <button type="button" class="btn btn-success pull-right" {{bindAttr disabled="view.isSubmitDisabled"}} {{action next}}>
+    {{#if App.router.nextBtnClickInProgress}}
+      {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+    {{/if}}
+    {{t common.next}} &rarr;
+  </button>
 </div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/templates/wizard/step10.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step10.hbs b/ambari-web/app/templates/wizard/step10.hbs
index 6a28f05..f2caf9c 100644
--- a/ambari-web/app/templates/wizard/step10.hbs
+++ b/ambari-web/app/templates/wizard/step10.hbs
@@ -49,6 +49,11 @@
     </ul>
   </div>
   <div class="btn-area">
-    <a class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action complete}}>{{t common.complete}} &rarr;</a>
+    <button type="button" class="btn btn-success pull-right" {{bindAttr disabled="App.router.btnClickInProgress"}} {{action complete}}>
+      {{#if App.router.nextBtnClickInProgress}}
+        {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+      {{/if}}
+      {{t common.complete}} &rarr;
+    </button>
   </div>
 </div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/templates/wizard/step2.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step2.hbs b/ambari-web/app/templates/wizard/step2.hbs
index 5aa4f89..790d23d 100644
--- a/ambari-web/app/templates/wizard/step2.hbs
+++ b/ambari-web/app/templates/wizard/step2.hbs
@@ -145,10 +145,19 @@
 
   <div class="btn-area">
     {{#unless view.parentView.controller.hideBackButton}}
-      <a class="btn pull-left installer-back-btn" {{action back}}>&larr; {{t common.back}}</a>
+      <a class="btn pull-left installer-back-btn" {{action back}} {{bindAttr disabled="App.router.btnClickInProgress"}}>
+        &larr; {{t common.back}}
+        {{#if App.router.backBtnClickInProgress}}
+          {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+        {{/if}}
+      </a>
     {{/unless}}
     <a class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action evaluateStep target="controller"}}>
-      {{t installer.step2.registerAndConfirm}} &rarr;</a>
+      {{#if App.router.nextBtnClickInProgress}}
+        {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+      {{/if}}
+      {{t installer.step2.registerAndConfirm}} &rarr;
+    </a>
   </div>
 
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/templates/wizard/step3.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step3.hbs b/ambari-web/app/templates/wizard/step3.hbs
index d19943d..f4108cd 100644
--- a/ambari-web/app/templates/wizard/step3.hbs
+++ b/ambari-web/app/templates/wizard/step3.hbs
@@ -148,7 +148,17 @@
     {{/unless}}
   </div>
   <div class="btn-area">
-    <button class="btn pull-left installer-back-btn" {{bindAttr disabled="isBackDisabled"}} {{action back}}>&larr; {{t common.back}}</button>
-    <button class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>{{t common.next}} &rarr;</button>
+    <button type="button" class="btn pull-left installer-back-btn" {{bindAttr disabled="isBackDisabled"}} {{action back}}>
+      &larr; {{t common.back}}
+      {{#if App.router.backBtnClickInProgress}}
+        {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+      {{/if}}
+    </button>
+    <button type="button" class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>
+      {{#if App.router.nextBtnClickInProgress}}
+        {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+      {{/if}}
+      {{t common.next}} &rarr;
+    </button>
   </div>
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/templates/wizard/step4.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step4.hbs b/ambari-web/app/templates/wizard/step4.hbs
index 0d4d0e7..c62d369 100644
--- a/ambari-web/app/templates/wizard/step4.hbs
+++ b/ambari-web/app/templates/wizard/step4.hbs
@@ -50,13 +50,18 @@
 
   <div class="btn-area">
     {{#unless view.parentView.controller.hideBackButton}}
-      <a class="btn pull-left installer-back-btn" {{action back}}>&larr; {{t common.back}}</a>
+      <button type="button" class="btn pull-left installer-back-btn" {{bindAttr disabled="App.router.btnClickInProgress"}} {{action back}}>
+        &larr; {{t common.back}}
+        {{#if App.router.backBtnClickInProgress}}
+          {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+        {{/if}}
+      </button>
     {{/unless}}
-    <a class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>
+    <button type="button" class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>
       {{#if App.router.nextBtnClickInProgress}}
         {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
       {{/if}}
       {{t common.next}} &rarr;
-    </a>
+    </button>
   </div>
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/templates/wizard/step6.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step6.hbs b/ambari-web/app/templates/wizard/step6.hbs
index 4ed5ace..126c9a6 100644
--- a/ambari-web/app/templates/wizard/step6.hbs
+++ b/ambari-web/app/templates/wizard/step6.hbs
@@ -94,12 +94,17 @@
     </div>
   </div>
   <div class="btn-area">
-    <a class="btn installer-back-btn" {{action back}}>&larr; {{t common.back}}</a>
-    <a class="btn btn-success pull-right" {{bindAttr disabled="submitDisabled"}} {{action next}}>
+    <button type="button" class="btn installer-back-btn" {{bindAttr disabled="App.router.btnClickInProgress"}} {{action back}}>
+      &larr; {{t common.back}}
+      {{#if App.router.backBtnClickInProgress}}
+        {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+      {{/if}}
+    </button>
+    <button type="button" class="btn btn-success pull-right" {{bindAttr disabled="submitDisabled"}} {{action next}}>
       {{#if App.router.nextBtnClickInProgress}}
         {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
       {{/if}}
       {{t common.next}} &rarr;
-    </a>
+    </button>
   </div>
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/templates/wizard/step7.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step7.hbs b/ambari-web/app/templates/wizard/step7.hbs
index d43cc2c..f6d640b 100644
--- a/ambari-web/app/templates/wizard/step7.hbs
+++ b/ambari-web/app/templates/wizard/step7.hbs
@@ -31,17 +31,22 @@
 
 
   <div class="btn-area">
-    <a class="btn installer-back-btn" {{action back}}>&larr; {{t common.back}}</a>
+    <button type="button" class="btn installer-back-btn" {{bindAttr disabled="App.router.btnClickInProgress"}} {{action back}}>
+      &larr; {{t common.back}}
+      {{#if App.router.backBtnClickInProgress}}
+        {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+      {{/if}}
+    </button>
     <div class="pull-right">
       {{#if App.supports.preInstallChecks}}
         <a class="btn" {{action runPreInstallChecks target="App.router.preInstallChecksController"}} {{bindAttr disabled="isSubmitDisabled"}}><i class="icon-exclamation"></i> {{t installer.step7.preInstallChecks}}</a>
       {{/if}}
-      <a class="btn btn-success" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>
+      <button type="button" class="btn btn-success" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>
         {{#if App.router.nextBtnClickInProgress}}
           {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
         {{/if}}
         {{t common.next}} &rarr;
-      </a>
+      </button>
     </div>
   </div>
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/templates/wizard/step8.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step8.hbs b/ambari-web/app/templates/wizard/step8.hbs
index 856ddeb..caa2e28 100644
--- a/ambari-web/app/templates/wizard/step8.hbs
+++ b/ambari-web/app/templates/wizard/step8.hbs
@@ -78,10 +78,20 @@
     </div>
   </div>
   <div class="btn-area">
-    <a class="btn pull-left installer-back-btn" {{bindAttr disabled="controller.isBackBtnDisabled"}} {{action back}}>&larr; {{t common.back}}</a>
-    <a class="btn btn-success pull-right"
-       id="spinner" {{bindAttr disabled="controller.isSubmitDisabled"}} {{action submit target="controller"}}>{{t common.deploy}} &rarr;</a>
-    <a class="btn btn-info pull-right" {{action printReview target="view"}}>{{t common.print}}</a>
-    <a {{bindAttr class=":btn :btn-primary :pull-right :mrm controller.showDownloadCsv::hide"}} {{action downloadCSV target="controller"}}>{{t admin.kerberos.wizard.step5.downloadCSV}}</a>
+    <button type="button" class="btn pull-left installer-back-btn" {{bindAttr disabled="App.router.btnClickInProgress"}} {{action back}}>
+      &larr; {{t common.back}}
+      {{#if App.router.backBtnClickInProgress}}
+        {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+      {{/if}}
+    </button>
+    <button type="button" class="btn btn-success pull-right"
+       id="spinner" {{bindAttr disabled="controller.isSubmitDisabled"}} {{action submit target="controller"}}>
+      {{#if App.router.nextBtnClickInProgress}}
+        {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+      {{/if}}
+      {{t common.deploy}} &rarr;
+    </button>
+    <button type="button" class="btn btn-info pull-right" {{action printReview target="view"}}>{{t common.print}}</button>
+    <button type="button" {{bindAttr class=":btn :btn-primary :pull-right :mrm controller.showDownloadCsv::hide"}} {{action downloadCSV target="controller"}}>{{t admin.kerberos.wizard.step5.downloadCSV}}</button>
   </div>
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/templates/wizard/step9.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step9.hbs b/ambari-web/app/templates/wizard/step9.hbs
index e65d4e1..9385df7 100644
--- a/ambari-web/app/templates/wizard/step9.hbs
+++ b/ambari-web/app/templates/wizard/step9.hbs
@@ -136,8 +136,12 @@
       </p>
     {{/if}}
     <div class="btn-area">
-      <button
-          class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>{{t common.next}} &rarr;</button>
+      <button class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>
+        {{#if App.router.nextBtnClickInProgress}}
+          {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+        {{/if}}
+        {{t common.next}} &rarr;
+      </button>
     </div>
   </div>
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/views/wizard/step1_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/wizard/step1_view.js b/ambari-web/app/views/wizard/step1_view.js
index 19be3bc..503d5ef 100644
--- a/ambari-web/app/views/wizard/step1_view.js
+++ b/ambari-web/app/views/wizard/step1_view.js
@@ -69,7 +69,7 @@ App.WizardStep1View = Em.View.extend({
    *
    * @type {bool}
    */
-  isSubmitDisabled: Em.computed.or('invalidFormatUrlExist', 'isNoOsChecked', 'controller.content.isCheckInProgress'),
+  isSubmitDisabled: Em.computed.or('invalidFormatUrlExist', 'isNoOsChecked', 'controller.content.isCheckInProgress', 'App.router.btnClickInProgress'),
 
   /**
    * Onclick handler for recheck repos urls. Used in Advanced Repository Options.

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/views/wizard/step4_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/wizard/step4_view.js b/ambari-web/app/views/wizard/step4_view.js
index b24c89d..137b9f5 100644
--- a/ambari-web/app/views/wizard/step4_view.js
+++ b/ambari-web/app/views/wizard/step4_view.js
@@ -21,9 +21,6 @@ var App = require('app');
 
 App.WizardStep4View = Em.View.extend({
 
-  templateName: require('templates/wizard/step4'),
-
-  didInsertElement: function () {
-  }
+  templateName: require('templates/wizard/step4')
 
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/app/views/wizard/step7_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/wizard/step7_view.js b/ambari-web/app/views/wizard/step7_view.js
index b7e2934..a715912 100644
--- a/ambari-web/app/views/wizard/step7_view.js
+++ b/ambari-web/app/views/wizard/step7_view.js
@@ -20,8 +20,7 @@
 var App = require('app');
 
 App.WizardStep7View = Em.View.extend({
-  templateName: require('templates/wizard/step7'),
 
-  didInsertElement: function () {
-  }
+  templateName: require('templates/wizard/step7')
+
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/test/controllers/wizard/step0_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/wizard/step0_test.js b/ambari-web/test/controllers/wizard/step0_test.js
index 336f445..53fea69 100644
--- a/ambari-web/test/controllers/wizard/step0_test.js
+++ b/ambari-web/test/controllers/wizard/step0_test.js
@@ -27,13 +27,13 @@ describe('App.WizardStep0Controller', function () {
     wizardStep0Controller = App.WizardStep0Controller.create({content: {cluster: {}}});
     sinon.stub(App.clusterStatus, 'set', Em.K);
     sinon.stub(App.router, 'send', Em.K);
-    App.router.nextBtnClickInProgress = false;
+    App.set('router.nextBtnClickInProgress', false);
   });
 
   afterEach(function() {
     App.clusterStatus.set.restore();
     App.router.send.restore();
-    App.router.nextBtnClickInProgress = false;
+    App.set('router.nextBtnClickInProgress', false);
   });
 
   describe('#invalidClusterName', function () {

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/test/controllers/wizard/step2_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/wizard/step2_test.js b/ambari-web/test/controllers/wizard/step2_test.js
index 6e6ad25..c1614b9 100644
--- a/ambari-web/test/controllers/wizard/step2_test.js
+++ b/ambari-web/test/controllers/wizard/step2_test.js
@@ -74,7 +74,7 @@ describe('App.WizardStep2Controller', function () {
 
   App.TestAliases.testAsComputedAlias(getController(), 'agentUser', 'content.installOptions.agentUser', 'string');
 
-  App.TestAliases.testAsComputedOr(getController(), 'isSubmitDisabled', ['hostsError', 'sshKeyError', 'sshUserError', 'sshPortError', 'agentUserError']);
+  App.TestAliases.testAsComputedOr(getController(), 'isSubmitDisabled', ['hostsError', 'sshKeyError', 'sshUserError', 'sshPortError', 'agentUserError', 'App.router.btnClickInProgress']);
 
   describe('#hostNames', function() {
     it('should be equal to content.installOptions.hostNames', function() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/test/controllers/wizard/step3_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/wizard/step3_test.js b/ambari-web/test/controllers/wizard/step3_test.js
index a214656..92b607d 100644
--- a/ambari-web/test/controllers/wizard/step3_test.js
+++ b/ambari-web/test/controllers/wizard/step3_test.js
@@ -42,14 +42,14 @@ describe('App.WizardStep3Controller', function () {
     sinon.stub(App.db, 'getDisplayLength', Em.K);
     sinon.stub(App.db, 'getFilterConditions').returns([]);
     sinon.stub(App.router, 'send', Em.K);
-    App.router.nextBtnClickInProgress = false;
+    App.set('router.nextBtnClickInProgress', false);
   });
 
   afterEach(function () {
     App.db.getDisplayLength.restore();
     App.router.send.restore();
     App.db.getFilterConditions.restore();
-    App.router.nextBtnClickInProgress = false;
+    App.set('router.nextBtnClickInProgress', false);
   });
 
   App.TestAliases.testAsComputedGt(getController(), 'isHostHaveWarnings', 'warnings.length', 0);
@@ -1068,19 +1068,6 @@ describe('App.WizardStep3Controller', function () {
       expect(c.get('confirmedHosts')).to.eql(bootHosts);
     });
 
-    it('if Next button is clicked multiple times before the next step renders, it must not be processed',function(){
-      var bootHosts = [
-        Em.Object.create({name: 'c1'})
-      ];
-      c.reopen({isHostHaveWarnings: false, bootHosts: bootHosts, hosts: []});
-      c.submit();
-      expect(App.router.send.calledWith('next')).to.equal(true);
-
-      App.router.send.reset();
-      c.submit();
-      expect(App.router.send.calledWith('next')).to.equal(false);
-    });
-
   });
 
   describe('#hostLogPopup', function () {

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/test/controllers/wizard/step4_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/wizard/step4_test.js b/ambari-web/test/controllers/wizard/step4_test.js
index 3bb6fb5..13532e7 100644
--- a/ambari-web/test/controllers/wizard/step4_test.js
+++ b/ambari-web/test/controllers/wizard/step4_test.js
@@ -573,27 +573,6 @@ describe('App.WizardStep4Controller', function () {
     })
   });
 
-  describe('#submit for  Next click', function() {
-    var c;
-    beforeEach(function(){
-      c = App.WizardStep4Controller.create();
-      sinon.stub(App.router, 'send', Em.K);
-      App.router.nextBtnClickInProgress = false;
-    });
-    afterEach(function(){
-      App.router.nextBtnClickInProgress = false;
-      App.router.send.restore();
-    });
-    it('if Next button is clicked multiple times before the next step renders, it must not be processed',function(){
-      c.reopen({isSubmitDisabled:false});
-      c.submit();
-      expect(App.router.send.calledWith('next')).to.equal(true);
-
-      App.router.send.reset();
-      c.submit();
-      expect(App.router.send.calledWith('next')).to.equal(false);
-    });
-  });
   describe('#dependencies', function() {
     var tests = [
       {

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/test/controllers/wizard/step5_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/wizard/step5_test.js b/ambari-web/test/controllers/wizard/step5_test.js
index a1ecbce..821a709 100644
--- a/ambari-web/test/controllers/wizard/step5_test.js
+++ b/ambari-web/test/controllers/wizard/step5_test.js
@@ -26,12 +26,12 @@ describe('App.WizardStep5Controller', function () {
   beforeEach(function () {
     c = App.WizardStep5Controller.create();
     sinon.stub(App.router, 'send', Em.K);
-    App.router.nextBtnClickInProgress = false;
+    App.set('router.nextBtnClickInProgress', false);
   });
 
   afterEach(function () {
     App.router.send.restore();
-    App.router.nextBtnClickInProgress = false;
+    App.set('router.nextBtnClickInProgress', false);
   });
 
   var controller = App.WizardStep5Controller.create();
@@ -1282,17 +1282,4 @@ describe('App.WizardStep5Controller', function () {
 
   });
 
-  describe('#submit',function(){
-    it('if Next button is clicked multiple times before the next step renders, it must not be processed',function(){
-      c.reopen({isSubmitDisabled:false, submitDisabled:false, useServerValidation:false});
-      c.submit();
-      expect(App.router.send.calledWith('next')).to.equal(true);
-
-      App.router.send.reset();
-      c.submit();
-      expect(App.router.send.calledWith('next')).to.equal(false);
-
-    });
-  });
-
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/test/controllers/wizard/step7_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/wizard/step7_test.js b/ambari-web/test/controllers/wizard/step7_test.js
index 0668381..d43e18d 100644
--- a/ambari-web/test/controllers/wizard/step7_test.js
+++ b/ambari-web/test/controllers/wizard/step7_test.js
@@ -111,11 +111,11 @@ describe('App.InstallerStep7Controller', function () {
   beforeEach(function () {
     sinon.stub(App.config, 'setPreDefinedServiceConfigs', Em.K);
     installerStep7Controller = getController();
-    App.router.nextBtnClickInProgress = false;
+    App.set('router.nextBtnClickInProgress', false);
   });
 
   afterEach(function() {
-    App.router.nextBtnClickInProgress = false;
+    App.set('router.nextBtnClickInProgress', false);
     App.config.setPreDefinedServiceConfigs.restore();
     installerStep7Controller.destroy();
   });

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/test/router_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/router_test.js b/ambari-web/test/router_test.js
index 1b1ee51..e17c9e2 100644
--- a/ambari-web/test/router_test.js
+++ b/ambari-web/test/router_test.js
@@ -86,11 +86,11 @@ describe('App.Router', function () {
 
   });
 
-  describe('#adminViewInfoSuccessCallback', function() {
-    beforeEach(function() {
+  describe('#adminViewInfoSuccessCallback', function () {
+    beforeEach(function () {
       sinon.stub(window.location, 'replace', Em.K);
     });
-    afterEach(function() {
+    afterEach(function () {
       window.location.replace.restore();
     });
 
@@ -135,7 +135,7 @@ describe('App.Router', function () {
       expected: '/views/ADMIN_VIEW/2.1.0/INSTANCE/#/'
     }];
 
-    tests.forEach(function(data, index) {
+    tests.forEach(function (data, index) {
       it('should redirect to the latest version of admin view ("' + data.expected + '") #' + (index + 1), function () {
         router.adminViewInfoSuccessCallback(data.mockData);
         expect(window.location.replace.calledWith(data.expected)).to.be.true;
@@ -143,46 +143,46 @@ describe('App.Router', function () {
     });
   });
 
-  describe.skip("#savePreferedPath()", function() {
+  describe.skip("#savePreferedPath()", function () {
     beforeEach(function () {
       router.set('preferedPath', null);
     });
-    it("has no key", function() {
+    it("has no key", function () {
       router.savePreferedPath('path');
       expect(router.get('preferedPath')).to.equal('path');
     });
-    it("path does not contain key", function() {
+    it("path does not contain key", function () {
       router.savePreferedPath('path', 'key');
       expect(router.get('preferedPath')).to.be.null;
     });
-    it("path contains key", function() {
+    it("path contains key", function () {
       router.savePreferedPath('key=path', 'key=');
       expect(router.get('preferedPath')).to.equal('path');
     });
   });
 
-  describe.skip("#restorePreferedPath()", function() {
-    it("preferedPath is null", function() {
+  describe.skip("#restorePreferedPath()", function () {
+    it("preferedPath is null", function () {
       router.set('preferedPath', null);
       expect(router.restorePreferedPath()).to.be.false;
       expect(router.get('preferedPath')).to.be.null;
     });
-    it("preferedPath is '/relativeURL'", function() {
+    it("preferedPath is '/relativeURL'", function () {
       router.set('preferedPath', '/relativeURL');
       expect(router.restorePreferedPath()).to.be.true;
       expect(router.get('preferedPath')).to.be.null;
     });
-    it("preferedPath is '#/relativeURL'", function() {
+    it("preferedPath is '#/relativeURL'", function () {
       router.set('preferedPath', '#/relativeURL');
       expect(router.restorePreferedPath()).to.be.true;
       expect(router.get('preferedPath')).to.be.null;
     });
-    it("preferedPath is '#/login'", function() {
+    it("preferedPath is '#/login'", function () {
       router.set('preferedPath', '#/login');
       expect(router.restorePreferedPath()).to.be.false;
       expect(router.get('preferedPath')).to.be.null;
     });
-    it("preferedPath is 'http://absoluteURL'", function() {
+    it("preferedPath is 'http://absoluteURL'", function () {
       router.set('preferedPath', 'http://absoluteURL');
       expect(router.restorePreferedPath()).to.be.false;
       expect(router.get('preferedPath')).to.be.null;
@@ -419,7 +419,7 @@ describe('App.Router', function () {
     });
   });
 
-  describe("#getAuthenticated", function() {
+  describe("#getAuthenticated", function () {
     beforeEach(function () {
       router = App.Router.create();
       this.mockGetCurrentLocationUrl = sinon.stub(router, 'getCurrentLocationUrl');
@@ -447,7 +447,7 @@ describe('App.Router', function () {
         lastSetURL: '/main/dashboard',
         isResolved: false,
         responseData: {
-          responseText: JSON.stringify({ jwtProviderUrl: 'http://some.com?originalUrl=' }),
+          responseText: JSON.stringify({jwtProviderUrl: 'http://some.com?originalUrl='}),
           status: 403
         },
         redirectCalled: true,
@@ -457,25 +457,26 @@ describe('App.Router', function () {
         lastSetURL: '/login/local',
         isResolved: false,
         responseData: {
-          responseText: JSON.stringify({ jwtProviderUrl: 'http://some.com?originalUrl=' }),
+          responseText: JSON.stringify({jwtProviderUrl: 'http://some.com?originalUrl='}),
           status: 403
         },
         redirectCalled: false,
         m: 'jwtProviderUrl is present, current location is local login url, no redirect'
       }
-    ].forEach(function(test) {
-      describe(test.m, function() {
+    ].forEach(function (test) {
+      describe(test.m, function () {
         var mockCurrentUrl;
         beforeEach(function () {
           mockCurrentUrl = 'http://localhost:3333/#/some/hash';
           router.set('location.lastSetURL', test.lastSetURL);
           App.ajax.send.restore(); // default ajax-mock can't be used here
-          sinon.stub(App.ajax, 'send', function() {
+          sinon.stub(App.ajax, 'send', function () {
             if (!test.isResolved) {
               router.onAuthenticationError(test.responseData);
             }
             return {
-              complete: function() {}
+              complete: function () {
+              }
             };
           });
           this.mockGetCurrentLocationUrl.returns(mockCurrentUrl);
@@ -577,3 +578,95 @@ describe('App.Router', function () {
   });
 
 });
+
+describe('App.StepRoute', function () {
+
+  beforeEach(function () {
+    this.route = App.StepRoute.create();
+    this.nextTransitionSpy = sinon.spy(this.route, 'nextTransition');
+    this.backTransitionSpy = sinon.spy(this.route, 'backTransition');
+    this.appGetStub = sinon.stub(App, 'get');
+    this.appSetStub = sinon.stub(App, 'set');
+    this.runNextStub = sinon.stub(Em.run, 'next', Em.clb);
+  });
+
+  afterEach(function () {
+    this.nextTransitionSpy.restore();
+    this.backTransitionSpy.restore();
+    this.appGetStub.restore();
+    this.appSetStub.restore();
+    this.runNextStub.restore();
+  });
+
+  describe('#back', function () {
+
+    [
+      {
+        btnClickInProgress: true,
+        backBtnClickInProgressIsSet: false,
+        backTransitionIsCalled: false,
+        m: 'backTransition is not called'
+      },
+      {
+        btnClickInProgress: false,
+        backBtnClickInProgressIsSet: true,
+        backTransitionIsCalled: true,
+        m: 'backTransition is called'
+      }
+    ].forEach(function (test) {
+      describe(test.m, function () {
+
+        beforeEach(function () {
+          this.appGetStub.withArgs('router.btnClickInProgress').returns(test.btnClickInProgress);
+          this.route.back({});
+        });
+
+        it('backTransition call', function () {
+          expect(this.backTransitionSpy.called).to.be.equal(test.backTransitionIsCalled);
+        });
+
+        it('backBtnClickInProgress is set', function () {
+          expect(this.appSetStub.calledWith('router.backBtnClickInProgress')).to.be.equal(test.backBtnClickInProgressIsSet);
+        });
+
+      });
+    });
+
+  });
+
+  describe('#next', function () {
+
+    [
+      {
+        btnClickInProgress: true,
+        nextBtnClickInProgressIsSet: false,
+        nextTransitionIsCalled: false,
+        m: 'nextTransition is not called'
+      },
+      {
+        btnClickInProgress: false,
+        nextBtnClickInProgressIsSet: true,
+        nextTransitionIsCalled: true,
+        m: 'nextTransition is called'
+      }
+    ].forEach(function (test) {
+      describe(test.m, function () {
+
+        beforeEach(function () {
+          this.appGetStub.withArgs('router.btnClickInProgress').returns(test.btnClickInProgress);
+          this.route.next({});
+        });
+
+        it('nextTransition call', function () {
+          expect(this.nextTransitionSpy.called).to.be.equal(test.nextTransitionIsCalled);
+        });
+
+        it('nextBtnClickInProgress is set', function () {
+          expect(this.appSetStub.calledWith('router.nextBtnClickInProgress')).to.be.equal(test.nextBtnClickInProgressIsSet);
+        });
+
+      });
+    });
+  });
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/03e41db8/ambari-web/test/views/wizard/step1_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/wizard/step1_view_test.js b/ambari-web/test/views/wizard/step1_view_test.js
index f94720a..3621aa9 100644
--- a/ambari-web/test/views/wizard/step1_view_test.js
+++ b/ambari-web/test/views/wizard/step1_view_test.js
@@ -33,7 +33,7 @@ describe('App.WizardStep1View', function () {
 
   App.TestAliases.testAsComputedEveryBy(getView(), 'isNoOsChecked', 'controller.selectedStack.operatingSystems', 'isSelected', false);
 
-  App.TestAliases.testAsComputedOr(getView(), 'isSubmitDisabled', ['invalidFormatUrlExist', 'isNoOsChecked', 'controller.content.isCheckInProgress']);
+  App.TestAliases.testAsComputedOr(getView(), 'isSubmitDisabled', ['invalidFormatUrlExist', 'isNoOsChecked', 'controller.content.isCheckInProgress', 'App.router.btnClickInProgress']);
 
   App.TestAliases.testAsComputedSomeBy(getView(), 'invalidUrlExist', 'allRepositories', 'validation', App.Repository.validation.INVALID);