Refactor publishNotification errors into errors middleware

pull/10616/head
Jared Scheib 2017-04-14 18:56:36 -07:00
parent 4385cc8df8
commit 277c877309
6 changed files with 27 additions and 46 deletions

View File

@ -4,9 +4,9 @@ import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
import {getSources} from 'shared/apis'
import {loadSources as loadSourcesAction} from 'shared/actions/sources'
import {showDatabases} from 'shared/apis/metaQuery'
import {publishNotification as publishNotificationAction} from 'shared/actions/notifications'
import {loadSources as loadSourcesAction} from 'shared/actions/sources'
import {errorThrown as errorThrownAction} from 'shared/actions/errors'
// Acts as a 'router middleware'. The main `App` component is responsible for
@ -25,7 +25,6 @@ const CheckSources = React.createClass({
pathname: PropTypes.string.isRequired,
}).isRequired,
sources: PropTypes.array.isRequired,
notify: PropTypes.func.isRequired,
errorThrown: PropTypes.func.isRequired,
loadSources: PropTypes.func.isRequired,
},
@ -37,21 +36,20 @@ const CheckSources = React.createClass({
},
async componentWillMount() {
const {loadSources, notify, errorThrown} = this.props
const {loadSources, errorThrown} = this.props
try {
const {data: {sources}} = await getSources()
loadSources(sources)
this.setState({isFetching: false})
} catch (error) {
errorThrown(error)
notify('error', 'Unable to connect to Chronograf server')
errorThrown(error, 'Unable to connect to Chronograf server')
this.setState({isFetching: false})
}
},
async componentWillUpdate(nextProps, nextState) {
const {router, location, params, notify, errorThrown, sources} = nextProps
const {router, location, params, errorThrown, sources} = nextProps
const {isFetching} = nextState
const source = sources.find((s) => s.id === params.sourceID)
const defaultSource = sources.find((s) => s.default === true)
@ -74,8 +72,7 @@ const CheckSources = React.createClass({
try {
await showDatabases(source.links.proxy)
} catch (error) {
errorThrown(error)
notify('error', 'Unable to connect to source')
errorThrown(error, 'Unable to connect to source')
}
}
},
@ -101,7 +98,6 @@ const mapStateToProps = ({sources}) => ({
const mapDispatchToProps = (dispatch) => ({
loadSources: bindActionCreators(loadSourcesAction, dispatch),
notify: bindActionCreators(publishNotificationAction, dispatch),
errorThrown: bindActionCreators(errorThrownAction, dispatch),
})

View File

@ -20,7 +20,6 @@ import {
killQuery as killQueryProxy,
} from 'shared/apis/metaQuery'
import {publishNotification} from 'shared/actions/notifications'
import {publishAutoDismissingNotification} from 'shared/dispatchers'
import {errorThrown} from 'shared/actions/errors'
@ -263,9 +262,8 @@ export const createUserAsync = (url, user) => async (dispatch) => {
dispatch(publishAutoDismissingNotification('success', 'User created successfully'))
dispatch(syncUser(user, data))
} catch (error) {
dispatch(errorThrown(error))
dispatch(errorThrown(error, `Failed to create user: ${error.data.message}`))
// undo optimistic update
dispatch(publishNotification('error', `Failed to create user: ${error.data.message}`))
setTimeout(() => dispatch(deleteUser(user)), REVERT_STATE_DELAY)
}
}
@ -276,9 +274,8 @@ export const createRoleAsync = (url, role) => async (dispatch) => {
dispatch(publishAutoDismissingNotification('success', 'Role created successfully'))
dispatch(syncRole(role, data))
} catch (error) {
dispatch(errorThrown(error))
dispatch(errorThrown(error, `Failed to create role: ${error.data.message}`))
// undo optimistic update
dispatch(publishNotification('error', `Failed to create role: ${error.data.message}`))
setTimeout(() => dispatch(deleteRole(role)), REVERT_STATE_DELAY)
}
}
@ -290,8 +287,7 @@ export const createDatabaseAsync = (url, database) => async (dispatch) => {
dispatch(publishAutoDismissingNotification('success', 'Database created successfully'))
} catch (error) {
dispatch(errorThrown(error))
// undo optimistic update
dispatch(publishNotification('error', `Failed to create database: ${error.data.message}`))
// undo optimistic upda, `Failed to create database: ${error.data.message}`te
setTimeout(() => dispatch(removeDatabase(database)), REVERT_STATE_DELAY)
}
}
@ -303,8 +299,7 @@ export const createRetentionPolicyAsync = (database, retentionPolicy) => async (
dispatch(syncRetentionPolicy(database, retentionPolicy, data))
} catch (error) {
dispatch(errorThrown(error))
// undo optimistic update
dispatch(publishNotification('error', `Failed to create retention policy: ${error.data.message}`))
// undo optimistic upda, `Failed to create retention policy: ${error.data.message}`te
setTimeout(() => dispatch(removeRetentionPolicy(database, retentionPolicy)), REVERT_STATE_DELAY)
}
}
@ -316,8 +311,7 @@ export const updateRetentionPolicyAsync = (database, retentionPolicy, updates) =
dispatch(publishAutoDismissingNotification('success', 'Retention policy updated successfully'))
dispatch(syncRetentionPolicy(database, retentionPolicy, data))
} catch (error) {
dispatch(errorThrown(error))
dispatch(publishNotification('error', `Failed to update retention policy: ${error.data.message}`))
dispatch(errorThrown(error, `Failed to update retention policy: ${error.data.message}`))
}
}
@ -340,8 +334,7 @@ export const deleteRoleAsync = (role) => async (dispatch) => {
await deleteRoleAJAX(role.links.self)
dispatch(publishAutoDismissingNotification('success', 'Role deleted'))
} catch (error) {
dispatch(errorThrown(error))
dispatch(publishNotification('error', `Failed to delete role: ${error.data.message}`))
dispatch(errorThrown(error, `Failed to delete role: ${error.data.message}`))
}
}
@ -351,8 +344,7 @@ export const deleteUserAsync = (user) => async (dispatch) => {
await deleteUserAJAX(user.links.self)
dispatch(publishAutoDismissingNotification('success', 'User deleted'))
} catch (error) {
dispatch(errorThrown(error))
dispatch(publishNotification('error', `Failed to delete user: ${error.data.message}`))
dispatch(errorThrown(error, `Failed to delete user: ${error.data.message}`))
}
}
@ -362,8 +354,7 @@ export const deleteDatabaseAsync = (database) => async (dispatch) => {
await deleteDatabaseAJAX(database.links.self)
dispatch(publishAutoDismissingNotification('success', 'Database deleted'))
} catch (error) {
dispatch(errorThrown(error))
dispatch(publishNotification('error', `Failed to delete database: ${error.data.message}`))
dispatch(errorThrown(error, `Failed to delete database: ${error.data.message}`))
}
}
@ -373,8 +364,7 @@ export const deleteRetentionPolicyAsync = (database, retentionPolicy) => async (
await deleteRetentionPolicyAJAX(retentionPolicy.links.self)
dispatch(publishAutoDismissingNotification('success', `Retention policy ${retentionPolicy.name} deleted`))
} catch (error) {
dispatch(errorThrown(error))
dispatch(publishNotification('error', `Failed to delete retentionPolicy: ${error.data.message}`))
dispatch(errorThrown(error, `Failed to delete retentionPolicy: ${error.data.message}`))
}
}
@ -384,8 +374,7 @@ export const updateRoleUsersAsync = (role, users) => async (dispatch) => {
dispatch(publishAutoDismissingNotification('success', 'Role users updated'))
dispatch(syncRole(role, data))
} catch (error) {
dispatch(errorThrown(error))
dispatch(publishNotification('error', `Failed to update role: ${error.data.message}`))
dispatch(errorThrown(error, `Failed to update role: ${error.data.message}`))
}
}
@ -395,8 +384,7 @@ export const updateRolePermissionsAsync = (role, permissions) => async (dispatch
dispatch(publishAutoDismissingNotification('success', 'Role permissions updated'))
dispatch(syncRole(role, data))
} catch (error) {
dispatch(errorThrown(error))
dispatch(publishNotification('error', `Failed to update role: ${error.data.message}`))
dispatch(errorThrown(error, `Failed to update role: ${error.data.message}`))
}
}
@ -406,8 +394,7 @@ export const updateUserPermissionsAsync = (user, permissions) => async (dispatch
dispatch(publishAutoDismissingNotification('success', 'User permissions updated'))
dispatch(syncUser(user, data))
} catch (error) {
dispatch(errorThrown(error))
dispatch(publishNotification('error', `Failed to update user: ${error.data.message}`))
dispatch(errorThrown(error, `Failed to update user: ${error.data.message}`))
}
}
@ -417,8 +404,7 @@ export const updateUserRolesAsync = (user, roles) => async (dispatch) => {
dispatch(publishAutoDismissingNotification('success', 'User roles updated'))
dispatch(syncUser(user, data))
} catch (error) {
dispatch(errorThrown(error))
dispatch(publishNotification('error', `Failed to update user: ${error.data.message}`))
dispatch(errorThrown(error, `Failed to update user: ${error.data.message}`))
}
}
@ -428,7 +414,6 @@ export const updateUserPasswordAsync = (user, password) => async (dispatch) => {
dispatch(publishAutoDismissingNotification('success', 'User password updated'))
dispatch(syncUser(user, data))
} catch (error) {
dispatch(errorThrown(error))
dispatch(publishNotification('error', `Failed to update user: ${error.data.message}`))
dispatch(errorThrown(error, `Failed to update user: ${error.data.message}`))
}
}

View File

@ -7,7 +7,6 @@ import {
deleteDashboardCell as deleteDashboardCellAJAX,
} from 'src/dashboards/apis'
import {publishNotification} from 'shared/actions/notifications'
import {publishAutoDismissingNotification} from 'shared/dispatchers'
import {errorThrown} from 'shared/actions/errors'
@ -149,9 +148,8 @@ export const deleteDashboardAsync = (dashboard) => async (dispatch) => {
await deleteDashboardAJAX(dashboard)
dispatch(publishAutoDismissingNotification('success', 'Dashboard deleted successfully.'))
} catch (error) {
dispatch(errorThrown(error))
dispatch(errorThrown(error, `Failed to delete dashboard: ${error.data.message}.`))
dispatch(deleteDashboardFailed(dashboard))
dispatch(publishNotification('error', `Failed to delete dashboard: ${error.data.message}.`))
}
}
@ -172,7 +170,6 @@ export const deleteDashboardCellAsync = (cell) => async (dispatch) => {
dispatch(deleteDashboardCell(cell))
} catch (error) {
dispatch(errorThrown(error))
console.error(error)
throw error
}
}

View File

@ -1,4 +1,5 @@
export const errorThrown = (error) => ({
export const errorThrown = (error, altText) => ({
type: 'ERROR_THROWN',
error,
altText,
})

View File

@ -43,7 +43,7 @@ export const fetchTimeSeriesAsync = async ({source, db, rp, query}, editQuerySta
const {data} = await proxy({source, db, rp, query: query.text})
return handleSuccess(data, query, editQueryStatus)
} catch (error) {
errorThrown(error) // use errorsMiddleware to catch 403s first, otherwise query --> config --> error.status will be error obj
errorThrown(error) // TODO: use errorsMiddleware to catch 403s first, otherwise query --> config --> error.status will be error obj
handleError(error, query, editQueryStatus)
throw error
}

View File

@ -9,7 +9,7 @@ let allowNotifications = true // eslint-disable-line
const errorsMiddleware = store => next => action => {
if (action.type === 'ERROR_THROWN') {
const {error, error: {status, auth}} = action
const {error, error: {status, auth}, altText} = action
console.error(error)
@ -29,6 +29,8 @@ const errorsMiddleware = store => next => action => {
} else {
store.dispatch(notify('error', 'Please login to use Chronograf.'))
}
} else if (altText) {
store.dispatch(notify('error', altText))
} else {
store.dispatch(notify('error', 'Cannot communicate with server.'))
}