Skip to content

Commit bd51842

Browse files
committed
hackathon
1 parent 25a8dba commit bd51842

File tree

10 files changed

+224
-1
lines changed

10 files changed

+224
-1
lines changed

thirdeye-ui/src/app/app.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { AnalyticsAndErrorReportingProviderV1 } from "./components/third-party-l
2222
import { AppCrashPage } from "./pages/app-crash-page/app-crash-page.component";
2323
import { AppContainerV1, useAuthProviderV1 } from "./platform/components";
2424
import { AppRouter } from "./routers/app/app.router";
25-
25+
import ErrorBoundary from '../app/routers/app/error-boundary'
2626
const queryClient = new QueryClient({
2727
defaultOptions: {
2828
queries: {
@@ -49,9 +49,11 @@ export const App: FunctionComponent = () => {
4949
<AnalyticsAndErrorReportingProviderV1>
5050
<AppContainerV1 name={t("label.thirdeye")}>
5151
<Sentry.ErrorBoundary fallback={<AppCrashPage />}>
52+
<ErrorBoundary>
5253
<AppBarConfigProvider>
5354
<AppRouter />
5455
</AppBarConfigProvider>
56+
</ErrorBoundary>
5557
</Sentry.ErrorBoundary>
5658
</AppContainerV1>
5759
</AnalyticsAndErrorReportingProviderV1>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React from "react";
2+
import { MainLayout } from "../../platform/components/layout/main/page.component";
3+
import { ErrorHeader } from "./sections/header";
4+
import { ErrorTable } from "./sections/error-table";
5+
6+
export const ErrorListPage = (): JSX.Element => {
7+
return (
8+
<MainLayout>
9+
<ErrorHeader />
10+
<ErrorTable />
11+
</MainLayout>
12+
);
13+
};
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import React, { useMemo } from "react"
2+
import DataTable from "../../../../platform/components/table/table.component";
3+
import { getErrorObj } from "../../util";
4+
import { Link } from "@material-ui/core";
5+
import { Link as RouterLink } from "react-router-dom";
6+
7+
export const ErrorTable = () => {
8+
const renderAlertLink = (data: TableRow): ReactElement => {
9+
const id = Number(data.id);
10+
11+
return (
12+
<Link component={RouterLink} to={`/errors/${id}/view`}>
13+
{data.type}
14+
</Link>
15+
);
16+
};
17+
const columns: TableColumns[] = [
18+
{
19+
title: 'type',
20+
datakey: "type",
21+
customRender: renderAlertLink,
22+
},
23+
{
24+
title: 'message',
25+
datakey: "message",
26+
},
27+
{
28+
title: 'user',
29+
datakey: 'user'
30+
},
31+
{
32+
title: 'time',
33+
datakey: "time",
34+
},
35+
];
36+
37+
const errorData = useMemo(() => {
38+
const data: { id: number; user: string; type: string; message: string; time: string}[] = [];
39+
for (let i=0;i< 20;i++){
40+
data.push(getErrorObj(i))
41+
}
42+
return data;
43+
}, []);
44+
45+
return (
46+
<>
47+
<DataTable
48+
columns={columns}
49+
data={errorData}
50+
emptyStateView={'Yaay! No errors. Go break it for me to stay in business'}
51+
/>
52+
</>
53+
)
54+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import React from "react";
2+
import { PageHeader } from "../../../platform/components/layout/page-header/page-header.component";
3+
4+
export const ErrorHeader = () => {
5+
return <PageHeader mainHeading="TE Errors" />;
6+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export const getErrorObj = (id:number) => {
2+
const date = new Date()
3+
return {
4+
id: id+1,
5+
user: `test-${id+1}@error.com`,
6+
type: 'TypeError',
7+
message: 'Cannot read properties of the object',
8+
time: `${date.getMonth()}-${date.getDate()}-${date.getFullYear()}`
9+
}
10+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import React from "react"
2+
import { useParams } from "react-router-dom";
3+
import { getErrorObj } from "./util";
4+
5+
export const ErrorView = () => {
6+
const {id} = useParams();
7+
// const errorObj = getErrorObj(Number(id))
8+
const errorObj = {
9+
"user": "test@test.com",
10+
"os": "MacOS",
11+
"userAgentInfo": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
12+
"errorType": "TypeError",
13+
"errorMessage": "Cannot read properties of null (reading 'name')",
14+
"errorInfo": {
15+
"componentStack": "\n in HomePage (created by GeneralAuthenticatedRouter)\n in CancelAPICallsOnPageUnload (created by GeneralAuthenticatedRouter)\n in RenderedRoute (created by Routes)\n in Routes (created by GeneralAuthenticatedRouter)\n in Suspense (created by GeneralAuthenticatedRouter)\n in GeneralAuthenticatedRouter (created by AppRouter)\n in RenderedRoute (created by Routes)\n in Routes (created by AppRouter)\n in Suspense (created by AppRouter)\n in AppRouter (created by App)\n in div (created by AppBarConfigProvider)\n in div (created by AppBarConfigProvider)\n in AppBarConfigProvider (created by App)\n in ErrorBoundary (created by App)\n in ErrorBoundary (created by App)\n in div (created by AppContainerV1)\n in HelmetProvider (created by AppContainerV1)\n in AppContainerV1 (created by App)\n in IntercomProvider (created by AnalyticsAndErrorReportingProviderV1)\n in AnalyticsAndErrorReportingProviderV1 (created by App)\n in QueryClientProvider (created by App)\n in App\n in DialogProviderV1\n in TimeRangeProvider\n in AuthProviderV1 (created by AuthProviderWrapper)\n in AuthProviderWrapper\n in NotificationProviderV1\n in Router (created by BrowserRouter)\n in BrowserRouter\n in ThemeProvider\n in StrictMode"
16+
},
17+
"url": "http://localhost:7004/home",
18+
"project": "ThirdEye Ui"
19+
}
20+
21+
const renderStack = (stackObj) => {
22+
const componentStack = stackObj.componentStack.split('\n')
23+
return (
24+
<div>
25+
{componentStack.map(stackFrame=> <div>{stackFrame}</div>)}
26+
</div>
27+
)
28+
}
29+
return (
30+
<div
31+
style={{
32+
display: 'flex',
33+
flexDirection: 'column',
34+
gap: '20px',
35+
padding: '20px',
36+
border: '1px solid black',
37+
borderTop: 0
38+
}}
39+
>
40+
{Object.entries(errorObj).map(entry => {
41+
return (
42+
<div style={{display: 'flex', gap: '50px'}}>
43+
<div style={{width: '15%'}}>
44+
{entry[0]}
45+
</div>
46+
<div>
47+
{typeof entry[1] === 'object' ? renderStack(entry[1]) : entry[1]}
48+
</div>
49+
</div>
50+
)
51+
})}
52+
</div>
53+
)
54+
}

thirdeye-ui/src/app/pages/home-page/home-page.component.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ export const HomePage: FunctionComponent = () => {
5757
const [searchParams, setSearchParams] = useSearchParams();
5858
const style = useHomePageStyles();
5959

60+
// useEffect(()=>{
61+
// const a = null
62+
// const b = a.name
63+
// }, [])
64+
6065
const getAlertsQuery = useFetchQuery<Alert[], AxiosError>({
6166
queryKey: ["alerts"],
6267
queryFn: () => {

thirdeye-ui/src/app/routers/app/app.router.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import React, { FunctionComponent, lazy, Suspense } from "react";
1717
import { Route, Routes } from "react-router-dom";
1818
import { CancelAPICallsOnPageUnload } from "../../components/cancel-api-calls-on-page-unload/cancel-api-calls-on-page-unload.component";
1919
import { AppCrashPage } from "../../pages/app-crash-page/app-crash-page.component";
20+
import {ErrorListPage} from "../../pages/errors"
21+
import {ErrorView} from "../../pages/errors/view"
2022
import {
2123
AppLoadingIndicatorV1,
2224
useAuthProviderV1,
@@ -113,6 +115,15 @@ export const AppRouter: FunctionComponent = () => {
113115
path={`${AppRoute.WELCOME}/*`}
114116
/>
115117

118+
<Route
119+
element={<ErrorListPage/>}
120+
path={`/errors`}
121+
/>
122+
<Route
123+
element={<ErrorView/>}
124+
path={`/errors/:id/view`}
125+
/>
126+
116127
{/* Direct all other paths to general authenticated router */}
117128
<Route element={<GeneralAuthenticatedRouter />} path="/*" />
118129
</Routes>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import React, { Component } from 'react';
2+
import { getOS, getUserAgent } from './util';
3+
class ErrorBoundary extends Component {
4+
state = {
5+
hasError: false,
6+
error: null,
7+
errorInfo: null,
8+
};
9+
10+
static getDerivedStateFromError(error) {
11+
// Update state to trigger a re-render and show fallback UI
12+
return { hasError: true };
13+
}
14+
15+
componentDidCatch(error, errorInfo) {
16+
const url = window.location.href
17+
console.log('Caught an error:', error);
18+
console.log('er', error.message)
19+
console.log('Error stack trace:', errorInfo);
20+
21+
const errorObj = {
22+
user: {email: 'test@test.com'},
23+
os: getOS(),
24+
userAgentInfo: getUserAgent(),
25+
errorType: error.name,
26+
errorMessage: error.message,
27+
errorInfo,
28+
url,
29+
project: 'ThirdEye Ui'
30+
}
31+
console.log('err', errorObj)
32+
this.setState({
33+
error,
34+
errorInfo,
35+
});
36+
}
37+
38+
render() {
39+
if (this.state.hasError) {
40+
return (
41+
<div>
42+
<h1>Something went wrong.</h1>
43+
<details style={{ whiteSpace: 'pre-wrap' }}>
44+
{this.state.error && this.state.error.toString()}
45+
<br />
46+
{/* {this.state.errorInfo.componentStack} */}
47+
</details>
48+
</div>
49+
);
50+
}
51+
52+
return this.props.children;
53+
}
54+
}
55+
56+
export default ErrorBoundary;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export function getOS() {
2+
const userAgent = window.navigator.userAgent;
3+
if (userAgent.indexOf("Win") !== -1) return "Windows";
4+
if (userAgent.indexOf("Mac") !== -1) return "MacOS";
5+
if (userAgent.indexOf("X11") !== -1) return "Unix";
6+
if (userAgent.indexOf("Linux") !== -1) return "Linux";
7+
return "Unknown OS";
8+
}
9+
10+
export function getUserAgent() {
11+
return navigator.userAgent;
12+
}

0 commit comments

Comments
 (0)