feat(dashboard): alerts page + toast notifications + polish

- Full Alerts page with active alerts, history table, subscriptions
- Active alert cards with severity styling and acknowledge button
- Alert history table with type/severity filtering and pagination
- Subscription viewer showing mesh subscriptions
- ToastProvider for app-wide toast notifications
- Toast notifications triggered on WebSocket alert_fired messages
- Auto-dismiss toasts after 8 seconds, click to navigate
- Page titles on all pages (Dashboard/Mesh/Environment/Config/Alerts)
- Improved alert_routes.py with proper pending alert handling
- Added AlertHistoryItem, Subscription types to api.ts
- Added fetchAlertHistory, fetchSubscriptions functions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
K7ZVX 2026-05-13 01:36:31 +00:00
commit f8874104ad
14 changed files with 1173 additions and 366 deletions

View file

@ -93,6 +93,34 @@ export interface Alert {
scope_value?: string
}
export interface AlertHistoryItem {
id?: number
type: string
severity: string
message: string
timestamp: string
duration?: number
scope_type?: string
scope_value?: string
resolved_at?: string
}
export interface AlertHistoryResponse {
items: AlertHistoryItem[]
total: number
}
export interface Subscription {
id: number
user_id: string
sub_type: string
schedule_time?: string
schedule_day?: string
scope_type: string
scope_value?: string
enabled: boolean
}
export interface EnvStatus {
enabled: boolean
feeds: EnvFeedHealth[]
@ -209,6 +237,24 @@ export async function fetchAlerts(): Promise<Alert[]> {
return fetchJson<Alert[]>('/api/alerts/active')
}
export async function fetchAlertHistory(
limit: number = 50,
offset: number = 0,
type?: string,
severity?: string
): Promise<AlertHistoryResponse | AlertHistoryItem[]> {
const params = new URLSearchParams()
params.set('limit', limit.toString())
params.set('offset', offset.toString())
if (type && type !== 'all') params.set('type', type)
if (severity && severity !== 'all') params.set('severity', severity)
return fetchJson<AlertHistoryResponse | AlertHistoryItem[]>(`/api/alerts/history?${params.toString()}`)
}
export async function fetchSubscriptions(): Promise<Subscription[]> {
return fetchJson<Subscription[]>('/api/subscriptions')
}
export async function fetchEnvStatus(): Promise<EnvStatus> {
return fetchJson<EnvStatus>('/api/env/status')
}