Skip to content

Commit

Permalink
feat(errors) add error boundaries
Browse files Browse the repository at this point in the history
Signed-off-by: David Edler <david.edler@canonical.com>
  • Loading branch information
edlerd committed Jan 5, 2024
1 parent 9534445 commit ad397c3
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 18 deletions.
41 changes: 23 additions & 18 deletions src/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,34 @@ import { InstanceLoadingProvider } from "context/instanceLoading";
import { ProjectProvider } from "context/project";
import Events from "pages/instances/Events";
import App from "./App";
import ErrorBoundary from "components/ErrorBoundary";

const queryClient = new QueryClient();

const Root: FC = () => {
return (
<NotificationProvider>
<QueryClientProvider client={queryClient}>
<AuthProvider>
<ProjectProvider>
<InstanceLoadingProvider>
<EventQueueProvider>
<div className="l-application" role="presentation">
<Navigation />
<App />
<Panels />
<Events />
</div>
</EventQueueProvider>
</InstanceLoadingProvider>
</ProjectProvider>
</AuthProvider>
</QueryClientProvider>
</NotificationProvider>
<ErrorBoundary>
<NotificationProvider>
<QueryClientProvider client={queryClient}>
<AuthProvider>
<ProjectProvider>
<InstanceLoadingProvider>
<EventQueueProvider>
<div className="l-application" role="presentation">
<Navigation />
<ErrorBoundary>
<App />
<Panels />
<Events />
</ErrorBoundary>
</div>
</EventQueueProvider>
</InstanceLoadingProvider>
</ProjectProvider>
</AuthProvider>
</QueryClientProvider>
</NotificationProvider>
</ErrorBoundary>
);
};

Expand Down
77 changes: 77 additions & 0 deletions src/components/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React from "react";
import {
CodeSnippet,
CodeSnippetBlockAppearance,
Notification,
Strip,
} from "@canonical/react-components";
import type { PropsWithChildren } from "react";
import { Component } from "react";

type Props = PropsWithChildren;

type State = {
error?: Error;
hasError: boolean;
};

export default class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}

static getDerivedStateFromError(error: Error) {
return {
hasError: true,
error,
};
}

render() {
const { error, hasError } = this.state;
const { children } = this.props;
const body = encodeURIComponent(
`\`\`\`\n${error?.stack ?? "No stack track"}\n\`\`\``,
);
const url = `https://github.com/canonical/lxd-ui/issues/new?labels=bug&title=Error%20report&body=${body}`;
if (hasError) {
return (
<Strip>
<Notification severity="negative" title="Error">
Something has gone wrong. If this issue persists,{" "}
<a href={url} rel="noopener noreferrer" target="_blank">
please raise an issue on GitHub.
</a>
</Notification>
<CodeSnippet
blocks={[
...(error?.message
? [
{
title: "Error",
appearance: CodeSnippetBlockAppearance.NUMBERED,
wrapLines: true,
code: error.message,
},
]
: []),
...(error?.stack
? [
{
title: "Stack trace",
appearance: CodeSnippetBlockAppearance.NUMBERED,
wrapLines: true,
code: error.stack,
},
]
: []),
]}
/>
</Strip>
);
}

return <>{children}</>;
}
}

0 comments on commit ad397c3

Please sign in to comment.