mirror of
https://github.com/mblanke/ThreatHunt.git
synced 2026-03-01 14:00:20 -05:00
- Implemented PlaybookManager for creating and managing investigation playbooks with templates. - Added SavedSearches component for managing bookmarked queries and recurring scans. - Introduced TimelineView for visualizing forensic event timelines with zoomable charts. - Enhanced backend processing with auto-queued jobs for dataset uploads and improved database concurrency. - Updated frontend components for better user experience and performance optimizations. - Documented changes in update log for future reference.
60 lines
2.1 KiB
Python
60 lines
2.1 KiB
Python
from pathlib import Path
|
|
p=Path(r'd:/Projects/Dev/ThreatHunt/frontend/src/components/NetworkMap.tsx')
|
|
t=p.read_text(encoding='utf-8')
|
|
insert='''
|
|
function isPointOnNodeLabel(node: GNode, wx: number, wy: number, vp: Viewport): boolean {
|
|
const fontSize = Math.max(9, Math.round(12 / vp.scale));
|
|
const approxCharW = Math.max(5, fontSize * 0.58);
|
|
const line1 = node.label || '';
|
|
const line2 = node.meta.ips.length > 0 ? node.meta.ips[0] : '';
|
|
const tw = Math.max(line1.length * approxCharW, line2 ? line2.length * approxCharW : 0);
|
|
const px = 5, py = 2;
|
|
const totalH = line2 ? fontSize * 2 + py * 2 : fontSize + py * 2;
|
|
const lx = node.x, ly = node.y - node.radius - 6;
|
|
const rx = lx - tw / 2 - px;
|
|
const ry = ly - totalH;
|
|
const rw = tw + px * 2;
|
|
const rh = totalH;
|
|
return wx >= rx && wx <= (rx + rw) && wy >= ry && wy <= (ry + rh);
|
|
}
|
|
|
|
'''
|
|
if 'function isPointOnNodeLabel' not in t:
|
|
t=t.replace('// == Hit-test =============================================================\n', '// == Hit-test =============================================================\n'+insert)
|
|
|
|
old='''function hitTest(
|
|
graph: Graph, canvas: HTMLCanvasElement, clientX: number, clientY: number, vp: Viewport,
|
|
): GNode | null {
|
|
const { wx, wy } = screenToWorld(canvas, clientX, clientY, vp);
|
|
for (const n of graph.nodes) {
|
|
const dx = n.x - wx, dy = n.y - wy;
|
|
if (dx * dx + dy * dy < (n.radius + 5) ** 2) return n;
|
|
}
|
|
return null;
|
|
}
|
|
'''
|
|
new='''function hitTest(
|
|
graph: Graph, canvas: HTMLCanvasElement, clientX: number, clientY: number, vp: Viewport,
|
|
): GNode | null {
|
|
const { wx, wy } = screenToWorld(canvas, clientX, clientY, vp);
|
|
|
|
// Node-circle hit has priority
|
|
for (const n of graph.nodes) {
|
|
const dx = n.x - wx, dy = n.y - wy;
|
|
if (dx * dx + dy * dy < (n.radius + 5) ** 2) return n;
|
|
}
|
|
|
|
// Then label hit (so clicking text works too)
|
|
for (const n of graph.nodes) {
|
|
if (isPointOnNodeLabel(n, wx, wy, vp)) return n;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
'''
|
|
if old not in t:
|
|
raise SystemExit('hitTest block not found')
|
|
t=t.replace(old,new)
|
|
p.write_text(t,encoding='utf-8')
|
|
print('updated NetworkMap hit-test for labels')
|