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