diff --git a/ui/src/app/error.tsx b/ui/src/app/error.tsx
new file mode 100644
index 00000000..b100986d
--- /dev/null
+++ b/ui/src/app/error.tsx
@@ -0,0 +1,30 @@
+'use client';
+
+import { useState } from 'react';
+import ApiErrorModal from '@/components/modal/api-error-modal';
+
+interface ErrorProps {
+ reset: () => void;
+}
+
+const Error = ({ reset }: ErrorProps) => {
+ const [open, setOpen] = useState(true);
+
+ const handleClose = () => {
+ setOpen(false);
+ reset();
+ };
+
+ return (
+
+ );
+};
+
+export default Error;
diff --git a/ui/src/app/layout.tsx b/ui/src/app/layout.tsx
index 30116baf..c3dd7247 100644
--- a/ui/src/app/layout.tsx
+++ b/ui/src/app/layout.tsx
@@ -25,13 +25,13 @@ const RootLayout = ({
}: Readonly<{
children?: React.ReactNode;
}>) => (
-
-
-
- {children}
-
-
-
+
+
+
+ {children}
+
+
+
);
export default RootLayout;
diff --git a/ui/src/components/modal/api-error-modal.tsx b/ui/src/components/modal/api-error-modal.tsx
index b37d39e0..5a5a21f8 100644
--- a/ui/src/components/modal/api-error-modal.tsx
+++ b/ui/src/components/modal/api-error-modal.tsx
@@ -13,7 +13,7 @@ import {
import Link from 'next/link';
import { useState } from 'react';
-const ApiErrorModal = ({ open }: { open: boolean }) => {
+const ApiErrorModal = ({ open, onClose }: { open: boolean }) => {
const [openApiErrorModal, setOpenApiErrorModal] = useState(open);
/**
@@ -21,7 +21,9 @@ const ApiErrorModal = ({ open }: { open: boolean }) => {
*/
const close = () => {
setOpenApiErrorModal(false);
+ onClose();
};
+
return (
diff --git a/ui/src/lib/http-client.ts b/ui/src/lib/http-client.ts
index a4cb2afb..a05b2b63 100644
--- a/ui/src/lib/http-client.ts
+++ b/ui/src/lib/http-client.ts
@@ -260,10 +260,11 @@ export const deleteRequestAsync = async (
*
* @returns The res.json()
*/
-const handleFetch = (res: Response, httpMethod: HTTPMethod) => {
+const handleFetch = async (res: Response, httpMethod: HTTPMethod) => {
if (!res.ok) {
const error = Error(`${res.status} error from ${httpMethod} ${res.url}`);
- sendStackTrace(error.stack as string);
+ await sendStackTrace(error.stack as string);
+ throw error;
}
return res.json();
};
diff --git a/ui/tests/lib/fetchers.test.ts b/ui/tests/lib/fetchers.test.ts
index ae069236..2d0046a2 100644
--- a/ui/tests/lib/fetchers.test.ts
+++ b/ui/tests/lib/fetchers.test.ts
@@ -151,7 +151,8 @@ describe('fetchers', () => {
fetchMock.mockResponse(JSON.stringify(mockError), { status: 500 });
let res = ownedGrouping(groupPaths, page, size, sortString, isAscending);
await jest.advanceTimersByTimeAsync(5000);
- expect(await res).toEqual(mockError);
+ expect(await res).toBeInstanceOf(Error);
+ expect((await res).message).toMatch(/500 error from POST/);
fetchMock.mockReject(() => Promise.reject(mockError));
res = ownedGrouping(groupPaths, page, size, sortString, isAscending);