Move error api to more generic alert api (#605)
This commit is contained in:
@@ -25,9 +25,9 @@ import { createApp } from '@backstage/core';
|
||||
import React, { FC } from 'react';
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import Root from './components/Root';
|
||||
import ErrorDisplay from './components/ErrorDisplay';
|
||||
import AlertDisplay from './components/AlertDisplay';
|
||||
import * as plugins from './plugins';
|
||||
import apis, { errorDialogForwarder } from './apis';
|
||||
import apis, { alertApiForwarder } from './apis';
|
||||
import { ThemeContextType, ThemeContext, useThemeType } from './ThemeContext';
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
@@ -86,7 +86,7 @@ const App: FC<{}> = () => {
|
||||
<ThemeContext.Provider value={themeContext}>
|
||||
<ThemeProvider theme={backstageTheme as Theme}>
|
||||
<CssBaseline>
|
||||
<ErrorDisplay forwarder={errorDialogForwarder} />
|
||||
<AlertDisplay forwarder={alertApiForwarder} />
|
||||
<Router>
|
||||
<Root>
|
||||
<AppComponent />
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
import {
|
||||
ApiHolder,
|
||||
ApiRegistry,
|
||||
alertApiRef,
|
||||
errorApiRef,
|
||||
AlertApiForwarder,
|
||||
ErrorApiForwarder,
|
||||
featureFlagsApiRef,
|
||||
FeatureFlags,
|
||||
} from '@backstage/core';
|
||||
@@ -26,13 +29,13 @@ import {
|
||||
LighthouseRestApi,
|
||||
} from '@backstage/plugin-lighthouse';
|
||||
|
||||
import { ErrorDisplayForwarder } from './components/ErrorDisplay/ErrorDisplay';
|
||||
|
||||
const builder = ApiRegistry.builder();
|
||||
|
||||
export const errorDialogForwarder = new ErrorDisplayForwarder();
|
||||
export const alertApiForwarder = new AlertApiForwarder();
|
||||
builder.add(alertApiRef, alertApiForwarder);
|
||||
|
||||
builder.add(errorApiRef, errorDialogForwarder);
|
||||
export const errorApiForwarder = new ErrorApiForwarder(alertApiForwarder);
|
||||
builder.add(errorApiRef, errorApiForwarder);
|
||||
|
||||
builder.add(featureFlagsApiRef, new FeatureFlags());
|
||||
|
||||
|
||||
+16
-39
@@ -19,59 +19,36 @@ import PropTypes from 'prop-types';
|
||||
import { Snackbar, IconButton } from '@material-ui/core';
|
||||
import CloseIcon from '@material-ui/icons/Close';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import { ErrorApi, ErrorContext } from '@backstage/core';
|
||||
|
||||
type SubscriberFunc = (error: Error) => void;
|
||||
type Unsubscribe = () => void;
|
||||
|
||||
// TODO: figure out where to put implementations of APIs, both inside apps
|
||||
// but also in core/separate package.
|
||||
export class ErrorDisplayForwarder implements ErrorApi {
|
||||
private readonly subscribers = new Set<SubscriberFunc>();
|
||||
|
||||
post(error: Error, context?: ErrorContext) {
|
||||
if (context?.hidden) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.subscribers.forEach(subscriber => subscriber(error));
|
||||
}
|
||||
|
||||
subscribe(func: SubscriberFunc): Unsubscribe {
|
||||
this.subscribers.add(func);
|
||||
|
||||
return () => {
|
||||
this.subscribers.delete(func);
|
||||
};
|
||||
}
|
||||
}
|
||||
import { AlertApiForwarder, AlertMessage } from '@backstage/core';
|
||||
|
||||
type Props = {
|
||||
forwarder: ErrorDisplayForwarder;
|
||||
forwarder: AlertApiForwarder;
|
||||
};
|
||||
|
||||
// TODO: improve on this and promote to a shared component for use by all apps.
|
||||
const ErrorDisplay: FC<Props> = ({ forwarder }) => {
|
||||
const [errors, setErrors] = useState<Array<Error>>([]);
|
||||
const AlertDisplay: FC<Props> = ({ forwarder }) => {
|
||||
const [messages, setMessages] = useState<Array<AlertMessage>>([]);
|
||||
|
||||
useEffect(() => {
|
||||
return forwarder.subscribe(error => setErrors(errs => errs.concat(error)));
|
||||
return forwarder.subscribe((message: AlertMessage) =>
|
||||
setMessages(msgs => msgs.concat(message)),
|
||||
);
|
||||
}, [forwarder]);
|
||||
|
||||
if (errors.length === 0) {
|
||||
if (messages.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const [firstError] = errors;
|
||||
const [firstMessage] = messages;
|
||||
|
||||
const handleClose = () => {
|
||||
setErrors(errs => errs.filter(err => err !== firstError));
|
||||
setMessages(msgs => msgs.filter(msg => msg !== firstMessage));
|
||||
};
|
||||
|
||||
return (
|
||||
<Snackbar
|
||||
open
|
||||
message={firstError.toString()}
|
||||
message={firstMessage.message.toString()}
|
||||
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
|
||||
>
|
||||
<Alert
|
||||
@@ -85,16 +62,16 @@ const ErrorDisplay: FC<Props> = ({ forwarder }) => {
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
}
|
||||
severity="error"
|
||||
severity={firstMessage.severity}
|
||||
>
|
||||
{firstError.toString()}
|
||||
{firstMessage.message.toString()}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
);
|
||||
};
|
||||
|
||||
ErrorDisplay.propTypes = {
|
||||
forwarder: PropTypes.instanceOf(ErrorDisplayForwarder).isRequired,
|
||||
AlertDisplay.propTypes = {
|
||||
forwarder: PropTypes.instanceOf(AlertApiForwarder).isRequired,
|
||||
};
|
||||
|
||||
export default ErrorDisplay;
|
||||
export default AlertDisplay;
|
||||
+1
-1
@@ -14,4 +14,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { default } from './ErrorDisplay';
|
||||
export { default } from './AlertDisplay';
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed 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 ApiRef from '../ApiRef';
|
||||
|
||||
export type AlertMessage = {
|
||||
message: string;
|
||||
// Severity will default to success since that is what material ui defaults the value to.
|
||||
severity?: 'success' | 'info' | 'warning' | 'error';
|
||||
};
|
||||
|
||||
/**
|
||||
* The alert API is used to report alerts to the app, and display them to the user.
|
||||
*/
|
||||
|
||||
export type AlertApi = {
|
||||
/**
|
||||
* Post an alert for handling by the application.
|
||||
*/
|
||||
post(alert: AlertMessage);
|
||||
};
|
||||
|
||||
export const alertApiRef = new ApiRef<AlertApi>({
|
||||
id: 'core.alert',
|
||||
description: 'Used to report alerts and forward them to the app',
|
||||
});
|
||||
@@ -20,5 +20,6 @@
|
||||
//
|
||||
// If you think some API definition is missing, please open an Issue or send a PR!
|
||||
|
||||
export * from './alert';
|
||||
export * from './error';
|
||||
export * from './featureFlags';
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed 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 { AlertApi, AlertMessage } from '../../../';
|
||||
|
||||
type SubscriberFunc = (message: AlertMessage) => void;
|
||||
type Unsubscribe = () => void;
|
||||
|
||||
export class AlertApiForwarder implements AlertApi {
|
||||
private readonly subscribers = new Set<SubscriberFunc>();
|
||||
|
||||
post(alert: AlertMessage) {
|
||||
this.subscribers.forEach(subscriber => subscriber(alert));
|
||||
}
|
||||
|
||||
subscribe(func: SubscriberFunc): Unsubscribe {
|
||||
this.subscribers.add(func);
|
||||
|
||||
return () => {
|
||||
this.subscribers.delete(func);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed 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 { ErrorApi, ErrorContext, AlertApi } from '../../../';
|
||||
|
||||
type SubscriberFunc = (error: Error) => void;
|
||||
type Unsubscribe = () => void;
|
||||
|
||||
export class ErrorApiForwarder implements ErrorApi {
|
||||
private readonly subscribers = new Set<SubscriberFunc>();
|
||||
private alertApi: AlertApi;
|
||||
|
||||
constructor(alertApi: AlertApi) {
|
||||
this.alertApi = alertApi;
|
||||
}
|
||||
|
||||
post(error: Error, context?: ErrorContext) {
|
||||
if (context?.hidden) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.alertApi.post({ message: error.message, severity: 'error' });
|
||||
this.subscribers.forEach(subscriber => subscriber(error));
|
||||
}
|
||||
|
||||
subscribe(func: SubscriberFunc): Unsubscribe {
|
||||
this.subscribers.add(func);
|
||||
|
||||
return () => {
|
||||
this.subscribers.delete(func);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
// This folder contains implementations for all core APIs.
|
||||
//
|
||||
// Plugins should rely on these APIs for functionality as much as possible.
|
||||
|
||||
export * from './AlertApiForwarder';
|
||||
export * from './ErrorApiForwarder';
|
||||
@@ -20,3 +20,4 @@ export { default as ApiTestRegistry } from './ApiTestRegistry';
|
||||
export { default as ApiRef } from './ApiRef';
|
||||
export * from './types';
|
||||
export * from './definitions';
|
||||
export * from './implementations';
|
||||
|
||||
@@ -17382,7 +17382,7 @@ request@^2.85.0, request@^2.87.0, request@^2.88.0:
|
||||
tunnel-agent "^0.6.0"
|
||||
uuid "^3.3.2"
|
||||
|
||||
request@cypress-io/request#b5af0d1fa47eec97ba980cde90a13e69a2afcd16:
|
||||
"request@github:cypress-io/request#b5af0d1fa47eec97ba980cde90a13e69a2afcd16":
|
||||
version "2.88.1"
|
||||
resolved "https://codeload.github.com/cypress-io/request/tar.gz/b5af0d1fa47eec97ba980cde90a13e69a2afcd16"
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user