diff --git a/frontend/assets/js/app.js b/frontend/assets/js/app.js index b53827a..e0762d5 100644 --- a/frontend/assets/js/app.js +++ b/frontend/assets/js/app.js @@ -24,6 +24,7 @@ let dragType = null; let dragOffX, dragOffY; let dragHandle = null; let dragOrig = null; +let dragNodeIds = null; let selectStartX, selectStartY; let selectRect = null; @@ -1221,9 +1222,8 @@ let syncHashes = { events: null, documents: null, network: null }; function startSync() { if (syncInterval) return; syncInterval = setInterval(async () => { - // Skip sync if a modal is open (user is editing) + if (dragType || dragTarget || isPanning) return; const openModals = document.querySelectorAll('.modal.show'); - if (openModals.length > 0) return; try { const [eventsData, docsData, nodesData, linksData, shapesData] = await Promise.all([ apiFetch('events'), @@ -1312,6 +1312,7 @@ function onMouseDown(e) { if (e.shiftKey) { selectNode(node.id, true); } else if (!selectedNodeIds.includes(node.id)) { selectNode(node.id); } dragType = 'node'; dragTarget = node; + dragNodeIds = [...selectedNodeIds]; dragOffX = mx - node.x; dragOffY = my - node.y; return; } @@ -1338,10 +1339,10 @@ function onMouseDown(e) { function onMouseMove(e) { const rect = canvas.getBoundingClientRect(); - if (dragType === 'node' && dragTarget) { + if (dragType === 'node' && dragNodeIds) { const dx = e.clientX - rect.left - panX - dragOffX - dragTarget.x; const dy = e.clientY - rect.top - panY - dragOffY - dragTarget.y; - for (const c of canvasNodes) { if (selectedNodeIds.includes(c.id)) { c.x += dx; c.y += dy; } } + for (const c of canvasNodes) { if (dragNodeIds.includes(c.id)) { c.x += dx; c.y += dy; } } renderNetwork(); return; } if (dragType === 'shape' && dragTarget) { @@ -1385,8 +1386,11 @@ function onMouseMove(e) { } function onMouseUp(e) { - if (dragType === 'node') { - for (const c of canvasNodes) { if (selectedNodeIds.includes(c.id)) apiFetch('nodes/' + c.id, { method: 'PUT', body: JSON.stringify({ pos_x: c.x, pos_y: c.y }) }); } + if (dragType === 'node' && dragNodeIds) { + for (const id of dragNodeIds) { + const c = canvasNodes.find(n => n.id === id); + if (c) apiFetch('nodes/' + id, { method: 'PUT', body: JSON.stringify({ pos_x: c.x, pos_y: c.y }) }); + } } else if (dragTarget && (dragType === 'shape' || dragType === 'resize')) { apiFetch('shapes/' + dragTarget.id, { method: 'PUT', body: JSON.stringify({ pos_x: dragTarget.x, pos_y: dragTarget.y, width: dragTarget.w, height: dragTarget.h }) }); } else if (dragType === 'select') { @@ -1406,7 +1410,7 @@ function onMouseUp(e) { renderNodeList(); renderShapeList(); renderNetwork(); } } - dragType = null; dragTarget = null; dragOrig = null; + dragType = null; dragTarget = null; dragOrig = null; dragNodeIds = null; selectRect = null; isPanning = false; canvas.style.cursor = 'grab';