diff --git a/frontend/src/NetworkMapDashboard.jsx b/frontend/src/NetworkMapDashboard.jsx index 1b06533..9204878 100644 --- a/frontend/src/NetworkMapDashboard.jsx +++ b/frontend/src/NetworkMapDashboard.jsx @@ -195,14 +195,21 @@ export default function NetworkMapDashboard() { /** Один ключ пинга на ребро (маршруты статичны — одна сторона) */ const edgePingKey = (a, b) => [String(a), String(b)].sort().join(':'); - const requestPings = useCallback(async () => { - if (connections.length === 0) return; + /** + * Запросить пинг для всех соединений или для конкретного подмножества. + * Если передать force=true, игнорирует TTL кеша по пингу. + */ + const requestPings = useCallback(async (options = {}) => { + const { connections: targetConnections, force = false } = options; + const sourceConnections = + Array.isArray(targetConnections) && targetConnections.length > 0 ? targetConnections : connections; + if (sourceConnections.length === 0) return; pingAbortRef.current = false; setPingLoading(true); const ttlMs = Math.max(0, (pingCacheSeconds || 0) * 1000); const tasks = []; - connections.forEach((c) => { + sourceConnections.forEach((c) => { const from = String(c.from); const to = String(c.to); if (!from || !to || from === to) return; @@ -214,7 +221,7 @@ export default function NetworkMapDashboard() { srcTo && ['jumphost', 'home'].includes(String(srcTo.type || '').toLowerCase()) && c.internalToFrom; const ekey = edgePingKey(from, to); - if (ttlMs > 0 && pingTimestampsRef.current[ekey] && Date.now() - pingTimestampsRef.current[ekey] < ttlMs) { + if (!force && ttlMs > 0 && pingTimestampsRef.current[ekey] && Date.now() - pingTimestampsRef.current[ekey] < ttlMs) { return; } @@ -291,8 +298,14 @@ export default function NetworkMapDashboard() { const speedKey = (key1, key2) => [String(key1), String(key2)].sort().join(':'); - const requestSpeeds = useCallback(async () => { - const withSpeed = connections.filter( + /** + * Запросить скорость для всех соединений или подмножества. + */ + const requestSpeeds = useCallback(async (options = {}) => { + const { connections: targetConnections } = options; + const sourceConnections = + Array.isArray(targetConnections) && targetConnections.length > 0 ? targetConnections : connections; + const withSpeed = sourceConnections.filter( (c) => c.speedTestServerId && c.interfaceName ); if (withSpeed.length === 0) return; @@ -343,6 +356,22 @@ export default function NetworkMapDashboard() { setSpeedLoading(false); }, [connections]); + const handleRefreshPingForConnection = useCallback( + (connection) => { + if (!connection) return; + requestPings({ connections: [connection], force: true }); + }, + [requestPings] + ); + + const handleRefreshSpeedForConnection = useCallback( + (connection) => { + if (!connection) return; + requestSpeeds({ connections: [connection] }); + }, + [requestSpeeds] + ); + useEffect(() => { const controller = new AbortController(); fetchData(controller.signal); @@ -427,6 +456,10 @@ export default function NetworkMapDashboard() { speedMap={speedMap} pingStaleMap={pingStaleMap} speedStaleMap={speedStaleMap} + onRefreshPingForConnection={handleRefreshPingForConnection} + onRefreshSpeedForConnection={handleRefreshSpeedForConnection} + pingLoading={pingLoading} + speedLoading={speedLoading} /> )} diff --git a/frontend/src/NetworkMapUnifi.jsx b/frontend/src/NetworkMapUnifi.jsx index cda5b42..353febf 100644 --- a/frontend/src/NetworkMapUnifi.jsx +++ b/frontend/src/NetworkMapUnifi.jsx @@ -86,7 +86,18 @@ function speedKey(key1, key2) { return [String(key1), String(key2)].sort().join(':'); } -export default function NetworkMapUnifi({ servers = [], connections = [], pingMap = {}, speedMap = {}, pingStaleMap = {}, speedStaleMap = {} }) { +export default function NetworkMapUnifi({ + servers = [], + connections = [], + pingMap = {}, + speedMap = {}, + pingStaleMap = {}, + speedStaleMap = {}, + onRefreshPingForConnection, + onRefreshSpeedForConnection, + pingLoading = false, + speedLoading = false, +}) { const containerRef = useRef(null); const svgRef = useRef(null); const [size, setSize] = useState({ w: 800, h: 520 }); @@ -514,6 +525,17 @@ export default function NetworkMapUnifi({ servers = [], connections = [], pingMa const sk = speedKey(selectedEdge.raw?.fromKey, selectedEdge.raw?.toKey); const speed = speedMap[sk] ?? selectedEdge.speed; const speedStale = speedStaleMap[sk] === true; + const canPingFrom = + fromServer && + ['jumphost', 'home'].includes(String(fromServer.type || '').toLowerCase()) && + selectedEdge.raw?.internalFromTo; + const canPingTo = + toServer && + ['jumphost', 'home'].includes(String(toServer.type || '').toLowerCase()) && + selectedEdge.raw?.internalToFrom; + const canPing = Boolean(canPingFrom || canPingTo); + const canSpeed = + Boolean(selectedEdge.raw?.speedTestServerId && selectedEdge.raw?.interfaceName); return (