Feature: Snapshot-Tab gruppiert nach Dataset wie Cockpit-Plugin
Snapshots werden nach Dataset gruppiert angezeigt (tank: 94, tank/share: 94) mit aufklappbaren Zeilen statt flacher Liste. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -501,7 +501,16 @@ export default function DatasetsPage() {
|
|||||||
<div className="text-center py-6 text-muted-foreground text-xs">Loading…</div>
|
<div className="text-center py-6 text-muted-foreground text-xs">Loading…</div>
|
||||||
) : snaps.length === 0 ? (
|
) : snaps.length === 0 ? (
|
||||||
<div className="text-center py-6 text-muted-foreground text-xs">No snapshots</div>
|
<div className="text-center py-6 text-muted-foreground text-xs">No snapshots</div>
|
||||||
) : (
|
) : (() => {
|
||||||
|
// Group snapshots by dataset
|
||||||
|
const groups = new Map<string, Snapshot[]>()
|
||||||
|
snaps.forEach((s) => {
|
||||||
|
const ds = s.dataset || s.name.split("@")[0]
|
||||||
|
if (!groups.has(ds)) groups.set(ds, [])
|
||||||
|
groups.get(ds)!.push(s)
|
||||||
|
})
|
||||||
|
const expandKey = `snapgroup-${pool.name}`
|
||||||
|
return (
|
||||||
<div className="overflow-x-auto">
|
<div className="overflow-x-auto">
|
||||||
<table className="w-full text-xs">
|
<table className="w-full text-xs">
|
||||||
<thead className="bg-muted">
|
<thead className="bg-muted">
|
||||||
@@ -515,34 +524,56 @@ export default function DatasetsPage() {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{snaps.map((snap) => (
|
{Array.from(groups.entries()).map(([ds, dsSnaps]) => {
|
||||||
<tr key={snap.name} className="border-b border-border/50 hover:bg-muted/30">
|
const isGroupExpanded = expandedDatasets.has(`${expandKey}-${ds}`)
|
||||||
<td className="px-3 py-2 font-mono">
|
return [
|
||||||
<span className="text-muted-foreground">{snap.dataset}@</span>{snap.name.split("@")[1]}
|
// Group header row
|
||||||
|
<tr
|
||||||
|
key={`group-${ds}`}
|
||||||
|
className="border-b border-border bg-muted/20 hover:bg-muted/40 cursor-pointer select-none"
|
||||||
|
onClick={() => {
|
||||||
|
const next = new Set(expandedDatasets)
|
||||||
|
if (isGroupExpanded) next.delete(`${expandKey}-${ds}`)
|
||||||
|
else next.add(`${expandKey}-${ds}`)
|
||||||
|
setExpandedDatasets(next)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<td className="px-3 py-2 font-mono font-medium" colSpan={5}>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
{isGroupExpanded ? <ChevronDown className="w-3 h-3" /> : <ChevronRight className="w-3 h-3" />}
|
||||||
|
<span>{ds}</span>
|
||||||
|
<span className="text-muted-foreground font-normal">{dsSnaps.length}</span>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-3 py-2 text-muted-foreground">
|
<td />
|
||||||
|
</tr>,
|
||||||
|
// Snapshot rows (expanded)
|
||||||
|
...(isGroupExpanded ? dsSnaps.map((snap) => (
|
||||||
|
<tr key={snap.name} className="border-b border-border/40 hover:bg-muted/30">
|
||||||
|
<td className="px-3 py-1.5 font-mono pl-8">{snap.name.split("@")[1]}</td>
|
||||||
|
<td className="px-3 py-1.5 text-muted-foreground">
|
||||||
{snap.creation_datetime ? new Date(snap.creation_datetime).toLocaleString() : "—"}
|
{snap.creation_datetime ? new Date(snap.creation_datetime).toLocaleString() : "—"}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-3 py-2">{formatBytes(snap.used)}</td>
|
<td className="px-3 py-1.5">{formatBytes(snap.used)}</td>
|
||||||
<td className="px-3 py-2">{formatBytes(snap.referenced)}</td>
|
<td className="px-3 py-1.5">{formatBytes(snap.referenced)}</td>
|
||||||
<td className="px-3 py-2 text-muted-foreground">—</td>
|
<td className="px-3 py-1.5 text-muted-foreground">—</td>
|
||||||
<td className="px-3 py-2 text-right">
|
<td className="px-3 py-1.5 text-right">
|
||||||
<button
|
<button
|
||||||
className="p-1 rounded hover:bg-muted"
|
className="p-1 rounded hover:bg-muted"
|
||||||
onClick={(e) => {
|
onClick={(e) => { e.stopPropagation(); setSnapContextMenu({ snap, x: e.clientX, y: e.clientY }) }}
|
||||||
e.stopPropagation()
|
|
||||||
setSnapContextMenu({ snap, x: e.clientX, y: e.clientY })
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<MoreVertical className="w-3 h-3" />
|
<MoreVertical className="w-3 h-3" />
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
)) : [])
|
||||||
|
]
|
||||||
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)
|
||||||
|
})()}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})()}
|
})()}
|
||||||
|
|||||||
Reference in New Issue
Block a user