ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From onechipore...@apache.org
Subject ambari git commit: AMBARI-10453. Widgets should use increment-step specified in API (onechiporenko)
Date Tue, 14 Apr 2015 15:40:25 GMT
Repository: ambari
Updated Branches:
  refs/heads/trunk 1de06bbe2 -> 7f648f9fa


AMBARI-10453. Widgets should use increment-step specified in API (onechiporenko)


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

Branch: refs/heads/trunk
Commit: 7f648f9fa3885e412cd0687b6a88197201f8d144
Parents: 1de06bb
Author: Oleg Nechiporenko <onechiporenko@apache.org>
Authored: Tue Apr 14 18:36:56 2015 +0300
Committer: Oleg Nechiporenko <onechiporenko@apache.org>
Committed: Tue Apr 14 18:39:23 2015 +0300

----------------------------------------------------------------------
 .../mixins/common/configs/enhanced_configs.js   |   4 +-
 .../unit_convert/base_unit_convert_mixin.js     |   4 +-
 .../app/templates/common/form/spinner_input.hbs |   6 +-
 .../widgets/slider_config_widget_view.js        |   4 +-
 .../widgets/time_interval_spinner_view.js       |  45 +++-
 .../app/views/common/form/spinner_input_view.js | 220 +++++++++++--------
 .../base_unit_convert_mixin_test.js             |   4 +-
 .../widgets/time_interval_spinner_view_test.js  | 144 ++++++++----
 8 files changed, 273 insertions(+), 158 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/7f648f9f/ambari-web/app/mixins/common/configs/enhanced_configs.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/configs/enhanced_configs.js b/ambari-web/app/mixins/common/configs/enhanced_configs.js
index 1a53b7f..ecc096d 100644
--- a/ambari-web/app/mixins/common/configs/enhanced_configs.js
+++ b/ambari-web/app/mixins/common/configs/enhanced_configs.js
@@ -448,8 +448,8 @@ App.EnhancedConfigsMixin = Em.Mixin.create({
             if (configs[key].property_attributes[propertyName].max) {
               stackProperty.set('valueAttributes.maximum', configs[key].property_attributes[propertyName].max);
             }
-            if (configs[key].property_attributes[propertyName].step) {
-              stackProperty.set('valueAttributes.step', configs[key].property_attributes[propertyName].step);
+            if (configs[key].property_attributes[propertyName].increment_step) {
+              stackProperty.set('valueAttributes.increment_step', configs[key].property_attributes[propertyName].increment_step);
             }
           }
         }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7f648f9f/ambari-web/app/mixins/unit_convert/base_unit_convert_mixin.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/unit_convert/base_unit_convert_mixin.js b/ambari-web/app/mixins/unit_convert/base_unit_convert_mixin.js
index 3863c43..51141f1 100644
--- a/ambari-web/app/mixins/unit_convert/base_unit_convert_mixin.js
+++ b/ambari-web/app/mixins/unit_convert/base_unit_convert_mixin.js
@@ -78,7 +78,7 @@ App.BaseUnitConvertMixin = Em.Mixin.create({
   }),
 
   /**
-   * Convert value between different unit types. Coversion works for following directions:
+   * Convert value between different unit types. Conversion works for following directions:
    *  single unit -> single unit e.g. from "s" -> "s".
    *  single unit -> multi unit e.g. from "ms" -> "days,hours"
    *  multi unit -> single unit e.g. from "days,hours" -> "ms"
@@ -98,7 +98,7 @@ App.BaseUnitConvertMixin = Em.Mixin.create({
    * @param {String|String[]} fromUnit - specified value unit type(s) e.g. "mb"
    *    Form multi dimensional format pass units separated with "," or list of unit types
    *    e.g. "gb,mb", ['gb', 'mb']
-   * @param {Boolean} [isObjectOutput=false] - 'returned' value should be object this option
usefull for widgets where its
+   * @param {Boolean} [isObjectOutput=false] - 'returned' value should be object this option
useful for widgets where its
    *    value should be an Object
    * @param {String|String[]} toUnit - desired unit(s) to convert specified value. Same format
as for `fromUnit`
    * @returns {Number|Object[]} returns single value or array of objects according to multi
unit format

http://git-wip-us.apache.org/repos/asf/ambari/blob/7f648f9f/ambari-web/app/templates/common/form/spinner_input.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/form/spinner_input.hbs b/ambari-web/app/templates/common/form/spinner_input.hbs
index 09b0422..9ed9dd2 100644
--- a/ambari-web/app/templates/common/form/spinner_input.hbs
+++ b/ambari-web/app/templates/common/form/spinner_input.hbs
@@ -17,9 +17,9 @@
 }}
 
 <div class="input-prepend input-append">
-  <button class="btn" {{bindAttr disabled="view.disabled"}} {{action decrementValue target="view"}}><span
class="icon icon-caret-left"></span></button>
-  {{view Em.TextField valueBinding="view.content.value" disabledBinding="view.disabled"}}
-  <button class="btn" {{bindAttr disabled="view.disabled"}} {{action incrementValue target="view"}}><span
class="icon icon-caret-right"></span></button>
+  <button class="btn" {{bindAttr disabled="view.computedDisabled"}} {{action decrementValue
target="view"}}><span class="icon icon-caret-left"></span></button>
+  {{view Em.TextField valueBinding="view.content.value" disabledBinding="view.computedDisabled"}}
+  <button class="btn" {{bindAttr disabled="view.computedDisabled"}} {{action incrementValue
target="view"}}><span class="icon icon-caret-right"></span></button>
 </div>
 {{#if view.content.label}}
   <span class="spinner-input-label">{{view.content.label}}</span>

http://git-wip-us.apache.org/repos/asf/ambari/blob/7f648f9f/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 fcdb412..8fff947 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
@@ -231,14 +231,14 @@ App.SliderConfigWidgetView = App.ConfigWidgetView.extend({
     } else {
       defaultValueId = ticks.indexOf(defaultValue);
     }
-
+    var increment_step = Em.get(valueAttributes, 'increment_step');
     var slider = new Slider(this.$('input.slider-input')[0], {
       value: this.widgetValueByConfigAttributes(parseFunction(this.get('config.value'))),
       ticks: ticks,
       tooltip: 'hide',
       ticks_labels: ticksLabels,
       ticks_snap_bounds: Em.get(valueAttributes, 'type') === 'int' ? 1 : 0.1,
-      step: Em.get(valueAttributes, 'type') === 'int' ? 1 : 0.1
+      step: increment_step ? this.widgetValueByConfigAttributes(increment_step) : (Em.get(valueAttributes,
'type') === 'int' ? 1 : 0.1)
     });
 
     slider.on('change', function (obj) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/7f648f9f/ambari-web/app/views/common/configs/widgets/time_interval_spinner_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/configs/widgets/time_interval_spinner_view.js b/ambari-web/app/views/common/configs/widgets/time_interval_spinner_view.js
index 2bc5716..3e8375e 100644
--- a/ambari-web/app/views/common/configs/widgets/time_interval_spinner_view.js
+++ b/ambari-web/app/views/common/configs/widgets/time_interval_spinner_view.js
@@ -94,16 +94,36 @@ App.TimeIntervalSpinnerView = App.ConfigWidgetView.extend({
    *  @see minValue
    *  @see maxValue
    *       content
+   * @method prepareContent
    */
   prepareContent: function() {
-    var self = this;
     var property = this.get('config');
-    var propertyUnit = property.get('stackConfigProperty.valueAttributes').unit;
 
-    this.set('propertyUnit', propertyUnit);
-    this.set('minValue', this.generateWidgetValue(property.get('stackConfigProperty.valueAttributes.minimum')));
-    this.set('maxValue', this.generateWidgetValue(property.get('stackConfigProperty.valueAttributes.maximum')));
-    this.set('content', this.generateWidgetValue(property.get('value')));
+    this.setProperties({
+      propertyUnit: property.get('stackConfigProperty.valueAttributes.unit'),
+      minValue: this.generateWidgetValue(property.get('stackConfigProperty.valueAttributes.minimum')),
+      maxValue: this.generateWidgetValue(property.get('stackConfigProperty.valueAttributes.maximum')),
+      content: this.generateWidgetValue(property.get('value'))
+    });
+    this.parseIncrement();
+  },
+
+  /**
+   * If <code>config.stackConfigProperty.valueAttributes.increment_step</code>
exists, it should be used as increment
+   * for controls. Also if it's value greater than maximum value for last unit, it (unit)
should be disabled
+   * @method parseIncrement
+   */
+  parseIncrement: function () {
+    var property = this.get('config');
+    var type = this.get('content.lastObject.type');
+    var step = property.get('stackConfigProperty.valueAttributes.increment_step');
+    if (step) {
+      step = this.convertValue(step, property.get('stackConfigProperty.valueAttributes.unit'),
type);
+      this.set('content.lastObject.incrementStep', step);
+      if (step >  Em.get(this, 'timeMaxValueOverflow.' + type)) {
+        this.set('content.lastObject.enabled', false);
+      }
+    }
   },
 
   /**
@@ -112,19 +132,23 @@ App.TimeIntervalSpinnerView = App.ConfigWidgetView.extend({
    *
    * @param {String|Number} value
    * @returns {Object[]}
+   * @method generateWidgetValue
    */
   generateWidgetValue: function(value) {
     return this.widgetValueByConfigAttributes(value, true).map(function(item) {
       item.label = Em.I18n.t('common.' + item.type);
       item.minValue = 0;
       item.maxValue = Em.get(this, 'timeMaxValueOverflow.' + item.type);
+      item.incrementStep = 1;
+      item.enabled = true;
       item.invertOnOverflow = true;
       return item;
     }, this);
   },
 
   /**
-   * Subscribe for value changes.
+   * Subscribe for value changes
+   * @method valueObserver
    */
   valueObserver: function() {
     if (!this.get('content')) return;
@@ -146,7 +170,8 @@ App.TimeIntervalSpinnerView = App.ConfigWidgetView.extend({
   },
 
   /**
-   * Check for validation errors like minimum or maximum required value.
+   * Check for validation errors like minimum or maximum required value
+   * @method checkErrors
    */
   checkErrors: function() {
     var convertedValue = this.configValueByWidget(this.get('content'));
@@ -166,6 +191,7 @@ App.TimeIntervalSpinnerView = App.ConfigWidgetView.extend({
 
   /**
    * set appropriate attribute for configProperty model
+   * @method setConfigValue
    */
   setConfigValue: function() {
     this.set('config.value', this.configValueByWidget(this.get('content')));
@@ -176,6 +202,7 @@ App.TimeIntervalSpinnerView = App.ConfigWidgetView.extend({
    *
    * @param {Object[]} widgetFormatValue - value formatted for widget @see convertToWidgetUnits
    * @return {String}
+   * @method dateToText
    */
   dateToText: function(widgetFormatValue) {
     return widgetFormatValue.map(function(item) {
@@ -190,9 +217,11 @@ App.TimeIntervalSpinnerView = App.ConfigWidgetView.extend({
 
   /**
    * Restore value to default.
+   * @method restoreValue
    */
   restoreValue: function() {
     this._super();
     this.set('content', this.generateWidgetValue(this.get('config.defaultValue')));
+    this.parseIncrement();
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/7f648f9f/ambari-web/app/views/common/form/spinner_input_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/form/spinner_input_view.js b/ambari-web/app/views/common/form/spinner_input_view.js
index b40a9c5..0cacc80 100644
--- a/ambari-web/app/views/common/form/spinner_input_view.js
+++ b/ambari-web/app/views/common/form/spinner_input_view.js
@@ -19,115 +19,141 @@
 var App = require('app');
 
 App.SpinnerInputView = Em.View.extend({
-    templateName: require('templates/common/form/spinner_input'),
-    classNames: ['spinner-input'],
+  templateName: require('templates/common/form/spinner_input'),
+  classNames: ['spinner-input'],
+
+  /**
+   * Bind content directly from Handlebars template or any another way.
+   * For example:
+   * {{view App.SpinnerInputView contentBinding="someContent"}}
+   *
+   * @property content
+   * @type {Object}
+   */
+  content: {
+
+    /**
+     * Minimal value that can be set. (not required)
+     *
+     * @property [minValue]
+     * @type {Number}
+     */
+    minValue: null,
+
+    /**
+     * Maximum value that can be set. (not required)
+     *
+     * @property [maxValue]
+     * @type {Number}
+     */
+    maxValue: null,
 
     /**
-     * Bind content directly from Handlebars template or any another way.
-     * For example:
-     * {{view App.SpinnerInputView contentBinding="someContent"}}
+     * Input value. (required)
      *
-     * @property content
-     * @type {Object}
+     * @property value
+     * @type {String|Number}
      */
-    content: {
-
-      /**
-       * Minimal value that can be set. (not required)
-       *
-       * @property [minValue]
-       * @type {Number}
-       */
-      minValue: null,
-
-      /**
-       * Maximum value that can be set. (not required)
-       *
-       * @property [maxValue]
-       * @type {Number}
-       */
-      maxValue: null,
-
-      /**
-       * Input value. (required)
-       *
-       * @property value
-       * @type {String|Number}
-       */
-      value: null,
-
-      /**
-       * Config display name. Will be shown beneath the input. (not required)
-       *
-       * @type {String}
-       * @property [label]
-       */
-      label: null,
-
-      /**
-       * If set to true value will toggle with max|min on property exceed value.
-       *
-       * @property [invertOnOverflow]
-       * @type {Boolean}
-       */
-      invertOnOverflow: false
-    },
-
-    incrementValue: function() {
-      this.setValue(true);
-    },
-
-    decrementValue: function() {
-      this.setValue();
-    },
-
-    setValue: function(increment) {
-      var value = parseInt(this.get('content.value')) + ((increment) ? 1 : -1);
-      // if minimal required value is specified and decremented property value is less than
minimal
-      if (!Em.isEmpty(this.get('content.minValue')) && !increment && (value
< this.get('content.minValue') )) {
-        // set maximum value if value invert accepted
-        value = (this.get('content.invertOnOverflow')) ? this.get('content.maxValue') : this.get('content.minValue');
-      }
-      // if maximum require value is specified and incremented value is more than maximum
-      else if (!Em.isEmpty(this.get('content.maxValue')) && increment &&
(value > this.get('content.maxValue'))) {
-        // set minimum if value invert accepted
-        value = (this.get('content.invertOnOverflow')) ? this.get('content.minValue') : this.get('content.maxValue');
-      }
-      this.set('content.value', value);
-    },
+    value: null,
 
     /**
-     * Handle keyboard event. Allow digits only and some key maps.
+     * Config display name. Will be shown beneath the input. (not required)
+     *
+     * @type {String}
+     * @property [label]
+     */
+    label: null,
+
+    /**
+     * If set to true value will toggle with max|min on property exceed value.
+     *
+     * @property [invertOnOverflow]
+     * @type {Boolean}
      */
-    keyDown: function(e) {
-      var charCode = (e.charCode) ? e.charCode : e.which;
-      if ([46, 8, 9, 27, 13, 110, 190].contains(charCode) ||
-        (charCode == 65 && e.ctrlKey === true) ||
-        (charCode == 67 && e.ctrlKey === true) ||
-        (charCode == 88 && e.ctrlKey === true) ||
-        (charCode >= 35 && charCode <= 39)) {
-          return;
-        }
-      if ((e.shiftKey || (charCode < 48 || charCode > 57)) && (charCode <
96 || charCode > 105)) {
-          e.preventDefault();
-      }
-    },
+    invertOnOverflow: false,
 
     /**
-     * Change value to maximum if exceeded.
+     * Determines if this control should be enabled or disabled
+     * It's based on increment_step value
+     *
+     * @property [enabled]
+     * @type {Boolean}
      */
-    keyUp: function(e) {
-      if (!Em.isEmpty(this.get('content.maxValue')) && this.get('content.value')
> this.get('content.maxValue')) {
-        this.set('content.value', this.get('content.maxValue'));
-      }
-    },
+    enabled: true,
 
     /**
-     * Set value to 0 if user removed it and changed focus to another element.
+     * Increment value
+     *
+     * @property [incrementStep]
+     * @type {Number}
      */
-    focusOut: function(e) {
-      if (Em.isEmpty(this.get('content.value'))) {
-        this.set('content.value', 0);
-      }
+    incrementStep: 1
+  },
+
+  /**
+   * Input should be disabled, if whole widget is disabled or if its unit is less than step_increment
value
+   * @type {boolean}
+   */
+  computedDisabled: function () {
+    return !this.get('content.enabled') || this.get('disabled');
+  }.property('disabled', 'content.enabled'),
+
+  incrementValue: function () {
+    this.setValue(true);
+  },
+
+  decrementValue: function () {
+    this.setValue(false);
+  },
+
+  setValue: function (increment) {
+    var incrementStep = this.get('content.incrementStep');
+    var value = parseInt(this.get('content.value')) + ((increment) ? incrementStep : -incrementStep);
+    // if minimal required value is specified and decremented property value is less than
minimal
+    if (!Em.isEmpty(this.get('content.minValue')) && !increment && (value
< this.get('content.minValue') )) {
+      // set maximum value if value invert accepted
+      value = (this.get('content.invertOnOverflow')) ? (this.get('content.maxValue') + 1
- incrementStep) : this.get('content.minValue');
+    }
+    // if maximum require value is specified and incremented value is more than maximum
+    else if (!Em.isEmpty(this.get('content.maxValue')) && increment && (value
> this.get('content.maxValue'))) {
+      // set minimum if value invert accepted
+      value = (this.get('content.invertOnOverflow')) ? this.get('content.minValue') : this.get('content.maxValue');
+    }
+    this.set('content.value', value);
+  },
+
+  /**
+   * Handle keyboard event. Allow digits only and some key maps.
+   */
+  keyDown: function (e) {
+    var charCode = (e.charCode) ? e.charCode : e.which;
+    if ([46, 8, 9, 27, 13, 110, 190].contains(charCode) ||
+      (charCode == 65 && e.ctrlKey === true) ||
+      (charCode == 67 && e.ctrlKey === true) ||
+      (charCode == 88 && e.ctrlKey === true) ||
+      (charCode >= 35 && charCode <= 39)) {
+      return;
+    }
+    if ((e.shiftKey || (charCode < 48 || charCode > 57)) && (charCode <
96 || charCode > 105)) {
+      e.preventDefault();
+    }
+  },
+
+  /**
+   * Change value to maximum if exceeded.
+   */
+  keyUp: function (e) {
+    if (!Em.isEmpty(this.get('content.maxValue')) && this.get('content.value') >
this.get('content.maxValue')) {
+      this.set('content.value', this.get('content.maxValue'));
+    }
+  },
+
+  /**
+   * Set value to 0 if user removed it and changed focus to another element.
+   */
+  focusOut: function (e) {
+    if (Em.isEmpty(this.get('content.value'))) {
+      this.set('content.value', 0);
     }
+  }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/7f648f9f/ambari-web/test/mixins/unit_convert/base_unit_convert_mixin_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mixins/unit_convert/base_unit_convert_mixin_test.js b/ambari-web/test/mixins/unit_convert/base_unit_convert_mixin_test.js
index 9f07581..3e30fdb 100644
--- a/ambari-web/test/mixins/unit_convert/base_unit_convert_mixin_test.js
+++ b/ambari-web/test/mixins/unit_convert/base_unit_convert_mixin_test.js
@@ -77,7 +77,7 @@ describe('App.BaseUnitConvertMixin', function() {
         ],
         fromUnit: ["mb", "kb"],
         toUnit: "b",
-        e: 1294336,
+        e: 1294336
       },
       {
         value: [
@@ -86,7 +86,7 @@ describe('App.BaseUnitConvertMixin', function() {
         ],
         fromUnit: "mb,kb",
         toUnit: "b",
-        e: 1294336,
+        e: 1294336
       },
       {
         value: 60000,

http://git-wip-us.apache.org/repos/asf/ambari/blob/7f648f9f/ambari-web/test/views/common/configs/widgets/time_interval_spinner_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/common/configs/widgets/time_interval_spinner_view_test.js
b/ambari-web/test/views/common/configs/widgets/time_interval_spinner_view_test.js
index fe58e45..b9ae58f 100644
--- a/ambari-web/test/views/common/configs/widgets/time_interval_spinner_view_test.js
+++ b/ambari-web/test/views/common/configs/widgets/time_interval_spinner_view_test.js
@@ -17,21 +17,24 @@
  */
 
 var App = require('app');
+var view;
 
-describe('App.TimeIntervalSpinnerView', function() {
-  describe('#generateWidgetValue', function(){
-    beforeEach(function() {
-      this.view = App.TimeIntervalSpinnerView.create({
-        initPopover: Em.K
-      });
-    });
+describe('App.TimeIntervalSpinnerView', function () {
 
-    afterEach(function() {
-      this.view.destroy();
-      this.view = null;
+  beforeEach(function () {
+    view = App.TimeIntervalSpinnerView.create({
+      initPopover: Em.K,
+      checkErrors: Em.K
     });
+  });
 
-    var createProperty = function(widgetUnits, configPropertyUnits) {
+  afterEach(function () {
+    view.destroy();
+  });
+
+  describe('#generateWidgetValue', function () {
+
+    var createProperty = function (widgetUnits, configPropertyUnits, incrementStep) {
       return Em.Object.create({
         stackConfigProperty: Em.Object.create({
           widget: {
@@ -39,80 +42,137 @@ describe('App.TimeIntervalSpinnerView', function() {
               { unit: widgetUnits }
             ]
           },
-          valueAttributes: { unit: configPropertyUnits }
+          valueAttributes: {
+            unit: configPropertyUnits,
+            increment_step: incrementStep
+          }
         })
       });
     };
+
     var tests = [
       {
         input: 60000,
-        config: createProperty("days,hours,minutes", "milliseconds"),
+        config: createProperty("days,hours,minutes", "milliseconds", 1000),
         e: [
-          { label: 'Days', value: 0},
-          { label: 'Hours', value: 0},
-          { label: 'Minutes', value: 1}
+          { label: 'Days', value: 0, incrementStep: 1, enabled: true},
+          { label: 'Hours', value: 0, incrementStep: 1, enabled: true},
+          { label: 'Minutes', value: 1, incrementStep: 1, enabled: true}
         ]
       },
       {
         input: "2592000000",
-        config: createProperty("days,hours,minutes", "milliseconds"),
+        config: createProperty("days,hours,minutes", "milliseconds", 60000),
         e: [
-          { label: 'Days', value: 30},
-          { label: 'Hours', value: 0},
-          { label: 'Minutes', value: 0}
+          { label: 'Days', value: 30, incrementStep: 1, enabled: true},
+          { label: 'Hours', value: 0, incrementStep: 1, enabled: true},
+          { label: 'Minutes', value: 0, incrementStep: 1, enabled: true}
         ]
       },
       {
         input: "604800000",
-        config: createProperty("days,hours,minutes", "milliseconds"),
+        config: createProperty("days,hours,minutes", "milliseconds", 60000),
         e: [
-          { label: 'Days', value: 7},
-          { label: 'Hours', value: 0},
-          { label: 'Minutes', value: 0}
+          { label: 'Days', value: 7, incrementStep: 1, enabled: true},
+          { label: 'Hours', value: 0, incrementStep: 1, enabled: true},
+          { label: 'Minutes', value: 0, incrementStep: 1, enabled: true}
         ]
       },
       {
         input: "804820200",
-        config: createProperty("days,hours,minutes", "milliseconds"),
+        config: createProperty("days,hours,minutes", "milliseconds", 60000),
         e: [
-          { label: 'Days', value: 9},
-          { label: 'Hours', value: 7},
-          { label: 'Minutes', value: 33}
+          { label: 'Days', value: 9, incrementStep: 1, enabled: true},
+          { label: 'Hours', value: 7, incrementStep: 1, enabled: true},
+          { label: 'Minutes', value: 33, incrementStep: 1, enabled: true}
         ]
       },
       {
         input: "70000",
-        config: createProperty("minutes", "milliseconds"),
+        config: createProperty("minutes", "milliseconds", 1000),
         e: [
-          { label: 'Minutes', value: 1}
+          { label: 'Minutes', value: 1, incrementStep: 1, enabled: true}
         ]
       },
       {
         input: "140",
-        config: createProperty("hours,minutes", "minutes"),
+        config: createProperty("hours,minutes", "minutes", 1),
         e: [
-          { label: 'Hours', value: 2},
-          { label: 'Minutes', value: 20}
+          { label: 'Hours', value: 2, incrementStep: 1, enabled: true},
+          { label: 'Minutes', value: 20, incrementStep: 1, enabled: true}
         ]
       },
       {
         input: "2",
-        config: createProperty("hours", "hours"),
+        config: createProperty("hours", "hours", 1),
         e: [
-          { label: 'Hours', value: 2}
+          { label: 'Hours', value: 2, incrementStep: 1, enabled: true}
         ]
       }
     ];
 
-    tests.forEach(function(test) {
-      it('should convert {0} {1} to {2}'.format(test.input, test.config.get('stackConfigProperty.valueAttributes.unit'),
JSON.stringify(test.e)), function() {
-        this.view.set('config', test.config);
-        var result = this.view.generateWidgetValue(test.input, test.inputType, test.desiredUnits).map(function(item)
{
-          // remove unneccessary keys
-          return App.permit(item, ['label', 'value']);
+    tests.forEach(function (test) {
+      it('should convert {0} {1} to {2}'.format(test.input, test.config.get('stackConfigProperty.valueAttributes.unit'),
JSON.stringify(test.e)), function () {
+        view.set('config', test.config);
+        var result = view.generateWidgetValue(test.input, test.inputType, test.desiredUnits).map(function
(item) {
+          // remove unnecessary keys
+          return App.permit(item, ['label', 'value', 'enabled', 'incrementStep']);
         });
         expect(result).to.eql(test.e);
       });
     });
+
+  });
+
+  describe('#parseIncrement', function () {
+
+    var createProperty = function (widgetUnits, configPropertyUnits, incrementStep, value)
{
+      return Em.Object.create({
+        value: value,
+        stackConfigProperty: Em.Object.create({
+          widget: {
+            units: [
+              { unit: widgetUnits }
+            ]
+          },
+          valueAttributes: {
+            unit: configPropertyUnits,
+            minimum: 1,
+            maximum: 2,
+            increment_step: incrementStep
+          }
+        })
+      });
+    };
+
+    Em.A([
+        {
+          input: "120000",
+          config: createProperty("minutes,seconds", "milliseconds", 10000, "120000"),
+          e: [
+            { label: 'Minutes', value: 2, incrementStep: 1, enabled: true},
+            { label: 'Seconds', value: 0, incrementStep: 10, enabled: true}
+          ]
+        },
+        {
+          input: "120000",
+          config: createProperty("minutes,seconds", "milliseconds", 60000, "120000"),
+          e: [
+            { label: 'Minutes', value: 2, incrementStep: 1, enabled: true},
+            { label: 'Seconds', value: 0, incrementStep: 60, enabled: false}
+          ]
+        }
+      ]).forEach(function (test) {
+        it('should convert {0} {1} to {2}'.format(test.input, test.config.get('stackConfigProperty.valueAttributes.unit'),
JSON.stringify(test.e)), function () {
+          view.set('config', test.config);
+          view.prepareContent();
+          var result = view.get('content').map(function (c) {
+            return App.permit(c, ['label', 'value', 'incrementStep', 'enabled']);
+          });
+          expect(result).to.eql(test.e);
+        });
+      });
+
   });
-});
+
+});
\ No newline at end of file


Mime
View raw message