Skip to content

Commit a406830

Browse files
committed
fix: Correct typo in containerClassName and remove unused RouteErrorBoundary component
1 parent c8ef5a0 commit a406830

File tree

3 files changed

+218
-95
lines changed

3 files changed

+218
-95
lines changed

client/src/components/Chat/Landing.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export default function Landing({ Header }: { Header?: ReactNode }) {
9797
assistantMap={assistantMap}
9898
conversation={conversation}
9999
endpointsConfig={endpointsConfig}
100-
containerClassName={containerClassName}
100+
containerClassName={containerClassNam2e}
101101
context="landing"
102102
className="h-2/3 w-2/3"
103103
size={41}
+216
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
import { useRouteError } from 'react-router-dom';
2+
import { Button } from '~/components/ui';
3+
4+
interface UserAgentData {
5+
getHighEntropyValues(hints: string[]): Promise<{ platform: string; platformVersion: string }>;
6+
}
7+
8+
type PlatformInfo = {
9+
os: string;
10+
version?: string;
11+
};
12+
13+
const formatStackTrace = (stack: string) => {
14+
return stack
15+
.split('\n')
16+
.map((line) => line.trim())
17+
.filter(Boolean)
18+
.map((line, i) => ({
19+
number: i + 1,
20+
content: line,
21+
}));
22+
};
23+
24+
const getPlatformInfo = async (): Promise<PlatformInfo> => {
25+
if ('userAgentData' in navigator) {
26+
try {
27+
const ua = navigator.userAgentData as UserAgentData;
28+
const highEntropyValues = await ua.getHighEntropyValues(['platform', 'platformVersion']);
29+
return {
30+
os: highEntropyValues.platform,
31+
version: highEntropyValues.platformVersion,
32+
};
33+
} catch (e) {
34+
console.warn('Failed to get high entropy values:', e);
35+
}
36+
}
37+
38+
const userAgent = navigator.userAgent.toLowerCase();
39+
40+
if (userAgent.includes('mac')) {
41+
return { os: 'macOS' };
42+
}
43+
if (userAgent.includes('win')) {
44+
return { os: 'Windows' };
45+
}
46+
if (userAgent.includes('linux')) {
47+
return { os: 'Linux' };
48+
}
49+
if (userAgent.includes('android')) {
50+
return { os: 'Android' };
51+
}
52+
if (userAgent.includes('ios') || userAgent.includes('iphone') || userAgent.includes('ipad')) {
53+
return { os: 'iOS' };
54+
}
55+
56+
return { os: 'Unknown' };
57+
};
58+
59+
const getBrowserInfo = async () => {
60+
const platformInfo = await getPlatformInfo();
61+
return {
62+
userAgent: navigator.userAgent,
63+
platform: platformInfo.os,
64+
platformVersion: platformInfo.version,
65+
language: navigator.language,
66+
windowSize: `${window.innerWidth}x${window.innerHeight}`,
67+
};
68+
};
69+
70+
export default function RouteErrorBoundary() {
71+
const typedError = useRouteError() as {
72+
message?: string;
73+
stack?: string;
74+
status?: number;
75+
statusText?: string;
76+
data?: unknown;
77+
};
78+
79+
const errorDetails = {
80+
message: typedError.message ?? 'An unexpected error occurred',
81+
stack: typedError.stack,
82+
status: typedError.status,
83+
statusText: typedError.statusText,
84+
data: typedError.data,
85+
};
86+
87+
const handleDownloadLogs = async () => {
88+
const browser = await getBrowserInfo();
89+
const errorLog = {
90+
timestamp: new Date().toISOString(),
91+
browser,
92+
error: {
93+
...errorDetails,
94+
stack:
95+
errorDetails.stack != null && errorDetails.stack.trim() !== ''
96+
? formatStackTrace(errorDetails.stack)
97+
: undefined,
98+
},
99+
};
100+
101+
const blob = new Blob([JSON.stringify(errorLog, null, 2)], { type: 'application/json' });
102+
const url = URL.createObjectURL(blob);
103+
const a = document.createElement('a');
104+
a.href = url;
105+
a.download = `error-log-${new Date().toISOString()}.json`;
106+
document.body.appendChild(a);
107+
a.click();
108+
document.body.removeChild(a);
109+
URL.revokeObjectURL(url);
110+
};
111+
112+
const handleCopyStack = async () => {
113+
if (errorDetails.stack != null && errorDetails.stack !== '') {
114+
await navigator.clipboard.writeText(errorDetails.stack);
115+
}
116+
};
117+
118+
return (
119+
<div
120+
role="alert"
121+
className="flex min-h-screen flex-col items-center justify-center bg-surface-primary bg-gradient-to-br"
122+
>
123+
<div className="bg-surface-primary/60 mx-4 w-11/12 max-w-4xl rounded-2xl border border-border-light p-8 shadow-2xl backdrop-blur-xl">
124+
<h2 className="mb-6 text-center text-3xl font-medium tracking-tight text-text-primary">
125+
Oops! Something Unexpected Occurred
126+
</h2>
127+
128+
{/* Error Message */}
129+
<div className="mb-4 rounded-xl border border-red-500/20 bg-red-500/5 p-4 text-sm text-gray-600 dark:text-gray-200">
130+
<h3 className="mb-2 font-medium">Error Message:</h3>
131+
<pre className="whitespace-pre-wrap text-sm font-light leading-relaxed text-text-primary">
132+
{errorDetails.message}
133+
</pre>
134+
</div>
135+
136+
{/* Status Information */}
137+
{(typeof errorDetails.status === 'number' ||
138+
typeof errorDetails.statusText === 'string') && (
139+
<div className="mb-4 rounded-xl border border-yellow-500/20 bg-yellow-500/5 p-4 text-sm text-text-primary">
140+
<h3 className="mb-2 font-medium">Status:</h3>
141+
<p className="text-text-primary">
142+
{typeof errorDetails.status === 'number' && `${errorDetails.status} `}
143+
{typeof errorDetails.statusText === 'string' && errorDetails.statusText}
144+
</p>
145+
</div>
146+
)}
147+
148+
{/* Stack Trace - Collapsible */}
149+
{errorDetails.stack != null && errorDetails.stack.trim() !== '' && (
150+
<details className="group mb-4 rounded-xl border border-border-light p-4">
151+
<summary className="mb-2 flex cursor-pointer items-center justify-between text-sm font-medium text-text-primary">
152+
<span>Stack Trace</span>
153+
<div className="flex items-center">
154+
<Button
155+
variant="outline"
156+
size="sm"
157+
onClick={handleCopyStack}
158+
className="ml-2 px-2 py-1 text-xs"
159+
>
160+
Copy
161+
</Button>
162+
</div>
163+
</summary>
164+
<div className="overflow-x-auto rounded-lg bg-black/5 p-4 dark:bg-white/5">
165+
{formatStackTrace(errorDetails.stack).map(({ number, content }) => (
166+
<div key={number} className="flex">
167+
<span className="select-none pr-4 font-mono text-xs text-text-secondary">
168+
{String(number).padStart(3, '0')}
169+
</span>
170+
<pre className="flex-1 font-mono text-xs leading-relaxed text-text-primary">
171+
{content}
172+
</pre>
173+
</div>
174+
))}
175+
</div>
176+
</details>
177+
)}
178+
179+
{/* Additional Error Data */}
180+
{errorDetails.data != null && (
181+
<details className="group mb-4 rounded-xl border border-border-light p-4">
182+
<summary className="mb-2 flex cursor-pointer items-center justify-between text-sm font-medium text-text-primary">
183+
<span>Additional Details</span>
184+
<span className="transition-transform group-open:rotate-90">{'>'}</span>
185+
</summary>
186+
<pre className="whitespace-pre-wrap text-xs font-light leading-relaxed text-text-primary">
187+
{JSON.stringify(errorDetails.data, null, 2)}
188+
</pre>
189+
</details>
190+
)}
191+
192+
<div className="mt-6 flex flex-col gap-4">
193+
<p className="text-sm font-light text-text-secondary">Please try one of the following:</p>
194+
<ul className="list-inside list-disc text-sm text-text-secondary">
195+
<li>Refresh the page</li>
196+
<li>Clear your browser cache</li>
197+
<li>Check your internet connection</li>
198+
<li>Contact the Admin if the issue persists</li>
199+
</ul>
200+
<div className="mt-4 flex flex-col items-center gap-4 sm:flex-row sm:justify-center">
201+
<Button
202+
variant="submit"
203+
onClick={() => window.location.reload()}
204+
className="w-full sm:w-auto"
205+
>
206+
Refresh Page
207+
</Button>
208+
<Button variant="outline" onClick={handleDownloadLogs} className="w-full sm:w-auto">
209+
Download Error Logs
210+
</Button>
211+
</div>
212+
</div>
213+
</div>
214+
</div>
215+
);
216+
}

client/src/routes/index.tsx

+1-94
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ import {
88
ApiErrorWatcher,
99
} from '~/components/Auth';
1010
import { AuthContextProvider } from '~/hooks/AuthContext';
11+
import RouteErrorBoundary from './RouteErrorBoundary';
1112
import StartupLayout from './Layouts/Startup';
1213
import LoginLayout from './Layouts/Login';
1314
import dashboardRoutes from './Dashboard';
1415
import ShareRoute from './ShareRoute';
1516
import ChatRoute from './ChatRoute';
1617
import Search from './Search';
1718
import Root from './Root';
18-
import { useRouteError } from 'react-router-dom';
1919

2020
const AuthLayout = () => (
2121
<AuthContextProvider>
@@ -24,99 +24,6 @@ const AuthLayout = () => (
2424
</AuthContextProvider>
2525
);
2626

27-
function RouteErrorBoundary() {
28-
const typedError = useRouteError() as {
29-
message?: string;
30-
stack?: string;
31-
status?: number;
32-
statusText?: string;
33-
data?: unknown;
34-
};
35-
36-
const errorDetails = {
37-
message: typedError.message ?? 'An unexpected error occurred',
38-
stack: typedError.stack,
39-
status: typedError.status,
40-
statusText: typedError.statusText,
41-
data: typedError.data,
42-
};
43-
44-
return (
45-
<div
46-
role="alert"
47-
className="flex min-h-screen flex-col items-center justify-center bg-surface-primary bg-gradient-to-br"
48-
>
49-
<div className="bg-surface-primary/60 mx-4 w-full max-w-4xl rounded-2xl border border-border-light p-8 shadow-2xl backdrop-blur-xl">
50-
<h2 className="mb-6 text-center text-3xl font-medium tracking-tight text-text-primary">
51-
Oops! Something went wrong
52-
</h2>
53-
54-
{/* Error Message */}
55-
<div className="mb-4 rounded-xl border border-red-500/20 bg-red-500/5 p-4 text-sm text-gray-600 dark:text-gray-200">
56-
<h3 className="mb-2 font-medium">Error Message:</h3>
57-
<pre className="whitespace-pre-wrap text-sm font-light leading-relaxed text-text-primary">
58-
{errorDetails.message}
59-
</pre>
60-
</div>
61-
62-
{/* Status Information */}
63-
{(typeof errorDetails.status === 'number' ||
64-
typeof errorDetails.statusText === 'string') && (
65-
<div className="mb-4 rounded-xl border border-yellow-500/20 bg-yellow-500/5 p-4 text-sm text-text-primary">
66-
<h3 className="mb-2 font-medium">Status:</h3>
67-
<p className="text-text-primary">
68-
{typeof errorDetails.status === 'number' && `${errorDetails.status} `}
69-
{typeof errorDetails.statusText === 'string' && errorDetails.statusText}
70-
</p>
71-
</div>
72-
)}
73-
74-
{/* Stack Trace - Collapsible */}
75-
{errorDetails.stack && (
76-
<details className="mb-4 rounded-xl border border-border-light p-4">
77-
<summary className="mb-2 cursor-pointer text-sm font-medium text-text-primary">
78-
Stack Trace
79-
</summary>
80-
<pre className="overflow-x-auto whitespace-pre-wrap text-xs font-light leading-relaxed text-text-primary">
81-
{errorDetails.stack}
82-
</pre>
83-
</details>
84-
)}
85-
86-
{/* Additional Error Data */}
87-
{errorDetails.data && (
88-
<details className="mb-4 rounded-xl border border-border-light p-4">
89-
<summary className="mb-2 cursor-pointer text-sm font-medium text-text-primary">
90-
Additional Details
91-
</summary>
92-
<pre className="whitespace-pre-wrap text-xs font-light leading-relaxed text-text-primary">
93-
{JSON.stringify(errorDetails.data, null, 2)}
94-
</pre>
95-
</details>
96-
)}
97-
98-
<div className="mt-6 flex flex-col gap-4">
99-
<p className="text-sm font-light text-text-secondary">Please try one of the following:</p>
100-
<ul className="list-inside list-disc text-sm text-text-secondary">
101-
<li>Refresh the page</li>
102-
<li>Clear your browser cache</li>
103-
<li>Check your internet connection</li>
104-
<li>Contact the Admin if the issue persists</li>
105-
</ul>
106-
<div className="mt-4 flex justify-center gap-4">
107-
<button
108-
onClick={() => window.location.reload()}
109-
className="rounded-lg bg-surface-submit px-4 py-2 text-white transition-colors hover:bg-surface-submit-hover"
110-
>
111-
Refresh Page
112-
</button>
113-
</div>
114-
</div>
115-
</div>
116-
</div>
117-
);
118-
}
119-
12027
export const router = createBrowserRouter([
12128
{
12229
path: 'share/:shareId',

0 commit comments

Comments
 (0)