feat: update data format returned from query api and add getGroupBys (#72)

* fix: update data format returned from query api

* fix: format

* fix: remove unnecessary type

* fix: remove hack prior to typescript 3.4
This commit is contained in:
Krist Wongsuphasawat 2019-04-24 11:18:06 -07:00 committed by Yongjie Zhao
parent 911382f152
commit 827394261a
10 changed files with 367 additions and 361 deletions

View File

@ -1,7 +1,5 @@
/* eslint-disable sort-keys, no-magic-numbers */
export default {
keys: ['name', 'x', 'y'],
values: [
export default [
{ x: -157766400000, y: 24703, name: 'Christopher' },
{ x: -126230400000, y: 27861, name: 'Christopher' },
{ x: -94694400000, y: 29436, name: 'Christopher' },
@ -222,5 +220,4 @@ export default {
{ x: 1136073600000, y: 22498, name: 'Michael' },
{ x: 1167609600000, y: 21805, name: 'Michael' },
{ x: 1199145600000, y: 20271, name: 'Michael' },
],
};
];

View File

@ -1,7 +1,5 @@
/* eslint-disable sort-keys, no-magic-numbers */
export default {
keys: ['snapshot', 'x', 'y'],
values: [
export default [
{ x: -157766400000, y: 24703, snapshot: 'Last year' },
{ x: -126230400000, y: 27861, snapshot: 'Last year' },
{ x: -94694400000, y: 29436, snapshot: 'Last year' },
@ -90,5 +88,4 @@ export default {
{ x: 1136073600000, y: 22498, snapshot: 'Current' },
{ x: 1167609600000, y: 21805, snapshot: 'Current' },
{ x: 1199145600000, y: 20271, snapshot: 'Current' },
],
};
];

View File

@ -4,13 +4,10 @@ import { SuperChart, ChartProps } from '@superset-ui/chart';
import data from '../data/data';
import { LINE_PLUGIN_TYPE } from '../constants';
const missingData = {
keys: data.keys,
values: data.values.map(({ y, ...rest }) => ({
const missingData = data.map(({ y, ...rest }) => ({
...rest,
y: Math.random() < 0.25 ? null : y,
})),
};
}));
export default [
{

View File

@ -5,21 +5,13 @@ import { EncodingFromChannelsAndOutputs } from '../encodeable/types/Channel';
/**
* Define channel types
*/
// This is a workaround until TypeScript 3.4 which has const context
// which will allow use to derive type from object literal
// without type widening (e.g. 'X' instead of string).
// Now we have to define class with readonly fields
// to be able to use "typeof" to infer strict types
// See more details from
// https://github.com/Microsoft/TypeScript/issues/20195
// https://github.com/Microsoft/TypeScript/pull/29510
const channelTypes = new (class Channels {
readonly x = 'X';
readonly y = 'Y';
readonly color = 'Color';
readonly fill = 'Category';
readonly strokeDasharray = 'Category';
})();
const channelTypes = {
color: 'Color',
fill: 'Category',
strokeDasharray: 'Category',
x: 'X',
y: 'Y',
} as const;
export type ChannelTypes = typeof channelTypes;

View File

@ -81,15 +81,12 @@ class LineChart extends PureComponent<Props> {
renderChart(dim: Dimension) {
const { width, height } = dim;
const { data, encoding, margin, theme } = this.props;
const { data, margin, theme } = this.props;
const { channels } = this.encoder;
const fieldNames = this.encoder.getGroupBys();
const fieldNames = data.keys
.filter(k => k !== encoding.x.field && k !== encoding.y.field)
.sort((a, b) => a.localeCompare(b));
const groups = groupBy(data.values, row => fieldNames.map(f => `${f}=${row[f]}`).join(','));
const groups = groupBy(data, row => fieldNames.map(f => `${f}=${row[f]}`).join(','));
const allSeries = values(groups).map(seriesData => {
const firstDatum = seriesData[0];

View File

@ -16,9 +16,7 @@ export default function transformProps(chartProps: ChartProps) {
const data = payload.data as DataRow[];
return {
data: {
keys: ['name', 'x', 'y'],
values: flatMap(
data: flatMap(
data.map((row: DataRow) =>
row.values.map(v => ({
...v,
@ -26,7 +24,6 @@ export default function transformProps(chartProps: ChartProps) {
})),
),
),
},
width,
height,
encoding: {

View File

@ -47,7 +47,7 @@ export default class ChartLegend<
const legends = Object.keys(encoder.legends).map((field: string) => {
const channelNames = encoder.legends[field];
const channelEncoder = encoder.channels[channelNames[0]];
const domain = Array.from(new Set(data.values.map(channelEncoder.get)));
const domain = Array.from(new Set(data.map(channelEncoder.get)));
const scale = scaleOrdinal({
domain,
range: domain.map((key: string) => channelEncoder.encodeValue(key)),

View File

@ -99,6 +99,23 @@ export default abstract class AbstractEncoder<
};
}
getChannelNames() {
return Object.keys(this.channelTypes) as (keyof ChannelTypes)[];
}
getChannelsAsArray() {
return this.getChannelNames().map(name => this.channels[name]);
}
getGroupBys() {
const fields = this.getChannelsAsArray()
.filter(c => c.isGroupBy())
.map(c => (isFieldDef(c.definition) ? c.definition.field : ''))
.filter(field => field !== '');
return Array.from(new Set(fields));
}
hasLegend() {
return Object.keys(this.legends).length > 0;
}

View File

@ -11,6 +11,7 @@ import {
isValueDef,
isFieldDef,
isNonValueDef,
isTypedFieldDef,
} from './types/ChannelDef';
import isEnabled from './utils/isEnabled';
import isDisabled from './utils/isDisabled';
@ -107,6 +108,20 @@ export default class ChannelEncoder<Def extends ChannelDef<Output>, Output exten
return isScaleFieldDef(this.definition);
}
isGroupBy() {
if (isTypedFieldDef(this.definition)) {
return (
this.type === 'XBand' ||
this.type === 'YBand' ||
this.type === 'Category' ||
this.type === 'Text' ||
(this.type === 'Color' && this.definition.type === 'nominal')
);
}
return false;
}
isX() {
return this.type === 'X' || this.type === 'XBand';
}

View File

@ -2,7 +2,4 @@ export type PlainObject<Key extends string = string, Value extends any = any> =
[key in Key]: Value
};
export type Dataset<T extends string = string> = {
keys: T[];
values: Partial<PlainObject<T>>[];
};
export type Dataset<T extends string = string> = Partial<PlainObject<T>>[];