Compare commits

..

1 Commits

Author SHA1 Message Date
936679f274 feat: live topology view through websocket updates 2025-10-23 21:27:31 +02:00

View File

@@ -291,14 +291,23 @@ class TopologyGraphComponent extends Component {
// Clear existing content // Clear existing content
container.innerHTML = ''; container.innerHTML = '';
// Create a wrapper for SVG and controls
const wrapper = document.createElement('div');
wrapper.style.position = 'relative';
wrapper.style.width = '100%';
wrapper.style.height = '100%';
container.appendChild(wrapper);
// Add rearrange button
this.createRearrangeButton(wrapper);
// Create SVG element // Create SVG element
this.svg = d3.select(container) this.svg = d3.select(wrapper)
.append('svg') .append('svg')
.attr('width', '100%') .attr('width', '100%')
.attr('height', '100%') .attr('height', '100%')
.attr('viewBox', `0 0 ${this.width} ${this.height}`) .attr('viewBox', `0 0 ${this.width} ${this.height}`)
.style('border', '1px solid rgba(255, 255, 255, 0.1)') .style('border', '1px solid rgba(255, 255, 255, 0.1)')
//.style('background', 'rgba(0, 0, 0, 0.2)')
.style('border-radius', '12px'); .style('border-radius', '12px');
// Add zoom behavior // Add zoom behavior
@@ -319,6 +328,94 @@ class TopologyGraphComponent extends Component {
logger.debug('TopologyGraphComponent: SVG setup completed'); logger.debug('TopologyGraphComponent: SVG setup completed');
} }
createRearrangeButton(container) {
const button = document.createElement('button');
button.className = 'topology-rearrange-btn';
button.innerHTML = `
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="5" r="1.5"/>
<circle cx="12" cy="12" r="1.5"/>
<circle cx="12" cy="19" r="1.5"/>
<circle cx="5" cy="12" r="1.5"/>
<circle cx="19" cy="12" r="1.5"/>
<path d="M12 7v3m0 2v3m-5-3h3m2 0h3"/>
</svg>
<span>Rearrange</span>
`;
button.title = 'Rearrange nodes into a clean layout';
button.style.cssText = `
position: absolute;
left: 16px;
top: 16px;
z-index: 10;
display: flex;
align-items: center;
gap: 8px;
padding: 8px 14px;
background: var(--card-background, rgba(30, 30, 30, 0.95));
border: 1px solid var(--border-color, rgba(255, 255, 255, 0.1));
border-radius: 8px;
color: var(--text-primary, #ecf0f1);
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
`;
// Add hover effect
button.addEventListener('mouseenter', () => {
button.style.background = 'var(--card-hover, rgba(40, 40, 40, 0.95))';
button.style.borderColor = 'var(--primary-color, #3498db)';
button.style.transform = 'translateY(-1px)';
button.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.3)';
});
button.addEventListener('mouseleave', () => {
button.style.background = 'var(--card-background, rgba(30, 30, 30, 0.95))';
button.style.borderColor = 'var(--border-color, rgba(255, 255, 255, 0.1))';
button.style.transform = 'translateY(0)';
button.style.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.2)';
});
button.addEventListener('click', () => {
this.rearrangeNodes();
});
container.appendChild(button);
}
rearrangeNodes() {
logger.debug('TopologyGraphComponent: Rearranging nodes');
// Clear all manually dragged positions
this.draggedNodePositions.clear();
logger.debug('TopologyGraphComponent: Cleared dragged positions');
if (!this.simulation) {
logger.warn('TopologyGraphComponent: No simulation to rearrange');
return;
}
// Get current nodes and reset their fixed positions
const nodes = this.simulation.nodes();
nodes.forEach(node => {
node.fx = null;
node.fy = null;
// Give them a slight random velocity to help spread out
node.vx = (Math.random() - 0.5) * 50;
node.vy = (Math.random() - 0.5) * 50;
});
// Restart the simulation with high alpha for a fresh layout
this.simulation
.alpha(1)
.alphaTarget(0)
.restart();
logger.debug('TopologyGraphComponent: Simulation restarted for rearrangement');
}
// Ensure component is initialized // Ensure component is initialized
async ensureInitialized() { async ensureInitialized() {
if (!this.isInitialized) { if (!this.isInitialized) {
@@ -835,8 +932,8 @@ class TopologyGraphComponent extends Component {
} }
getLinkColor(latency) { getLinkColor(latency) {
if (latency <= 30) return '#10b981'; if (latency <= 50) return '#10b981';
if (latency <= 50) return '#f59e0b'; if (latency <= 100) return '#f59e0b';
return '#ef4444'; return '#ef4444';
} }