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({
|
export default async function Layout({
|
||||||
children,
|
children,
|
||||||
deployment,
|
deployment,
|
||||||
@ -10,13 +13,15 @@ export default async function Layout({
|
|||||||
workflow: React.ReactNode;
|
workflow: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<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)]">
|
<ErrorBoundary fallback={<Error />}>
|
||||||
<div className="w-full flex gap-4 flex-col min-w-0">
|
<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)]">
|
||||||
{workflow}
|
<div className="w-full flex gap-4 flex-col min-w-0">
|
||||||
{deployment}
|
{workflow}
|
||||||
|
{deployment}
|
||||||
|
</div>
|
||||||
|
{runs}
|
||||||
|
{children}
|
||||||
</div>
|
</div>
|
||||||
{runs}
|
</ErrorBoundary>
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
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