Skip to content

Commit

Permalink
docs: add storybook page for testing query (#70)
Browse files Browse the repository at this point in the history
* docs: add storybook page for testing query

* fix: remove is_time_series
  • Loading branch information
kristw authored and zhaoyongjie committed Nov 17, 2021
1 parent 6281960 commit ba29c2f
Show file tree
Hide file tree
Showing 7 changed files with 311 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"peerDependencies": {
"@superset-ui/chart": "^0.11.0",
"@superset-ui/color": "^0.11.0",
"@superset-ui/connection": "^0.11.0",
"@superset-ui/time-format": "^0.11.0",
"@superset-ui/translation": "^0.11.0"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';

export type Props = {
error: Error;
};

export default function ErrorMessage({ error }: Props) {
return (
<div className="alert alert-danger">
{error.stack || error.message}
{!error.message &&
!error.stack &&
(typeof error === 'object' ? JSON.stringify(error) : String(error))}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, { ReactNode } from 'react';

export type Props = {
children: ReactNode;
expandableWhat?: string;
};

type State = {
open: boolean;
};

export default class Expandable extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { open: false };
this.handleToggle = this.handleToggle.bind(this);
}

handleToggle() {
this.setState(({ open }) => ({ open: !open }));
}

render() {
const { open } = this.state;
const { children, expandableWhat } = this.props;

return (
<div>
<button
type="button"
onClick={this.handleToggle}
className="btn btn-outline-primary btn-sm"
>
{`${open ? 'Hide' : 'Show'} ${expandableWhat}`}
</button>
<br />
<br />
{open ? children : null}
</div>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import React, { ReactNode } from 'react';
import { SupersetClient } from '@superset-ui/connection';
import ErrorMessage from './ErrorMessage';

export type Props = {
children: ({ payload }: { payload?: object }) => ReactNode;
endpoint?: string;
host: string;
method?: 'POST' | 'GET';
postPayload?: string;
};

type State = {
didVerify: boolean;
error?: Error;
payload?: object;
};

export const renderError = (error: Error) => (
<div>
The following error occurred, make sure you have <br />
1) configured CORS in Superset to receive requests from this domain. <br />
2) set the Superset host correctly below. <br />
3) debug the CORS configuration under the `@superset-ui/connection` stories.
<br />
<br />
<ErrorMessage error={error} />
</div>
);

export default class VerifyCORS extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { didVerify: false };
this.handleVerify = this.handleVerify.bind(this);
}

componentDidUpdate(prevProps: Props) {
const { endpoint, host, postPayload, method } = this.props;
if (
(this.state.didVerify || this.state.error) &&
(prevProps.endpoint !== endpoint ||
prevProps.host !== host ||
prevProps.postPayload !== postPayload ||
prevProps.method !== method)
) {
// eslint-disable-next-line react/no-did-update-set-state
this.setState({ didVerify: false, error: undefined });
}
}

handleVerify() {
const { endpoint, host, postPayload, method } = this.props;

SupersetClient.reset();

SupersetClient.configure({
credentials: 'include',
host,
mode: 'cors',
})
.init()
.then(() =>
// Test an endpoint if specified
endpoint
? SupersetClient.request({
endpoint,
method,
postPayload: postPayload ? JSON.parse(postPayload) : '',
})
: Promise.resolve({}),
)
.then(response => this.setState({ didVerify: true, error: undefined, payload: response }))
.catch((error: Response) => {
const { status, statusText = error } = error;
this.setState({ error: Error(`${status || ''}${status ? ':' : ''} ${statusText}`) });
});
}

render() {
const { didVerify, error, payload } = this.state;
const { children } = this.props;

return didVerify ? (
children({ payload })
) : (
<div className="row">
<div className="col-md-10">
This example requires CORS requests from this domain. <br />
<br />
1) enable CORS requests in your Superset App from{' '}
<code>{`${window.location.origin}`}</code>
<br />
2) configure your Superset App host name below <br />
3) click &quot;Verify&quot; to authenticate and fetch data for your test UI. <br />
<br />
<button
type="button"
onClick={this.handleVerify}
className="btn btn-outline-primary btn-sm"
>
Verify
</button>
<br />
<br />
</div>

{error && (
<div className="col-md-8">
<ErrorMessage error={error} />
</div>
)}
</div>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import React from 'react';
import { text, select } from '@storybook/addon-knobs';
import { SuperChart, ChartDataProvider, ChartProps } from '@superset-ui/chart';
import { SupersetClient } from '@superset-ui/connection';
import Expandable from './Expandable';
import VerifyCORS, { renderError } from './VerifyCORS';

export default function createQueryStory({
choices,
storyName = 'Queries',
storyPath = '',
}: {
choices: {
[key: string]: {
chartType: string;
formData: {
[key: string]: any;
};
};
};
storyName: string;
storyPath: string;
}) {
const keys = Object.keys(choices);

return {
renderStory: () => {
const host = text('Set Superset App host for CORS request', 'localhost:8088');
const mode = select('Choose mode:', keys, keys[0]);
const { formData: presetFormData, chartType } = choices[mode];
const width = text('Vis width', '400');
const height = text('Vis height', '400');
const formData = text('Override formData', JSON.stringify(presetFormData, null, 2));

return (
<div style={{ margin: 16 }}>
<VerifyCORS host={host}>
{() => (
<ChartDataProvider
client={SupersetClient}
formData={JSON.parse(formData.replace(/&quot;/g, '"'))}
>
{({ loading, payload, error }) => {
if (loading) return <div>Loading!</div>;

if (error) return renderError(error);

if (payload)
return (
<>
<SuperChart
chartType={chartType}
chartProps={
new ChartProps({
formData: payload.formData,
height: Number(height),
// @TODO fix typing
// all vis's now expect objects but api/v1/ returns an array
payload: Array.isArray(payload.queryData)
? payload.queryData[0]
: payload.queryData,
width: Number(width),
})
}
/>
<br />
<Expandable expandableWhat="payload">
<pre style={{ fontSize: 11 }}>{JSON.stringify(payload, null, 2)}</pre>
</Expandable>
</>
);

return null;
}}
</ChartDataProvider>
)}
</VerifyCORS>
</div>
);
},
storyName,
storyPath,
};
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { LineChartPlugin as LegacyLineChartPlugin } from '../../../../../superset-ui-preset-chart-xy/src/legacy';
import { LineChartPlugin } from '../../../../../superset-ui-preset-chart-xy/src';
import BasicStories from './stories/basic';
import QueryStories from './stories/query';
import LegacyStories from './stories/legacy';
import MissingStories from './stories/missing';
import TimeShiftStories from './stories/timeShift';
Expand All @@ -10,5 +11,11 @@ new LegacyLineChartPlugin().configure({ key: LINE_PLUGIN_LEGACY_TYPE }).register
new LineChartPlugin().configure({ key: LINE_PLUGIN_TYPE }).register();

export default {
examples: [...BasicStories, ...MissingStories, ...TimeShiftStories, ...LegacyStories],
examples: [
...BasicStories,
...MissingStories,
...TimeShiftStories,
...LegacyStories,
...QueryStories,
],
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* eslint-disable sort-keys */
import { LINE_PLUGIN_TYPE, LINE_PLUGIN_LEGACY_TYPE } from '../constants';
import createQueryStory from '../../../../shared/components/createQueryStory';

export default [
createQueryStory({
choices: {
'Line Chart - Legacy API': {
chartType: LINE_PLUGIN_LEGACY_TYPE,
formData: {
datasource: '3__table',
viz_type: 'line',
url_params: {},
granularity_sqla: 'ds',
time_grain_sqla: 'P1D',
time_range: '100 years ago : now',
metrics: ['sum__num'],
adhoc_filters: [],
groupby: [],
limit: 25,
row_limit: 50000,
},
},
'Line Chart - /api/v1/query': {
chartType: LINE_PLUGIN_TYPE,
formData: {
viz_type: LINE_PLUGIN_TYPE,
datasource: '3__table',
url_params: {},
granularity_sqla: 'ds',
time_grain_sqla: 'P1D',
time_range: '100 years ago : now',
metrics: ['sum__num'],
adhoc_filters: [],
groupby: [],
limit: 25,
row_limit: 50000,
},
},
},
storyName: 'Queries',
storyPath: 'preset-chart-xy|LineChartPlugin',
}),
];

0 comments on commit ba29c2f

Please sign in to comment.