From a4068306d412aa033cf443097899fd10439c2c61 Mon Sep 17 00:00:00 2001 From: Marco Beretta <81851188+berry-13@users.noreply.github.com> Date: Wed, 22 Jan 2025 22:03:15 +0100 Subject: [PATCH] fix: Correct typo in containerClassName and remove unused RouteErrorBoundary component --- client/src/components/Chat/Landing.tsx | 2 +- client/src/routes/RouteErrorBoundary.tsx | 216 +++++++++++++++++++++++ client/src/routes/index.tsx | 95 +--------- 3 files changed, 218 insertions(+), 95 deletions(-) create mode 100644 client/src/routes/RouteErrorBoundary.tsx diff --git a/client/src/components/Chat/Landing.tsx b/client/src/components/Chat/Landing.tsx index 8d65fba0ba3..e18ee6fb1f4 100644 --- a/client/src/components/Chat/Landing.tsx +++ b/client/src/components/Chat/Landing.tsx @@ -97,7 +97,7 @@ export default function Landing({ Header }: { Header?: ReactNode }) { assistantMap={assistantMap} conversation={conversation} endpointsConfig={endpointsConfig} - containerClassName={containerClassName} + containerClassName={containerClassNam2e} context="landing" className="h-2/3 w-2/3" size={41} diff --git a/client/src/routes/RouteErrorBoundary.tsx b/client/src/routes/RouteErrorBoundary.tsx new file mode 100644 index 00000000000..082d9645594 --- /dev/null +++ b/client/src/routes/RouteErrorBoundary.tsx @@ -0,0 +1,216 @@ +import { useRouteError } from 'react-router-dom'; +import { Button } from '~/components/ui'; + +interface UserAgentData { + getHighEntropyValues(hints: string[]): Promise<{ platform: string; platformVersion: string }>; +} + +type PlatformInfo = { + os: string; + version?: string; +}; + +const formatStackTrace = (stack: string) => { + return stack + .split('\n') + .map((line) => line.trim()) + .filter(Boolean) + .map((line, i) => ({ + number: i + 1, + content: line, + })); +}; + +const getPlatformInfo = async (): Promise => { + if ('userAgentData' in navigator) { + try { + const ua = navigator.userAgentData as UserAgentData; + const highEntropyValues = await ua.getHighEntropyValues(['platform', 'platformVersion']); + return { + os: highEntropyValues.platform, + version: highEntropyValues.platformVersion, + }; + } catch (e) { + console.warn('Failed to get high entropy values:', e); + } + } + + const userAgent = navigator.userAgent.toLowerCase(); + + if (userAgent.includes('mac')) { + return { os: 'macOS' }; + } + if (userAgent.includes('win')) { + return { os: 'Windows' }; + } + if (userAgent.includes('linux')) { + return { os: 'Linux' }; + } + if (userAgent.includes('android')) { + return { os: 'Android' }; + } + if (userAgent.includes('ios') || userAgent.includes('iphone') || userAgent.includes('ipad')) { + return { os: 'iOS' }; + } + + return { os: 'Unknown' }; +}; + +const getBrowserInfo = async () => { + const platformInfo = await getPlatformInfo(); + return { + userAgent: navigator.userAgent, + platform: platformInfo.os, + platformVersion: platformInfo.version, + language: navigator.language, + windowSize: `${window.innerWidth}x${window.innerHeight}`, + }; +}; + +export default function RouteErrorBoundary() { + const typedError = useRouteError() as { + message?: string; + stack?: string; + status?: number; + statusText?: string; + data?: unknown; + }; + + const errorDetails = { + message: typedError.message ?? 'An unexpected error occurred', + stack: typedError.stack, + status: typedError.status, + statusText: typedError.statusText, + data: typedError.data, + }; + + const handleDownloadLogs = async () => { + const browser = await getBrowserInfo(); + const errorLog = { + timestamp: new Date().toISOString(), + browser, + error: { + ...errorDetails, + stack: + errorDetails.stack != null && errorDetails.stack.trim() !== '' + ? formatStackTrace(errorDetails.stack) + : undefined, + }, + }; + + const blob = new Blob([JSON.stringify(errorLog, null, 2)], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `error-log-${new Date().toISOString()}.json`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + }; + + const handleCopyStack = async () => { + if (errorDetails.stack != null && errorDetails.stack !== '') { + await navigator.clipboard.writeText(errorDetails.stack); + } + }; + + return ( +
+
+

+ Oops! Something Unexpected Occurred +

+ + {/* Error Message */} +
+

Error Message:

+
+            {errorDetails.message}
+          
+
+ + {/* Status Information */} + {(typeof errorDetails.status === 'number' || + typeof errorDetails.statusText === 'string') && ( +
+

Status:

+

+ {typeof errorDetails.status === 'number' && `${errorDetails.status} `} + {typeof errorDetails.statusText === 'string' && errorDetails.statusText} +

+
+ )} + + {/* Stack Trace - Collapsible */} + {errorDetails.stack != null && errorDetails.stack.trim() !== '' && ( +
+ + Stack Trace +
+ +
+
+
+ {formatStackTrace(errorDetails.stack).map(({ number, content }) => ( +
+ + {String(number).padStart(3, '0')} + +
+                    {content}
+                  
+
+ ))} +
+
+ )} + + {/* Additional Error Data */} + {errorDetails.data != null && ( +
+ + Additional Details + {'>'} + +
+              {JSON.stringify(errorDetails.data, null, 2)}
+            
+
+ )} + +
+

Please try one of the following:

+
    +
  • Refresh the page
  • +
  • Clear your browser cache
  • +
  • Check your internet connection
  • +
  • Contact the Admin if the issue persists
  • +
+
+ + +
+
+
+
+ ); +} diff --git a/client/src/routes/index.tsx b/client/src/routes/index.tsx index 8d8a6f6355a..3cdfe3c46e2 100644 --- a/client/src/routes/index.tsx +++ b/client/src/routes/index.tsx @@ -8,6 +8,7 @@ import { ApiErrorWatcher, } from '~/components/Auth'; import { AuthContextProvider } from '~/hooks/AuthContext'; +import RouteErrorBoundary from './RouteErrorBoundary'; import StartupLayout from './Layouts/Startup'; import LoginLayout from './Layouts/Login'; import dashboardRoutes from './Dashboard'; @@ -15,7 +16,6 @@ import ShareRoute from './ShareRoute'; import ChatRoute from './ChatRoute'; import Search from './Search'; import Root from './Root'; -import { useRouteError } from 'react-router-dom'; const AuthLayout = () => ( @@ -24,99 +24,6 @@ const AuthLayout = () => ( ); -function RouteErrorBoundary() { - const typedError = useRouteError() as { - message?: string; - stack?: string; - status?: number; - statusText?: string; - data?: unknown; - }; - - const errorDetails = { - message: typedError.message ?? 'An unexpected error occurred', - stack: typedError.stack, - status: typedError.status, - statusText: typedError.statusText, - data: typedError.data, - }; - - return ( -
-
-

- Oops! Something went wrong -

- - {/* Error Message */} -
-

Error Message:

-
-            {errorDetails.message}
-          
-
- - {/* Status Information */} - {(typeof errorDetails.status === 'number' || - typeof errorDetails.statusText === 'string') && ( -
-

Status:

-

- {typeof errorDetails.status === 'number' && `${errorDetails.status} `} - {typeof errorDetails.statusText === 'string' && errorDetails.statusText} -

-
- )} - - {/* Stack Trace - Collapsible */} - {errorDetails.stack && ( -
- - Stack Trace - -
-              {errorDetails.stack}
-            
-
- )} - - {/* Additional Error Data */} - {errorDetails.data && ( -
- - Additional Details - -
-              {JSON.stringify(errorDetails.data, null, 2)}
-            
-
- )} - -
-

Please try one of the following:

-
    -
  • Refresh the page
  • -
  • Clear your browser cache
  • -
  • Check your internet connection
  • -
  • Contact the Admin if the issue persists
  • -
-
- -
-
-
-
- ); -} - export const router = createBrowserRouter([ { path: 'share/:shareId',