From 92bfbbb5989f2ad4391f41e7ef6a7d5c834a2029 Mon Sep 17 00:00:00 2001 From: Ville Brofeldt Date: Sat, 24 Aug 2019 13:13:41 +0300 Subject: [PATCH 1/2] feat: add duration formatter --- .../superset-ui-number-format/package.json | 3 +- .../src/NumberFormats.ts | 7 +++++ .../src/NumberFormatterRegistry.ts | 4 +++ .../src/factories/createDurationFormatter.ts | 21 ++++++++++++++ .../superset-ui-number-format/src/index.ts | 1 + .../test/NumberFormatterRegistry.test.ts | 3 ++ .../factories/createDurationFormatter.test.ts | 29 +++++++++++++++++++ .../test/index.test.ts | 2 ++ 8 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 packages/superset-ui-number-format/src/factories/createDurationFormatter.ts create mode 100644 packages/superset-ui-number-format/test/factories/createDurationFormatter.test.ts diff --git a/packages/superset-ui-number-format/package.json b/packages/superset-ui-number-format/package.json index 5a6b4d9bc0..91602e39c6 100644 --- a/packages/superset-ui-number-format/package.json +++ b/packages/superset-ui-number-format/package.json @@ -27,7 +27,8 @@ }, "dependencies": { "@types/d3-format": "^1.3.0", - "d3-format": "^1.3.2" + "d3-format": "^1.3.2", + "pretty-ms": "^5.0.0" }, "peerDependencies": { "@superset-ui/core": "^0.11.0" diff --git a/packages/superset-ui-number-format/src/NumberFormats.ts b/packages/superset-ui-number-format/src/NumberFormats.ts index c5a181fc67..cf35e91151 100644 --- a/packages/superset-ui-number-format/src/NumberFormats.ts +++ b/packages/superset-ui-number-format/src/NumberFormats.ts @@ -3,6 +3,10 @@ const DOLLAR_SIGNED = '+$,.2f'; const DOLLAR_ROUND = '$,d'; const DOLLAR_ROUND_SIGNED = '+$,d'; +const DURATION = 'DURATION'; +const DURATION_MS = 'DURATION_MS'; +const DURATION_S = 'DURATION_S'; + const FLOAT_1_POINT = ',.1f'; const FLOAT_2_POINT = ',.2f'; const FLOAT_3_POINT = ',.3f'; @@ -39,6 +43,9 @@ const NumberFormats = { DOLLAR_ROUND, DOLLAR_ROUND_SIGNED, DOLLAR_SIGNED, + DURATION, + DURATION_MS, + DURATION_S, FLOAT, FLOAT_1_POINT, FLOAT_2_POINT, diff --git a/packages/superset-ui-number-format/src/NumberFormatterRegistry.ts b/packages/superset-ui-number-format/src/NumberFormatterRegistry.ts index 96237fa051..6a7c92ea3d 100644 --- a/packages/superset-ui-number-format/src/NumberFormatterRegistry.ts +++ b/packages/superset-ui-number-format/src/NumberFormatterRegistry.ts @@ -1,5 +1,6 @@ import { RegistryWithDefaultKey, OverwritePolicy } from '@superset-ui/core'; import createD3NumberFormatter from './factories/createD3NumberFormatter'; +import createDurationFormatter from './factories/createDurationFormatter'; import createSmartNumberFormatter from './factories/createSmartNumberFormatter'; import NumberFormats from './NumberFormats'; import NumberFormatter from './NumberFormatter'; @@ -14,6 +15,9 @@ export default class NumberFormatterRegistry extends RegistryWithDefaultKey< overwritePolicy: OverwritePolicy.WARN, }); + this.registerValue(NumberFormats.DURATION, createDurationFormatter()); + this.registerValue(NumberFormats.DURATION_MS, createDurationFormatter({ multiplier: 1 })); + this.registerValue(NumberFormats.DURATION_S, createDurationFormatter({ multiplier: 1000 })); this.registerValue(NumberFormats.SMART_NUMBER, createSmartNumberFormatter()); this.registerValue( NumberFormats.SMART_NUMBER_SIGNED, diff --git a/packages/superset-ui-number-format/src/factories/createDurationFormatter.ts b/packages/superset-ui-number-format/src/factories/createDurationFormatter.ts new file mode 100644 index 0000000000..1554009a1b --- /dev/null +++ b/packages/superset-ui-number-format/src/factories/createDurationFormatter.ts @@ -0,0 +1,21 @@ +import prettyMsFormatter from 'pretty-ms'; +import NumberFormatter from '../NumberFormatter'; +import NumberFormats from '../NumberFormats'; + +export default function createDurationFormatter( + config: { + description?: string; + id?: string; + label?: string; + multiplier?: number; + } = {}, +) { + const { description, id, label, multiplier = 1 } = config; + + return new NumberFormatter({ + description, + formatFunc: value => prettyMsFormatter(value * multiplier), + id: id || NumberFormats.DURATION, + label: label || `Duration formatter`, + }); +} diff --git a/packages/superset-ui-number-format/src/index.ts b/packages/superset-ui-number-format/src/index.ts index eb9cbfa19e..95cde2a2a4 100644 --- a/packages/superset-ui-number-format/src/index.ts +++ b/packages/superset-ui-number-format/src/index.ts @@ -8,6 +8,7 @@ export { } from './NumberFormatterRegistrySingleton'; export { default as createD3NumberFormatter } from './factories/createD3NumberFormatter'; +export { default as createDurationFormatter } from './factories/createDurationFormatter'; export { default as createSiAtMostNDigitFormatter, } from './factories/createSiAtMostNDigitFormatter'; diff --git a/packages/superset-ui-number-format/test/NumberFormatterRegistry.test.ts b/packages/superset-ui-number-format/test/NumberFormatterRegistry.test.ts index 140e184092..d87eaf0a5a 100644 --- a/packages/superset-ui-number-format/test/NumberFormatterRegistry.test.ts +++ b/packages/superset-ui-number-format/test/NumberFormatterRegistry.test.ts @@ -42,6 +42,9 @@ describe('NumberFormatterRegistry', () => { it('return the value with the specified format', () => { expect(registry.format('.2f', 100)).toEqual('100.00'); expect(registry.format(',d', 100)).toEqual('100'); + expect(registry.format('DURATION', 1000)).toEqual('1s'); + expect(registry.format('DURATION_MS', 1000)).toEqual('1s'); + expect(registry.format('DURATION_S', 1)).toEqual('1s'); }); }); }); diff --git a/packages/superset-ui-number-format/test/factories/createDurationFormatter.test.ts b/packages/superset-ui-number-format/test/factories/createDurationFormatter.test.ts new file mode 100644 index 0000000000..e773d04147 --- /dev/null +++ b/packages/superset-ui-number-format/test/factories/createDurationFormatter.test.ts @@ -0,0 +1,29 @@ +import NumberFormatter from '../../src/NumberFormatter'; +import createDurationFormatter from '../../src/factories/createDurationFormatter'; + +describe('createDurationFormatter()', () => { + it('creates an instance of NumberFormatter', () => { + const formatter = createDurationFormatter(); + const formatterMs = createDurationFormatter({ multiplier: 1 }); + const formatterS = createDurationFormatter({ multiplier: 1000 }); + expect(formatter).toBeInstanceOf(NumberFormatter); + expect(formatterMs).toBeInstanceOf(NumberFormatter); + expect(formatterS).toBeInstanceOf(NumberFormatter); + }); + it('format milliseconds in human readable format', () => { + const formatter = createDurationFormatter(); + expect(formatter(0)).toBe('0ms'); + expect(formatter(1000)).toBe('1s'); + expect(formatter(1337)).toBe('1.3s'); + expect(formatter(60 * 1000)).toBe('1m'); + expect(formatter(90 * 1000)).toBe('1m 30s'); + }); + it('format seconds in human readable format', () => { + const formatter = createDurationFormatter({ multiplier: 1000 }); + expect(formatter(0.5)).toBe('500ms'); + expect(formatter(1)).toBe('1s'); + expect(formatter(30)).toBe('30s'); + expect(formatter(60)).toBe('1m'); + expect(formatter(90)).toBe('1m 30s'); + }); +}); diff --git a/packages/superset-ui-number-format/test/index.test.ts b/packages/superset-ui-number-format/test/index.test.ts index 433e14e9e2..ffbebc52e9 100644 --- a/packages/superset-ui-number-format/test/index.test.ts +++ b/packages/superset-ui-number-format/test/index.test.ts @@ -1,5 +1,6 @@ import { createD3NumberFormatter, + createDurationFormatter, createSiAtMostNDigitFormatter, formatNumber, getNumberFormatter, @@ -13,6 +14,7 @@ describe('index', () => { it('exports modules', () => { [ createD3NumberFormatter, + createDurationFormatter, createSiAtMostNDigitFormatter, formatNumber, getNumberFormatter, From e718a0b5969097ba4836a4721db24813486d71cc Mon Sep 17 00:00:00 2001 From: Ville Brofeldt Date: Sun, 25 Aug 2019 14:15:03 +0300 Subject: [PATCH 2/2] fix: address review comments --- .../src/NumberFormats.ts | 7 ------- .../src/NumberFormatterRegistry.ts | 4 ---- .../src/factories/createDurationFormatter.ts | 9 ++++----- .../test/NumberFormatterRegistry.test.ts | 3 --- .../factories/createDurationFormatter.test.ts | 15 +++++++++------ 5 files changed, 13 insertions(+), 25 deletions(-) diff --git a/packages/superset-ui-number-format/src/NumberFormats.ts b/packages/superset-ui-number-format/src/NumberFormats.ts index cf35e91151..c5a181fc67 100644 --- a/packages/superset-ui-number-format/src/NumberFormats.ts +++ b/packages/superset-ui-number-format/src/NumberFormats.ts @@ -3,10 +3,6 @@ const DOLLAR_SIGNED = '+$,.2f'; const DOLLAR_ROUND = '$,d'; const DOLLAR_ROUND_SIGNED = '+$,d'; -const DURATION = 'DURATION'; -const DURATION_MS = 'DURATION_MS'; -const DURATION_S = 'DURATION_S'; - const FLOAT_1_POINT = ',.1f'; const FLOAT_2_POINT = ',.2f'; const FLOAT_3_POINT = ',.3f'; @@ -43,9 +39,6 @@ const NumberFormats = { DOLLAR_ROUND, DOLLAR_ROUND_SIGNED, DOLLAR_SIGNED, - DURATION, - DURATION_MS, - DURATION_S, FLOAT, FLOAT_1_POINT, FLOAT_2_POINT, diff --git a/packages/superset-ui-number-format/src/NumberFormatterRegistry.ts b/packages/superset-ui-number-format/src/NumberFormatterRegistry.ts index 6a7c92ea3d..96237fa051 100644 --- a/packages/superset-ui-number-format/src/NumberFormatterRegistry.ts +++ b/packages/superset-ui-number-format/src/NumberFormatterRegistry.ts @@ -1,6 +1,5 @@ import { RegistryWithDefaultKey, OverwritePolicy } from '@superset-ui/core'; import createD3NumberFormatter from './factories/createD3NumberFormatter'; -import createDurationFormatter from './factories/createDurationFormatter'; import createSmartNumberFormatter from './factories/createSmartNumberFormatter'; import NumberFormats from './NumberFormats'; import NumberFormatter from './NumberFormatter'; @@ -15,9 +14,6 @@ export default class NumberFormatterRegistry extends RegistryWithDefaultKey< overwritePolicy: OverwritePolicy.WARN, }); - this.registerValue(NumberFormats.DURATION, createDurationFormatter()); - this.registerValue(NumberFormats.DURATION_MS, createDurationFormatter({ multiplier: 1 })); - this.registerValue(NumberFormats.DURATION_S, createDurationFormatter({ multiplier: 1000 })); this.registerValue(NumberFormats.SMART_NUMBER, createSmartNumberFormatter()); this.registerValue( NumberFormats.SMART_NUMBER_SIGNED, diff --git a/packages/superset-ui-number-format/src/factories/createDurationFormatter.ts b/packages/superset-ui-number-format/src/factories/createDurationFormatter.ts index 1554009a1b..0f1da64eb9 100644 --- a/packages/superset-ui-number-format/src/factories/createDurationFormatter.ts +++ b/packages/superset-ui-number-format/src/factories/createDurationFormatter.ts @@ -1,6 +1,5 @@ import prettyMsFormatter from 'pretty-ms'; import NumberFormatter from '../NumberFormatter'; -import NumberFormats from '../NumberFormats'; export default function createDurationFormatter( config: { @@ -8,14 +7,14 @@ export default function createDurationFormatter( id?: string; label?: string; multiplier?: number; - } = {}, + } & prettyMsFormatter.Options = {}, ) { - const { description, id, label, multiplier = 1 } = config; + const { description, id, label, multiplier = 1, ...prettyMsOptions } = config; return new NumberFormatter({ description, - formatFunc: value => prettyMsFormatter(value * multiplier), - id: id || NumberFormats.DURATION, + formatFunc: value => prettyMsFormatter(value * multiplier, prettyMsOptions), + id: id || 'duration_format', label: label || `Duration formatter`, }); } diff --git a/packages/superset-ui-number-format/test/NumberFormatterRegistry.test.ts b/packages/superset-ui-number-format/test/NumberFormatterRegistry.test.ts index d87eaf0a5a..140e184092 100644 --- a/packages/superset-ui-number-format/test/NumberFormatterRegistry.test.ts +++ b/packages/superset-ui-number-format/test/NumberFormatterRegistry.test.ts @@ -42,9 +42,6 @@ describe('NumberFormatterRegistry', () => { it('return the value with the specified format', () => { expect(registry.format('.2f', 100)).toEqual('100.00'); expect(registry.format(',d', 100)).toEqual('100'); - expect(registry.format('DURATION', 1000)).toEqual('1s'); - expect(registry.format('DURATION_MS', 1000)).toEqual('1s'); - expect(registry.format('DURATION_S', 1)).toEqual('1s'); }); }); }); diff --git a/packages/superset-ui-number-format/test/factories/createDurationFormatter.test.ts b/packages/superset-ui-number-format/test/factories/createDurationFormatter.test.ts index e773d04147..c278d1412f 100644 --- a/packages/superset-ui-number-format/test/factories/createDurationFormatter.test.ts +++ b/packages/superset-ui-number-format/test/factories/createDurationFormatter.test.ts @@ -4,21 +4,18 @@ import createDurationFormatter from '../../src/factories/createDurationFormatter describe('createDurationFormatter()', () => { it('creates an instance of NumberFormatter', () => { const formatter = createDurationFormatter(); - const formatterMs = createDurationFormatter({ multiplier: 1 }); - const formatterS = createDurationFormatter({ multiplier: 1000 }); expect(formatter).toBeInstanceOf(NumberFormatter); - expect(formatterMs).toBeInstanceOf(NumberFormatter); - expect(formatterS).toBeInstanceOf(NumberFormatter); }); - it('format milliseconds in human readable format', () => { + it('format milliseconds in human readable format with default options', () => { const formatter = createDurationFormatter(); expect(formatter(0)).toBe('0ms'); expect(formatter(1000)).toBe('1s'); expect(formatter(1337)).toBe('1.3s'); + expect(formatter(10500)).toBe('10.5s'); expect(formatter(60 * 1000)).toBe('1m'); expect(formatter(90 * 1000)).toBe('1m 30s'); }); - it('format seconds in human readable format', () => { + it('format seconds in human readable format with default options', () => { const formatter = createDurationFormatter({ multiplier: 1000 }); expect(formatter(0.5)).toBe('500ms'); expect(formatter(1)).toBe('1s'); @@ -26,4 +23,10 @@ describe('createDurationFormatter()', () => { expect(formatter(60)).toBe('1m'); expect(formatter(90)).toBe('1m 30s'); }); + it('format milliseconds in human readable format with additional pretty-ms options', () => { + const zeroDecimalFormatter = createDurationFormatter({ secondsDecimalDigits: 0 }); + expect(zeroDecimalFormatter(10500)).toBe('11s'); + const subMillisecondFormatter = createDurationFormatter({ formatSubMilliseconds: true }); + expect(subMillisecondFormatter(100.40008)).toBe('100ms 400µs 80ns'); + }); });