From 9a5195ab8513f2f5da5133d827f3a71c2cccb30e Mon Sep 17 00:00:00 2001 From: Erik Ritter Date: Mon, 6 Jul 2020 09:49:32 -0700 Subject: [PATCH] feat: support new errors payload in SQL Lab (#10243) --- .../javascripts/sqllab/ResultSet_spec.jsx | 30 ++++++++++++- .../spec/javascripts/sqllab/fixtures.js | 44 +++++++++++++++++++ .../src/SqlLab/actions/sqlLab.js | 10 +++-- .../src/SqlLab/components/ResultSet.tsx | 15 +++---- .../src/SqlLab/reducers/sqlLab.js | 1 + superset-frontend/src/SqlLab/types.ts | 4 +- .../ErrorMessageWithStackTrace.tsx | 6 ++- 7 files changed, 92 insertions(+), 18 deletions(-) diff --git a/superset-frontend/spec/javascripts/sqllab/ResultSet_spec.jsx b/superset-frontend/spec/javascripts/sqllab/ResultSet_spec.jsx index e77b1c895d..dcba856a93 100644 --- a/superset-frontend/spec/javascripts/sqllab/ResultSet_spec.jsx +++ b/superset-frontend/spec/javascripts/sqllab/ResultSet_spec.jsx @@ -19,12 +19,20 @@ import React from 'react'; import { shallow } from 'enzyme'; import sinon from 'sinon'; - import { Alert, ProgressBar } from 'react-bootstrap'; + import FilterableTable from 'src/components/FilterableTable/FilterableTable'; import ExploreResultsButton from 'src/SqlLab/components/ExploreResultsButton'; import ResultSet from 'src/SqlLab/components/ResultSet'; -import { queries, stoppedQuery, runningQuery, cachedQuery } from './fixtures'; +import ErrorMessageWithStackTrace from 'src/components/ErrorMessage/ErrorMessageWithStackTrace'; +import { + cachedQuery, + failedQueryWithErrorMessage, + failedQueryWithErrors, + queries, + runningQuery, + stoppedQuery, +} from './fixtures'; describe('ResultSet', () => { const clearQuerySpy = sinon.spy(); @@ -42,6 +50,14 @@ describe('ResultSet', () => { const stoppedQueryProps = { ...mockedProps, query: stoppedQuery }; const runningQueryProps = { ...mockedProps, query: runningQuery }; const cachedQueryProps = { ...mockedProps, query: cachedQuery }; + const failedQueryWithErrorMessageProps = { + ...mockedProps, + query: failedQueryWithErrorMessage, + }; + const failedQueryWithErrorsProps = { + ...mockedProps, + query: failedQueryWithErrors, + }; const newProps = { query: { cached: false, @@ -117,5 +133,15 @@ describe('ResultSet', () => { const wrapper = shallow(); expect(wrapper.find(ProgressBar)).toHaveLength(1); }); + it('should render a failed query with an error message', () => { + const wrapper = shallow( + , + ); + expect(wrapper.find(ErrorMessageWithStackTrace)).toHaveLength(1); + }); + it('should render a failed query with an errors object', () => { + const wrapper = shallow(); + expect(wrapper.find(ErrorMessageWithStackTrace)).toHaveLength(1); + }); }); }); diff --git a/superset-frontend/spec/javascripts/sqllab/fixtures.js b/superset-frontend/spec/javascripts/sqllab/fixtures.js index 45bbb2ee9e..e7503ee113 100644 --- a/superset-frontend/spec/javascripts/sqllab/fixtures.js +++ b/superset-frontend/spec/javascripts/sqllab/fixtures.js @@ -389,6 +389,50 @@ export const stoppedQuery = { tab: 'Untitled Query 2', tempTable: '', }; + +export const failedQueryWithErrorMessage = { + dbId: 1, + cached: false, + ctas: false, + errorMessage: 'Something went wrong', + id: 'ryhMUZCGb', + progress: 0, + results: [], + runAsync: false, + schema: 'main', + sql: 'SELECT ...', + sqlEditorId: 'rJaf5u9WZ', + startDttm: 1497400851936, + state: 'failed', + tab: 'Untitled Query 2', + tempTable: '', +}; + +export const failedQueryWithErrors = { + dbId: 1, + cached: false, + ctas: false, + errors: [ + { + message: 'Something went wrong', + error_type: 'TEST_ERROR', + level: 'error', + extra: null, + }, + ], + id: 'ryhMUZCGb', + progress: 0, + results: [], + runAsync: false, + schema: 'main', + sql: 'SELECT ...', + sqlEditorId: 'rJaf5u9WZ', + startDttm: 1497400851936, + state: 'failed', + tab: 'Untitled Query 2', + tempTable: '', +}; + export const runningQuery = { dbId: 1, cached: false, diff --git a/superset-frontend/src/SqlLab/actions/sqlLab.js b/superset-frontend/src/SqlLab/actions/sqlLab.js index e38a4fe56d..8fb7428aae 100644 --- a/superset-frontend/src/SqlLab/actions/sqlLab.js +++ b/superset-frontend/src/SqlLab/actions/sqlLab.js @@ -271,7 +271,7 @@ export function querySuccess(query, results) { }; } -export function queryFailed(query, msg, link) { +export function queryFailed(query, msg, link, errors) { return function (dispatch) { const sync = !query.isDataPreview && @@ -283,7 +283,7 @@ export function queryFailed(query, msg, link) { : Promise.resolve(); return sync - .then(() => dispatch({ type: QUERY_FAILED, query, msg, link })) + .then(() => dispatch({ type: QUERY_FAILED, query, msg, link, errors })) .catch(() => dispatch( addDangerToast( @@ -332,7 +332,9 @@ export function fetchQueryResults(query, displayLimit) { error.statusText || t('Failed at retrieving results'); - return dispatch(queryFailed(query, message, error.link)); + return dispatch( + queryFailed(query, message, error.link, error.errors), + ); }), ); }; @@ -376,7 +378,7 @@ export function runQuery(query) { if (message.includes('CSRF token')) { message = t(COMMON_ERR_MESSAGES.SESSION_TIMED_OUT); } - dispatch(queryFailed(query, message, error.link)); + dispatch(queryFailed(query, message, error.link, error.errors)); }), ); }; diff --git a/superset-frontend/src/SqlLab/components/ResultSet.tsx b/superset-frontend/src/SqlLab/components/ResultSet.tsx index 75273b3e17..b074872ccc 100644 --- a/superset-frontend/src/SqlLab/components/ResultSet.tsx +++ b/superset-frontend/src/SqlLab/components/ResultSet.tsx @@ -21,6 +21,7 @@ import { Alert, Button, ButtonGroup, ProgressBar } from 'react-bootstrap'; import shortid from 'shortid'; import { t } from '@superset-ui/translation'; +import ErrorMessageWithStackTrace from 'src/components/ErrorMessage/ErrorMessageWithStackTrace'; import Loading from '../../components/Loading'; import ExploreCtasResultsButton from './ExploreCtasResultsButton'; import ExploreResultsButton from './ExploreResultsButton'; @@ -215,15 +216,11 @@ export default class ResultSet extends React.PureComponent< return Query was stopped; } else if (query.state === 'failed') { return ( - - {query.errorMessage} - {query.link && ( - - {' '} - {t('(Request Access)')}{' '} - - )} - + ); } else if (query.state === 'success' && query.ctas) { const { tempSchema, tempTable } = query; diff --git a/superset-frontend/src/SqlLab/reducers/sqlLab.js b/superset-frontend/src/SqlLab/reducers/sqlLab.js index 6257ce8c9e..d47a45aa21 100644 --- a/superset-frontend/src/SqlLab/reducers/sqlLab.js +++ b/superset-frontend/src/SqlLab/reducers/sqlLab.js @@ -343,6 +343,7 @@ export default function sqlLabReducer(state = {}, action) { } const alts = { state: 'failed', + errors: action.errors, errorMessage: action.msg, endDttm: now(), link: action.link, diff --git a/superset-frontend/src/SqlLab/types.ts b/superset-frontend/src/SqlLab/types.ts index 3b1c4e125e..0fe83a7f5e 100644 --- a/superset-frontend/src/SqlLab/types.ts +++ b/superset-frontend/src/SqlLab/types.ts @@ -16,7 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import { CtasEnum } from './actions/sqlLab'; +import { SupersetError } from 'src/components/ErrorMessage/types'; +import { CtasEnum } from 'src/SqlLab/actions/sqlLab'; export type Column = { name: string; @@ -27,6 +28,7 @@ export type Query = { ctas: boolean; ctas_method?: keyof typeof CtasEnum; dbId: number; + errors?: SupersetError[]; errorMessage: string | null; extra: { progress: string | null; diff --git a/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.tsx b/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.tsx index fff4e060c0..5f3f6794e7 100644 --- a/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.tsx +++ b/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.tsx @@ -19,13 +19,15 @@ import React, { useState } from 'react'; // @ts-ignore import { Alert, Collapse } from 'react-bootstrap'; +import { t } from '@superset-ui/translation'; + import getErrorMessageComponentRegistry from './getErrorMessageComponentRegistry'; import { SupersetError } from './types'; type Props = { error?: SupersetError; link?: string; - message: string; + message?: string; stackTrace?: string; }; @@ -54,7 +56,7 @@ export default function ErrorMessageWithStackTrace({ bsStyle="warning" onClick={() => setShowStackTrace(!showStackTrace)} > - {message} + {message || t('An error occurred.')} {link && ( (Request Access)