Files
headlamp-tns-csi-plugin/src/components/PVCDetailSection.tsx
T
DevContainer User c1c5e8a37d fix: resolve bugs in benchmark lifecycle, snapshot filtering, and dark mode
- Fix PVC bind loop leak on unmount via cancellation ref
- Fix DeleteOptions body structure for proper foreground propagation
- Filter snapshots to tns-csi driver only (was showing all drivers)
- Fix stale closures in Escape key handlers with useCallback
- Add loading state to cleanup delete button, remove window.confirm/alert
- Use CSS custom properties for protocol chart colors (dark mode support)
- Fix all 35 ESLint warnings (import sort, indent, boolean attrs)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:47:33 +00:00

64 lines
2.1 KiB
TypeScript

/**
* PVCDetailSection — injected into Headlamp's PVC detail view.
*
* Shown only when the bound PV uses tns.csi.io as the CSI driver.
* Uses registerDetailsViewSection in index.tsx.
*/
import { NameValueTable, SectionBox } from '@kinvolk/headlamp-plugin/lib/CommonComponents';
import React from 'react';
import { findBoundPv, formatProtocol } from '../api/k8s';
import { useTnsCsiContext } from '../api/TnsCsiDataContext';
interface PVCDetailSectionProps {
resource: {
metadata?: { name?: string; namespace?: string };
spec?: { volumeName?: string; storageClassName?: string };
};
}
export default function PVCDetailSection({ resource }: PVCDetailSectionProps) {
const { persistentVolumes, persistentVolumeClaims, loading } = useTnsCsiContext();
if (loading) return null;
// Find this PVC in our filtered list
const pvcName = resource.metadata?.name;
const pvcNamespace = resource.metadata?.namespace;
const matchedPvc = persistentVolumeClaims.find(
pvc => pvc.metadata.name === pvcName && pvc.metadata.namespace === pvcNamespace
);
if (!matchedPvc) {
// Not a tns-csi PVC — render nothing
return null;
}
const boundPv = findBoundPv(matchedPvc, persistentVolumes);
if (!boundPv) return null;
const attrs = boundPv.spec.csi?.volumeAttributes ?? {};
const protocol = formatProtocol(attrs['protocol']);
return (
<SectionBox title="TNS-CSI Storage Details">
<NameValueTable
rows={[
{ name: 'Driver', value: 'tns.csi.io' },
{ name: 'Protocol', value: protocol },
{ name: 'Server', value: attrs['server'] ?? '—' },
{ name: 'Storage Class', value: boundPv.spec.storageClassName ?? '—' },
{ name: 'Volume Handle', value: boundPv.spec.csi?.volumeHandle ?? '—' },
...Object.entries(attrs)
.filter(([k]) => !['protocol', 'server'].includes(k))
.map(([k, v]) => ({ name: k, value: v ?? '—' })),
{
name: 'PV Name',
value: boundPv.metadata.name,
},
]}
/>
</SectionBox>
);
}