import { useCallback, useEffect, useState } from 'react' import { ChevronRight, Database, Download, ExternalLink, Folder, HardDrive, Loader2, RefreshCw } from 'lucide-react' import { cn } from '../../lib/utils' import { subTabActive, subTabIdle } from '../../lib/tabActive' type Bucket = { name: string; created?: string; has_objects?: boolean } type S3Item = { type: string; name?: string; prefix?: string; key?: string; size_human?: string; modified?: string } export function StorageView() { const [health, setHealth] = useState<{ ok: boolean; endpoint?: string; bucket_names?: string[]; error?: string } | null>(null) const [buckets, setBuckets] = useState([]) const [bucket, setBucket] = useState(null) const [prefix, setPrefix] = useState('') const [folders, setFolders] = useState([]) const [objects, setObjects] = useState([]) const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const loadBuckets = useCallback(async () => { setLoading(true) setError(null) try { const [h, b] = await Promise.all([ fetch('/api/storage/s3/health'), fetch('/api/storage/s3/buckets'), ]) if (h.ok) setHealth(await h.json()) if (b.ok) { const j = await b.json() setBuckets(j.buckets || []) if (!bucket && j.buckets?.length) setBucket(j.buckets[0].name) } else { setError('Failed to load buckets') } } catch { setError('S3 API unavailable') } finally { setLoading(false) } }, [bucket]) const loadObjects = useCallback(async (b: string, p: string) => { setLoading(true) setError(null) try { const r = await fetch(`/api/storage/s3/buckets/${encodeURIComponent(b)}/objects?prefix=${encodeURIComponent(p)}`) const j = await r.json() if (!r.ok || !j.ok) { setError(j.error || 'List failed') return } setFolders(j.folders || []) setObjects(j.objects || []) } catch { setError('Failed to list objects') } finally { setLoading(false) } }, []) useEffect(() => { loadBuckets() }, [loadBuckets]) useEffect(() => { if (bucket) loadObjects(bucket, prefix) }, [bucket, prefix, loadObjects]) const crumbs = prefix ? prefix.split('/').filter(Boolean) : [] return (

ObjectScale S3 Storage

Dell ECS · {health?.endpoint || '10.0.20.111:9020'} · live bucket browser

Open Jupyter
{bucket && ( )} {loading && (

Loading…

)} {error &&

{error}

}
{folders.map((f) => ( ))} {objects.map((o) => ( ))}
Name Size Modified
{o.name || o.key} {o.size_human} {o.modified?.slice(0, 19) || '—'} {o.key && bucket && ( )}
{!loading && folders.length === 0 && objects.length === 0 && bucket && (

This prefix is empty.

)}
) }