Repository: ambari
Updated Branches:
  refs/heads/trunk 4d0a5cf65 -> a13e96e75


AMBARI-20510. Oozie Database URL property was changed by itself (alexantonenko)


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

Branch: refs/heads/trunk
Commit: a13e96e755f5daf692375b15bd32767eda987b6d
Parents: 4d0a5cf
Author: Alex Antonenko <[email protected]>
Authored: Mon Mar 20 22:40:53 2017 +0200
Committer: Alex Antonenko <[email protected]>
Committed: Tue Mar 21 02:55:15 2017 +0200

----------------------------------------------------------------------
 ambari-web/app/assets/test/tests.js             |   1 +
 .../controllers/main/service/info/configs.js    |  17 +++
 ambari-web/app/mixins.js                        |   1 +
 .../mixins/common/loading_overlay_support.js    | 136 +++++++++++++++++++
 ambari-web/app/styles/application.less          |  11 ++
 ambari-web/app/styles/config_history_flow.less  |   4 +-
 .../configs/service_config_layout_tab.hbs       |   1 +
 .../configs/config_category_container_view.js   |  28 +++-
 .../configs/service_config_layout_tab_view.js   |   9 +-
 .../common/loading_overlay_support_test.js      |  96 +++++++++++++
 10 files changed, 297 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/a13e96e7/ambari-web/app/assets/test/tests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/test/tests.js 
b/ambari-web/app/assets/test/tests.js
index 8fadb44..d404d1f 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -179,6 +179,7 @@ var files = [
   'test/mixins/common/widgets/export_metrics_mixin_test',
   'test/mixins/common/widgets/time_range_mixin_test',
   'test/mixins/common/widgets/widget_section_test',
+  'test/mixins/common/loading_overlay_support_test',
   'test/mixins/common/kdc_credentials_controller_mixin_test',
   'test/mixins/common/localStorage_test',
   'test/mixins/common/reload_popup_test',

http://git-wip-us.apache.org/repos/asf/ambari/blob/a13e96e7/ambari-web/app/controllers/main/service/info/configs.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service/info/configs.js 
b/ambari-web/app/controllers/main/service/info/configs.js
index 7eae5c3..8436086 100644
--- a/ambari-web/app/controllers/main/service/info/configs.js
+++ b/ambari-web/app/controllers/main/service/info/configs.js
@@ -46,6 +46,23 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.AddSecurityConfi
   groupsStore: App.ServiceConfigGroup.find(),
 
   /**
+   * Configs tab for current service
+   *
+   * @type {App.Tab[]}
+   */
+  activeServiceTabs: function () {
+    var selectedServiceName = this.get('selectedService.serviceName');
+    return selectedServiceName ? App.Tab.find().filterProperty('serviceName', 
selectedServiceName) : [];
+  }.property('selectedService.serviceName'),
+
+  /**
+   * Currently opened configs tab
+   *
+   * @type {App.Tab}
+   */
+  activeTab: Em.computed.findBy('activeServiceTabs', 'isActive', true),
+
+  /**
    * config groups for current service
    * @type {App.ConfigGroup[]}
    */

http://git-wip-us.apache.org/repos/asf/ambari/blob/a13e96e7/ambari-web/app/mixins.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins.js b/ambari-web/app/mixins.js
index 9d833b5..4fdfa54 100644
--- a/ambari-web/app/mixins.js
+++ b/ambari-web/app/mixins.js
@@ -30,6 +30,7 @@ require('mixins/common/serverValidator');
 require('mixins/common/table_server_view_mixin');
 require('mixins/common/table_server_mixin');
 require('mixins/common/track_request_mixin');
+require('mixins/common/loading_overlay_support');
 require('mixins/main/dashboard/widgets/editable');
 require('mixins/main/dashboard/widgets/editable_with_limit');
 require('mixins/main/dashboard/widgets/single_numeric_threshold');

http://git-wip-us.apache.org/repos/asf/ambari/blob/a13e96e7/ambari-web/app/mixins/common/loading_overlay_support.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/loading_overlay_support.js 
b/ambari-web/app/mixins/common/loading_overlay_support.js
new file mode 100644
index 0000000..fd898bc
--- /dev/null
+++ b/ambari-web/app/mixins/common/loading_overlay_support.js
@@ -0,0 +1,136 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+/**
+ * This Mixin is used for views that should "wait" while some external action 
is executed (e.g., ajax-request).
+ * You should set <code>fieldToObserve</code> to fieldName which value 
determines begin and end of such action
+ * When <code>fieldToObserve</code>-value becomes truly, overlay is shown
+ * Overlay size is taken from current view size
+ *
+ * Usage:
+ *
+ * <pre>
+ *   Em.View.extend(App.LoadingOverlaySupport, {
+ *    fieldToObserve: 'someFieldName'
+ *   });
+ * </pre>
+ *
+ * Don't forget to add <code><div class="loading-overlay"></div></code> to 
your view's template
+ *
+ * @type {Em.Mixin}
+ */
+App.LoadingOverlaySupport = Em.Mixin.create({
+
+  /**
+   * @type {string}
+   */
+  fieldToObserve: '',
+
+  /**
+   * Determines if <code>handleFieldChanges</code> should be call on 
<code>didInsertElement</code>
+   *
+   * @type {boolean}
+   * @default {true}
+   */
+  handleFieldChangesOnDidInsert: true,
+
+  init() {
+    const fieldToObserve = this.get('fieldToObserve');
+    Em.assert('`fieldToObserve` should be defined', fieldToObserve);
+    this.addObserver(fieldToObserve, this, 'handleFieldChanges');
+    return this._super(...arguments);
+  },
+
+  /**
+   * Don't allow change `fieldToObserve` after view is initialized. This may 
cause a lot of errors
+   */
+  doNotChangeFieldToObserve: function () {
+    Em.assert('Do not change `fieldToObserve` after view is initialized', 
false);
+  }.observes('fieldToObserve'),
+
+  /**
+   * Value in the <code>fieldToObserve</code> may be <code>truly</code> on 
view init, so
+   * <code>handleFieldChanges</code> should be called to check this
+   *
+   * Example use case:
+   *  Switching tabs on the configs page for some service. Every tab should be 
disabled when switching on it
+   *  if needed property is set to <code>true</code>
+   *
+   * @returns {*}
+   */
+  didInsertElement() {
+    this._super(...arguments);
+    if (this.get('handleFieldChangesOnDidInsert')) {
+      this.handleFieldChanges();
+    }
+  },
+
+  /**
+   * Remove observer `handleFieldChanges`
+   */
+  willDestroyElement() {
+    const fieldToObserve = this.get('fieldToObserve');
+    this.removeObserver(fieldToObserve, this, 'handleFieldChanges');
+    this._cleanUp();
+  },
+
+  /**
+   * Show overlay when `fieldToObserve`-value is set to some truly
+   * Remove overlay otherwise
+   */
+  handleFieldChanges() {
+    const fieldToObserve = this.get('fieldToObserve');
+    const fieldValue = this.get(fieldToObserve);
+    const overlay = this.$('.loading-overlay');
+    let polling = this.get('_polling');
+    if (fieldValue) {
+      if (!polling) {
+        polling = setInterval(() => {
+          if (fieldValue && overlay) {
+            overlay.addClass('overlay-visible').css({
+              width: this.$().width(),
+              height: this.$().height()
+            });
+          }
+          else {
+            this._cleanUp();
+          }
+        }, 50);
+        this.set('_polling', polling);
+      }
+    }
+    else {
+      this._cleanUp();
+    }
+  },
+
+  /**
+   * @private
+   */
+  _cleanUp() {
+    clearInterval(this.get('_polling'));
+    this.set('_polling', null);
+    const overlay = this.$('.loading-overlay');
+    if (overlay) {
+      overlay.removeClass('overlay-visible');
+    }
+  }
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/a13e96e7/ambari-web/app/styles/application.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/application.less 
b/ambari-web/app/styles/application.less
index 7140ad7..0df1644 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -2660,3 +2660,14 @@ a.abort-icon:hover {
   padding: 4px;
   background-color: rgba(0, 0, 0, 0.6);
 }
+
+.loading-overlay {
+  background: #fff;
+  opacity: 0.3;
+  display: none;
+  position: absolute;
+  z-index: 10;
+  &.overlay-visible {
+    display: block;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/a13e96e7/ambari-web/app/styles/config_history_flow.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/config_history_flow.less 
b/ambari-web/app/styles/config_history_flow.less
index 41d23d4..d47a28c 100644
--- a/ambari-web/app/styles/config_history_flow.less
+++ b/ambari-web/app/styles/config_history_flow.less
@@ -41,7 +41,7 @@
 }
 
 .dependencies-info-bar-wrapper {
-  z-index: 3;
+  z-index: 100;
   margin: 0 0 20px;
   .alert {
     margin: 0;
@@ -191,7 +191,7 @@
   }
   .version-info-bar-wrapper {
     margin: 0;
-    z-index: 3;
+    z-index: 100;
   }
 
   .version-info-bar {

http://git-wip-us.apache.org/repos/asf/ambari/blob/a13e96e7/ambari-web/app/templates/common/configs/service_config_layout_tab.hbs
----------------------------------------------------------------------
diff --git 
a/ambari-web/app/templates/common/configs/service_config_layout_tab.hbs 
b/ambari-web/app/templates/common/configs/service_config_layout_tab.hbs
index f78952c..3709033 100644
--- a/ambari-web/app/templates/common/configs/service_config_layout_tab.hbs
+++ b/ambari-web/app/templates/common/configs/service_config_layout_tab.hbs
@@ -19,6 +19,7 @@
 {{#if view.dataIsReady}}
   {{#unless tab.isHiddenByFilter}}
   <div class="section-layout-container">
+    <div class="loading-overlay"></div>
     <table class="config-section-table">
       {{#each row in tab.sectionRows}}
         <tr>

http://git-wip-us.apache.org/repos/asf/ambari/blob/a13e96e7/ambari-web/app/views/common/configs/config_category_container_view.js
----------------------------------------------------------------------
diff --git 
a/ambari-web/app/views/common/configs/config_category_container_view.js 
b/ambari-web/app/views/common/configs/config_category_container_view.js
index 37fc10f..882b0f0 100644
--- a/ambari-web/app/views/common/configs/config_category_container_view.js
+++ b/ambari-web/app/views/common/configs/config_category_container_view.js
@@ -20,7 +20,7 @@ var App = require('app');
 
 var lazyLoading = require('utils/lazy_loading');
 
-App.ConfigCategoryContainerView = Em.ContainerView.extend({
+App.ConfigCategoryContainerView = 
Em.ContainerView.extend(App.LoadingOverlaySupport, {
 
   lazyLoading: null,
 
@@ -28,6 +28,10 @@ App.ConfigCategoryContainerView = Em.ContainerView.extend({
 
   classNames: ['accordion'],
 
+  fieldToObserve: 'controller.recommendationsInProgress',
+
+  handleFieldChangesOnDidInsert: false,
+
   didInsertElement: function () {
     this.pushViews();
     this._super();
@@ -35,16 +39,32 @@ App.ConfigCategoryContainerView = Em.ContainerView.extend({
 
   willDestroyElement: function () {
     if (this.get('lazyLoading')) {
-      lazyLoading.terminate(this.get('lazyLoading'))
+      lazyLoading.terminate(this.get('lazyLoading'));
     }
     this._super();
   },
 
+  /**
+   * extra calls for <code>handleFieldChanges</code>:
+   * <ul>
+   *  <li>child views are pushed to this (lazy loading is used)</li>
+   *  <li>tab is switched</li>
+   * </ul>
+   */
+  checkOverlay: function () {
+    this.handleFieldChanges();
+  }.observes('isLoaded', 'controller.activeTab.id', 
'controller.activeTab.isRendered'),
+
   pushViews: function () {
     var self = this;
-    var categoriesViews = [];
+    // Create view with loading-overlay. For some unknown reasons overlay 
can't be added to the container view
+    var categoriesViews = [
+      Em.View.extend({
+        template: Em.Handlebars.compile('<div class="loading-overlay"></div>')
+      }).create()
+    ];
     var categories = this.get('categories');
-    if (!categories) return false;
+    if (!categories) return;
     categories.forEach(function (category) {
       var viewClass = category.isCustomView ? category.customView : 
App.ServiceConfigsByCategoryView;
       categoriesViews.push(viewClass.create({

http://git-wip-us.apache.org/repos/asf/ambari/blob/a13e96e7/ambari-web/app/views/common/configs/service_config_layout_tab_view.js
----------------------------------------------------------------------
diff --git 
a/ambari-web/app/views/common/configs/service_config_layout_tab_view.js 
b/ambari-web/app/views/common/configs/service_config_layout_tab_view.js
index ccbb148..fad73e1 100644
--- a/ambari-web/app/views/common/configs/service_config_layout_tab_view.js
+++ b/ambari-web/app/views/common/configs/service_config_layout_tab_view.js
@@ -18,7 +18,7 @@
 
 var App = require('app');
 
-App.ServiceConfigLayoutTabView = Em.View.extend(App.ConfigOverridable, {
+App.ServiceConfigLayoutTabView = Em.View.extend(App.ConfigOverridable, 
App.LoadingOverlaySupport, {
 
   /**
    * Determines if view is editable
@@ -43,6 +43,8 @@ App.ServiceConfigLayoutTabView = 
Em.View.extend(App.ConfigOverridable, {
 
   templateName: require('templates/common/configs/service_config_layout_tab'),
 
+  fieldToObserve: 'controller.recommendationsInProgress',
+
   classNames: ['enhanced-config-tab-content'],
   /**
    * ConfigType-Widget map
@@ -71,6 +73,10 @@ App.ServiceConfigLayoutTabView = 
Em.View.extend(App.ConfigOverridable, {
     num_llap_nodes: App.NumLlapNodesWidgetMixin
   },
 
+  checkOverlay: function () {
+    this.handleFieldChanges();
+  }.observes('controller.activeTab.id', 'controller.activeTab.isRendered'),
+
   /**
    * Prepare configs for render
    * <code>subsection.configs</code> is an array of App.StackConfigProperty, 
but not App.ConfigProperty,
@@ -203,6 +209,7 @@ App.ServiceConfigLayoutTabView = 
Em.View.extend(App.ConfigOverridable, {
     }
     this.set('content.isConfigsPrepared', true);
     this.set('dataIsReady', true);
+    this._super(...arguments);
   }
 
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/a13e96e7/ambari-web/test/mixins/common/loading_overlay_support_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mixins/common/loading_overlay_support_test.js 
b/ambari-web/test/mixins/common/loading_overlay_support_test.js
new file mode 100644
index 0000000..cf53d56
--- /dev/null
+++ b/ambari-web/test/mixins/common/loading_overlay_support_test.js
@@ -0,0 +1,96 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+var view;
+
+describe('App.LoadingOverlaySupport', function () {
+
+  beforeEach(function (done) {
+    view = Em.View.extend(App.LoadingOverlaySupport, {
+      flag: false,
+      fieldToObserve: 'flag',
+      attributeBindings: ['style'],
+      style: 'height: 100px; width: 200px;',
+      template: Em.Handlebars.compile('<div class="loading-overlay"></div>'),
+      didInsertElement: function () {
+        this._super();
+        done();
+      }
+    }).create();
+    view.appendTo('#wrapper');
+    sinon.stub(window, 'setInterval', Em.clb);
+  });
+
+  afterEach(function () {
+    view.destroy();
+    window.setInterval.restore();
+  });
+
+  describe('#doNotChangeFieldToObserve', function () {
+
+    it('should throw an error', function () {
+      expect(function () {
+        view.set('fieldToObserve', 'somethingNew');
+      }).to.throw(Error, 'Do not change `fieldToObserve` after view is 
initialized');
+    });
+
+  });
+
+  describe('#handleFieldChanges', function () {
+
+    describe('overlay is shown', function () {
+
+      beforeEach(function () {
+        view.set('flag', true);
+      });
+
+      afterEach(function () {
+        view.set('flag', false);
+      });
+
+      it('should add overlay', function () {
+        
expect(view.$('.loading-overlay.overlay-visible').length).to.be.equal(1);
+      });
+
+      it('overlay width is correct', function () {
+        
expect(view.$('.loading-overlay.overlay-visible').width()).to.be.equal(200);
+      });
+
+      it('overlay height is correct', function () {
+        
expect(view.$('.loading-overlay.overlay-visible').height()).to.be.equal(100);
+      });
+
+    });
+
+    describe('overlay is hidden', function () {
+
+      it('overlay is depends of `flag`-value', function () {
+        
expect(view.$('.loading-overlay.overlay-visible').length).to.be.equal(0);
+        view.set('flag', true);
+        
expect(view.$('.loading-overlay.overlay-visible').length).to.be.equal(1);
+        view.set('flag', false);
+        
expect(view.$('.loading-overlay.overlay-visible').length).to.be.equal(0);
+      });
+
+    });
+
+  });
+
+});

Reply via email to