fix: chart empty state & result panel when multiple queries are executed display incorrectly (#20816)

This commit is contained in:
Diego Medina 2022-07-22 03:58:42 -03:00 committed by GitHub
parent 34278c2d56
commit 279ab954b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 53 additions and 44 deletions

View File

@ -26,6 +26,7 @@ import { ParentSize } from '@vx/responsive';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { withTheme } from '@emotion/react'; import { withTheme } from '@emotion/react';
import { parseLength, Dimension } from '../../dimension'; import { parseLength, Dimension } from '../../dimension';
import getChartMetadataRegistry from '../registries/ChartMetadataRegistrySingleton';
import SuperChartCore, { Props as SuperChartCoreProps } from './SuperChartCore'; import SuperChartCore, { Props as SuperChartCoreProps } from './SuperChartCore';
import DefaultFallbackComponent from './FallbackComponent'; import DefaultFallbackComponent from './FallbackComponent';
import ChartProps, { ChartPropsConfig } from '../models/ChartProps'; import ChartProps, { ChartPropsConfig } from '../models/ChartProps';
@ -140,6 +141,9 @@ class SuperChart extends React.PureComponent<Props, {}> {
this.core = core; this.core = core;
}; };
private getQueryCount = () =>
getChartMetadataRegistry().get(this.props.chartType)?.queryObjectCount ?? 1;
renderChart(width: number, height: number) { renderChart(width: number, height: number) {
const { const {
id, id,
@ -174,9 +178,11 @@ class SuperChart extends React.PureComponent<Props, {}> {
const noResultQueries = const noResultQueries =
enableNoResults && enableNoResults &&
(!queriesData || (!queriesData ||
queriesData.every( queriesData
({ data }) => !data || (Array.isArray(data) && data.length === 0), .slice(0, this.getQueryCount())
)); .every(
({ data }) => !data || (Array.isArray(data) && data.length === 0),
));
if (noResultQueries) { if (noResultQueries) {
chart = noResults || ( chart = noResults || (
<NoResultsComponent <NoResultsComponent

View File

@ -48,6 +48,7 @@ export interface ChartMetadataConfig {
// label: ChartLabel.DEPRECATED which will display a "deprecated" label on the chart. // label: ChartLabel.DEPRECATED which will display a "deprecated" label on the chart.
label?: ChartLabel | null; label?: ChartLabel | null;
labelExplanation?: string | null; labelExplanation?: string | null;
queryObjectCount?: number;
} }
export default class ChartMetadata { export default class ChartMetadata {
@ -87,6 +88,8 @@ export default class ChartMetadata {
labelExplanation?: string | null; labelExplanation?: string | null;
queryObjectCount: number;
constructor(config: ChartMetadataConfig) { constructor(config: ChartMetadataConfig) {
const { const {
name, name,
@ -106,6 +109,7 @@ export default class ChartMetadata {
deprecated = false, deprecated = false,
label = null, label = null,
labelExplanation = null, labelExplanation = null,
queryObjectCount = 1,
} = config; } = config;
this.name = name; this.name = name;
@ -134,6 +138,7 @@ export default class ChartMetadata {
this.deprecated = deprecated; this.deprecated = deprecated;
this.label = label; this.label = label;
this.labelExplanation = labelExplanation; this.labelExplanation = labelExplanation;
this.queryObjectCount = queryObjectCount;
} }
canBeAnnotationType(type: string): boolean { canBeAnnotationType(type: string): boolean {

View File

@ -84,6 +84,7 @@ export default class EchartsTimeseriesChartPlugin extends ChartPlugin<
t('Time'), t('Time'),
t('Transformable'), t('Transformable'),
], ],
queryObjectCount: 2,
}), }),
// @ts-ignore // @ts-ignore
transformProps, transformProps,

View File

@ -17,13 +17,17 @@
* under the License. * under the License.
*/ */
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { ensureIsArray, styled, t } from '@superset-ui/core'; import {
ensureIsArray,
styled,
t,
getChartMetadataRegistry,
} from '@superset-ui/core';
import Loading from 'src/components/Loading'; import Loading from 'src/components/Loading';
import { EmptyStateMedium } from 'src/components/EmptyState'; import { EmptyStateMedium } from 'src/components/EmptyState';
import { getChartDataRequest } from 'src/components/Chart/chartAction'; import { getChartDataRequest } from 'src/components/Chart/chartAction';
import { getClientErrorObject } from 'src/utils/getClientErrorObject'; import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import { ResultsPaneProps, QueryResultInterface } from '../types'; import { ResultsPaneProps, QueryResultInterface } from '../types';
import { getQueryCount } from '../utils';
import { SingleQueryResultPane } from './SingleQueryResultPane'; import { SingleQueryResultPane } from './SingleQueryResultPane';
import { TableControls } from './DataTableControls'; import { TableControls } from './DataTableControls';
@ -43,12 +47,14 @@ export const useResultsPane = ({
isVisible, isVisible,
dataSize = 50, dataSize = 50,
}: ResultsPaneProps): React.ReactElement[] => { }: ResultsPaneProps): React.ReactElement[] => {
const metadata = getChartMetadataRegistry().get(
queryFormData?.viz_type || queryFormData?.vizType,
);
const [resultResp, setResultResp] = useState<QueryResultInterface[]>([]); const [resultResp, setResultResp] = useState<QueryResultInterface[]>([]);
const [isLoading, setIsLoading] = useState<boolean>(true); const [isLoading, setIsLoading] = useState<boolean>(true);
const [responseError, setResponseError] = useState<string>(''); const [responseError, setResponseError] = useState<string>('');
const queryCount = getQueryCount( const queryCount = metadata?.queryObjectCount ?? 1;
queryFormData?.viz_type || queryFormData?.vizType,
);
useEffect(() => { useEffect(() => {
// it's an invalid formData when gets a errorMessage // it's an invalid formData when gets a errorMessage
@ -122,15 +128,17 @@ export const useResultsPane = ({
); );
} }
return resultResp.map((result, idx) => ( return resultResp
<SingleQueryResultPane .slice(0, queryCount)
data={result.data} .map((result, idx) => (
colnames={result.colnames} <SingleQueryResultPane
coltypes={result.coltypes} data={result.data}
dataSize={dataSize} colnames={result.colnames}
datasourceId={queryFormData.datasource} coltypes={result.coltypes}
key={idx} dataSize={dataSize}
isVisible={isVisible} datasourceId={queryFormData.datasource}
/> key={idx}
)); isVisible={isVisible}
/>
));
}; };

View File

@ -24,7 +24,7 @@ import {
waitForElementToBeRemoved, waitForElementToBeRemoved,
} from 'spec/helpers/testing-library'; } from 'spec/helpers/testing-library';
import { exploreActions } from 'src/explore/actions/exploreActions'; import { exploreActions } from 'src/explore/actions/exploreActions';
import { promiseTimeout } from '@superset-ui/core'; import { ChartMetadata, ChartPlugin, promiseTimeout } from '@superset-ui/core';
import { ResultsPaneOnDashboard } from '../components'; import { ResultsPaneOnDashboard } from '../components';
import { createResultsPaneOnDashboardProps } from './fixture'; import { createResultsPaneOnDashboardProps } from './fixture';
@ -147,6 +147,19 @@ describe('ResultsPaneOnDashboard', () => {
}); });
test('multiple results pane', async () => { test('multiple results pane', async () => {
const FakeChart = () => <span>test</span>;
const metadata = new ChartMetadata({
name: 'test-chart',
thumbnail: '',
queryObjectCount: 2,
});
const plugin = new ChartPlugin({
metadata,
Chart: FakeChart,
});
plugin.configure({ key: 'mixed_timeseries' }).register();
const props = createResultsPaneOnDashboardProps({ const props = createResultsPaneOnDashboardProps({
sliceId: 196, sliceId: 196,
vizType: 'mixed_timeseries', vizType: 'mixed_timeseries',

View File

@ -1,24 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
const queryObjectCount = {
mixed_timeseries: 2,
};
export const getQueryCount = (vizType: string): number =>
queryObjectCount?.[vizType] || 1;