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
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 6m18s
This commit is contained in:
+28
-56
@@ -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"
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user