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 2015/03/24 14:06:52 UTC

ambari git commit: AMBARI-10191. YARN configs should show slider-widgets when configured in theme (onechiporenko)

Repository: ambari
Updated Branches:
  refs/heads/trunk ed231bead -> fd5e6e682


AMBARI-10191. YARN configs should show slider-widgets when configured in theme (onechiporenko)


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

Branch: refs/heads/trunk
Commit: fd5e6e6823cec08ef3334286924e964638c9fa16
Parents: ed231be
Author: Oleg Nechiporenko <on...@apache.org>
Authored: Tue Mar 24 14:59:18 2015 +0200
Committer: Oleg Nechiporenko <on...@apache.org>
Committed: Tue Mar 24 14:59:18 2015 +0200

----------------------------------------------------------------------
 .../controllers/main/service/info/configs.js    |  7 +-
 ambari-web/app/styles/widgets.less              |  9 +--
 .../configs/service_config_layout_tab.hbs       | 10 ++-
 .../configs/widgets/slider_config_widget.hbs    | 34 +++++----
 .../configs/service_config_layout_tab_view.js   | 48 ++++++++++++-
 .../widgets/slider_config_widget_view.js        | 76 +++++++++++++++-----
 .../main/service/info/config_test.js            |  7 +-
 .../widgets/slider_config_widget_view_test.js   | 48 ++++++++++---
 8 files changed, 187 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/fd5e6e68/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 0314afc..be086ac 100644
--- a/ambari-web/app/controllers/main/service/info/configs.js
+++ b/ambari-web/app/controllers/main/service/info/configs.js
@@ -257,7 +257,9 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM
     var self = this;
     if (App.get('supports.enhancedConfigs')) {
       App.config.loadConfigTheme(this.get('content.serviceName')).then(function() {
-        App.themesMapper.generateAdvancedTabs([self.get('content.serviceName')]);
+        self.loadDependentConfigs().done(function () {
+          App.themesMapper.generateAdvancedTabs([self.get('content.serviceName')]);
+        });
       });
     }
     this.clearStep();
@@ -354,7 +356,7 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM
      * by serviceName that has dependent properties
      */
     if (serviceConfigsToLoad.length > 0) {
-      App.config.loadConfigCurrentVersions(serviceConfigsToLoad);
+      return App.config.loadConfigCurrentVersions(serviceConfigsToLoad);
     }
   },
 
@@ -988,7 +990,6 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM
     this.set('versionLoaded', true);
     this.set('hash', this.getHash());
     this.set('isInit', false);
-    this.loadDependentConfigs();
   },
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/fd5e6e68/ambari-web/app/styles/widgets.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/widgets.less b/ambari-web/app/styles/widgets.less
index 9746547..33f8b15 100644
--- a/ambari-web/app/styles/widgets.less
+++ b/ambari-web/app/styles/widgets.less
@@ -31,10 +31,6 @@
 
   @slider-widget-border-color: #999;
 
-  .ui-slider-wrapper {
-    margin: 0 30px;
-  }
-
   .slider-track {
     height: 20px !important;
     border: 1px solid @slider-widget-border-color;
@@ -70,6 +66,11 @@
     border-radius: 11px;
     box-shadow: none;
   }
+
+  .undo-button {
+    margin-left: 20px;
+  }
+
 }
 
 .spinner-input-widget {

http://git-wip-us.apache.org/repos/asf/ambari/blob/fd5e6e68/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 9f3fb8e..3fd541d 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
@@ -22,12 +22,18 @@
       <tr>
         {{#each section in row}}
           <td class="config-section" {{bindAttr colspan="section.columnSpan" rowspan="section.rowSpan"}}>
-            {{section.displayName}}
+            <h3>{{section.displayName}}</h3>
             <table class="config-subsection-table">
               {{#each subRow in section.subsectionRows}}
                 <tr>
                   {{#each subsection in subRow}}
-                    <td class="config-subsection">{{subsection.name}}</td>
+                    <td class="config-subsection">
+                      {{#each config in subsection.configs}}
+                        {{#if config.view}}
+                          {{view config.widget configBinding="config"}}
+                        {{/if}}
+                      {{/each}}
+                    </td>
                   {{/each}}
                 </tr>
               {{/each}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/fd5e6e68/ambari-web/app/templates/common/configs/widgets/slider_config_widget.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/configs/widgets/slider_config_widget.hbs b/ambari-web/app/templates/common/configs/widgets/slider_config_widget.hbs
index 960bc72..c38e4b3 100644
--- a/ambari-web/app/templates/common/configs/widgets/slider_config_widget.hbs
+++ b/ambari-web/app/templates/common/configs/widgets/slider_config_widget.hbs
@@ -17,24 +17,30 @@
 }}
 
 <div class="widget slider-widget">
+  <p>{{view.config.name}}</p>
+
   <p>{{view.config.description}}</p>
-  <div {{bindAttr class="view.isMirrorValueValid::error :control-group :pull-left"}}>
-    <div {{bindAttr class="view.config.stackConfigProperty.valueAttributes.unit:input-append"}}>
-      {{view Ember.TextField valueBinding="view.mirrorValue" class="input-mini"}}
-      {{#if view.config.stackConfigProperty.valueAttributes.unit}}
-        <span class="add-on">{{view.config.stackConfigProperty.valueAttributes.unit}}</span>
-      {{/if}}
+
+  <div>
+    <div {{bindAttr class="view.isMirrorValueValid::error :control-group :pull-left"}}>
+      <div {{bindAttr class="view.config.stackConfigProperty.valueAttributes.unit:input-append"}}>
+        {{view Ember.TextField valueBinding="view.mirrorValue" class="input-mini"}}
+        {{#if view.config.stackConfigProperty.valueAttributes.unit}}
+          <span class="add-on">{{view.config.stackConfigProperty.valueAttributes.unit}}</span>
+        {{/if}}
+      </div>
     </div>
+    {{#if view.valueIsChanged}}
+      <div class="pull-left undo-button">
+        <a class="btn btn-small" href="#" {{action "restoreValue" target="view"}}>
+          <i class="icon-undo"></i>
+        </a>
+      </div>
+    {{/if}}
+    <div class="clearfix"></div>
   </div>
-  <div class="pull-left ui-slider-wrapper">
+  <div class="ui-slider-wrapper">
     {{view Ember.TextField valueBinding="view.config.value" class="input-mini slider-input"}}
   </div>
-  {{#if view.valueIsChanged}}
-    <div class="pull-left undo-button">
-      <a class="btn btn-small" href="#" {{action "restoreValue" target="view"}}>
-        <i class="icon-undo"></i>
-      </a>
-    </div>
-  {{/if}}
   <div class="clearfix"></div>
 </div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/fd5e6e68/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 2fa35b6..9e93076 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
@@ -19,5 +19,51 @@
 var App = require('app');
 
 App.ServiceConfigLayoutTabView = Em.View.extend({
-  templateName: require('templates/common/configs/service_config_layout_tab')
+
+  templateName: require('templates/common/configs/service_config_layout_tab'),
+
+  /**
+   * ConfigType-Widget map
+   * key - widget type
+   * value - widget view
+   * @type {object}
+   */
+  widgetTypeMap: {
+    slider: App.SliderConfigWidgetView
+  },
+
+  /**
+   * Prepare configs for render
+   * <code>subsection.configs</code> is an array of App.StackConfigProperty, but not App.ConfigProperty,
+   * so proper config-properties should be linked to the subsections.
+   * Also correct widget should be used for each config (it's selected according to <code>widget.type</code> and
+   * <code>widgetTypeMap</code>). It may throw an error if needed widget can't be found in the <code>widgetTypeMap</code>
+   * @method prepareConfigProperties
+   */
+  prepareConfigProperties: function () {
+    var widgetTypeMap = this.get('widgetTypeMap');
+    var self = this;
+    this.get('content.sectionRows').forEach(function (row) {
+      row.forEach(function (section) {
+        section.get('subsectionRows').forEach(function (subRow) {
+          subRow.forEach(function (subsection) {
+            subsection.set('configs', []);
+            subsection.get('configProperties').forEach(function (config) {
+              var c = App.ConfigProperty.find(config.get('id') + '_' + self.get('controller.selectedVersion'));
+              subsection.get('configs').pushObject(c);
+              var configWidgetType = config.get('widget.type');
+              var widget = widgetTypeMap[configWidgetType];
+              Em.assert('Unknown config widget view for config ' + c.get('id') + ' with type ' + configWidgetType, widget);
+              c.set('widget', widget);
+            });
+          });
+        });
+      });
+    });
+  },
+
+  beforeRender: function () {
+    this.prepareConfigProperties();
+  }
+
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/fd5e6e68/ambari-web/app/views/common/configs/widgets/slider_config_widget_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/configs/widgets/slider_config_widget_view.js b/ambari-web/app/views/common/configs/widgets/slider_config_widget_view.js
index 05306f5..f6c44c5 100644
--- a/ambari-web/app/views/common/configs/widgets/slider_config_widget_view.js
+++ b/ambari-web/app/views/common/configs/widgets/slider_config_widget_view.js
@@ -48,6 +48,24 @@ App.SliderConfigWidgetView = App.ConfigWidgetView.extend({
    */
   isMirrorValueValid: true,
 
+  /**
+   * Function used to parse config value (based on <code>config.stackConfigProperty.valueAttributes.type</code>)
+   * For integer - parseInt, for float - parseFloat
+   * @type {Function}
+   */
+  parseFunction: function () {
+    return this.get('config.stackConfigProperty.valueAttributes.type') === 'int' ? parseInt : parseFloat;
+  }.property('config.stackConfigProperty.valueAttributes.type'),
+
+  /**
+   * Function used to validate config value (based on <code>config.stackConfigProperty.valueAttributes.type</code>)
+   * For integer - validator.isValidInt, for float - validator.isValidFloat
+   * @type {Function}
+   */
+  validateFunction: function () {
+    return this.get('config.stackConfigProperty.valueAttributes.type') === 'int' ? validator.isValidInt : validator.isValidFloat;
+  }.property('config.stackConfigProperty.valueAttributes.type'),
+
   willInsertElement: function () {
     this._super();
     this.addObserver('mirrorValue', this, this.mirrorValueObs);
@@ -56,6 +74,7 @@ App.SliderConfigWidgetView = App.ConfigWidgetView.extend({
   didInsertElement: function () {
     this._super();
     this.set('mirrorValue', this.get('config.value'));
+    this.prepareValueAttributes();
     this.initSlider();
   },
 
@@ -69,15 +88,15 @@ App.SliderConfigWidgetView = App.ConfigWidgetView.extend({
       slider = this.get('slider'),
       min = this.get('config.stackConfigProperty.valueAttributes.minimum'),
       max = this.get('config.stackConfigProperty.valueAttributes.maximum'),
-      validationFunction = this.get('config.stackConfigProperty.valueAttributes.type') == 'int' ? validator.isValidInt : validator.isValidFloat,
-      parseFunction = this.get('config.stackConfigProperty.valueAttributes.type') == 'int' ? parseInt : parseFloat;
+      validationFunction = this.get('validateFunction'),
+      parseFunction = this.get('parseFunction');
     if (validationFunction(mirrorValue)) {
       var parsed = parseFunction(mirrorValue);
       if (parsed >= min && parsed <=max) {
         this.set('isMirrorValueValid', true);
         this.set('config.value', parsed);
         if (slider) {
-          slider.setValue(this.get('config.value'));
+          slider.setValue(parsed);
         }
       }
       else {
@@ -90,6 +109,19 @@ App.SliderConfigWidgetView = App.ConfigWidgetView.extend({
   },
 
   /**
+   * valueAttributes are strings, but should be numbers
+   * parse them using <code>parseFunction</code>
+   * @method prepareValueAttributes
+   */
+  prepareValueAttributes: function () {
+    var valueAttributes = this.get('config.stackConfigProperty.valueAttributes'),
+      parseFunction = this.get('parseFunction');
+    if (!valueAttributes) return;
+    Em.set(valueAttributes, 'maximum', parseFunction(valueAttributes.maximum));
+    Em.set(valueAttributes, 'minimum', parseFunction(valueAttributes.minimum));
+  },
+
+  /**
    * Draw slider for current config
    * @method initSlider
    */
@@ -97,30 +129,40 @@ App.SliderConfigWidgetView = App.ConfigWidgetView.extend({
     var self = this,
       config = this.get('config'),
       valueAttributes = config.get('stackConfigProperty.valueAttributes'),
-      unit = valueAttributes.get('unit'),
+      unit = Em.getWithDefault(valueAttributes, 'unit', ''),
+      parseFunction = this.get('parseFunction'),
       ticks = [valueAttributes.minimum],
       ticksLabels = [];
+
+    // ticks and labels
     for (var i = 1; i <= 3; i++) {
-      ticks.push(Math.round((valueAttributes.minimum + valueAttributes.maximum) / 4 * i));
+      var val = (valueAttributes.minimum + valueAttributes.maximum) / 4 * i;
+      // if value's type is float, ticks may be float too
+      ticks.push(valueAttributes.type === 'int' ? Math.round(val) : parseFloat(val.toFixed(1)));
     }
     ticks.push(valueAttributes.maximum);
-    ticks.forEach(function (tick, indx) {
-      ticksLabels.push(indx  % 2===0 ? tick + ' ' + unit : '');
+    ticks.forEach(function (tick, index) {
+      ticksLabels.push(index % 2 === 0 ? tick + ' ' + unit : '');
     });
+
     var slider = new Slider('#' + this.get('elementId') + ' input.slider-input', {
-      value: this.get('config.value'),
+      value: parseFunction(this.get('config.value')),
       ticks: ticks,
       tooltip: 'hide',
       ticks_labels: ticksLabels,
-      ticks_snap_bounds: valueAttributes.get('type') === 'int' ? 1 : 0.1,
-      step: valueAttributes.get('type') === 'int' ? 1 : 0.1
+      ticks_snap_bounds: Em.get(valueAttributes, 'type') === 'int' ? 1 : 0.1,
+      step: Em.get(valueAttributes, 'type') === 'int' ? 1 : 0.1
     });
-    slider.on('slide', function (newValue) {
-      self.set('config.value', newValue);
-      self.set('mirrorValue', newValue);
+
+    slider.on('change', function (obj) {
+      var val = parseFunction(obj.newValue);
+      self.set('config.value', val);
+      self.set('mirrorValue', val);
     });
+
     this.set('slider', slider);
-    this.$('.slider-tick:first, .slider-tick:last').hide(); // hide some ticks. can't do this via css
+    // hide some ticks. can't do this via css
+    this.$('.slider-tick:first, .slider-tick:last').hide();
   },
 
   /**
@@ -130,8 +172,10 @@ App.SliderConfigWidgetView = App.ConfigWidgetView.extend({
    */
   restoreValue: function () {
     this._super();
-    this.get('slider').setValue(this.get('config.value'));
-    this.set('mirrorValue', this.get('config.value'));
+    var parseFunction = this.get('parseFunction'),
+      val = parseFunction(this.get('config.value'));
+    this.get('slider').setValue(val);
+    this.set('mirrorValue', val);
   }
 
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/fd5e6e68/ambari-web/test/controllers/main/service/info/config_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/service/info/config_test.js b/ambari-web/test/controllers/main/service/info/config_test.js
index a6785ee..9de9f39 100644
--- a/ambari-web/test/controllers/main/service/info/config_test.js
+++ b/ambari-web/test/controllers/main/service/info/config_test.js
@@ -25,7 +25,11 @@ describe("App.MainServiceInfoConfigsController", function () {
   beforeEach(function () {
     sinon.stub(App.config, 'loadConfigTheme').returns($.Deferred().resolve().promise());
     sinon.stub(App.themesMapper, 'generateAdvancedTabs').returns(Em.K);
-    mainServiceInfoConfigsController = App.MainServiceInfoConfigsController.create({});
+    mainServiceInfoConfigsController = App.MainServiceInfoConfigsController.create({
+      loadDependentConfigs: function () {
+        return {done: Em.K}
+      }
+    });
   });
 
   afterEach(function() {
@@ -1311,7 +1315,6 @@ describe("App.MainServiceInfoConfigsController", function () {
     });
   });
 
-
   describe('#calculateDependentFileNames()', function() {
 
     beforeEach(function() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/fd5e6e68/ambari-web/test/views/common/configs/widgets/slider_config_widget_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/common/configs/widgets/slider_config_widget_view_test.js b/ambari-web/test/views/common/configs/widgets/slider_config_widget_view_test.js
index f34fb8f..b6d9ba6 100644
--- a/ambari-web/test/views/common/configs/widgets/slider_config_widget_view_test.js
+++ b/ambari-web/test/views/common/configs/widgets/slider_config_widget_view_test.js
@@ -28,13 +28,13 @@ describe('App.SliderConfigWidgetView', function () {
       config: Em.Object.create({
         name: 'a.b.c',
         description: 'A B C',
-        value: 486,
-        defaultValue: 486,
+        value: '486',
+        defaultValue: '486',
         stackConfigProperty: Em.Object.create({
           valueAttributes: Em.Object.create({
             type: 'int',
-            minimum: 0,
-            maximum: 2096,
+            minimum: '0',
+            maximum: '2096',
             unit: 'MB'
           })
         })
@@ -47,13 +47,13 @@ describe('App.SliderConfigWidgetView', function () {
       config: Em.Object.create({
         name: 'a.b.c2',
         description: 'A B C 2',
-        value: 72.2,
-        defaultValue: 72.2,
+        value: '72.2',
+        defaultValue: '72.2',
         stackConfigProperty: Em.Object.create({
           valueAttributes: Em.Object.create({
             type: 'float',
-            minimum: 0,
-            maximum: 100,
+            minimum: '0',
+            maximum: '100',
             unit: '%'
           })
         })
@@ -65,8 +65,8 @@ describe('App.SliderConfigWidgetView', function () {
 
   describe('#mirrorValue', function () {
     it('should be equal to config.value after init', function () {
-      expect(viewInt.get('mirrorValue')).to.equal(viewInt.get('config.value'));
-      expect(viewFloat.get('mirrorValue')).to.equal(viewFloat.get('config.value'));
+      expect(viewInt.get('mirrorValue')).to.equal('' + viewInt.get('config.value'));
+      expect(viewFloat.get('mirrorValue')).to.equal('' + viewFloat.get('config.value'));
     });
   });
 
@@ -94,4 +94,32 @@ describe('App.SliderConfigWidgetView', function () {
 
   });
 
+  describe('#prepareValueAttributes', function () {
+
+    it('should parse string to int', function () {
+
+      var max = viewInt.get('config.stackConfigProperty.valueAttributes.maximum'),
+        min = viewInt.get('config.stackConfigProperty.valueAttributes.minimum');
+      viewInt.set('config.stackConfigProperty.valueAttributes.maximum', '' + max);
+      viewInt.set('config.stackConfigProperty.valueAttributes.minimum', '' + min);
+      viewInt.prepareValueAttributes();
+      expect(viewInt.get('config.stackConfigProperty.valueAttributes.maximum')).to.equal(max);
+      expect(viewInt.get('config.stackConfigProperty.valueAttributes.minimum')).to.equal(min);
+
+    });
+
+    it('should parse string to float', function () {
+
+      var max = viewFloat.get('config.stackConfigProperty.valueAttributes.maximum'),
+        min = viewFloat.get('config.stackConfigProperty.valueAttributes.minimum');
+      viewFloat.set('config.stackConfigProperty.valueAttributes.maximum', '' + max);
+      viewFloat.set('config.stackConfigProperty.valueAttributes.minimum', '' + min);
+      viewFloat.prepareValueAttributes();
+      expect(viewFloat.get('config.stackConfigProperty.valueAttributes.maximum')).to.equal(max);
+      expect(viewFloat.get('config.stackConfigProperty.valueAttributes.minimum')).to.equal(min);
+
+    });
+
+  });
+
 });
\ No newline at end of file