diff --git a/backend/run.py b/backend/run.py index 655973b..4753965 100644 --- a/backend/run.py +++ b/backend/run.py @@ -1,4 +1,4 @@ import uvicorn if __name__ == "__main__": - uvicorn.run("app.main:app", host="127.0.0.1", port=8000, reload=False) + uvicorn.run("app.main:app", host="127.0.0.1", port=8000, reload=True) diff --git a/frontend/js/app.js b/frontend/js/app.js index b6cd3ed..b6b68c8 100644 --- a/frontend/js/app.js +++ b/frontend/js/app.js @@ -10,6 +10,7 @@ class WiringApp { this._preDrag = null; // snapshot captured at dragstart for undo this._octopartReady = null; // null=unknown, true/false after status check this._bundles = []; // wire bundles for current diagram + this._updatingBundleDropdown = false; this.canvas = new DiagramCanvas("canvas-container", { onDeviceSelected: (d) => this._showDeviceProps(d), @@ -62,11 +63,26 @@ class WiringApp { this._savedTimer = setTimeout(() => { const el = document.getElementById("saved-indicator"); if (!el) return; + el.textContent = "✓ Saved"; + el.style.color = ""; el.classList.add("show"); setTimeout(() => el.classList.remove("show"), 1400); }, 600); } + _flashError() { + clearTimeout(this._savedTimer); + const el = document.getElementById("saved-indicator"); + if (!el) return; + el.textContent = "✗ Save failed"; + el.style.color = "#e06c6c"; + el.classList.add("show"); + this._savedTimer = setTimeout(() => { + el.classList.remove("show"); + el.style.color = ""; + }, 3000); + } + // ── Undo ────────────────────────────────────────────────────────────────────── _pushUndo(fn) { @@ -599,6 +615,7 @@ class WiringApp { }); document.getElementById("wire-bundle-select")?.addEventListener("change", (e) => { + if (this._updatingBundleDropdown) return; const bundleId = e.target.value ? parseInt(e.target.value) : null; this._patchWire({ bundle_id: bundleId }, true); this._refreshBundleEditPanel(bundleId); @@ -708,8 +725,13 @@ class WiringApp { Object.assign(w, data); if (redraw) this.canvas.updateWire(w); } - await api.wires.update(id, data).catch(e => console.error("Wire save failed:", e)); - this._flashSaved(); + try { + await api.wires.update(id, data); + this._flashSaved(); + } catch (e) { + console.error("Wire save failed:", e); + this._flashError(); + } } // ── Diagram management ──────────────────────────────────────────────────────── @@ -1338,6 +1360,7 @@ class WiringApp { _refreshBundleDropdown(selectedId) { const sel = document.getElementById("wire-bundle-select"); if (!sel) return; + this._updatingBundleDropdown = true; sel.innerHTML = ''; this._bundles.forEach(b => { const opt = document.createElement("option"); @@ -1346,6 +1369,7 @@ class WiringApp { if (b.id === selectedId) opt.selected = true; sel.appendChild(opt); }); + this._updatingBundleDropdown = false; } _refreshBundleEditPanel(bundleId) {