From 1109a5cea46b25b3bd27b095c5fd11881d88bd72 Mon Sep 17 00:00:00 2001 From: Winnie Hellmann Date: Tue, 12 Dec 2017 12:39:31 +0100 Subject: [PATCH] Move dateTickFormat to separate module --- .../graphs/stat_graph_contributors_graph.js | 20 ++-------- .../javascripts/lib/utils/tick_formats.js | 39 ++++++++++++++++++ spec/javascripts/helpers/locale_helper.js | 11 +++++ .../lib/utils/tick_formats_spec.js | 40 +++++++++++++++++++ spec/javascripts/locale/index_spec.js | 10 +---- 5 files changed, 94 insertions(+), 26 deletions(-) create mode 100644 app/assets/javascripts/lib/utils/tick_formats.js create mode 100644 spec/javascripts/helpers/locale_helper.js create mode 100644 spec/javascripts/lib/utils/tick_formats_spec.js diff --git a/app/assets/javascripts/graphs/stat_graph_contributors_graph.js b/app/assets/javascripts/graphs/stat_graph_contributors_graph.js index 55ddebe7c10..187f3c008e8 100644 --- a/app/assets/javascripts/graphs/stat_graph_contributors_graph.js +++ b/app/assets/javascripts/graphs/stat_graph_contributors_graph.js @@ -1,25 +1,11 @@ /* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, max-len, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, comma-dangle, no-return-assign, prefer-arrow-callback, quotes, prefer-template, newline-per-chained-call, no-else-return, no-shadow */ import _ from 'underscore'; import d3 from 'd3'; -import { createDateTimeFormat } from '../locale'; +import { dateTickFormat } from '../lib/utils/tick_formats'; const extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; const hasProp = {}.hasOwnProperty; -const dayFormat = createDateTimeFormat({ month: 'short', day: 'numeric' }); -const monthFormat = createDateTimeFormat({ month: 'long' }); -const yearFormat = createDateTimeFormat({ year: 'numeric' }); - -const xTickFormat = (date) => { - if (date.getDate() !== 1) { - return dayFormat.format(date); - } else if (date.getMonth() > 0) { - return monthFormat.format(date); - } else { - return yearFormat.format(date); - } -}; - export const ContributorsGraph = (function() { function ContributorsGraph() {} @@ -152,7 +138,7 @@ export const ContributorsMasterGraph = (function(superClass) { this.x_axis = d3.svg.axis() .scale(this.x) .orient('bottom') - .tickFormat(xTickFormat); + .tickFormat(dateTickFormat); return this.y_axis = d3.svg.axis().scale(this.y).orient("left").ticks(5); }; @@ -244,7 +230,7 @@ export const ContributorsAuthorGraph = (function(superClass) { .scale(this.x) .orient('bottom') .ticks(8) - .tickFormat(xTickFormat); + .tickFormat(dateTickFormat); return this.y_axis = d3.svg.axis().scale(this.y).orient("left").ticks(5); }; diff --git a/app/assets/javascripts/lib/utils/tick_formats.js b/app/assets/javascripts/lib/utils/tick_formats.js new file mode 100644 index 00000000000..0c10a85e336 --- /dev/null +++ b/app/assets/javascripts/lib/utils/tick_formats.js @@ -0,0 +1,39 @@ +import { createDateTimeFormat } from '../../locale'; + +let dateTimeFormats; + +export const initDateFormats = () => { + const dayFormat = createDateTimeFormat({ month: 'short', day: 'numeric' }); + const monthFormat = createDateTimeFormat({ month: 'long' }); + const yearFormat = createDateTimeFormat({ year: 'numeric' }); + + dateTimeFormats = { + dayFormat, + monthFormat, + yearFormat, + }; +}; + +initDateFormats(); + +/** + Formats a localized date in way that it can be used for d3.js axis.tickFormat(). + + That is, it displays + - 4-digit for first of January + - full month name for first of every month + - day and abbreviated month otherwise + + see also https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Axes.md#tickFormat + */ +export const dateTickFormat = (date) => { + if (date.getDate() !== 1) { + return dateTimeFormats.dayFormat.format(date); + } + + if (date.getMonth() > 0) { + return dateTimeFormats.monthFormat.format(date); + } + + return dateTimeFormats.yearFormat.format(date); +}; diff --git a/spec/javascripts/helpers/locale_helper.js b/spec/javascripts/helpers/locale_helper.js new file mode 100644 index 00000000000..99e6ce61234 --- /dev/null +++ b/spec/javascripts/helpers/locale_helper.js @@ -0,0 +1,11 @@ +/* eslint-disable import/prefer-default-export */ + +export const setLanguage = (languageCode) => { + const htmlElement = document.querySelector('html'); + + if (languageCode) { + htmlElement.setAttribute('lang', languageCode); + } else { + htmlElement.removeAttribute('lang'); + } +}; diff --git a/spec/javascripts/lib/utils/tick_formats_spec.js b/spec/javascripts/lib/utils/tick_formats_spec.js new file mode 100644 index 00000000000..283989b4fc8 --- /dev/null +++ b/spec/javascripts/lib/utils/tick_formats_spec.js @@ -0,0 +1,40 @@ +import { dateTickFormat, initDateFormats } from '~/lib/utils/tick_formats'; + +import { setLanguage } from '../../helpers/locale_helper'; + +describe('tick formats', () => { + describe('dateTickFormat', () => { + beforeAll(() => { + setLanguage('de'); + initDateFormats(); + }); + + afterAll(() => { + setLanguage(null); + }); + + it('returns year for first of January', () => { + const tick = dateTickFormat(new Date('2001-01-01')); + + expect(tick).toBe('2001'); + }); + + it('returns month for first of February', () => { + const tick = dateTickFormat(new Date('2001-02-01')); + + expect(tick).toBe('Februar'); + }); + + it('returns day and month for second of February', () => { + const tick = dateTickFormat(new Date('2001-02-02')); + + expect(tick).toBe('2. Feb.'); + }); + + it('ignores time', () => { + const tick = dateTickFormat(new Date('2001-02-02 12:34:56')); + + expect(tick).toBe('2. Feb.'); + }); + }); +}); diff --git a/spec/javascripts/locale/index_spec.js b/spec/javascripts/locale/index_spec.js index 0f685c6d69d..29b0b21eed7 100644 --- a/spec/javascripts/locale/index_spec.js +++ b/spec/javascripts/locale/index_spec.js @@ -1,14 +1,6 @@ import { createDateTimeFormat, languageCode } from '~/locale'; -const setLanguage = (languageCode) => { - const htmlElement = document.querySelector('html'); - - if (languageCode) { - htmlElement.setAttribute('lang', languageCode); - } else { - htmlElement.removeAttribute('lang'); - } -}; +import { setLanguage } from '../helpers/locale_helper'; describe('locale', () => { afterEach(() => {