feat(NetworkMapDashboard, NetworkMapUnifi): enhance network visualization with tunnel interface connections and draggable node layout functionality
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m7s

This commit is contained in:
2026-02-17 16:21:37 +07:00
parent d3b21d3dc0
commit cfd7b53a54
2 changed files with 158 additions and 22 deletions
+26 -5
View File
@@ -34,16 +34,37 @@ export default function NetworkMapDashboard() {
const [error, setError] = useState(null);
const pingAbortRef = useRef(false);
/** Связи строятся из интерфейсов раздела «Сетевые настройки» (/network-config), tunnelInterfaces */
const fetchData = useCallback(async () => {
setLoading(true);
setError(null);
try {
const [serversRes, connRes] = await Promise.all([
const [serversRes, configRes] = await Promise.all([
api.get('/servers'),
api.get('/server-connections'),
api.get('/network-config').catch(() => ({ data: null })),
]);
const serversList = Array.isArray(serversRes?.data) ? serversRes.data : [];
const connList = Array.isArray(connRes?.data) ? connRes.data : [];
const config = configRes?.data || {};
const tunnelInterfaces = Array.isArray(config.tunnelInterfaces) ? config.tunnelInterfaces : [];
const getServer = (serverId) =>
serversList.find((s) => s.id === serverId || s.ip === serverId || s.dns === serverId);
const connList = [];
tunnelInterfaces.forEach((iface) => {
if (!iface.serverId || !iface.serverId2) return;
const s1 = getServer(iface.serverId);
const s2 = getServer(iface.serverId2);
if (!s1 || !s2 || s1.ip === s2.ip) return;
connList.push({
from: s1.ip,
to: s2.ip,
tunnelType: iface.type || 'GRE',
ipA: iface.localIp,
ipB: iface.remoteIp,
});
});
setServers(serversList);
setConnections(connList);
} catch (e) {
@@ -156,7 +177,7 @@ export default function NetworkMapDashboard() {
<PageHeader
title="Карта сети"
icon={<IconTopologyRing size={24} />}
meta="Серверы и пинг между ними (на рёбрах — задержка в мс)"
meta="Связи из раздела «Сетевые настройки» → Интерфейсы; на рёбрах — пинг (мс)"
actions={
<button
type="button"
@@ -171,7 +192,7 @@ export default function NetworkMapDashboard() {
/>
{servers.length === 0 ? (
<div className="alert alert-info">
Нет серверов. Добавьте серверы и связи в разделе «Серверы».
Нет серверов. Добавьте серверы в разделе «Серверы».
</div>
) : (
<NetworkMapUnifi