From 4867234eacdcda96f5be4d760c75e46a5568866e Mon Sep 17 00:00:00 2001 From: Anso Date: Thu, 7 May 2026 23:45:05 -0400 Subject: [PATCH] chore(resources): remove Largest 5 and Recently changed cards from Volumes tab (#981) The two landing cards above the volumes table did not earn their space and made the Volumes view feel cluttered. Drop the cards, the unused TabLanding component, and the helpers that only fed it. --- frontend/src/components/ResourcesView.tsx | 47 +------- .../src/components/resources/TabLanding.tsx | 109 ------------------ 2 files changed, 1 insertion(+), 155 deletions(-) delete mode 100644 frontend/src/components/resources/TabLanding.tsx diff --git a/frontend/src/components/ResourcesView.tsx b/frontend/src/components/ResourcesView.tsx index 6700720f..5ece7c21 100644 --- a/frontend/src/components/ResourcesView.tsx +++ b/frontend/src/components/ResourcesView.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect, useMemo } from 'react'; +import { useState, useEffect } from 'react'; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Tabs, TabsContent, TabsList, TabsTrigger, TabsHighlight, TabsHighlightItem } from "@/components/ui/tabs"; @@ -37,22 +37,9 @@ import { FootprintTreemap } from './resources/FootprintTreemap'; import { ImageDetailsSheet } from './resources/ImageDetailsSheet'; import { VolumeBrowserSheet } from './resources/VolumeBrowserSheet'; import { NetworkDetailSheet, type NetworkInspectData } from './resources/NetworkDetailSheet'; -import { TabLanding, type TabLandingEntry } from './resources/TabLanding'; const NetworkTopologyView = lazy(() => import('./NetworkTopologyView')); -const RECENT_WINDOW_MS = 24 * 60 * 60 * 1000; - -function ageLabel(ms: number): string { - const minutes = Math.max(0, Math.round((Date.now() - ms) / 60000)); - if (minutes < 1) return 'just now'; - if (minutes < 60) return `${minutes}m ago`; - const hours = Math.round(minutes / 60); - if (hours < 24) return `${hours}h ago`; - const days = Math.round(hours / 24); - return `${days}d ago`; -} - // ── Interfaces ───────────────────────────────────────────────────────────────── interface UsageData { @@ -627,28 +614,6 @@ export default function ResourcesView() { setConfirmPrune({ target: 'images', scope: 'all' }); }; - const volumeLandings = useMemo(() => { - const largest: TabLandingEntry[] = [...volumes] - .sort((a, b) => b.Size - a.Size) - .slice(0, 5) - .map(vol => ({ - key: vol.Name, - primary: vol.Name, - secondary: vol.Size > 0 ? formatBytes(vol.Size) : '-', - })); - const now = Date.now(); - const recent: TabLandingEntry[] = volumes - .filter(v => !!v.CreatedAt && now - new Date(v.CreatedAt).getTime() <= RECENT_WINDOW_MS) - .sort((a, b) => new Date(b.CreatedAt ?? 0).getTime() - new Date(a.CreatedAt ?? 0).getTime()) - .slice(0, 5) - .map(vol => ({ - key: vol.Name, - primary: vol.Name, - secondary: vol.CreatedAt ? ageLabel(new Date(vol.CreatedAt).getTime()) : '-', - })); - return { largest, recent }; - }, [volumes]); - return (
@@ -896,16 +861,6 @@ export default function ResourcesView() { {/* Volumes */} - {!isLoading && volumes.length > 0 && ( - - )} void; - accent?: 'brand' | 'warning'; -} - -function LandingCard({ label, subtitle, entries, emptyLabel, onEntryClick, accent = 'brand' }: LandingCardProps) { - const accentClass = accent === 'warning' ? 'text-warning' : 'text-brand'; - return ( -
-
- - {label} - - {subtitle ? ( - {subtitle} - ) : null} -
- {entries.length === 0 ? ( -
- {emptyLabel} -
- ) : ( -
    - {entries.map(entry => ( -
  • - -
  • - ))} -
- )} -
- ); -} - -interface TabLandingProps { - largestLabel?: string; - largestSubtitle?: string; - largestEntries: TabLandingEntry[]; - largestEmpty: string; - recentLabel?: string; - recentSubtitle?: string; - recentEntries: TabLandingEntry[]; - recentEmpty: string; - onLargestClick?: (entry: TabLandingEntry) => void; - onRecentClick?: (entry: TabLandingEntry) => void; -} - -export function TabLanding({ - largestLabel = 'Largest 5', - largestSubtitle, - largestEntries, - largestEmpty, - recentLabel = 'Recently changed', - recentSubtitle, - recentEntries, - recentEmpty, - onLargestClick, - onRecentClick, -}: TabLandingProps) { - const largestTop = useMemo(() => largestEntries.slice(0, 5), [largestEntries]); - const recentTop = useMemo(() => recentEntries.slice(0, 5), [recentEntries]); - - return ( -
- - -
- ); -}