Compare commits
1 Commits
9e398f8bb1
...
936679f274
| Author | SHA1 | Date | |
|---|---|---|---|
| 936679f274 |
@@ -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';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user