diff --git a/packages/api/src/routers/api/alerts.ts b/packages/api/src/routers/api/alerts.ts index b43f997d9..e7bd1d122 100644 --- a/packages/api/src/routers/api/alerts.ts +++ b/packages/api/src/routers/api/alerts.ts @@ -79,7 +79,12 @@ router.get('/', async (req, res, next) => { charts: alert.dashboardId.charts .filter(chart => chart.id === alert.chartId) .map(chart => _.pick(chart, ['id', 'name'])), - ..._.pick(alert.dashboardId, ['_id', 'name', 'updatedAt']), + ..._.pick(alert.dashboardId, [ + '_id', + 'name', + 'updatedAt', + 'tags', + ]), }, }), ...(alert.logView && { @@ -88,6 +93,7 @@ router.get('/', async (req, res, next) => { 'createdAt', 'name', 'updatedAt', + 'tags', ]), }), ..._.pick(alert, [ diff --git a/packages/app/src/AlertsPage.tsx b/packages/app/src/AlertsPage.tsx index 33c6400fa..ad193c9c6 100644 --- a/packages/app/src/AlertsPage.tsx +++ b/packages/app/src/AlertsPage.tsx @@ -3,6 +3,11 @@ import Head from 'next/head'; import Link from 'next/link'; import cx from 'classnames'; import { formatRelative } from 'date-fns'; +import { + DelimitedArrayParam, + useQueryParam, + withDefault, +} from 'use-query-params'; import { Alert as MAlert, Badge, @@ -16,6 +21,7 @@ import { import api from './api'; import { withAppNav } from './layout'; +import { Tags } from './Tags'; import type { Alert, AlertHistory, LogView } from './types'; import { AlertState } from './types'; @@ -27,6 +33,7 @@ type AlertData = Alert & { _id: string; name: string; charts: { id: string; name: string }[]; + tags?: string[]; }; logView?: LogView; }; @@ -203,6 +210,7 @@ function AlertCardList({ alerts }: { alerts: AlertData[] }) { alert.state === AlertState.DISABLED || alert.state === AlertState.INSUFFICIENT_DATA, ); + return (
{alarmAlerts.length > 0 && ( @@ -247,10 +255,31 @@ function AlertCardList({ alerts }: { alerts: AlertData[] }) { export default function AlertsPage() { const { data, isError, isLoading } = api.useAlerts(); - const alerts = data?.data; + const alerts = React.useMemo( + () => (data?.data || []) as AlertData[], + [data?.data], + ); // TODO: Error and loading states + const [_tags, setTags] = useQueryParam( + 'tags', + withDefault(DelimitedArrayParam, [] as (string | null)[]), + { updateType: 'replaceIn' }, + ); + const tags = React.useMemo(() => _tags.filter(Boolean) as string[], [_tags]); + + const filteredAlerts = React.useMemo(() => { + if (!tags.length) { + return alerts; + } + return alerts.filter(alert => + [...(alert.dashboard?.tags || []), ...(alert.logView?.tags || [])].some( + tag => tags.includes(tag), + ), + ); + }, [tags, alerts]); + return (
@@ -280,7 +309,44 @@ export default function AlertsPage() { ) : isError ? (
Error
) : alerts?.length ? ( - + <> + + + + + {tags.length > 0 && ( + + )} + + + ) : (
No alerts created yet