Add Notifier component

This commit is contained in:
Germán Martínez 2019-09-25 15:14:07 +02:00
parent d4ed0d7f4a
commit aa613de2e7
4 changed files with 98 additions and 0 deletions

View File

@ -0,0 +1,16 @@
// @flow
import enqueueSnackbar from '~/logic/notifications/store/actions/enqueueSnackbar'
import closeSnackbar from '~/logic/notifications/store/actions/closeSnackbar'
import removeSnackbar from '~/logic/notifications/store/actions/removeSnackbar'
export type Actions = {
enqueueSnackbar: typeof enqueueSnackbar,
closeSnackbar: typeof closeSnackbar,
removeSnackbar: typeof removeSnackbar,
}
export default {
enqueueSnackbar,
closeSnackbar,
removeSnackbar,
}

View File

@ -0,0 +1,73 @@
// @flow
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { withSnackbar } from 'notistack'
import actions from './actions'
import selector from './selector'
class Notifier extends Component {
displayed = []
shouldComponentUpdate({ notifications: newSnacks = [] }) {
const { notifications: currentSnacks, closeSnackbar, removeSnackbar } = this.props
if (!newSnacks.size) {
this.displayed = []
return false
}
let notExists = false
for (let i = 0; i < newSnacks.size; i += 1) {
const newSnack = newSnacks.get(i)
if (newSnack.dismissed) {
closeSnackbar(newSnack.key)
removeSnackbar(newSnack.key)
}
if (notExists) {
continue
}
notExists = notExists || !currentSnacks.filter(({ key }) => newSnack.key === key).length
}
return notExists
}
componentDidUpdate() {
const { notifications = [], enqueueSnackbar, removeSnackbar } = this.props
notifications.map(({ key, message, options = {} }) => {
// Do nothing if snackbar is already displayed
if (this.displayed.includes(key)) {
return
}
// Display snackbar using notistack
enqueueSnackbar(message, {
...options,
onClose: (event, reason, key) => {
if (options.onClose) {
options.onClose(event, reason, key)
}
// Dispatch action to remove snackbar from redux store
removeSnackbar(key)
},
})
// Keep track of snackbars that we've displayed
this.storeDisplayed(key)
})
}
storeDisplayed = (id) => {
this.displayed = [...this.displayed, id]
}
render() {
return null
}
}
export default withSnackbar(
connect(
selector,
actions,
)(Notifier),
)

View File

@ -0,0 +1,7 @@
// @flow
import { createStructuredSelector } from 'reselect'
import { notificationsListSelector } from '~/logic/notifications/store/selectors'
export default createStructuredSelector<Object, *>({
notifications: notificationsListSelector,
})

View File

@ -5,6 +5,7 @@ import { withStyles } from '@material-ui/core/styles'
import SidebarProvider from '~/components/Sidebar'
import Header from '~/components/Header'
import Img from '~/components/layout/Img'
import Notifier from '~/components/Notifier'
import AlertLogo from './assets/alert.svg'
import CheckLogo from './assets/check.svg'
import ErrorLogo from './assets/error.svg'
@ -72,6 +73,7 @@ const PageFrame = ({ children, classes }: Props) => (
info: '',
}}
>
<Notifier />
<SidebarProvider>
<Header />
{children}