mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2026-03-13 02:53:47 +00:00
Merge pull request #117 from acelaya/feature/error-handler
Feature/error handler
This commit is contained in:
@@ -26,6 +26,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||||||
|
|
||||||
* [#103](https://github.com/shlinkio/shlink-web-client/issues/103) Fixed visits page getting freezed when loading large amounts of visits.
|
* [#103](https://github.com/shlinkio/shlink-web-client/issues/103) Fixed visits page getting freezed when loading large amounts of visits.
|
||||||
* [#111](https://github.com/shlinkio/shlink-web-client/issues/111) Fixed crash when trying to load a map modal with only one location.
|
* [#111](https://github.com/shlinkio/shlink-web-client/issues/111) Fixed crash when trying to load a map modal with only one location.
|
||||||
|
* [#115](https://github.com/shlinkio/shlink-web-client/issues/115) Created `ErrorHandler` component which will prevent crashes in app to make it unusable.
|
||||||
|
|
||||||
|
|
||||||
## 2.0.1 - 2019-03-03
|
## 2.0.1 - 2019-03-03
|
||||||
|
|||||||
36
src/common/ErrorHandler.js
Normal file
36
src/common/ErrorHandler.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import * as PropTypes from 'prop-types';
|
||||||
|
import './ErrorHandler.scss';
|
||||||
|
import { Button } from 'reactstrap';
|
||||||
|
|
||||||
|
const ErrorHandler = ({ location }) => class ErrorHandler extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = { hasError: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
static getDerivedStateFromError() {
|
||||||
|
return { hasError: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.state.hasError) {
|
||||||
|
return (
|
||||||
|
<div className="error-handler">
|
||||||
|
<h1>Oops! This is awkward :S</h1>
|
||||||
|
<p>It seems that something went wrong. Try refreshing the page or just click this button.</p>
|
||||||
|
<br />
|
||||||
|
<Button outline color="primary" onClick={() => location.reload()}>Take me back</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.props.children;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ErrorHandler;
|
||||||
9
src/common/ErrorHandler.scss
Normal file
9
src/common/ErrorHandler.scss
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
@import '../utils/mixins/vertical-align.scss';
|
||||||
|
|
||||||
|
.error-handler {
|
||||||
|
@include vertical-align();
|
||||||
|
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import MainHeader from '../MainHeader';
|
|||||||
import Home from '../Home';
|
import Home from '../Home';
|
||||||
import MenuLayout from '../MenuLayout';
|
import MenuLayout from '../MenuLayout';
|
||||||
import AsideMenu from '../AsideMenu';
|
import AsideMenu from '../AsideMenu';
|
||||||
|
import ErrorHandler from '../ErrorHandler';
|
||||||
|
|
||||||
const provideServices = (bottle, connect, withRouter) => {
|
const provideServices = (bottle, connect, withRouter) => {
|
||||||
bottle.constant('window', global.window);
|
bottle.constant('window', global.window);
|
||||||
@@ -29,6 +30,8 @@ const provideServices = (bottle, connect, withRouter) => {
|
|||||||
bottle.decorator('MenuLayout', withRouter);
|
bottle.decorator('MenuLayout', withRouter);
|
||||||
|
|
||||||
bottle.serviceFactory('AsideMenu', AsideMenu, 'DeleteServerButton');
|
bottle.serviceFactory('AsideMenu', AsideMenu, 'DeleteServerButton');
|
||||||
|
|
||||||
|
bottle.serviceFactory('ErrorHandler', ErrorHandler, 'window');
|
||||||
};
|
};
|
||||||
|
|
||||||
export default provideServices;
|
export default provideServices;
|
||||||
|
|||||||
10
src/index.js
10
src/index.js
@@ -16,14 +16,16 @@ import './index.scss';
|
|||||||
// This overwrites icons used for leaflet maps, fixing some issues caused by webpack while processing the CSS
|
// This overwrites icons used for leaflet maps, fixing some issues caused by webpack while processing the CSS
|
||||||
fixLeafletIcons();
|
fixLeafletIcons();
|
||||||
|
|
||||||
const { App, ScrollToTop } = container;
|
const { App, ScrollToTop, ErrorHandler } = container;
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<BrowserRouter basename={homepage}>
|
<BrowserRouter basename={homepage}>
|
||||||
<ScrollToTop>
|
<ErrorHandler>
|
||||||
<App />
|
<ScrollToTop>
|
||||||
</ScrollToTop>
|
<App />
|
||||||
|
</ScrollToTop>
|
||||||
|
</ErrorHandler>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
</Provider>,
|
</Provider>,
|
||||||
document.getElementById('root')
|
document.getElementById('root')
|
||||||
|
|||||||
36
test/common/ErrorHandler.test.js
Normal file
36
test/common/ErrorHandler.test.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
import { Button } from 'reactstrap';
|
||||||
|
import createErrorHandler from '../../src/common/ErrorHandler';
|
||||||
|
|
||||||
|
describe('<ErrorHandler />', () => {
|
||||||
|
const window = {
|
||||||
|
location: {
|
||||||
|
reload: jest.fn(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let wrapper;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const ErrorHandler = createErrorHandler(window);
|
||||||
|
|
||||||
|
wrapper = shallow(<ErrorHandler children={<span>Foo</span>} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => wrapper.unmount());
|
||||||
|
|
||||||
|
it('renders children when no error has occurred', () => {
|
||||||
|
expect(wrapper.text()).toEqual('Foo');
|
||||||
|
expect(wrapper.find(Button)).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders error page when error has occurred', () => {
|
||||||
|
wrapper.setState({ hasError: true });
|
||||||
|
|
||||||
|
expect(wrapper.text()).toContain('Oops! This is awkward :S');
|
||||||
|
expect(wrapper.text()).toContain(
|
||||||
|
'It seems that something went wrong. Try refreshing the page or just click this button.'
|
||||||
|
);
|
||||||
|
expect(wrapper.find(Button)).toHaveLength(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user