add top error boundary & reset localStorage on error (#493)
* add top error boundary & reset localStorage on error * add issue tracker details and link * add pointer cursor to buttons * Update src/bug-issue-template.js Co-Authored-By: Lipis <lipiridis@gmail.com> * Update src/styles.scss Co-Authored-By: Lipis <lipiridis@gmail.com> * Update src/bug-issue-template.js Co-Authored-By: Lipis <lipiridis@gmail.com> * use open-color colors * use Cascadia font Co-authored-by: Lipis <lipiridis@gmail.com>
This commit is contained in:
parent
885b9c1483
commit
20cf1078fc
13
src/bug-issue-template.js
Normal file
13
src/bug-issue-template.js
Normal file
@ -0,0 +1,13 @@
|
||||
export default `
|
||||
### Stack strace
|
||||
|
||||
\`\`\`
|
||||
// paste stack trace here
|
||||
\`\`\`
|
||||
|
||||
### localStorage
|
||||
|
||||
\`\`\`
|
||||
// paste localStorage content here (if it doesn't contain sensitive data)
|
||||
\`\`\`
|
||||
`;
|
@ -1371,4 +1371,100 @@ export class App extends React.Component<any, AppState> {
|
||||
const AppWithTrans = withTranslation()(App);
|
||||
|
||||
const rootElement = document.getElementById("root");
|
||||
ReactDOM.render(<AppWithTrans />, rootElement);
|
||||
|
||||
class TopErrorBoundary extends React.Component {
|
||||
state = { hasError: false, stack: "", localStorage: "" };
|
||||
|
||||
static getDerivedStateFromError(error: any) {
|
||||
console.error(error);
|
||||
return {
|
||||
hasError: true,
|
||||
localStorage: JSON.stringify({ ...localStorage }),
|
||||
stack: error.stack
|
||||
};
|
||||
}
|
||||
|
||||
private selectTextArea(event: React.MouseEvent<HTMLTextAreaElement>) {
|
||||
(event.target as HTMLTextAreaElement).select();
|
||||
}
|
||||
|
||||
private async createGithubIssue() {
|
||||
let body = "";
|
||||
try {
|
||||
const templateStr = (await import("./bug-issue-template")).default;
|
||||
if (typeof templateStr === "string") {
|
||||
body = encodeURIComponent(templateStr);
|
||||
}
|
||||
} catch {}
|
||||
|
||||
window.open(
|
||||
`https://github.com/excalidraw/excalidraw/issues/new?body=${body}`
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
return (
|
||||
<div className="ErrorSplash">
|
||||
<div className="ErrorSplash-messageContainer">
|
||||
<div className="ErrorSplash-paragraph bigger">
|
||||
Encountered an error. Please{" "}
|
||||
<button onClick={() => window.location.reload()}>
|
||||
reload the page
|
||||
</button>
|
||||
.
|
||||
</div>
|
||||
<div className="ErrorSplash-paragraph">
|
||||
If reloading doesn't work. Try{" "}
|
||||
<button
|
||||
onClick={() => {
|
||||
localStorage.clear();
|
||||
window.location.reload();
|
||||
}}
|
||||
>
|
||||
clearing the canvas
|
||||
</button>
|
||||
.<br />
|
||||
<div className="smaller">
|
||||
(This will unfortunately result in loss of work.)
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="ErrorSplash-paragraph">
|
||||
Before doing so, we'd appreciate if you opened an issue on our{" "}
|
||||
<button onClick={this.createGithubIssue}>bug tracker</button>.
|
||||
Please include the following error stack trace & localStorage
|
||||
content (provided it's not private):
|
||||
</div>
|
||||
<div className="ErrorSplash-paragraph">
|
||||
<div className="ErrorSplash-details">
|
||||
<label>Error stack trace:</label>
|
||||
<textarea
|
||||
rows={10}
|
||||
onClick={this.selectTextArea}
|
||||
defaultValue={this.state.stack}
|
||||
/>
|
||||
<label>LocalStorage content:</label>
|
||||
<textarea
|
||||
rows={5}
|
||||
onClick={this.selectTextArea}
|
||||
defaultValue={this.state.localStorage}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<TopErrorBoundary>
|
||||
<AppWithTrans />
|
||||
</TopErrorBoundary>,
|
||||
rootElement
|
||||
);
|
||||
|
@ -73,6 +73,8 @@ button {
|
||||
padding: 0.25rem;
|
||||
outline: transparent;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 2px #a5d8ff;
|
||||
}
|
||||
@ -133,3 +135,51 @@ button {
|
||||
.App-right-menu {
|
||||
width: 13.75rem;
|
||||
}
|
||||
|
||||
.ErrorSplash {
|
||||
min-height: 100vh;
|
||||
padding: 20px 0;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.ErrorSplash-messageContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
padding: 40px;
|
||||
background-color: #fff5f5;
|
||||
border: 3px solid #c92a2a;
|
||||
}
|
||||
|
||||
.ErrorSplash-paragraph {
|
||||
margin: 15px 0;
|
||||
text-align: center;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.bigger,
|
||||
.bigger button {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
.smaller,
|
||||
.smaller button {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.ErrorSplash-details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
margin: 10px 0;
|
||||
font-family: "Cascadia";
|
||||
font-size: 0.8em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user