From 0f18ce13074de22f6222af583dd5fc651787404a Mon Sep 17 00:00:00 2001 From: xzhu Date: Tue, 1 May 2018 13:45:12 -0500 Subject: [PATCH] New: Add number format selector component --- .../components/number-format-selector.js | 60 +++++++++++++++ .../visualization-config/metric-label.js | 47 +----------- .../addon/models/metric-label.js | 4 +- .../components/number-format-selector.hbs | 52 +++++++++++++ .../visualization-config/metric-label.hbs | 54 +------------ .../addon/utils/enums/number-formats.js | 16 ++++ .../app/components/number-format-selector.js | 1 + .../navi-visualizations/components/index.less | 1 + .../components/number-format-selector.less | 34 +++++++++ .../visualization-config/goal-gauge.less | 2 +- .../visualization-config/metric-label.less | 18 +---- .../app/utils/enums/number-formats.js | 1 + .../blueprints/navi-visualizations/index.js | 1 + packages/visualizations/package.json | 1 + .../tests/dummy/app/styles/app.less | 4 + .../components/number-format-selector-test.js | 76 +++++++++++++++++++ .../visualization-config/metric-label-test.js | 70 +---------------- 17 files changed, 264 insertions(+), 178 deletions(-) create mode 100644 packages/visualizations/addon/components/number-format-selector.js create mode 100644 packages/visualizations/addon/templates/components/number-format-selector.hbs create mode 100644 packages/visualizations/addon/utils/enums/number-formats.js create mode 100644 packages/visualizations/app/components/number-format-selector.js create mode 100644 packages/visualizations/app/styles/navi-visualizations/components/number-format-selector.less create mode 100644 packages/visualizations/app/utils/enums/number-formats.js create mode 100644 packages/visualizations/tests/integration/components/number-format-selector-test.js diff --git a/packages/visualizations/addon/components/number-format-selector.js b/packages/visualizations/addon/components/number-format-selector.js new file mode 100644 index 000000000..74a75fc9b --- /dev/null +++ b/packages/visualizations/addon/components/number-format-selector.js @@ -0,0 +1,60 @@ +/** + * Copyright 2018, Yahoo Holdings Inc. + * Licensed under the terms of the MIT license. See accompanying LICENSE.md file for terms. + * + * Usage: + * {{number-format-selector + * format=format + * onUpdateFormat = (action 'onUpdateFormat') + * }} + */ + +import { get, computed } from '@ember/object'; +import { A } from '@ember/array'; +import Component from '@ember/component'; +import layout from '../templates/components/number-format-selector'; +import NumberFormats from 'navi-visualizations/utils/enums/number-formats'; + +export default Component.extend({ + layout, + + /** + * @property {Array} classNames + */ + classNames: ['number-format-selector'], + + /** + * @property {Array} predefinedFormats + * list of format types shown to the user + */ + predefinedFormats: NumberFormats, + + /** + * @property {String} customFormat + * returns empty string if the current format + * is one of the predefined formats + */ + customFormat: computed('format', function () { + let predefinedFormats = A(get(this, 'predefinedFormats')), + currentFormat = get(this, 'format'), + match = predefinedFormats.findBy('format', currentFormat); + return match ? '' : currentFormat; + }), + + actions: { + /** + * @action updateFormat + */ + updateFormat(format) { + this.attrs.onUpdateFormat({ format }); + }, + + /** + * @action clearFormat + * format is cleared after selecting the custom format type + */ + clearFormat() { + this.attrs.onUpdateFormat({ format: '' }); + } + } +}); diff --git a/packages/visualizations/addon/components/visualization-config/metric-label.js b/packages/visualizations/addon/components/visualization-config/metric-label.js index 47a52b9c8..6da172ea7 100644 --- a/packages/visualizations/addon/components/visualization-config/metric-label.js +++ b/packages/visualizations/addon/components/visualization-config/metric-label.js @@ -1,5 +1,5 @@ /** - * Copyright 2017, Yahoo Holdings Inc. + * Copyright 2018, Yahoo Holdings Inc. * Licensed under the terms of the MIT license. See accompanying LICENSE.md file for terms. * * Usage: @@ -7,42 +7,18 @@ * request=request * response=response * options=options + * onUpdateConfig=(action 'onUpdateConfig') * }} */ -import Ember from 'ember'; +import Component from '@ember/component'; import layout from '../../templates/components/visualization-config/metric-label'; -const { get, computed } = Ember; - -export default Ember.Component.extend({ +export default Component.extend({ /** * @property {Object} layout */ layout, - /** - * @property {Array} predefinedFormats - * list of format types shown to the user - */ - predefinedFormats: [ - {name: 'Number', format: '0,0.00', class: "metric-label-config__radio-number"}, - {name: 'Decimal', format: '0.000', class: "metric-label-config__radio-decimal"}, - {name: 'Nice Number', format: '0.0a', class: "metric-label-config__radio-nice-number"}, - {name: 'Money', format: '$0,0[.]00', class: "metric-label-config__radio-money"} - ], - - /** - * @property {String} customFormat - * returns empty string if the current format - * is one of the predefined formats - */ - customFormat: computed('options.format', function() { - let predefinedFormats = Ember.A(get(this, 'predefinedFormats')), - currentFormat = get(this, 'options.format'), - match = predefinedFormats.findBy('format', currentFormat); - return match ? '' : currentFormat; - }), - /** * @property {Array} classNames */ @@ -54,21 +30,6 @@ export default Ember.Component.extend({ */ updateLabel(description) { this.sendAction('onUpdateConfig', { description }); - }, - - /** - * @action updateFormat - */ - updateFormat(format) { - this.sendAction('onUpdateConfig', { format }); - }, - - /** - * @action clearFormat - * format is cleared after selecting the custom format type - */ - clearFormat() { - this.sendAction('onUpdateConfig', { format: '' }); } } }); diff --git a/packages/visualizations/addon/models/metric-label.js b/packages/visualizations/addon/models/metric-label.js index f9ce4a261..85d662cad 100644 --- a/packages/visualizations/addon/models/metric-label.js +++ b/packages/visualizations/addon/models/metric-label.js @@ -3,11 +3,11 @@ * Licensed under the terms of the MIT license. See accompanying LICENSE.md file for terms. */ import VisualizationBase from './visualization'; -import MetricLabelConfig from '../components/visualization-config/metric-label'; import { buildValidations, validator } from 'ember-cp-validations'; import Ember from 'ember'; import DS from 'ember-data'; import { metricFormat } from 'navi-data/helpers/metric-format'; +import NumberFormats from 'navi-visualizations/utils/enums/number-formats'; const { computed, set, get } = Ember; @@ -43,7 +43,7 @@ export default VisualizationBase.extend(Validations, { let metrics = Ember.A( get(request, 'metrics') ), metric = get(metrics, 'firstObject').toJSON(), description = metricFormat(get(metrics, 'firstObject'), get(metrics, 'firstObject.metric.longName')), - allFormats = get(MetricLabelConfig.proto(), 'predefinedFormats'), + allFormats = NumberFormats, format = get(this, 'metadata.format') || get(allFormats[0], 'format'); set(this, 'metadata', { metric, description, format }); diff --git a/packages/visualizations/addon/templates/components/number-format-selector.hbs b/packages/visualizations/addon/templates/components/number-format-selector.hbs new file mode 100644 index 000000000..0e981c548 --- /dev/null +++ b/packages/visualizations/addon/templates/components/number-format-selector.hbs @@ -0,0 +1,52 @@ +{{!-- Copyright 2018, Yahoo Holdings Inc. Licensed under the terms of the MIT license. See accompanying LICENSE.md file for terms. --}} +
+ Format Type +
+
+ {{#each predefinedFormats as |predefinedFormat|}} +
+ {{#radio-button + name='format' + groupValue=(readonly format) + changed=(action 'updateFormat' predefinedFormat.format) + value=predefinedFormat.format + }} + {{predefinedFormat.name}} + {{/radio-button}} +
+ {{/each}} +
+ {{#radio-button + name='format' + groupValue=(readonly format) + value=customFormat + changed=(action 'clearFormat') + }} + Custom + {{/radio-button}} +
+
+ +
+ Format +
+
+ {{input + autofocus=true + class='number-format-selector__format-input number-format-selector__text-input' + name='format-input' + type='text' + maxlength="22" + placeholder='Raw Format' + value=format + enter='updateFormat' + focus-out='updateFormat' + }} +
+ + {{navi-icon 'life-ring' class='number-format-selector__icon-documentation'}} + Format Documentation + diff --git a/packages/visualizations/addon/templates/components/visualization-config/metric-label.hbs b/packages/visualizations/addon/templates/components/visualization-config/metric-label.hbs index 52105cb17..5cfd34036 100644 --- a/packages/visualizations/addon/templates/components/visualization-config/metric-label.hbs +++ b/packages/visualizations/addon/templates/components/visualization-config/metric-label.hbs @@ -1,4 +1,4 @@ -{{!-- Copyright 2017, Yahoo Holdings Inc. Licensed under the terms of the MIT license. See accompanying LICENSE.md file for terms. --}} +{{!-- Copyright 2018, Yahoo Holdings Inc. Licensed under the terms of the MIT license. See accompanying LICENSE.md file for terms. --}}
Label @@ -14,55 +14,5 @@ placeholder='No Label' }}
-
- Format Type -
-
- {{#each predefinedFormats as |format|}} -
- {{#radio-button - name='format' - groupValue=(readonly options.format) - changed=(action 'updateFormat' format.format) - value=format.format - }} - {{format.name}} - {{/radio-button}} -
- {{/each}} -
- {{#radio-button - name='format' - groupValue=(readonly options.format) - value=customFormat - changed=(action 'clearFormat') - }} - Custom - {{/radio-button}} -
-
- -
- Format -
-
- {{input - autofocus=true - class='metric-label-config__format-input metric-label-config__text-input' - name='format-input' - type='text' - maxlength="22" - placeholder='Raw Format' - value=options.format - enter='updateFormat' - focus-out='updateFormat' - }} -
- - {{navi-icon 'life-ring' class='metric-label-config__icon-documentation'}} - Format Documentation - + {{number-format-selector format=options.format onUpdateFormat=onUpdateConfig}}
diff --git a/packages/visualizations/addon/utils/enums/number-formats.js b/packages/visualizations/addon/utils/enums/number-formats.js new file mode 100644 index 000000000..bb3c950af --- /dev/null +++ b/packages/visualizations/addon/utils/enums/number-formats.js @@ -0,0 +1,16 @@ +/** + * Copyright 2018, Yahoo Holdings Inc. + * Licensed under the terms of the MIT license. See accompanying LICENSE.md file for terms. + */ + +import { A } from '@ember/array'; + +/** + * List of number formats + */ +export default A([ + { name: 'Number', format: '0,0.00' }, + { name: 'Decimal', format: '0.000' }, + { name: 'Nice Number', format: '0.0a' }, + { name: 'Money', format: '$0,0[.]00' } +]); \ No newline at end of file diff --git a/packages/visualizations/app/components/number-format-selector.js b/packages/visualizations/app/components/number-format-selector.js new file mode 100644 index 000000000..9c7a2392f --- /dev/null +++ b/packages/visualizations/app/components/number-format-selector.js @@ -0,0 +1 @@ +export { default } from 'navi-visualizations/components/number-format-selector'; \ No newline at end of file diff --git a/packages/visualizations/app/styles/navi-visualizations/components/index.less b/packages/visualizations/app/styles/navi-visualizations/components/index.less index 8c8f4a3bd..623fae37e 100644 --- a/packages/visualizations/app/styles/navi-visualizations/components/index.less +++ b/packages/visualizations/app/styles/navi-visualizations/components/index.less @@ -8,4 +8,5 @@ @import 'chart-series-collection'; @import 'series-selector'; @import 'navi-table-sort-icon'; +@import 'number-format-selector'; @import 'subtotal-dimension-select-trigger'; diff --git a/packages/visualizations/app/styles/navi-visualizations/components/number-format-selector.less b/packages/visualizations/app/styles/navi-visualizations/components/number-format-selector.less new file mode 100644 index 000000000..d2dbb4d99 --- /dev/null +++ b/packages/visualizations/app/styles/navi-visualizations/components/number-format-selector.less @@ -0,0 +1,34 @@ +/** + * Copyright 2018, Yahoo Holdings Inc. + * Licensed under the terms of the MIT license. See accompanying LICENSE.md file for terms. + */ + +.number-format-selector { + &__format-list { + display: flex; + flex-direction: column; + } + + &__format { + height: @report-form-height; + } + + &__doc-link { + font-size: 15px; + } + + &__format-input { + font-size: @font-size-base-large; + } + + &__section { + .config-section(); + } + + &__text-input { + font-family: @font-family-thin; + line-height: @navi-ideal-line-height; + overflow-y: hidden; + padding: 0; + } +} diff --git a/packages/visualizations/app/styles/navi-visualizations/components/visualization-config/goal-gauge.less b/packages/visualizations/app/styles/navi-visualizations/components/visualization-config/goal-gauge.less index e9dc92c4f..0f0dfba7f 100644 --- a/packages/visualizations/app/styles/navi-visualizations/components/visualization-config/goal-gauge.less +++ b/packages/visualizations/app/styles/navi-visualizations/components/visualization-config/goal-gauge.less @@ -16,7 +16,7 @@ } .goal-gauge-config__goal-input, .goal-gauge-config__baseline-input { - .metric-label-config__format-input; + font-size: @font-size-base-large; } .goal-gauge-config__section { diff --git a/packages/visualizations/app/styles/navi-visualizations/components/visualization-config/metric-label.less b/packages/visualizations/app/styles/navi-visualizations/components/visualization-config/metric-label.less index 79dade127..1abd814be 100644 --- a/packages/visualizations/app/styles/navi-visualizations/components/visualization-config/metric-label.less +++ b/packages/visualizations/app/styles/navi-visualizations/components/visualization-config/metric-label.less @@ -5,15 +5,13 @@ .metric-label-config { .config-container(); -} -.metric-label-config__format-list { - display: flex; - flex-direction: column; + .number-format-selector__section-header { + .metric-label-config__section-header; + } } -.metric-label-config__description, -.metric-label-config__format { +.metric-label-config__description { height: @report-form-height; } @@ -21,14 +19,6 @@ font-size: @font-size-base-large; } -.metric-label-config__doc-link { - font-size: 15px; -} - -.metric-label-config__format-input { - font-size: @font-size-base-large; -} - .metric-label-config__section { .config-section(); } diff --git a/packages/visualizations/app/utils/enums/number-formats.js b/packages/visualizations/app/utils/enums/number-formats.js new file mode 100644 index 000000000..623ba7aec --- /dev/null +++ b/packages/visualizations/app/utils/enums/number-formats.js @@ -0,0 +1 @@ +export { default } from 'navi-visualizations/utils/enums/number-formats'; diff --git a/packages/visualizations/blueprints/navi-visualizations/index.js b/packages/visualizations/blueprints/navi-visualizations/index.js index 68d607bc4..940705e26 100644 --- a/packages/visualizations/blueprints/navi-visualizations/index.js +++ b/packages/visualizations/blueprints/navi-visualizations/index.js @@ -26,6 +26,7 @@ module.exports = { { name: 'ember-power-select', target: '1.10.4' }, { name: 'ember-radio-button', target: '1.2.1' }, { name: 'ember-sortable', target: '1.10.0' }, + { name: 'ember-cli-string-helpers', target: '1.8.1' }, { name: 'ember-tether', target: '0.4.1' }, { name: 'ember-toggle', target: '5.2.1' }, { name: 'ember-tooltips', target: '2.9.2' }, diff --git a/packages/visualizations/package.json b/packages/visualizations/package.json index 732f4a62b..796f8000c 100644 --- a/packages/visualizations/package.json +++ b/packages/visualizations/package.json @@ -42,6 +42,7 @@ "ember-cli-qunit": "^4.2.1", "ember-cli-shims": "^1.1.0", "ember-cli-sri": "^2.1.0", + "ember-cli-string-helpers": "^1.8.1", "ember-cli-uglify": "^2.0.0", "ember-collection": "1.0.0-alpha.7", "ember-composable-helpers": "^2.1.0", diff --git a/packages/visualizations/tests/dummy/app/styles/app.less b/packages/visualizations/tests/dummy/app/styles/app.less index ebabfb7ca..b4c501f62 100644 --- a/packages/visualizations/tests/dummy/app/styles/app.less +++ b/packages/visualizations/tests/dummy/app/styles/app.less @@ -96,3 +96,7 @@ h3 { transform: none !important; zoom: 50%; } + +.visualization-config { + min-height: 500px; +} \ No newline at end of file diff --git a/packages/visualizations/tests/integration/components/number-format-selector-test.js b/packages/visualizations/tests/integration/components/number-format-selector-test.js new file mode 100644 index 000000000..03c0c3fa6 --- /dev/null +++ b/packages/visualizations/tests/integration/components/number-format-selector-test.js @@ -0,0 +1,76 @@ +import { run } from '@ember/runloop'; +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; +import wait from 'ember-test-helpers/wait'; + +let Template = hbs` + {{number-format-selector + format=format + onUpdateFormat=(action onUpdateFormat) + }}`; + +moduleForComponent('number-format-selector', 'Integration | Component | number format selector', { + integration: true, + beforeEach() { + this.set('format', '$0,0[.]00'); + this.set('onUpdateFormat', () => null); + } +}); + +test('updateFormat from radio button', function (assert) { + assert.expect(1); + + this.set('onUpdateFormat', result => { + assert.equal(result.format, + '0,0.00', + 'onUpdateFormat action is called by radio button'); + }); + + this.render(Template); + + run(() => { + $('.number-format-selector__radio-number input').click(); + }); +}); + +test('clearFormat', function (assert) { + assert.expect(1); + + this.set('onUpdateFormat', result => { + assert.equal(result.format, + '', + 'onUpdateFormat action is called by custom format radio button'); + }); + + this.render(Template); + + run(() => { + $('.number-format-selector__radio-custom input').click(); + }); +}); + +test('highlight correct format when customFormat is changed', function (assert) { + assert.expect(2); + + this.render(Template); + + run(() => { + $('.number-format-selector__format-input').val('$0,0[.]00a'); + $('.number-format-selector__format-input').focusout(); + }); + + return wait().then(() => { + assert.ok($('.number-format-selector__radio-custom input').prop('checked'), + 'custom format correctly highlighted when user enters custom format'); + + run(() => { + $('.number-format-selector__format-input').val('0,0.00'); + $('.number-format-selector__format-input').focusout(); + }); + + return wait().then(() => { + assert.ok($('.number-format-selector__radio-number input').prop('checked'), + 'number format correctly highlighted when user enters number format'); + }); + }); +}); diff --git a/packages/visualizations/tests/integration/components/visualization-config/metric-label-test.js b/packages/visualizations/tests/integration/components/visualization-config/metric-label-test.js index 1bacbd6e6..3a6a6c93b 100644 --- a/packages/visualizations/tests/integration/components/visualization-config/metric-label-test.js +++ b/packages/visualizations/tests/integration/components/visualization-config/metric-label-test.js @@ -1,6 +1,5 @@ import Ember from 'ember'; import { moduleForComponent, test } from 'ember-qunit'; -import wait from 'ember-test-helpers/wait'; import hbs from 'htmlbars-inline-precompile'; let Template = hbs` @@ -32,7 +31,7 @@ test('component renders', function(assert) { 'Glass Bottles of the ranch\'s finest pasteurized whole milk!!!!!!!', 'Component correctly displays initial description'); - assert.equal(this.$('.metric-label-config__format-input').val().trim(), + assert.equal(this.$('.number-format-selector__format-input').val().trim(), '$0,0[.]00', 'Component correctly displays initial format'); }); @@ -49,8 +48,8 @@ test('onUpdateConfig format input', function(assert) { this.render(Template); Ember.run(() => { - $('.metric-label-config__format-input').val('foo'); - $('.metric-label-config__format-input').focusout(); + $('.number-format-selector__format-input').val('foo'); + $('.number-format-selector__format-input').focusout(); }); }); @@ -69,65 +68,4 @@ test('onUpdateConfig description input', function(assert) { $('.metric-label-config__description-input').val('foo'); $('.metric-label-config__description-input').focusout(); }); -}); - -test('updateFormat from radio button', function(assert) { - assert.expect(1); - - this.set('onUpdateConfig', result => { - assert.equal(result.format, - '0,0.00', - 'onUpdateConfig action is called by radio button'); - }); - - this.render(Template); - - Ember.run(() => { - $('.metric-label-config__radio-number input').click(); - }); -}); - -test('clearFormat', function(assert) { - assert.expect(1); - - this.set('onUpdateConfig', result => { - assert.equal(result.format, - '', - 'onUpdateConfig action is called by custom format radio button'); - }); - - this.render(Template); - - Ember.run(() => { - $('.metric-label-config__radio-custom input').click(); - }); -}); - -test('highlight correct format when customFormat is changed', function(assert) { - assert.expect(2); - - return wait().then(() => { - this.render(Template); - - Ember.run(() => { - $('.metric-label-config__format-input').val('$0,0[.]00a'); - $('.metric-label-config__format-input').focusout(); - }); - return wait().then(() => { - assert.equal($('.metric-label-config__radio-custom input').prop('checked'), - true, - 'custom format correctly highlighted when user enters custom format'); - - Ember.run(() => { - $('.metric-label-config__format-input').val('0,0.00'); - $('.metric-label-config__format-input').focusout(); - }); - - return wait().then(() => { - assert.equal($('.metric-label-config__radio-number input').prop('checked'), - true, - 'number format correctly highlighted when user enters number format'); - }); - }); - }); -}); +}); \ No newline at end of file