From c6ccde8e07778bbeaa5a0b70da9cf90b94144437 Mon Sep 17 00:00:00 2001 From: Zach Zibrat Date: Tue, 15 Nov 2016 16:48:55 -0800 Subject: [PATCH] improves axis helper (#52) adds more D3 axis methods, allows for more intuitive axis configuration. Needed new version of `ember-d3-helpers`, which required upgrade to Ember v2.9. Allows `ember-try` failures in Glimmer2 (https://github.com/LocusEnergy/ember-sparkles/issues/53) --- .editorconfig | 14 ------- .travis.yml | 27 +++++++------ README.md | 11 +++++- addon/helpers/e-s/axis-helper.js | 39 +++++-------------- addon/helpers/e-s/axis-options.js | 18 +++++++++ addon/page-objects/grouped-bar-chart.js | 6 +-- addon/templates/components/e-s/axis.hbs | 19 ++++----- addon/templates/components/ember-sparkles.hbs | 5 ++- app/helpers/e-s/axis-options.js | 1 + bower.json | 4 +- config/ember-try.js | 11 ------ package.json | 34 ++++++++-------- testem.js | 4 +- .../app/controllers/grouped-bar-chart.js | 3 +- tests/dummy/app/templates/bar-chart.hbs | 2 +- .../dummy/app/templates/grouped-bar-chart.hbs | 5 ++- tests/dummy/app/templates/line-chart.hbs | 2 +- tests/dummy/config/environment.js | 4 ++ tests/index.html | 4 +- tests/integration/components/e-s/axis-test.js | 2 +- .../components/e-s/grouped-bar-chart-test.js | 2 +- tests/unit/helpers/e-s/axis-options-test.js | 11 ++++++ 22 files changed, 114 insertions(+), 114 deletions(-) create mode 100644 addon/helpers/e-s/axis-options.js create mode 100644 app/helpers/e-s/axis-options.js create mode 100644 tests/unit/helpers/e-s/axis-options-test.js diff --git a/.editorconfig b/.editorconfig index 47c5438..219985c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,22 +13,8 @@ insert_final_newline = true indent_style = space indent_size = 2 -[*.js] -indent_style = space -indent_size = 2 - [*.hbs] insert_final_newline = false -indent_style = space -indent_size = 2 - -[*.css] -indent_style = space -indent_size = 2 - -[*.html] -indent_style = space -indent_size = 2 [*.{diff,md}] trim_trailing_whitespace = false diff --git a/.travis.yml b/.travis.yml index 2033476..ad29b51 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,14 @@ --- language: node_js node_js: - - "4.2" + - "4" -sudo: required dist: trusty +sudo: required + +cache: + directories: + - node_modules addons: apt: @@ -13,33 +17,32 @@ addons: packages: - google-chrome-stable -cache: - directories: - - node_modules - env: + # we recommend testing LTS's and latest stable release (bonus points to beta/canary) - EMBER_TRY_SCENARIO=default - EMBER_TRY_SCENARIO=ember-release - # - EMBER_TRY_SCENARIO=ember-beta - - EMBER_TRY_SCENARIO=ember-canary + matrix: fast_finish: true allow_failures: - - env: EMBER_TRY_SCENARIO=ember-canary + - env: + - EMBER_TRY_SCENARIO=ember-beta + - EMBER_TRY_SCENARIO=ember-canary before_install: + - if [[ `npm -v` != 3* ]]; then npm i -g npm@3; fi - export DISPLAY=:99.0 - sh -e /etc/init.d/xvfb start - npm config set spin false - - npm install -g npm@^2 + - npm install -g bower + - bower --version install: - - npm install -g bower - npm install - bower install script: # Usually, it's ok to finish the test scenario without reverting # to the addon's original dependency state, skipping "cleanup". - - ember try:one $EMBER_TRY_SCENARIO test --skip-cleanup + - ember try:one $EMBER_TRY_SCENARIO test --skip-cleanup \ No newline at end of file diff --git a/README.md b/README.md index d70989f..11a1971 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ To render an axis, add `{{chart.y-axis}}` or `{{chart.x-axis}}` to the `{{#ember ```hbs {{#ember-sparkles as |chart|}} {{chart.x-axis - tick-format='%Y-%m-%d' + tick-format=(d3-time-format '%Y-%m-%d') label='date' dy=100 dx=-100 @@ -98,14 +98,21 @@ To render an axis, add `{{chart.y-axis}}` or `{{chart.x-axis}}` to the `{{#ember {{chart.y-axis label='kWh' + position='right' ticks=5 - yGrid=true + tick-format=(d3-format '.2s') + gridlines=true dx=100 dy=-30 }} {{/ember-sparkles}} ``` +Similar to the `y-axis` example, the `x-axis` contextual component can take a `position` property, set to `top` (by default these are set to `left` and `bottom`), respectively). + +For more information on configuring tick formats using the `d3-time-format` and `d3-format` helpers, please see +[d3-format](https://github.com/d3/d3-format) and [d3-time-format](https://github.com/d3/d3-time-format), respectively. + ### Legend To show a legend, add `{{chart.legend}}` to the `{{#ember-sparkles}}` block. diff --git a/addon/helpers/e-s/axis-helper.js b/addon/helpers/e-s/axis-helper.js index bf61284..94904c7 100644 --- a/addon/helpers/e-s/axis-helper.js +++ b/addon/helpers/e-s/axis-helper.js @@ -1,39 +1,20 @@ import Ember from 'ember'; import axis from 'd3-axis'; -import { timeFormat } from 'd3-time-format'; - -const tickFilter = (tickFormat, skipIdx) => { - let formatter = timeFormat(tickFormat); - return (d, idx) => { - if (idx % skipIdx === 0) { - return formatter(d); - } - }; -}; const { String: { capitalize } } = Ember; -export function emberSparklesAxis([ scale ], { position, tickFormat, ticks, width, height, skipIdx=1, xGrid, yGrid }) { - let axisType = `axis${capitalize(position)}`; - let axisFn = axis[axisType]; - - let result = axisFn().scale(scale); - - if (tickFormat) { - result.tickFormat(tickFilter(tickFormat, skipIdx)); - } - - if (ticks) { - result.ticks(ticks); - } +export function emberSparklesAxis([ scale ], { position, ticks, tickFormat, tickValues, tickSizeInner=6, tickSizeOuter=6, tickPadding=3, gridlines=false, gridLength }) { + let axisFn = axis[`axis${capitalize(position)}`]; + let result = axisFn().scale(scale); - if (yGrid) { - result.tickSizeInner((-1)*width); - } + result.ticks(ticks); + result.tickFormat(tickFormat); + result.tickValues(tickValues); - if (xGrid) { - result.tickSizeInner((-1)*height); - } + let innerSize = gridlines ? (-1) * gridLength : tickSizeInner; + result.tickSizeInner(innerSize); + result.tickSizeOuter(tickSizeOuter); + result.tickPadding(tickPadding); return result; } diff --git a/addon/helpers/e-s/axis-options.js b/addon/helpers/e-s/axis-options.js new file mode 100644 index 0000000..f021e5c --- /dev/null +++ b/addon/helpers/e-s/axis-options.js @@ -0,0 +1,18 @@ +import Ember from 'ember'; + +export function axisOptions([ position, width, height, x=0, y=0 ]) { + let w = position === 'right' ? width : 0; + let h = position === 'bottom' ? height : 0; + let translate = `translate(${w + x},${h + y})`; + + let gridLength; + if (position === 'left' || position === 'right') { + gridLength = width; + } else { + gridLength = height; + } + + return { gridLength, translate }; +} + +export default Ember.Helper.helper(axisOptions); diff --git a/addon/page-objects/grouped-bar-chart.js b/addon/page-objects/grouped-bar-chart.js index 444698a..cbcef16 100644 --- a/addon/page-objects/grouped-bar-chart.js +++ b/addon/page-objects/grouped-bar-chart.js @@ -1,5 +1,3 @@ -/* global $ */ - export default class GroupedBarChart { constructor(env) { this.env = env; @@ -11,11 +9,11 @@ export default class GroupedBarChart { } rect(method, property) { - let rects = this.groups().map((idx, g) => $(g).children()).toArray(); + let rects = this.groups().map((idx, g) => this.$(g).children()).toArray(); if (!arguments.length) { return rects; } else { - return rects.map(g => g.map((idx, r) => $(r)[method](property)).toArray()); + return rects.map(g => g.map((idx, r) => this.$(r)[method](property)).toArray()); } } diff --git a/addon/templates/components/e-s/axis.hbs b/addon/templates/components/e-s/axis.hbs index a484a79..4762ca0 100644 --- a/addon/templates/components/e-s/axis.hbs +++ b/addon/templates/components/e-s/axis.hbs @@ -1,12 +1,11 @@ -{{#with (e-s/axis-helper scale +{{#let (e-s/axis-options position width height x-translate y-translate) as |options|}} +{{#let (e-s/axis-helper scale position=position ticks=ticks - width=width - height=height tickFormat=tick-format - skipIdx=responsiveSkipIdx - xGrid=xGrid - yGrid=yGrid + tickValues=tick-values + gridlines=gridlines + gridLength=(get options 'gridLength') ) as |axis|}} {{#d3-graph classNames="ember-sparkles--axis" as |d3|}} @@ -19,7 +18,7 @@ {{d3.graph (pipe (d3-select-all '.axis') (if with-transition (d3-transition transition) (d3-noop)) - (d3-attr 'transform' (i 'translate(${w},${h})' w=(or x-translate 0) h=(or height 0))) + (d3-attr 'transform' (get options 'translate')) (d3-call axis) )}} @@ -33,7 +32,7 @@ (d3-select-all '.label') (d3-attr 'dy' (or dy 0)) (d3-attr 'dx' (or dx 0)) - (d3-call (or labelAttrs (d3-noop))) + (d3-call (or label-attrs (d3-noop))) (d3-call (or label-transform (d3-noop))) (d3-style 'text-anchor' 'end') (d3-text label) @@ -42,4 +41,6 @@ {{/d3-graph}} -{{/with}} +{{/let}} +{{/let}} + diff --git a/addon/templates/components/ember-sparkles.hbs b/addon/templates/components/ember-sparkles.hbs index 1203331..47d601b 100644 --- a/addon/templates/components/ember-sparkles.hbs +++ b/addon/templates/components/ember-sparkles.hbs @@ -20,12 +20,13 @@ {{yield (hash x-scale=(compute options.x-scale) y-scale=(compute options.y-scale) + x-axis=(component 'e-s/axis' scale=(compute options.x-scale) position='bottom' height=innerHeight transition=options.transition - labelAttrs=(pipe (d3-attr 'x' width)) + label-attrs=(pipe (d3-attr 'x' width)) ) y-axis=(component 'e-s/axis' @@ -33,7 +34,7 @@ position='left' width=innerWidth transition=options.transition - labelAttrs=(pipe (d3-attr 'transform' 'rotate(-90)')) + label-attrs=(pipe (d3-attr 'transform' 'rotate(-90)')) ) bar-chart=(component 'e-s/bar-chart' diff --git a/app/helpers/e-s/axis-options.js b/app/helpers/e-s/axis-options.js new file mode 100644 index 0000000..50ffb7a --- /dev/null +++ b/app/helpers/e-s/axis-options.js @@ -0,0 +1 @@ +export { default, axisOptions } from 'ember-sparkles/helpers/e-s/axis-options'; diff --git a/bower.json b/bower.json index 0660987..4910356 100644 --- a/bower.json +++ b/bower.json @@ -1,8 +1,8 @@ { "name": "ember-sparkles", "dependencies": { - "ember": "~2.8.0", - "ember-cli-shims": "0.1.1", + "ember": "~2.9.0", + "ember-cli-shims": "0.1.3", "moment-range": "^2.2.0" } } diff --git a/config/ember-try.js b/config/ember-try.js index 014f603..be846e1 100644 --- a/config/ember-try.js +++ b/config/ember-try.js @@ -7,17 +7,6 @@ module.exports = { dependencies: { } } }, - { - name: 'ember-1.13', - bower: { - dependencies: { - 'ember': '~1.13.0' - }, - resolutions: { - 'ember': '~1.13.0' - } - } - }, { name: 'ember-release', bower: { diff --git a/package.json b/package.json index ef9a1f7..8d9d13b 100644 --- a/package.json +++ b/package.json @@ -20,33 +20,33 @@ "license": "MIT", "devDependencies": { "babel-eslint": "^6.1.2", - "broccoli-asset-rev": "^2.4.2", - "ember-ajax": "2.0.1", - "ember-cli": "2.8.0", - "ember-cli-app-version": "^1.0.0", - "ember-cli-dependency-checker": "^1.2.0", + "broccoli-asset-rev": "^2.4.5", + "ember-ajax": "2.4.1", + "ember-cli": "2.9.1", + "ember-cli-app-version": "^2.0.0", + "ember-cli-dependency-checker": "^1.3.0", "ember-cli-deploy": "0.5.1", "ember-cli-eslint": "3.0.0", "ember-cli-github-pages": "0.1.0", "ember-cli-htmlbars": "^1.0.3", - "ember-cli-htmlbars-inline-precompile": "^0.3.1", - "ember-cli-inject-live-reload": "^1.4.0", - "ember-cli-qunit": "^2.1.0", + "ember-cli-htmlbars-inline-precompile": "^0.3.3", + "ember-cli-inject-live-reload": "^1.4.1", + "ember-cli-qunit": "^3.0.1", "ember-cli-release": "1.0.0-beta.2", - "ember-cli-sass": "5.3.1", + "ember-cli-sass": "5.6.0", "ember-cli-sri": "^2.1.0", "ember-cli-test-loader": "^1.1.0", "ember-cli-uglify": "^1.2.0", "ember-code-snippet": "1.4.0", "ember-computed-decorators": "0.2.2", "ember-concurrency": "0.7.8", - "ember-data": "^2.8.0", + "ember-data": "^2.9.0", "ember-disable-prototype-extensions": "^1.1.0", "ember-export-application-global": "^1.0.5", - "ember-let": "0.5.0", + "ember-let": "0.5.3", "ember-load-initializers": "^0.5.1", "ember-resolver": "^2.0.3", - "loader.js": "^4.0.1" + "loader.js": "^4.0.10" }, "keywords": [ "ember-addon", @@ -55,12 +55,12 @@ "htmlbars" ], "dependencies": { - "ember-cli-babel": "^5.1.6", - "ember-cli-d3-shape": "0.9.4-4.1.1.0", - "ember-cli-htmlbars": "^1.0.3", + "ember-cli-babel": "^5.1.7", + "ember-cli-htmlbars": "^1.0.10", "ember-composable-helpers": "1.0.0", - "ember-d3-helpers": "0.5.8", - "ember-interpolate-helper": "0.1.1", + "ember-d3": "^0.3.0", + "ember-d3-helpers": "0.5.11", + "ember-interpolate-helper": "1.0.0", "ember-lodash": "0.0.7", "ember-math-helpers": "1.2.2", "ember-reactive-helpers": "0.3.7", diff --git a/testem.js b/testem.js index 6256423..a2295b3 100644 --- a/testem.js +++ b/testem.js @@ -7,6 +7,6 @@ module.exports = { "Chrome" ], "launch_in_dev": [ - "PhantomJS", + "Chrome" ] -}; +}; \ No newline at end of file diff --git a/tests/dummy/app/controllers/grouped-bar-chart.js b/tests/dummy/app/controllers/grouped-bar-chart.js index 6eb1629..70f4f80 100644 --- a/tests/dummy/app/controllers/grouped-bar-chart.js +++ b/tests/dummy/app/controllers/grouped-bar-chart.js @@ -15,14 +15,13 @@ let generateData = function() { let dateRange = moment.range(start, end); let series = ['series 1', 'series 2', 'series 3', 'series 4', 'series 5', 'series 6', 'series 7']; let valueType = 'W'; - let seriesSample = _.sample(series, _.random(2, _.size(series))); return dateRange.toArray('days').map(d => { let seriesData = seriesSample.map(s => { return { name: s, - value: _.random(10, 1050) + value: _.random(1000, 10000) }; }); return { diff --git a/tests/dummy/app/templates/bar-chart.hbs b/tests/dummy/app/templates/bar-chart.hbs index 9f517af..4adc5f9 100644 --- a/tests/dummy/app/templates/bar-chart.hbs +++ b/tests/dummy/app/templates/bar-chart.hbs @@ -13,7 +13,7 @@ as |chart|}} {{chart.x-axis - tick-format='%Y-%m-%d' + tick-format=(d3-time-format '%Y-%m-%d') label='Date (Y-M-D)' dy=(add chart.height 30) dx=-100 diff --git a/tests/dummy/app/templates/grouped-bar-chart.hbs b/tests/dummy/app/templates/grouped-bar-chart.hbs index 5fd6638..b590c10 100644 --- a/tests/dummy/app/templates/grouped-bar-chart.hbs +++ b/tests/dummy/app/templates/grouped-bar-chart.hbs @@ -18,7 +18,7 @@ as |chart|}} {{chart.x-axis - tick-format='%Y-%m-%d' + tick-format=(d3-time-format '%Y-%m-%d') label='Date (Y-M-D)' dy=(add chart.height 30) dx=-100 @@ -27,7 +27,8 @@ as |chart|}} {{chart.y-axis label='Watts' ticks=5 - yGrid=true + tick-format=(d3-format '.2s') + gridlines=true dx=(mult -0.5 chart.height) dy=-30 }} diff --git a/tests/dummy/app/templates/line-chart.hbs b/tests/dummy/app/templates/line-chart.hbs index 9e92977..cb99816 100644 --- a/tests/dummy/app/templates/line-chart.hbs +++ b/tests/dummy/app/templates/line-chart.hbs @@ -20,7 +20,7 @@ {{chart.line-chart}} {{chart.x-axis - tick-format='%Y-%m-%d' + tick-format=(d3-time-format '%Y-%m-%d') label='date' dy=(add chart.height 30) dx=-100 diff --git a/tests/dummy/config/environment.js b/tests/dummy/config/environment.js index 804460a..2c3ef23 100644 --- a/tests/dummy/config/environment.js +++ b/tests/dummy/config/environment.js @@ -10,6 +10,10 @@ module.exports = function(environment) { FEATURES: { // Here you can enable experimental features on an ember canary build // e.g. 'with-controller': true + }, + EXTEND_PROTOTYPES: { + // Prevent Ember Data from overriding Date.parse. + Date: false } }, diff --git a/tests/index.html b/tests/index.html index b89438b..0a0e793 100644 --- a/tests/index.html +++ b/tests/index.html @@ -11,7 +11,7 @@ {{content-for "test-head"}} - + {{content-for "head-footer"}} @@ -21,7 +21,7 @@ {{content-for "body"}} {{content-for "test-body"}} - + diff --git a/tests/integration/components/e-s/axis-test.js b/tests/integration/components/e-s/axis-test.js index 7445e54..9021c42 100644 --- a/tests/integration/components/e-s/axis-test.js +++ b/tests/integration/components/e-s/axis-test.js @@ -5,7 +5,7 @@ moduleForComponent('ember-sparkles/axis', 'Integration | Component | ember spark integration: true }); -test('accepts a scale argument', function(assert) { +test('accepts a dynamic scale property', function(assert) { this.set('domain', ['2016-03-02', '2016-03-03', '2016-03-04', '2016-03-05']); this.render(hbs` diff --git a/tests/integration/components/e-s/grouped-bar-chart-test.js b/tests/integration/components/e-s/grouped-bar-chart-test.js index b36e372..909b574 100644 --- a/tests/integration/components/e-s/grouped-bar-chart-test.js +++ b/tests/integration/components/e-s/grouped-bar-chart-test.js @@ -165,7 +165,7 @@ test('accepts data and dynamically generates rectangles and legend', function(as // check deletion of data data.pop(); - this.setProperties({ + this.setProperties({ data, xDomain: data.map(({ ts }) => ts) }); diff --git a/tests/unit/helpers/e-s/axis-options-test.js b/tests/unit/helpers/e-s/axis-options-test.js new file mode 100644 index 0000000..da0f891 --- /dev/null +++ b/tests/unit/helpers/e-s/axis-options-test.js @@ -0,0 +1,11 @@ +import { axisOptions } from 'dummy/helpers/e-s/axis-options'; +import { module, test } from 'qunit'; + +module('Unit | Helper | axis options'); + +// Replace this with your real tests. +test('it works', function(assert) { + let result = axisOptions([42]); + assert.ok(result); +}); +