mirror of
https://github.com/apache/superset.git
synced 2026-04-20 16:44:46 +00:00
feat(errors): add client scaffolding for custom error messages (#9677)
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 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 React from 'react';
|
||||
import getErrorMessageComponentRegistry from 'src/components/ErrorMessage/getErrorMessageComponentRegistry';
|
||||
import { ErrorMessageComponentProps } from 'src/components/ErrorMessage/types';
|
||||
|
||||
const ERROR_MESSAGE_COMPONENT = (_: ErrorMessageComponentProps) => (
|
||||
<div>Test error</div>
|
||||
);
|
||||
|
||||
const OVERRIDE_ERROR_MESSAGE_COMPONENT = (_: ErrorMessageComponentProps) => (
|
||||
<div>Custom error</div>
|
||||
);
|
||||
|
||||
describe('getErrorMessageComponentRegistry', () => {
|
||||
it('returns undefined for a non existent key', () => {
|
||||
expect(getErrorMessageComponentRegistry().get('INVALID_KEY')).toEqual(
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns a component for a set key', () => {
|
||||
getErrorMessageComponentRegistry().registerValue(
|
||||
'VALID_KEY',
|
||||
ERROR_MESSAGE_COMPONENT,
|
||||
);
|
||||
|
||||
expect(getErrorMessageComponentRegistry().get('VALID_KEY')).toEqual(
|
||||
ERROR_MESSAGE_COMPONENT,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the correct component for an overridden key', () => {
|
||||
getErrorMessageComponentRegistry().registerValue(
|
||||
'OVERRIDE_KEY',
|
||||
ERROR_MESSAGE_COMPONENT,
|
||||
);
|
||||
|
||||
getErrorMessageComponentRegistry().registerValue(
|
||||
'OVERRIDE_KEY',
|
||||
OVERRIDE_ERROR_MESSAGE_COMPONENT,
|
||||
);
|
||||
|
||||
expect(getErrorMessageComponentRegistry().get('OVERRIDE_KEY')).toEqual(
|
||||
OVERRIDE_ERROR_MESSAGE_COMPONENT,
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -24,7 +24,7 @@ import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags';
|
||||
import { Logger, LOG_ACTIONS_RENDER_CHART_CONTAINER } from '../logger/LogUtils';
|
||||
import Loading from '../components/Loading';
|
||||
import RefreshChartOverlay from '../components/RefreshChartOverlay';
|
||||
import ErrorMessageWithStackTrace from '../components/ErrorMessageWithStackTrace';
|
||||
import ErrorMessageWithStackTrace from '../components/ErrorMessage/ErrorMessageWithStackTrace';
|
||||
import ErrorBoundary from '../components/ErrorBoundary';
|
||||
import ChartRenderer from './ChartRenderer';
|
||||
import './chart.less';
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { t } from '@superset-ui/translation';
|
||||
import ErrorMessageWithStackTrace from './ErrorMessageWithStackTrace';
|
||||
import ErrorMessageWithStackTrace from './ErrorMessage/ErrorMessageWithStackTrace';
|
||||
|
||||
const propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
|
||||
@@ -19,19 +19,35 @@
|
||||
import React, { useState } from 'react';
|
||||
// @ts-ignore
|
||||
import { Alert, Collapse } from 'react-bootstrap';
|
||||
import getErrorMessageComponentRegistry from './getErrorMessageComponentRegistry';
|
||||
import { SupersetError } from './types';
|
||||
|
||||
interface Props {
|
||||
message: string;
|
||||
type Props = {
|
||||
error?: SupersetError;
|
||||
link?: string;
|
||||
message: string;
|
||||
stackTrace?: string;
|
||||
}
|
||||
};
|
||||
|
||||
export default function ErrorMessageWithStackTrace({
|
||||
error,
|
||||
message,
|
||||
link,
|
||||
stackTrace,
|
||||
}: Props) {
|
||||
const [showStackTrace, setShowStackTrace] = useState(false);
|
||||
|
||||
// Check if a custom error message component was registered for this message
|
||||
if (error) {
|
||||
const ErrorMessageComponent = getErrorMessageComponentRegistry().get(
|
||||
error.errorType,
|
||||
);
|
||||
if (ErrorMessageComponent) {
|
||||
return <ErrorMessageComponent error={error} />;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to the default error message renderer
|
||||
return (
|
||||
<div className={`stack-trace-container${stackTrace ? ' has-trace' : ''}`}>
|
||||
<Alert
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 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 { Registry, makeSingleton, OverwritePolicy } from '@superset-ui/core';
|
||||
import { ErrorMessageComponent } from './types';
|
||||
|
||||
class ErrorMessageComponentRegistry extends Registry<
|
||||
ErrorMessageComponent,
|
||||
ErrorMessageComponent
|
||||
> {
|
||||
constructor() {
|
||||
super({
|
||||
name: 'ErrorMessageComponent',
|
||||
overwritePolicy: OverwritePolicy.ALLOW,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const getErrorMessageComponentRegistry = makeSingleton(
|
||||
ErrorMessageComponentRegistry,
|
||||
);
|
||||
|
||||
export default getErrorMessageComponentRegistry;
|
||||
47
superset-frontend/src/components/ErrorMessage/types.ts
Normal file
47
superset-frontend/src/components/ErrorMessage/types.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// TODO: Add more error types as we classify more errors
|
||||
export const ErrorTypeEnum = {
|
||||
// Generic errors created on the frontend
|
||||
FRONTEND_CSRF_ERROR: 'FRONTEND_CSRF_ERROR',
|
||||
FRONTEND_NETWORK_ERROR: 'FRONTEND_NETWORK_ERROR',
|
||||
FRONTEND_TIMEOUT_ERROR: 'FRONTEND_TIMEOUT_ERROR',
|
||||
} as const;
|
||||
|
||||
type ValueOf<T> = T[keyof T];
|
||||
|
||||
export type ErrorType = ValueOf<typeof ErrorTypeEnum>;
|
||||
|
||||
export type ErrorLevel = 'info' | 'warning' | 'error';
|
||||
|
||||
export type SupersetError = {
|
||||
errorType: ErrorType;
|
||||
extra: Record<string, any>;
|
||||
level: ErrorLevel;
|
||||
message: string;
|
||||
};
|
||||
|
||||
export type ErrorMessageComponentProps = {
|
||||
error: SupersetError;
|
||||
};
|
||||
|
||||
export type ErrorMessageComponent = React.ComponentType<
|
||||
ErrorMessageComponentProps
|
||||
>;
|
||||
@@ -20,6 +20,7 @@
|
||||
import $ from 'jquery';
|
||||
import { SupersetClient } from '@superset-ui/connection';
|
||||
import getClientErrorObject from '../utils/getClientErrorObject';
|
||||
import setupErrorMessages from './setupErrorMessages';
|
||||
|
||||
function showApiMessage(resp: { severity?: string; message: string }) {
|
||||
const template =
|
||||
@@ -84,4 +85,7 @@ export default function setupApp() {
|
||||
// @ts-ignore
|
||||
window.jQuery = $;
|
||||
require('bootstrap');
|
||||
|
||||
// setup appwide custom error messages
|
||||
setupErrorMessages();
|
||||
}
|
||||
|
||||
24
superset-frontend/src/setup/setupErrorMessages.ts
Normal file
24
superset-frontend/src/setup/setupErrorMessages.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* 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 setupErrorMessagesExtra from './setupErrorMessagesExtra';
|
||||
|
||||
export default function setupErrorMessages() {
|
||||
// TODO: Register error messages to the ErrorMessageComponentRegistry once implemented
|
||||
setupErrorMessagesExtra();
|
||||
}
|
||||
21
superset-frontend/src/setup/setupErrorMessagesExtra.ts
Normal file
21
superset-frontend/src/setup/setupErrorMessagesExtra.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// For individual deployments to add custom error messages
|
||||
export default function setupErrorMessagesExtra() {}
|
||||
Reference in New Issue
Block a user