From 758b60f3fd5d8999d0a97f93e4f4e83832d4ebe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?PROFERIS=20-=20Mi=C2=B3osz=20Stocki?= Date: Wed, 15 Jul 2026 14:12:11 +0200 Subject: [PATCH] Add manual pick on Board Control. Closes #26 --- web/js/sections/board-control.js | 61 +++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/web/js/sections/board-control.js b/web/js/sections/board-control.js index 7c12057..40df49e 100644 --- a/web/js/sections/board-control.js +++ b/web/js/sections/board-control.js @@ -13,6 +13,7 @@ let bounds = { xMin: -150, xMax: 150, yMin: -30, yMax: 145 }; let currentBg = localStorage.getItem('wiji_bg') || 'default'; let steps1 = 0; let steps2 = 0; +let isManualPickMode = false; function syncStateFromStorage() { isHomed = localStorage.getItem('wiji_homed') === 'true'; @@ -86,7 +87,12 @@ function buildHTML() {
-
Interactive Map
+
+ Interactive Map + +
@@ -430,6 +436,59 @@ export default { } }); + // ── Manual Pick Mode ────────────────────────────────────── + const btnManualPick = document.getElementById('btn-manual-pick'); + const mapContainer = document.getElementById('map-container'); + + if (btnManualPick && mapContainer) { + btnManualPick.addEventListener('click', () => { + isManualPickMode = !isManualPickMode; + if (isManualPickMode) { + btnManualPick.classList.add('btn-success'); + btnManualPick.classList.remove('btn-secondary'); + mapContainer.style.cursor = 'crosshair'; + } else { + btnManualPick.classList.remove('btn-success'); + btnManualPick.classList.add('btn-secondary'); + mapContainer.style.cursor = 'default'; + } + }); + + mapContainer.addEventListener('click', (e) => { + if (!isManualPickMode) return; + // Ignore clicks on existing markers + if (e.target.classList.contains('spot-marker')) return; + + const rect = mapContainer.getBoundingClientRect(); + const xClick = e.clientX - rect.left; + const yClick = e.clientY - rect.top; + + const w = bounds.xMax - bounds.xMin; + const h = bounds.yMax - bounds.yMin; + + const x = bounds.xMin + (xClick / rect.width) * w; + const y = bounds.yMax - (yClick / rect.height) * h; + + const check = IK.checkWorkspace(x, y); + if (!check.valid) { + UI.log(check.reason, 'warning'); + return; + } + + // Execute move + if (listEl) listEl.value = ''; // Deselect predefined spots + goBtn.disabled = true; + + executeMove({ id: 'manual', label: `Manual [${x.toFixed(1)}, ${y.toFixed(1)}]`, x, y }); + + // Turn off mode automatically (one-shot) + isManualPickMode = false; + btnManualPick.classList.remove('btn-success'); + btnManualPick.classList.add('btn-secondary'); + mapContainer.style.cursor = 'default'; + }); + } + // ── Sync Steps from BLE ─────────────────────────────────── const onBLEStatus = (e) => { const msg = e.detail;