diff --git a/ui/app/api/mirrors/alerts/route.ts b/ui/app/api/mirrors/alerts/route.ts
index ecb9891cbd..5a2d52ed55 100644
--- a/ui/app/api/mirrors/alerts/route.ts
+++ b/ui/app/api/mirrors/alerts/route.ts
@@ -19,3 +19,21 @@ export async function POST(request: Request) {
}
return new Response(JSON.stringify(mirrorStatus));
}
+
+export async function PUT(request: Request) {
+ const { mirrorIDStringList } = await request.json();
+ const mirrorIDList: bigint[] = mirrorIDStringList.map((id: string) =>
+ BigInt(id)
+ );
+ const success = await prisma.flow_errors.updateMany({
+ where: {
+ id: {
+ in: mirrorIDList,
+ },
+ },
+ data: {
+ ack: true,
+ },
+ });
+ return new Response(JSON.stringify(success.count));
+}
diff --git a/ui/app/mirrors/edit/[mirrorId]/cdcDetails.tsx b/ui/app/mirrors/edit/[mirrorId]/cdcDetails.tsx
index e7729c487d..738218c64f 100644
--- a/ui/app/mirrors/edit/[mirrorId]/cdcDetails.tsx
+++ b/ui/app/mirrors/edit/[mirrorId]/cdcDetails.tsx
@@ -32,10 +32,9 @@ function CdcDetails({ syncs, createdAt, mirrorConfig }: props) {
diff --git a/ui/app/mirrors/errors/[mirrorName]/ackbutton.tsx b/ui/app/mirrors/errors/[mirrorName]/ackbutton.tsx
new file mode 100644
index 0000000000..3247e61d88
--- /dev/null
+++ b/ui/app/mirrors/errors/[mirrorName]/ackbutton.tsx
@@ -0,0 +1,56 @@
+'use client';
+import { Button } from '@/lib/Button';
+import { Label } from '@/lib/Label';
+import { ProgressCircle } from '@/lib/ProgressCircle';
+import { useState } from 'react';
+import { toast } from 'react-toastify';
+
+const notifyErr = (errMsg: string) => {
+ toast.error(errMsg, {
+ position: toast.POSITION.BOTTOM_CENTER,
+ });
+};
+
+const AckButton = ({ ack, id }: { ack: boolean; id: number | bigint }) => {
+ const [loading, setLoading] = useState(false);
+ const [updated, setUpdated] = useState(false);
+ // handleAck updates ack to true for the given mirrorId list
+ const handleAck = async (mirrorIDList: (bigint | number)[]) => {
+ setLoading(true);
+ const updateRes = await fetch('/api/mirrors/alerts', {
+ method: 'PUT',
+ body: JSON.stringify({
+ mirrorIDStringList: mirrorIDList.map((id) => id.toString()),
+ }),
+ }).then((res) => res.json());
+ setLoading(false);
+ if (!updateRes || updateRes === 0) {
+ notifyErr('Something went wrong when trying to acknowledge');
+ return;
+ }
+ setUpdated(true);
+ };
+ return (
+ <>
+ {ack !== true && updated !== true ? (
+
+ ) : (
+
+ )}
+ >
+ );
+};
+
+export default AckButton;
diff --git a/ui/app/mirrors/errors/[mirrorName]/page.tsx b/ui/app/mirrors/errors/[mirrorName]/page.tsx
index 97efca644a..4a048a10bb 100644
--- a/ui/app/mirrors/errors/[mirrorName]/page.tsx
+++ b/ui/app/mirrors/errors/[mirrorName]/page.tsx
@@ -3,6 +3,9 @@ import prisma from '@/app/utils/prisma';
import TimeLabel from '@/components/TimeComponent';
import { Label } from '@/lib/Label';
import { Table, TableCell, TableRow } from '@/lib/Table';
+import { ToastContainer } from 'react-toastify';
+import 'react-toastify/dist/ReactToastify.css';
+import AckButton from './ackbutton';
type MirrorErrorProps = {
params: { mirrorName: string };
@@ -14,62 +17,72 @@ const MirrorError = async ({ params: { mirrorName } }: MirrorErrorProps) => {
flow_name: mirrorName,
error_type: 'error',
},
- distinct: ['error_message'],
orderBy: {
error_timestamp: 'desc',
},
});
return (
-
-
-
-
-
-
-
-
- Type
-
- Message
-
- }
+ <>
+
+
+
+
+
+
+
- {mirrorErrors.map((mirrorError) => (
-
-
- {mirrorError.error_type.toUpperCase()}
-
-
-
-
-
- {mirrorError.error_message}
-
-
- ))}
-
+
+ Type
+
+
+
+ Message
+
+
+ }
+ >
+ {mirrorErrors.map((mirrorError) => (
+
+
+ {mirrorError.error_type.toUpperCase()}
+
+
+
+
+
+ {mirrorError.error_message}
+
+
+
+
+
+ ))}
+
+
-
+