diff --git a/frontend/src/components/reactflow/overlayui/CreateLinkModal.tsx b/frontend/src/components/reactflow/overlayui/CreateLinkModal.tsx index d77faf1..ac92688 100644 --- a/frontend/src/components/reactflow/overlayui/CreateLinkModal.tsx +++ b/frontend/src/components/reactflow/overlayui/CreateLinkModal.tsx @@ -16,37 +16,24 @@ interface CreateLinkModalProps { export default function CreateLinkModal({ deviceData, currentDevicePorts, labDevices, onClose }: CreateLinkModalProps) { const { user } = useAuth(); - const { getEdges, getNodes } = useReactFlow, Edge>(); + const { getEdges } = useReactFlow, Edge>(); const { createLink } = useLinkOperations(); const [selectedFirstDevice, setSelectedFirstDevice] = useState(deviceData?.name ?? ""); const [selectedFirstDevicePort, setSelectedFirstDevicePort] = useState(""); const [selectedSecondDevice, setSelectedSecondDevice] = useState(""); const [selectedSecondDevicePort, setSelectedSecondDevicePort] = useState(""); const [availablePorts, setAvailablePorts] = useState([]); - const [filteredLabDevices] = useState(labDevices); const [firstDeviceOccupiedPorts, setFirstDeviceOccupiedPorts] = useState([]); - const [secondDeviceOccupiedPorts, setSecondDeviceOccupiedPorts] = useState([]); + const [secondDeviceOccupiedPorts, setSecondDeviceOccupiedPorts] = useState>({}); useEscapeKey(onClose); - // get a list of the current nodes in the topology to create a link - const nodes = getNodes(); - const currentNodesInTopology = new Set(nodes.map(n => n.data?.deviceData?.name)); - - // get occupied ports when selectedFirstDevice changes useEffect(() => { const edges = getEdges(); const ports = edges.filter((edge: Edge) => edge.source === selectedFirstDevice || edge.target === selectedFirstDevice).map((edge: Edge) => edge.id.split('-').filter((port: string) => port !== 'edge')); setFirstDeviceOccupiedPorts(ports.flat()); }, [selectedFirstDevice, getEdges]); - // get occupied ports when selectedSecondDevice changes - useEffect(() => { - const edges = getEdges(); - const ports = edges.filter((edge: Edge) => edge.source === selectedSecondDevice || edge.target === selectedSecondDevice).map((edge: Edge) => edge.id.split('-').filter((port: string) => port !== 'edge')); - setSecondDeviceOccupiedPorts(ports.flat()); - }, [selectedSecondDevice, getEdges]); - useEffect(() => { if (deviceData?.name) { setSelectedFirstDevice(deviceData.name); @@ -89,6 +76,31 @@ export default function CreateLinkModal({ deviceData, currentDevicePorts, labDev }); } + useEffect(() => { + const edges = getEdges(); + if (selectedSecondDevice) { + const ports = edges + .filter((edge: Edge) => edge.source === selectedSecondDevice || edge.target === selectedSecondDevice) + .map((edge: Edge) => edge.id.split('-').filter((port: string) => port !== 'edge')); + setSecondDeviceOccupiedPorts((prev) => ({ + ...prev, + [selectedSecondDevice]: ports.flat(), + })); + } else { + // Initialize occupied ports for all devices on mount + const allOccupiedPorts = labDevices.reduce((acc, device) => { + const devicePorts = edges + .filter((edge: Edge) => edge.source === device.name || edge.target === device.name) + .map((edge: Edge) => edge.id.split('-').filter((port: string) => port !== 'edge')) + .flat(); + acc[device.name] = devicePorts; + return acc; + }, {} as Record); + + setSecondDeviceOccupiedPorts(allOccupiedPorts); + } + }, [selectedSecondDevice, getEdges, labDevices]); + return (
@@ -115,7 +127,7 @@ export default function CreateLinkModal({ deviceData, currentDevicePorts, labDev const hasAvailablePorts = generatedPorts.some(port => !firstDeviceOccupiedPorts.includes(port)); return ( ); })} @@ -127,9 +139,10 @@ export default function CreateLinkModal({ deviceData, currentDevicePorts, labDev value={selectedFirstDevicePort} onChange={(e) => setSelectedFirstDevicePort(e.target.value)} className="block w-full mt-1 rounded-md bg-[#ffffff] focus:outline-none" + > - {(deviceData ? currentDevicePorts : filteredLabDevices.map(device => device.ports.split(',').flatMap(portDef => generatePorts(portDef)))).flat().map((port, index) => ( + {(deviceData ? currentDevicePorts : labDevices.map(device => device.ports.split(',').flatMap(portDef => generatePorts(portDef)))).flat().map((port, index) => ( @@ -144,13 +157,18 @@ export default function CreateLinkModal({ deviceData, currentDevicePorts, labDev className="block w-full mt-1 rounded-md bg-[#ffffff] focus:outline-none" > - {filteredLabDevices.filter((device) => (device.userId == null || device.userId == user?.id) && currentNodesInTopology.has(device.name)).map((device) => { + {labDevices.filter((d) => d.name !== deviceData?.name).map((device) => { const portsArray = device.ports.split(','); const generatedPorts = portsArray.flatMap(portDef => generatePorts(portDef)); - const hasAvailablePorts = generatedPorts.some(port => !secondDeviceOccupiedPorts.includes(port)); + const occupiedPorts = secondDeviceOccupiedPorts[device.name] || []; + const hasAvailablePorts = generatedPorts.some(port => !occupiedPorts.includes(port)); return ( - ); })} @@ -161,14 +179,18 @@ export default function CreateLinkModal({ deviceData, currentDevicePorts, labDev