// modal-new-recorder.jsx - New Recorder dialog (SRT / RTMP / SDI / Deltacast) /** * DevicePortPicker - groups a flat per-port API response by node_id and * renders one button per actual port. Replaces the old code that iterated * over entries and synthesised port counts, which caused duplicate groups. * * props: * ports - flat array from /cluster/devices/blackmagic or /deltacast * each entry: { node_id, hostname, model, index, device, present? } * selectedIdx - currently selected device_index * selectedNode - currently selected node_id * onSelect(idx, nodeId) * portLabel - e.g. "SDI" or "Port" * showTestBadge - show TEST CARD badge when present===false */ function DevicePortPicker({ ports, selectedIdx, selectedNode, onSelect, portLabel = 'Port', showTestBadge = false }) { // Group by node_id (stable - one group per physical node) const groups = React.useMemo(() => { const map = new Map(); for (const p of ports) { const key = p.node_id || p.hostname || 'unknown'; if (!map.has(key)) map.set(key, { nodeId: p.node_id || p.hostname || '', hostname: p.hostname || key, model: p.model || '', ports: [] }); map.get(key).ports.push(p); } // Sort ports within each group by index for (const g of map.values()) g.ports.sort((a, b) => a.index - b.index); return Array.from(map.values()); }, [ports]); return (