diff --git a/imports/startup/client/ravenLogger.js b/imports/startup/client/ravenLogger.js index 6b69209..509121a 100644 --- a/imports/startup/client/ravenLogger.js +++ b/imports/startup/client/ravenLogger.js @@ -1,13 +1,13 @@ import RavenLogger from 'meteor/flowkey:raven'; import { Meteor } from 'meteor/meteor'; -if (Meteor.isProduction) { - var ravenOptions = {}; +const ravenOptions = {}; - export const ravenLogger = new RavenLogger({ - publicDSN: Meteor.settings.public.sentryPublicDSN, // will be used on the client - privateDSN: Meteor.settings.sentryPrivateDSN, // will be used on the server - shouldCatchConsoleError: true, // default - trackUser: false, // default - }, ravenOptions); -} +const ravenLogger = new RavenLogger({ + publicDSN: Meteor.settings.public.sentryPublicDSN, // will be used on the client + privateDSN: Meteor.settings.sentryPrivateDSN, // will be used on the server + shouldCatchConsoleError: true, // default + trackUser: false // default +}, ravenOptions); + +export default ravenLogger; diff --git a/imports/ui/components/ErrorBoundary/ErrorBoundary.js b/imports/ui/components/ErrorBoundary/ErrorBoundary.js new file mode 100644 index 0000000..542894f --- /dev/null +++ b/imports/ui/components/ErrorBoundary/ErrorBoundary.js @@ -0,0 +1,59 @@ +/* eslint-disable react/jsx-indent-props */ +/* eslint-disable import/no-absolute-path */ +/* eslint-disable import/no-absolute-path */ + +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { translate } from 'react-i18next'; +import { Row, Col } from 'react-bootstrap'; +import { withTracker } from 'meteor/react-meteor-data'; +import ravenLogger from '/imports/startup/client/ravenLogger'; +import './ErrorBoundary.scss'; + +// https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html +class ErrorBoundary extends Component { + constructor(props) { + super(props); + this.t = props.t; + this.state = { hasError: false }; + } + + componentDidCatch(error, info) { + // Display fallback UI + this.setState({ hasError: true }); + // You can also log the error to an error reporting service + ravenLogger.log(error); + ravenLogger.log(info); + } + + render() { + if (this.state.hasError) { + // You can render any custom fallback UI + return ( +
+ + +

{this.t('AppNameFull')}

+

{this.t('general-error-title')}

+ + {this.t('general-error-description')} + + +
+
+ ); + } + return this.props.children; + } +} + +ErrorBoundary.propTypes = { + t: PropTypes.func.isRequired +}; + +ErrorBoundary.defaultProps = { +}; + +export default translate([], { wait: true })(withTracker(props => ({ + // props.something +}))(ErrorBoundary)); diff --git a/imports/ui/components/ErrorBoundary/ErrorBoundary.scss b/imports/ui/components/ErrorBoundary/ErrorBoundary.scss new file mode 100644 index 0000000..9ced77e --- /dev/null +++ b/imports/ui/components/ErrorBoundary/ErrorBoundary.scss @@ -0,0 +1,10 @@ +.error-boundary { + background-image: url('/error-background.png'); + height: 100%; + min-height: 55vh; + margin-top: 40px; +} + +.error-boundary > div > div > h4 { + line-height: 1.5em; +} diff --git a/imports/ui/layouts/App/App.js b/imports/ui/layouts/App/App.js index a456841..8ff8489 100644 --- a/imports/ui/layouts/App/App.js +++ b/imports/ui/layouts/App/App.js @@ -43,6 +43,7 @@ import Privacy from '../../pages/Privacy/Privacy'; import License from '../../pages/License/License'; import Credits from '../../pages/Credits/Credits'; import ReSendEmail from '../../components/ReSendEmail/ReSendEmail'; +import ErrorBoundary from '../../components/ErrorBoundary/ErrorBoundary'; import history from '../../components/History/History'; import '../../components/NotificationsObserver/NotificationsObserver'; import FiresMap from '../../pages/FiresMap/FiresMap'; @@ -53,56 +54,60 @@ import './App.scss'; const App = props => ( /* https://react.i18next.com/components/i18nextprovider.html */ - - { !props.loading ? -
- - - {i18n.t('AppName')} - - - - - - - - {/* - - - - */} - - - - - - - - - - - - - - {/* } /> */} + + + { !props.loading ? +
+ + + {i18n.t('AppName')} + + + + - - - - - - - - - - -
- - {props.i18nReady.get() && - - } -
: ''} -
+ + + + {/* + + + + */} + + + + + + + + + + + + + + {/* } /> */} + + + + + + + + + + + + +
: ''} +
+
); diff --git a/public/error-background.png b/public/error-background.png new file mode 100644 index 0000000..2713a7e Binary files /dev/null and b/public/error-background.png differ diff --git a/public/locales/es/common.json b/public/locales/es/common.json index e03e25c..0848b4b 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -222,6 +222,8 @@ "Fuego notificado por uno de nuestros usuarios/as <1>": "Fuego notificado por uno de nuestros usuarios/as <1>", "No recibirás notificaciones de fuegos en este equipo, solo por correo": "No recibirás notificaciones de fuegos en este equipo, solo por correo", "not-found": "Upppps: Esta página no existe", + "general-error-title": "Upppps: Algo ha ido mal", + "general-error-description": "Estamos investigando el problema, vuelve a intentarlo en un rato", "Más información sobre este fuego": "Más información sobre este fuego", "Última actualización, {{when}}": "Última actualización, {{when}}", "termsAccept": "Acepto las <1>condiciones de servicio de este sitio",