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; }