diff --git a/packages/client/src/components/DataTable/DataTableErrorBoundary.tsx b/packages/client/src/components/DataTable/DataTableErrorBoundary.tsx index de2f492cc1..aa6dd2294f 100644 --- a/packages/client/src/components/DataTable/DataTableErrorBoundary.tsx +++ b/packages/client/src/components/DataTable/DataTableErrorBoundary.tsx @@ -1,6 +1,8 @@ -import { Component, ErrorInfo, ReactNode } from 'react'; -import { Button } from '../Button'; +import { Component, ErrorInfo, ReactNode, createRef } from 'react'; import { RefreshCw } from 'lucide-react'; +import { Button } from '../Button'; +import { logger } from '~/utils'; +import { useLocalize } from '~/hooks'; /** * Error boundary specifically for DataTable component. @@ -17,29 +19,39 @@ interface DataTableErrorBoundaryProps { onError?: (error: Error) => void; onReset?: () => void; } +interface DataTableErrorBoundaryInnerProps extends DataTableErrorBoundaryProps { + localize: ReturnType; +} -export class DataTableErrorBoundary extends Component< - DataTableErrorBoundaryProps, +class DataTableErrorBoundaryInner extends Component< + DataTableErrorBoundaryInnerProps, DataTableErrorBoundaryState > { - constructor(props: DataTableErrorBoundaryProps) { + private errorCardRef = createRef(); + + constructor(props: DataTableErrorBoundaryInnerProps) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error: Error): DataTableErrorBoundaryState { - // Update state to show fallback UI and store error for logging return { hasError: true, error }; } componentDidCatch(error: Error, errorInfo: ErrorInfo) { - // Log the error (you can also log to an error reporting service) - console.error('DataTable Error Boundary caught an error:', error, errorInfo); - - // Call parent error handler if provided + logger.error('DataTable Error Boundary caught an error:', error, errorInfo); this.props.onError?.(error); } + componentDidUpdate( + _prevProps: DataTableErrorBoundaryInnerProps, + prevState: DataTableErrorBoundaryState, + ) { + if (!prevState.hasError && this.state.hasError && this.errorCardRef.current) { + this.errorCardRef.current.focus(); + } + } + /** * Reset the error state and attempt to re-render the children. * This can be used to retry after a table error (e.g., network retry). @@ -51,36 +63,45 @@ export class DataTableErrorBoundary extends Component< render() { if (this.state.hasError) { - // Custom fallback UI for DataTable errors return (
-
-
- -

Table Error

+
+
+ +

+ {this.props.localize('com_ui_table_error')} +

-

- Table failed to load. Please refresh or try again. +

+ {this.props.localize('com_ui_table_error_description')}

{import.meta.env.MODE === 'development' && this.state.error && ( -
- - Error Details (Dev) +
+ + {this.props.localize('com_ui_error_details')} -
+              
                 {this.state.error.message}
               
@@ -93,5 +114,9 @@ export class DataTableErrorBoundary extends Component< } } -// Named export for convenience +export function DataTableErrorBoundary(props: DataTableErrorBoundaryProps) { + const localize = useLocalize(); + return ; +} + export default DataTableErrorBoundary; diff --git a/packages/client/src/locales/en/translation.json b/packages/client/src/locales/en/translation.json index 17305d7cb2..9f61e6c0fb 100644 --- a/packages/client/src/locales/en/translation.json +++ b/packages/client/src/locales/en/translation.json @@ -18,5 +18,8 @@ "com_ui_data_table_scroll_area": "Scrollable data table area", "com_ui_select_row": "Select Row {{0}}", "com_ui_loading_more_data": "Loading more data...", - "com_ui_no_search_results": "No search results found" + "com_ui_no_search_results": "No search results found", + "com_ui_table_error": "Table Error", + "com_ui_table_error_description": "Table failed to load. Please refresh or try again.", + "com_ui_error_details": "Error Details (Dev)" }