Skip to content

Commit

Permalink
Error boundaries for panels
Browse files Browse the repository at this point in the history
We already use error boundaries in more tightly scoped parts of auspice
(e.g. surrounding the legend), presumably in response to specific
bugs/crashes observed therein. This adds a panel-specific error boundary
which surrounds each panel.
  • Loading branch information
jameshadfield committed Nov 12, 2024
1 parent e8337a8 commit d101449
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 14 deletions.
80 changes: 80 additions & 0 deletions src/components/errorBoundaries/panelErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React from "react";
import styled from "styled-components";

const Background = styled.div`
background: repeating-linear-gradient(
45deg,
transparent,
transparent 20px,
#f4d2ff 20px,
#f4d2ff 21px
);
margin: 10px 10px;
padding: 10px 10px;
border: 1px solid #f4d2ff;
display: inline-block;
position: relative;
`;

interface Props {
width: number;
height: number;
name: string;
}
interface State {
hasError: boolean;
errorMessage: string;
}

class PanelErrorBoundary extends React.Component<Props, State> {
constructor(props) {
super(props);
this.state = { hasError: false, errorMessage: ''};
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return {
hasError: true,
errorMessage: error instanceof Error ? error.message : "Unknown error (thrown value was not an instance of Error)",
};
}
override componentDidCatch(error, info) {
// You can also log the error to an error reporting service
console.error(error);
console.error(info);
}

override render() {
if (!this.state.hasError) return this.props.children;

/**
* We could add something like
* <button onClick={() => {this.setState({hasError: false})}}>You can try clicking here to re-render the panel</button>
* but it risks rendering an incorrect state so I'd prefer not to
*/

return (
<Background style={{width: this.props.width, height: this.props.height}}>
<h1 style={{fontSize: '3rem'}}>{`Error! Something's gone wrong within the ${this.props.name} panel`}</h1>

<p style={{fontSize: '1.8rem'}}>
{`Error message: "${this.state.errorMessage}"`}
</p>

<p style={{fontSize: '1.8rem'}}>
{'Please consider making a bug report either on '}
<a href="https://github.com/nextstrain/auspice/issues/new" target="_blank" rel="noreferrer noopener">GitHub</a>
{' or via '}
<a href="mailto:[email protected]" target="_blank" rel="noreferrer noopener">email</a>.
(The more information you can include the better - things such as steps to reproduce the bug, your browser version, the version of Auspice etc are incredibly helpful.)
</p>
<p style={{fontSize: '1.8rem'}}>
In the meantime you could try refreshing the page which may fix things in the short term.
</p>

</Background>
);
}
}

export default PanelErrorBoundary;
51 changes: 37 additions & 14 deletions src/components/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import ErrorBoundary from "../../util/errorBoundary";
import Spinner, { PanelSpinner } from "../framework/spinner";
import MainDisplayMarkdown from "../narrative/MainDisplayMarkdown";
import MobileNarrativeDisplay from "../narrative/MobileNarrativeDisplay";
import PanelErrorBoundary from "../errorBoundaries/panelErrorBoundary";

const Entropy = lazy(() => import("../entropy"));
const Frequencies = lazy(() => import("../frequencies"));
Expand Down Expand Up @@ -155,11 +156,17 @@ class Main extends React.Component {
}
{this.props.displayNarrative || this.props.showOnlyPanels ? null : <Info width={calcUsableWidth(availableWidth, 1)} />}
{this.props.panelsToDisplay.includes("tree") ?
<Tree
<PanelErrorBoundary
width={this.inGrid() ? grid.width : full.width}
height={this.inGrid() ? grid.height : full.height}
key={keyName}
/> :
name="tree"
>
<Tree
width={this.inGrid() ? grid.width : full.width}
height={this.inGrid() ? grid.height : full.height}
key={keyName}
/>
</PanelErrorBoundary> :
null
}
{this.props.panelsToDisplay.includes("measurements") ?
Expand All @@ -172,34 +179,50 @@ class Main extends React.Component {
/>
}
>
<Measurements
<PanelErrorBoundary
width={this.inGrid() ? grid.width : full.width}
height={this.inGrid() ? grid.height : full.height}
key={keyName+"_measurements"}
showLegend={this.shouldShowMeasurementsLegend()}
/>
name="measurements"
>
<Measurements
width={this.inGrid() ? grid.width : full.width}
height={this.inGrid() ? grid.height : full.height}
key={keyName+"_measurements"}
showLegend={this.shouldShowMeasurementsLegend()}
/>
</PanelErrorBoundary>
</Suspense> :
null
}
{this.props.panelsToDisplay.includes("map") ?
<Map
<PanelErrorBoundary
width={this.shouldMapBeInGrid() ? grid.width : full.width}
height={this.shouldMapBeInGrid() ? grid.height : full.height}
key={keyName+"_map"}
justGotNewDatasetRenderNewMap={false}
legend={this.shouldShowMapLegend()}
/> :
name="map"
>
<Map
width={this.shouldMapBeInGrid() ? grid.width : full.width}
height={this.shouldMapBeInGrid() ? grid.height : full.height}
key={keyName+"_map"}
justGotNewDatasetRenderNewMap={false}
legend={this.shouldShowMapLegend()}
/>
</PanelErrorBoundary> :
null
}
{this.props.panelsToDisplay.includes("entropy") ?
(<Suspense fallback={null}>
<Entropy width={chartEntropy.width} height={chartEntropy.height} key={keyName+"_entropy"}/>
<PanelErrorBoundary width={chartEntropy.width} height={chartEntropy.height} name="entropy">
<Entropy width={chartEntropy.width} height={chartEntropy.height} key={keyName+"_entropy"}/>
</PanelErrorBoundary>
</Suspense>) :
null
}
{this.props.panelsToDisplay.includes("frequencies") && this.props.frequenciesLoaded ?
(<Suspense fallback={null}>
<Frequencies width={chartFrequencies.width} height={chartFrequencies.height} key={keyName+"_frequencies"}/>
<PanelErrorBoundary width={chartFrequencies.width} height={chartFrequencies.height} name="frequencies">
<Frequencies width={chartFrequencies.width} height={chartFrequencies.height} key={keyName+"_frequencies"}/>
</PanelErrorBoundary>
</Suspense>) :
null
}
Expand Down

0 comments on commit d101449

Please sign in to comment.