refactor: Simplify GraphView component by removing state management and implementing grid-based node positioning for improved layout
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 6m18s

This commit is contained in:
2025-07-15 22:01:09 +07:00
parent a104cc7a3f
commit bbf143dee7
2 changed files with 31 additions and 60 deletions
+28 -56
View File
@@ -1,44 +1,6 @@
import React, { useState, useEffect, useRef } from 'react'; import React from 'react';
function GraphView({ servers, connections }) { function GraphView({ servers, connections }) {
const [positions, setPositions] = useState({});
const [dimensions, setDimensions] = useState({ width: 800, height: 500 });
const svgRef = useRef(null);
// Вычисляем позиции узлов
useEffect(() => {
if (servers.length === 0) return;
const newPositions = {};
const centerX = dimensions.width / 2;
const centerY = dimensions.height / 2;
const radius = Math.min(dimensions.width, dimensions.height) * 0.3;
servers.forEach((server, index) => {
const angle = (index / servers.length) * 2 * Math.PI;
newPositions[server.ip] = {
x: centerX + radius * Math.cos(angle),
y: centerY + radius * Math.sin(angle)
};
});
setPositions(newPositions);
}, [servers, dimensions]);
// Обработчик изменения размера
useEffect(() => {
const handleResize = () => {
if (svgRef.current) {
const rect = svgRef.current.getBoundingClientRect();
setDimensions({ width: rect.width, height: 500 });
}
};
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
if (servers.length === 0) { if (servers.length === 0) {
return ( return (
<div className="text-center py-5"> <div className="text-center py-5">
@@ -50,21 +12,32 @@ function GraphView({ servers, connections }) {
); );
} }
// Простое позиционирование узлов в сетке
const getNodePosition = (index, total) => {
const cols = Math.ceil(Math.sqrt(total));
const row = Math.floor(index / cols);
const col = index % cols;
const spacing = 150;
return {
x: 100 + col * spacing,
y: 100 + row * spacing
};
};
return ( return (
<div style={{ width: '100%', height: '500px', border: '1px solid #e5e7eb', borderRadius: '8px', overflow: 'hidden' }}> <div style={{ width: '100%', height: '500px', border: '1px solid #e5e7eb', borderRadius: '8px', overflow: 'hidden', background: '#f8fafc' }}>
<svg <svg width="100%" height="100%" viewBox="0 0 800 500">
ref={svgRef}
width="100%"
height="100%"
viewBox={`0 0 ${dimensions.width} ${dimensions.height}`}
style={{ background: '#f8fafc' }}
>
{/* Связи */} {/* Связи */}
{connections.map((connection, index) => { {connections.map((connection, index) => {
const fromPos = positions[connection.from]; const fromServer = servers.find(s => s.ip === connection.from);
const toPos = positions[connection.to]; const toServer = servers.find(s => s.ip === connection.to);
if (!fromPos || !toPos) return null; if (!fromServer || !toServer) return null;
const fromIndex = servers.indexOf(fromServer);
const toIndex = servers.indexOf(toServer);
const fromPos = getNodePosition(fromIndex, servers.length);
const toPos = getNodePosition(toIndex, servers.length);
return ( return (
<g key={`link-${index}`}> <g key={`link-${index}`}>
@@ -104,9 +77,8 @@ function GraphView({ servers, connections }) {
})} })}
{/* Узлы (серверы) */} {/* Узлы (серверы) */}
{servers.map(server => { {servers.map((server, index) => {
const pos = positions[server.ip]; const pos = getNodePosition(index, servers.length);
if (!pos) return null;
return ( return (
<g key={server.ip}> <g key={server.ip}>
@@ -114,7 +86,7 @@ function GraphView({ servers, connections }) {
<circle <circle
cx={pos.x} cx={pos.x}
cy={pos.y} cy={pos.y}
r="25" r="30"
fill="#3b82f6" fill="#3b82f6"
stroke="#1e40af" stroke="#1e40af"
strokeWidth="2" strokeWidth="2"
@@ -123,7 +95,7 @@ function GraphView({ servers, connections }) {
{/* DNS имя */} {/* DNS имя */}
<text <text
x={pos.x} x={pos.x}
y={pos.y - 5} y={pos.y - 8}
textAnchor="middle" textAnchor="middle"
fontSize="11" fontSize="11"
fill="white" fill="white"
@@ -135,7 +107,7 @@ function GraphView({ servers, connections }) {
{/* IP адрес */} {/* IP адрес */}
<text <text
x={pos.x} x={pos.x}
y={pos.y + 10} y={pos.y + 8}
textAnchor="middle" textAnchor="middle"
fontSize="10" fontSize="10"
fill="white" fill="white"
+3 -4
View File
@@ -17,7 +17,7 @@ import {
IconChevronDown, IconChevronDown,
IconLink IconLink
} from '@tabler/icons-react'; } from '@tabler/icons-react';
// import GraphView from './GraphView'; import GraphView from './GraphView';
const API_URL = '/api'; const API_URL = '/api';
@@ -668,15 +668,14 @@ function ServerManager() {
error={error} error={error}
/> />
{/* Временно отключаем граф для отладки */} <div className="card w-100 mb-4">
{/* <div className="card w-100 mb-4">
<div className="card-header"> <div className="card-header">
<h3 className="card-title mb-0">Граф связей между серверами</h3> <h3 className="card-title mb-0">Граф связей между серверами</h3>
</div> </div>
<div className="card-body"> <div className="card-body">
<GraphView servers={servers} connections={connections} /> <GraphView servers={servers} connections={connections} />
</div> </div>
</div> */} </div>
<div className="card w-100 mb-4"> <div className="card w-100 mb-4">
<div className="card-header"> <div className="card-header">
<h3 className="card-title mb-0">Добавить связь между серверами</h3> <h3 className="card-title mb-0">Добавить связь между серверами</h3>