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

chore(chart): remove faux @superset-ui/core TS declaration #121

Merged
merged 7 commits into from
Mar 22, 2019
Merged
Show file tree
Hide file tree
Changes from all 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
10 changes: 6 additions & 4 deletions packages/superset-ui-chart/src/clients/ChartClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,14 @@ export default class ChartClient {
: Promise.reject(new Error('At least one of sliceId or formData must be specified'));
}

loadQueryData(formData: ChartFormData, options?: Partial<RequestConfig>): Promise<object> {
async loadQueryData(formData: ChartFormData, options?: Partial<RequestConfig>): Promise<object> {
const { viz_type: visType } = formData;
const metaDataRegistry = getChartMetadataRegistry();
const buildQueryRegistry = getChartBuildQueryRegistry();

if (getChartMetadataRegistry().has(visType)) {
const { useLegacyApi } = getChartMetadataRegistry().get(visType);
const buildQuery = useLegacyApi ? () => formData : getChartBuildQueryRegistry().get(visType);
if (metaDataRegistry.has(visType)) {
const { useLegacyApi } = metaDataRegistry.get(visType)!;
const buildQuery = (await buildQueryRegistry.get(visType)) || (() => formData);

return this.client
.post({
Expand Down
36 changes: 14 additions & 22 deletions packages/superset-ui-chart/src/components/SuperChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import getChartComponentRegistry from '../registries/ChartComponentRegistrySingl
import getChartTransformPropsRegistry from '../registries/ChartTransformPropsRegistrySingleton';
import ChartProps from '../models/ChartProps';
import createLoadableRenderer, { LoadableRenderer } from './createLoadableRenderer';
import { ChartType } from '../models/ChartPlugin';
import { PreTransformProps, TransformProps, PostTransformProps } from '../types/Query';

const IDENTITY = (x: any) => x;

Expand All @@ -21,26 +23,21 @@ const defaultProps = {
};
/* eslint-enable sort-keys */

type TransformFunction<Input = PlainProps, Output = PlainProps> = (x: Input) => Output;
type HandlerFunction = (...args: any[]) => void;

interface LoadingProps {
error: any;
}

interface PlainProps {
[key: string]: any;
}

interface LoadedModules {
Chart: React.Component | { default: React.Component };
transformProps: TransformFunction | { default: TransformFunction };
Chart: ChartType;
transformProps: TransformProps;
}

interface RenderProps {
chartProps: ChartProps;
preTransformProps?: TransformFunction<ChartProps>;
postTransformProps?: TransformFunction;
preTransformProps?: PreTransformProps;
postTransformProps?: PostTransformProps;
}

const BLANK_CHART_PROPS = new ChartProps();
Expand All @@ -50,17 +47,13 @@ export interface SuperChartProps {
className?: string;
chartProps?: ChartProps | null;
chartType: string;
preTransformProps?: TransformFunction<ChartProps>;
overrideTransformProps?: TransformFunction;
postTransformProps?: TransformFunction;
preTransformProps?: PreTransformProps;
overrideTransformProps?: TransformProps;
postTransformProps?: PostTransformProps;
onRenderSuccess?: HandlerFunction;
onRenderFailure?: HandlerFunction;
}

function getModule<T>(value: any): T {
return (value.default ? value.default : value) as T;
}

export default class SuperChart extends React.PureComponent<SuperChartProps, {}> {
static defaultProps = defaultProps;

Expand Down Expand Up @@ -125,19 +118,18 @@ export default class SuperChart extends React.PureComponent<SuperChartProps, {}>

processChartProps: (input: {
chartProps: ChartProps;
preTransformProps?: TransformFunction<ChartProps>;
transformProps?: TransformFunction;
postTransformProps?: TransformFunction;
preTransformProps?: PreTransformProps;
transformProps?: TransformProps;
postTransformProps?: PostTransformProps;
}) => any;

createLoadableRenderer: (input: {
chartType: string;
overrideTransformProps?: TransformFunction;
overrideTransformProps?: TransformProps;
}) => LoadableRenderer<RenderProps, LoadedModules> | (() => null);

renderChart(loaded: LoadedModules, props: RenderProps) {
const Chart = getModule<typeof React.Component>(loaded.Chart);
const transformProps = getModule<TransformFunction>(loaded.transformProps);
const { Chart, transformProps } = loaded;
const { chartProps, preTransformProps, postTransformProps } = props;

return (
Expand Down
22 changes: 12 additions & 10 deletions packages/superset-ui-chart/src/models/ChartMetadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@ interface LookupTable {
[key: string]: boolean;
}

export interface ChartMetadataConfig {
name: string;
canBeAnnotationTypes?: string[];
credits?: string[];
description?: string;
show?: boolean;
supportedAnnotationTypes?: string[];
thumbnail: string;
useLegacyApi?: boolean;
}

export default class ChartMetadata {
name: string;
canBeAnnotationTypes?: string[];
Expand All @@ -13,16 +24,7 @@ export default class ChartMetadata {
thumbnail: string;
useLegacyApi: boolean;

constructor(config: {
name: string;
canBeAnnotationTypes?: string[];
credits?: string[];
description?: string;
show?: boolean;
supportedAnnotationTypes?: string[];
thumbnail: string;
useLegacyApi?: boolean;
}) {
constructor(config: ChartMetadataConfig) {
const {
name,
canBeAnnotationTypes = [],
Expand Down
61 changes: 38 additions & 23 deletions packages/superset-ui-chart/src/models/ChartPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,57 @@
import { FunctionComponent, ComponentType } from 'react';
import { isRequired, Plugin } from '@superset-ui/core';
import ChartMetadata from './ChartMetadata';
import ChartProps from './ChartProps';
import getChartMetadataRegistry from '../registries/ChartMetadataRegistrySingleton';
import getChartBuildQueryRegistry from '../registries/ChartBuildQueryRegistrySingleton';
import getChartComponentRegistry from '../registries/ChartComponentRegistrySingleton';
import getChartTransformPropsRegistry from '../registries/ChartTransformPropsRegistrySingleton';
import { ChartFormData } from '../types/ChartFormData';
import { QueryContext } from '../types/Query';
import { BuildQueryFunction, TransformProps } from '../types/Query';

const IDENTITY = (x: any) => x;

type PromiseOrValue<T> = Promise<T> | T;
type PromiseOrValueLoader<T> = () => PromiseOrValue<T> | PromiseOrValue<{ default: T }>;

export type BuildQueryFunction<T extends ChartFormData> = (formData: T) => QueryContext;

export type TransformPropsFunction = (
chartProps: ChartProps,
) => {
[key: string]: any;
};
export type PromiseOrValue<T> = Promise<T> | T;
export type PromiseOrValueLoader<T> = () => PromiseOrValue<T>;
export type ChartType = ComponentType | FunctionComponent;
type ValueOrModuleWithValue<T> = T | { default: T };

interface ChartPluginConfig<T extends ChartFormData> {
metadata: ChartMetadata;
// use buildQuery for immediate value
buildQuery?: BuildQueryFunction<T>;
// use loadBuildQuery for dynamic import (lazy-loading)
loadBuildQuery?: PromiseOrValueLoader<BuildQueryFunction<T>>;
loadBuildQuery?: PromiseOrValueLoader<ValueOrModuleWithValue<BuildQueryFunction<T>>>;
// use transformProps for immediate value
transformProps?: TransformPropsFunction;
transformProps?: TransformProps;
// use loadTransformProps for dynamic import (lazy-loading)
loadTransformProps?: PromiseOrValueLoader<TransformPropsFunction>;
loadTransformProps?: PromiseOrValueLoader<ValueOrModuleWithValue<TransformProps>>;
// use Chart for immediate value
Chart?: Function;
Chart?: ChartType;
// use loadChart for dynamic import (lazy-loading)
loadChart?: PromiseOrValueLoader<Function>;
loadChart?: PromiseOrValueLoader<ValueOrModuleWithValue<ChartType>>;
}

/**
* Loaders of the form `() => import('foo')` may return esmodules
* which require the value to be extracted as `module.default`
* */
function sanitizeLoader<T>(
loader: PromiseOrValueLoader<ValueOrModuleWithValue<T>>,
): PromiseOrValueLoader<T> {
return () => {
const loaded = loader();

return loaded instanceof Promise
? (loaded.then(module => ('default' in module && module.default) || module) as Promise<T>)
: (loaded as T);
};
}

export default class ChartPlugin<T extends ChartFormData = ChartFormData> extends Plugin {
metadata: ChartMetadata;
loadBuildQuery?: PromiseOrValueLoader<BuildQueryFunction<T>>;
loadTransformProps: PromiseOrValueLoader<TransformPropsFunction>;
loadChart: PromiseOrValueLoader<Function>;
loadTransformProps: PromiseOrValueLoader<TransformProps>;
loadChart: PromiseOrValueLoader<ChartType>;

constructor(config: ChartPluginConfig<T>) {
super();
Expand All @@ -55,11 +65,14 @@ export default class ChartPlugin<T extends ChartFormData = ChartFormData> extend
loadChart,
} = config;
this.metadata = metadata;
this.loadBuildQuery = loadBuildQuery || (buildQuery ? () => buildQuery : undefined);
this.loadTransformProps = loadTransformProps || (() => transformProps);
this.loadBuildQuery =
(loadBuildQuery && sanitizeLoader(loadBuildQuery)) ||
(buildQuery && sanitizeLoader(() => buildQuery)) ||
undefined;
this.loadTransformProps = sanitizeLoader(loadTransformProps || (() => transformProps));

if (loadChart) {
this.loadChart = loadChart;
this.loadChart = sanitizeLoader<ChartType>(loadChart);
} else if (Chart) {
this.loadChart = () => Chart;
} else {
Expand All @@ -70,9 +83,11 @@ export default class ChartPlugin<T extends ChartFormData = ChartFormData> extend
register() {
const { key = isRequired('config.key') } = this.config;
getChartMetadataRegistry().registerValue(key, this.metadata);
getChartBuildQueryRegistry().registerLoader(key, this.loadBuildQuery);
getChartComponentRegistry().registerLoader(key, this.loadChart);
getChartTransformPropsRegistry().registerLoader(key, this.loadTransformProps);
if (this.loadBuildQuery) {
getChartBuildQueryRegistry().registerLoader(key, this.loadBuildQuery);
}

return this;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { Registry, makeSingleton, OverwritePolicy } from '@superset-ui/core';
import { QueryContext } from '../types/Query';

class ChartBuildQueryRegistry extends Registry {
// Ideally this would be <T extends ChartFormData>
type BuildQuery = (formData: any) => QueryContext;

class ChartBuildQueryRegistry extends Registry<BuildQuery> {
constructor() {
super({ name: 'ChartBuildQuery', overwritePolicy: OverwritePolicy.WARN });
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Registry, makeSingleton, OverwritePolicy } from '@superset-ui/core';
import { ChartType } from '../models/ChartPlugin';

class ChartComponentRegistry extends Registry {
class ChartComponentRegistry extends Registry<ChartType> {
constructor() {
super({ name: 'ChartComponent', overwritePolicy: OverwritePolicy.WARN });
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Registry, makeSingleton, OverwritePolicy } from '@superset-ui/core';
import ChartMetadata from '../models/ChartMetadata';

class ChartMetadataRegistry extends Registry {
class ChartMetadataRegistry extends Registry<ChartMetadata, ChartMetadata> {
constructor() {
super({ name: 'ChartMetadata', overwritePolicy: OverwritePolicy.WARN });
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Registry, makeSingleton, OverwritePolicy } from '@superset-ui/core';
import { TransformProps } from '../types/Query';

class ChartTransformPropsRegistry extends Registry {
class ChartTransformPropsRegistry extends Registry<TransformProps> {
constructor() {
super({ name: 'ChartTransformProps', overwritePolicy: OverwritePolicy.WARN });
}
Expand Down
18 changes: 11 additions & 7 deletions packages/superset-ui-chart/src/types/Query.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* eslint camelcase: 0 */
import ChartProps from '../models/ChartProps';
import { DatasourceType } from './Datasource';
import { ChartFormData } from './ChartFormData';
import { Metric } from './Metric';
import ChartProps from '../models/ChartProps';

export interface QueryObject {
granularity: string;
Expand Down Expand Up @@ -32,10 +32,14 @@ export interface QueryContext {
queries: QueryObject[];
}

export type BuildQueryFunction<T extends ChartFormData> = (formData: T) => QueryContext;

export type TransformPropsFunction = (
chartProps: ChartProps,
) => {
export interface PlainProps {
[key: string]: any;
};
}

type TransformFunction<Input = PlainProps, Output = PlainProps> = (x: Input) => Output;

export type PreTransformProps = TransformFunction<ChartProps>;
export type TransformProps = TransformFunction;
export type PostTransformProps = TransformFunction;

export type BuildQueryFunction<T extends ChartFormData> = (formData: T) => QueryContext;
23 changes: 17 additions & 6 deletions packages/superset-ui-chart/test/clients/ChartClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
buildQueryContext,
ChartFormData,
getChartMetadataRegistry,
ChartMetadata,
} from '../../src';

import { SliceIdAndOrFormData } from '../../src/clients/ChartClient';
Expand Down Expand Up @@ -97,7 +98,10 @@ describe('ChartClient', () => {

describe('.loadQueryData(formData, options)', () => {
it('returns a promise of query data for known chart type', () => {
getChartMetadataRegistry().registerValue('word_cloud', { name: 'Word Cloud' });
getChartMetadataRegistry().registerValue(
'word_cloud',
new ChartMetadata({ name: 'Word Cloud', thumbnail: '' }),
);

getChartBuildQueryRegistry().registerValue('word_cloud', (formData: ChartFormData) =>
buildQueryContext(formData),
Expand Down Expand Up @@ -129,10 +133,14 @@ describe('ChartClient', () => {

it('fetches data from the legacy API if ChartMetadata has useLegacyApi=true,', () => {
// note legacy charts do not register a buildQuery function in the registry
getChartMetadataRegistry().registerValue('word_cloud_legacy', {
name: 'Legacy Word Cloud',
useLegacyApi: true,
});
getChartMetadataRegistry().registerValue(
'word_cloud_legacy',
new ChartMetadata({
name: 'Legacy Word Cloud',
thumbnail: '.png',
useLegacyApi: true,
}),
);

fetchMock.post('glob:*/api/v1/query/', () =>
Promise.reject(Error('Unexpected all to v1 API')),
Expand Down Expand Up @@ -233,7 +241,10 @@ describe('ChartClient', () => {
amet: true,
});

getChartMetadataRegistry().registerValue('line', { name: 'Line' });
getChartMetadataRegistry().registerValue(
'line',
new ChartMetadata({ name: 'Line', thumbnail: '.gif' }),
);

getChartBuildQueryRegistry().registerValue('line', (formData: ChartFormData) =>
buildQueryContext(formData),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ describe('SuperChart', () => {
name: 'second-chart',
thumbnail: '',
}),
// this mirrors `() => import(module)` syntax
loadChart: () => Promise.resolve({ default: TestComponent }),
transformProps: x => x,
// promise without .default
loadTransformProps: () => Promise.resolve((x: any) => x),
});
}
}
Expand All @@ -42,7 +44,7 @@ describe('SuperChart', () => {
thumbnail: '',
}),
loadChart: () =>
new Promise<Function>(resolve => {
new Promise(resolve => {
setTimeout(() => {
resolve(TestComponent);
}, 1000);
Expand Down
Loading