From be703eb71dd7e85dd5e428af01cac8e22e3ad8d0 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Tue, 21 Apr 2026 19:00:18 +0200 Subject: [PATCH] feat(ui/alerts): hooks for bulk-ack, delete, bulk-delete, restore + acked/read filter params - useAlerts gains acked/read filter params threaded into query + queryKey - new mutations: useBulkAckAlerts, useDeleteAlert, useBulkDeleteAlerts, useRestoreAlert - all cache-invalidate the alerts list and unread-count on success Co-Authored-By: Claude Opus 4.7 (1M context) --- ui/src/api/queries/alerts.ts | 83 +++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/ui/src/api/queries/alerts.ts b/ui/src/api/queries/alerts.ts index eab53cb0..72fd04a0 100644 --- a/ui/src/api/queries/alerts.ts +++ b/ui/src/api/queries/alerts.ts @@ -11,6 +11,8 @@ type AlertSeverity = NonNullable; export interface AlertsFilter { state?: AlertState | AlertState[]; severity?: AlertSeverity | AlertSeverity[]; + acked?: boolean; + read?: boolean; ruleId?: string; limit?: number; } @@ -47,7 +49,7 @@ export function useAlerts(filter: AlertsFilter = {}) { const severityKey = severityArr ? [...severityArr].sort() : null; return useQuery({ - queryKey: ['alerts', env, 'list', fetchLimit, stateKey, severityKey], + queryKey: ['alerts', env, 'list', fetchLimit, stateKey, severityKey, filter.acked ?? null, filter.read ?? null], enabled: !!env, refetchInterval: 30_000, refetchIntervalInBackground: false, @@ -56,6 +58,8 @@ export function useAlerts(filter: AlertsFilter = {}) { const query: Record = { limit: fetchLimit }; if (stateArr && stateArr.length > 0) query.state = stateArr; if (severityArr && severityArr.length > 0) query.severity = severityArr; + if (filter.acked !== undefined) query.acked = filter.acked; + if (filter.read !== undefined) query.read = filter.read; const { data, error } = await apiClient.GET( '/environments/{envSlug}/alerts', { @@ -180,3 +184,80 @@ export function useBulkReadAlerts() { }, }); } + +/** Acknowledge a batch of alert instances. */ +export function useBulkAckAlerts() { + const env = useSelectedEnv(); + const qc = useQueryClient(); + return useMutation({ + mutationFn: async (ids: string[]) => { + if (!env) throw new Error('no env'); + const { error } = await apiClient.POST( + '/environments/{envSlug}/alerts/bulk-ack', + { params: { path: { envSlug: env } }, body: { instanceIds: ids } } as any, + ); + if (error) throw error; + }, + onSuccess: () => qc.invalidateQueries({ queryKey: ['alerts', env] }), + }); +} + +/** Delete (soft) a single alert instance. */ +export function useDeleteAlert() { + const env = useSelectedEnv(); + const qc = useQueryClient(); + return useMutation({ + mutationFn: async (id: string) => { + if (!env) throw new Error('no env'); + const { error } = await apiClient.DELETE( + '/environments/{envSlug}/alerts/{id}', + { params: { path: { envSlug: env, id } } } as any, + ); + if (error) throw error; + }, + onSuccess: () => { + qc.invalidateQueries({ queryKey: ['alerts', env] }); + qc.invalidateQueries({ queryKey: ['alerts', env, 'unread-count'] }); + }, + }); +} + +/** Delete (soft) a batch of alert instances. */ +export function useBulkDeleteAlerts() { + const env = useSelectedEnv(); + const qc = useQueryClient(); + return useMutation({ + mutationFn: async (ids: string[]) => { + if (!env) throw new Error('no env'); + const { error } = await apiClient.POST( + '/environments/{envSlug}/alerts/bulk-delete', + { params: { path: { envSlug: env } }, body: { instanceIds: ids } } as any, + ); + if (error) throw error; + }, + onSuccess: () => { + qc.invalidateQueries({ queryKey: ['alerts', env] }); + qc.invalidateQueries({ queryKey: ['alerts', env, 'unread-count'] }); + }, + }); +} + +/** Restore a soft-deleted alert instance. */ +export function useRestoreAlert() { + const env = useSelectedEnv(); + const qc = useQueryClient(); + return useMutation({ + mutationFn: async (id: string) => { + if (!env) throw new Error('no env'); + const { error } = await apiClient.POST( + '/environments/{envSlug}/alerts/{id}/restore', + { params: { path: { envSlug: env, id } } } as any, + ); + if (error) throw error; + }, + onSuccess: () => { + qc.invalidateQueries({ queryKey: ['alerts', env] }); + qc.invalidateQueries({ queryKey: ['alerts', env, 'unread-count'] }); + }, + }); +}