Add reducer to keep track of dismissed notifications. So that You're Only Warned Once.

pull/10616/head
Hunter Trujillo 2017-12-06 09:28:10 -07:00
parent e5afdc3c23
commit 9b7c4dd1bf
6 changed files with 48 additions and 13 deletions

View File

@ -44,7 +44,8 @@ class TickscriptPage extends Component {
})
notify(
'warning',
'Could not use logging, requires Kapacitor version 1.4'
'Could not use logging, requires Kapacitor version 1.4',
{once: true}
)
return
}

View File

@ -52,6 +52,7 @@ export const saveToLocalStorage = ({
timeRange,
dataExplorer,
dashTimeV1: {ranges},
dismissedNotifications,
}) => {
try {
const appPersisted = Object.assign({}, {app: {persisted}})
@ -66,6 +67,7 @@ export const saveToLocalStorage = ({
dataExplorer,
VERSION, // eslint-disable-line no-undef
dashTimeV1,
dismissedNotifications,
})
)
} catch (err) {

View File

@ -1,4 +1,4 @@
export function publishNotification(type, message) {
export function publishNotification(type, message, options = {once: false}) {
// this validator is purely for development purposes. It might make sense to move this to a middleware.
const validTypes = ['error', 'success', 'warning']
if (!validTypes.includes(type) || message === undefined) {
@ -10,6 +10,7 @@ export function publishNotification(type, message) {
payload: {
type,
message,
once: options.once,
},
}
}

View File

@ -4,6 +4,8 @@ import {withRouter} from 'react-router'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
import {getNotificationID} from 'src/shared/reducers/notifications'
import {
publishNotification as publishNotificationAction,
dismissNotification as dismissNotificationAction,
@ -25,7 +27,10 @@ class Notifications extends Component {
}
renderNotification(type, message) {
if (!message) {
const isDismissed = this.props.dismissedNotifications[
getNotificationID(message, type)
]
if (!message || isDismissed) {
return null
}
const cls = classnames('alert', {
@ -86,10 +91,12 @@ Notifications.propTypes = {
error: string,
warning: string,
}),
dismissedNotifications: shape({}),
}
const mapStateToProps = ({notifications}) => ({
const mapStateToProps = ({notifications, dismissedNotifications}) => ({
notifications,
dismissedNotifications,
})
const mapDispatchToProps = dispatch => ({

View File

@ -2,7 +2,7 @@ import app from './app'
import auth from './auth'
import errors from './errors'
import links from './links'
import notifications from './notifications'
import {notifications, dismissedNotifications} from './notifications'
import sources from './sources'
export default {
@ -11,5 +11,6 @@ export default {
errors,
links,
notifications,
dismissedNotifications,
sources,
}

View File

@ -1,11 +1,7 @@
import u from 'updeep'
import _ from 'lodash'
function getInitialState() {
return {}
}
const initialState = getInitialState()
const notificationsReducer = (state = initialState, action) => {
export const notifications = (state = {}, action) => {
switch (action.type) {
case 'NOTIFICATION_RECEIVED': {
const {type, message} = action.payload
@ -16,11 +12,38 @@ const notificationsReducer = (state = initialState, action) => {
return u(u.omit(type), state)
}
case 'ALL_NOTIFICATIONS_DISMISSED': {
return getInitialState()
// Reset to initial state
return {}
}
}
return state
}
export default notificationsReducer
export const getNotificationID = (message, type) => _.snakeCase(message) + type
export const dismissedNotifications = (state = {}, action) => {
switch (action.type) {
case 'NOTIFICATION_RECEIVED': {
const {type, message, once} = action.payload
if (once) {
// Create a message ID in a deterministic way, also with its type
const messageID = getNotificationID(message, type)
if (state[messageID]) {
// Message action called with once option but we've already seen it
return state
}
// Message action called with once option and it's not present on
// the persisted state
return {
...state,
[messageID]: true,
}
}
// Message action not called with once option
return state
}
}
return state
}