Browse Source

AMBARI-5056 Spinner needed between Restart All call to refresh configs on Service page and opening operations popup. (atkach)

atkach 11 years ago
parent
commit
b7f2d16a8c

+ 12 - 9
ambari-web/app/controllers/main/service.js

@@ -97,8 +97,8 @@ App.MainServiceController = Em.ArrayController.extend({
       return;
     }
     var self = this;
-    App.showConfirmationPopup(function() {
-      self.allServicesCall('startAllService');
+    App.showConfirmationFeedBackPopup(function(query) {
+      self.allServicesCall('startAllService', query);
     });
   },
 
@@ -110,12 +110,12 @@ App.MainServiceController = Em.ArrayController.extend({
       return;
     }
     var self = this;
-    App.showConfirmationPopup(function() {
-      self.allServicesCall('stopAllService');
+    App.showConfirmationFeedBackPopup(function(query) {
+      self.allServicesCall('stopAllService', query);
     });
   },
 
-  allServicesCall: function(state) {
+  allServicesCall: function(state, query) {
     var data;
     if (state == 'stopAllService') {
       data = '{"RequestInfo": {"context" :"' +
@@ -131,17 +131,19 @@ App.MainServiceController = Em.ArrayController.extend({
       name: 'service.start_stop',
       sender: this,
       data: {
-        data: data
+        data: data,
+        query: query
       },
       success: 'allServicesCallSuccessCallback',
       error: 'allServicesCallErrorCallback'
     });
   },
 
-  allServicesCallSuccessCallback: function(data) {
+  allServicesCallSuccessCallback: function(data, xhr, params) {
     console.log("TRACE: Start/Stop all service -> In success function for the start/stop all Service call");
     console.log("TRACE: Start/Stop all service -> value of the received data is: " + data);
     var requestId = data.Requests.id;
+    params.query.set('status', 'SUCCESS');
     console.log('requestId is: ' + requestId);
 
     // load data (if we need to show this background operations popup) from persist
@@ -151,8 +153,9 @@ App.MainServiceController = Em.ArrayController.extend({
       }
     });
   },
-  allServicesCallErrorCallback: function(xhr, textStatus, errorThrown, opt) {
-    App.ajax.defaultErrorHandler(xhr, opt.url, 'PUT', xhr.status);
+  allServicesCallErrorCallback: function(request, ajaxOptions, error, opt, params) {
+    console.log("ERROR");
+    params.query.set('status', 'FAIL');
   },
 
   gotoAddService: function() {

+ 52 - 46
ambari-web/app/controllers/main/service/item.js

@@ -45,44 +45,41 @@ App.MainServiceItemController = Em.Controller.extend({
     }
   },
   /**
-   * Success ajax response processing
+   * Common method for ajax (start/stop service) responses
    * @param data
    * @param ajaxOptions
+   * @param params
    */
-  ajaxSuccess: function(data, ajaxOptions) {
-    if(data && data.Requests) {
-      this.ajaxCallBack(data.Requests.id, (JSON.parse(ajaxOptions.data)).Body.ServiceInfo.state);
-    }
-    else {
+  startStopPopupSuccessCallback: function (data, ajaxOptions, params) {
+    if (data && data.Requests) {
+      params.query.set('status', 'SUCCESS');
+      var config = this.get('callBackConfig')[(JSON.parse(ajaxOptions.data)).Body.ServiceInfo.state];
+      var self = this;
+      console.log('Send request for ' + config.c + ' successfully');
+      if (App.testMode) {
+        self.set('content.workStatus', App.Service.Health[config.f]);
+        self.get('content.hostComponents').setEach('workStatus', App.HostComponentStatus[config.f]);
+        setTimeout(function () {
+          self.set('content.workStatus', App.Service.Health[config.c2]);
+          self.get('content.hostComponents').setEach('workStatus', App.HostComponentStatus[config.hs]);
+        }, App.testModeDelayForActions);
+      }
+      else {
+        App.router.get('clusterController').loadUpdatedStatusDelayed(500);// @todo check working without param 500
+      }
+      // load data (if we need to show this background operations popup) from persist
+      App.router.get('applicationController').dataLoading().done(function (initValue) {
+        if (initValue) {
+          App.router.get('backgroundOperationsController').showPopup();
+        }
+      });
+    } else {
+      params.query.set('status', 'FAIL');
       console.log('cannot get request id from ', data);
     }
   },
-  /**
-   * Common method for ajax (start/stop service) responses
-   * @param requestId
-   * @param serviceHealth
-   */
-  ajaxCallBack: function(requestId, serviceHealth) {
-    var config = this.get('callBackConfig')[serviceHealth];
-    var self = this;
-    console.log('Send request for ' + config.c + ' successfully');
-    if (App.testMode) {
-      self.set('content.workStatus', App.Service.Health[config.f]);
-      self.get('content.hostComponents').setEach('workStatus', App.HostComponentStatus[config.f]);
-      setTimeout(function () {
-        self.set('content.workStatus', App.Service.Health[config.c2]);
-        self.get('content.hostComponents').setEach('workStatus', App.HostComponentStatus[config.hs]);
-      }, App.testModeDelayForActions);
-    }
-    else {
-      App.router.get('clusterController').loadUpdatedStatusDelayed(500);// @todo check working without param 500
-    }
-    // load data (if we need to show this background operations popup) from persist
-    App.router.get('applicationController').dataLoading().done(function (initValue) {
-      if (initValue) {
-        App.router.get('backgroundOperationsController').showPopup();
-      }
-    });
+  startStopPopupErrorCallback: function(request, ajaxOptions, error, opt, params){
+    params.query.set('status', 'FAIL');
   },
   /**
    * Confirmation popup for start/stop services
@@ -94,13 +91,13 @@ App.MainServiceItemController = Em.Controller.extend({
       return;
     }
     var self = this;
-    App.showConfirmationPopup(function() {
+    App.showConfirmationFeedBackPopup(function(query) {
       self.set('isPending', true);
-      self.startStopPopupPrimary(serviceHealth);
+      self.startStopPopupPrimary(serviceHealth, query);
     });
   },
 
-  startStopPopupPrimary: function (serviceHealth) {
+  startStopPopupPrimary: function (serviceHealth, query) {
     var requestInfo = "";
     if (serviceHealth == "STARTED") {
       requestInfo = App.BackgroundOperationsController.CommandContexts.START_SERVICE.format(this.get('content.serviceName'));
@@ -111,11 +108,13 @@ App.MainServiceItemController = Em.Controller.extend({
     App.ajax.send({
       'name': 'service.item.start_stop',
       'sender': this,
-      'success': 'ajaxSuccess',
+      'success': 'startStopPopupSuccessCallback',
+      'error': 'startStopPopupErrorCallback',
       'data': {
         'requestInfo': requestInfo,
         'serviceName': this.get('content.serviceName').toUpperCase(),
-        'state': serviceHealth
+        'state': serviceHealth,
+        'query': query
       }
     });
     this.set('isStopDisabled', true);
@@ -182,14 +181,14 @@ App.MainServiceItemController = Em.Controller.extend({
       App.showAlertPopup(Em.I18n.t('common.error'), Em.I18n.t('services.mapreduce2.smokeTest.requirement'));
       return;
     }
-    App.showConfirmationPopup(function() {
-      self.runSmokeTestPrimary();
+    App.showConfirmationFeedBackPopup(function(query) {
+      self.runSmokeTestPrimary(query);
     });
   },
 
   restartAllHostComponents : function(serviceName) {
-    App.showConfirmationPopup(function() {
-      batchUtils.restartAllServiceHostComponents(serviceName, false);
+    App.showConfirmationFeedBackPopup(function(query) {
+      batchUtils.restartAllServiceHostComponents(serviceName, false, query);
     });
   },
 
@@ -229,32 +228,39 @@ App.MainServiceItemController = Em.Controller.extend({
     });
   },
 
-  runSmokeTestPrimary: function() {
+  runSmokeTestPrimary: function(query) {
     App.ajax.send({
       'name': 'service.item.smoke',
       'sender': this,
       'success':'runSmokeTestSuccessCallBack',
+      'error':'runSmokeTestErrorCallBack',
       'data': {
         'serviceName': this.get('content.serviceName'),
         'displayName': this.get('content.displayName'),
-        'actionName': this.get('content.serviceName') === 'ZOOKEEPER' ? 'ZOOKEEPER_QUORUM_SERVICE_CHECK' : this.get('content.serviceName') + '_SERVICE_CHECK'
+        'actionName': this.get('content.serviceName') === 'ZOOKEEPER' ? 'ZOOKEEPER_QUORUM_SERVICE_CHECK' : this.get('content.serviceName') + '_SERVICE_CHECK',
+        'query': query
       }
     });
   },
 
-  runSmokeTestSuccessCallBack: function(data) {
+  runSmokeTestSuccessCallBack: function (data, ajaxOptions, params) {
     if (data.Requests.id) {
       // load data (if we need to show this background operations popup) from persist
       App.router.get('applicationController').dataLoading().done(function (initValue) {
         if (initValue) {
+          params.query.set('status', 'SUCCESS');
           App.router.get('backgroundOperationsController').showPopup();
         }
       });
     }
     else {
+      params.query.set('status', 'FAIL');
       console.warn('error during runSmokeTestSuccessCallBack');
     }
   },
+  runSmokeTestErrorCallBack: function (request, ajaxOptions, error, opt, params) {
+    params.query.set('status', 'FAIL');
+  },
 
   /**
    * On click callback for <code>Reassign <master component></code> button
@@ -292,8 +298,8 @@ App.MainServiceItemController = Em.Controller.extend({
   refreshConfigs: function() {
     var self = this;
     if (this.get('content.isClientsOnly')) {
-      App.showConfirmationPopup(function() {
-        batchUtils.restartHostComponents(self.get('content.hostComponents'), Em.I18n.t('rollingrestart.context.allForSelectedService').format(self.get('content.serviceName')));
+      App.showConfirmationFeedBackPopup(function(query) {
+        batchUtils.restartHostComponents(self.get('content.hostComponents'), Em.I18n.t('rollingrestart.context.allForSelectedService').format(self.get('content.serviceName')), query);
       });
     }
   },

+ 2 - 0
ambari-web/app/messages.js

@@ -239,6 +239,8 @@ Em.I18n.translations = {
   'popup.highlight':'click to highlight',
   'popup.confirmation.commonHeader':'Confirmation',
   'popup.prompt.commonHeader':'Prompt',
+  'popup.confirmationFeedBack.sending':'Sending...',
+  'popup.confirmationFeedBack.query.fail':'Request failed',
 
   'router.hadoopClusterNotSetUp':'Your administrator has not set up a Hadoop cluster yet.',
 

+ 20 - 0
ambari-web/app/templates/common/confirmation_feedback.hbs

@@ -0,0 +1,20 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div>
+  {{view.parentView.statusMessage}}
+</div>

+ 2 - 2
ambari-web/app/templates/common/modal_popup.hbs

@@ -52,10 +52,10 @@
           {{t app.settings.notShowBgOperations}}</label>
         {{/if}}
         {{#if view.secondary}}
-          <a class="btn" {{action onSecondary target="view"}}>{{view.secondary}}</a>
+          <a {{bindAttr class="view.enableSecondary::disabled :btn"}} {{action onSecondary target="view"}}>{{view.secondary}}</a>
         {{/if}}
         {{#if view.primary}}
-          <a {{bindAttr class="view.enablePrimary::disabled :btn :btn-success"}} {{action onPrimary target="view"}}>{{view.primary}}</a>
+          <a {{bindAttr class="view.enablePrimary::disabled :btn view.primaryClass"}} {{action onPrimary target="view"}}>{{view.primary}}</a>
         {{/if}}
       </div>
     {{/if}}

+ 1 - 1
ambari-web/app/utils/ajax.js

@@ -1838,7 +1838,7 @@ var ajax = Em.Object.extend({
     };
     opt.error = function (request, ajaxOptions, error) {
       if (config.error) {
-        config.sender[config.error](request, ajaxOptions, error, opt);
+        config.sender[config.error](request, ajaxOptions, error, opt, params);
       } else {
         this.defaultErrorHandler(request, opt.url, opt.type);
       }

+ 9 - 6
ambari-web/app/utils/batch_scheduled_requests.js

@@ -21,9 +21,10 @@ var App = require('app');
  * Default success callback for ajax-requests in this module
  * @type {Function}
  */
-var defaultSuccessCallback = function() {
+var defaultSuccessCallback = function(data, ajaxOptions, params) {
   App.router.get('applicationController').dataLoading().done(function(initValue) {
     if (initValue) {
+      params.query && params.query.set('status', 'SUCCESS');
       App.router.get('backgroundOperationsController').showPopup();
     }
   });
@@ -36,7 +37,8 @@ var defaultSuccessCallback = function() {
  * @param {Object} opt
  * @type {Function}
  */
-var defaultErrorCallback = function(xhr, textStatus, error, opt) {
+var defaultErrorCallback = function(xhr, textStatus, error, opt, params) {
+  params.query && params.query.set('status', 'FAIL');
   App.ajax.defaultErrorHandler(xhr, opt.url, 'POST', xhr.status);
 };
 
@@ -67,7 +69,7 @@ module.exports = {
    * @param {String} serviceName for which service hostComponents should be restarted
    * @param {bool} staleConfigsOnly restart only hostComponents with <code>staleConfig</code> true
    */
-  restartAllServiceHostComponents: function(serviceName, staleConfigsOnly) {
+  restartAllServiceHostComponents: function(serviceName, staleConfigsOnly, query) {
     var service = App.Service.find(serviceName);
     var context = staleConfigsOnly ? Em.I18n.t('rollingrestart.context.allWithStaleConfigsForSelectedService').format(serviceName) : Em.I18n.t('rollingrestart.context.allForSelectedService').format(serviceName);
     if (service) {
@@ -75,7 +77,7 @@ module.exports = {
       if (staleConfigsOnly) {
         hostComponents = hostComponents.filterProperty('staleConfigs', true);
       }
-      this.restartHostComponents(hostComponents, context);
+      this.restartHostComponents(hostComponents, context, query);
     }
   },
 
@@ -84,7 +86,7 @@ module.exports = {
    * @param {Ember.Enumerable} hostComponentsList list of host components should be restarted
    * @param {String} context message to show in BG popup
    */
-  restartHostComponents: function(hostComponentsList, context) {
+  restartHostComponents: function(hostComponentsList, context, query) {
     context = context || Em.I18n.t('rollingrestart.context.default');
     /**
      * Format: {
@@ -121,7 +123,8 @@ module.exports = {
         },
         data: {
           context: context,
-          resource_filters: resource_filters
+          resource_filters: resource_filters,
+          query: query
         },
         success: 'successCallback',
         error: 'errorCallback'

+ 49 - 0
ambari-web/app/views/common/modal_popup.js

@@ -30,6 +30,8 @@ App.ModalPopup = Ember.View.extend({
   secondary: Em.I18n.t('common.cancel'),
   autoHeight: true,
   enablePrimary: true,
+  enableSecondary: true,
+  primaryClass: 'btn-success',
   onPrimary: function () {
     this.hide();
   },
@@ -137,6 +139,53 @@ App.showConfirmationPopup = function (primary, body, secondary) {
   });
 };
 
+/**
+ * Show confirmation popup
+ * After sending command watch status of query,
+ * and in case of failure provide ability to retry to launch an operation.
+ *
+ * @param {Function} primary - "OK" button click handler
+ * @param {Function} secondary - "Cancel" button click handler
+ * @return {*}
+ */
+App.showConfirmationFeedBackPopup = function (primary, secondary) {
+  if (!primary) {
+    return false;
+  }
+  return App.ModalPopup.show({
+    header: Em.I18n.t('popup.confirmation.commonHeader'),
+    bodyClass: Em.View.extend({
+      templateName: require('templates/common/confirmation_feedback')
+    }),
+    query: Em.Object.create({status: "INIT"}),
+    onPrimary: function () {
+      this.set('query.status', "INIT");
+      this.set('enablePrimary', false);
+      this.set('enableSecondary', false);
+      this.set('statusMessage', Em.I18n.t('popup.confirmationFeedBack.sending'));
+      primary(this.get('query'));
+    },
+    statusMessage: Em.I18n.t('question.sure'),
+    watchStatus: function() {
+      if (this.get('query.status') === "SUCCESS") {
+        this.hide();
+      } else if(this.get('query.status') === "FAIL") {
+        this.set('primaryClass', 'btn-primary');
+        this.set('primary', Em.I18n.t('common.retry'));
+        this.set('enablePrimary', true);
+        this.set('enableSecondary', true);
+        this.set('statusMessage', Em.I18n.t('popup.confirmationFeedBack.query.fail'));
+      }
+    }.observes('query.status'),
+    onSecondary: function () {
+      this.hide();
+      if (secondary) {
+        secondary();
+      }
+    }
+  });
+};
+
 /**
  * Show alert popup
  *