Return-Path: X-Original-To: apmail-ambari-commits-archive@www.apache.org Delivered-To: apmail-ambari-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 85293173C9 for ; Tue, 24 Mar 2015 13:13:33 +0000 (UTC) Received: (qmail 19109 invoked by uid 500); 24 Mar 2015 13:06:52 -0000 Delivered-To: apmail-ambari-commits-archive@ambari.apache.org Received: (qmail 19083 invoked by uid 500); 24 Mar 2015 13:06:52 -0000 Mailing-List: contact commits-help@ambari.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: ambari-dev@ambari.apache.org Delivered-To: mailing list commits@ambari.apache.org Received: (qmail 19074 invoked by uid 99); 24 Mar 2015 13:06:52 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 24 Mar 2015 13:06:52 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 1927EDFF44; Tue, 24 Mar 2015 13:06:52 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: onechiporenko@apache.org To: commits@ambari.apache.org Message-Id: <14ac3d31946c4adcbf38db13849eae9b@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: ambari git commit: AMBARI-10191. YARN configs should show slider-widgets when configured in theme (onechiporenko) Date: Tue, 24 Mar 2015 13:06:52 +0000 (UTC) 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 Authored: Tue Mar 24 14:59:18 2015 +0200 Committer: Oleg Nechiporenko 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 @@ {{#each section in row}} - {{section.displayName}} +

{{section.displayName}}

{{#each subRow in section.subsectionRows}} {{#each subsection in subRow}} - + {{/each}} {{/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 @@ }}
+

{{view.config.name}}

+

{{view.config.description}}

-
-
- {{view Ember.TextField valueBinding="view.mirrorValue" class="input-mini"}} - {{#if view.config.stackConfigProperty.valueAttributes.unit}} - {{view.config.stackConfigProperty.valueAttributes.unit}} - {{/if}} + +
+
+
+ {{view Ember.TextField valueBinding="view.mirrorValue" class="input-mini"}} + {{#if view.config.stackConfigProperty.valueAttributes.unit}} + {{view.config.stackConfigProperty.valueAttributes.unit}} + {{/if}} +
+ {{#if view.valueIsChanged}} +
+ + + +
+ {{/if}} +
-
+
{{view Ember.TextField valueBinding="view.config.value" class="input-mini slider-input"}}
- {{#if view.valueIsChanged}} -
- - - -
- {{/if}}
\ 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 + * subsection.configs 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 widget.type and + * widgetTypeMap). It may throw an error if needed widget can't be found in the widgetTypeMap + * @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 config.stackConfigProperty.valueAttributes.type) + * 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 config.stackConfigProperty.valueAttributes.type) + * 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 parseFunction + * @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
{{subsection.name}} + {{#each config in subsection.configs}} + {{#if config.view}} + {{view config.widget configBinding="config"}} + {{/if}} + {{/each}} +