packages/core: add consumer side to AlertApi and use for AlertDialog + friends
This commit is contained in:
@@ -19,7 +19,7 @@ import React, { FC } from 'react';
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import Root from './components/Root';
|
||||
import * as plugins from './plugins';
|
||||
import apis, { alertApiForwarder } from './apis';
|
||||
import apis from './apis';
|
||||
|
||||
const app = createApp({
|
||||
apis,
|
||||
@@ -31,7 +31,7 @@ const AppComponent = app.getRootComponent();
|
||||
|
||||
const App: FC<{}> = () => (
|
||||
<AppProvider>
|
||||
<AlertDisplay forwarder={alertApiForwarder} />
|
||||
<AlertDisplay />
|
||||
<OAuthRequestDialog />
|
||||
<Router>
|
||||
<Root>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { createApiRef } from '../ApiRef';
|
||||
import { Observable } from '../../types';
|
||||
|
||||
export type AlertMessage = {
|
||||
message: string;
|
||||
@@ -30,6 +31,11 @@ export type AlertApi = {
|
||||
* Post an alert for handling by the application.
|
||||
*/
|
||||
post(alert: AlertMessage): void;
|
||||
|
||||
/**
|
||||
* Observe alerts posted by other parts of the application.
|
||||
*/
|
||||
alert$(): Observable<AlertMessage>;
|
||||
};
|
||||
|
||||
export const alertApiRef = createApiRef<AlertApi>({
|
||||
|
||||
@@ -14,22 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { AlertApi, AlertMessage } from '../../../';
|
||||
|
||||
type SubscriberFunc = (message: AlertMessage) => void;
|
||||
type Unsubscribe = () => void;
|
||||
import { PublishSubject } from './lib';
|
||||
import { Observable } from '../../types';
|
||||
|
||||
export class AlertApiForwarder implements AlertApi {
|
||||
private readonly subscribers = new Set<SubscriberFunc>();
|
||||
private readonly subject = new PublishSubject<AlertMessage>();
|
||||
|
||||
post(alert: AlertMessage) {
|
||||
this.subscribers.forEach(subscriber => subscriber(alert));
|
||||
this.subject.next(alert);
|
||||
}
|
||||
|
||||
subscribe(func: SubscriberFunc): Unsubscribe {
|
||||
this.subscribers.add(func);
|
||||
|
||||
return () => {
|
||||
this.subscribers.delete(func);
|
||||
};
|
||||
alert$(): Observable<AlertMessage> {
|
||||
return this.subject;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,25 +15,27 @@
|
||||
*/
|
||||
|
||||
import React, { FC, useEffect, useState } from 'react';
|
||||
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 { AlertApiForwarder, AlertMessage } from '../../api';
|
||||
import { AlertMessage, useApi, alertApiRef } from '../../api';
|
||||
|
||||
type Props = {
|
||||
forwarder: AlertApiForwarder;
|
||||
};
|
||||
type Props = {};
|
||||
|
||||
// TODO: improve on this and promote to a shared component for use by all apps.
|
||||
export const AlertDisplay: FC<Props> = ({ forwarder }) => {
|
||||
export const AlertDisplay: FC<Props> = () => {
|
||||
const [messages, setMessages] = useState<Array<AlertMessage>>([]);
|
||||
const alertApi = useApi(alertApiRef);
|
||||
|
||||
useEffect(() => {
|
||||
return forwarder.subscribe((message: AlertMessage) =>
|
||||
setMessages(msgs => msgs.concat(message)),
|
||||
);
|
||||
}, [forwarder]);
|
||||
const subscription = alertApi
|
||||
.alert$()
|
||||
.subscribe(message => setMessages(msgs => msgs.concat(message)));
|
||||
|
||||
return () => {
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
}, [alertApi]);
|
||||
|
||||
if (messages.length === 0) {
|
||||
return null;
|
||||
@@ -69,7 +71,3 @@ export const AlertDisplay: FC<Props> = ({ forwarder }) => {
|
||||
</Snackbar>
|
||||
);
|
||||
};
|
||||
|
||||
AlertDisplay.propTypes = {
|
||||
forwarder: PropTypes.instanceOf(AlertApiForwarder).isRequired,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user