import React, { ErrorInfo, ReactNode } from "react"; import { CodeBlock } from "../CodeBlock/CodeBlock"; import { FaExclamationCircle } from "react-icons/fa"; import { Button, Collapse } from "antd"; import { getErrorMessage, getLog } from "juava"; import { PropsWithChildrenClassname } from "../../lib/ui"; import { AlertCircle } from "lucide-react"; import classNames from "classnames"; import { useUserSessionControls } from "../../lib/context"; export type GlobalErrorProps = { error?: any; title?: string; children?: ReactNode; hideActions?: boolean; }; export type ErrorProps = { error: Error; errorInfo: ErrorInfo }; export class ErrorBoundary extends React.Component< { children: ReactNode; renderError: (props: ErrorProps) => ReactNode }, ErrorProps > { constructor(props) { super(props); } componentDidCatch(error, errorInfo) { console.log(`Unhandled React error: ${errorInfo?.componentStack} `, error); this.setState({ error: error, errorInfo: errorInfo, }); } render() { if (this.state?.error) { return this.props.renderError(this.state); } return this.props.children; } } export function ErrorDetails(props: { error: any }) { const message = props.error?.message && `${props.error.message}`; const stack = props.error?.stack && `${props.error.stack}`; return ( {message && ( Error}> {message} )} {props.error.response && ( Response}> {JSON.stringify(props.error.response, null, 2)} )} {props.error.request && ( Request}> {JSON.stringify(props.error.request, null, 2)} )} {stack && ( Stack}> {stack} )} ); } const log = getLog("error"); export const EmbeddedErrorMessage: React.FC> = ({ children, className, actions, }) => ( {children} {actions && {actions}} ); function maxLen(str: string, maxLen = 200) { return str.length <= maxLen - 2 ? str : str.substring(0, maxLen) + "..."; } export function SimpleErrorCard(props: { error?: any; title?: string }) { const title = props.title || (props.error ? maxLen(getErrorMessage(props.error), 60) : "Error"); const description = ( <> {getErrorMessage(props.error) || `We encountered an error processing your request. Please try refreshing the page, or logging out and back in. If the problem persists, please contact support.`} > ); return ( {title} {description} ); } export function ErrorCard(props: { error?: any; title?: string; hideActions?: boolean; children?: ReactNode }) { const sessionControl = useUserSessionControls(); const title = props.title || (props.error ? maxLen(getErrorMessage(props.error), 60) : "Error"); const description = ( <> {props.children || `We encountered an error processing your request`}. Please try refreshing the page, or logging out and back in. If the problem persists, please contact support. > ); const [detailsVisible, setDetailsVisible] = React.useState(false); return ( {title} {description} {!props.hideActions && ( Logout window.location.reload()} className="mt-0.5"> Reload {props.error && ( setDetailsVisible(!detailsVisible)} className="mt-0.5"> {detailsVisible ? "Hide technical details" : "Show technical details"} )} )} {props.error && detailsVisible && ( {(props.error?.stack || props.error?.message) && } {typeof props.error === "string" && } )} ); } export const GlobalOverlay: React.FC> = ({ children, className }) => ( {children} ); export const GlobalError: React.FC = props => ( );