77c6b62ee2
Web UI rework. - Migrate BackupAlertsTable, BackupJobsTable, BackupRunsTable, BackupsPage, BackupDashboardWidget off @mui (shadcn Table + Badge severity variants: success=chart-2, warning=chart-3, destructive) - App.tsx IA: Backups now top-level nav (DatabaseBackup icon); Media surface primary at /media; /applications -> /media redirect in both route trees (mirrors /monitoring -> /observability) Gate: build + lint + test green.
74 lines
1.9 KiB
TypeScript
74 lines
1.9 KiB
TypeScript
import { Badge } from "@/components/ui/badge";
|
|
import { Button } from "@/components/ui/button";
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow,
|
|
} from "@/components/ui/table";
|
|
import type { BackupAlert } from "../types/backups";
|
|
|
|
interface Props {
|
|
alerts: BackupAlert[];
|
|
onAcknowledge: (alertId: string) => void;
|
|
}
|
|
|
|
function formatTimestamp(ts: number): string {
|
|
return new Date(ts * 1000).toLocaleString();
|
|
}
|
|
|
|
type SeverityVariant = "destructive" | "warning";
|
|
|
|
/**
|
|
* Map an alert severity onto a Badge variant per design §2.3.
|
|
* `critical` → destructive (chart-4); `warning` → warning (chart-3).
|
|
*/
|
|
function severityVariant(severity: string): SeverityVariant {
|
|
return severity === "critical" ? "destructive" : "warning";
|
|
}
|
|
|
|
export default function BackupAlertsTable({ alerts, onAcknowledge }: Props) {
|
|
return (
|
|
<div className="overflow-hidden rounded-lg border border-border">
|
|
<Table aria-label="Backup alerts">
|
|
<TableHeader>
|
|
<TableRow className="bg-card hover:bg-card">
|
|
<TableHead>Severity</TableHead>
|
|
<TableHead>Type</TableHead>
|
|
<TableHead>Message</TableHead>
|
|
<TableHead>Created</TableHead>
|
|
<TableHead>Actions</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
{alerts.map((alert) => (
|
|
<TableRow key={alert.id}>
|
|
<TableCell>
|
|
<Badge variant={severityVariant(alert.severity)}>
|
|
{alert.severity}
|
|
</Badge>
|
|
</TableCell>
|
|
<TableCell>{alert.alert_type}</TableCell>
|
|
<TableCell>{alert.message}</TableCell>
|
|
<TableCell>{formatTimestamp(alert.created_at)}</TableCell>
|
|
<TableCell>
|
|
{!alert.acknowledged && (
|
|
<Button
|
|
size="sm"
|
|
variant="outline"
|
|
onClick={() => onAcknowledge(alert.id)}
|
|
>
|
|
Acknowledge
|
|
</Button>
|
|
)}
|
|
</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</div>
|
|
);
|
|
}
|