瀏覽代碼

AMBARI-11532. "Max idle tez session length" widget on Hive Customize Service settings has inconsistent behavior between slider view and text view (onechiporenko)

Oleg Nechiporenko 10 年之前
父節點
當前提交
81a2fa3b71

+ 1 - 1
ambari-web/app/templates/common/configs/widgets/controls.hbs

@@ -42,7 +42,7 @@
           </a>
         {{else}}
           <i class="icon-pencil widget-action widget-action-switch-view text-error"
-             data-toggle="tooltip" {{translateAttr data-original-title="config.infoMessage.wrong.value.for.widget"}}></i>
+             data-toggle="tooltip" {{bindAttr data-original-title="view.issueMessage"}}></i>
         {{/if}}
       {{/if}}
       {{#if view.config.recommendedValueExists}}

+ 7 - 1
ambari-web/app/views/common/configs/widgets/combo_config_widget_view.js

@@ -142,7 +142,13 @@ App.ComboConfigWidgetView = App.ConfigWidgetView.extend({
   },
 
   isValueCompatibleWithWidget: function() {
-    return this._super() && this.get('content.valuesList').someProperty('configValue', this.get('config.value'));
+    var res = this._super() && this.get('content.valuesList').someProperty('configValue', this.get('config.value'));
+    if (!res) {
+      this.updateWarningsForCompatibilityWithWidget(Em.I18n.t('config.infoMessage.wrong.value.for.widget'));
+      return false;
+    }
+    this.updateWarningsForCompatibilityWithWidget('');
+    return true;
   }
 
 });

+ 17 - 1
ambari-web/app/views/common/configs/widgets/config_widget_view.js

@@ -394,6 +394,7 @@ App.ConfigWidgetView = Em.View.extend(App.SupportsDependentConfigs, App.WidgetPo
 
   /**
    * check if config value can be converted to config widget value
+   * IMPORTANT! Each config-widget that override this method should use <code>updateWarningsForCompatibilityWithWidget</code>
    * @returns {boolean}
    */
   isValueCompatibleWithWidget: function() {
@@ -418,6 +419,21 @@ App.ConfigWidgetView = Em.View.extend(App.SupportsDependentConfigs, App.WidgetPo
       return true;
     }
     return this.isValueCompatibleWithWidget();
-  }.property('config.value', 'config.showAsTextBox')
+  }.property('config.value', 'config.showAsTextBox'),
+
+  /**
+   * Used in <code>isValueCompatibleWithWidget</code>
+   * Updates issue-parameters if config is in the raw-mode
+   * @param {string} message empty string if value compatible with widget, error-message if value isn't compatible with widget
+   * @method updateWarningsForCompatibilityWithWidget
+   */
+  updateWarningsForCompatibilityWithWidget: function (message) {
+    this.setProperties({
+      warnMessage: message,
+      issueMessage: message,
+      iconClass: message ? 'warning' : '',
+      configLabelClass: message ? 'text-warning' : ''
+    });
+  }
 
 });

+ 7 - 1
ambari-web/app/views/common/configs/widgets/list_config_widget_view.js

@@ -277,7 +277,13 @@ App.ListConfigWidgetView = App.ConfigWidgetView.extend({
   },
 
   isValueCompatibleWithWidget: function() {
-    return this._super() && this.isOptionExist(this.get('config.value'));
+    var res = this._super() && this.isOptionExist(this.get('config.value'));
+    if (!res) {
+      this.updateWarningsForCompatibilityWithWidget(Em.I18n.t('config.infoMessage.wrong.value.for.widget'));
+      return false;
+    }
+    this.updateWarningsForCompatibilityWithWidget('');
+    return true;
   },
 
   isOptionExist: function(value) {

+ 6 - 0
ambari-web/app/views/common/configs/widgets/plain_config_text_field.js

@@ -34,10 +34,16 @@ App.PlainConfigTextField = Ember.View.extend(App.SupportsDependentConfigs, App.W
     return this.get('config.stackConfigProperty.displayName') || this.get('config.displayName') || this.get('config.name');
   }.property('config.name', 'config.displayName'),
 
+  /**
+   * @type {string|boolean}
+   */
   unit: function() {
     return Em.getWithDefault(this, 'config.stackConfigProperty.valueAttributes.unit', false);
   }.property('config.stackConfigProperty.valueAttributes.unit'),
 
+  /**
+   * @type {string}
+   */
   displayUnit: function() {
     var unit = this.get('unit');
     if ('milliseconds' == unit) {

+ 9 - 2
ambari-web/app/views/common/configs/widgets/slider_config_widget_view.js

@@ -502,12 +502,19 @@ App.SliderConfigWidgetView = App.ConfigWidgetView.extend({
       var configValue = this.get('parseFunction')(this.get('config.value'));
       if (this.get('config.stackConfigProperty.valueAttributes.minimum')) {
         var min = this.get('parseFunction')(this.get('config.stackConfigProperty.valueAttributes.minimum'));
-        if (configValue < min) return false;
+        if (configValue < min) {
+          this.updateWarningsForCompatibilityWithWidget(Em.I18n.t('config.warnMessage.outOfBoundaries.less').format(min));
+          return false;
+        }
       }
       if (this.get('config.stackConfigProperty.valueAttributes.maximum')) {
         var max = this.get('parseFunction')(this.get('config.stackConfigProperty.valueAttributes.maximum'));
-        if (configValue > max) return false;
+        if (configValue > max) {
+          this.updateWarningsForCompatibilityWithWidget(Em.I18n.t('config.warnMessage.outOfBoundaries.greater').format(max));
+          return false;
+        }
       }
+      this.updateWarningsForCompatibilityWithWidget('');
       return true;
     }
     return false;

+ 22 - 6
ambari-web/app/views/common/configs/widgets/time_interval_spinner_view.js

@@ -152,8 +152,14 @@ App.TimeIntervalSpinnerView = App.ConfigWidgetView.extend({
    */
   valueObserver: function() {
     if (!this.get('content') || isNaN(parseInt(this.get('config.value')))) return;
-    Em.run.once(this, 'valueObserverCallback');
-  }.observes('content.@each.value'),
+
+    if (this.get('config.showAsTextBox')) {
+      this.checkErrors(this.generateWidgetValue(this.get('config.value')));
+    }
+    else {
+      Em.run.once(this, 'valueObserverCallback');
+    }
+  }.observes('content.@each.value', 'config.value'),
 
   valueObserverCallback: function() {
     this.checkModified();
@@ -172,10 +178,12 @@ App.TimeIntervalSpinnerView = App.ConfigWidgetView.extend({
 
   /**
    * Check for validation errors like minimum or maximum required value
+   * @param {*} [val]
    * @method checkErrors
    */
-  checkErrors: function() {
-    var convertedValue = this.configValueByWidget(this.get('content'));
+  checkErrors: function(val) {
+    val = val || this.get('content');
+    var convertedValue = this.configValueByWidget(val);
     var warnMessage = '';
     var warn = false;
     if (convertedValue < parseInt(this.get('config.stackConfigProperty.valueAttributes.minimum'))) {
@@ -242,17 +250,25 @@ App.TimeIntervalSpinnerView = App.ConfigWidgetView.extend({
       if (isNaN(configValue)) return false;
       if (this.get('config.stackConfigProperty.valueAttributes.minimum')) {
         var min = parseInt(this.get('config.stackConfigProperty.valueAttributes.minimum'));
-        if (configValue < min) return false;
+        if (configValue < min) {
+          this.updateWarningsForCompatibilityWithWidget(Em.I18n.t('config.warnMessage.outOfBoundaries.less').format(this.dateToText(this.get('minValue'))));
+          return false;
+        }
       }
       if (this.get('config.stackConfigProperty.valueAttributes.maximum')) {
         var max = parseInt(this.get('config.stackConfigProperty.valueAttributes.maximum'));
-        if (configValue > max) return false;
+        if (configValue > max) {
+          this.updateWarningsForCompatibilityWithWidget(Em.I18n.t('config.warnMessage.outOfBoundaries.greater').format(this.dateToText(this.get('maxValue'))));
+          return false;
+        }
       }
       if (this.get('config.stackConfigProperty.valueAttributes.increment_step')) {
         if (configValue % this.get('config.stackConfigProperty.valueAttributes.increment_step') != 0) return false;
       }
+      this.updateWarningsForCompatibilityWithWidget('');
       return true;
     }
     return false;
   }
+
 });

+ 7 - 1
ambari-web/app/views/common/configs/widgets/toggle_config_widget_view.js

@@ -185,7 +185,13 @@ App.ToggleConfigWidgetView = App.ConfigWidgetView.extend({
    */
   isValueCompatibleWithWidget: function () {
     if (this._super()) {
-      return this.get('config.stackConfigProperty.valueAttributes.entries').mapProperty('value').contains(this.get('config.value'));
+      var res = this.get('config.stackConfigProperty.valueAttributes.entries').mapProperty('value').contains(this.get('config.value'));
+      if (!res) {
+        this.updateWarningsForCompatibilityWithWidget(Em.I18n.t('config.infoMessage.wrong.value.for.widget'));
+        return false;
+      }
+      this.updateWarningsForCompatibilityWithWidget('');
+      return true;
     }
     return false;
   }

+ 7 - 1
ambari-web/test/views/common/configs/widgets/slider_config_widget_view_test.js

@@ -404,14 +404,18 @@ describe('App.SliderConfigWidgetView', function () {
     it ('fail: to large', function() {
       viewInt.set('config.value', 12);
       expect(viewInt.isValueCompatibleWithWidget()).to.be.false;
+      expect(viewInt.get('warnMessage')).to.have.property('length').that.is.least(1);
+      expect(viewInt.get('issueMessage')).to.have.property('length').that.is.least(1);
     });
 
     it ('fail: to small', function() {
       viewInt.set('config.value', 0);
       expect(viewInt.isValueCompatibleWithWidget()).to.be.false;
+      expect(viewInt.get('warnMessage')).to.have.property('length').that.is.least(1);
+      expect(viewInt.get('issueMessage')).to.have.property('length').that.is.least(1);
     });
 
-    it ('ok for wrong step', function() {
+    it ('fail: for wrong step', function() {
       viewInt.set('config.stackConfigProperty', stackConfigProperty);
       viewInt.set('config.value', '3');
       expect(viewInt.isValueCompatibleWithWidget()).to.be.true;
@@ -420,6 +424,8 @@ describe('App.SliderConfigWidgetView', function () {
     it ('ok', function() {
       viewInt.set('config.value', 4);
       expect(viewInt.isValueCompatibleWithWidget()).to.be.true;
+      expect(viewInt.get('warnMessage')).to.equal('');
+      expect(viewInt.get('issueMessage')).to.equal('');
     });
   });
 

+ 12 - 3
ambari-web/test/views/common/configs/widgets/time_interval_spinner_view_test.js

@@ -26,13 +26,14 @@ describe('App.TimeIntervalSpinnerView', function () {
       controller: Em.Object.create({
         removeCurrentFromDependentList: Em.K
       }),
-      initPopover: Em.K,
-      setProperties: Em.K
+      initPopover: Em.K
     });
+    sinon.stub(Em.run, 'once', Em.K);
   });
 
   afterEach(function () {
     view.destroy();
+    Em.run.once.restore();
   });
 
   describe('#generateWidgetValue', function () {
@@ -251,10 +252,12 @@ describe('App.TimeIntervalSpinnerView', function () {
     var stackConfigProperty = null;
 
     beforeEach(function() {
-      view.set('config', {});
+      view.set('config', Em.Object.create({}));
       stackConfigProperty = App.StackConfigProperty.createRecord({name: 'p1', valueAttributes: {minimum: 1, maximum: 10, increment_step: 4, type: 'int'}});
       view.set('config.stackConfigProperty', stackConfigProperty);
       view.set('config.isValid', true);
+      view.set('maxValue', [{"value":10,"type":"hours","minValue":0,"maxValue":10,"incrementStep":1,"enabled":true},{"value":0,"type":"minutes","minValue":0,"maxValue":59,"incrementStep":1,"enabled":true}]);
+      view.set('minValue', [{"value":0,"type":"hours","minValue":0,"maxValue":23,"incrementStep":1,"enabled":true},{"value":10,"type":"minutes","minValue":0,"maxValue":59,"incrementStep":1,"enabled":true}]);
     });
 
     it ('fail by config validation', function() {
@@ -275,11 +278,15 @@ describe('App.TimeIntervalSpinnerView', function () {
     it ('fail: to large', function() {
       view.set('config.value', 12);
       expect(view.isValueCompatibleWithWidget()).to.be.false;
+      expect(view.get('warnMessage')).to.have.property('length').that.is.least(1);
+      expect(view.get('issueMessage')).to.have.property('length').that.is.least(1);
     });
 
     it ('fail: to small', function() {
       view.set('config.value', 0);
       expect(view.isValueCompatibleWithWidget()).to.be.false;
+      expect(view.get('warnMessage')).to.have.property('length').that.is.least(1);
+      expect(view.get('issueMessage')).to.have.property('length').that.is.least(1);
     });
 
     it ('fail: wrong step', function() {
@@ -291,6 +298,8 @@ describe('App.TimeIntervalSpinnerView', function () {
     it ('ok', function() {
       view.set('config.value', 4);
       expect(view.isValueCompatibleWithWidget()).to.be.true;
+      expect(view.get('warnMessage')).to.equal('');
+      expect(view.get('issueMessage')).to.equal('');
     });
   });
 

+ 8 - 0
ambari-web/test/views/common/configs/widgets/toggle_config_widget_view_test.js

@@ -91,6 +91,14 @@ describe('App.ToggleConfigWidgetView', function () {
           isValid: true
         });
         expect(this.view.isValueCompatibleWithWidget()).to.equal(test.e);
+        if (test.e) {
+          expect(this.view.get('warnMessage')).to.equal('');
+          expect(this.view.get('issueMessage')).to.equal('');
+        }
+        else {
+          expect(this.view.get('warnMessage')).to.have.property('length').that.is.least(1);
+          expect(this.view.get('issueMessage')).to.have.property('length').that.is.least(1);
+        }
       });
     });