mirror of
https://github.com/apache/superset.git
synced 2024-09-19 12:09:42 -04:00
feat: add functions for parsing formatters from encoding (#205)
* feat: add function for parsing formatters from encoding * fix: add unit test * feat: add getter * fix: update type
This commit is contained in:
parent
3df26ae76d
commit
be65a04238
@ -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",
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
export default function fallbackFormatter(v: any) {
|
||||
return `${v}`;
|
||||
}
|
@ -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;
|
||||
|
@ -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');
|
||||
});
|
||||
});
|
@ -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');
|
||||
});
|
||||
});
|
@ -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);
|
||||
});
|
||||
});
|
@ -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]');
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user