web: add error reducer and info toast notification
This change adds a new error reducer to manage error from API calls. The info actions retries failed info request after 5 seconds. Change-Id: Ieb2b66a2847650788d9bf68080ab208855941f24
This commit is contained in:
parent
17144c2a46
commit
f312f68ec6
|
@ -8,7 +8,9 @@
|
|||
"private": true,
|
||||
"dependencies": {
|
||||
"axios": "^0.18.0",
|
||||
"immutability-helper": "^2.8.1",
|
||||
"lodash": "^4.17.10",
|
||||
"moment": "^2.22.2",
|
||||
"patternfly-react": "^2.13.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.4.2",
|
||||
|
|
|
@ -25,16 +25,21 @@ import {
|
|||
Masthead,
|
||||
Notification,
|
||||
NotificationDrawer,
|
||||
TimedToastNotification,
|
||||
ToastNotificationList,
|
||||
} from 'patternfly-react'
|
||||
import * as moment from 'moment'
|
||||
|
||||
import logo from './images/logo.png'
|
||||
import { routes } from './routes'
|
||||
import { fetchConfigErrorsAction } from './actions/configErrors'
|
||||
import { setTenantAction } from './actions/tenant'
|
||||
import { clearError } from './actions/errors'
|
||||
|
||||
|
||||
class App extends React.Component {
|
||||
static propTypes = {
|
||||
errors: PropTypes.array,
|
||||
configErrors: PropTypes.array,
|
||||
info: PropTypes.object,
|
||||
tenant: PropTypes.object,
|
||||
|
@ -149,6 +154,25 @@ class App extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
renderErrors = (errors) => {
|
||||
return (
|
||||
<ToastNotificationList>
|
||||
{errors.map(error => (
|
||||
<TimedToastNotification
|
||||
key={error.id}
|
||||
type='error'
|
||||
onDismiss={() => {this.props.dispatch(clearError(error.id))}}
|
||||
>
|
||||
<span title={moment(error.date).format()}>
|
||||
<strong>{error.text}</strong> ({error.status})
|
||||
{error.url}
|
||||
</span>
|
||||
</TimedToastNotification>
|
||||
))}
|
||||
</ToastNotificationList>
|
||||
)
|
||||
}
|
||||
|
||||
renderConfigErrors = (configErrors) => {
|
||||
const { history } = this.props
|
||||
const errors = []
|
||||
|
@ -207,7 +231,7 @@ class App extends React.Component {
|
|||
|
||||
render() {
|
||||
const { menuCollapsed, showErrors } = this.state
|
||||
const { tenant, configErrors } = this.props
|
||||
const { errors, configErrors, tenant } = this.props
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
|
@ -252,6 +276,7 @@ class App extends React.Component {
|
|||
</div>
|
||||
)}
|
||||
</Masthead>
|
||||
{errors.length > 0 && this.renderErrors(errors)}
|
||||
<div className='container-fluid container-cards-pf'>
|
||||
{this.renderContent()}
|
||||
</div>
|
||||
|
@ -263,6 +288,7 @@ class App extends React.Component {
|
|||
// This connect the info state from the store to the info property of the App.
|
||||
export default withRouter(connect(
|
||||
state => ({
|
||||
errors: state.errors,
|
||||
configErrors: state.configErrors,
|
||||
info: state.info,
|
||||
tenant: state.tenant
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright 2018 Red Hat, Inc
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
export const ADD_ERROR = 'ADD_ERROR'
|
||||
export const CLEAR_ERROR = 'CLEAR_ERROR'
|
||||
export const CLEAR_ERRORS = 'CLEAR_ERRORS'
|
||||
|
||||
let errorId = 0
|
||||
|
||||
export const addError = error => ({
|
||||
type: ADD_ERROR,
|
||||
id: errorId++,
|
||||
error
|
||||
})
|
||||
|
||||
export const addApiError = error => (
|
||||
addError({
|
||||
url: error.request.responseURL,
|
||||
status: error.response.status,
|
||||
text: error.response.statusText,
|
||||
})
|
||||
)
|
||||
|
||||
export const clearError = id => ({
|
||||
type: CLEAR_ERROR,
|
||||
id
|
||||
})
|
||||
|
||||
export const clearErrors = () => ({
|
||||
type: CLEAR_ERRORS
|
||||
})
|
|
@ -36,7 +36,10 @@ const fetchInfo = () => dispatch => {
|
|||
dispatch(fetchInfoRequest())
|
||||
return API.fetchInfo()
|
||||
.then(response => dispatch(fetchInfoSuccess(response.data)))
|
||||
.catch(error => dispatch(fetchInfoFail(error)))
|
||||
.catch(error => {
|
||||
dispatch(fetchInfoFail(error))
|
||||
setTimeout(() => {dispatch(fetchInfo())}, 5000)
|
||||
})
|
||||
}
|
||||
|
||||
const shouldFetchInfo = state => {
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright 2018 Red Hat, Inc
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
import update from 'immutability-helper'
|
||||
|
||||
import {
|
||||
ADD_ERROR,
|
||||
CLEAR_ERROR,
|
||||
CLEAR_ERRORS,
|
||||
addApiError,
|
||||
} from '../actions/errors'
|
||||
|
||||
|
||||
export default (state = [], action) => {
|
||||
// Intercept API failure
|
||||
if (action.error && action.type.match(/.*_FETCH_FAIL$/)) {
|
||||
action = addApiError(action.error)
|
||||
}
|
||||
switch (action.type) {
|
||||
case ADD_ERROR:
|
||||
if (state.filter(error => (
|
||||
error.url === action.error.url &&
|
||||
error.status === action.error.status)).length > 0)
|
||||
return state
|
||||
action.error.id = action.id
|
||||
action.error.date = Date.now()
|
||||
return update(state, {$push: [action.error]})
|
||||
case CLEAR_ERROR:
|
||||
return update(state, {$splice: [[state.indexOf(
|
||||
state.filter(item => (item.id === action.id))[0]), 1]]})
|
||||
case CLEAR_ERRORS:
|
||||
return []
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
|
@ -15,12 +15,14 @@
|
|||
import { combineReducers } from 'redux'
|
||||
|
||||
import configErrors from './configErrors'
|
||||
import errors from './errors'
|
||||
import info from './info'
|
||||
import tenant from './tenant'
|
||||
|
||||
const reducers = {
|
||||
info,
|
||||
configErrors,
|
||||
errors,
|
||||
tenant,
|
||||
}
|
||||
|
||||
|
|
|
@ -3762,6 +3762,12 @@ ignore@^4.0.2:
|
|||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
|
||||
|
||||
immutability-helper@^2.8.1:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.yarnpkg.com/immutability-helper/-/immutability-helper-2.8.1.tgz#3c5ec05fcd83676bfae7146f319595243ad904f4"
|
||||
dependencies:
|
||||
invariant "^2.2.0"
|
||||
|
||||
import-lazy@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
|
||||
|
@ -3857,7 +3863,7 @@ interpret@^1.0.0:
|
|||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614"
|
||||
|
||||
invariant@^2.0.0, invariant@^2.1.0, invariant@^2.2.1, invariant@^2.2.2, invariant@^2.2.4:
|
||||
invariant@^2.0.0, invariant@^2.1.0, invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2, invariant@^2.2.4:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
|
||||
dependencies:
|
||||
|
@ -5027,7 +5033,7 @@ moment-timezone@^0.4.0, moment-timezone@^0.4.1:
|
|||
dependencies:
|
||||
moment ">= 2.6.0"
|
||||
|
||||
"moment@>= 2.6.0", moment@^2.10, moment@^2.19.1:
|
||||
"moment@>= 2.6.0", moment@^2.10, moment@^2.19.1, moment@^2.22.2:
|
||||
version "2.22.2"
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66"
|
||||
|
||||
|
|
Loading…
Reference in New Issue