diff --git a/ui/react-app/src/Router.tsx b/ui/react-app/src/Router.tsx
index 94d32a23..0dc422e8 100644
--- a/ui/react-app/src/Router.tsx
+++ b/ui/react-app/src/Router.tsx
@@ -2,13 +2,17 @@
import { Suspense, lazy } from 'react';
import { Route, Routes } from 'react-router-dom';
-const ViewStatus = lazy(() => import('./views/ViewStatus'));
+const StatusView = lazy(() => import('./views/StatusView'));
+const AlertView = lazy(() => import('./views/AlertView'));
+
+const routePrefix = '/react-app';
function Router() {
return (
- } />
+ } />
+ } />
);
diff --git a/ui/react-app/src/client/alert.ts b/ui/react-app/src/client/alert.ts
new file mode 100644
index 00000000..4c52b5bf
--- /dev/null
+++ b/ui/react-app/src/client/alert.ts
@@ -0,0 +1,40 @@
+import { useQuery } from '@tanstack/react-query';
+import buildURL from '../utils/url-builder';
+import { fetchJson } from '../utils/fetch';
+
+const resource = 'alerts/groups';
+
+export interface Receiver {
+ name: string;
+}
+
+export interface AlertStatus {
+ state: 'active' | 'unprocessed' | 'suppressed';
+ inhibitedBy: string[];
+ silenceby: string[];
+}
+
+export interface Alert {
+ labels: Record;
+ annotations: Record;
+ generatorURL?: string;
+ receivers: Receiver[];
+ fingerprint: string;
+ startsAt: string;
+ endsAt: string;
+ updatedAt: string;
+ status: AlertStatus;
+}
+
+export interface AlertGroup {
+ labels: Record;
+ receiver: Receiver;
+ alerts: Alert[];
+}
+
+export function useAlertGroups() {
+ return useQuery([], () => {
+ const url = buildURL({ resource: resource });
+ return fetchJson(url);
+ });
+}
diff --git a/ui/react-app/src/client/am-client.ts b/ui/react-app/src/client/status.ts
similarity index 100%
rename from ui/react-app/src/client/am-client.ts
rename to ui/react-app/src/client/status.ts
diff --git a/ui/react-app/src/components/navbar.tsx b/ui/react-app/src/components/navbar.tsx
index 9debf8a7..87a1eb4a 100644
--- a/ui/react-app/src/components/navbar.tsx
+++ b/ui/react-app/src/components/navbar.tsx
@@ -27,8 +27,18 @@ export default function Navbar(): JSX.Element {
AlertManager
-
-
+
+
-
+
diff --git a/ui/react-app/src/views/AlertView.tsx b/ui/react-app/src/views/AlertView.tsx
new file mode 100644
index 00000000..b382335f
--- /dev/null
+++ b/ui/react-app/src/views/AlertView.tsx
@@ -0,0 +1,15 @@
+import { useAlertGroups } from '../client/alert';
+import { Container, Typography } from '@mui/material';
+
+export default function AlertView() {
+ const { data } = useAlertGroups();
+ if (data === undefined || data === null) {
+ return null;
+ }
+
+ return (
+
+ Alert
+
+ );
+}
diff --git a/ui/react-app/src/views/ViewStatus.tsx b/ui/react-app/src/views/StatusView.tsx
similarity index 94%
rename from ui/react-app/src/views/ViewStatus.tsx
rename to ui/react-app/src/views/StatusView.tsx
index f1e166db..dc047d93 100644
--- a/ui/react-app/src/views/ViewStatus.tsx
+++ b/ui/react-app/src/views/StatusView.tsx
@@ -13,7 +13,7 @@ import {
Theme,
Typography,
} from '@mui/material';
-import { useAMStatus } from '../client/am-client';
+import { useAMStatus } from '../client/status';
const tableStyle: SxProps = {
[`& .${tableCellClasses.root}`]: {
@@ -42,9 +42,9 @@ function CustomTableCell(props: tableCellProperties) {
);
}
-export default function ViewStatus() {
+export default function StatusView() {
const { data } = useAMStatus();
- if (data === undefined || data === null) {
+ if (data === undefined || data === null || (Array.isArray(data) && data.length === 0)) {
return null;
}