update style
This commit is contained in:
@@ -2,6 +2,56 @@
|
||||
* Graph visualization module for DNSRecon
|
||||
* Handles network graph rendering using vis.js
|
||||
*/
|
||||
const contextMenuCSS = `
|
||||
.graph-context-menu {
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
background: linear-gradient(135deg, #2a2a2a 0%, #1e1e1e 100%);
|
||||
border: 1px solid #444;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 8px 25px rgba(0,0,0,0.6);
|
||||
display: none;
|
||||
font-family: 'Roboto Mono', monospace;
|
||||
font-size: 0.9rem;
|
||||
color: #c7c7c7;
|
||||
min-width: 180px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.graph-context-menu ul {
|
||||
list-style: none;
|
||||
padding: 0.5rem 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.graph-context-menu ul li {
|
||||
padding: 0.75rem 1rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.graph-context-menu ul li:hover {
|
||||
background: linear-gradient(135deg, #3a3a3a 0%, #2e2e2e 100%);
|
||||
color: #00ff41;
|
||||
}
|
||||
|
||||
.graph-context-menu .menu-icon {
|
||||
font-size: 0.9rem;
|
||||
width: 1.2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.graph-context-menu ul li:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.graph-context-menu ul li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
`;
|
||||
|
||||
class GraphManager {
|
||||
constructor(containerId) {
|
||||
@@ -119,12 +169,18 @@ class GraphManager {
|
||||
randomSeed: 2
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof document !== 'undefined') {
|
||||
const style = document.createElement('style');
|
||||
style.textContent = contextMenuCSS;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
this.createNodeInfoPopup();
|
||||
this.createContextMenu();
|
||||
document.body.addEventListener('click', () => this.hideContextMenu());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create floating node info popup
|
||||
*/
|
||||
@@ -139,6 +195,12 @@ class GraphManager {
|
||||
* Create context menu
|
||||
*/
|
||||
createContextMenu() {
|
||||
// Remove existing context menu if it exists
|
||||
const existing = document.getElementById('graph-context-menu');
|
||||
if (existing) {
|
||||
existing.remove();
|
||||
}
|
||||
|
||||
this.contextMenu = document.createElement('div');
|
||||
this.contextMenu.id = 'graph-context-menu';
|
||||
this.contextMenu.className = 'graph-context-menu';
|
||||
@@ -150,9 +212,12 @@ class GraphManager {
|
||||
});
|
||||
|
||||
document.body.appendChild(this.contextMenu);
|
||||
console.log('Context menu created and added to body');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the network graph
|
||||
*/
|
||||
@@ -225,9 +290,10 @@ class GraphManager {
|
||||
setupNetworkEvents() {
|
||||
if (!this.network) return;
|
||||
|
||||
// Use a standard DOM event listener for the context menu for better reliability
|
||||
// FIXED: Right-click context menu
|
||||
this.container.addEventListener('contextmenu', (event) => {
|
||||
event.preventDefault();
|
||||
console.log('Right-click detected at:', event.offsetX, event.offsetY);
|
||||
|
||||
// Get coordinates relative to the canvas
|
||||
const pointer = {
|
||||
@@ -236,6 +302,7 @@ class GraphManager {
|
||||
};
|
||||
|
||||
const nodeId = this.network.getNodeAt(pointer);
|
||||
console.log('Node at pointer:', nodeId);
|
||||
|
||||
if (nodeId) {
|
||||
// Pass the original client event for positioning
|
||||
@@ -288,6 +355,13 @@ class GraphManager {
|
||||
console.log('Selected nodes:', params.nodes);
|
||||
console.log('Selected edges:', params.edges);
|
||||
});
|
||||
|
||||
// Click away to hide context menu
|
||||
document.addEventListener('click', (e) => {
|
||||
if (!this.contextMenu.contains(e.target)) {
|
||||
this.hideContextMenu();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1071,20 +1145,51 @@ class GraphManager {
|
||||
* @param {Event} event - The contextmenu event
|
||||
*/
|
||||
showContextMenu(nodeId, event) {
|
||||
console.log('Showing context menu for node:', nodeId);
|
||||
|
||||
// Create menu items
|
||||
this.contextMenu.innerHTML = `
|
||||
<ul>
|
||||
<li data-action="hide" data-node-id="${nodeId}">Hide Node</li>
|
||||
<li data-action="delete" data-node-id="${nodeId}">Delete Node</li>
|
||||
<li data-action="focus" data-node-id="${nodeId}">
|
||||
<span class="menu-icon">🎯</span>
|
||||
<span>Focus on Node</span>
|
||||
</li>
|
||||
<li data-action="hide" data-node-id="${nodeId}">
|
||||
<span class="menu-icon">👁️🗨️</span>
|
||||
<span>Hide Node</span>
|
||||
</li>
|
||||
<li data-action="delete" data-node-id="${nodeId}">
|
||||
<span class="menu-icon">🗑️</span>
|
||||
<span>Delete Node</span>
|
||||
</li>
|
||||
<li data-action="details" data-node-id="${nodeId}">
|
||||
<span class="menu-icon">ℹ️</span>
|
||||
<span>Show Details</span>
|
||||
</li>
|
||||
</ul>
|
||||
`;
|
||||
|
||||
// Position the menu
|
||||
this.contextMenu.style.left = `${event.clientX}px`;
|
||||
this.contextMenu.style.top = `${event.clientY}px`;
|
||||
this.contextMenu.style.display = 'block';
|
||||
|
||||
// Ensure menu stays within viewport
|
||||
const rect = this.contextMenu.getBoundingClientRect();
|
||||
if (rect.right > window.innerWidth) {
|
||||
this.contextMenu.style.left = `${event.clientX - rect.width}px`;
|
||||
}
|
||||
if (rect.bottom > window.innerHeight) {
|
||||
this.contextMenu.style.top = `${event.clientY - rect.height}px`;
|
||||
}
|
||||
|
||||
// Add event listeners to menu items
|
||||
this.contextMenu.querySelectorAll('li').forEach(item => {
|
||||
item.addEventListener('click', (e) => {
|
||||
const action = e.target.dataset.action;
|
||||
const nodeId = e.target.dataset.nodeId;
|
||||
e.stopPropagation();
|
||||
const action = e.currentTarget.dataset.action;
|
||||
const nodeId = e.currentTarget.dataset.nodeId;
|
||||
console.log('Context menu action:', action, 'for node:', nodeId);
|
||||
this.performContextMenuAction(action, nodeId);
|
||||
this.hideContextMenu();
|
||||
});
|
||||
@@ -1106,13 +1211,26 @@ class GraphManager {
|
||||
* @param {string} nodeId - The ID of the node
|
||||
*/
|
||||
performContextMenuAction(action, nodeId) {
|
||||
console.log('Performing action:', action, 'on node:', nodeId);
|
||||
|
||||
switch (action) {
|
||||
case 'focus':
|
||||
this.focusOnNode(nodeId);
|
||||
break;
|
||||
case 'hide':
|
||||
this.hideNodeAndOrphans(nodeId);
|
||||
break;
|
||||
case 'delete':
|
||||
this.deleteNodeAndOrphans(nodeId);
|
||||
break;
|
||||
case 'details':
|
||||
const node = this.nodes.get(nodeId);
|
||||
if (node) {
|
||||
this.showNodeDetails(node);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.warn('Unknown action:', action);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1010
static/js/main.js
1010
static/js/main.js
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user