Repository: ambari Updated Branches: refs/heads/trunk 96a953f39 -> b7f2d16a8
AMBARI-5056 Spinner needed between Restart All call to refresh configs on Service page and opening operations popup. (atkach) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/b7f2d16a Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/b7f2d16a Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/b7f2d16a Branch: refs/heads/trunk Commit: b7f2d16a8cbc83c04e379767bad77840b6e03c2c Parents: 96a953f Author: atkach <[email protected]> Authored: Wed Mar 12 21:09:34 2014 +0200 Committer: atkach <[email protected]> Committed: Wed Mar 12 21:09:34 2014 +0200 ---------------------------------------------------------------------- ambari-web/app/controllers/main/service.js | 21 +++-- ambari-web/app/controllers/main/service/item.js | 98 +++++++++++--------- ambari-web/app/messages.js | 2 + .../templates/common/confirmation_feedback.hbs | 20 ++++ ambari-web/app/templates/common/modal_popup.hbs | 4 +- ambari-web/app/utils/ajax.js | 2 +- .../app/utils/batch_scheduled_requests.js | 15 +-- ambari-web/app/views/common/modal_popup.js | 49 ++++++++++ 8 files changed, 147 insertions(+), 64 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/b7f2d16a/ambari-web/app/controllers/main/service.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/service.js b/ambari-web/app/controllers/main/service.js index 5b019e4..d92a3c7 100644 --- a/ambari-web/app/controllers/main/service.js +++ b/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() { http://git-wip-us.apache.org/repos/asf/ambari/blob/b7f2d16a/ambari-web/app/controllers/main/service/item.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/service/item.js b/ambari-web/app/controllers/main/service/item.js index b212a96..0c48f61 100644 --- a/ambari-web/app/controllers/main/service/item.js +++ b/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); }); } }, http://git-wip-us.apache.org/repos/asf/ambari/blob/b7f2d16a/ambari-web/app/messages.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js index 838ce43..a78511d 100644 --- a/ambari-web/app/messages.js +++ b/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.', http://git-wip-us.apache.org/repos/asf/ambari/blob/b7f2d16a/ambari-web/app/templates/common/confirmation_feedback.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/common/confirmation_feedback.hbs b/ambari-web/app/templates/common/confirmation_feedback.hbs new file mode 100644 index 0000000..72fbb66 --- /dev/null +++ b/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> http://git-wip-us.apache.org/repos/asf/ambari/blob/b7f2d16a/ambari-web/app/templates/common/modal_popup.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/common/modal_popup.hbs b/ambari-web/app/templates/common/modal_popup.hbs index 1d7a0f8..a3c1b2c 100644 --- a/ambari-web/app/templates/common/modal_popup.hbs +++ b/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}} http://git-wip-us.apache.org/repos/asf/ambari/blob/b7f2d16a/ambari-web/app/utils/ajax.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/ajax.js b/ambari-web/app/utils/ajax.js index f3528aa..6bed45b 100644 --- a/ambari-web/app/utils/ajax.js +++ b/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); } http://git-wip-us.apache.org/repos/asf/ambari/blob/b7f2d16a/ambari-web/app/utils/batch_scheduled_requests.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/batch_scheduled_requests.js b/ambari-web/app/utils/batch_scheduled_requests.js index d7483d9..da7de43 100644 --- a/ambari-web/app/utils/batch_scheduled_requests.js +++ b/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' http://git-wip-us.apache.org/repos/asf/ambari/blob/b7f2d16a/ambari-web/app/views/common/modal_popup.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/common/modal_popup.js b/ambari-web/app/views/common/modal_popup.js index f9c944c..1789c39 100644 --- a/ambari-web/app/views/common/modal_popup.js +++ b/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(); }, @@ -138,6 +140,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 * * @param {String} header - header of the popup
