Existing accounts (including admin) seeded before new demos shipped had no easy way to pull in the latest copies — the registration-time seeder is intentionally non-destructive. The new badge action fetches src/static/bundled-demos/manifest.json, confirms the overwrite, and re-copies each canonical demo into code/. Open tabs of those files are refreshed in place so the user sees the new content immediately. src/static/bundled-demos/ ships the six canonical files plus the manifest so this works in local mode and on a static-only host. The Dockerfile now mirrors workspace/code/<demo>.py into bundled-demos/ during the image build, keeping the two locations in sync. Co-authored-by: Cursor <cursoragent@cursor.com>
124 lines
5.2 KiB
HTML
124 lines
5.2 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||
<meta name="theme-color" content="#2d3748">
|
||
<title>LED Editor</title>
|
||
<link rel="icon" href="data:,">
|
||
<link rel="stylesheet" href="/static/styles.css?v=32">
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<div class="sidebar-backdrop" id="sidebar-backdrop" hidden></div>
|
||
<div class="sidebar" id="sidebar">
|
||
<div class="sidebar-header">
|
||
<h3>Files</h3>
|
||
<div class="sidebar-actions">
|
||
<button id="new-file-btn" title="New File">📄</button>
|
||
<button id="new-folder-btn" title="New Folder">📁+</button>
|
||
<button id="delete-selected-btn" title="Delete Selected">🗑️</button>
|
||
<button id="refresh-btn" title="Refresh">🔄</button>
|
||
</div>
|
||
</div>
|
||
<div class="file-tree" id="file-tree">
|
||
<div class="loading">Loading files...</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="main-content">
|
||
<div class="editor-header">
|
||
<button id="sidebar-toggle" class="sidebar-toggle" type="button" aria-label="Toggle file tree" aria-controls="sidebar" aria-expanded="true" title="Toggle file browser"><span class="sidebar-toggle-icon" aria-hidden="true">‹</span></button>
|
||
<div class="file-info">
|
||
<span id="save-status" class="save-status"></span>
|
||
<span id="workspace-badge" class="runtime-hint hidden"></span>
|
||
</div>
|
||
<div class="editor-actions">
|
||
<button id="run-btn" class="icon-btn" disabled aria-label="Run" title="Run">▶</button>
|
||
<button id="stop-btn" class="icon-btn" disabled aria-label="Stop" title="Stop">■</button>
|
||
<details class="header-menu" id="header-menu">
|
||
<summary class="menu-toggle" aria-label="Editor options" title="Options">⋮</summary>
|
||
<div class="menu-content" role="menu">
|
||
<a href="/" class="menu-item" id="home-btn" role="menuitem">🏠 Home</a>
|
||
<label class="menu-item menu-checkbox">
|
||
<input type="checkbox" id="run-main-checkbox" />
|
||
Run main.py
|
||
</label>
|
||
<label class="menu-item menu-checkbox">
|
||
<input type="checkbox" id="panel-16x16-checkbox" />
|
||
16×16 panel
|
||
</label>
|
||
</div>
|
||
</details>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="tabs" class="tabs"></div>
|
||
|
||
<div class="editor-container">
|
||
<div id="editor"></div>
|
||
<div id="completion-dropdown" class="completion-dropdown"></div>
|
||
</div>
|
||
|
||
<section id="led-sim-panel" class="led-sim-panel hidden" aria-label="NeoPixel Simulator">
|
||
<div id="led-grid" class="led-grid"></div>
|
||
</section>
|
||
|
||
<section id="pin-panel" class="pin-panel hidden" aria-label="Pins">
|
||
<div class="pin-panel-header">
|
||
<span class="pin-panel-title">Pins</span>
|
||
<span class="pin-panel-hint">OUT shows live state · IN is clickable · PWM shows duty</span>
|
||
</div>
|
||
<div id="pin-rows" class="pin-rows"></div>
|
||
</section>
|
||
|
||
<section id="adc-panel" class="adc-panel hidden" aria-label="ADC inputs">
|
||
<div class="adc-panel-header">
|
||
<span class="adc-panel-title">ADC inputs</span>
|
||
<span class="adc-panel-hint">drag to set value (0–65535)</span>
|
||
</div>
|
||
<div id="adc-sliders" class="adc-sliders"></div>
|
||
</section>
|
||
|
||
<section id="serial-panel" class="serial-panel hidden" aria-label="Serial monitor">
|
||
<div class="serial-header">
|
||
<span class="serial-title">Serial monitor</span>
|
||
<span id="serial-meta" class="serial-meta"></span>
|
||
<button type="button" id="serial-clear" class="serial-clear" title="Clear">Clear</button>
|
||
</div>
|
||
<div id="serial-output" class="serial-output" aria-live="polite"></div>
|
||
<form id="serial-form" class="serial-form" autocomplete="off">
|
||
<input id="serial-input" type="text" class="serial-input" placeholder="Type and press Enter to send" />
|
||
<label class="serial-newline" title="Append \n on send">
|
||
<input type="checkbox" id="serial-newline-checkbox" checked />
|
||
<span>\n</span>
|
||
</label>
|
||
<button type="submit" class="serial-send">Send</button>
|
||
</form>
|
||
</section>
|
||
|
||
<div class="console-container" id="console-container">
|
||
<button type="button" class="console-header" id="console-toggle" aria-expanded="true" aria-controls="console-output">
|
||
<span class="chevron" aria-hidden="true">▾</span>
|
||
<span>Console Output</span>
|
||
</button>
|
||
<pre id="console-output" class="console-output"></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="new-file-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h3>Create New File</h3>
|
||
<input type="text" id="new-filename" placeholder="Enter filename (e.g., example.txt)" />
|
||
<div class="modal-actions">
|
||
<button id="create-file-btn">Create</button>
|
||
<button id="cancel-create-btn">Cancel</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script type="module" src="/static/script.js?v=57"></script>
|
||
</body>
|
||
</html>
|