Skip to content

Commit

Permalink
feat: add functions for parsing formatters from encoding (apache#205)
Browse files Browse the repository at this point in the history
* feat: add function for parsing formatters from encoding

* fix: add unit test

* feat: add getter

* fix: update type
  • Loading branch information
kristw authored and zhaoyongjie committed Nov 26, 2021
1 parent 3df26ae commit be65a04
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
"private": true,
"dependencies": {
"vega": "^5.4.0",
"vega-lite": "^3.4.0"
"vega-lite": "^3.4.0",
"lodash": "^4.17.15"
},
"peerDependencies": {
"@superset-ui/time-format": "^0.11.14",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ChannelDef } from '../types/ChannelDef';
import { isTypedFieldDef } from '../typeGuards/ChannelDef';
import fallbackFormatter from './fallbackFormatter';
import createFormatterFromFieldTypeAndFormat from './createFormatterFromFieldTypeAndFormat';

export default function createFormatterFromChannelDef(definition: ChannelDef) {
if (isTypedFieldDef(definition)) {
const { type, format = '' } = definition;

return createFormatterFromFieldTypeAndFormat(type, format);
}

return fallbackFormatter;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { getNumberFormatter } from '@superset-ui/number-format';
import { getTimeFormatter } from '@superset-ui/time-format';
import { Type } from '../types/VegaLite';
import { Formatter } from '../types/ChannelDef';
import fallbackFormatter from './fallbackFormatter';

export default function createFormatterFromFieldTypeAndFormat(
type: Type,
format: string,
): Formatter {
if (type === 'quantitative') {
const formatter = getNumberFormatter(format);

return (value: any) => formatter(value);
} else if (type === 'temporal') {
const formatter = getTimeFormatter(format);

return (value: any) => formatter(value);
}

return fallbackFormatter;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { get } from 'lodash/fp';
import identity from '../utils/identity';
import { ChannelDef } from '../types/ChannelDef';
import { isValueDef } from '../typeGuards/ChannelDef';
import { PlainObject } from '../types/Data';

export default function createGetterFromChannelDef(
definition: ChannelDef,
): (x?: PlainObject) => any {
if (isValueDef(definition)) {
return () => definition.value;
} else if (typeof definition.field !== 'undefined') {
return get(definition.field);
}

return identity;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function fallbackFormatter(v: any) {
return `${v}`;
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { TimeFormatter } from '@superset-ui/time-format';
import { NumberFormatter } from '@superset-ui/number-format';
import { ValueDef, Value, Type } from './VegaLite';
import { WithScale } from './Scale';
import { WithXAxis, WithYAxis, WithAxis } from './Axis';
import { WithLegend } from './Legend';

export type Formatter = NumberFormatter | TimeFormatter | ((d: any) => string);
export type Formatter = (d: any) => string;

export interface FieldDef {
field: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import createFormatterFromChannelDef from '../../src/parsers/createFormatterFromChannelDef';

describe('createFormatterFromChannelDef(type, format)', () => {
it('handles when format is defined', () => {
const formatter = createFormatterFromChannelDef({
field: 'lunchTime',
type: 'temporal',
format: '%b %d, %Y',
});
expect(formatter(new Date(Date.UTC(2019, 5, 20)))).toEqual('Jun 20, 2019');
});
it('handles when format is not defined', () => {
const formatter = createFormatterFromChannelDef({
field: 'lunchTime',
type: 'temporal',
});
expect(formatter(new Date(Date.UTC(2019, 5, 20)))).toEqual('2019-06-20 00:00:00');
});
it('uses fallback for other cases', () => {
const formatter = createFormatterFromChannelDef({ type: 'nominal', field: 'restaurantName' });
expect(formatter('Lazy Burger')).toEqual('Lazy Burger');
});
it('uses fallback for channel definitions without type', () => {
const formatter = createFormatterFromChannelDef({ value: 'Lettuce' });
expect(formatter('Lazy Burger')).toEqual('Lazy Burger');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import createFormatterFromFieldTypeAndFormat from '../../src/parsers/createFormatterFromFieldTypeAndFormat';

describe('createFormatterFromFieldTypeAndFormat(type, format)', () => {
it('handles quantitative field type', () => {
const formatter = createFormatterFromFieldTypeAndFormat('quantitative', '.2f');
expect(formatter(200)).toEqual('200.00');
});
it('handles temporal field type', () => {
const formatter = createFormatterFromFieldTypeAndFormat('temporal', '%b %d, %Y');
expect(formatter(new Date(Date.UTC(2019, 5, 20)))).toEqual('Jun 20, 2019');
});
it('uses fallback for other cases', () => {
const formatter = createFormatterFromFieldTypeAndFormat('nominal', '');
expect(formatter('cat')).toEqual('cat');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import createGetterFromChannelDef from '../../src/parsers/createGetterFromChannelDef';

describe('createGetterFromChannelDef(definition)', () => {
it('handles ValueDef', () => {
const getter = createGetterFromChannelDef({ value: 1 });
expect(getter()).toBe(1);
});
it('handleFieldDef', () => {
const getter = createGetterFromChannelDef({ field: 'cost' });
expect(getter({ cost: 10 })).toBe(10);
});
it('handleFieldDef with nested field', () => {
const getter = createGetterFromChannelDef({ field: 'fuel.cost' });
expect(getter({ fuel: { cost: 10 } })).toBe(10);
});
it('otherwise return identity', () => {
// @ts-ignore
const getter = createGetterFromChannelDef({});
expect(getter(300)).toBe(300);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import fallbackFormatter from '../../src/parsers/fallbackFormatter';

describe('fallbackFormatter(v: any)', () => {
it('handles primitive types', () => {
expect(fallbackFormatter(undefined)).toEqual('undefined');
expect(fallbackFormatter(null)).toEqual('null');
expect(fallbackFormatter(true)).toEqual('true');
expect(fallbackFormatter(false)).toEqual('false');
expect(fallbackFormatter(0)).toEqual('0');
expect(fallbackFormatter(1)).toEqual('1');
expect(fallbackFormatter(-1)).toEqual('-1');
});
it('handles arrays', () => {
expect(fallbackFormatter([])).toEqual('');
expect(fallbackFormatter(['def'])).toEqual('def');
expect(fallbackFormatter(['def', 'ghi'])).toEqual('def,ghi');
});
it('handles objects', () => {
expect(fallbackFormatter({})).toEqual('[object Object]');
expect(fallbackFormatter({ abc: 1 })).toEqual('[object Object]');
});
});

0 comments on commit be65a04

Please sign in to comment.