321 lines
16 KiB
HTML
321 lines
16 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>LED Controller - Tab Mode</title>
|
||
<link rel="stylesheet" href="/static/style.css">
|
||
</head>
|
||
<body>
|
||
<div class="app-container">
|
||
<header>
|
||
<div class="tabs-container">
|
||
<div id="tabs-list">
|
||
Loading tabs...
|
||
</div>
|
||
</div>
|
||
<div class="header-actions">
|
||
<button class="btn btn-secondary" id="profiles-btn">Profiles</button>
|
||
<button class="btn btn-secondary edit-mode-only" id="tabs-btn">Tabs</button>
|
||
<button class="btn btn-secondary edit-mode-only" id="presets-btn">Presets</button>
|
||
<button class="btn btn-secondary edit-mode-only" id="patterns-btn">Patterns</button>
|
||
<button class="btn btn-secondary edit-mode-only" id="color-palette-btn">Colour Palette</button>
|
||
<button class="btn btn-secondary edit-mode-only" id="send-profile-presets-btn">Send Presets</button>
|
||
<button class="btn btn-secondary" id="help-btn">Help</button>
|
||
<button type="button" class="btn btn-secondary ui-mode-toggle" id="ui-mode-toggle" aria-pressed="false" title="Switch preset strip mode — label is the mode you will switch to">Edit mode</button>
|
||
</div>
|
||
<div class="header-menu-mobile">
|
||
<button class="btn btn-secondary" id="main-menu-btn">Menu</button>
|
||
<div id="main-menu-dropdown" class="main-menu-dropdown">
|
||
<button type="button" class="ui-mode-toggle" id="ui-mode-toggle-mobile" aria-pressed="false">Edit mode</button>
|
||
<button type="button" data-target="profiles-btn">Profiles</button>
|
||
<button type="button" class="edit-mode-only" data-target="tabs-btn">Tabs</button>
|
||
<button type="button" class="edit-mode-only" data-target="presets-btn">Presets</button>
|
||
<button type="button" class="edit-mode-only" data-target="patterns-btn">Patterns</button>
|
||
<button type="button" class="edit-mode-only" data-target="color-palette-btn">Colour Palette</button>
|
||
<button type="button" class="edit-mode-only" data-target="send-profile-presets-btn">Send Presets</button>
|
||
<button type="button" data-target="help-btn">Help</button>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="main-content">
|
||
<div id="tab-content" class="tab-content">
|
||
<div class="tab-content-placeholder">
|
||
Select a tab to get started
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tabs Modal -->
|
||
<div id="tabs-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Tabs</h2>
|
||
<div class="profiles-actions">
|
||
<input type="text" id="new-tab-name" placeholder="Tab name">
|
||
<input type="text" id="new-tab-ids" placeholder="Device IDs (1,2,3)" value="1">
|
||
<button class="btn btn-primary" id="create-tab-btn">Create</button>
|
||
</div>
|
||
<div id="tabs-list-modal" class="profiles-list"></div>
|
||
<div class="modal-actions">
|
||
<button class="btn btn-secondary" id="tabs-close-btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Edit Tab Modal -->
|
||
<div id="edit-tab-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Edit Tab</h2>
|
||
<form id="edit-tab-form">
|
||
<input type="hidden" id="edit-tab-id">
|
||
<div class="modal-actions" style="margin-bottom: 1rem;">
|
||
<button type="submit" class="btn btn-primary">Save</button>
|
||
<button type="button" class="btn btn-secondary" onclick="document.getElementById('edit-tab-modal').classList.remove('active')">Close</button>
|
||
</div>
|
||
<label>Tab Name:</label>
|
||
<input type="text" id="edit-tab-name" placeholder="Enter tab name" required>
|
||
<label>Device IDs (comma-separated):</label>
|
||
<input type="text" id="edit-tab-ids" placeholder="1,2,3" required>
|
||
<label style="margin-top: 1rem;">Add presets to this tab</label>
|
||
<div id="edit-tab-presets-list" class="profiles-list" style="max-height: 200px; overflow-y: auto; margin-bottom: 1rem;"></div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Profiles Modal -->
|
||
<div id="profiles-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Profiles</h2>
|
||
<div class="profiles-actions">
|
||
<input type="text" id="new-profile-name" placeholder="Profile name">
|
||
<button class="btn btn-primary" id="create-profile-btn">Create</button>
|
||
</div>
|
||
<div class="form-group" style="margin-top: 0.5rem; margin-bottom: 0;">
|
||
<label style="display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0;">
|
||
<input type="checkbox" id="new-profile-seed-dj">
|
||
DJ tab
|
||
</label>
|
||
</div>
|
||
<div id="profiles-list" class="profiles-list"></div>
|
||
<div class="modal-actions">
|
||
<button class="btn btn-secondary" id="profiles-close-btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Presets Modal -->
|
||
<div id="presets-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Presets</h2>
|
||
<div class="modal-actions">
|
||
<button class="btn btn-primary" id="preset-add-btn">Add</button>
|
||
</div>
|
||
<div id="presets-list" class="profiles-list"></div>
|
||
<div class="modal-actions">
|
||
<button class="btn btn-secondary" id="presets-close-btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Preset Editor Modal -->
|
||
<div id="preset-editor-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Preset</h2>
|
||
<div class="profiles-actions">
|
||
<input type="text" id="preset-name-input" placeholder="Preset name">
|
||
<select id="preset-pattern-input">
|
||
<option value="">Pattern</option>
|
||
</select>
|
||
</div>
|
||
<label>Colours</label>
|
||
<div id="preset-colors-container" class="preset-colors-container"></div>
|
||
<div class="profiles-actions">
|
||
<input type="color" id="preset-new-color" value="#ffffff" title="Choose colour (auto-adds)">
|
||
<button class="btn btn-secondary btn-small" id="preset-add-from-palette-btn">From Palette</button>
|
||
</div>
|
||
<div class="profiles-actions">
|
||
<div class="preset-editor-field">
|
||
<label for="preset-brightness-input">Brightness (0–255)</label>
|
||
<input type="number" id="preset-brightness-input" placeholder="Brightness" min="0" max="255" value="0">
|
||
</div>
|
||
<div class="preset-editor-field">
|
||
<label for="preset-delay-input">Delay (ms)</label>
|
||
<input type="number" id="preset-delay-input" placeholder="Delay" min="0" max="10000" value="0">
|
||
</div>
|
||
</div>
|
||
<div class="n-params-grid">
|
||
<div class="n-param-group">
|
||
<label for="preset-n1-input" id="preset-n1-label">n1:</label>
|
||
<input type="number" id="preset-n1-input" min="0" max="255" value="0" class="n-input">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="preset-n2-input" id="preset-n2-label">n2:</label>
|
||
<input type="number" id="preset-n2-input" min="0" max="255" value="0" class="n-input">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="preset-n3-input" id="preset-n3-label">n3:</label>
|
||
<input type="number" id="preset-n3-input" min="0" max="255" value="0" class="n-input">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="preset-n4-input" id="preset-n4-label">n4:</label>
|
||
<input type="number" id="preset-n4-input" min="0" max="255" value="0" class="n-input">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="preset-n5-input" id="preset-n5-label">n5:</label>
|
||
<input type="number" id="preset-n5-input" min="0" max="255" value="0" class="n-input">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="preset-n6-input" id="preset-n6-label">n6:</label>
|
||
<input type="number" id="preset-n6-input" min="0" max="255" value="0" class="n-input">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="preset-n7-input" id="preset-n7-label">n7:</label>
|
||
<input type="number" id="preset-n7-input" min="0" max="255" value="0" class="n-input">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="preset-n8-input" id="preset-n8-label">n8:</label>
|
||
<input type="number" id="preset-n8-input" min="0" max="255" value="0" class="n-input">
|
||
</div>
|
||
</div>
|
||
<div class="modal-actions">
|
||
<button class="btn btn-secondary" id="preset-send-btn">Try</button>
|
||
<button class="btn btn-secondary" id="preset-default-btn">Default</button>
|
||
<button class="btn btn-primary" id="preset-save-btn">Save & Send</button>
|
||
<button class="btn btn-secondary" id="preset-editor-close-btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Patterns Modal -->
|
||
<div id="patterns-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Patterns</h2>
|
||
<div id="patterns-list" class="profiles-list"></div>
|
||
<div class="modal-actions">
|
||
<button class="btn btn-secondary" id="patterns-close-btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Colour Palette Modal -->
|
||
<div id="color-palette-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Colour Palette</h2>
|
||
<p class="muted-text">Profile: <span id="palette-current-profile-name">None</span></p>
|
||
<div id="palette-container" class="profiles-list"></div>
|
||
<div class="profiles-actions">
|
||
<input type="color" id="palette-new-color" value="#ffffff">
|
||
</div>
|
||
<div class="modal-actions">
|
||
<button class="btn btn-secondary" id="color-palette-close-btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Help Modal -->
|
||
<div id="help-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Help</h2>
|
||
<p class="muted-text">How to use the LED controller UI.</p>
|
||
|
||
<h3>Run mode</h3>
|
||
<ul>
|
||
<li><strong>Select tab</strong>: left-click a tab button in the top bar.</li>
|
||
<li><strong>Select preset</strong>: left-click a preset tile to send a <code>select</code> message to all devices in the tab.</li>
|
||
<li><strong>Profiles</strong>: open <strong>Profiles</strong> to apply a profile. Profile editing actions are hidden in Run mode.</li>
|
||
<li><strong>Send all presets</strong>: this action is available in <strong>Edit mode</strong> and pushes every preset used in the current tab to all tab devices.</li>
|
||
<li><strong>Switch modes</strong>: use the mode button in the menu. The button label shows the mode you will switch to.</li>
|
||
</ul>
|
||
|
||
<h3>Edit mode</h3>
|
||
<ul>
|
||
<li><strong>Tabs</strong>: create, edit, and manage tabs and device assignments.</li>
|
||
<li><strong>Presets</strong>: create/manage reusable presets and edit preset details.</li>
|
||
<li><strong>Preset tiles</strong>: each tile shows <strong>Edit</strong> and <strong>Remove</strong> controls in Edit mode.</li>
|
||
<li><strong>Reorder presets</strong>: drag and drop preset tiles to save tab order.</li>
|
||
<li><strong>Profiles</strong>: create/clone/delete profiles. New profiles get a populated <strong>default</strong> tab and can optionally seed a <strong>DJ tab</strong>.</li>
|
||
<li><strong>Colour Palette</strong>: build profile colours and use <strong>From Palette</strong> in preset editor to add linked colours (badge <strong>P</strong>) that update when palette colours change.</li>
|
||
</ul>
|
||
|
||
<div class="modal-actions">
|
||
<button class="btn btn-secondary" id="help-close-btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Settings Modal -->
|
||
<div id="settings-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Device Settings</h2>
|
||
<p class="muted-text">Configure WiFi Access Point and device settings.</p>
|
||
|
||
<div id="settings-message" class="message"></div>
|
||
|
||
<!-- Device Name -->
|
||
<div class="settings-section">
|
||
<h3>Device</h3>
|
||
<form id="device-form">
|
||
<div class="form-group">
|
||
<label for="device-name-input">Device Name</label>
|
||
<input type="text" id="device-name-input" name="device_name" placeholder="e.g. led-controller" required>
|
||
<small>This name may be used for mDNS (e.g. <code>name.local</code>) and UI display.</small>
|
||
</div>
|
||
<div class="btn-group">
|
||
<button type="submit" class="btn btn-primary btn-full">Save Name</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<!-- WiFi Access Point Settings -->
|
||
<div class="settings-section ap-settings-section">
|
||
<h3>WiFi Access Point</h3>
|
||
|
||
<div id="ap-status" class="status-info">
|
||
<h4>AP Status</h4>
|
||
<p>Loading...</p>
|
||
</div>
|
||
|
||
<form id="ap-form">
|
||
<div class="form-group">
|
||
<label for="ap-ssid">AP SSID (Network Name)</label>
|
||
<input type="text" id="ap-ssid" name="ssid" placeholder="Enter AP name" required>
|
||
<small>The name of the WiFi access point this device creates</small>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="ap-password">AP Password</label>
|
||
<input type="password" id="ap-password" name="password" placeholder="Enter AP password (min 8 chars)" data-bwignore>
|
||
<small>Leave empty for open network (min 8 characters if set)</small>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="ap-channel">Channel (1-11)</label>
|
||
<input type="number" id="ap-channel" name="channel" min="1" max="11" placeholder="Auto">
|
||
<small>WiFi channel (1-11 for 2.4GHz). Leave empty for auto.</small>
|
||
</div>
|
||
|
||
<div class="btn-group">
|
||
<button type="submit" class="btn btn-primary btn-full">Configure AP</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<div class="modal-actions">
|
||
<button class="btn btn-secondary" id="settings-close-btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Styles moved to /static/style.css -->
|
||
<script src="/static/tabs.js"></script>
|
||
<script src="/static/help.js"></script>
|
||
<script src="/static/color_palette.js"></script>
|
||
<script src="/static/profiles.js"></script>
|
||
<script src="/static/tab_palette.js"></script>
|
||
<script src="/static/patterns.js"></script>
|
||
<script src="/static/presets.js"></script>
|
||
</body>
|
||
</html>
|