Skip to content

Commit

Permalink
feat: add NoResultsComponent to charts (#305)
Browse files Browse the repository at this point in the history
  • Loading branch information
Erik Ritter authored and zhaoyongjie committed Nov 26, 2021
1 parent 517020a commit 06d7ad5
Show file tree
Hide file tree
Showing 5 changed files with 254 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React, { CSSProperties, useMemo } from 'react';

const MESSAGE_STYLES: CSSProperties = { maxWidth: 800 };
const TITLE_STYLES: CSSProperties = { fontSize: 20, fontWeight: 'bold', paddingBottom: 8 };
const BODY_STYLES: CSSProperties = { fontSize: 16 };

const generateContainerStyles: (
height: number | string,
width: number | string,
) => CSSProperties = (height: number | string, width: number | string) => ({
alignItems: 'center',
display: 'flex',
flexDirection: 'column',
height,
justifyContent: 'center',
padding: 16,
textAlign: 'center',
width,
});

type Props = {
className?: string;
height: number | string;
id?: string;
width: number | string;
};

const NoResultsComponent = ({ className, height, id, width }: Props) => {
const containerStyles = useMemo(() => generateContainerStyles(height, width), [height, width]);

return (
<div className={className} id={id} style={containerStyles}>
<div style={MESSAGE_STYLES}>
<div style={TITLE_STYLES}>No Results</div>
<div style={BODY_STYLES}>
No results were returned for this query. If you expected results to be returned, ensure
any filters are configured properly and the datasource contains data for the selected time
range.
</div>
</div>
</div>
);
};

export default NoResultsComponent;
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { createSelector } from 'reselect';
import SuperChartCore, { Props as SuperChartCoreProps } from './SuperChartCore';
import DefaultFallbackComponent from './FallbackComponent';
import ChartProps, { ChartPropsConfig } from '../models/ChartProps';
import NoResultsComponent from './NoResultsComponent';

const defaultProps = {
FallbackComponent: DefaultFallbackComponent,
Expand Down Expand Up @@ -110,35 +111,48 @@ export default class SuperChart extends React.PureComponent<Props, {}> {
FallbackComponent,
onErrorBoundary,
Wrapper,
queryData,
...rest
} = this.props as PropsWithDefault;

const chartWithoutWrapper = (
<SuperChartCore
ref={this.setRef}
id={id}
className={className}
chartType={chartType}
chartProps={this.createChartProps({
...rest,
height,
width,
})}
preTransformProps={preTransformProps}
overrideTransformProps={overrideTransformProps}
postTransformProps={postTransformProps}
onRenderSuccess={onRenderSuccess}
onRenderFailure={onRenderFailure}
/>
);
const chart = Wrapper ? (
<Wrapper width={width} height={height}>
{chartWithoutWrapper}
</Wrapper>
) : (
chartWithoutWrapper
);

const chartProps = this.createChartProps({
...rest,
queryData,
height,
width,
});

let chart;
// Render the no results component if the query data is null or empty
if (
queryData == null ||
queryData.data === null ||
(Array.isArray(queryData.data) && queryData.data.length === 0)
) {
chart = <NoResultsComponent id={id} className={className} height={height} width={width} />;
} else {
const chartWithoutWrapper = (
<SuperChartCore
ref={this.setRef}
id={id}
className={className}
chartType={chartType}
chartProps={chartProps}
preTransformProps={preTransformProps}
overrideTransformProps={overrideTransformProps}
postTransformProps={postTransformProps}
onRenderSuccess={onRenderSuccess}
onRenderFailure={onRenderFailure}
/>
);
chart = Wrapper ? (
<Wrapper width={width} height={height}>
{chartWithoutWrapper}
</Wrapper>
) : (
chartWithoutWrapper
);
}
// Include the error boundary by default unless it is specifically disabled.
return disableErrorBoundary === true ? (
chart
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';
import { shallow } from 'enzyme';
import NoResultsComponent from '../../src/components/NoResultsComponent';

describe('NoResultsComponent', () => {
it('renders the no results error', () => {
const wrapper = shallow(<NoResultsComponent height="400" width="300" />);

expect(wrapper.text()).toEqual(
'No ResultsNo results were returned for this query. If you expected results to be returned, ensure any filters are configured properly and the datasource contains data for the selected time range.',
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import { promiseTimeout } from '@superset-ui/core';
import { SuperChart } from '../../src';
import RealSuperChart, { WrapperProps } from '../../src/components/SuperChart';
import { ChartKeys, DiligentChartPlugin, BuggyChartPlugin } from './MockChartPlugins';
import NoResultsComponent from '../../src/components/NoResultsComponent';

const DEFAULT_QUERY_DATA = { data: ['foo', 'bar'] };

function expectDimension(renderedWrapper: Cheerio, width: number, height: number) {
expect(renderedWrapper.find('.dimension').text()).toEqual([width, height].join('x'));
Expand Down Expand Up @@ -69,7 +72,14 @@ describe('SuperChart', () => {
it('renders default FallbackComponent', () => {
expectedErrors = 1;
jest.spyOn(RealSuperChart.defaultProps, 'FallbackComponent');
const wrapper = mount(<SuperChart chartType={ChartKeys.BUGGY} width="200" height="200" />);
const wrapper = mount(
<SuperChart
chartType={ChartKeys.BUGGY}
queryData={DEFAULT_QUERY_DATA}
width="200"
height="200"
/>,
);
const renderedWrapper = wrapper.render();

return promiseTimeout(() => {
Expand All @@ -83,6 +93,7 @@ describe('SuperChart', () => {
const wrapper = mount(
<SuperChart
chartType={ChartKeys.BUGGY}
queryData={DEFAULT_QUERY_DATA}
width="200"
height="200"
FallbackComponent={CustomFallbackComponent}
Expand All @@ -100,6 +111,7 @@ describe('SuperChart', () => {
mount(
<SuperChart
chartType={ChartKeys.BUGGY}
queryData={DEFAULT_QUERY_DATA}
width="200"
height="200"
onErrorBoundary={handleError}
Expand All @@ -119,6 +131,7 @@ describe('SuperChart', () => {
<SuperChart
disableErrorBoundary
chartType={ChartKeys.BUGGY}
queryData={DEFAULT_QUERY_DATA}
width="200"
height="200"
onErrorBoundary={inactiveErrorHandler}
Expand All @@ -135,7 +148,13 @@ describe('SuperChart', () => {

it('passes the props to renderer correctly', () => {
const wrapper = mount(
<SuperChart chartType={ChartKeys.DILIGENT} width={101} height={118} formData={{ abc: 1 }} />,
<SuperChart
chartType={ChartKeys.DILIGENT}
queryData={DEFAULT_QUERY_DATA}
width={101}
height={118}
formData={{ abc: 1 }}
/>,
);

return promiseTimeout(() => {
Expand All @@ -145,9 +164,50 @@ describe('SuperChart', () => {
});
});

describe('supports NoResultsComponent', () => {
it('renders NoResultsComponent when queryData is missing', () => {
const wrapper = mount(<SuperChart chartType={ChartKeys.DILIGENT} width="200" height="200" />);

expect(wrapper.find(NoResultsComponent)).toHaveLength(1);
});

it('renders NoResultsComponent when queryData data is null', () => {
const wrapper = mount(
<SuperChart
chartType={ChartKeys.DILIGENT}
queryData={{ data: null }}
width="200"
height="200"
/>,
);

expect(wrapper.find(NoResultsComponent)).toHaveLength(1);
});

it('renders NoResultsComponent when queryData data is empty', () => {
const wrapper = mount(
<SuperChart
chartType={ChartKeys.DILIGENT}
queryData={{ data: [] }}
width="200"
height="200"
/>,
);

expect(wrapper.find(NoResultsComponent)).toHaveLength(1);
});
});

describe('supports dynamic width and/or height', () => {
it('works with width and height that are numbers', () => {
const wrapper = mount(<SuperChart chartType={ChartKeys.DILIGENT} width={100} height={100} />);
const wrapper = mount(
<SuperChart
chartType={ChartKeys.DILIGENT}
queryData={DEFAULT_QUERY_DATA}
width={100}
height={100}
/>,
);

return promiseTimeout(() => {
const renderedWrapper = wrapper.render();
Expand All @@ -157,7 +217,13 @@ describe('SuperChart', () => {
});
it('works when width and height are percent', () => {
const wrapper = mount(
<SuperChart chartType={ChartKeys.DILIGENT} debounceTime={1} width="100%" height="100%" />,
<SuperChart
chartType={ChartKeys.DILIGENT}
queryData={DEFAULT_QUERY_DATA}
debounceTime={1}
width="100%"
height="100%"
/>,
);
triggerResizeObserver();

Expand All @@ -169,7 +235,13 @@ describe('SuperChart', () => {
});
it('works when only width is percent', () => {
const wrapper = mount(
<SuperChart chartType={ChartKeys.DILIGENT} debounceTime={1} width="50%" height="125" />,
<SuperChart
chartType={ChartKeys.DILIGENT}
queryData={DEFAULT_QUERY_DATA}
debounceTime={1}
width="50%"
height="125"
/>,
);
triggerResizeObserver([{ contentRect: { height: 125, width: 150 } }]);

Expand All @@ -188,7 +260,13 @@ describe('SuperChart', () => {
});
it('works when only height is percent', () => {
const wrapper = mount(
<SuperChart chartType={ChartKeys.DILIGENT} debounceTime={1} width="50" height="25%" />,
<SuperChart
chartType={ChartKeys.DILIGENT}
queryData={DEFAULT_QUERY_DATA}
debounceTime={1}
width="50"
height="25%"
/>,
);
triggerResizeObserver([{ contentRect: { height: 75, width: 50 } }]);

Expand All @@ -206,7 +284,13 @@ describe('SuperChart', () => {
}, 100);
});
it('works when width and height are not specified', () => {
const wrapper = mount(<SuperChart chartType={ChartKeys.DILIGENT} debounceTime={1} />);
const wrapper = mount(
<SuperChart
chartType={ChartKeys.DILIGENT}
queryData={DEFAULT_QUERY_DATA}
debounceTime={1}
/>,
);
triggerResizeObserver();

return promiseTimeout(() => {
Expand All @@ -231,7 +315,13 @@ describe('SuperChart', () => {

it('works with width and height that are numbers', () => {
const wrapper = mount(
<SuperChart chartType={ChartKeys.DILIGENT} width={100} height={100} Wrapper={MyWrapper} />,
<SuperChart
chartType={ChartKeys.DILIGENT}
queryData={DEFAULT_QUERY_DATA}
width={100}
height={100}
Wrapper={MyWrapper}
/>,
);

return promiseTimeout(() => {
Expand All @@ -247,6 +337,7 @@ describe('SuperChart', () => {
const wrapper = mount(
<SuperChart
chartType={ChartKeys.DILIGENT}
queryData={DEFAULT_QUERY_DATA}
debounceTime={1}
width="100%"
height="100%"
Expand Down

0 comments on commit 06d7ad5

Please sign in to comment.