it
This commit is contained in:
@@ -1000,6 +1000,46 @@ input[type="text"]:focus, select:focus {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.correlation-values-list {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.correlation-value-details {
|
||||
margin-bottom: 0.5rem;
|
||||
border: 1px solid #333;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.correlation-value-details summary {
|
||||
padding: 0.5rem;
|
||||
background-color: #3a3a3a;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
color: #c7c7c7;
|
||||
}
|
||||
|
||||
.correlation-value-details summary:hover {
|
||||
background-color: #4a4a4a;
|
||||
}
|
||||
|
||||
.correlation-value-details .detail-row {
|
||||
margin-left: 1rem;
|
||||
margin-right: 1rem;
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
|
||||
.correlation-value-details .detail-label {
|
||||
color: #999;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.correlation-value-details .detail-value {
|
||||
color: #c7c7c7;
|
||||
word-break: break-all;
|
||||
font-family: 'Roboto Mono', monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {opacity: 0; transform: scale(0.95);}
|
||||
to {opacity: 1; transform: scale(1);}
|
||||
|
||||
@@ -365,11 +365,24 @@ class GraphManager {
|
||||
}
|
||||
}
|
||||
|
||||
// Handle merged correlation objects (similar to large entities)
|
||||
if (node.type === 'correlation_object') {
|
||||
const value = node.metadata.value;
|
||||
const label = Array.isArray(value) ? `Correlated (${value.length})` : String(value);
|
||||
processedNode.label = this.formatNodeLabel(label, node.type);
|
||||
processedNode.title = Array.isArray(value) ? value.join(', ') : value;
|
||||
const metadata = node.metadata || {};
|
||||
const values = metadata.values || [];
|
||||
const mergeCount = metadata.merge_count || 1;
|
||||
|
||||
if (mergeCount > 1) {
|
||||
// Display as merged correlation container
|
||||
processedNode.label = `Correlations (${mergeCount})`;
|
||||
processedNode.title = `Merged correlation container with ${mergeCount} values: ${values.slice(0, 3).join(', ')}${values.length > 3 ? '...' : ''}`;
|
||||
processedNode.borderWidth = 3; // Thicker border for merged nodes
|
||||
} else {
|
||||
// Single correlation value
|
||||
const value = Array.isArray(values) && values.length > 0 ? values[0] : (metadata.value || 'Unknown');
|
||||
const displayValue = typeof value === 'string' && value.length > 20 ? value.substring(0, 17) + '...' : value;
|
||||
processedNode.label = `Corr: ${displayValue}`;
|
||||
processedNode.title = `Correlation: ${value}`;
|
||||
}
|
||||
}
|
||||
|
||||
return processedNode;
|
||||
|
||||
@@ -799,10 +799,51 @@ class DNSReconApp {
|
||||
*/
|
||||
generateNodeDetailsHtml(node) {
|
||||
if (!node) return '<div class="detail-row"><span class="detail-value">Details not available.</span></div>';
|
||||
|
||||
|
||||
let detailsHtml = '<div class="modal-details-grid">';
|
||||
|
||||
// Section for Incoming Edges (Source Nodes)
|
||||
// Handle merged correlation objects similar to large entities
|
||||
if (node.type === 'correlation_object') {
|
||||
const metadata = node.metadata || {};
|
||||
const values = metadata.values || [];
|
||||
const mergeCount = metadata.merge_count || 1;
|
||||
|
||||
detailsHtml += '<div class="modal-section">';
|
||||
detailsHtml += '<h4>Correlation Details</h4>';
|
||||
|
||||
if (mergeCount > 1) {
|
||||
detailsHtml += `<p><strong>Merged Correlations:</strong> ${mergeCount} values</p>`;
|
||||
detailsHtml += '<div class="correlation-values-list">';
|
||||
|
||||
values.forEach((value, index) => {
|
||||
detailsHtml += `<details class="correlation-value-details">`;
|
||||
detailsHtml += `<summary>Value ${index + 1}: ${typeof value === 'string' && value.length > 50 ? value.substring(0, 47) + '...' : value}</summary>`;
|
||||
detailsHtml += `<div class="detail-row"><span class="detail-label">Full Value:</span><span class="detail-value">${value}</span></div>`;
|
||||
detailsHtml += `</details>`;
|
||||
});
|
||||
|
||||
detailsHtml += '</div>';
|
||||
} else {
|
||||
const singleValue = values.length > 0 ? values[0] : (metadata.value || 'Unknown');
|
||||
detailsHtml += `<div class="detail-row"><span class="detail-label">Correlation Value:</span><span class="detail-value">${singleValue}</span></div>`;
|
||||
}
|
||||
|
||||
// Show correlated nodes
|
||||
const correlatedNodes = metadata.correlated_nodes || [];
|
||||
if (correlatedNodes.length > 0) {
|
||||
detailsHtml += `<div class="detail-row"><span class="detail-label">Correlated Nodes:</span><span class="detail-value">${correlatedNodes.length}</span></div>`;
|
||||
detailsHtml += '<ul>';
|
||||
correlatedNodes.forEach(nodeId => {
|
||||
detailsHtml += `<li><a href="#" class="node-link" data-node-id="${nodeId}">${nodeId}</a></li>`;
|
||||
});
|
||||
detailsHtml += '</ul>';
|
||||
}
|
||||
|
||||
detailsHtml += '</div>';
|
||||
}
|
||||
|
||||
// Continue with standard node details for all node types
|
||||
// Section for Incoming Edges (Source Nodes)
|
||||
if (node.incoming_edges && node.incoming_edges.length > 0) {
|
||||
detailsHtml += '<div class="modal-section">';
|
||||
detailsHtml += '<h4>Source Nodes (Incoming)</h4>';
|
||||
@@ -812,7 +853,7 @@ class DNSReconApp {
|
||||
});
|
||||
detailsHtml += '</ul></div>';
|
||||
}
|
||||
|
||||
|
||||
// Section for Outgoing Edges (Destination Nodes)
|
||||
if (node.outgoing_edges && node.outgoing_edges.length > 0) {
|
||||
detailsHtml += '<div class="modal-section">';
|
||||
@@ -824,24 +865,28 @@ class DNSReconApp {
|
||||
detailsHtml += '</ul></div>';
|
||||
}
|
||||
|
||||
// Section for Attributes
|
||||
detailsHtml += '<div class="modal-section">';
|
||||
detailsHtml += '<h4>Attributes</h4>';
|
||||
detailsHtml += this.formatObjectToHtml(node.attributes);
|
||||
detailsHtml += '</div>';
|
||||
|
||||
// Section for Attributes (skip for correlation objects - already handled above)
|
||||
if (node.type !== 'correlation_object') {
|
||||
detailsHtml += '<div class="modal-section">';
|
||||
detailsHtml += '<h4>Attributes</h4>';
|
||||
detailsHtml += this.formatObjectToHtml(node.attributes);
|
||||
detailsHtml += '</div>';
|
||||
}
|
||||
|
||||
// Section for Description
|
||||
detailsHtml += '<div class="modal-section">';
|
||||
detailsHtml += '<h4>Description</h4>';
|
||||
detailsHtml += `<p class="description-text">${node.description || 'No description available.'}</p>`;
|
||||
detailsHtml += '</div>';
|
||||
|
||||
// Section for Metadata
|
||||
detailsHtml += '<div class="modal-section">';
|
||||
detailsHtml += '<h4>Metadata</h4>';
|
||||
detailsHtml += this.formatObjectToHtml(node.metadata);
|
||||
detailsHtml += '</div>';
|
||||
|
||||
|
||||
// Section for Metadata (skip detailed metadata for correlation objects - already handled above)
|
||||
if (node.type !== 'correlation_object') {
|
||||
detailsHtml += '<div class="modal-section">';
|
||||
detailsHtml += '<h4>Metadata</h4>';
|
||||
detailsHtml += this.formatObjectToHtml(node.metadata);
|
||||
detailsHtml += '</div>';
|
||||
}
|
||||
|
||||
detailsHtml += '</div>';
|
||||
return detailsHtml;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user