Files
headquarter/apps/web/src/api/notifications.ts
T
Alex Blank 2b5223097f feat: filter notifications to warnings/errors/ready only and add clear-all button
Notification filtering:
- lifecycle_hooks.py: only instance.error and instance.health_changed
  with status=running generate notifications. All other lifecycle events
  (created, started, stopped, restarted, deleted) are filtered out.
- health_monitor.py: only error and unhealthy states generate notifications.
  Running/recovered state no longer creates info notifications.
- _derive_title now maps instance.health_changed to "Container ready".

Clear-all button:
- Added dismiss_all() to NotificationService
- Added DELETE /notifications endpoint for bulk dismiss
- Frontend: clearAllNotifications API, clearAll in notification context,
  "Clear all" button in notification drawer alongside "Mark all as read"
- Added CSS for .notification-clear-all with danger hover state
- Updated notification-center tests

Quality gates: pytest (21 passed), vitest (11 passed)
2026-05-29 16:42:31 +02:00

74 lines
1.8 KiB
TypeScript

import { apiClient } from "./client";
export interface NotificationItem {
id: string;
user_id: string;
category: string;
severity: "info" | "warning" | "error" | "success";
title: string;
message: string | null;
source_type: string | null;
source_id: string | null;
metadata: Record<string, unknown>;
read_at: string | null;
dismissed_at: string | null;
created_at: string;
}
export interface NotificationListResponse {
items: NotificationItem[];
total: number;
limit: number;
offset: number;
}
export interface UnreadCountResponse {
count: number;
}
export interface MarkAllReadResponse {
marked_count: number;
}
export interface ClearAllResponse {
cleared_count: number;
}
export const getNotifications = async (): Promise<NotificationListResponse> => {
const response =
await apiClient.get<NotificationListResponse>("/notifications");
return response.data;
};
export const getUnreadCount = async (): Promise<number> => {
const response = await apiClient.get<UnreadCountResponse>(
"/notifications/unread",
);
return response.data.count;
};
export const markNotificationRead = async (
id: string,
): Promise<NotificationItem> => {
const response = await apiClient.patch<NotificationItem>(
`/notifications/${id}/read`,
);
return response.data;
};
export const markAllNotificationsRead = async (): Promise<number> => {
const response = await apiClient.post<MarkAllReadResponse>(
"/notifications/mark-all-read",
);
return response.data.marked_count;
};
export const dismissNotification = async (id: string): Promise<void> => {
await apiClient.delete(`/notifications/${id}`);
};
export const clearAllNotifications = async (): Promise<number> => {
const response = await apiClient.delete<ClearAllResponse>("/notifications");
return response.data.cleared_count;
};