diff --git a/frontend/assets/js/app.js b/frontend/assets/js/app.js index 5730baa..d2c65ff 100644 --- a/frontend/assets/js/app.js +++ b/frontend/assets/js/app.js @@ -49,10 +49,10 @@ document.addEventListener('DOMContentLoaded', () => { window.addEventListener('resize', () => { resizeCanvas(); renderNetwork(); }); document.addEventListener('keydown', (e) => { - if (e.key === 'Delete' || e.key === 'Backspace') { + if (e.key === 'Delete') { if (!document.activeElement || document.activeElement.tagName !== 'INPUT') { - if (selectedNodeId) deleteSelectedNode(); - else if (selectedShapeId) deleteSelectedShape(); + if (selectedNodeId) deleteSelectedNode(selectedNodeId); + else if (selectedShapeId) deleteSelectedShape(selectedShapeId); } } if (e.key === 'Escape') { @@ -204,9 +204,9 @@ async function loadNetworkData() { apiFetch('links'), apiFetch('shapes') ]); - nodes = n; - links = l; - shapes = s; + nodes = Array.isArray(n) ? n : []; + links = Array.isArray(l) ? l : []; + shapes = Array.isArray(s) ? s : []; populateNodeSelects(); renderNodeList(); renderShapeList(); @@ -265,7 +265,7 @@ function selectNode(id) {
Type: ${n.node_type}
Status: ${n.status}
Group: ${n.group_name}
- + `; } @@ -282,24 +282,43 @@ function selectShape(id) { renderNetwork(); } -async function deleteSelectedNode() { - if (!selectedNodeId) return; - if (!confirm('Delete this node and its connections?')) return; - const id = selectedNodeId; +async function deleteSelectedNode(id) { + if (!id) return; + const ok = await showConfirm('Delete this node and its connections?'); + if (!ok) return; selectedNodeId = null; await apiFetch(`nodes/${id}`, { method: 'DELETE' }); loadNetworkData(); } -async function deleteSelectedShape() { - if (!selectedShapeId) return; - if (!confirm('Delete this shape?')) return; - const id = selectedShapeId; +async function deleteSelectedShape(id) { + if (!id) return; + const ok = await showConfirm('Delete this shape?'); + if (!ok) return; selectedShapeId = null; await apiFetch(`shapes/${id}`, { method: 'DELETE' }); loadNetworkData(); } +function showConfirm(msg) { + return new Promise((resolve) => { + const modalEl = document.getElementById('confirmModal'); + const modal = new bootstrap.Modal(modalEl); + document.getElementById('confirmMsg').textContent = msg; + const btn = document.getElementById('confirmBtn'); + let resolved = false; + const cleanup = () => { + btn.removeEventListener('click', onClick); + modalEl.removeEventListener('hidden.bs.modal', onHidden); + }; + const onClick = () => { resolved = true; cleanup(); modal.hide(); resolve(true); }; + const onHidden = () => { if (!resolved) { cleanup(); resolve(false); } }; + btn.addEventListener('click', onClick); + modalEl.addEventListener('hidden.bs.modal', onHidden); + modal.show(); + }); +} + async function saveNode() { const data = { label: document.getElementById('nodeLabel').value, diff --git a/frontend/index.html b/frontend/index.html index 54ddc20..2ee12b4 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -329,6 +329,22 @@ + + +