diff --git a/js/src/common/Application.ts b/js/src/common/Application.ts index 813fe8f14..abd753799 100644 --- a/js/src/common/Application.ts +++ b/js/src/common/Application.ts @@ -25,6 +25,7 @@ import ModalManager from './components/ModalManager'; import RequestErrorModal from './components/RequestErrorModal'; import flattenDeep from 'lodash/flattenDeep'; +import AlertManager from './components/AlertManager'; export type ApplicationData = { apiDocument: any; @@ -102,7 +103,9 @@ export default abstract class Application { titleCount = 0; drawer = new Drawer(); + modal!: ModalManager; + alerts!: AlertManager; load(payload) { this.data = payload; @@ -136,9 +139,9 @@ export default abstract class Application { } mount(basePath = '') { - m.mount(document.getElementById('modal'), new ModalManager()); + m.mount(document.getElementById('modal'), (this.modal = new ModalManager())); - // this.alerts = m.mount(document.getElementById('alerts'), ); + m.mount(document.getElementById('alerts'), (this.alerts = new AlertManager({ oninit: vnode => (this.alerts = vnode.state) }))); m.route(document.getElementById('content'), basePath + '/', mapRoutes(this.routes, basePath)); @@ -280,8 +283,7 @@ export default abstract class Application { } }; - // TODO: ALERT MANAGER - // if (this.requestError) this.alerts.dismiss(this.requestError.alert); + if (this.requestError) this.alerts.dismiss(this.requestError.alert); // Now make the request. If it's a failure, inspect the error that was // returned and show an alert containing its contents. @@ -336,7 +338,7 @@ export default abstract class Application { options.errorHandler(error); } catch (error) { console.error(error); - // this.alerts.show(error.alert); + this.alerts.show(error.alert); } return Promise.reject(error); @@ -345,7 +347,7 @@ export default abstract class Application { } private showDebug(error: RequestError) { - // this.alerts.dismiss(this.requestError.alert); + this.alerts.dismiss(this.requestError.alert); this.modal.show(RequestErrorModal, { error }); } diff --git a/js/src/common/components/AlertManager.tsx b/js/src/common/components/AlertManager.tsx new file mode 100644 index 000000000..447132595 --- /dev/null +++ b/js/src/common/components/AlertManager.tsx @@ -0,0 +1,54 @@ +import Component, { ComponentProps } from '../Component'; +import Alert from './Alert'; +import { Vnode } from 'mithril'; + +/** + * The `AlertManager` component provides an area in which `Alert` components can + * be shown and dismissed. + */ +export default class AlertManager extends Component { + /** + * An array of Alert components which are currently showing. + */ + protected components: Vnode[] = []; + + view() { + return ( + + {this.components.map(vnode => ( + {vnode} + ))} + + ); + } + + /** + * Show an Alert in the alerts area. + */ + public show(vnode: Vnode) { + vnode.attrs.ondismiss = this.dismiss.bind(this, vnode); + + this.components.push(vnode); + m.redraw(); + } + + /** + * Dismiss an alert. + */ + public dismiss(vnode) { + const index = this.components.indexOf(vnode); + + if (index !== -1) { + this.components.splice(index, 1); + m.redraw(); + } + } + + /** + * Clear all alerts. + */ + public clear() { + this.components = []; + m.redraw(); + } +}