+34
-15
@@ -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) {
|
||||
<div><span class="text-secondary">Type:</span> ${n.node_type}</div>
|
||||
<div><span class="text-secondary">Status:</span> ${n.status}</div>
|
||||
<div><span class="text-secondary">Group:</span> ${n.group_name}</div>
|
||||
<button class="btn btn-outline-danger btn-sm mt-2" onclick="deleteSelectedNode()"><i class="fas fa-trash me-1"></i>Delete</button>
|
||||
<button class="btn btn-outline-danger btn-sm mt-2" onclick="deleteSelectedNode(${n.id})"><i class="fas fa-trash me-1"></i>Delete</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user