feat: Add fullscreen toggle functionality to GraphView for enhanced user experience and improved interaction
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 5m52s

This commit is contained in:
2025-08-08 16:15:59 +07:00
parent 16c75a40a8
commit efc561a2a1
+26 -6
View File
@@ -1,15 +1,17 @@
import React, { useState, useRef, useEffect } from 'react';
import * as d3 from 'd3';
import { IconZoomIn, IconZoomOut, IconMaximize } from '@tabler/icons-react';
import { IconZoomIn, IconZoomOut, IconMaximize, IconMinimize } from '@tabler/icons-react';
function GraphView({ servers, connections }) {
const [nodePositions, setNodePositions] = useState({});
const [draggedNode, setDraggedNode] = useState(null);
const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 });
const [hoveredLinkId, setHoveredLinkId] = useState(null);
const containerRef = useRef(null);
const svgRef = useRef(null);
const gRef = useRef(null);
const zoomRef = useRef(null);
const [isFullscreen, setIsFullscreen] = useState(false);
// Размеры карточки узла
const NODE_WIDTH = 160;
@@ -111,6 +113,23 @@ function GraphView({ servers, connections }) {
d3.select(svgEl).transition().duration(250).call(zoomRef.current.transform, t);
};
// Полноэкранный режим
useEffect(() => {
const handler = () => setIsFullscreen(Boolean(document.fullscreenElement));
document.addEventListener('fullscreenchange', handler);
return () => document.removeEventListener('fullscreenchange', handler);
}, []);
const toggleFullscreen = () => {
const el = containerRef.current;
if (!el) return;
if (!document.fullscreenElement) {
el.requestFullscreen?.();
} else {
document.exitFullscreen?.();
}
};
if (servers.length === 0) {
return (
<div className="text-center py-5">
@@ -222,7 +241,7 @@ function GraphView({ servers, connections }) {
};
return (
<div style={{ width: '100%', height: '500px', border: '1px solid #e5e7eb', borderRadius: '8px', overflow: 'hidden', background: '#f8fafc', position: 'relative' }}>
<div ref={containerRef} style={{ width: '100%', height: '500px', border: '1px solid #e5e7eb', borderRadius: '8px', overflow: 'hidden', background: '#f8fafc', position: 'relative' }}>
<svg
ref={svgRef}
width="100%"
@@ -415,8 +434,9 @@ function GraphView({ servers, connections }) {
x={badgeX + 18}
y={badgeY + 12}
textAnchor="middle"
fontSize="12"
fontSize="14"
dominantBaseline="middle"
style={{ fontFamily: 'Segoe UI Emoji, Noto Color Emoji, Apple Color Emoji, "Twemoji Mozilla", "EmojiOne Color", sans-serif' }}
>
{flag}
</text>
@@ -462,7 +482,7 @@ function GraphView({ servers, connections }) {
</g>
</svg>
{/* Контролы масштабирования */}
<div className="position-absolute" style={{ right: 10, top: 10 }}>
<div className="position-absolute" style={{ right: 10, top: 10, zIndex: 10, pointerEvents: 'auto' }}>
<div className="btn-group btn-group-sm">
<button className="btn btn-outline-secondary" onClick={() => zoomBy(1.2)} title="Увеличить">
<IconZoomIn size={16} />
@@ -470,8 +490,8 @@ function GraphView({ servers, connections }) {
<button className="btn btn-outline-secondary" onClick={() => zoomBy(1/1.2)} title="Уменьшить">
<IconZoomOut size={16} />
</button>
<button className="btn btn-outline-secondary" onClick={fitToView} title="Подогнать по окну">
<IconMaximize size={16} />
<button className="btn btn-outline-secondary" onClick={toggleFullscreen} title={isFullscreen ? 'Выйти из полноэкранного' : 'Во весь экран'}>
{isFullscreen ? <IconMinimize size={16} /> : <IconMaximize size={16} />}
</button>
</div>
</div>