From 277c8773098fe8829faf30349c47660dfd57306f Mon Sep 17 00:00:00 2001 From: Jared Scheib Date: Fri, 14 Apr 2017 18:56:36 -0700 Subject: [PATCH] Refactor publishNotification errors into errors middleware --- ui/src/CheckSources.js | 16 ++++------- ui/src/admin/actions/index.js | 43 ++++++++++------------------- ui/src/dashboards/actions/index.js | 5 +--- ui/src/shared/actions/errors.js | 3 +- ui/src/shared/actions/timeSeries.js | 2 +- ui/src/shared/middleware/errors.js | 4 ++- 6 files changed, 27 insertions(+), 46 deletions(-) diff --git a/ui/src/CheckSources.js b/ui/src/CheckSources.js index 80bf503de8..4ae15ac9e4 100644 --- a/ui/src/CheckSources.js +++ b/ui/src/CheckSources.js @@ -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), }) diff --git a/ui/src/admin/actions/index.js b/ui/src/admin/actions/index.js index 034a99d859..280039c192 100644 --- a/ui/src/admin/actions/index.js +++ b/ui/src/admin/actions/index.js @@ -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}`)) } } diff --git a/ui/src/dashboards/actions/index.js b/ui/src/dashboards/actions/index.js index e4e780b6ff..355c398d32 100644 --- a/ui/src/dashboards/actions/index.js +++ b/ui/src/dashboards/actions/index.js @@ -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 } } diff --git a/ui/src/shared/actions/errors.js b/ui/src/shared/actions/errors.js index ebaa2aaef6..3a522d34ef 100644 --- a/ui/src/shared/actions/errors.js +++ b/ui/src/shared/actions/errors.js @@ -1,4 +1,5 @@ -export const errorThrown = (error) => ({ +export const errorThrown = (error, altText) => ({ type: 'ERROR_THROWN', error, + altText, }) diff --git a/ui/src/shared/actions/timeSeries.js b/ui/src/shared/actions/timeSeries.js index ad1e93aebe..da9fc27a45 100644 --- a/ui/src/shared/actions/timeSeries.js +++ b/ui/src/shared/actions/timeSeries.js @@ -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 } diff --git a/ui/src/shared/middleware/errors.js b/ui/src/shared/middleware/errors.js index 1909b8634e..337ce3b523 100644 --- a/ui/src/shared/middleware/errors.js +++ b/ui/src/shared/middleware/errors.js @@ -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.')) }