forked from apache/superset
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(chart): Add
<ChartDataProvider />
(#120)
* docs: [demo][connection] add ConfigureCORS story for testing CORS * docs: [demo][ConfigureCORS] better instructions * feat: [chart] add mvp DataProvider component * docs: better CORS story, update webpack for @babel/polyfill * docs: [chart] add DataProvider story with WordCloudPlugin * docs: [chart] add DataProvider deets to Readme * test(chart): move SuperChart.test.jsx => .tsx and instead use @ts-ignore * fix(connection): point interface.request to client.request * feat(chart): re-write DataProvider as ChartDataProvider * docs(demo): re-write LegacyWordCloudStories => ChartDataProviderStories * refactor(chart): use IDENTITY as ChartPlugin buildQuery default * feat(chart): support legacy + v1 loadQueryData endpoints in ChartClient * docs(demo): add sankey + sunburst plugins to ChartDataProvider story * style(chart): run prettier on SuperChart * feat(chart): export QueryData type from models/ChartProps * feat(chart): export Metrics and BaseFormData from types/ChartFormData * feat(chart): add request option overrides in ChartDataProvider * fix(chart): use Partial<> for ChartClient request option overrides * test(chart): add ChartDataProvider tests * build: include demo pkg in type script * build: move storybook/mocks to test/fixtures * build: move json-bigint TS declaration to root * test(chart): clean up ChartDataProvider test TS * chore(chart): lint fix SuperChart * fix(chart): set ChartPlugin.buildQuery default back to undefined * test(connection): fix expected Client.get call count * test(chart): fix ChartClient tests and add test for legacy API * fix(chart): uninitialized typo, change fetching => loading * docs(chart): update README to final ChartDataProvider API * docs(chart): fix typo * test(chart): get ChartDataProvider to one hundo * feat(chart): add and export more meaningful Datasource type * feat(chart): use Datasource type in ChartClient
- Loading branch information
1 parent
7c6da22
commit b585467
Showing
22 changed files
with
726 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
144 changes: 144 additions & 0 deletions
144
...y_superset_ui/superset-ui/packages/superset-ui-chart/src/components/ChartDataProvider.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
/* eslint react/sort-comp: 'off' */ | ||
import React, { ReactNode } from 'react'; | ||
import { SupersetClientInterface, RequestConfig } from '../../../superset-ui-connection/src/types'; | ||
|
||
import ChartClient, { SliceIdAndOrFormData } from '../clients/ChartClient'; | ||
import { ChartFormData } from '../types/ChartFormData'; | ||
import { Datasource } from '../types/Datasource'; | ||
import { QueryData } from '../models/ChartProps'; | ||
|
||
interface Payload { | ||
formData: Partial<ChartFormData>; | ||
queryData: QueryData; | ||
datasource?: Datasource; | ||
} | ||
|
||
export interface ProvidedProps { | ||
payload?: Payload; | ||
error?: Error; | ||
loading?: boolean; | ||
} | ||
|
||
export type Props = | ||
/** User can pass either one or both of sliceId or formData */ | ||
SliceIdAndOrFormData & { | ||
/** Child function called with ProvidedProps */ | ||
children: (provided: ProvidedProps) => ReactNode; | ||
/** Superset client which is used to fetch data. It should already be configured and initialized. */ | ||
client?: SupersetClientInterface; | ||
/** Will fetch and include datasource metadata for SliceIdAndOrFormData in the payload. */ | ||
loadDatasource?: boolean; | ||
/** Callback when an error occurs. Enables wrapping the Provider in an ErrorBoundary. */ | ||
onError?: (error: ProvidedProps['error']) => void; | ||
/** Callback when data is loaded. */ | ||
onLoaded?: (payload: ProvidedProps['payload']) => void; | ||
/** Hook to override the formData request config. */ | ||
formDataRequestOptions?: Partial<RequestConfig>; | ||
/** Hook to override the datasource request config. */ | ||
datasourceRequestOptions?: Partial<RequestConfig>; | ||
/** Hook to override the queryData request config. */ | ||
queryRequestOptions?: Partial<RequestConfig>; | ||
}; | ||
|
||
type State = { | ||
status: 'uninitialized' | 'loading' | 'error' | 'loaded'; | ||
payload?: ProvidedProps['payload']; | ||
error?: ProvidedProps['error']; | ||
}; | ||
|
||
class ChartDataProvider extends React.PureComponent<Props, State> { | ||
readonly chartClient: ChartClient; | ||
|
||
constructor(props: Props) { | ||
super(props); | ||
this.handleFetchData = this.handleFetchData.bind(this); | ||
this.handleReceiveData = this.handleReceiveData.bind(this); | ||
this.handleError = this.handleError.bind(this); | ||
this.chartClient = new ChartClient({ client: props.client }); | ||
this.state = { status: 'uninitialized' }; | ||
} | ||
|
||
componentDidMount() { | ||
this.handleFetchData(); | ||
} | ||
|
||
componentDidUpdate(prevProps: Props) { | ||
const { formData, sliceId } = this.props; | ||
if (formData !== prevProps.formData || sliceId !== prevProps.sliceId) { | ||
this.handleFetchData(); | ||
} | ||
} | ||
|
||
private extractSliceIdAndFormData() { | ||
const { formData, sliceId } = this.props; | ||
const result: any = {}; | ||
|
||
if (formData) result.formData = formData; | ||
if (sliceId) result.sliceId = sliceId; | ||
|
||
return result as SliceIdAndOrFormData; | ||
} | ||
|
||
private handleFetchData() { | ||
const { | ||
loadDatasource, | ||
formDataRequestOptions, | ||
datasourceRequestOptions, | ||
queryRequestOptions, | ||
} = this.props; | ||
|
||
this.setState({ status: 'loading' }, () => { | ||
try { | ||
this.chartClient | ||
.loadFormData(this.extractSliceIdAndFormData(), formDataRequestOptions) | ||
.then(formData => | ||
Promise.all([ | ||
loadDatasource | ||
? this.chartClient.loadDatasource(formData.datasource, datasourceRequestOptions) | ||
: Promise.resolve(undefined), | ||
this.chartClient.loadQueryData(formData, queryRequestOptions), | ||
]).then(([datasource, queryData]) => ({ | ||
datasource, | ||
formData, | ||
queryData, | ||
})), | ||
) | ||
.then(this.handleReceiveData) | ||
.catch(this.handleError); | ||
} catch (error) { | ||
this.handleError(error); | ||
} | ||
}); | ||
} | ||
|
||
handleReceiveData(data: Payload) { | ||
const { onLoaded } = this.props; | ||
if (onLoaded) onLoaded(data); | ||
this.setState({ payload: data, status: 'loaded' }); | ||
} | ||
|
||
handleError(error: ProvidedProps['error']) { | ||
const { onError } = this.props; | ||
if (onError) onError(error); | ||
this.setState({ error, status: 'error' }); | ||
} | ||
|
||
render() { | ||
const { children } = this.props; | ||
const { status, payload, error } = this.state; | ||
|
||
switch (status) { | ||
case 'loading': | ||
return children({ loading: true }); | ||
case 'loaded': | ||
return children({ payload }); | ||
case 'error': | ||
return children({ error }); | ||
case 'uninitialized': | ||
default: | ||
return null; | ||
} | ||
} | ||
} | ||
|
||
export default ChartDataProvider; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 12 additions & 1 deletion
13
...tend/temporary_superset_ui/superset-ui/packages/superset-ui-chart/src/types/Datasource.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,17 @@ | ||
/* eslint-disable import/prefer-default-export, no-unused-vars */ | ||
import { Column } from './Column'; | ||
import { Metric } from './Metric'; | ||
|
||
export enum DatasourceType { | ||
Table = 'table', | ||
Druid = 'druid', | ||
} | ||
|
||
/** @TODO can continue to add fields to this */ | ||
export interface Datasource { | ||
id: number; | ||
name: string; | ||
description?: string; | ||
type: DatasourceType; | ||
columns: Column[]; | ||
metrics: Metric[]; | ||
} |
Oops, something went wrong.