feat: error page
This commit is contained in:
parent
770acfcedf
commit
3644e5044c
51
web/src/app/(app)/workflows/[workflow_id]/@runs/error.tsx
Normal file
51
web/src/app/(app)/workflows/[workflow_id]/@runs/error.tsx
Normal 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>
|
||||
);
|
||||
}
|
@ -1,3 +1,6 @@
|
||||
import Error from "@/app/(app)/workflows/[workflow_id]/@runs/error";
|
||||
import { ErrorBoundary } from "@/components/ErrorBoundary";
|
||||
|
||||
export default async function Layout({
|
||||
children,
|
||||
deployment,
|
||||
@ -10,6 +13,7 @@ export default async function Layout({
|
||||
workflow: React.ReactNode;
|
||||
}) {
|
||||
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="w-full flex gap-4 flex-col min-w-0">
|
||||
{workflow}
|
||||
@ -18,5 +22,6 @@ export default async function Layout({
|
||||
{runs}
|
||||
{children}
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
47
web/src/components/ErrorBoundary.tsx
Normal file
47
web/src/components/ErrorBoundary.tsx
Normal 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;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user