From 50c1db8f2b895b109f68809a39e812d9968f0504 Mon Sep 17 00:00:00 2001 From: janis steiner Date: Tue, 12 May 2026 10:58:57 +0200 Subject: [PATCH] fix canvas --- frontend/assets/js/app.js | 40 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/frontend/assets/js/app.js b/frontend/assets/js/app.js index 54e4df1..1da7efd 100644 --- a/frontend/assets/js/app.js +++ b/frontend/assets/js/app.js @@ -86,6 +86,40 @@ function startSync() { }, 5000); } +function setupCanvasClickCreate() { + const wrapper = document.getElementById('networkCanvasWrapper'); + const bar = document.getElementById('nodeToolbar'); + wrapper.addEventListener('click', async (e) => { + if (!pendingCanvasCreate) return; + const rect = canvas.getBoundingClientRect(); + const mx = e.clientX - rect.left - panX; + const my = e.clientY - rect.top - panY; + const type = pendingCanvasCreate; + pendingCanvasCreate = null; + if (bar) bar.querySelectorAll('.d-inline-flex').forEach(s => s.style.outline = 'none'); + + if (type.startsWith('shape:')) { + const shapeType = type.split(':')[1]; + await apiFetch('shapes', { method: 'POST', body: JSON.stringify({ + label: shapeType === 'rectangle' ? 'Box' : 'Ellipse', + shape_type: shapeType, + pos_x: mx - 100, pos_y: my - 75, + width: 200, height: 150, + color: '#1e3a5f', border_color: '#3b82f6', + opacity: 0.15, z_index: nextShapeZ++ + })}); + } else { + await apiFetch('nodes', { method: 'POST', body: JSON.stringify({ + label: type.charAt(0).toUpperCase() + type.slice(1), + ip_address: '', node_type: type || 'host', status: 'unknown', + group_name: 'default', notes: '', + pos_x: mx, pos_y: my + })}); + } + await loadNetworkData(); + }); +} + const DOC_TYPE_ICONS = { deployment: { icon: 'fa-server', color: '#06b6d4' }, attack: { icon: 'fa-bolt', color: '#ef4444' }, @@ -783,6 +817,7 @@ async function loadNetworkData() { renderNodeList(); renderShapeList(); renderNodeToolbar(); + setupCanvasClickCreate(); startSync(); if (shapes.length) nextShapeZ = Math.max(...shapes.map(x => x.z_index)) + 1; buildCanvasGraph(); @@ -1234,15 +1269,18 @@ function renderNodeToolbar() { function setupCanvasClickCreate() { const wrapper = document.getElementById('networkCanvasWrapper'); + if (wrapper.dataset.clickCreate) return; + wrapper.dataset.clickCreate = '1'; const bar = document.getElementById('nodeToolbar'); wrapper.addEventListener('click', async (e) => { if (!pendingCanvasCreate) return; + if (e.target !== canvas && e.target !== wrapper) return; const rect = canvas.getBoundingClientRect(); const mx = e.clientX - rect.left - panX; const my = e.clientY - rect.top - panY; const type = pendingCanvasCreate; pendingCanvasCreate = null; - bar.querySelectorAll('.d-inline-flex').forEach(s => s.style.outline = 'none'); + if (bar) bar.querySelectorAll('.d-inline-flex').forEach(s => s.style.outline = 'none'); if (type.startsWith('shape:')) { const shapeType = type.split(':')[1];