feat: error page

This commit is contained in:
EdwinWong 2024-01-19 03:46:24 +08:00
parent 770acfcedf
commit 3644e5044c
3 changed files with 110 additions and 7 deletions

View File

@ -0,0 +1,51 @@
"use client";
import { Button } from "@/components/ui/button";
import {
Card,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
// Error components must be Client Components
import { useEffect } from "react";
export default function Error({
error,
reset,
}: {
error?: Error & { digest?: string };
reset?: () => void;
}) {
useEffect(() => {
// Log the error to an error reporting service
console.log(error?.message);
}, [error]);
return (
<div className="border rounded-2xl flex flex-col w-full gap-20 justify-center items-center">
<Card className="max-w-2xl">
<CardHeader>
<CardTitle>
<div className="text-2xl">Something went wrong!</div>
</CardTitle>
<CardDescription
suppressHydrationWarning={true}
className="flex flex-col gap-4"
>
<div className="text-lg">{error?.message}</div>
<Button
className="w-full"
onClick={
// Attempt to recover by trying to re-render the segment
() => reset?.()
}
>
Try again
</Button>
</CardDescription>
</CardHeader>
</Card>
</div>
);
}

View File

@ -1,3 +1,6 @@
import Error from "@/app/(app)/workflows/[workflow_id]/@runs/error";
import { ErrorBoundary } from "@/components/ErrorBoundary";
export default async function Layout({ export default async function Layout({
children, children,
deployment, deployment,
@ -10,6 +13,7 @@ export default async function Layout({
workflow: React.ReactNode; workflow: React.ReactNode;
}) { }) {
return ( return (
<ErrorBoundary fallback={<Error />}>
<div className="mt-4 w-full grid grid-rows-[1fr,1fr] lg:grid-cols-[minmax(auto,500px),1fr] gap-4 max-h-[calc(100dvh-100px)]"> <div className="mt-4 w-full grid grid-rows-[1fr,1fr] lg:grid-cols-[minmax(auto,500px),1fr] gap-4 max-h-[calc(100dvh-100px)]">
<div className="w-full flex gap-4 flex-col min-w-0"> <div className="w-full flex gap-4 flex-col min-w-0">
{workflow} {workflow}
@ -18,5 +22,6 @@ export default async function Layout({
{runs} {runs}
{children} {children}
</div> </div>
</ErrorBoundary>
); );
} }

View File

@ -0,0 +1,47 @@
"use client";
import type { ErrorInfo, ReactNode } from "react";
import { Component } from "react";
interface ErrorBoundaryProps {
fallback: ReactNode;
children: ReactNode;
}
interface ErrorBoundaryState {
hasError: boolean;
}
export class ErrorBoundary extends Component<
ErrorBoundaryProps,
ErrorBoundaryState
> {
constructor(props: ErrorBoundaryProps) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(_: Error): ErrorBoundaryState {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
componentDidCatch(error: Error, info: ErrorInfo) {
// Example "componentStack":
// in ComponentThatThrows (created by App)
// in ErrorBoundary (created by App)
// in div (created by App)
// in App
// TODO: Replace this with your own error reporting logic.
console.error("Uncaught error:", error, info);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return this.props.fallback;
}
return this.props.children;
}
}