This is an automated email from the ASF dual-hosted git repository.
kgabryje pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new a498d6d10f refactor: Move fetchTimeRange to core package (#27852)
a498d6d10f is described below
commit a498d6d10f2819ca40f0ab846b337f55906e0424
Author: Kamil Gabryjelski <[email protected]>
AuthorDate: Wed Apr 3 18:34:23 2024 +0200
refactor: Move fetchTimeRange to core package (#27852)
---
.../superset-ui-core/src/connection/constants.ts | 5 +
.../superset-ui-core/src/connection/index.ts | 1 +
.../src/query}/getClientErrorObject.ts | 54 ++---
.../packages/superset-ui-core/src/query/index.ts | 1 +
.../superset-ui-core/src/query/types/Query.ts | 21 +-
.../src/time-comparison/fetchTimeRange.ts} | 34 +--
.../superset-ui-core/src/time-comparison/index.ts | 1 +
.../chart/components/ChartDataProvider.test.tsx | 13 +-
.../test/color/SharedLabelColorSingleton.test.ts | 14 +-
.../test/query/getClientErrorObject.test.ts | 233 +++++++++++++++++++++
.../test/time-comparison/fetchTimeRange.test.ts | 118 +++++++++++
superset-frontend/src/SqlLab/actions/sqlLab.js | 4 +-
.../AceEditorWrapper/useAnnotations.test.ts | 2 +-
.../components/AceEditorWrapper/useAnnotations.ts | 4 +-
.../SqlLab/components/ShareSqlLabQuery/index.tsx | 2 +-
.../src/components/Chart/ChartErrorMessage.tsx | 2 +-
.../src/components/Chart/chartAction.js | 2 +-
.../Datasource/ChangeDatasourceModal.tsx | 8 +-
.../src/components/Datasource/DatasourceEditor.jsx | 2 +-
.../src/components/Datasource/DatasourceModal.tsx | 4 +-
.../ErrorMessage/BasicErrorAlert.test.tsx | 3 +-
.../components/ErrorMessage/BasicErrorAlert.tsx | 3 +-
.../ErrorMessage/DatabaseErrorMessage.test.tsx | 2 +-
.../DatasetNotFoundErrorMessage.test.tsx | 2 +-
.../components/ErrorMessage/ErrorAlert.test.tsx | 3 +-
.../src/components/ErrorMessage/ErrorAlert.tsx | 9 +-
.../ErrorMessageWithStackTrace.test.tsx | 2 +-
.../ErrorMessage/ErrorMessageWithStackTrace.tsx | 3 +-
.../ErrorMessage/MarshmallowErrorMessage.test.tsx | 8 +-
.../ErrorMessage/OAuth2RedirectMessage.test.tsx | 7 +-
.../ErrorMessage/ParameterErrorMessage.test.tsx | 2 +-
.../ErrorMessage/TimeoutErrorMessage.test.tsx | 2 +-
.../src/components/ErrorMessage/types.ts | 89 +-------
.../src/components/Select/AsyncSelect.tsx | 8 +-
.../src/components/TableSelector/index.tsx | 11 +-
superset-frontend/src/components/Tags/utils.tsx | 11 +-
.../src/dashboard/actions/dashboardInfo.ts | 8 +-
.../src/dashboard/actions/dashboardState.js | 2 +-
.../src/dashboard/actions/sliceEntities.ts | 8 +-
.../dashboard/components/PropertiesModal/index.tsx | 2 +-
.../components/URLShortLinkButton/index.tsx | 3 +-
.../FilterBar/FilterControls/FilterValue.tsx | 6 +-
.../FiltersConfigForm/ColumnSelect.test.tsx | 4 +-
.../FiltersConfigForm/ColumnSelect.tsx | 9 +-
.../FiltersConfigForm/DatasetSelect.tsx | 7 +-
.../FiltersConfigForm/FiltersConfigForm.tsx | 6 +-
.../src/explore/actions/datasourcesActions.test.ts | 4 +-
.../src/explore/actions/datasourcesActions.ts | 3 +-
.../DataTablesPane/components/useResultsPane.tsx | 2 +-
.../explore/components/PropertiesModal/index.tsx | 2 +-
.../controls/DateFilterControl/DateFilterLabel.tsx | 2 +-
.../DateFilterControl/components/AdvancedFrame.tsx | 3 +-
.../controls/DateFilterControl/tests/utils.test.ts | 33 ---
.../DateFilterControl/utils/dateFilterUtils.ts | 47 +----
.../controls/DateFilterControl/utils/dateParser.ts | 2 +-
.../utils/useGetTimeRangeLabel.test.ts | 6 +-
.../FilterControl/utils/useGetTimeRangeLabel.tsx | 3 +-
.../controls/SelectAsyncControl/index.tsx | 3 +-
.../explore/components/controls/ViewQueryModal.tsx | 8 +-
.../src/features/reports/ReportModal/index.tsx | 3 +-
.../src/hooks/apiResources/queryApi.ts | 4 +-
.../src/middleware/asyncEvent.test.ts | 5 +-
superset-frontend/src/middleware/asyncEvent.ts | 8 +-
.../src/pages/AnnotationList/index.tsx | 9 +-
superset-frontend/src/pages/Chart/index.tsx | 2 +-
superset-frontend/src/setup/setupApp.ts | 4 +-
superset-frontend/src/setup/setupErrorMessages.ts | 2 +-
superset-frontend/src/utils/errorMessages.ts | 26 ---
.../src/utils/getClientErrorObject.test.ts | 83 --------
superset-frontend/src/views/CRUD/hooks.ts | 9 +-
superset-frontend/src/views/CRUD/utils.tsx | 2 +-
superset/errors.py | 4 +-
72 files changed, 561 insertions(+), 463 deletions(-)
diff --git
a/superset-frontend/packages/superset-ui-core/src/connection/constants.ts
b/superset-frontend/packages/superset-ui-core/src/connection/constants.ts
index 370c1a50ed..98a8c38574 100644
--- a/superset-frontend/packages/superset-ui-core/src/connection/constants.ts
+++ b/superset-frontend/packages/superset-ui-core/src/connection/constants.ts
@@ -34,3 +34,8 @@ export const DEFAULT_FETCH_RETRY_OPTIONS: FetchRetryOptions =
{
retryDelay: 1000,
retryOn: [503],
};
+
+export const COMMON_ERR_MESSAGES = {
+ SESSION_TIMED_OUT:
+ 'Your session timed out, please refresh your page and try again.',
+};
diff --git
a/superset-frontend/packages/superset-ui-core/src/connection/index.ts
b/superset-frontend/packages/superset-ui-core/src/connection/index.ts
index 594bbcedef..3ac9806a05 100644
--- a/superset-frontend/packages/superset-ui-core/src/connection/index.ts
+++ b/superset-frontend/packages/superset-ui-core/src/connection/index.ts
@@ -22,4 +22,5 @@ export { default as SupersetClient } from './SupersetClient';
export { default as SupersetClientClass } from './SupersetClientClass';
export * from './types';
+export * from './constants';
export { default as __hack_reexport_connection } from './types';
diff --git a/superset-frontend/src/utils/getClientErrorObject.ts
b/superset-frontend/packages/superset-ui-core/src/query/getClientErrorObject.ts
similarity index 97%
rename from superset-frontend/src/utils/getClientErrorObject.ts
rename to
superset-frontend/packages/superset-ui-core/src/query/getClientErrorObject.ts
index a5f2871872..8b4b62cf76 100644
--- a/superset-frontend/src/utils/getClientErrorObject.ts
+++
b/superset-frontend/packages/superset-ui-core/src/query/getClientErrorObject.ts
@@ -16,12 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { JsonObject, SupersetClientResponse, t } from '@superset-ui/core';
import {
+ COMMON_ERR_MESSAGES,
+ JsonObject,
+ SupersetClientResponse,
+ t,
SupersetError,
ErrorTypeEnum,
-} from 'src/components/ErrorMessage/types';
-import COMMON_ERR_MESSAGES from './errorMessages';
+} from '@superset-ui/core';
// The response always contains an error attribute, can contain anything from
the
// SupersetClientResponse object, and can contain a spread JSON blob
@@ -86,29 +88,6 @@ export function parseErrorJson(responseObject: JsonObject):
ClientErrorObject {
return { ...error, error: error.error }; // explicit ClientErrorObject
}
-/*
- * Utility to get standardized error text for generic update failures
- */
-export async function getErrorText(
- errorObject: ErrorType,
- source: ErrorTextSource,
-) {
- const { error, message } = await getClientErrorObject(errorObject);
- let errorText = t('Sorry, an unknown error occurred.');
-
- if (error) {
- errorText = t(
- 'Sorry, there was an error saving this %s: %s',
- source,
- error,
- );
- }
- if (typeof message === 'string' && message === 'Forbidden') {
- errorText = t('You do not have permission to edit this %s', source);
- }
- return errorText;
-}
-
export function getClientErrorObject(
response:
| SupersetClientResponse
@@ -203,6 +182,29 @@ export function getClientErrorObject(
});
}
+/*
+ * Utility to get standardized error text for generic update failures
+ */
+export async function getErrorText(
+ errorObject: ErrorType,
+ source: ErrorTextSource,
+) {
+ const { error, message } = await getClientErrorObject(errorObject);
+ let errorText = t('Sorry, an unknown error occurred.');
+
+ if (error) {
+ errorText = t(
+ 'Sorry, there was an error saving this %s: %s',
+ source,
+ error,
+ );
+ }
+ if (typeof message === 'string' && message === 'Forbidden') {
+ errorText = t('You do not have permission to edit this %s', source);
+ }
+ return errorText;
+}
+
export function getClientErrorMessage(
message: string,
clientError?: ClientErrorObject,
diff --git a/superset-frontend/packages/superset-ui-core/src/query/index.ts
b/superset-frontend/packages/superset-ui-core/src/query/index.ts
index bb83e3d340..434fe95798 100644
--- a/superset-frontend/packages/superset-ui-core/src/query/index.ts
+++ b/superset-frontend/packages/superset-ui-core/src/query/index.ts
@@ -31,6 +31,7 @@ export { default as normalizeOrderBy } from
'./normalizeOrderBy';
export { normalizeTimeColumn } from './normalizeTimeColumn';
export { default as extractQueryFields } from './extractQueryFields';
export * from './getXAxis';
+export * from './getClientErrorObject';
export * from './types/AnnotationLayer';
export * from './types/QueryFormData';
diff --git
a/superset-frontend/packages/superset-ui-core/src/query/types/Query.ts
b/superset-frontend/packages/superset-ui-core/src/query/types/Query.ts
index 718f10514c..4d5ccaf6f0 100644
--- a/superset-frontend/packages/superset-ui-core/src/query/types/Query.ts
+++ b/superset-frontend/packages/superset-ui-core/src/query/types/Query.ts
@@ -166,6 +166,7 @@ export interface QueryContext {
form_data?: QueryFormData;
}
+// Keep in sync with superset/errors.py
export const ErrorTypeEnum = {
// Frontend errors
FRONTEND_CSRF_ERROR: 'FRONTEND_CSRF_ERROR',
@@ -187,9 +188,10 @@ export const ErrorTypeEnum = {
CONNECTION_UNKNOWN_DATABASE_ERROR: 'CONNECTION_UNKNOWN_DATABASE_ERROR',
CONNECTION_DATABASE_PERMISSIONS_ERROR:
'CONNECTION_DATABASE_PERMISSIONS_ERROR',
- CONNECTION_MISSING_PARAMETERS_ERRORS: 'CONNECTION_MISSING_PARAMETERS_ERRORS',
+ CONNECTION_MISSING_PARAMETERS_ERROR: 'CONNECTION_MISSING_PARAMETERS_ERROR',
OBJECT_DOES_NOT_EXIST_ERROR: 'OBJECT_DOES_NOT_EXIST_ERROR',
SYNTAX_ERROR: 'SYNTAX_ERROR',
+ CONNECTION_DATABASE_TIMEOUT: 'CONNECTION_DATABASE_TIMEOUT',
// Viz errors
VIZ_GET_DF_ERROR: 'VIZ_GET_DF_ERROR',
@@ -203,12 +205,17 @@ export const ErrorTypeEnum = {
DATABASE_SECURITY_ACCESS_ERROR: 'DATABASE_SECURITY_ACCESS_ERROR',
QUERY_SECURITY_ACCESS_ERROR: 'QUERY_SECURITY_ACCESS_ERROR',
MISSING_OWNERSHIP_ERROR: 'MISSING_OWNERSHIP_ERROR',
+ USER_ACTIVITY_SECURITY_ACCESS_ERROR: 'USER_ACTIVITY_SECURITY_ACCESS_ERROR',
+ DASHBOARD_SECURITY_ACCESS_ERROR: 'DASHBOARD_SECURITY_ACCESS_ERROR',
+ CHART_SECURITY_ACCESS_ERROR: 'CHART_SECURITY_ACCESS_ERROR',
+ OAUTH2_REDIRECT: 'OAUTH2_REDIRECT',
+ OAUTH2_REDIRECT_ERROR: 'OAUTH2_REDIRECT_ERROR',
// Other errors
BACKEND_TIMEOUT_ERROR: 'BACKEND_TIMEOUT_ERROR',
DATABASE_NOT_FOUND_ERROR: 'DATABASE_NOT_FOUND_ERROR',
- // Sqllab error
+ // Sql Lab errors
MISSING_TEMPLATE_PARAMS_ERROR: 'MISSING_TEMPLATE_PARAMS_ERROR',
INVALID_TEMPLATE_PARAMS_ERROR: 'INVALID_TEMPLATE_PARAMS_ERROR',
RESULTS_BACKEND_NOT_CONFIGURED_ERROR: 'RESULTS_BACKEND_NOT_CONFIGURED_ERROR',
@@ -218,6 +225,8 @@ export const ErrorTypeEnum = {
SQLLAB_TIMEOUT_ERROR: 'SQLLAB_TIMEOUT_ERROR',
RESULTS_BACKEND_ERROR: 'RESULTS_BACKEND_ERROR',
ASYNC_WORKERS_ERROR: 'ASYNC_WORKERS_ERROR',
+ ADHOC_SUBQUERY_NOT_ALLOWED_ERROR: 'ADHOC_SUBQUERY_NOT_ALLOWED_ERROR',
+ INVALID_SQL_ERROR: 'INVALID_SQL_ERROR',
// Generic errors
GENERIC_COMMAND_ERROR: 'GENERIC_COMMAND_ERROR',
@@ -226,16 +235,20 @@ export const ErrorTypeEnum = {
// API errors
INVALID_PAYLOAD_FORMAT_ERROR: 'INVALID_PAYLOAD_FORMAT_ERROR',
INVALID_PAYLOAD_SCHEMA_ERROR: 'INVALID_PAYLOAD_SCHEMA_ERROR',
+ MARSHMALLOW_ERROR: 'MARSHMALLOW_ERROR',
+
+ // Report errors
+ REPORT_NOTIFICATION_ERROR: 'REPORT_NOTIFICATION_ERROR',
} as const;
type ValueOf<T> = T[keyof T];
export type ErrorType = ValueOf<typeof ErrorTypeEnum>;
-// Keep in sync with superset/views/errors.py
+// Keep in sync with superset/errors.py
export type ErrorLevel = 'info' | 'warning' | 'error';
-export type ErrorSource = 'dashboard' | 'explore' | 'sqllab';
+export type ErrorSource = 'dashboard' | 'explore' | 'sqllab' | 'crud';
export type SupersetError<ExtraType = Record<string, any> | null> = {
error_type: ErrorType;
diff --git
a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts
b/superset-frontend/packages/superset-ui-core/src/time-comparison/fetchTimeRange.ts
similarity index 70%
copy from
superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts
copy to
superset-frontend/packages/superset-ui-core/src/time-comparison/fetchTimeRange.ts
index aad2f9984d..50509af52b 100644
---
a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts
+++
b/superset-frontend/packages/superset-ui-core/src/time-comparison/fetchTimeRange.ts
@@ -17,15 +17,7 @@
* under the License.
*/
import rison from 'rison';
-import { SupersetClient, NO_TIME_RANGE, JsonObject } from '@superset-ui/core';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
-import { useSelector } from 'react-redux';
-import {
- COMMON_RANGE_VALUES_SET,
- CALENDAR_RANGE_VALUES_SET,
- customTimeRangeDecode,
-} from '.';
-import { FrameType } from '../types';
+import { SupersetClient, getClientErrorObject } from '@superset-ui/core';
export const SEPARATOR = ' : ';
@@ -47,22 +39,6 @@ export const formatTimeRange = (
)} ≤ ${columnPlaceholder} < ${formatDateEndpoint(splitDateRange[1])}`;
};
-export const guessFrame = (timeRange: string): FrameType => {
- if (COMMON_RANGE_VALUES_SET.has(timeRange)) {
- return 'Common';
- }
- if (CALENDAR_RANGE_VALUES_SET.has(timeRange)) {
- return 'Calendar';
- }
- if (timeRange === NO_TIME_RANGE) {
- return 'No filter';
- }
- if (customTimeRangeDecode(timeRange).matchedFlag) {
- return 'Custom';
- }
- return 'Advanced';
-};
-
export const fetchTimeRange = async (
timeRange: string,
columnPlaceholder = 'col',
@@ -85,11 +61,3 @@ export const fetchTimeRange = async (
};
}
};
-
-export function useDefaultTimeFilter() {
- return (
- useSelector(
- (state: JsonObject) => state?.common?.conf?.DEFAULT_TIME_FILTER,
- ) ?? NO_TIME_RANGE
- );
-}
diff --git
a/superset-frontend/packages/superset-ui-core/src/time-comparison/index.ts
b/superset-frontend/packages/superset-ui-core/src/time-comparison/index.ts
index 4b9fb361fd..ad5b5f5918 100644
--- a/superset-frontend/packages/superset-ui-core/src/time-comparison/index.ts
+++ b/superset-frontend/packages/superset-ui-core/src/time-comparison/index.ts
@@ -21,3 +21,4 @@ export * from './types';
export { default as getComparisonInfo } from './getComparisonInfo';
export { default as getComparisonFilters } from './getComparisonFilters';
+export { SEPARATOR, fetchTimeRange } from './fetchTimeRange';
diff --git
a/superset-frontend/packages/superset-ui-core/test/chart/components/ChartDataProvider.test.tsx
b/superset-frontend/packages/superset-ui-core/test/chart/components/ChartDataProvider.test.tsx
index 2947fd9f94..8423ee99ad 100644
---
a/superset-frontend/packages/superset-ui-core/test/chart/components/ChartDataProvider.test.tsx
+++
b/superset-frontend/packages/superset-ui-core/test/chart/components/ChartDataProvider.test.tsx
@@ -49,14 +49,13 @@ const mockLoadQueryData = jest.fn<Promise<unknown>,
unknown[]>(
createArrayPromise,
);
+const actual = jest.requireActual('../../../src/chart/clients/ChartClient');
// ChartClient is now a mock
-jest.mock('../../../src/chart/clients/ChartClient', () =>
- jest.fn().mockImplementation(() => ({
- loadDatasource: mockLoadDatasource,
- loadFormData: mockLoadFormData,
- loadQueryData: mockLoadQueryData,
- })),
-);
+jest.spyOn(actual, 'default').mockImplementation(() => ({
+ loadDatasource: mockLoadDatasource,
+ loadFormData: mockLoadFormData,
+ loadQueryData: mockLoadQueryData,
+}));
const ChartClientMock = ChartClient as jest.Mock<ChartClient>;
diff --git
a/superset-frontend/packages/superset-ui-core/test/color/SharedLabelColorSingleton.test.ts
b/superset-frontend/packages/superset-ui-core/test/color/SharedLabelColorSingleton.test.ts
index 8f89ae8a69..ca3f89a523 100644
---
a/superset-frontend/packages/superset-ui-core/test/color/SharedLabelColorSingleton.test.ts
+++
b/superset-frontend/packages/superset-ui-core/test/color/SharedLabelColorSingleton.test.ts
@@ -25,13 +25,11 @@ import {
SharedLabelColor,
SharedLabelColorSource,
} from '@superset-ui/core';
-import { getAnalogousColors } from '../../src/color/utils';
-jest.mock('../../src/color/utils', () => ({
- getAnalogousColors: jest
- .fn()
- .mockImplementation(() => ['red', 'green', 'blue']),
-}));
+const actual = jest.requireActual('../../src/color/utils');
+const getAnalogousColorsSpy = jest
+ .spyOn(actual, 'getAnalogousColors')
+ .mockImplementation(() => ['red', 'green', 'blue']);
describe('SharedLabelColor', () => {
beforeAll(() => {
@@ -161,7 +159,7 @@ describe('SharedLabelColor', () => {
sharedLabelColor.updateColorMap('', 'testColors');
const colorMap = sharedLabelColor.getColorMap();
expect(Object.fromEntries(colorMap)).not.toEqual({});
- expect(getAnalogousColors).not.toBeCalled();
+ expect(getAnalogousColorsSpy).not.toBeCalled();
});
it('should use analagous colors', () => {
@@ -176,7 +174,7 @@ describe('SharedLabelColor', () => {
sharedLabelColor.updateColorMap('', 'testColors');
const colorMap = sharedLabelColor.getColorMap();
expect(Object.fromEntries(colorMap)).not.toEqual({});
- expect(getAnalogousColors).toBeCalled();
+ expect(getAnalogousColorsSpy).toBeCalled();
});
});
diff --git
a/superset-frontend/packages/superset-ui-core/test/query/getClientErrorObject.test.ts
b/superset-frontend/packages/superset-ui-core/test/query/getClientErrorObject.test.ts
new file mode 100644
index 0000000000..c37e6fbe93
--- /dev/null
+++
b/superset-frontend/packages/superset-ui-core/test/query/getClientErrorObject.test.ts
@@ -0,0 +1,233 @@
+/**
+ * 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.
+ */
+import {
+ COMMON_ERR_MESSAGES,
+ getClientErrorMessage,
+ getClientErrorObject,
+ getErrorText,
+ parseErrorJson,
+ ErrorTypeEnum,
+} from '@superset-ui/core';
+
+it('Returns a Promise', () => {
+ const response = getClientErrorObject('error');
+ expect(response instanceof Promise).toBe(true);
+});
+
+it('Returns a Promise that resolves to an object with an error key', async ()
=> {
+ const error = 'error';
+
+ const errorObj = await getClientErrorObject(error);
+ expect(errorObj).toMatchObject({ error });
+});
+
+it('Handles Response that can be parsed as json', async () => {
+ const jsonError = { something: 'something', error: 'Error message' };
+ const jsonErrorString = JSON.stringify(jsonError);
+
+ const errorObj = await getClientErrorObject(new Response(jsonErrorString));
+ expect(errorObj).toMatchObject(jsonError);
+});
+
+it('Handles backwards compatibility between old error messages and the new
SIP-40 errors format', async () => {
+ const jsonError = {
+ errors: [
+ {
+ error_type: ErrorTypeEnum.GENERIC_DB_ENGINE_ERROR,
+ extra: { engine: 'presto', link: 'https://www.google.com' },
+ level: 'error',
+ message: 'presto error: test error',
+ },
+ ],
+ };
+ const jsonErrorString = JSON.stringify(jsonError);
+
+ const errorObj = await getClientErrorObject(new Response(jsonErrorString));
+ expect(errorObj.error).toEqual(jsonError.errors[0].message);
+ expect(errorObj.link).toEqual(jsonError.errors[0].extra.link);
+});
+
+it('Handles Response that can be parsed as text', async () => {
+ const textError = 'Hello I am a text error';
+
+ const errorObj = await getClientErrorObject(new Response(textError));
+ expect(errorObj).toMatchObject({ error: textError });
+});
+
+it('Handles TypeError Response', async () => {
+ const error = new TypeError('Failed to fetch');
+
+ // @ts-ignore
+ const errorObj = await getClientErrorObject(error);
+ expect(errorObj).toMatchObject({ error: 'Network error' });
+});
+
+it('Handles timeout error', async () => {
+ const errorObj = await getClientErrorObject({
+ timeout: 1000,
+ statusText: 'timeout',
+ });
+ expect(errorObj).toMatchObject({
+ timeout: 1000,
+ statusText: 'timeout',
+ error: 'Request timed out',
+ errors: [
+ {
+ error_type: ErrorTypeEnum.FRONTEND_TIMEOUT_ERROR,
+ extra: {
+ timeout: 1,
+ issue_codes: [
+ {
+ code: 1000,
+ message: 'Issue 1000 - The dataset is too large to query.',
+ },
+ {
+ code: 1001,
+ message: 'Issue 1001 - The database is under an unusual load.',
+ },
+ ],
+ },
+ level: 'error',
+ message: 'Request timed out',
+ },
+ ],
+ });
+});
+
+it('Handles plain text as input', async () => {
+ const error = 'error';
+
+ const errorObj = await getClientErrorObject(error);
+ expect(errorObj).toMatchObject({ error });
+});
+
+it('Handles error with status text and message', async () => {
+ const statusText = 'status';
+ const message = 'message';
+
+ // @ts-ignore
+ expect(await getClientErrorObject({ statusText, message })).toMatchObject({
+ error: statusText,
+ });
+ // @ts-ignore
+ expect(await getClientErrorObject({ message })).toMatchObject({
+ error: message,
+ });
+ // @ts-ignore
+ expect(await getClientErrorObject({})).toMatchObject({
+ error: 'An error occurred',
+ });
+});
+
+it('getClientErrorMessage', () => {
+ expect(getClientErrorMessage('error')).toEqual('error');
+ expect(
+ getClientErrorMessage('error', {
+ error: 'client error',
+ message: 'client error message',
+ }),
+ ).toEqual('error:\nclient error message');
+ expect(
+ getClientErrorMessage('error', {
+ error: 'client error',
+ }),
+ ).toEqual('error:\nclient error');
+});
+
+it('parseErrorJson with message', () => {
+ expect(parseErrorJson({ message: 'error message' })).toEqual({
+ message: 'error message',
+ error: 'error message',
+ });
+
+ expect(
+ parseErrorJson({
+ message: {
+ key1: ['error message1', 'error message2'],
+ key2: ['error message3', 'error message4'],
+ },
+ }),
+ ).toEqual({
+ message: {
+ key1: ['error message1', 'error message2'],
+ key2: ['error message3', 'error message4'],
+ },
+ error: 'error message1',
+ });
+
+ expect(
+ parseErrorJson({
+ message: {},
+ }),
+ ).toEqual({
+ message: {},
+ error: 'Invalid input',
+ });
+});
+
+it('parseErrorJson with stacktrace', () => {
+ expect(
+ parseErrorJson({ error: 'error message', stack: 'stacktrace' }),
+ ).toEqual({
+ error: 'Unexpected error: (no description, click to see stack trace)',
+ stacktrace: 'stacktrace',
+ stack: 'stacktrace',
+ });
+
+ expect(
+ parseErrorJson({
+ error: 'error message',
+ description: 'error description',
+ stack: 'stacktrace',
+ }),
+ ).toEqual({
+ error: 'Unexpected error: error description',
+ stacktrace: 'stacktrace',
+ description: 'error description',
+ stack: 'stacktrace',
+ });
+});
+
+it('parseErrorJson with CSRF', () => {
+ expect(
+ parseErrorJson({
+ responseText: 'CSRF',
+ }),
+ ).toEqual({
+ error: COMMON_ERR_MESSAGES.SESSION_TIMED_OUT,
+ responseText: 'CSRF',
+ });
+});
+
+it('getErrorText', async () => {
+ expect(await getErrorText('error', 'dashboard')).toEqual(
+ 'Sorry, there was an error saving this dashboard: error',
+ );
+
+ const error = JSON.stringify({ message: 'Forbidden' });
+ expect(await getErrorText(new Response(error), 'dashboard')).toEqual(
+ 'You do not have permission to edit this dashboard',
+ );
+ expect(
+ await getErrorText(
+ new Response(JSON.stringify({ status: 'error' })),
+ 'dashboard',
+ ),
+ ).toEqual('Sorry, an unknown error occurred.');
+});
diff --git
a/superset-frontend/packages/superset-ui-core/test/time-comparison/fetchTimeRange.test.ts
b/superset-frontend/packages/superset-ui-core/test/time-comparison/fetchTimeRange.test.ts
new file mode 100644
index 0000000000..e07fa8617f
--- /dev/null
+++
b/superset-frontend/packages/superset-ui-core/test/time-comparison/fetchTimeRange.test.ts
@@ -0,0 +1,118 @@
+/**
+ * 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.
+ */
+
+import fetchMock from 'fetch-mock';
+import { fetchTimeRange } from '@superset-ui/core';
+import {
+ buildTimeRangeString,
+ formatTimeRange,
+} from '../../src/time-comparison/fetchTimeRange';
+
+afterEach(fetchMock.restore);
+
+it('generates proper time range string', () => {
+ expect(
+ buildTimeRangeString('2010-07-30T00:00:00', '2020-07-30T00:00:00'),
+ ).toBe('2010-07-30T00:00:00 : 2020-07-30T00:00:00');
+ expect(buildTimeRangeString('', '2020-07-30T00:00:00')).toBe(
+ ' : 2020-07-30T00:00:00',
+ );
+ expect(buildTimeRangeString('', '')).toBe(' : ');
+});
+
+it('generates a readable time range', () => {
+ expect(formatTimeRange('Last 7 days')).toBe('Last 7 days');
+ expect(formatTimeRange('No filter')).toBe('No filter');
+ expect(formatTimeRange('Yesterday : Tomorrow')).toBe(
+ 'Yesterday ≤ col < Tomorrow',
+ );
+ expect(formatTimeRange('2010-07-30T00:00:00 : 2020-07-30T00:00:00')).toBe(
+ '2010-07-30 ≤ col < 2020-07-30',
+ );
+ expect(formatTimeRange('2010-07-30T01:00:00 : ')).toBe(
+ '2010-07-30T01:00:00 ≤ col < ∞',
+ );
+ expect(formatTimeRange(' : 2020-07-30T00:00:00')).toBe(
+ '-∞ ≤ col < 2020-07-30',
+ );
+});
+
+it('returns a formatted time range from response', async () => {
+ fetchMock.get("glob:*/api/v1/time_range/?q='Last+day'", {
+ result: [
+ {
+ since: '2021-04-13T00:00:00',
+ until: '2021-04-14T00:00:00',
+ timeRange: 'Last day',
+ },
+ ],
+ });
+
+ const timeRange = await fetchTimeRange('Last day', 'temporal_col');
+ expect(timeRange).toEqual({
+ value: '2021-04-13 ≤ temporal_col < 2021-04-14',
+ });
+});
+
+it('returns a formatted time range from empty response', async () => {
+ fetchMock.get("glob:*/api/v1/time_range/?q='Last+day'", {
+ result: [],
+ });
+
+ const timeRange = await fetchTimeRange('Last day');
+ expect(timeRange).toEqual({
+ value: '-∞ ≤ col < ∞',
+ });
+});
+
+it('returns a formatted error message from response', async () => {
+ fetchMock.getOnce("glob:*/api/v1/time_range/?q='Last+day'", {
+ throws: new Response(JSON.stringify({ message: 'Network error' })),
+ });
+ let timeRange = await fetchTimeRange('Last day');
+ expect(timeRange).toEqual({
+ error: 'Network error',
+ });
+
+ fetchMock.getOnce(
+ "glob:*/api/v1/time_range/?q='Last+day'",
+ {
+ throws: new Error('Internal Server Error'),
+ },
+ { overwriteRoutes: true },
+ );
+ timeRange = await fetchTimeRange('Last day');
+ expect(timeRange).toEqual({
+ error: 'Internal Server Error',
+ });
+
+ fetchMock.getOnce(
+ "glob:*/api/v1/time_range/?q='Last+day'",
+ {
+ throws: new Response(JSON.stringify({ statusText: 'Network error' }), {
+ statusText: 'Network error',
+ }),
+ },
+ { overwriteRoutes: true },
+ );
+ timeRange = await fetchTimeRange('Last day');
+ expect(timeRange).toEqual({
+ error: 'Network error',
+ });
+});
diff --git a/superset-frontend/src/SqlLab/actions/sqlLab.js
b/superset-frontend/src/SqlLab/actions/sqlLab.js
index fa5198e532..6befa17ac1 100644
--- a/superset-frontend/src/SqlLab/actions/sqlLab.js
+++ b/superset-frontend/src/SqlLab/actions/sqlLab.js
@@ -23,6 +23,8 @@ import {
SupersetClient,
t,
isFeatureEnabled,
+ COMMON_ERR_MESSAGES,
+ getClientErrorObject,
} from '@superset-ui/core';
import { invert, mapKeys } from 'lodash';
@@ -33,8 +35,6 @@ import {
addSuccessToast as addSuccessToastAction,
addWarningToast as addWarningToastAction,
} from 'src/components/MessageToasts/actions';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
-import COMMON_ERR_MESSAGES from 'src/utils/errorMessages';
import { LOG_ACTIONS_SQLLAB_FETCH_FAILED_QUERY } from 'src/logger/LogUtils';
import getBootstrapData from 'src/utils/getBootstrapData';
import { logEvent } from 'src/logger/actions';
diff --git
a/superset-frontend/src/SqlLab/components/AceEditorWrapper/useAnnotations.test.ts
b/superset-frontend/src/SqlLab/components/AceEditorWrapper/useAnnotations.test.ts
index ddabbea55b..0f17fdafcb 100644
---
a/superset-frontend/src/SqlLab/components/AceEditorWrapper/useAnnotations.test.ts
+++
b/superset-frontend/src/SqlLab/components/AceEditorWrapper/useAnnotations.test.ts
@@ -18,13 +18,13 @@
*/
import fetchMock from 'fetch-mock';
import { act, renderHook } from '@testing-library/react-hooks';
+import { COMMON_ERR_MESSAGES } from '@superset-ui/core';
import {
createWrapper,
defaultStore as store,
} from 'spec/helpers/testing-library';
import { api } from 'src/hooks/apiResources/queryApi';
import { initialState } from 'src/SqlLab/fixtures';
-import COMMON_ERR_MESSAGES from 'src/utils/errorMessages';
import { useAnnotations } from './useAnnotations';
const fakeApiResult = {
diff --git
a/superset-frontend/src/SqlLab/components/AceEditorWrapper/useAnnotations.ts
b/superset-frontend/src/SqlLab/components/AceEditorWrapper/useAnnotations.ts
index f6924a243f..f640e30779 100644
--- a/superset-frontend/src/SqlLab/components/AceEditorWrapper/useAnnotations.ts
+++ b/superset-frontend/src/SqlLab/components/AceEditorWrapper/useAnnotations.ts
@@ -18,16 +18,14 @@
*/
import { useSelector } from 'react-redux';
+import { COMMON_ERR_MESSAGES, ClientErrorObject, t } from '@superset-ui/core';
import { SqlLabRootState } from 'src/SqlLab/types';
-import COMMON_ERR_MESSAGES from 'src/utils/errorMessages';
import { VALIDATION_DEBOUNCE_MS } from 'src/SqlLab/constants';
import {
FetchValidationQueryParams,
useQueryValidationsQuery,
} from 'src/hooks/apiResources';
import { useDebounceValue } from 'src/hooks/useDebounceValue';
-import { ClientErrorObject } from 'src/utils/getClientErrorObject';
-import { t } from '@superset-ui/core';
export function useAnnotations(params: FetchValidationQueryParams) {
const { sql, dbId, schema, templateParams } = params;
diff --git a/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/index.tsx
b/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/index.tsx
index 8f4cde1a66..9309ce7c05 100644
--- a/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/index.tsx
+++ b/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/index.tsx
@@ -23,13 +23,13 @@ import {
t,
useTheme,
isFeatureEnabled,
+ getClientErrorObject,
} from '@superset-ui/core';
import Button from 'src/components/Button';
import Icons from 'src/components/Icons';
import withToasts from 'src/components/MessageToasts/withToasts';
import CopyToClipboard from 'src/components/CopyToClipboard';
import { storeQuery } from 'src/utils/common';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import useQueryEditor from 'src/SqlLab/hooks/useQueryEditor';
interface ShareSqlLabQueryProps {
diff --git a/superset-frontend/src/components/Chart/ChartErrorMessage.tsx
b/superset-frontend/src/components/Chart/ChartErrorMessage.tsx
index 077ca2282a..b15a20ea67 100644
--- a/superset-frontend/src/components/Chart/ChartErrorMessage.tsx
+++ b/superset-frontend/src/components/Chart/ChartErrorMessage.tsx
@@ -18,9 +18,9 @@
*/
import React from 'react';
+import { SupersetError } from '@superset-ui/core';
import { useChartOwnerNames } from 'src/hooks/apiResources';
import ErrorMessageWithStackTrace from
'src/components/ErrorMessage/ErrorMessageWithStackTrace';
-import { SupersetError } from 'src/components/ErrorMessage/types';
interface Props {
chartId: string;
diff --git a/superset-frontend/src/components/Chart/chartAction.js
b/superset-frontend/src/components/Chart/chartAction.js
index 9597a3cbb3..d4657988ca 100644
--- a/superset-frontend/src/components/Chart/chartAction.js
+++ b/superset-frontend/src/components/Chart/chartAction.js
@@ -25,6 +25,7 @@ import {
SupersetClient,
t,
isFeatureEnabled,
+ getClientErrorObject,
} from '@superset-ui/core';
import { getControlsState } from 'src/explore/store';
import {
@@ -38,7 +39,6 @@ import {
import { addDangerToast } from 'src/components/MessageToasts/actions';
import { logEvent } from 'src/logger/actions';
import { Logger, LOG_ACTIONS_LOAD_CHART } from 'src/logger/LogUtils';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import { allowCrossDomain as domainShardingEnabled } from
'src/utils/hostNamesConfig';
import { updateDataMask } from 'src/dataMask/actions';
import { waitForAsyncData } from 'src/middleware/asyncEvent';
diff --git
a/superset-frontend/src/components/Datasource/ChangeDatasourceModal.tsx
b/superset-frontend/src/components/Datasource/ChangeDatasourceModal.tsx
index 5e837f0a26..7fde5645a1 100644
--- a/superset-frontend/src/components/Datasource/ChangeDatasourceModal.tsx
+++ b/superset-frontend/src/components/Datasource/ChangeDatasourceModal.tsx
@@ -24,7 +24,12 @@ import React, {
useCallback,
} from 'react';
import Alert from 'src/components/Alert';
-import { SupersetClient, t, styled } from '@superset-ui/core';
+import {
+ SupersetClient,
+ t,
+ styled,
+ getClientErrorObject,
+} from '@superset-ui/core';
import TableView, { EmptyWrapperType } from 'src/components/TableView';
import { ServerPagination, SortByType } from 'src/components/TableView/types';
import StyledModal from 'src/components/Modal';
@@ -33,7 +38,6 @@ import { useListViewResource } from 'src/views/CRUD/hooks';
import Dataset from 'src/types/Dataset';
import { useDebouncedEffect } from 'src/explore/exploreUtils';
import { SLOW_DEBOUNCE } from 'src/constants';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import Loading from 'src/components/Loading';
import { AntdInput } from 'src/components';
import { Input } from 'src/components/Input';
diff --git a/superset-frontend/src/components/Datasource/DatasourceEditor.jsx
b/superset-frontend/src/components/Datasource/DatasourceEditor.jsx
index cc18ec0fe4..b9af27d2af 100644
--- a/superset-frontend/src/components/Datasource/DatasourceEditor.jsx
+++ b/superset-frontend/src/components/Datasource/DatasourceEditor.jsx
@@ -34,6 +34,7 @@ import {
SupersetClient,
t,
withTheme,
+ getClientErrorObject,
} from '@superset-ui/core';
import { Select, AsyncSelect, Row, Col } from 'src/components';
import { FormLabel } from 'src/components/Form';
@@ -46,7 +47,6 @@ import Label from 'src/components/Label';
import Loading from 'src/components/Loading';
import TableSelector from 'src/components/TableSelector';
import EditableTitle from 'src/components/EditableTitle';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import CheckboxControl from 'src/explore/components/controls/CheckboxControl';
import TextControl from 'src/explore/components/controls/TextControl';
import TextAreaControl from 'src/explore/components/controls/TextAreaControl';
diff --git a/superset-frontend/src/components/Datasource/DatasourceModal.tsx
b/superset-frontend/src/components/Datasource/DatasourceModal.tsx
index e318821a5b..f4cdecc1c3 100644
--- a/superset-frontend/src/components/Datasource/DatasourceModal.tsx
+++ b/superset-frontend/src/components/Datasource/DatasourceModal.tsx
@@ -26,16 +26,16 @@ import {
Metric,
styled,
SupersetClient,
+ getClientErrorObject,
t,
+ SupersetError,
} from '@superset-ui/core';
import Modal from 'src/components/Modal';
import AsyncEsmComponent from 'src/components/AsyncEsmComponent';
-import { SupersetError } from 'src/components/ErrorMessage/types';
import ErrorMessageWithStackTrace from
'src/components/ErrorMessage/ErrorMessageWithStackTrace';
import withToasts from 'src/components/MessageToasts/withToasts';
import { useSelector } from 'react-redux';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
const DatasourceEditor = AsyncEsmComponent(() => import('./DatasourceEditor'));
diff --git
a/superset-frontend/src/components/ErrorMessage/BasicErrorAlert.test.tsx
b/superset-frontend/src/components/ErrorMessage/BasicErrorAlert.test.tsx
index a82f3583cd..e39f5079b6 100644
--- a/superset-frontend/src/components/ErrorMessage/BasicErrorAlert.test.tsx
+++ b/superset-frontend/src/components/ErrorMessage/BasicErrorAlert.test.tsx
@@ -19,9 +19,8 @@
import React from 'react';
import { render, screen } from 'spec/helpers/testing-library';
-import { supersetTheme } from '@superset-ui/core';
+import { ErrorLevel, supersetTheme } from '@superset-ui/core';
import BasicErrorAlert from './BasicErrorAlert';
-import { ErrorLevel } from './types';
jest.mock(
'src/components/Icons/Icon',
diff --git a/superset-frontend/src/components/ErrorMessage/BasicErrorAlert.tsx
b/superset-frontend/src/components/ErrorMessage/BasicErrorAlert.tsx
index 918aee5f24..db61656b83 100644
--- a/superset-frontend/src/components/ErrorMessage/BasicErrorAlert.tsx
+++ b/superset-frontend/src/components/ErrorMessage/BasicErrorAlert.tsx
@@ -17,9 +17,8 @@
* under the License.
*/
import React from 'react';
-import { styled, useTheme } from '@superset-ui/core';
+import { ErrorLevel, styled, useTheme } from '@superset-ui/core';
import Icons from 'src/components/Icons';
-import { ErrorLevel } from './types';
const StyledContainer = styled.div<{ level: ErrorLevel }>`
display: flex;
diff --git
a/superset-frontend/src/components/ErrorMessage/DatabaseErrorMessage.test.tsx
b/superset-frontend/src/components/ErrorMessage/DatabaseErrorMessage.test.tsx
index 0a1ad27299..1ddcb67aca 100644
---
a/superset-frontend/src/components/ErrorMessage/DatabaseErrorMessage.test.tsx
+++
b/superset-frontend/src/components/ErrorMessage/DatabaseErrorMessage.test.tsx
@@ -18,10 +18,10 @@
*/
import React from 'react';
+import { ErrorLevel, ErrorSource, ErrorTypeEnum } from '@superset-ui/core';
import { render, screen } from 'spec/helpers/testing-library';
import userEvent from '@testing-library/user-event';
import DatabaseErrorMessage from './DatabaseErrorMessage';
-import { ErrorLevel, ErrorSource, ErrorTypeEnum } from './types';
jest.mock(
'src/components/Icons/Icon',
diff --git
a/superset-frontend/src/components/ErrorMessage/DatasetNotFoundErrorMessage.test.tsx
b/superset-frontend/src/components/ErrorMessage/DatasetNotFoundErrorMessage.test.tsx
index 60883ae9a0..c258d9128c 100644
---
a/superset-frontend/src/components/ErrorMessage/DatasetNotFoundErrorMessage.test.tsx
+++
b/superset-frontend/src/components/ErrorMessage/DatasetNotFoundErrorMessage.test.tsx
@@ -18,9 +18,9 @@
*/
import React from 'react';
+import { ErrorLevel, ErrorSource, ErrorTypeEnum } from '@superset-ui/core';
import { render, screen } from 'spec/helpers/testing-library';
import DatasetNotFoundErrorMessage from './DatasetNotFoundErrorMessage';
-import { ErrorLevel, ErrorSource, ErrorTypeEnum } from './types';
jest.mock(
'src/components/Icons/Icon',
diff --git a/superset-frontend/src/components/ErrorMessage/ErrorAlert.test.tsx
b/superset-frontend/src/components/ErrorMessage/ErrorAlert.test.tsx
index d6f2ebe25e..65530ff91f 100644
--- a/superset-frontend/src/components/ErrorMessage/ErrorAlert.test.tsx
+++ b/superset-frontend/src/components/ErrorMessage/ErrorAlert.test.tsx
@@ -20,10 +20,9 @@
import React from 'react';
import userEvent from '@testing-library/user-event';
import { render, screen } from 'spec/helpers/testing-library';
-import { supersetTheme } from '@superset-ui/core';
+import { ErrorLevel, ErrorSource, supersetTheme } from '@superset-ui/core';
import { isCurrentUserBot } from 'src/utils/isBot';
import ErrorAlert from './ErrorAlert';
-import { ErrorLevel, ErrorSource } from './types';
jest.mock(
'src/components/Icons/Icon',
diff --git a/superset-frontend/src/components/ErrorMessage/ErrorAlert.tsx
b/superset-frontend/src/components/ErrorMessage/ErrorAlert.tsx
index da5894e887..c80d78d926 100644
--- a/superset-frontend/src/components/ErrorMessage/ErrorAlert.tsx
+++ b/superset-frontend/src/components/ErrorMessage/ErrorAlert.tsx
@@ -17,14 +17,19 @@
* under the License.
*/
import React, { useState, ReactNode } from 'react';
-import { styled, useTheme, t } from '@superset-ui/core';
+import {
+ ErrorLevel,
+ ErrorSource,
+ styled,
+ useTheme,
+ t,
+} from '@superset-ui/core';
import { noOp } from 'src/utils/common';
import Modal from 'src/components/Modal';
import Button from 'src/components/Button';
import { isCurrentUserBot } from 'src/utils/isBot';
import Icons from 'src/components/Icons';
-import { ErrorLevel, ErrorSource } from './types';
import CopyToClipboard from '../CopyToClipboard';
const ErrorAlertDiv = styled.div<{ level: ErrorLevel }>`
diff --git
a/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.test.tsx
b/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.test.tsx
index 7583983e43..ef505e4ab2 100644
---
a/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.test.tsx
+++
b/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.test.tsx
@@ -18,11 +18,11 @@
*/
import React from 'react';
+import { ErrorLevel, ErrorSource, ErrorTypeEnum } from '@superset-ui/core';
import { render, screen } from 'spec/helpers/testing-library';
import userEvent from '@testing-library/user-event';
import ErrorMessageWithStackTrace from './ErrorMessageWithStackTrace';
import BasicErrorAlert from './BasicErrorAlert';
-import { ErrorLevel, ErrorSource, ErrorTypeEnum } from './types';
jest.mock(
'src/components/Icons/Icon',
diff --git
a/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.tsx
b/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.tsx
index b9e7e5c053..5197ea72ef 100644
---
a/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.tsx
+++
b/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.tsx
@@ -17,9 +17,8 @@
* under the License.
*/
import React from 'react';
-import { t } from '@superset-ui/core';
+import { ErrorSource, t, SupersetError } from '@superset-ui/core';
import getErrorMessageComponentRegistry from
'./getErrorMessageComponentRegistry';
-import { SupersetError, ErrorSource } from './types';
import ErrorAlert from './ErrorAlert';
const DEFAULT_TITLE = t('Unexpected error');
diff --git
a/superset-frontend/src/components/ErrorMessage/MarshmallowErrorMessage.test.tsx
b/superset-frontend/src/components/ErrorMessage/MarshmallowErrorMessage.test.tsx
index 5fd6ee7bfb..5a35f93068 100644
---
a/superset-frontend/src/components/ErrorMessage/MarshmallowErrorMessage.test.tsx
+++
b/superset-frontend/src/components/ErrorMessage/MarshmallowErrorMessage.test.tsx
@@ -20,8 +20,12 @@
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
-import { ThemeProvider, supersetTheme } from '@superset-ui/core';
-import { ErrorLevel, ErrorTypeEnum } from 'src/components/ErrorMessage/types';
+import {
+ ErrorLevel,
+ ErrorTypeEnum,
+ ThemeProvider,
+ supersetTheme,
+} from '@superset-ui/core';
import MarshmallowErrorMessage from './MarshmallowErrorMessage';
describe('MarshmallowErrorMessage', () => {
diff --git
a/superset-frontend/src/components/ErrorMessage/OAuth2RedirectMessage.test.tsx
b/superset-frontend/src/components/ErrorMessage/OAuth2RedirectMessage.test.tsx
index c0930ee41b..f9c6872f00 100644
---
a/superset-frontend/src/components/ErrorMessage/OAuth2RedirectMessage.test.tsx
+++
b/superset-frontend/src/components/ErrorMessage/OAuth2RedirectMessage.test.tsx
@@ -23,13 +23,14 @@ import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { render, fireEvent, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
-import { ThemeProvider, supersetTheme } from '@superset-ui/core';
-import OAuth2RedirectMessage from
'src/components/ErrorMessage/OAuth2RedirectMessage';
import {
ErrorLevel,
ErrorSource,
ErrorTypeEnum,
-} from 'src/components/ErrorMessage/types';
+ ThemeProvider,
+ supersetTheme,
+} from '@superset-ui/core';
+import OAuth2RedirectMessage from
'src/components/ErrorMessage/OAuth2RedirectMessage';
import { reRunQuery } from 'src/SqlLab/actions/sqlLab';
import { triggerQuery } from 'src/components/Chart/chartAction';
import { onRefresh } from 'src/dashboard/actions/dashboardState';
diff --git
a/superset-frontend/src/components/ErrorMessage/ParameterErrorMessage.test.tsx
b/superset-frontend/src/components/ErrorMessage/ParameterErrorMessage.test.tsx
index 0b9518b4fc..5d7b949267 100644
---
a/superset-frontend/src/components/ErrorMessage/ParameterErrorMessage.test.tsx
+++
b/superset-frontend/src/components/ErrorMessage/ParameterErrorMessage.test.tsx
@@ -18,10 +18,10 @@
*/
import userEvent from '@testing-library/user-event';
+import { ErrorLevel, ErrorSource, ErrorTypeEnum } from '@superset-ui/core';
import React from 'react';
import { render, screen } from 'spec/helpers/testing-library';
import ParameterErrorMessage from './ParameterErrorMessage';
-import { ErrorLevel, ErrorSource, ErrorTypeEnum } from './types';
jest.mock(
'src/components/Icons/Icon',
diff --git
a/superset-frontend/src/components/ErrorMessage/TimeoutErrorMessage.test.tsx
b/superset-frontend/src/components/ErrorMessage/TimeoutErrorMessage.test.tsx
index a82b4d3f76..a99afed906 100644
--- a/superset-frontend/src/components/ErrorMessage/TimeoutErrorMessage.test.tsx
+++ b/superset-frontend/src/components/ErrorMessage/TimeoutErrorMessage.test.tsx
@@ -19,9 +19,9 @@
import userEvent from '@testing-library/user-event';
import React from 'react';
+import { ErrorSource, ErrorTypeEnum, ErrorLevel } from '@superset-ui/core';
import { render, screen } from 'spec/helpers/testing-library';
import TimeoutErrorMessage from './TimeoutErrorMessage';
-import { ErrorLevel, ErrorSource, ErrorTypeEnum } from './types';
jest.mock(
'src/components/Icons/Icon',
diff --git a/superset-frontend/src/components/ErrorMessage/types.ts
b/superset-frontend/src/components/ErrorMessage/types.ts
index a27c4aff45..ed05ef4481 100644
--- a/superset-frontend/src/components/ErrorMessage/types.ts
+++ b/superset-frontend/src/components/ErrorMessage/types.ts
@@ -17,95 +17,14 @@
* under the License.
*/
-// Keep in sync with superset/views/errors.py
-export const ErrorTypeEnum = {
- // Frontend errors
- FRONTEND_CSRF_ERROR: 'FRONTEND_CSRF_ERROR',
- FRONTEND_NETWORK_ERROR: 'FRONTEND_NETWORK_ERROR',
- FRONTEND_TIMEOUT_ERROR: 'FRONTEND_TIMEOUT_ERROR',
-
- // DB Engine errors
- GENERIC_DB_ENGINE_ERROR: 'GENERIC_DB_ENGINE_ERROR',
- COLUMN_DOES_NOT_EXIST_ERROR: 'COLUMN_DOES_NOT_EXIST_ERROR',
- TABLE_DOES_NOT_EXIST_ERROR: 'TABLE_DOES_NOT_EXIST_ERROR',
- SCHEMA_DOES_NOT_EXIST_ERROR: 'SCHEMA_DOES_NOT_EXIST_ERROR',
- CONNECTION_INVALID_USERNAME_ERROR: 'CONNECTION_INVALID_USERNAME_ERROR',
- CONNECTION_INVALID_PASSWORD_ERROR: 'CONNECTION_INVALID_PASSWORD_ERROR',
- CONNECTION_INVALID_HOSTNAME_ERROR: 'CONNECTION_INVALID_HOSTNAME_ERROR',
- CONNECTION_PORT_CLOSED_ERROR: 'CONNECTION_PORT_CLOSED_ERROR',
- CONNECTION_INVALID_PORT_ERROR: 'CONNECTION_INVALID_PORT_ERROR',
- CONNECTION_HOST_DOWN_ERROR: 'CONNECTION_HOST_DOWN_ERROR',
- CONNECTION_ACCESS_DENIED_ERROR: 'CONNECTION_ACCESS_DENIED_ERROR',
- CONNECTION_UNKNOWN_DATABASE_ERROR: 'CONNECTION_UNKNOWN_DATABASE_ERROR',
- CONNECTION_DATABASE_PERMISSIONS_ERROR:
- 'CONNECTION_DATABASE_PERMISSIONS_ERROR',
- CONNECTION_MISSING_PARAMETERS_ERRORS: 'CONNECTION_MISSING_PARAMETERS_ERRORS',
- OBJECT_DOES_NOT_EXIST_ERROR: 'OBJECT_DOES_NOT_EXIST_ERROR',
- SYNTAX_ERROR: 'SYNTAX_ERROR',
-
- // Viz errors
- VIZ_GET_DF_ERROR: 'VIZ_GET_DF_ERROR',
- UNKNOWN_DATASOURCE_TYPE_ERROR: 'UNKNOWN_DATASOURCE_TYPE_ERROR',
- FAILED_FETCHING_DATASOURCE_INFO_ERROR:
- 'FAILED_FETCHING_DATASOURCE_INFO_ERROR',
-
- // Security access errors
- TABLE_SECURITY_ACCESS_ERROR: 'TABLE_SECURITY_ACCESS_ERROR',
- DATASOURCE_SECURITY_ACCESS_ERROR: 'DATASOURCE_SECURITY_ACCESS_ERROR',
- DATABASE_SECURITY_ACCESS_ERROR: 'DATABASE_SECURITY_ACCESS_ERROR',
- QUERY_SECURITY_ACCESS_ERROR: 'QUERY_SECURITY_ACCESS_ERROR',
- MISSING_OWNERSHIP_ERROR: 'MISSING_OWNERSHIP_ERROR',
- DASHBOARD_SECURITY_ACCESS_ERROR: 'DASHBOARD_SECURITY_ACCESS_ERROR',
- OAUTH2_REDIRECT: 'OAUTH2_REDIRECT',
- OAUTH2_REDIRECT_ERROR: 'OAUTH2_REDIRECT_ERROR',
-
- // Other errors
- BACKEND_TIMEOUT_ERROR: 'BACKEND_TIMEOUT_ERROR',
- DATABASE_NOT_FOUND_ERROR: 'DATABASE_NOT_FOUND_ERROR',
-
- // Sqllab error
- MISSING_TEMPLATE_PARAMS_ERROR: 'MISSING_TEMPLATE_PARAMS_ERROR',
- INVALID_TEMPLATE_PARAMS_ERROR: 'INVALID_TEMPLATE_PARAMS_ERROR',
- RESULTS_BACKEND_NOT_CONFIGURED_ERROR: 'RESULTS_BACKEND_NOT_CONFIGURED_ERROR',
- DML_NOT_ALLOWED_ERROR: 'DML_NOT_ALLOWED_ERROR',
- INVALID_CTAS_QUERY_ERROR: 'INVALID_CTAS_QUERY_ERROR',
- INVALID_CVAS_QUERY_ERROR: 'INVALID_CVAS_QUERY_ERROR',
- SQLLAB_TIMEOUT_ERROR: 'SQLLAB_TIMEOUT_ERROR',
- RESULTS_BACKEND_ERROR: 'RESULTS_BACKEND_ERROR',
- ASYNC_WORKERS_ERROR: 'ASYNC_WORKERS_ERROR',
-
- // Generic errors
- GENERIC_COMMAND_ERROR: 'GENERIC_COMMAND_ERROR',
- GENERIC_BACKEND_ERROR: 'GENERIC_BACKEND_ERROR',
-
- // API errors
- INVALID_PAYLOAD_FORMAT_ERROR: 'INVALID_PAYLOAD_FORMAT_ERROR',
- INVALID_PAYLOAD_SCHEMA_ERROR: 'INVALID_PAYLOAD_SCHEMA_ERROR',
- MARSHMALLOW_ERROR: 'MARSHMALLOW_ERROR',
-} as const;
-
-type ValueOf<T> = T[keyof T];
-
-export type ErrorType = ValueOf<typeof ErrorTypeEnum>;
-
-// Keep in sync with superset/views/errors.py
-export type ErrorLevel = 'info' | 'warning' | 'error';
-
-export type ErrorSource = 'dashboard' | 'explore' | 'sqllab' | 'crud';
-
-export type SupersetError<ExtraType = Record<string, any> | null> = {
- error_type: ErrorType;
- extra: ExtraType;
- level: ErrorLevel;
- message: string;
-};
+import { ReactNode, ComponentType } from 'react';
+import { ErrorSource, SupersetError } from '@superset-ui/core';
export type ErrorMessageComponentProps<ExtraType = Record<string, any> | null>
=
{
error: SupersetError<ExtraType>;
source?: ErrorSource;
- subtitle?: React.ReactNode;
+ subtitle?: ReactNode;
};
-export type ErrorMessageComponent =
- React.ComponentType<ErrorMessageComponentProps>;
+export type ErrorMessageComponent = ComponentType<ErrorMessageComponentProps>;
diff --git a/superset-frontend/src/components/Select/AsyncSelect.tsx
b/superset-frontend/src/components/Select/AsyncSelect.tsx
index 3fb8bceaf4..4f7a69784d 100644
--- a/superset-frontend/src/components/Select/AsyncSelect.tsx
+++ b/superset-frontend/src/components/Select/AsyncSelect.tsx
@@ -29,11 +29,15 @@ import React, {
useImperativeHandle,
ClipboardEvent,
} from 'react';
-import { ensureIsArray, t, usePrevious } from '@superset-ui/core';
+import {
+ ensureIsArray,
+ t,
+ usePrevious,
+ getClientErrorObject,
+} from '@superset-ui/core';
import { LabeledValue as AntdLabeledValue } from 'antd/lib/select';
import { debounce, isEqual, uniq } from 'lodash';
import Icons from 'src/components/Icons';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import { FAST_DEBOUNCE, SLOW_DEBOUNCE } from 'src/constants';
import {
getValue,
diff --git a/superset-frontend/src/components/TableSelector/index.tsx
b/superset-frontend/src/components/TableSelector/index.tsx
index 2598d4df23..b7c92a978a 100644
--- a/superset-frontend/src/components/TableSelector/index.tsx
+++ b/superset-frontend/src/components/TableSelector/index.tsx
@@ -25,7 +25,12 @@ import React, {
} from 'react';
import { SelectValue } from 'antd/lib/select';
-import { styled, t } from '@superset-ui/core';
+import {
+ styled,
+ t,
+ getClientErrorMessage,
+ getClientErrorObject,
+} from '@superset-ui/core';
import { Select } from 'src/components';
import { FormLabel } from 'src/components/Form';
import Icons from 'src/components/Icons';
@@ -37,10 +42,6 @@ import CertifiedBadge from 'src/components/CertifiedBadge';
import WarningIconWithTooltip from 'src/components/WarningIconWithTooltip';
import { useToasts } from 'src/components/MessageToasts/withToasts';
import { useTables, Table } from 'src/hooks/apiResources';
-import {
- getClientErrorMessage,
- getClientErrorObject,
-} from 'src/utils/getClientErrorObject';
const REFRESH_WIDTH = 30;
diff --git a/superset-frontend/src/components/Tags/utils.tsx
b/superset-frontend/src/components/Tags/utils.tsx
index ec08a3b126..f0dd4c46f6 100644
--- a/superset-frontend/src/components/Tags/utils.tsx
+++ b/superset-frontend/src/components/Tags/utils.tsx
@@ -17,15 +17,16 @@
* under the License.
*/
-import { SupersetClient, t } from '@superset-ui/core';
+import {
+ ClientErrorObject,
+ getClientErrorObject,
+ SupersetClient,
+ t,
+} from '@superset-ui/core';
import Tag from 'src/types/TagType';
import rison from 'rison';
import { cacheWrapper } from 'src/utils/cacheWrapper';
-import {
- ClientErrorObject,
- getClientErrorObject,
-} from 'src/utils/getClientErrorObject';
const localCache = new Map<string, any>();
diff --git a/superset-frontend/src/dashboard/actions/dashboardInfo.ts
b/superset-frontend/src/dashboard/actions/dashboardInfo.ts
index 472f945b54..d1029203c7 100644
--- a/superset-frontend/src/dashboard/actions/dashboardInfo.ts
+++ b/superset-frontend/src/dashboard/actions/dashboardInfo.ts
@@ -17,9 +17,13 @@
* under the License.
*/
import { Dispatch } from 'redux';
-import { makeApi, CategoricalColorNamespace, t } from '@superset-ui/core';
+import {
+ makeApi,
+ CategoricalColorNamespace,
+ t,
+ getErrorText,
+} from '@superset-ui/core';
import { isString } from 'lodash';
-import { getErrorText } from 'src/utils/getClientErrorObject';
import { addDangerToast } from 'src/components/MessageToasts/actions';
import {
ChartConfiguration,
diff --git a/superset-frontend/src/dashboard/actions/dashboardState.js
b/superset-frontend/src/dashboard/actions/dashboardState.js
index bdbf430903..d6c7109a4c 100644
--- a/superset-frontend/src/dashboard/actions/dashboardState.js
+++ b/superset-frontend/src/dashboard/actions/dashboardState.js
@@ -26,6 +26,7 @@ import {
getSharedLabelColor,
SupersetClient,
t,
+ getClientErrorObject,
} from '@superset-ui/core';
import {
addChart,
@@ -34,7 +35,6 @@ import {
} from 'src/components/Chart/chartAction';
import { chart as initChart } from 'src/components/Chart/chartReducer';
import { applyDefaultFormData } from 'src/explore/store';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import {
SAVE_TYPE_OVERWRITE,
SAVE_TYPE_OVERWRITE_CONFIRMED,
diff --git a/superset-frontend/src/dashboard/actions/sliceEntities.ts
b/superset-frontend/src/dashboard/actions/sliceEntities.ts
index 9d85e57a6a..91b5faf6f0 100644
--- a/superset-frontend/src/dashboard/actions/sliceEntities.ts
+++ b/superset-frontend/src/dashboard/actions/sliceEntities.ts
@@ -17,9 +17,13 @@
* under the License.
*/
import rison from 'rison';
-import { DatasourceType, SupersetClient, t } from '@superset-ui/core';
+import {
+ DatasourceType,
+ SupersetClient,
+ t,
+ getClientErrorObject,
+} from '@superset-ui/core';
import { addDangerToast } from 'src/components/MessageToasts/actions';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import { Dispatch } from 'redux';
import { Slice } from '../types';
diff --git
a/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx
b/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx
index 1b5ef5fceb..8613a8db6f 100644
--- a/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx
+++ b/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx
@@ -34,6 +34,7 @@ import {
styled,
SupersetClient,
t,
+ getClientErrorObject,
} from '@superset-ui/core';
import Modal from 'src/components/Modal';
@@ -41,7 +42,6 @@ import { JsonEditor } from 'src/components/AsyncAceEditor';
import ColorSchemeControlWrapper from
'src/dashboard/components/ColorSchemeControlWrapper';
import FilterScopeModal from
'src/dashboard/components/filterscope/FilterScopeModal';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import withToasts from 'src/components/MessageToasts/withToasts';
import TagType from 'src/types/TagType';
import {
diff --git
a/superset-frontend/src/dashboard/components/URLShortLinkButton/index.tsx
b/superset-frontend/src/dashboard/components/URLShortLinkButton/index.tsx
index 2d13cedcd6..f91790e814 100644
--- a/superset-frontend/src/dashboard/components/URLShortLinkButton/index.tsx
+++ b/superset-frontend/src/dashboard/components/URLShortLinkButton/index.tsx
@@ -17,14 +17,13 @@
* under the License.
*/
import React, { useState } from 'react';
-import { t } from '@superset-ui/core';
+import { getClientErrorObject, t } from '@superset-ui/core';
import Popover, { PopoverProps } from 'src/components/Popover';
import CopyToClipboard from 'src/components/CopyToClipboard';
import { getDashboardPermalink } from 'src/utils/urlUtils';
import { useToasts } from 'src/components/MessageToasts/withToasts';
import { useSelector } from 'react-redux';
import { RootState } from 'src/dashboard/types';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
export type URLShortLinkButtonProps = {
dashboardId: number;
diff --git
a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx
b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx
index 5041fa3c97..f8f4f6174e 100644
---
a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx
+++
b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx
@@ -35,6 +35,8 @@ import {
styled,
SuperChart,
t,
+ ClientErrorObject,
+ getClientErrorObject,
} from '@superset-ui/core';
import { useDispatch, useSelector } from 'react-redux';
import { isEqual, isEqualWith } from 'lodash';
@@ -43,10 +45,6 @@ import Loading from 'src/components/Loading';
import BasicErrorAlert from 'src/components/ErrorMessage/BasicErrorAlert';
import ErrorMessageWithStackTrace from
'src/components/ErrorMessage/ErrorMessageWithStackTrace';
import { waitForAsyncData } from 'src/middleware/asyncEvent';
-import {
- ClientErrorObject,
- getClientErrorObject,
-} from 'src/utils/getClientErrorObject';
import { FilterBarOrientation, RootState } from 'src/dashboard/types';
import {
onFiltersRefreshSuccess,
diff --git
a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.test.tsx
b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.test.tsx
index 096771e44d..07e1432733 100644
---
a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.test.tsx
+++
b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.test.tsx
@@ -19,7 +19,7 @@
import React from 'react';
import { render, screen, waitFor } from 'spec/helpers/testing-library';
import fetchMock from 'fetch-mock';
-import * as utils from 'src/utils/getClientErrorObject';
+import * as uiCore from '@superset-ui/core';
import { Column, JsonObject } from '@superset-ui/core';
import userEvent from '@testing-library/user-event';
import { ColumnSelect } from './ColumnSelect';
@@ -97,7 +97,7 @@ test('Should call "getClientErrorObject" when api returns an
error', async () =>
const props = createProps();
props.datasetId = 789;
- const spy = jest.spyOn(utils, 'getClientErrorObject');
+ const spy = jest.spyOn(uiCore, 'getClientErrorObject');
expect(spy).not.toBeCalled();
render(<ColumnSelect {...(props as any)} />, {
diff --git
a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.tsx
b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.tsx
index d167a9be8c..243f3d2135 100644
---
a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.tsx
+++
b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.tsx
@@ -18,10 +18,15 @@
*/
import React, { useCallback, useState, useMemo, useEffect } from 'react';
import rison from 'rison';
-import { Column, ensureIsArray, t, useChangeEffect } from '@superset-ui/core';
+import {
+ Column,
+ ensureIsArray,
+ t,
+ useChangeEffect,
+ getClientErrorObject,
+} from '@superset-ui/core';
import { Select, FormInstance } from 'src/components';
import { useToasts } from 'src/components/MessageToasts/withToasts';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import { cachedSupersetGet } from 'src/utils/cachedSupersetGet';
import { NativeFiltersForm } from '../types';
diff --git
a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DatasetSelect.tsx
b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DatasetSelect.tsx
index 532547e58a..a27d6d089a 100644
---
a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DatasetSelect.tsx
+++
b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DatasetSelect.tsx
@@ -18,12 +18,13 @@
*/
import React, { useCallback, useMemo, ReactNode } from 'react';
import rison from 'rison';
-import { t, JsonResponse } from '@superset-ui/core';
-import { AsyncSelect } from 'src/components';
import {
+ t,
+ JsonResponse,
ClientErrorObject,
getClientErrorObject,
-} from 'src/utils/getClientErrorObject';
+} from '@superset-ui/core';
+import { AsyncSelect } from 'src/components';
import { cachedSupersetGet } from 'src/utils/cachedSupersetGet';
import {
Dataset,
diff --git
a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
index 029a95f3ab..be8311b913 100644
---
a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
+++
b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
@@ -37,6 +37,8 @@ import {
styled,
SupersetApiError,
t,
+ ClientErrorObject,
+ getClientErrorObject,
} from '@superset-ui/core';
import { isEqual } from 'lodash';
import React, {
@@ -73,10 +75,6 @@ import {
import DateFilterControl from
'src/explore/components/controls/DateFilterControl';
import AdhocFilterControl from
'src/explore/components/controls/FilterControl/AdhocFilterControl';
import { waitForAsyncData } from 'src/middleware/asyncEvent';
-import {
- ClientErrorObject,
- getClientErrorObject,
-} from 'src/utils/getClientErrorObject';
import { SingleValueType } from 'src/filters/components/Range/SingleValueType';
import {
getFormData,
diff --git a/superset-frontend/src/explore/actions/datasourcesActions.test.ts
b/superset-frontend/src/explore/actions/datasourcesActions.test.ts
index a844ff4789..71a92cfd21 100644
--- a/superset-frontend/src/explore/actions/datasourcesActions.test.ts
+++ b/superset-frontend/src/explore/actions/datasourcesActions.test.ts
@@ -18,13 +18,13 @@
*/
import { DatasourceType } from '@superset-ui/core';
import fetchMock from 'fetch-mock';
+import * as uiCore from '@superset-ui/core';
import {
setDatasource,
changeDatasource,
saveDataset,
} from 'src/explore/actions/datasourcesActions';
import sinon from 'sinon';
-import * as ClientError from 'src/utils/getClientErrorObject';
import datasourcesReducer from '../reducers/datasourcesReducer';
import { updateFormDataByDatasource } from './exploreActions';
@@ -126,7 +126,7 @@ test('updateSlice with add to existing dashboard handles
failure', async () => {
const sampleError = new Error('sampleError');
fetchMock.post(saveDatasetEndpoint, { throws: sampleError });
const dispatch = sinon.spy();
- const errorSpy = jest.spyOn(ClientError, 'getClientErrorObject');
+ const errorSpy = jest.spyOn(uiCore, 'getClientErrorObject');
let caughtError;
try {
diff --git a/superset-frontend/src/explore/actions/datasourcesActions.ts
b/superset-frontend/src/explore/actions/datasourcesActions.ts
index c11be07be3..54990c6f38 100644
--- a/superset-frontend/src/explore/actions/datasourcesActions.ts
+++ b/superset-frontend/src/explore/actions/datasourcesActions.ts
@@ -20,9 +20,8 @@
import { Dispatch, AnyAction } from 'redux';
import { ThunkDispatch } from 'redux-thunk';
import { Dataset } from '@superset-ui/chart-controls';
-import { SupersetClient } from '@superset-ui/core';
+import { SupersetClient, getClientErrorObject } from '@superset-ui/core';
import { addDangerToast } from 'src/components/MessageToasts/actions';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import { updateFormDataByDatasource } from './exploreActions';
import { ExplorePageState } from '../types';
diff --git
a/superset-frontend/src/explore/components/DataTablesPane/components/useResultsPane.tsx
b/superset-frontend/src/explore/components/DataTablesPane/components/useResultsPane.tsx
index bae6b6fd7b..bab7b78957 100644
---
a/superset-frontend/src/explore/components/DataTablesPane/components/useResultsPane.tsx
+++
b/superset-frontend/src/explore/components/DataTablesPane/components/useResultsPane.tsx
@@ -22,11 +22,11 @@ import {
styled,
t,
getChartMetadataRegistry,
+ getClientErrorObject,
} from '@superset-ui/core';
import Loading from 'src/components/Loading';
import { EmptyStateMedium } from 'src/components/EmptyState';
import { getChartDataRequest } from 'src/components/Chart/chartAction';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import { ResultsPaneProps, QueryResultInterface } from '../types';
import { SingleQueryResultPane } from './SingleQueryResultPane';
import { TableControls } from './DataTableControls';
diff --git a/superset-frontend/src/explore/components/PropertiesModal/index.tsx
b/superset-frontend/src/explore/components/PropertiesModal/index.tsx
index ba78dfa037..45af79a54b 100644
--- a/superset-frontend/src/explore/components/PropertiesModal/index.tsx
+++ b/superset-frontend/src/explore/components/PropertiesModal/index.tsx
@@ -29,9 +29,9 @@ import {
styled,
isFeatureEnabled,
FeatureFlag,
+ getClientErrorObject,
} from '@superset-ui/core';
import Chart, { Slice } from 'src/types/Chart';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import withToasts from 'src/components/MessageToasts/withToasts';
import { loadTags } from 'src/components/Tags/utils';
import {
diff --git
a/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx
b/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx
index a1a0a670f6..059bb35828 100644
---
a/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx
+++
b/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx
@@ -25,6 +25,7 @@ import {
NO_TIME_RANGE,
SupersetTheme,
useCSSTextTruncation,
+ fetchTimeRange,
} from '@superset-ui/core';
import Button from 'src/components/Button';
import ControlHeader from 'src/explore/components/ControlHeader';
@@ -41,7 +42,6 @@ import ControlPopover from '../ControlPopover/ControlPopover';
import { DateFilterControlProps, FrameType } from './types';
import {
DateFilterTestKey,
- fetchTimeRange,
FRAME_OPTIONS,
guessFrame,
useDefaultTimeFilter,
diff --git
a/superset-frontend/src/explore/components/controls/DateFilterControl/components/AdvancedFrame.tsx
b/superset-frontend/src/explore/components/controls/DateFilterControl/components/AdvancedFrame.tsx
index 77f42598ac..88d36f23ce 100644
---
a/superset-frontend/src/explore/components/controls/DateFilterControl/components/AdvancedFrame.tsx
+++
b/superset-frontend/src/explore/components/controls/DateFilterControl/components/AdvancedFrame.tsx
@@ -17,8 +17,7 @@
* under the License.
*/
import React from 'react';
-import { t } from '@superset-ui/core';
-import { SEPARATOR } from
'src/explore/components/controls/DateFilterControl/utils';
+import { SEPARATOR, t } from '@superset-ui/core';
import { Input } from 'src/components/Input';
import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
import { FrameComponentProps } from
'src/explore/components/controls/DateFilterControl/types';
diff --git
a/superset-frontend/src/explore/components/controls/DateFilterControl/tests/utils.test.ts
b/superset-frontend/src/explore/components/controls/DateFilterControl/tests/utils.test.ts
index 3a0debfec8..d44b08dddd 100644
---
a/superset-frontend/src/explore/components/controls/DateFilterControl/tests/utils.test.ts
+++
b/superset-frontend/src/explore/components/controls/DateFilterControl/tests/utils.test.ts
@@ -20,8 +20,6 @@
import {
customTimeRangeEncode,
customTimeRangeDecode,
- buildTimeRangeString,
- formatTimeRange,
} from 'src/explore/components/controls/DateFilterControl/utils';
describe('Custom TimeRange', () => {
@@ -298,34 +296,3 @@ describe('Custom TimeRange', () => {
});
});
});
-
-describe('buildTimeRangeString', () => {
- it('generates proper time range string', () => {
- expect(
- buildTimeRangeString('2010-07-30T00:00:00', '2020-07-30T00:00:00'),
- ).toBe('2010-07-30T00:00:00 : 2020-07-30T00:00:00');
- expect(buildTimeRangeString('', '2020-07-30T00:00:00')).toBe(
- ' : 2020-07-30T00:00:00',
- );
- expect(buildTimeRangeString('', '')).toBe(' : ');
- });
-});
-
-describe('formatTimeRange', () => {
- it('generates a readable time range', () => {
- expect(formatTimeRange('Last 7 days')).toBe('Last 7 days');
- expect(formatTimeRange('No filter')).toBe('No filter');
- expect(formatTimeRange('Yesterday : Tomorrow')).toBe(
- 'Yesterday ≤ col < Tomorrow',
- );
- expect(formatTimeRange('2010-07-30T00:00:00 : 2020-07-30T00:00:00')).toBe(
- '2010-07-30 ≤ col < 2020-07-30',
- );
- expect(formatTimeRange('2010-07-30T01:00:00 : ')).toBe(
- '2010-07-30T01:00:00 ≤ col < ∞',
- );
- expect(formatTimeRange(' : 2020-07-30T00:00:00')).toBe(
- '-∞ ≤ col < 2020-07-30',
- );
- });
-});
diff --git
a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts
b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts
index aad2f9984d..4be932e34a 100644
---
a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts
+++
b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts
@@ -16,9 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-import rison from 'rison';
-import { SupersetClient, NO_TIME_RANGE, JsonObject } from '@superset-ui/core';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
+import { NO_TIME_RANGE, JsonObject } from '@superset-ui/core';
import { useSelector } from 'react-redux';
import {
COMMON_RANGE_VALUES_SET,
@@ -27,26 +25,6 @@ import {
} from '.';
import { FrameType } from '../types';
-export const SEPARATOR = ' : ';
-
-export const buildTimeRangeString = (since: string, until: string): string =>
- `${since}${SEPARATOR}${until}`;
-
-const formatDateEndpoint = (dttm: string, isStart?: boolean): string =>
- dttm.replace('T00:00:00', '') || (isStart ? '-∞' : '∞');
-
-export const formatTimeRange = (
- timeRange: string,
- columnPlaceholder = 'col',
-) => {
- const splitDateRange = timeRange.split(SEPARATOR);
- if (splitDateRange.length === 1) return timeRange;
- return `${formatDateEndpoint(
- splitDateRange[0],
- true,
- )} ≤ ${columnPlaceholder} < ${formatDateEndpoint(splitDateRange[1])}`;
-};
-
export const guessFrame = (timeRange: string): FrameType => {
if (COMMON_RANGE_VALUES_SET.has(timeRange)) {
return 'Common';
@@ -63,29 +41,6 @@ export const guessFrame = (timeRange: string): FrameType => {
return 'Advanced';
};
-export const fetchTimeRange = async (
- timeRange: string,
- columnPlaceholder = 'col',
-) => {
- const query = rison.encode_uri(timeRange);
- const endpoint = `/api/v1/time_range/?q=${query}`;
- try {
- const response = await SupersetClient.get({ endpoint });
- const timeRangeString = buildTimeRangeString(
- response?.json?.result[0]?.since || '',
- response?.json?.result[0]?.until || '',
- );
- return {
- value: formatTimeRange(timeRangeString, columnPlaceholder),
- };
- } catch (response) {
- const clientError = await getClientErrorObject(response);
- return {
- error: clientError.message || clientError.error || response.statusText,
- };
- }
-};
-
export function useDefaultTimeFilter() {
return (
useSelector(
diff --git
a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateParser.ts
b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateParser.ts
index e4863665bf..b55cceccea 100644
---
a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateParser.ts
+++
b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateParser.ts
@@ -17,13 +17,13 @@
* under the License.
*/
import moment, { Moment } from 'moment';
+import { SEPARATOR } from '@superset-ui/core';
import {
CustomRangeDecodeType,
CustomRangeType,
DateTimeGrainType,
DateTimeModeType,
} from 'src/explore/components/controls/DateFilterControl/types';
-import { SEPARATOR } from './dateFilterUtils';
import { SEVEN_DAYS_AGO, MIDNIGHT, MOMENT_FORMAT } from './constants';
/**
diff --git
a/superset-frontend/src/explore/components/controls/FilterControl/utils/useGetTimeRangeLabel.test.ts
b/superset-frontend/src/explore/components/controls/FilterControl/utils/useGetTimeRangeLabel.test.ts
index 1c3dc321a8..7c0c916109 100644
---
a/superset-frontend/src/explore/components/controls/FilterControl/utils/useGetTimeRangeLabel.test.ts
+++
b/superset-frontend/src/explore/components/controls/FilterControl/utils/useGetTimeRangeLabel.test.ts
@@ -18,8 +18,8 @@
*/
import { renderHook } from '@testing-library/react-hooks';
import { NO_TIME_RANGE } from '@superset-ui/core';
+import * as uiCore from '@superset-ui/core';
import { Operators } from 'src/explore/constants';
-import * as FetchTimeRangeModule from
'src/explore/components/controls/DateFilterControl';
import { useGetTimeRangeLabel } from './useGetTimeRangeLabel';
import AdhocFilter from '../AdhocFilter';
import { Clauses, ExpressionTypes } from '../types';
@@ -65,7 +65,7 @@ test('should get "No filter" label', () => {
test('should get actualTimeRange and title', async () => {
jest
- .spyOn(FetchTimeRangeModule, 'fetchTimeRange')
+ .spyOn(uiCore, 'fetchTimeRange')
.mockResolvedValue({ value: 'MOCK TIME' });
const adhocFilter = new AdhocFilter({
@@ -85,7 +85,7 @@ test('should get actualTimeRange and title', async () => {
test('should get actualTimeRange and title when gets an error', async () => {
jest
- .spyOn(FetchTimeRangeModule, 'fetchTimeRange')
+ .spyOn(uiCore, 'fetchTimeRange')
.mockResolvedValue({ error: 'MOCK ERROR' });
const adhocFilter = new AdhocFilter({
diff --git
a/superset-frontend/src/explore/components/controls/FilterControl/utils/useGetTimeRangeLabel.tsx
b/superset-frontend/src/explore/components/controls/FilterControl/utils/useGetTimeRangeLabel.tsx
index 3a0b7a45ca..d68239c709 100644
---
a/superset-frontend/src/explore/components/controls/FilterControl/utils/useGetTimeRangeLabel.tsx
+++
b/superset-frontend/src/explore/components/controls/FilterControl/utils/useGetTimeRangeLabel.tsx
@@ -17,8 +17,7 @@
* under the License.
*/
import { useEffect, useState } from 'react';
-import { NO_TIME_RANGE } from '@superset-ui/core';
-import { fetchTimeRange } from
'src/explore/components/controls/DateFilterControl';
+import { NO_TIME_RANGE, fetchTimeRange } from '@superset-ui/core';
import { Operators } from 'src/explore/constants';
import AdhocFilter from '../AdhocFilter';
import { ExpressionTypes } from '../types';
diff --git
a/superset-frontend/src/explore/components/controls/SelectAsyncControl/index.tsx
b/superset-frontend/src/explore/components/controls/SelectAsyncControl/index.tsx
index ddc242a764..702abf5479 100644
---
a/superset-frontend/src/explore/components/controls/SelectAsyncControl/index.tsx
+++
b/superset-frontend/src/explore/components/controls/SelectAsyncControl/index.tsx
@@ -17,13 +17,12 @@
* under the License.
*/
import React, { useEffect, useState } from 'react';
-import { t, SupersetClient } from '@superset-ui/core';
+import { t, SupersetClient, getClientErrorObject } from '@superset-ui/core';
import ControlHeader from 'src/explore/components/ControlHeader';
import { Select } from 'src/components';
import { SelectOptionsType, SelectProps } from 'src/components/Select/types';
import { SelectValue, LabeledValue } from 'antd/lib/select';
import withToasts from 'src/components/MessageToasts/withToasts';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
type SelectAsyncProps = Omit<SelectProps, 'options' | 'ariaLabel' |
'onChange'>;
diff --git
a/superset-frontend/src/explore/components/controls/ViewQueryModal.tsx
b/superset-frontend/src/explore/components/controls/ViewQueryModal.tsx
index 023c1e3551..bd07ff5f01 100644
--- a/superset-frontend/src/explore/components/controls/ViewQueryModal.tsx
+++ b/superset-frontend/src/explore/components/controls/ViewQueryModal.tsx
@@ -17,9 +17,13 @@
* under the License.
*/
import React, { useEffect, useState } from 'react';
-import { styled, ensureIsArray, t } from '@superset-ui/core';
+import {
+ styled,
+ ensureIsArray,
+ t,
+ getClientErrorObject,
+} from '@superset-ui/core';
import Loading from 'src/components/Loading';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import { getChartDataRequest } from 'src/components/Chart/chartAction';
import ViewQuery from 'src/explore/components/controls/ViewQuery';
diff --git a/superset-frontend/src/features/reports/ReportModal/index.tsx
b/superset-frontend/src/features/reports/ReportModal/index.tsx
index c9993c8ffa..2f79e31f59 100644
--- a/superset-frontend/src/features/reports/ReportModal/index.tsx
+++ b/superset-frontend/src/features/reports/ReportModal/index.tsx
@@ -23,9 +23,8 @@ import React, {
useCallback,
useMemo,
} from 'react';
-import { t, SupersetTheme } from '@superset-ui/core';
+import { t, SupersetTheme, getClientErrorObject } from '@superset-ui/core';
import { useDispatch, useSelector } from 'react-redux';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import {
addReport,
editReport,
diff --git a/superset-frontend/src/hooks/apiResources/queryApi.ts
b/superset-frontend/src/hooks/apiResources/queryApi.ts
index ae25f3cc56..439418529f 100644
--- a/superset-frontend/src/hooks/apiResources/queryApi.ts
+++ b/superset-frontend/src/hooks/apiResources/queryApi.ts
@@ -17,12 +17,10 @@
* under the License.
*/
import rison from 'rison';
+import { createApi, BaseQueryFn } from '@reduxjs/toolkit/query/react';
import {
ClientErrorObject,
getClientErrorObject,
-} from 'src/utils/getClientErrorObject';
-import { createApi, BaseQueryFn } from '@reduxjs/toolkit/query/react';
-import {
SupersetClient,
ParseMethod,
SupersetClientResponse,
diff --git a/superset-frontend/src/middleware/asyncEvent.test.ts
b/superset-frontend/src/middleware/asyncEvent.test.ts
index c819893580..1debb22ac0 100644
--- a/superset-frontend/src/middleware/asyncEvent.test.ts
+++ b/superset-frontend/src/middleware/asyncEvent.test.ts
@@ -20,7 +20,6 @@ import fetchMock from 'fetch-mock';
import WS from 'jest-websocket-mock';
import sinon from 'sinon';
import * as uiCore from '@superset-ui/core';
-import { parseErrorJson } from 'src/utils/getClientErrorObject';
import * as asyncEvent from 'src/middleware/asyncEvent';
describe('asyncEvent middleware', () => {
@@ -129,7 +128,7 @@ describe('asyncEvent middleware', () => {
status: 200,
body: { result: [asyncErrorEvent] },
});
- const errorResponse = await parseErrorJson(asyncErrorEvent);
+ const errorResponse = await uiCore.parseErrorJson(asyncErrorEvent);
await expect(
asyncEvent.waitForAsyncData(asyncPendingEvent),
).rejects.toEqual(errorResponse);
@@ -204,7 +203,7 @@ describe('asyncEvent middleware', () => {
wsServer.send(JSON.stringify(asyncErrorEvent));
- const errorResponse = await parseErrorJson(asyncErrorEvent);
+ const errorResponse = await uiCore.parseErrorJson(asyncErrorEvent);
await expect(promise).rejects.toEqual(errorResponse);
diff --git a/superset-frontend/src/middleware/asyncEvent.ts
b/superset-frontend/src/middleware/asyncEvent.ts
index faa14229ca..0512e6817b 100644
--- a/superset-frontend/src/middleware/asyncEvent.ts
+++ b/superset-frontend/src/middleware/asyncEvent.ts
@@ -23,13 +23,11 @@ import {
makeApi,
SupersetClient,
logging,
-} from '@superset-ui/core';
-import { SupersetError } from 'src/components/ErrorMessage/types';
-import getBootstrapData from 'src/utils/getBootstrapData';
-import {
getClientErrorObject,
parseErrorJson,
-} from '../utils/getClientErrorObject';
+ SupersetError,
+} from '@superset-ui/core';
+import getBootstrapData from 'src/utils/getBootstrapData';
type AsyncEvent = {
id?: string | null;
diff --git a/superset-frontend/src/pages/AnnotationList/index.tsx
b/superset-frontend/src/pages/AnnotationList/index.tsx
index e04b48080f..344b7104ed 100644
--- a/superset-frontend/src/pages/AnnotationList/index.tsx
+++ b/superset-frontend/src/pages/AnnotationList/index.tsx
@@ -19,7 +19,13 @@
import React, { useMemo, useState, useEffect, useCallback } from 'react';
import { useParams, Link, useHistory } from 'react-router-dom';
-import { css, t, styled, SupersetClient } from '@superset-ui/core';
+import {
+ css,
+ t,
+ styled,
+ SupersetClient,
+ getClientErrorObject,
+} from '@superset-ui/core';
import moment from 'moment';
import rison from 'rison';
@@ -28,7 +34,6 @@ import ConfirmStatusChange from
'src/components/ConfirmStatusChange';
import DeleteModal from 'src/components/DeleteModal';
import ListView, { ListViewProps } from 'src/components/ListView';
import SubMenu, { SubMenuProps } from 'src/features/home/SubMenu';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import withToasts from 'src/components/MessageToasts/withToasts';
import { useListViewResource } from 'src/views/CRUD/hooks';
import { createErrorHandler } from 'src/views/CRUD/utils';
diff --git a/superset-frontend/src/pages/Chart/index.tsx
b/superset-frontend/src/pages/Chart/index.tsx
index c679e0e628..8cf47f0e3f 100644
--- a/superset-frontend/src/pages/Chart/index.tsx
+++ b/superset-frontend/src/pages/Chart/index.tsx
@@ -26,12 +26,12 @@ import {
makeApi,
SharedLabelColorSource,
t,
+ getClientErrorObject,
} from '@superset-ui/core';
import Loading from 'src/components/Loading';
import { addDangerToast } from 'src/components/MessageToasts/actions';
import { getUrlParam } from 'src/utils/urlUtils';
import { URL_PARAMS } from 'src/constants';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import getFormDataWithExtraFilters from
'src/dashboard/util/charts/getFormDataWithExtraFilters';
import { getAppliedFilterValues } from
'src/dashboard/util/activeDashboardFilters';
import { getParsedExploreURLParams } from
'src/explore/exploreUtils/getParsedExploreURLParams';
diff --git a/superset-frontend/src/setup/setupApp.ts
b/superset-frontend/src/setup/setupApp.ts
index 227aad3a68..0f31024cda 100644
--- a/superset-frontend/src/setup/setupApp.ts
+++ b/superset-frontend/src/setup/setupApp.ts
@@ -18,11 +18,11 @@
*/
/* eslint global-require: 0 */
import $ from 'jquery';
-import { SupersetClient } from '@superset-ui/core';
import {
+ SupersetClient,
getClientErrorObject,
ClientErrorObject,
-} from 'src/utils/getClientErrorObject';
+} from '@superset-ui/core';
import setupErrorMessages from 'src/setup/setupErrorMessages';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
diff --git a/superset-frontend/src/setup/setupErrorMessages.ts
b/superset-frontend/src/setup/setupErrorMessages.ts
index f393a36f1c..4d731cb4e3 100644
--- a/superset-frontend/src/setup/setupErrorMessages.ts
+++ b/superset-frontend/src/setup/setupErrorMessages.ts
@@ -16,8 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
+import { ErrorTypeEnum } from '@superset-ui/core';
import getErrorMessageComponentRegistry from
'src/components/ErrorMessage/getErrorMessageComponentRegistry';
-import { ErrorTypeEnum } from 'src/components/ErrorMessage/types';
import TimeoutErrorMessage from
'src/components/ErrorMessage/TimeoutErrorMessage';
import DatabaseErrorMessage from
'src/components/ErrorMessage/DatabaseErrorMessage';
import MarshmallowErrorMessage from
'src/components/ErrorMessage/MarshmallowErrorMessage';
diff --git a/superset-frontend/src/utils/errorMessages.ts
b/superset-frontend/src/utils/errorMessages.ts
deleted file mode 100644
index d5bfbdc17b..0000000000
--- a/superset-frontend/src/utils/errorMessages.ts
+++ /dev/null
@@ -1,26 +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.
- */
-
-// Error messages used in many places across applications
-const COMMON_ERR_MESSAGES = {
- SESSION_TIMED_OUT:
- 'Your session timed out, please refresh your page and try again.',
-};
-
-export default COMMON_ERR_MESSAGES;
diff --git a/superset-frontend/src/utils/getClientErrorObject.test.ts
b/superset-frontend/src/utils/getClientErrorObject.test.ts
deleted file mode 100644
index 8e89fec284..0000000000
--- a/superset-frontend/src/utils/getClientErrorObject.test.ts
+++ /dev/null
@@ -1,83 +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.
- */
-import { ErrorTypeEnum } from 'src/components/ErrorMessage/types';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
-
-describe('getClientErrorObject()', () => {
- it('Returns a Promise', () => {
- const response = getClientErrorObject('error');
- expect(response instanceof Promise).toBe(true);
- });
-
- it('Returns a Promise that resolves to an object with an error key', () => {
- const error = 'error';
-
- return getClientErrorObject(error).then(errorObj => {
- expect(errorObj).toMatchObject({ error });
- });
- });
-
- it('Handles Response that can be parsed as json', () => {
- const jsonError = { something: 'something', error: 'Error message' };
- const jsonErrorString = JSON.stringify(jsonError);
-
- return getClientErrorObject(new Response(jsonErrorString)).then(
- errorObj => {
- expect(errorObj).toMatchObject(jsonError);
- },
- );
- });
-
- it('Handles backwards compatibility between old error messages and the new
SIP-40 errors format', () => {
- const jsonError = {
- errors: [
- {
- error_type: ErrorTypeEnum.GENERIC_DB_ENGINE_ERROR,
- extra: { engine: 'presto', link: 'https://www.google.com' },
- level: 'error',
- message: 'presto error: test error',
- },
- ],
- };
- const jsonErrorString = JSON.stringify(jsonError);
-
- return getClientErrorObject(new Response(jsonErrorString)).then(
- errorObj => {
- expect(errorObj.error).toEqual(jsonError.errors[0].message);
- expect(errorObj.link).toEqual(jsonError.errors[0].extra.link);
- },
- );
- });
-
- it('Handles Response that can be parsed as text', () => {
- const textError = 'Hello I am a text error';
-
- return getClientErrorObject(new Response(textError)).then(errorObj => {
- expect(errorObj).toMatchObject({ error: textError });
- });
- });
-
- it('Handles plain text as input', () => {
- const error = 'error';
-
- return getClientErrorObject(error).then(errorObj => {
- expect(errorObj).toMatchObject({ error });
- });
- });
-});
diff --git a/superset-frontend/src/views/CRUD/hooks.ts
b/superset-frontend/src/views/CRUD/hooks.ts
index 8f31f2fcdd..129734fc8b 100644
--- a/superset-frontend/src/views/CRUD/hooks.ts
+++ b/superset-frontend/src/views/CRUD/hooks.ts
@@ -18,7 +18,13 @@
*/
import rison from 'rison';
import { useState, useEffect, useCallback } from 'react';
-import { makeApi, SupersetClient, t, JsonObject } from '@superset-ui/core';
+import {
+ makeApi,
+ SupersetClient,
+ t,
+ JsonObject,
+ getClientErrorObject,
+} from '@superset-ui/core';
import {
createErrorHandler,
@@ -33,7 +39,6 @@ import { FetchDataConfig } from 'src/components/ListView';
import { FilterValue } from 'src/components/ListView/types';
import Chart, { Slice } from 'src/types/Chart';
import copyTextToClipboard from 'src/utils/copy';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import SupersetText from 'src/utils/textUtils';
import { DatabaseObject } from 'src/features/databases/types';
import { FavoriteStatus, ImportResourceName } from './types';
diff --git a/superset-frontend/src/views/CRUD/utils.tsx
b/superset-frontend/src/views/CRUD/utils.tsx
index 514a39964e..96b8b0161d 100644
--- a/superset-frontend/src/views/CRUD/utils.tsx
+++ b/superset-frontend/src/views/CRUD/utils.tsx
@@ -24,12 +24,12 @@ import {
SupersetClient,
SupersetClientResponse,
SupersetTheme,
+ getClientErrorObject,
t,
} from '@superset-ui/core';
import Chart from 'src/types/Chart';
import { intersection } from 'lodash';
import rison from 'rison';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
import { FetchDataConfig, FilterValue } from 'src/components/ListView';
import SupersetText from 'src/utils/textUtils';
import { findPermission } from 'src/utils/findPermission';
diff --git a/superset/errors.py b/superset/errors.py
index b792a120da..612977ad65 100644
--- a/superset/errors.py
+++ b/superset/errors.py
@@ -26,7 +26,7 @@ class SupersetErrorType(StrEnum):
"""
Types of errors that can exist within Superset.
- Keep in sync with superset-frontend/src/components/ErrorMessage/types.ts
+ Keep in sync with
superset-frontend/packages/superset-ui-core/src/query/types/Query.ts
"""
# Frontend errors
@@ -196,7 +196,7 @@ class ErrorLevel(StrEnum):
"""
Levels of errors that can exist within Superset.
- Keep in sync with superset-frontend/src/components/ErrorMessage/types.ts
+ Keep in sync with
superset-frontend/packages/superset-ui-core/src/query/types/Query.ts
"""
INFO = "info"