Files
karma/ui/src/ErrorBoundary.js
Łukasz Mierzwa bfa021aabf fix(ui): don't let multiple exceptions set multiple timers
As reported via #77 countdown timer might be updated more often than 1s since we don't protect against multiple setInterval() calls, add a check
2018-09-28 00:02:10 +01:00

79 lines
2.1 KiB
JavaScript

import React, { Component } from "react";
import PropTypes from "prop-types";
import * as Sentry from "@sentry/browser";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons/faExclamationCircle";
const InternalError = ({ message, secondsLeft }) => (
<div className="jumbotron text-center bg-primary my-4">
<div className="container-fluid">
<h1 className="display-1 my-5">
<FontAwesomeIcon
className="text-danger mr-2"
icon={faExclamationCircle}
/>
<span className="text-muted">Internal error</span>
</h1>
<p className="lead text-muted">{message}</p>
<p className="text-muted">
This page will auto refresh in {secondsLeft}s
</p>
</div>
</div>
);
InternalError.propTypes = {
message: PropTypes.node.isRequired,
secondsLeft: PropTypes.number.isRequired
};
class ErrorBoundary extends Component {
static propTypes = {
children: PropTypes.any
};
constructor(props) {
super(props);
this.timer = null;
this.state = { cachedError: null, reloadSeconds: 60 };
}
reloadApp = () => {
if (this.state.reloadSeconds <= 1) {
window.location.reload();
} else {
this.setState({ reloadSeconds: this.state.reloadSeconds - 1 });
}
};
componentDidCatch(error, errorInfo) {
this.setState({ cachedError: error });
Sentry.configureScope(scope => {
Object.keys(errorInfo).forEach(key => {
scope.setExtra(key, errorInfo[key]);
});
});
Sentry.captureException(error);
// reload after 60s, this is to fix wall monitors automatically
// but only if the timer isn't set yet
if (this.timer === null) {
this.timer = setInterval(this.reloadApp, 1000);
}
}
render() {
if (this.state.cachedError !== null) {
return (
<InternalError
message={this.state.cachedError.toString()}
secondsLeft={this.state.reloadSeconds}
/>
);
}
return this.props.children;
}
}
export { ErrorBoundary };