update todo

This commit is contained in:
PROFERIS - Mi³osz Stocki
2026-07-06 15:47:02 +02:00
parent f652b741ae
commit a6aa6f00df
3 changed files with 172 additions and 177 deletions
+163 -168
View File
@@ -1,10 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>WijiBoard Control Dashboard</title>
<meta name="description" content="WijiBoard SCARA arm control dashboard. Web Bluetooth interface for the ESP32-S3 stepper controller." />
<meta name="description"
content="WijiBoard SCARA arm control dashboard. Web Bluetooth interface for the ESP32-S3 stepper controller." />
<!-- Shared styles -->
<link rel="stylesheet" href="web/styles/base.css" />
@@ -12,193 +14,186 @@
</head>
<body>
<div class="app-shell">
<div class="app-shell">
<!-- ── Sidebar overlay (click to close) ──────────────────────── -->
<div class="sidebar-overlay" id="sidebar-overlay"></div>
<!-- ── Sidebar overlay (click to close) ──────────────────────── -->
<div class="sidebar-overlay" id="sidebar-overlay"></div>
<!-- ── Sidebar ───────────────────────────────────────────────── -->
<nav class="sidebar" id="sidebar" aria-label="Main navigation">
<!-- ── Sidebar ───────────────────────────────────────────────── -->
<nav class="sidebar" id="sidebar" aria-label="Main navigation">
<span class="sidebar-section-label">Navigation</span>
<span class="sidebar-section-label">Navigation</span>
<a class="sidebar-nav-item active" id="nav-home"
href="#home" data-route="home"
role="button" aria-label="Go to Home">
<svg class="nav-icon" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
<polyline points="9 22 9 12 15 12 15 22"/>
</svg>
Home
</a>
<a class="sidebar-nav-item active" id="nav-home" href="#home" data-route="home" role="button"
aria-label="Go to Home">
<svg class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
<polyline points="9 22 9 12 15 12 15 22" />
</svg>
Home
</a>
<a class="sidebar-nav-item" id="nav-stepper-test"
href="#stepper-test" data-route="stepper-test"
role="button" aria-label="Go to Stepper Test">
<svg class="nav-icon" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="3"/>
<path d="M12 1v4M12 19v4M4.22 4.22l2.83 2.83M16.95 16.95l2.83 2.83M1 12h4M19 12h4M4.22 19.78l2.83-2.83M16.95 7.05l2.83-2.83"/>
</svg>
Stepper Test
</a>
<a class="sidebar-nav-item" id="nav-stepper-test" href="#stepper-test" data-route="stepper-test" role="button"
aria-label="Go to Stepper Test">
<svg class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="3" />
<path
d="M12 1v4M12 19v4M4.22 4.22l2.83 2.83M16.95 16.95l2.83 2.83M1 12h4M19 12h4M4.22 19.78l2.83-2.83M16.95 7.05l2.83-2.83" />
</svg>
Stepper Test
</a>
<!-- Spacer + coming soon -->
<div style="flex:1"></div>
<div class="divider"></div>
<span class="sidebar-section-label">Coming Soon</span>
<!-- Spacer + coming soon -->
<div style="flex:1"></div>
<div class="divider"></div>
<span class="sidebar-section-label">Coming Soon</span>
<div class="sidebar-nav-item" style="opacity:0.35;cursor:default" aria-disabled="true">
<svg class="nav-icon" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M12 20h9M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/>
</svg>
Board Control
</div>
<div class="sidebar-nav-item" style="opacity:0.35;cursor:default" aria-disabled="true">
<svg class="nav-icon" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M3 3h7v7H3zM14 3h7v7h-7zM14 14h7v7h-7zM3 14h7v7H3z"/>
</svg>
Sequence Editor
</div>
</nav>
<!-- ── Main area ──────────────────────────────────────────────── -->
<div style="display:flex;flex-direction:column;flex:1;overflow:hidden">
<!-- Top bar -->
<header class="topbar" role="banner">
<!-- Hamburger -->
<button class="hamburger" id="hamburger-btn"
aria-label="Toggle sidebar" aria-expanded="true" aria-controls="sidebar">
<div class="hamburger-bar"></div>
<div class="hamburger-bar"></div>
<div class="hamburger-bar"></div>
</button>
<!-- Brand -->
<div class="topbar-brand">
<div class="brand-icon" aria-hidden="true">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M12 2L3 7v10l9 5 9-5V7L12 2Z"
stroke="#448aff" stroke-width="1.5" stroke-linejoin="round"/>
<circle cx="12" cy="12" r="2.5" fill="#448aff" opacity="0.7"/>
</svg>
</div>
WijiBoard
<div class="sidebar-nav-item" style="opacity:0.35;cursor:default" aria-disabled="true">
<svg class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M12 20h9M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z" />
</svg>
Board Control
</div>
<!-- BLE actions -->
<div class="topbar-actions">
<!-- BLE status pill -->
<div class="ble-status" id="ble-status" aria-live="polite">
<div class="ble-dot" id="ble-dot"></div>
<span class="ble-label" id="ble-label">Disconnected</span>
</div>
<div class="sidebar-nav-item" style="opacity:0.35;cursor:default" aria-disabled="true">
<svg class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M3 3h7v7H3zM14 3h7v7h-7zM14 14h7v7h-7zM3 14h7v7H3z" />
</svg>
Sequence Editor
</div>
</nav>
<!-- Connect / Disconnect button -->
<button class="btn btn-sm btn-primary" id="btn-ble-connect"
aria-label="Connect to WijiBoard via Bluetooth">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2.5"
stroke-linecap="round" stroke-linejoin="round">
<path d="M6.5 6.5l11 11M17.5 6.5l-5 5 5 5"/>
<path d="M6 17.5l5-5-5-5"/>
</svg>
<span class="btn-text">Connect</span>
<!-- ── Main area ──────────────────────────────────────────────── -->
<div style="display:flex;flex-direction:column;flex:1;overflow:hidden">
<!-- Top bar -->
<header class="topbar" role="banner">
<!-- Hamburger -->
<button class="hamburger" id="hamburger-btn" aria-label="Toggle sidebar" aria-expanded="true"
aria-controls="sidebar">
<div class="hamburger-bar"></div>
<div class="hamburger-bar"></div>
<div class="hamburger-bar"></div>
</button>
</div>
</header>
<!-- Router outlet -->
<main class="main-content" id="view" role="main" aria-label="Page content">
<!-- Sections are injected here by router.js -->
</main>
<!-- Brand -->
<div class="topbar-brand">
<div class="brand-icon" aria-hidden="true">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M12 2L3 7v10l9 5 9-5V7L12 2Z" stroke="#448aff" stroke-width="1.5" stroke-linejoin="round" />
<circle cx="12" cy="12" r="2.5" fill="#448aff" opacity="0.7" />
</svg>
</div>
WijiBoard
</div>
<!-- BLE actions -->
<div class="topbar-actions">
<!-- BLE status pill -->
<div class="ble-status" id="ble-status" aria-live="polite">
<div class="ble-dot" id="ble-dot"></div>
<span class="ble-label" id="ble-label">Disconnected</span>
</div>
<!-- Connect / Disconnect button -->
<button class="btn btn-sm btn-primary" id="btn-ble-connect" aria-label="Connect to WijiBoard via Bluetooth">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"
stroke-linecap="round" stroke-linejoin="round">
<path d="M6.5 6.5l11 11M17.5 6.5l-5 5 5 5" />
<path d="M6 17.5l5-5-5-5" />
</svg>
<span class="btn-text">Connect</span>
</button>
</div>
</header>
<!-- Router outlet -->
<main class="main-content" id="view" role="main" aria-label="Page content">
<!-- Sections are injected here by router.js -->
</main>
</div>
</div>
</div>
<!-- ── App bootstrap (ES module entry point) ─────────────────── -->
<script type="module">
const V = Date.now(); // cache-buster ensures fresh module load on every page refresh
const { default: Router } = await import(`./web/js/router.js?v=${V}`);
const { default: BLE } = await import(`./web/js/ble.js?v=${V}`);
const { default: UI } = await import(`./web/js/ui.js?v=${V}`);
const { default: HomeSection } = await import(`./web/js/sections/home.js?v=${V}`);
const { default: StepperSection } = await import(`./web/js/sections/stepper-test.js?v=${V}`);
<!-- ── App bootstrap (ES module entry point) ─────────────────── -->
<script type="module">
const V = Date.now(); // cache-buster ensures fresh module load on every page refresh
const { default: Router } = await import(`./web/js/router.js?v=${V}`);
const { default: BLE } = await import(`./web/js/ble.js?v=${V}`);
const { default: UI } = await import(`./web/js/ui.js?v=${V}`);
const { default: HomeSection } = await import(`./web/js/sections/home.js?v=${V}`);
const { default: StepperSection } = await import(`./web/js/sections/stepper-test.js?v=${V}`);
// ── Register routes ────────────────────────────────────────────
Router.register('home', HomeSection);
Router.register('stepper-test', StepperSection);
// ── Register routes ────────────────────────────────────────────
Router.register('home', HomeSection);
Router.register('stepper-test', StepperSection);
// ── Sidebar toggle logic ───────────────────────────────────────
const sidebar = document.getElementById('sidebar');
const overlay = document.getElementById('sidebar-overlay');
const hamburger = document.getElementById('hamburger-btn');
const mainContent = document.getElementById('view');
// ── Sidebar toggle logic ───────────────────────────────────────
const sidebar = document.getElementById('sidebar');
const overlay = document.getElementById('sidebar-overlay');
const hamburger = document.getElementById('hamburger-btn');
const mainContent = document.getElementById('view');
let sidebarOpen = true;
let sidebarOpen = true;
function setSidebarOpen(open) {
sidebarOpen = open;
sidebar.classList.toggle('collapsed', !open);
overlay.classList.toggle('visible', open && window.innerWidth < 900);
hamburger.classList.toggle('open', open);
hamburger.setAttribute('aria-expanded', open);
function setSidebarOpen(open) {
sidebarOpen = open;
sidebar.classList.toggle('collapsed', !open);
overlay.classList.toggle('visible', open && window.innerWidth < 900);
hamburger.classList.toggle('open', open);
hamburger.setAttribute('aria-expanded', open);
// Shift main content on desktop
const mc = hamburger.closest('.app-shell')?.querySelector('.main-content');
if (mc) mc.classList.toggle('sidebar-collapsed', !open);
}
hamburger.addEventListener('click', () => setSidebarOpen(!sidebarOpen));
overlay.addEventListener('click', () => setSidebarOpen(false));
// Close sidebar on small screens when nav link clicked
document.querySelectorAll('.sidebar-nav-item[data-route]').forEach(link => {
link.addEventListener('click', (e) => {
e.preventDefault();
const route = link.dataset.route;
Router.navigate('#' + route);
if (window.innerWidth < 900) setSidebarOpen(false);
});
});
// Collapse sidebar by default on small screens
if (window.innerWidth < 900) setSidebarOpen(false);
// ── Wire BLE events to shared UI ──────────────────────────────
UI.initBLEListeners();
// Connect button handler (initial state)
document.getElementById('btn-ble-connect').addEventListener('click', () => {
if (BLE.isConnected()) {
BLE.disconnect();
} else {
BLE.connect().catch(e => {
if (!e.message?.includes('cancelled') && !e.name?.includes('NotFound')) {
UI.log(`Connect error: ${e.message}`, 'error');
}
});
// Shift main content on desktop
const mc = hamburger.closest('.app-shell')?.querySelector('.main-content');
if (mc) mc.classList.toggle('sidebar-collapsed', !open);
}
});
// ── Init router (last step) ────────────────────────────────────
Router.init('#view', '#home');
hamburger.addEventListener('click', () => setSidebarOpen(!sidebarOpen));
overlay.addEventListener('click', () => setSidebarOpen(false));
// ── Check Web Bluetooth availability ──────────────────────────
if (!navigator.bluetooth) {
setTimeout(() => {
UI.log('⚠ Web Bluetooth not available. Use Chrome or Edge on localhost/HTTPS.', 'error');
}, 600);
}
</script>
// Close sidebar on small screens when nav link clicked
document.querySelectorAll('.sidebar-nav-item[data-route]').forEach(link => {
link.addEventListener('click', (e) => {
e.preventDefault();
const route = link.dataset.route;
Router.navigate('#' + route);
if (window.innerWidth < 900) setSidebarOpen(false);
});
});
// Collapse sidebar by default on small screens
if (window.innerWidth < 900) setSidebarOpen(false);
// ── Wire BLE events to shared UI ──────────────────────────────
UI.initBLEListeners();
// Connect button handler (initial state)
document.getElementById('btn-ble-connect').addEventListener('click', () => {
if (BLE.isConnected()) {
BLE.disconnect();
} else {
BLE.connect().catch(e => {
if (!e.message?.includes('cancelled') && !e.name?.includes('NotFound')) {
UI.log(`Connect error: ${e.message}`, 'error');
}
});
}
});
// ── Init router (last step) ────────────────────────────────────
Router.init('#view', '#home');
// ── Check Web Bluetooth availability ──────────────────────────
if (!navigator.bluetooth) {
setTimeout(() => {
UI.log('⚠ Web Bluetooth not available. Use Chrome or Edge on localhost/HTTPS.', 'error');
}, 600);
}
</script>
</body>
</html>
</html>