Skip to content
This repository has been archived by the owner on Dec 10, 2021. It is now read-only.

feat: add functions for parsing formatters from encoding #205

Merged
merged 4 commits into from
Aug 20, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/superset-ui-encodeable/package.json
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,14 @@
import { get } from 'lodash/fp';
import identity from '../utils/identity';
import { ChannelDef } from '../types/ChannelDef';
import { isValueDef } from '../typeGuards/ChannelDef';

export default function createGetterFromChannelDef(definition: ChannelDef): (x?: any) => any {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this function have more explicit typing? If not, would be good to leave a comment documenting expected input/output

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}`;
}
4 changes: 1 addition & 3 deletions packages/superset-ui-encodeable/src/types/ChannelDef.ts
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]');
});
});