From 37413c1020b3562a24884a57c43425c07b3526af Mon Sep 17 00:00:00 2001 From: Anso Date: Tue, 19 May 2026 18:19:57 -0400 Subject: [PATCH] feat(cloud-backup): paginate cloud snapshots list (#1110) Splits the Cloud Snapshots panel in Settings > Cloud Backup into pages of 10 items with prev/next chevrons and a page counter, matching the existing pattern shipped in Fleet Snapshots. Long-running deployments with many snapshots no longer overflow the settings panel. The empty state, refresh, download, and delete flows are unchanged. The safePage clamp handles the last-page-delete case without extra reset logic. Chevron buttons carry aria-label values for screen reader users. --- .../settings/CloudBackupSection.tsx | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/settings/CloudBackupSection.tsx b/frontend/src/components/settings/CloudBackupSection.tsx index 3704f215..145419c5 100644 --- a/frontend/src/components/settings/CloudBackupSection.tsx +++ b/frontend/src/components/settings/CloudBackupSection.tsx @@ -10,7 +10,7 @@ import { toast } from '@/components/ui/toast-store'; import { apiFetch } from '@/lib/api'; import { formatBytes } from '@/lib/utils'; import { AdmiralGate } from '@/components/AdmiralGate'; -import { Cloud, CloudOff, RefreshCw, CheckCircle2, Loader2, Trash2, Download } from 'lucide-react'; +import { Cloud, CloudOff, RefreshCw, CheckCircle2, Loader2, Trash2, Download, ChevronLeft, ChevronRight } from 'lucide-react'; import { SettingsPrimaryButton } from './SettingsActions'; import { useMastheadStats } from './MastheadStatsContext'; @@ -64,6 +64,8 @@ const PROVIDER_OPTIONS = [ const PANEL_CLASS = 'rounded-lg border border-card-border border-t-card-border-top bg-card shadow-card-bevel p-4 space-y-3'; +const PAGE_SIZE = 10; + export function CloudBackupSection() { const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); @@ -76,6 +78,12 @@ export function CloudBackupSection() { const [testing, setTesting] = useState(false); const [provisioning, setProvisioning] = useState(false); const [deleteKey, setDeleteKey] = useState(null); + const [page, setPage] = useState(0); + + const totalPages = Math.max(1, Math.ceil(snapshots.length / PAGE_SIZE)); + const safePage = Math.min(page, totalPages - 1); + const pagedSnapshots = snapshots.slice(safePage * PAGE_SIZE, (safePage + 1) * PAGE_SIZE); + const needsPagination = snapshots.length > PAGE_SIZE; const loadConfig = useCallback(async () => { try { @@ -449,9 +457,24 @@ export function CloudBackupSection() {
Cloud Snapshots - +
+ {needsPagination && ( + <> + + + {safePage + 1} / {totalPages} + + + + )} + +
{snapshots.length === 0 ? (
@@ -460,7 +483,7 @@ export function CloudBackupSection() {
) : (
    - {snapshots.map(s => ( + {pagedSnapshots.map(s => (
  • {s.objectKey.split('/').pop()}