feat(alerts): DS alignment + AGENT_LIFECYCLE + single-inbox redesign #146

Merged
hsiegeln merged 49 commits from feat/alerts-ds-alignment into main 2026-04-21 19:53:12 +02:00
Showing only changes of commit be703eb71d - Show all commits

View File

@@ -11,6 +11,8 @@ type AlertSeverity = NonNullable<AlertDto['severity']>;
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<string, unknown> = { 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'] });
},
});
}