From 9be7870a34459e4af77c4c84ff5e21af98154bf2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 25 May 2020 21:51:06 +0200 Subject: [PATCH] packages/core: add consumer side to AlertApi and use for AlertDialog + friends --- packages/app/src/App.tsx | 4 +-- .../core/src/api/apis/definitions/AlertApi.ts | 6 +++++ .../apis/implementations/AlertApiForwarder.ts | 17 +++++------- .../components/AlertDisplay/AlertDisplay.tsx | 26 +++++++++---------- 4 files changed, 26 insertions(+), 27 deletions(-) diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 327bca48f8..b4d01e067b 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -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<{}> = () => ( - + diff --git a/packages/core/src/api/apis/definitions/AlertApi.ts b/packages/core/src/api/apis/definitions/AlertApi.ts index 9776a96d84..123cd47651 100644 --- a/packages/core/src/api/apis/definitions/AlertApi.ts +++ b/packages/core/src/api/apis/definitions/AlertApi.ts @@ -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; }; export const alertApiRef = createApiRef({ diff --git a/packages/core/src/api/apis/implementations/AlertApiForwarder.ts b/packages/core/src/api/apis/implementations/AlertApiForwarder.ts index 349512c0f9..c95408283c 100644 --- a/packages/core/src/api/apis/implementations/AlertApiForwarder.ts +++ b/packages/core/src/api/apis/implementations/AlertApiForwarder.ts @@ -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(); + private readonly subject = new PublishSubject(); 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 { + return this.subject; } } diff --git a/packages/core/src/components/AlertDisplay/AlertDisplay.tsx b/packages/core/src/components/AlertDisplay/AlertDisplay.tsx index 23d1c7825f..85b41f2e0a 100644 --- a/packages/core/src/components/AlertDisplay/AlertDisplay.tsx +++ b/packages/core/src/components/AlertDisplay/AlertDisplay.tsx @@ -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 = ({ forwarder }) => { +export const AlertDisplay: FC = () => { const [messages, setMessages] = useState>([]); + 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 = ({ forwarder }) => { ); }; - -AlertDisplay.propTypes = { - forwarder: PropTypes.instanceOf(AlertApiForwarder).isRequired, -};