This is an automated email from the ASF dual-hosted git repository.
robdiciuccio pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git
The following commit(s) were added to refs/heads/master by this push:
new 49ec13c feat: Support multiple queries per request (#11880)
49ec13c is described below
commit 49ec13c68c183b110b5c7ad18dfb829ce9f34245
Author: simchaNielsen <[email protected]>
AuthorDate: Fri Dec 18 19:15:27 2020 +0200
feat: Support multiple queries per request (#11880)
* refactor: add queriesData fields for multiple queries
* feat: support multi queries request
* lint: fix lint
* lint: fix lint
* lint: fix lint
* fix: fix CR notes
* fix: fix CR notes
* fix: fix CR notes
* fix: fix error case for multi queries
* feat: change queryResponse to queriesResponse
* fix: revert webpack
* test: fix tests
* chore: lint
* chore: adjust asyncEvent to multiple results
* fix: lint
* fix: eslint
* fix: another eslint rule
Co-authored-by: Amit Miran <[email protected]>
Co-authored-by: amitmiran137 <[email protected]>
---
.../spec/javascripts/chart/chartActions_spec.js | 2 +-
.../dashboard/components/FiltersBadge_spec.tsx | 36 ++++++++------
superset-frontend/src/chart/Chart.jsx | 16 ++----
superset-frontend/src/chart/ChartRenderer.jsx | 13 ++---
superset-frontend/src/chart/chartAction.js | 57 ++++++++++------------
superset-frontend/src/chart/chartReducer.js | 14 +++---
.../dashboard/components/FiltersBadge/selectors.ts | 4 +-
.../src/dashboard/components/SliceHeader.jsx | 8 +--
.../dashboard/components/SliceHeaderControls.jsx | 38 +++++++++++----
.../dashboard/components/gridComponents/Chart.jsx | 12 +++--
.../src/dashboard/util/propShapes.jsx | 2 +-
.../src/explore/components/DisplayQueryButton.jsx | 1 -
.../explore/components/ExploreActionButtons.jsx | 6 +--
.../src/explore/components/ExploreChartHeader.jsx | 4 +-
.../src/explore/components/ExploreChartPanel.jsx | 2 +-
.../src/explore/reducers/getInitialState.js | 2 +-
superset-frontend/src/middleware/asyncEvent.ts | 15 +++---
17 files changed, 127 insertions(+), 105 deletions(-)
diff --git a/superset-frontend/spec/javascripts/chart/chartActions_spec.js
b/superset-frontend/spec/javascripts/chart/chartActions_spec.js
index dc57e22..7bca9f7 100644
--- a/superset-frontend/spec/javascripts/chart/chartActions_spec.js
+++ b/superset-frontend/spec/javascripts/chart/chartActions_spec.js
@@ -189,7 +189,7 @@ describe('chart actions', () => {
expect(dispatch.callCount).toBe(5);
const updateFailedAction = dispatch.args[4][0];
expect(updateFailedAction.type).toBe(actions.CHART_UPDATE_FAILED);
- expect(updateFailedAction.queryResponse.error).toBe('misc error');
+ expect(updateFailedAction.queriesResponse[0].error).toBe('misc error');
setupDefaultFetchMock();
});
diff --git
a/superset-frontend/spec/javascripts/dashboard/components/FiltersBadge_spec.tsx
b/superset-frontend/spec/javascripts/dashboard/components/FiltersBadge_spec.tsx
index 07dfdd5..7a53de0 100644
---
a/superset-frontend/spec/javascripts/dashboard/components/FiltersBadge_spec.tsx
+++
b/superset-frontend/spec/javascripts/dashboard/components/FiltersBadge_spec.tsx
@@ -51,11 +51,13 @@ describe('FiltersBadge', () => {
store.dispatch({
type: CHART_UPDATE_SUCCEEDED,
key: sliceId,
- queryResponse: {
- status: 'success',
- applied_filters: [],
- rejected_filters: [],
- },
+ queriesResponse: [
+ {
+ status: 'success',
+ applied_filters: [],
+ rejected_filters: [],
+ },
+ ],
dashboardFilters,
});
const wrapper = shallow(
@@ -74,11 +76,13 @@ describe('FiltersBadge', () => {
store.dispatch({
type: CHART_UPDATE_SUCCEEDED,
key: sliceId,
- queryResponse: {
- status: 'success',
- applied_filters: [{ column: 'region' }],
- rejected_filters: [],
- },
+ queriesResponse: [
+ {
+ status: 'success',
+ applied_filters: [{ column: 'region' }],
+ rejected_filters: [],
+ },
+ ],
dashboardFilters,
});
const wrapper = shallow(
@@ -97,11 +101,13 @@ describe('FiltersBadge', () => {
store.dispatch({
type: CHART_UPDATE_SUCCEEDED,
key: sliceId,
- queryResponse: {
- status: 'success',
- applied_filters: [],
- rejected_filters: [{ column: 'region', reason: 'not_in_datasource' }],
- },
+ queriesResponse: [
+ {
+ status: 'success',
+ applied_filters: [],
+ rejected_filters: [{ column: 'region', reason: 'not_in_datasource'
}],
+ },
+ ],
dashboardFilters,
});
const wrapper = shallow(
diff --git a/superset-frontend/src/chart/Chart.jsx
b/superset-frontend/src/chart/Chart.jsx
index bb4910c..20b3b98 100644
--- a/superset-frontend/src/chart/Chart.jsx
+++ b/superset-frontend/src/chart/Chart.jsx
@@ -56,7 +56,7 @@ const propTypes = {
chartAlert: PropTypes.string,
chartStatus: PropTypes.string,
chartStackTrace: PropTypes.string,
- queryResponse: PropTypes.object,
+ queriesResponse: PropTypes.arrayOf(PropTypes.object),
triggerQuery: PropTypes.bool,
refreshOverlayVisible: PropTypes.bool,
errorMessage: PropTypes.node,
@@ -150,14 +150,8 @@ class Chart extends React.PureComponent {
});
}
- renderErrorMessage() {
- const {
- chartAlert,
- chartStackTrace,
- dashboardId,
- owners,
- queryResponse,
- } = this.props;
+ renderErrorMessage(queryResponse) {
+ const { chartAlert, chartStackTrace, dashboardId, owners } = this.props;
const error = queryResponse?.errors?.[0];
if (error) {
@@ -187,14 +181,14 @@ class Chart extends React.PureComponent {
errorMessage,
onQuery,
refreshOverlayVisible,
+ queriesResponse = [],
} = this.props;
const isLoading = chartStatus === 'loading';
-
const isFaded = refreshOverlayVisible && !errorMessage;
this.renderContainerStartTime = Logger.getTimestamp();
if (chartStatus === 'failed') {
- return this.renderErrorMessage();
+ return queriesResponse.map(item => this.renderErrorMessage(item));
}
if (errorMessage) {
return (
diff --git a/superset-frontend/src/chart/ChartRenderer.jsx
b/superset-frontend/src/chart/ChartRenderer.jsx
index dce5e75..81699ca 100644
--- a/superset-frontend/src/chart/ChartRenderer.jsx
+++ b/superset-frontend/src/chart/ChartRenderer.jsx
@@ -37,7 +37,7 @@ const propTypes = {
// state
chartAlert: PropTypes.string,
chartStatus: PropTypes.string,
- queryResponse: PropTypes.object,
+ queriesResponse: PropTypes.arrayOf(PropTypes.object),
triggerQuery: PropTypes.bool,
refreshOverlayVisible: PropTypes.bool,
// dashboard callbacks
@@ -78,14 +78,14 @@ class ChartRenderer extends React.Component {
shouldComponentUpdate(nextProps) {
const resultsReady =
- nextProps.queryResponse &&
+ nextProps.queriesResponse &&
['success', 'rendered'].indexOf(nextProps.chartStatus) > -1 &&
- !nextProps.queryResponse.error &&
+ !nextProps.queriesResponse?.[0]?.error &&
!nextProps.refreshOverlayVisible;
if (resultsReady) {
this.hasQueryResponseChange =
- nextProps.queryResponse !== this.props.queryResponse;
+ nextProps.queriesResponse !== this.props.queriesResponse;
return (
this.hasQueryResponseChange ||
nextProps.annotationData !== this.props.annotationData ||
@@ -179,7 +179,7 @@ class ChartRenderer extends React.Component {
datasource,
initialValues,
formData,
- queryResponse,
+ queriesResponse,
} = this.props;
// It's bad practice to use unprefixed `vizType` as classnames for chart
@@ -218,7 +218,8 @@ class ChartRenderer extends React.Component {
initialValues={initialValues}
formData={formData}
hooks={this.hooks}
- queryData={queryResponse}
+ queryData={queriesResponse?.[0]} // deprecated
+ queriesData={queriesResponse}
onRenderSuccess={this.handleRenderSuccess}
onRenderFailure={this.handleRenderFailure}
/>
diff --git a/superset-frontend/src/chart/chartAction.js
b/superset-frontend/src/chart/chartAction.js
index 0198b33..1e0c332 100644
--- a/superset-frontend/src/chart/chartAction.js
+++ b/superset-frontend/src/chart/chartAction.js
@@ -52,8 +52,8 @@ export function chartUpdateStarted(queryController,
latestQueryFormData, key) {
}
export const CHART_UPDATE_SUCCEEDED = 'CHART_UPDATE_SUCCEEDED';
-export function chartUpdateSucceeded(queryResponse, key) {
- return { type: CHART_UPDATE_SUCCEEDED, queryResponse, key };
+export function chartUpdateSucceeded(queriesResponse, key) {
+ return { type: CHART_UPDATE_SUCCEEDED, queriesResponse, key };
}
export const CHART_UPDATE_STOPPED = 'CHART_UPDATE_STOPPED';
@@ -62,8 +62,8 @@ export function chartUpdateStopped(key) {
}
export const CHART_UPDATE_FAILED = 'CHART_UPDATE_FAILED';
-export function chartUpdateFailed(queryResponse, key) {
- return { type: CHART_UPDATE_FAILED, queryResponse, key };
+export function chartUpdateFailed(queriesResponse, key) {
+ return { type: CHART_UPDATE_FAILED, queriesResponse, key };
}
export const CHART_UPDATE_QUEUED = 'CHART_UPDATE_QUEUED';
@@ -361,38 +361,35 @@ export function exploreJSON(
const chartDataRequestCaught = chartDataRequest
.then(response => {
+ const queriesResponse = response.result;
if (isFeatureEnabled(FeatureFlag.GLOBAL_ASYNC_QUERIES)) {
// deal with getChartDataRequest transforming the response data
const result = 'result' in response ? response.result[0] : response;
return dispatch(chartUpdateQueued(result, key));
}
- // new API returns an object with an array of restults
- // problem: response holds a list of results, when before we were just
getting one result.
- // How to make the entire app compatible with multiple results?
- // For now just use the first result.
- const result = response.result[0];
-
- dispatch(
- logEvent(LOG_ACTIONS_LOAD_CHART, {
- slice_id: key,
- applied_filters: result.applied_filters,
- is_cached: result.is_cached,
- force_refresh: force,
- row_count: result.rowcount,
- datasource: formData.datasource,
- start_offset: logStart,
- ts: new Date().getTime(),
- duration: Logger.getTimestamp() - logStart,
- has_extra_filters:
- formData.extra_filters && formData.extra_filters.length > 0,
- viz_type: formData.viz_type,
- data_age: result.is_cached
- ? moment(new Date()).diff(moment.utc(result.cached_dttm))
- : null,
- }),
+ queriesResponse.forEach(resultItem =>
+ dispatch(
+ logEvent(LOG_ACTIONS_LOAD_CHART, {
+ slice_id: key,
+ applied_filters: resultItem.applied_filters,
+ is_cached: resultItem.is_cached,
+ force_refresh: force,
+ row_count: resultItem.rowcount,
+ datasource: formData.datasource,
+ start_offset: logStart,
+ ts: new Date().getTime(),
+ duration: Logger.getTimestamp() - logStart,
+ has_extra_filters:
+ formData.extra_filters && formData.extra_filters.length > 0,
+ viz_type: formData.viz_type,
+ data_age: resultItem.is_cached
+ ? moment(new Date()).diff(moment.utc(resultItem.cached_dttm))
+ : null,
+ }),
+ ),
);
- return dispatch(chartUpdateSucceeded(result, key));
+ return dispatch(chartUpdateSucceeded(queriesResponse, key));
})
.catch(response => {
const appendErrorLog = (errorDetails, isCached) => {
@@ -419,7 +416,7 @@ export function exploreJSON(
} else {
appendErrorLog(parsedResponse.error, parsedResponse.is_cached);
}
- return dispatch(chartUpdateFailed(parsedResponse, key));
+ return dispatch(chartUpdateFailed([parsedResponse], key));
});
});
diff --git a/superset-frontend/src/chart/chartReducer.js
b/superset-frontend/src/chart/chartReducer.js
index fc28e99..923caf1 100644
--- a/superset-frontend/src/chart/chartReducer.js
+++ b/superset-frontend/src/chart/chartReducer.js
@@ -30,7 +30,7 @@ export const chart = {
chartUpdateStartTime: 0,
latestQueryFormData: {},
queryController: null,
- queryResponse: null,
+ queriesResponse: null,
triggerQuery: true,
lastRendered: 0,
};
@@ -47,8 +47,8 @@ export default function chartReducer(charts = {}, action) {
return {
...state,
chartStatus: 'success',
- queryResponse: action.queryResponse,
chartAlert: null,
+ queriesResponse: action.queriesResponse,
chartUpdateEndTime: now(),
};
},
@@ -97,13 +97,13 @@ export default function chartReducer(charts = {}, action) {
return {
...state,
chartStatus: 'failed',
- chartAlert: action.queryResponse
- ? action.queryResponse.error
+ chartAlert: action.queriesResponse
+ ? action.queriesResponse?.[0]?.error
: t('Network error.'),
chartUpdateEndTime: now(),
- queryResponse: action.queryResponse,
- chartStackTrace: action.queryResponse
- ? action.queryResponse.stacktrace
+ queriesResponse: action.queriesResponse,
+ chartStackTrace: action.queriesResponse
+ ? action.queriesResponse?.[0]?.stacktrace
: null,
};
},
diff --git
a/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts
b/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts
index 9cdd43a..6aaa0d9 100644
--- a/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts
+++ b/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts
@@ -132,12 +132,12 @@ export const selectIndicatorsForChart = (
// for now we only need to know which columns are compatible/incompatible,
// so grab the columns from the applied/rejected filters
const appliedColumns: Set<string> = new Set(
- (chart?.queryResponse?.applied_filters || []).map(
+ (chart?.queriesResponse?.[0]?.applied_filters || []).map(
(filter: any) => filter.column,
),
);
const rejectedColumns: Set<string> = new Set(
- (chart?.queryResponse?.rejected_filters || []).map(
+ (chart?.queriesResponse?.[0]?.rejected_filters || []).map(
(filter: any) => filter.column,
),
);
diff --git a/superset-frontend/src/dashboard/components/SliceHeader.jsx
b/superset-frontend/src/dashboard/components/SliceHeader.jsx
index 1f62d83..605ba8e 100644
--- a/superset-frontend/src/dashboard/components/SliceHeader.jsx
+++ b/superset-frontend/src/dashboard/components/SliceHeader.jsx
@@ -29,8 +29,8 @@ const propTypes = {
innerRef: PropTypes.func,
slice: PropTypes.object.isRequired,
isExpanded: PropTypes.bool,
- isCached: PropTypes.bool,
- cachedDttm: PropTypes.string,
+ isCached: PropTypes.arrayOf(PropTypes.bool),
+ cachedDttm: PropTypes.arrayOf(PropTypes.string),
updatedDttm: PropTypes.number,
updateSliceName: PropTypes.func,
toggleExpandSlice: PropTypes.func,
@@ -64,8 +64,8 @@ const defaultProps = {
annotationError: {},
cachedDttm: null,
updatedDttm: null,
- isCached: false,
- isExpanded: false,
+ isCached: [],
+ isExpanded: [],
sliceName: '',
supersetCanExplore: false,
supersetCanCSV: false,
diff --git a/superset-frontend/src/dashboard/components/SliceHeaderControls.jsx
b/superset-frontend/src/dashboard/components/SliceHeaderControls.jsx
index 5835199..c88b8f7 100644
--- a/superset-frontend/src/dashboard/components/SliceHeaderControls.jsx
+++ b/superset-frontend/src/dashboard/components/SliceHeaderControls.jsx
@@ -31,9 +31,9 @@ const propTypes = {
componentId: PropTypes.string.isRequired,
dashboardId: PropTypes.number.isRequired,
addDangerToast: PropTypes.func.isRequired,
- isCached: PropTypes.bool,
+ isCached: PropTypes.arrayOf(PropTypes.bool),
+ cachedDttm: PropTypes.arrayOf(PropTypes.string),
isExpanded: PropTypes.bool,
- cachedDttm: PropTypes.string,
updatedDttm: PropTypes.number,
supersetCanExplore: PropTypes.bool,
supersetCanCSV: PropTypes.bool,
@@ -49,9 +49,9 @@ const defaultProps = {
toggleExpandSlice: () => ({}),
exploreChart: () => ({}),
exportCSV: () => ({}),
- cachedDttm: null,
+ cachedDttm: [],
updatedDttm: null,
- isCached: false,
+ isCached: [],
isExpanded: false,
supersetCanExplore: false,
supersetCanCSV: false,
@@ -82,9 +82,14 @@ const VerticalDotsContainer = styled.div`
`;
const RefreshTooltip = styled.div`
- height: ${({ theme }) => theme.gridUnit * 4}px;
+ height: auto;
margin: ${({ theme }) => theme.gridUnit}px 0;
color: ${({ theme }) => theme.colors.grayscale.base};
+ line-height: ${({ theme }) => theme.typography.sizes.m * 1.5}px;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: flex-start;
`;
const SCREENSHOT_NODE_SELECTOR = '.dashboard-component-chart-holder';
@@ -171,13 +176,26 @@ class SliceHeaderControls extends React.PureComponent {
addDangerToast,
isFullSize,
} = this.props;
- const cachedWhen = moment.utc(cachedDttm).fromNow();
+ const cachedWhen = cachedDttm.map(itemCachedDttm =>
+ moment.utc(itemCachedDttm).fromNow(),
+ );
const updatedWhen = updatedDttm ? moment.utc(updatedDttm).fromNow() : '';
- const refreshTooltip = isCached
- ? t('Cached %s', cachedWhen)
- : (updatedWhen && t('Fetched %s', updatedWhen)) || '';
+ const getCachedTitle = itemCached => {
+ return itemCached
+ ? t('Cached %s', cachedWhen)
+ : updatedWhen && t('Fetched %s', updatedWhen);
+ };
+ const refreshTooltipData = isCached.map(getCachedTitle) || '';
+ // If all queries have same cache time we can unit them to one
+ let refreshTooltip = [...new Set(refreshTooltipData)];
+ refreshTooltip = refreshTooltip.map((item, index) => (
+ <div>
+ {refreshTooltip.length > 1
+ ? `${t('Query')} ${index + 1}: ${item}`
+ : item}
+ </div>
+ ));
const resizeLabel = isFullSize ? t('Minimize Chart') : t('Maximize Chart');
-
const menu = (
<Menu
onClick={this.handleMenuClick}
diff --git
a/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx
b/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx
index 7e4d809..a7d2b83 100644
--- a/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx
+++ b/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx
@@ -266,10 +266,13 @@ export default class Chart extends React.Component {
return <MissingChart height={this.getChartHeight()} />;
}
- const { queryResponse, chartUpdateEndTime, chartStatus } = chart;
+ const { queriesResponse, chartUpdateEndTime, chartStatus } = chart;
const isLoading = chartStatus === 'loading';
- const isCached = queryResponse && queryResponse.is_cached;
- const cachedDttm = queryResponse && queryResponse.cached_dttm;
+ // eslint-disable-next-line camelcase
+ const isCached = queriesResponse?.map(({ is_cached }) => is_cached) || [];
+ const cachedDttm =
+ // eslint-disable-next-line camelcase
+ queriesResponse?.map(({ cached_dttm }) => cached_dttm) || [];
const isOverflowable = OVERFLOWABLE_VIZ_TYPES.has(slice.viz_type);
const initialValues = isFilterBox(id)
? getFilterValuesByFilterId({
@@ -277,7 +280,6 @@ export default class Chart extends React.Component {
filterId: id,
})
: {};
-
return (
<div className="chart-slice">
<SliceHeader
@@ -352,7 +354,7 @@ export default class Chart extends React.Component {
dashboardId={dashboardId}
initialValues={initialValues}
formData={formData}
- queryResponse={chart.queryResponse}
+ queriesResponse={chart.queriesResponse}
timeout={timeout}
triggerQuery={chart.triggerQuery}
vizType={slice.viz_type}
diff --git a/superset-frontend/src/dashboard/util/propShapes.jsx
b/superset-frontend/src/dashboard/util/propShapes.jsx
index b8c2b09..78bcf3f 100644
--- a/superset-frontend/src/dashboard/util/propShapes.jsx
+++ b/superset-frontend/src/dashboard/util/propShapes.jsx
@@ -50,7 +50,7 @@ export const chartPropShape = PropTypes.shape({
chartUpdateStartTime: PropTypes.number,
latestQueryFormData: PropTypes.object,
queryController: PropTypes.shape({ abort: PropTypes.func }),
- queryResponse: PropTypes.object,
+ queriesResponse: PropTypes.arrayOf(PropTypes.object),
triggerQuery: PropTypes.bool,
lastRendered: PropTypes.number,
});
diff --git a/superset-frontend/src/explore/components/DisplayQueryButton.jsx
b/superset-frontend/src/explore/components/DisplayQueryButton.jsx
index e292839..e19beb6 100644
--- a/superset-frontend/src/explore/components/DisplayQueryButton.jsx
+++ b/superset-frontend/src/explore/components/DisplayQueryButton.jsx
@@ -47,7 +47,6 @@ SyntaxHighlighter.registerLanguage('json', jsonSyntax);
const propTypes = {
onOpenPropertiesModal: PropTypes.func,
onOpenInEditor: PropTypes.func,
- queryResponse: PropTypes.object,
chartStatus: PropTypes.string,
chartHeight: PropTypes.string.isRequired,
latestQueryFormData: PropTypes.object.isRequired,
diff --git a/superset-frontend/src/explore/components/ExploreActionButtons.jsx
b/superset-frontend/src/explore/components/ExploreActionButtons.jsx
index c96fbb8..d485696 100644
--- a/superset-frontend/src/explore/components/ExploreActionButtons.jsx
+++ b/superset-frontend/src/explore/components/ExploreActionButtons.jsx
@@ -33,7 +33,7 @@ const propTypes = {
chartStatus: PropTypes.string,
chartHeight: PropTypes.string.isRequired,
latestQueryFormData: PropTypes.object,
- queryResponse: PropTypes.object,
+ queriesResponse: PropTypes.arrayOf(PropTypes.object),
slice: PropTypes.object,
};
@@ -43,7 +43,7 @@ export default function ExploreActionButtons({
chartHeight,
chartStatus,
latestQueryFormData,
- queryResponse,
+ queriesResponse,
slice,
}) {
const exportToCSVClasses = cx('btn btn-default btn-sm', {
@@ -106,7 +106,7 @@ export default function ExploreActionButtons({
)}
<ConnectedDisplayQueryButton
chartHeight={chartHeight}
- queryResponse={queryResponse}
+ queryResponse={queriesResponse?.[0]}
latestQueryFormData={latestQueryFormData}
chartStatus={chartStatus}
onOpenInEditor={actions.redirectSQLLab}
diff --git a/superset-frontend/src/explore/components/ExploreChartHeader.jsx
b/superset-frontend/src/explore/components/ExploreChartHeader.jsx
index 88a54b3..9c1df9f 100644
--- a/superset-frontend/src/explore/components/ExploreChartHeader.jsx
+++ b/superset-frontend/src/explore/components/ExploreChartHeader.jsx
@@ -130,8 +130,10 @@ export class ExploreChartHeader extends
React.PureComponent {
chartUpdateEndTime,
chartUpdateStartTime,
latestQueryFormData,
- queryResponse,
+ queriesResponse,
} = this.props.chart;
+ // TODO: when will get appropriate design for multi queries use all
results and not first only
+ const queryResponse = queriesResponse?.[0];
const chartFinished = ['failed', 'rendered', 'success'].includes(
this.props.chart.chartStatus,
);
diff --git a/superset-frontend/src/explore/components/ExploreChartPanel.jsx
b/superset-frontend/src/explore/components/ExploreChartPanel.jsx
index bda8498..0c608ea 100644
--- a/superset-frontend/src/explore/components/ExploreChartPanel.jsx
+++ b/superset-frontend/src/explore/components/ExploreChartPanel.jsx
@@ -189,7 +189,7 @@ const ExploreChartPanel = props => {
formData={props.form_data}
onQuery={props.onQuery}
owners={props?.slice?.owners}
- queryResponse={chart.queryResponse}
+ queriesResponse={chart.queriesResponse}
refreshOverlayVisible={props.refreshOverlayVisible}
setControlValue={props.actions.setControlValue}
timeout={props.timeout}
diff --git a/superset-frontend/src/explore/reducers/getInitialState.js
b/superset-frontend/src/explore/reducers/getInitialState.js
index 53dad95..0774340 100644
--- a/superset-frontend/src/explore/reducers/getInitialState.js
+++ b/superset-frontend/src/explore/reducers/getInitialState.js
@@ -72,7 +72,7 @@ export default function getInitialState(bootstrapData) {
latestQueryFormData: getFormDataFromControls(controls),
sliceFormData,
queryController: null,
- queryResponse: null,
+ queriesResponse: null,
triggerQuery: false,
lastRendered: 0,
},
diff --git a/superset-frontend/src/middleware/asyncEvent.ts
b/superset-frontend/src/middleware/asyncEvent.ts
index 32d4010..b7a4912 100644
--- a/superset-frontend/src/middleware/asyncEvent.ts
+++ b/superset-frontend/src/middleware/asyncEvent.ts
@@ -16,10 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Middleware, MiddlewareAPI, Dispatch } from 'redux';
+import { Dispatch, Middleware, MiddlewareAPI } from 'redux';
import { makeApi, SupersetClient } from '@superset-ui/core';
import { SupersetError } from 'src/components/ErrorMessage/types';
-import { isFeatureEnabled, FeatureFlag } from '../featureFlags';
+import { FeatureFlag, isFeatureEnabled } from '../featureFlags';
import {
getClientErrorObject,
parseErrorJson,
@@ -100,7 +100,7 @@ const initAsyncEvents = (options: AsyncEventOptions) => {
const { json } = await SupersetClient.get({
endpoint: asyncEvent.result_url,
});
- data = 'result' in json ? json.result[0] : json;
+ data = 'result' in json ? json.result : json;
} catch (response) {
status = 'error';
data = await getClientErrorObject(response);
@@ -152,7 +152,7 @@ const initAsyncEvents = (options: AsyncEventOptions) => {
break;
case JOB_STATUS.ERROR:
store.dispatch(
- errorAction(componentId, parseErrorJson(asyncEvent)),
+ errorAction(componentId, [parseErrorJson(asyncEvent)]),
);
break;
default:
@@ -164,10 +164,13 @@ const initAsyncEvents = (options: AsyncEventOptions) => {
const fetchResults = await Promise.all(fetchDataEvents);
fetchResults.forEach(result => {
+ const data = Array.isArray(result.data)
+ ? result.data
+ : [result.data];
if (result.status === 'success') {
- store.dispatch(successAction(result.componentId, result.data));
+ store.dispatch(successAction(result.componentId, data));
} else {
- store.dispatch(errorAction(result.componentId, result.data));
+ store.dispatch(errorAction(result.componentId, data));
}
});
}