Repository: ambari Updated Branches: refs/heads/branch-2.4 c1c3e40b5 -> 91be87c28
AMBARI-19907 - On certain actions, there's no feedback from the UI when API takes a long time to respond (rzang) Change-Id: I220feaad9260b4316f680ef24d789d85a3cb72d0 Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/91be87c2 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/91be87c2 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/91be87c2 Branch: refs/heads/branch-2.4 Commit: 91be87c28c545b6dca198a07cd31234fd928283c Parents: c1c3e40 Author: Richard Zang <[email protected]> Authored: Mon Apr 17 17:30:34 2017 -0700 Committer: Richard Zang <[email protected]> Committed: Mon Apr 17 17:30:34 2017 -0700 ---------------------------------------------------------------------- .../main/host/bulk_operations_controller.js | 230 +++++++++++++++++-- ambari-web/app/controllers/main/host/details.js | 24 +- ambari-web/app/controllers/main/service.js | 15 +- ambari-web/app/controllers/main/service/item.js | 30 ++- ambari-web/app/utils/ajax/ajax.js | 24 +- .../app/utils/batch_scheduled_requests.js | 9 +- ambari-web/app/views/common/modal_popup.js | 9 + .../test/controllers/main/service_test.js | 6 +- 8 files changed, 299 insertions(+), 48 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/91be87c2/ambari-web/app/controllers/main/host/bulk_operations_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/host/bulk_operations_controller.js b/ambari-web/app/controllers/main/host/bulk_operations_controller.js index 09d6a52..482761f 100644 --- a/ambari-web/app/controllers/main/host/bulk_operations_controller.js +++ b/ambari-web/app/controllers/main/host/bulk_operations_controller.js @@ -249,12 +249,214 @@ App.BulkOperationsController = Em.Controller.extend({ context: operationData.message, noOpsMessage: Em.I18n.t('hosts.host.maintainance.reinstallFailedComponents.context') }, - success: 'bulkOperationForHostComponentsSuccessCallback' + success: 'bulkOperationForHostComponentsSuccessCallback', + showLoadingPopup: true }); }); }, /** + * Calling dry_run for bulk delete selected hosts + * @param {Object} operationData - data about bulk operation (action, hostComponents etc) + * @param {Ember.Enumerable} hosts - list of affected hosts + */ + bulkOperationForHostsDeleteDryRun: function (operationData, hosts) { + var self = this; + App.get('router.mainAdminKerberosController').getKDCSessionState(function () { + return App.ajax.send({ + name: 'common.hosts.delete', + sender: self, + data: { + urlParams: "/?dry_run=true", + query: 'Hosts/host_name.in(' + hosts.mapProperty('hostName').join(',') + ')', + hosts: hosts.mapProperty('hostName') + }, + success: 'bulkOperationForHostsDeleteDryRunCallback', + error: 'bulkOperationForHostsDeleteDryRunCallback', + showLoadingPopup: true + }); + }); + }, + + /** + * Show popup after dry_run for bulk delete hosts + * @method bulkOperationForHostsDeleteDryRunCallback + */ + bulkOperationForHostsDeleteDryRunCallback: function (arg0, arg1, arg2, arg3, arg4) { + var self = this; + var deletableHosts = []; + var undeletableHosts = []; + if (arg1 == "error") { + var request = arg0; + var params = arg4; + var response = JSON.parse(request.responseText); + var host = Ember.Object.create({ + error: { + key: params.hosts[0], + code: response.status, + message: response.message + }, + isCollapsed: true, + isBodyVisible: Em.computed.ifThenElse('isCollapsed', 'display: none;', 'display: block;') + }); + undeletableHosts.push(host); + } else { + var data = arg0; + var params = arg2; + if (data) { + data.deleteResult.forEach(function (host) { + if (host.deleted) { + deletableHosts.push(host); + } else { + var _host = Ember.Object.create({ + error: host.error, + isCollapsed: true, + isBodyVisible: Em.computed.ifThenElse('isCollapsed', 'display: none;', 'display: block;') + }); + undeletableHosts.push(_host); + } + }); + } else { + var host = { + deleted: { + key: params.hosts[0] + } + }; + deletableHosts.push(host); + } + } + + if (undeletableHosts.length) { + return App.ModalPopup.show({ + header: Em.I18n.t('hosts.bulkOperation.deleteHosts.dryRun.header'), + + primary: deletableHosts.length ? Em.I18n.t('hosts.bulkOperation.deleteHosts.dryRun.primary').format(deletableHosts.length) : null, + + onPrimary: function () { + this._super(); + self.bulkOperationForHostsDelete(deletableHosts); + }, + bodyClass: Em.View.extend({ + templateName: require('templates/main/host/delete_hosts_dry_run_popup'), + message: Em.I18n.t('hosts.bulkOperation.deleteHosts.dryRun.message').format(undeletableHosts.length), + undeletableHosts: undeletableHosts, + onToggleHost: function (host) { + host.contexts[0].toggleProperty('isCollapsed'); + } + }) + }); + } else if (deletableHosts.length) { + this.bulkOperationForHostsDelete(deletableHosts); + } + }, + + /** + * Bulk delete selected hosts + * @param {Ember.Enumerable} hosts - list of affected hosts + */ + bulkOperationForHostsDelete: function (hosts) { + var self = this; + App.get('router.mainAdminKerberosController').getKDCSessionState(function () { + return App.ModalPopup.show({ + header: Em.I18n.t('hosts.bulkOperation.deleteHosts.confirmation.header'), + + onPrimary: function () { + this._super(); + return App.ajax.send({ + name: 'common.hosts.delete', + sender: self, + data: { + query: 'Hosts/host_name.in(' + hosts.mapProperty('deleted.key').join(',') + ')', + hosts: hosts.mapProperty('deleted.key') + }, + success: 'bulkOperationForHostsDeleteCallback', + error: 'bulkOperationForHostsDeleteCallback', + showLoadingPopup: true + }); + }, + bodyClass: Em.View.extend({ + templateName: require('templates/main/host/delete_hosts_popup'), + hosts: hosts + }) + }); + }); + }, + + /** + * Show popup after bulk delete hosts + * @method bulkOperationForHostsDeleteCallback + */ + bulkOperationForHostsDeleteCallback: function (arg0, arg1, arg2, arg3, arg4) { + var deletedHosts = []; + var undeletableHosts = []; + if (arg1 == "error") { + var request = arg0; + var params = arg4; + var response = JSON.parse(request.responseText); + var host = Ember.Object.create({ + error: { + key: params.hosts[0], + code: response.status, + message: response.message + }, + isCollapsed: true, + isBodyVisible: Em.computed.ifThenElse('isCollapsed', 'display: none;', 'display: block;') + }); + undeletableHosts.push(host); + } else { + var data = arg0; + var params = arg2; + if (data) { + data.deleteResult.forEach(function (host) { + if (host.deleted) { + deletedHosts.push(host); + } else { + var _host = Ember.Object.create({ + error: host.error, + isCollapsed: true, + isBodyVisible: Em.computed.ifThenElse('isCollapsed', 'display: none;', 'display: block;') + }); + undeletableHosts.push(_host); + } + }); + } else { + var host = { + deleted: { + key: params.hosts[0] + } + }; + deletedHosts.push(host); + } + } + + return App.ModalPopup.show({ + header: Em.I18n.t('hosts.bulkOperation.deleteHosts.result.header'), + + secondary: null, + + bodyClass: Em.View.extend({ + templateName: require('templates/main/host/delete_hosts_result_popup'), + message: Em.I18n.t('hosts.bulkOperation.deleteHosts.dryRun.message').format(undeletableHosts.length), + undeletableHosts: undeletableHosts, + deletedHosts: deletedHosts, + onToggleHost: function (host) { + host.contexts[0].toggleProperty('isCollapsed'); + } + }), + + onPrimary: function () { + location.reload(); + this._super(); + }, + + onClose: function () { + location.reload(); + this._super(); + } + }); + }, + + /** * Bulk turn on/off passive state for selected hosts * @param {Object} operationData - data about bulk operation (action, hostComponents etc) * @param {Array} hosts - list of affected hosts @@ -421,7 +623,8 @@ App.BulkOperationsController = Em.Controller.extend({ }), context: operationData.message + ' ' + operationData.componentNameFormatted, }, - success: 'bulkOperationForHostComponentsAddSuccessCallback' + success: 'bulkOperationForHostComponentsAddSuccessCallback', + showLoadingPopup: true }); }); }, @@ -726,32 +929,23 @@ App.BulkOperationsController = Em.Controller.extend({ } if (operationData.action === 'SET_RACK_INFO') { - this.getHostsForBulkOperations(queryParams, operationData, null); + this.getHostsForBulkOperations(queryParams, operationData); return; } - var loadingPopup = App.ModalPopup.show({ - header: Em.I18n.t('jobs.loadingTasks'), - primary: false, - secondary: false, - bodyClass: Em.View.extend({ - template: Em.Handlebars.compile('{{view App.SpinnerView}}') - }) - }); - - this.getHostsForBulkOperations(queryParams, operationData, loadingPopup); + this.getHostsForBulkOperations(queryParams, operationData); }, - getHostsForBulkOperations: function (queryParams, operationData, loadingPopup) { + getHostsForBulkOperations: function (queryParams, operationData) { return App.ajax.send({ name: 'hosts.bulk.operations', sender: this, data: { parameters: App.router.get('updateController').computeParameters(queryParams), - operationData: operationData, - loadingPopup: loadingPopup + operationData: operationData }, - success: 'getHostsForBulkOperationSuccessCallback' + success: 'getHostsForBulkOperationSuccessCallback', + showLoadingPopup: true }); }, @@ -777,8 +971,6 @@ App.BulkOperationsController = Em.Controller.extend({ return; } - Em.tryInvoke(param.loadingPopup, 'hide'); - if ('SET_RACK_INFO' === operationData.action) { return self.bulkOperation(operationData, hosts); } http://git-wip-us.apache.org/repos/asf/ambari/blob/91be87c2/ambari-web/app/controllers/main/host/details.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/host/details.js b/ambari-web/app/controllers/main/host/details.js index 1364adf..48a99b4 100644 --- a/ambari-web/app/controllers/main/host/details.js +++ b/ambari-web/app/controllers/main/host/details.js @@ -154,7 +154,8 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow sender: this, data: data, success: 'sendComponentCommandSuccessCallback', - error: 'ajaxErrorCallback' + error: 'ajaxErrorCallback', + showLoadingPopup: true }); }, @@ -390,7 +391,8 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow hostName: this.get('content.hostName') }, success: '_doDeleteHostComponentSuccessCallback', - error: '_doDeleteHostComponentErrorCallback' + error: '_doDeleteHostComponentErrorCallback', + showLoadingPopup: true }).then(callback, callback); }, @@ -1221,7 +1223,8 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow resource_filters: resource_filters, context: context }, - success: 'refreshComponentConfigsSuccessCallback' + success: 'refreshComponentConfigsSuccessCallback', + showLoadingPopup: true }); }, @@ -1468,7 +1471,8 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow } }, success: 'installComponentSuccessCallback', - error: 'ajaxErrorCallback' + error: 'ajaxErrorCallback', + showLoadingPopup: true }); }) }); @@ -1574,7 +1578,8 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow slaveType: slaveType }, success: 'decommissionSuccessCallback', - error: 'decommissionErrorCallback' + error: 'decommissionErrorCallback', + showLoadingPopup: true }); }, @@ -1757,7 +1762,8 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow batches: batches }, success: 'decommissionSuccessCallback', - error: 'decommissionErrorCallback' + error: 'decommissionErrorCallback', + showLoadingPopup: true }); }, @@ -1864,7 +1870,8 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow batches: batches }, success: 'decommissionSuccessCallback', - error: 'decommissionErrorCallback' + error: 'decommissionErrorCallback', + showLoadingPopup: true }); }, @@ -2263,7 +2270,8 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow }, callback: completeCallback, success: 'deleteHostSuccessCallback', - error: 'deleteHostErrorCallback' + error: 'deleteHostErrorCallback', + showLoadingPopup: true }); } else { http://git-wip-us.apache.org/repos/asf/ambari/blob/91be87c2/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 7fe5b68..201bace 100644 --- a/ambari-web/app/controllers/main/service.js +++ b/ambari-web/app/controllers/main/service.js @@ -160,7 +160,8 @@ App.MainServiceController = Em.ArrayController.extend({ query: query }, success: 'allServicesCallSuccessCallback', - error: 'allServicesCallErrorCallback' + error: 'allServicesCallErrorCallback', + showLoadingPopup: true }); }, @@ -185,7 +186,8 @@ App.MainServiceController = Em.ArrayController.extend({ state: 'INSTALLED' } }, - success: 'silentStopSuccess' + success: 'silentStopSuccess', + showLoadingPopup: true }); }, @@ -235,7 +237,8 @@ App.MainServiceController = Em.ArrayController.extend({ state: 'STARTED' } }, - success: 'silentCallSuccessCallback' + success: 'silentCallSuccessCallback', + showLoadingPopup: true }); } }.observes('shouldStart', 'controllers.backgroundOperationsController.allOperationsCount'), @@ -369,7 +372,8 @@ App.MainServiceController = Em.ArrayController.extend({ tolerateSize: 0, batches: batches }, - success: 'restartAllRequiredSuccessCallback' + success: 'restartAllRequiredSuccessCallback', + showLoadingPopup: true }); } else { App.ajax.send({ @@ -378,7 +382,8 @@ App.MainServiceController = Em.ArrayController.extend({ data: { data: ajaxData }, - success: 'restartAllRequiredSuccessCallback' + success: 'restartAllRequiredSuccessCallback', + showLoadingPopup: true }); } }, http://git-wip-us.apache.org/repos/asf/ambari/blob/91be87c2/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 6ce811d..95852c8 100644 --- a/ambari-web/app/controllers/main/service/item.js +++ b/ambari-web/app/controllers/main/service/item.js @@ -477,7 +477,8 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow 'sender': this, 'success': 'startStopPopupSuccessCallback', 'error': 'startStopPopupErrorCallback', - 'data': data + 'data': data, + 'showLoadingPopup': true }); }, @@ -533,7 +534,8 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow forceRefreshConfigTags : "capacity-scheduler" }, success : 'refreshYarnQueuesSuccessCallback', - error : 'refreshYarnQueuesErrorCallback' + error : 'refreshYarnQueuesErrorCallback', + showLoadingPopup: true }); }); }, @@ -578,7 +580,8 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow componentName: "KNOX_GATEWAY" }, success: 'startStopLdapKnoxSuccessCallback', - error: 'startStopLdapKnoxErrorCallback' + error: 'startStopLdapKnoxErrorCallback', + showLoadingPopup: true }); }); }, @@ -625,7 +628,8 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow componentName: "HIVE_SERVER_INTERACTIVE" }, success: 'requestSuccessCallback', - error: 'requestErrorCallback' + error: 'requestErrorCallback', + showLoadingPopup: true }); }, @@ -670,7 +674,8 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow batches: batches }, success: 'requestSuccessCallback', - error: 'requestErrorCallback' + error: 'requestErrorCallback', + showLoadingPopup: true }); }, @@ -722,7 +727,8 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow threshold: this.get('inputValue') }, success : 'rebalanceHdfsNodesSuccessCallback', - error : 'rebalanceHdfsNodesErrorCallback' + error : 'rebalanceHdfsNodesErrorCallback', + showLoadingPopup: true }); this.hide(); }, @@ -847,7 +853,8 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow 'sender': this, 'success':'runSmokeTestSuccessCallBack', 'error':'runSmokeTestErrorCallBack', - 'data': requestData + 'data': requestData, + showLoadingPopup: true }); }, @@ -1108,7 +1115,8 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow componentName : context.component }, success : 'executeCustomCommandSuccessCallback', - error : 'executeCustomCommandErrorCallback' + error : 'executeCustomCommandErrorCallback', + showLoadingPopup: true }); }); }, @@ -1132,7 +1140,8 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow forceRefreshConfigTags : "capacity-scheduler" }, success : 'executeCustomCommandSuccessCallback', - error : 'executeCustomCommandErrorCallback' + error : 'executeCustomCommandErrorCallback', + showLoadingPopup: true }); }); }, @@ -1556,7 +1565,8 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow servicesToDeleteNext: servicesToDeleteNext }, success : 'deleteServiceCallSuccessCallback', - error: 'deleteServiceCallErrorCallback' + error: 'deleteServiceCallErrorCallback', + showLoadingPopup: true }); }, http://git-wip-us.apache.org/repos/asf/ambari/blob/91be87c2/ambari-web/app/utils/ajax/ajax.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/ajax/ajax.js b/ambari-web/app/utils/ajax/ajax.js index 3544c19..023adde 100644 --- a/ambari-web/app/utils/ajax/ajax.js +++ b/ambari-web/app/utils/ajax/ajax.js @@ -3054,13 +3054,29 @@ var ajax = Em.Object.extend({ return null; } + var loadingPopup = null; + var loadingPopupTimeout = null; + if(config.hasOwnProperty("showLoadingPopup") && config.showLoadingPopup === true) { + loadingPopupTimeout = setTimeout(function() { + loadingPopup = App.ModalPopup.show({ + header: Em.I18n.t('jobs.loadingTasks'), + backdrop: false, + primary: false, + secondary: false, + bodyClass: Em.View.extend({ + template: Em.Handlebars.compile('{{view App.SpinnerView}}') + }) + }); + }, 500); + } + // default parameters var params = { clusterName: (App.get('clusterName') || App.clusterStatus.get('clusterName')) }; // extend default parameters with provided - if (config.data) { + if (config.hasOwnProperty("data") && config.data) { jQuery.extend(params, config.data); } @@ -3103,6 +3119,12 @@ var ajax = Em.Object.extend({ } }; opt.complete = function () { + if (loadingPopupTimeout) { + clearTimeout(loadingPopupTimeout); + } + if(loadingPopup) { + Em.tryInvoke(loadingPopup, 'hide'); + } App.logger.logTimerIfMoreThan(consoleMsg, 1000); if (config.callback) { config.callback(); http://git-wip-us.apache.org/repos/asf/ambari/blob/91be87c2/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 c9828a4..92b8e9c 100644 --- a/ambari-web/app/utils/batch_scheduled_requests.js +++ b/ambari-web/app/utils/batch_scheduled_requests.js @@ -285,7 +285,8 @@ module.exports = { query: query }, success: 'successCallback', - error: 'errorCallback' + error: 'errorCallback', + showLoadingPopup: true }); } else { App.ajax.send({ @@ -301,7 +302,8 @@ module.exports = { operation_level: operation_level }, success: 'successCallback', - error: 'errorCallback' + error: 'errorCallback', + showLoadingPopup: true }); } } @@ -376,7 +378,8 @@ module.exports = { batches: this.getBatchesForRollingRestartRequest(restartHostComponents, batchSize) }, success: 'successCallback', - error: 'errorCallback' + error: 'errorCallback', + showLoadingPopup: true }); }, http://git-wip-us.apache.org/repos/asf/ambari/blob/91be87c2/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 252604e..a095a32 100644 --- a/ambari-web/app/views/common/modal_popup.js +++ b/ambari-web/app/views/common/modal_popup.js @@ -69,11 +69,20 @@ App.ModalPopup = Ember.View.extend({ .on('enter-key-pressed', this.enterKeyPressed.bind(this)) .on('escape-key-pressed', this.escapeKeyPressed.bind(this)); this.fitZIndex(); + this.handleBackDrop(); var firstInputElement = this.$('#modal').find(':input').not(':disabled, .no-autofocus').first(); this.focusElement(firstInputElement); this.subscribeResize(); }, + handleBackDrop: function () { + if (this.get('backdrop') === false) { + $('.modal-backdrop').css('visibility', 'hidden'); + } else { + $('.modal-backdrop').css('visibility', 'visible'); + } + }, + subscribeResize: function() { if (this.get('autoHeight') && !$.mocho) { this.fitHeight(); http://git-wip-us.apache.org/repos/asf/ambari/blob/91be87c2/ambari-web/test/controllers/main/service_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/service_test.js b/ambari-web/test/controllers/main/service_test.js index 06961a1..7b6981b 100644 --- a/ambari-web/test/controllers/main/service_test.js +++ b/ambari-web/test/controllers/main/service_test.js @@ -461,7 +461,8 @@ describe('App.MainServiceController', function () { state: 'INSTALLED' } }, - success: 'silentStopSuccess' + success: 'silentStopSuccess', + showLoadingPopup: true }); }); }); @@ -597,7 +598,8 @@ describe('App.MainServiceController', function () { state: 'STARTED' } }, - success: 'silentCallSuccessCallback' + success: 'silentCallSuccessCallback', + showLoadingPopup: true }); expect(mainServiceController.get('shouldStart')).to.be.false; });
