Skip to content

Commit

Permalink
Fix UI crash (#2380)
Browse files Browse the repository at this point in the history
- Add app error boundary
- Fix UI crash (conditions can be null on rare occasions)
- Fix bad setState in toggle component

---

This pull request introduces an error boundary component to the
`frontend/webapp` to handle errors gracefully and updates several
dependencies. The most important changes include the addition of the
`AppErrorBoundary` component, updates to the `RootLayout` to use the new
error boundary, and modifications to handle nullable conditions in
various types.

Error handling improvements:

*
[`frontend/webapp/app/layout.tsx`](diffhunk://#diff-788a38ec94bfca9467b13cb6eb93cdeccd4237facfb5fff310e05b3af67413efR7):
Added `AppErrorBoundary` component to wrap the main layout, ensuring
that errors are caught and displayed in a user-friendly manner.
[[1]](diffhunk://#diff-788a38ec94bfca9467b13cb6eb93cdeccd4237facfb5fff310e05b3af67413efR7)
[[2]](diffhunk://#diff-788a38ec94bfca9467b13cb6eb93cdeccd4237facfb5fff310e05b3af67413efR20)
[[3]](diffhunk://#diff-788a38ec94bfca9467b13cb6eb93cdeccd4237facfb5fff310e05b3af67413efR36)
*
[`frontend/webapp/components/app-error-boundary/index.tsx`](diffhunk://#diff-75013bded052d9cd6f26a18078332b113d5863aad2ab274f22b001e6d9277401R1-R60):
Created the `AppErrorBoundary` component using `react-error-boundary` to
provide a fallback UI in case of errors.
*
[`frontend/webapp/components/index.ts`](diffhunk://#diff-9a255ecda06fb13562b464a919eb789a51ea8728251b2aa31c28babfd8f3405dR1):
Exported the newly created `AppErrorBoundary` component.

Dependency updates:

*
[`frontend/webapp/package.json`](diffhunk://#diff-ccf6337b0064354343f900ffd8b4ee91aa8cd014f3292548a800ad3dac39c1f4L14-R33):
Updated several dependencies, including `@apollo/client`,
`@odigos/ui-components`, `@odigos/ui-utils`, and added
`react-error-boundary`.

Handling nullable conditions:

*
[`frontend/webapp/types/actions.ts`](diffhunk://#diff-3ae6790a1d85d899bad68bedc63fd62bd18aeda31add61046a76187d9175d21dL60-R60):
Updated `ActionData` interface to allow `conditions` to be `null`.
*
[`frontend/webapp/types/destinations.ts`](diffhunk://#diff-a260064e39c9894e9447a72de035e5e5bbb8c0df9fbcdba7c0c93dccf4d84b62L127-R127):
Updated `Destination` and `ActualDestination` interfaces to allow
`conditions` to be `null`.
[[1]](diffhunk://#diff-a260064e39c9894e9447a72de035e5e5bbb8c0df9fbcdba7c0c93dccf4d84b62L127-R127)
[[2]](diffhunk://#diff-a260064e39c9894e9447a72de035e5e5bbb8c0df9fbcdba7c0c93dccf4d84b62L154-R154)
*
[`frontend/webapp/types/sources.ts`](diffhunk://#diff-2e094683c1e156a4d3b841453d12f98342db28ae37230264200cf979063268b9L16-R16):
Updated `K8sActualSource` interface to allow `conditions` to be `null`.

---------

Co-authored-by: Amir Blum <[email protected]>
  • Loading branch information
BenElferink and blumamir authored Feb 4, 2025
1 parent f2ddc8a commit b1b5d15
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 39 deletions.
15 changes: 13 additions & 2 deletions frontend/graph/schema.resolvers.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 18 additions & 15 deletions frontend/webapp/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { METADATA } from '@/utils';
import { ApolloWrapper } from '@/lib';
import { ThemeProvider } from '@/styles';
import { useDarkModeStore } from '@/store';
import { AppErrorBoundary } from '@/components';

export default function RootLayout({ children }: { children: React.ReactNode }) {
const { darkMode } = useDarkModeStore();
Expand All @@ -16,21 +17,23 @@ export default function RootLayout({ children }: { children: React.ReactNode })
<link rel='manifest' href='/manifest.json' />
<title>{METADATA.title}</title>
</head>
<ApolloWrapper>
<ThemeProvider darkMode={darkMode}>
<body
suppressHydrationWarning={true}
style={{
width: '100vw',
height: '100vh',
margin: 0,
backgroundColor: darkMode ? '#111111' : '#EEEEEE',
}}
>
{children}
</body>
</ThemeProvider>
</ApolloWrapper>
<AppErrorBoundary>
<ApolloWrapper>
<ThemeProvider darkMode={darkMode}>
<body
suppressHydrationWarning={true}
style={{
width: '100vw',
height: '100vh',
margin: 0,
backgroundColor: darkMode ? '#111111' : '#EEEEEE',
}}
>
{children}
</body>
</ThemeProvider>
</ApolloWrapper>
</AppErrorBoundary>
</html>
);
}
60 changes: 60 additions & 0 deletions frontend/webapp/components/app-error-boundary/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
'use client';

import React from 'react';
import { Theme } from '@odigos/ui-theme';
import { Button } from '@odigos/ui-components';
import { ErrorBoundary } from 'react-error-boundary';

const ErrorFallback = ({ error }: { error: Error }) => {
const theme = Theme.useTheme();

return (
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
textAlign: 'center',
color: theme.text.error,
fontFamily: theme.font_family.primary,
}}
>
<h2>Something went wrong!</h2>

<pre
style={{
padding: 10,
borderRadius: 5,
whiteSpace: 'pre-wrap',
background: theme.colors.error,
}}
>
{error.message}
</pre>

<details style={{ textAlign: 'left', marginTop: 10 }}>
<summary>Stack Trace</summary>
<pre style={{ whiteSpace: 'pre-wrap', fontSize: '12px' }}>{error.stack}</pre>
</details>

<p style={{ marginTop: 100, color: theme.text.secondary }}>Try refreshing the page or contact support.</p>
<Button variant='secondary' onClick={() => window.location.reload()} style={{ fontSize: '1rem' }}>
Reload
</Button>
</div>
);
};

export const AppErrorBoundary = ({ children }: { children: React.ReactNode }) => {
return (
<ErrorBoundary
FallbackComponent={(props) => (
<Theme.Provider darkMode={false}>
<ErrorFallback {...props} />
</Theme.Provider>
)}
>
{children}
</ErrorBoundary>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ export const ErrorDropdown: React.FC<Props> = ({ title = 'Error Message', value,
const options = useMemo(() => {
const payload: DropdownProps['options'] = [];

sources.forEach(({ conditions = [] }) => {
conditions.forEach(({ status, message }) => {
sources.forEach(({ conditions }) => {
conditions?.forEach(({ status, message }) => {
if (status === BACKEND_BOOLEAN.FALSE && !payload.find((opt) => opt.id === message)) {
payload.push({ id: message, value: message });
}
Expand Down
1 change: 1 addition & 0 deletions frontend/webapp/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './app-error-boundary';
export * from './common';
export * from './main';
export * from './notification';
Expand Down
9 changes: 5 additions & 4 deletions frontend/webapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,26 @@
"cy:open": "cypress open --e2e -b electron"
},
"dependencies": {
"@apollo/client": "^3.12.8",
"@apollo/client": "^3.12.9",
"@apollo/experimental-nextjs-app-support": "^0.11.8",
"@odigos/ui-components": "^0.0.33",
"@odigos/ui-components": "^0.0.37",
"@odigos/ui-icons": "^0.0.2",
"@odigos/ui-theme": "^0.0.2",
"@odigos/ui-utils": "^0.0.3",
"@odigos/ui-utils": "^0.0.6",
"@xyflow/react": "^12.4.2",
"graphql": "^16.10.0",
"javascript-time-ago": "^2.5.11",
"next": "15.1.6",
"prism-react-renderer": "^2.4.1",
"react": "19.0.0",
"react-dom": "19.0.0",
"react-error-boundary": "^5.0.0",
"react-flow-renderer": "^10.3.17",
"styled-components": "^6.1.14",
"zustand": "^5.0.3"
},
"devDependencies": {
"@types/node": "22.13.0",
"@types/node": "22.13.1",
"@types/react": "19.0.8",
"@types/react-dom": "19.0.3",
"autoprefixer": "^10.4.20",
Expand Down
2 changes: 1 addition & 1 deletion frontend/webapp/types/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export interface ActionData {
id: string;
type: ACTION_TYPE;
spec: ActionItem | string;
conditions: Condition[];
conditions: Condition[] | null;
}

export interface ActionDataParsed extends ActionData {
Expand Down
4 changes: 2 additions & 2 deletions frontend/webapp/types/destinations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export interface Destination {
logs: boolean;
};
fields: Record<string, any>;
conditions: Condition[];
conditions: Condition[] | null;
destination_type: {
type: string;
display_name: string;
Expand All @@ -151,7 +151,7 @@ export interface ActualDestination {
logs: boolean;
};
fields: string;
conditions: Condition[];
conditions: Condition[] | null;
destinationType: {
type: string;
displayName: string;
Expand Down
2 changes: 1 addition & 1 deletion frontend/webapp/types/sources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export interface K8sActualSource extends WorkloadId {
numberOfInstances?: number;
otelServiceName: string;
containers: Array<SourceContainer>;
conditions: Array<Condition>;
conditions: Array<Condition> | null;
}

export interface PatchSourceRequestInput {
Expand Down
49 changes: 37 additions & 12 deletions frontend/webapp/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
dependencies:
ts-invariant "^0.10.3"

"@apollo/client@^3.12.8":
version "3.12.8"
resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.12.8.tgz#99670386104f77ceba03f7e3dc0d91813f03cd3c"
integrity sha512-053z5eCM7zNl81Lxs/SqHv8e+x3sszrtmGS2TNuPW0ZTZzmKATMsIsoblx1Kt0E67Ze3jb99JSPiQHG9ozGc3g==
"@apollo/client@^3.12.9":
version "3.12.9"
resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.12.9.tgz#fb7afc254bc4a5bfeeae905426edcb9d3e643fae"
integrity sha512-rH2Vzfbp+IR0l/xAjUIbDH4/sqBzPATMbzXv/L36E33yhp40yM5LFJnC6cc4YDPUH2gom7Dk4BrYZVLbFpYTsA==
dependencies:
"@graphql-typed-document-node/core" "^3.1.1"
"@wry/caches" "^1.0.0"
Expand Down Expand Up @@ -99,6 +99,13 @@
dependencies:
"@babel/helper-plugin-utils" "^7.25.9"

"@babel/runtime@^7.12.5":
version "7.26.7"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.7.tgz#f4e7fe527cd710f8dc0618610b61b4b060c3c341"
integrity sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==
dependencies:
regenerator-runtime "^0.14.0"

"@babel/runtime@^7.18.9":
version "7.26.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1"
Expand Down Expand Up @@ -514,10 +521,10 @@
resolved "https://registry.yarnpkg.com/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz#3dc35ba0f1e66b403c00b39344f870298ebb1c8e"
integrity sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==

"@odigos/ui-components@^0.0.33":
version "0.0.33"
resolved "https://registry.yarnpkg.com/@odigos/ui-components/-/ui-components-0.0.33.tgz#ede74c18ed070a117ea4cc47530846bb9bfeb3b2"
integrity sha512-YYCSkwhNUYcS2CT1HWPbQvuw8oIvClzl9sjXtp7dPfT/13m3QYJ0ZvgcY8Y5samTLQw1zC9sBOrou25Qm+DLEQ==
"@odigos/ui-components@^0.0.37":
version "0.0.37"
resolved "https://registry.yarnpkg.com/@odigos/ui-components/-/ui-components-0.0.37.tgz#27c0a4c346e28af69300c16d40d63e457250e605"
integrity sha512-ZV0+v0g63YHQn1+tLw0wlXrloaQt3SKZ+fENXVe/SsUO1AJ5XGdVClymCx3hmk/OJnr5HsOPu8B65whT9Hk6xQ==
dependencies:
"@odigos/ui-icons" "^0.0.2"
"@odigos/ui-theme" "^0.0.2"
Expand Down Expand Up @@ -556,6 +563,17 @@
react-dom "^19.0.0"
styled-components "^6.1.14"

"@odigos/ui-utils@^0.0.6":
version "0.0.6"
resolved "https://registry.yarnpkg.com/@odigos/ui-utils/-/ui-utils-0.0.6.tgz#10084c433151081c6ff1e3031fae221169f9ca51"
integrity sha512-s30fM28QBnYFmesalsJSn/ELom+AnIAB8JRNfsN5iC2WMtJjJ+vtLBzLxEPFT9uUc/493n5YC840NfGyP6yjPQ==
dependencies:
"@odigos/ui-icons" "^0.0.2"
javascript-time-ago "^2.5.11"
react "^19.0.0"
react-dom "^19.0.0"
styled-components "^6.1.14"

"@rtsao/scc@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8"
Expand Down Expand Up @@ -815,10 +833,10 @@
dependencies:
undici-types "~6.20.0"

"@types/[email protected].0":
version "22.13.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.0.tgz#d376dd9a0ee2f9382d86c2d5d7beb4d198b4ea8c"
integrity sha512-ClIbNe36lawluuvq3+YYhnIN2CELi+6q8NpnM7PYp4hBn/TatfboPgVSm2rwKRfnV2M+Ty9GWDFI64KEe+kysA==
"@types/[email protected].1":
version "22.13.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.1.tgz#a2a3fefbdeb7ba6b89f40371842162fac0934f33"
integrity sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==
dependencies:
undici-types "~6.20.0"

Expand Down Expand Up @@ -3403,6 +3421,13 @@ [email protected], react-dom@^19.0.0:
dependencies:
scheduler "^0.25.0"

react-error-boundary@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-5.0.0.tgz#6b6c7e075c922afb0283147e5b084efa44e68570"
integrity sha512-tnjAxG+IkpLephNcePNA7v6F/QpWLH8He65+DmedchDwg162JZqx4NmbXj0mlAYVVEd81OW7aFhmbsScYfiAFQ==
dependencies:
"@babel/runtime" "^7.12.5"

react-flow-renderer@^10.3.17:
version "10.3.17"
resolved "https://registry.yarnpkg.com/react-flow-renderer/-/react-flow-renderer-10.3.17.tgz#06d6ecef5559ba5d3e64d2c8dcb74c43071d62b1"
Expand Down

0 comments on commit b1b5d15

Please sign in to comment.