feat(zones): profile-scoped groups, zone modes, sequence brightness
- Optional profile_id on groups; UI and API for shared vs profile-only groups\n- Zone content_kind (presets vs sequences); edit modal shows matching sections; devices via groups only\n- Server sequence playback folds zone brightness into preset wire b (per MAC where needed)\n- Related preset/sequence/audio/beat-route and client updates Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -83,6 +83,11 @@
|
||||
<input type="text" id="new-zone-name" placeholder="Zone name">
|
||||
<button class="btn btn-primary" id="create-zone-btn">Create</button>
|
||||
</div>
|
||||
<fieldset class="muted-text" style="margin:0.35rem 0 0.75rem;border:none;padding:0;">
|
||||
<legend style="font-size:0.85em;margin-bottom:0.35rem;">This zone is for</legend>
|
||||
<label style="margin-right:1rem;"><input type="radio" name="new-zone-content-kind" value="presets" checked> Presets</label>
|
||||
<label><input type="radio" name="new-zone-content-kind" value="sequences"> Sequences</label>
|
||||
</fieldset>
|
||||
<div id="zones-list-modal" class="profiles-list"></div>
|
||||
<div class="modal-actions">
|
||||
<button class="btn btn-secondary" id="zones-close-btn">Close</button>
|
||||
@@ -102,16 +107,22 @@
|
||||
</div>
|
||||
<label>Zone Name:</label>
|
||||
<input type="text" id="edit-zone-name" placeholder="Enter zone name" required>
|
||||
<label class="zone-devices-label">Device groups in this zone</label>
|
||||
<div id="edit-zone-devices-editor" class="zone-devices-editor"></div>
|
||||
<div id="edit-zone-block-groups">
|
||||
<label class="zone-devices-label">Device groups on this zone</label>
|
||||
<div id="edit-zone-groups-editor" class="zone-devices-editor"></div>
|
||||
</div>
|
||||
<div id="edit-zone-block-presets">
|
||||
<label class="zone-presets-section-label">Presets on this zone</label>
|
||||
<div id="edit-zone-presets-current" class="profiles-list edit-zone-presets-scroll"></div>
|
||||
<label class="zone-presets-section-label">Add presets to this zone</label>
|
||||
<div id="edit-zone-presets-list" class="profiles-list edit-zone-presets-scroll"></div>
|
||||
</div>
|
||||
<div id="edit-zone-block-sequences">
|
||||
<label class="zone-presets-section-label">Sequences on this zone</label>
|
||||
<div id="edit-zone-sequences-current" class="profiles-list edit-zone-presets-scroll"></div>
|
||||
<label class="zone-presets-section-label">Add a sequence to this zone</label>
|
||||
<div id="edit-zone-sequences-list" class="profiles-list edit-zone-presets-scroll"></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -148,13 +159,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Device groups: members + Wi‑Fi driver defaults (zones reference groups) -->
|
||||
<!-- Device groups: members + Wi‑Fi driver defaults (zones reference groups for presets) -->
|
||||
<div id="groups-modal" class="modal">
|
||||
<div class="modal-content">
|
||||
<h2>Device groups</h2>
|
||||
<p class="muted-text" style="margin-top:0;">Assign drivers to a group, set Wi‑Fi defaults once per group, then attach groups to zones.</p>
|
||||
<p class="muted-text" style="margin-top:0;">Assign drivers to a group, set Wi‑Fi defaults once per group, then attach groups to a zone for standalone presets (sequences use each lane’s groups only). By default new groups are <strong>shared</strong> across all profiles; tick “this profile only” to hide a group from other profiles.</p>
|
||||
<div class="profiles-actions zone-modal-create-row">
|
||||
<input type="text" id="new-group-name" placeholder="Group name">
|
||||
<label class="muted-text" style="display:inline-flex;align-items:center;gap:0.35rem;white-space:nowrap;">
|
||||
<input type="checkbox" id="new-group-profile-only"> This profile only
|
||||
</label>
|
||||
<button class="btn btn-primary" id="create-group-btn">Create</button>
|
||||
</div>
|
||||
<div id="groups-list-modal" class="profiles-list"></div>
|
||||
@@ -175,6 +189,10 @@
|
||||
</div>
|
||||
<label for="edit-group-name">Group name</label>
|
||||
<input type="text" id="edit-group-name" required autocomplete="off">
|
||||
<label class="muted-text" style="display:flex;align-items:flex-start;gap:0.5rem;margin-top:0.5rem;">
|
||||
<input type="checkbox" id="edit-group-share-all-profiles" style="margin-top:0.2rem;">
|
||||
<span>Share with all profiles (untick to keep this group on the <strong>current profile only</strong>)</span>
|
||||
</label>
|
||||
<label class="zone-devices-label">Devices in this group</label>
|
||||
<div id="edit-group-devices-editor" class="zone-devices-editor"></div>
|
||||
<div class="profiles-actions" style="margin-top: 0.5rem;">
|
||||
@@ -315,26 +333,15 @@
|
||||
<label for="sequence-editor-name">Name</label>
|
||||
<input type="text" id="sequence-editor-name" placeholder="Sequence name" style="width:100%;max-width:24rem;">
|
||||
</div>
|
||||
<div class="preset-editor-field">
|
||||
<label for="sequence-editor-advance-mode">Advance</label>
|
||||
<select id="sequence-editor-advance-mode" style="max-width:16rem;">
|
||||
<option value="time">Time (ms between steps)</option>
|
||||
<option value="beats">Audio beats (requires Audio detector)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="preset-editor-field" id="sequence-editor-duration-wrap">
|
||||
<label for="sequence-editor-duration">Step duration (ms), all lanes together</label>
|
||||
<div style="display:flex;align-items:center;gap:0.6rem;flex-wrap:wrap;">
|
||||
<input type="number" id="sequence-editor-duration" min="200" max="600000" value="3000" style="width:8rem;">
|
||||
<span id="sequence-editor-time-bpm-hint" class="muted-text" style="font-size:0.9em;"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="preset-editor-field" id="sequence-editor-transition-wrap">
|
||||
<label for="sequence-editor-transition">Pause before next step (ms)</label>
|
||||
<input type="number" id="sequence-editor-transition" min="0" max="60000" value="500" style="width:8rem;">
|
||||
</div>
|
||||
<div id="sequence-editor-beats-panel" style="display:none;margin:0 0 0.75rem 0;">
|
||||
<p id="sequence-editor-bpm-live" class="muted-text" style="font-size:0.85em;margin:0;">—</p>
|
||||
<div id="sequence-editor-beats-panel" style="margin:0 0 0.75rem 0;">
|
||||
<p class="muted-text" style="font-size:0.85em;margin:0 0 0.5rem 0;">
|
||||
Each step runs for the number of <strong>beats</strong> you set on that step.
|
||||
When the header <strong>Audio</strong> detector is running, real beats advance the sequence.
|
||||
When it is stopped, the server uses <strong>simulated</strong> beats at the BPM below.
|
||||
</p>
|
||||
<label for="sequence-editor-simulated-bpm" style="display:block;margin-bottom:0.25rem;">Simulated BPM (when audio is off)</label>
|
||||
<input type="number" id="sequence-editor-simulated-bpm" min="30" max="300" value="120" style="width:6rem;" title="Used only while the audio detector is stopped">
|
||||
<p id="sequence-editor-bpm-live" class="muted-text" style="font-size:0.85em;margin:0.5rem 0 0 0;">—</p>
|
||||
</div>
|
||||
<div id="sequence-editor-lanes"></div>
|
||||
<div class="modal-actions" style="margin-top:0.75rem;">
|
||||
@@ -377,6 +384,7 @@
|
||||
<label for="preset-background-input">Background</label>
|
||||
<div class="profiles-actions" style="gap: 0.4rem;">
|
||||
<button type="button" class="btn btn-secondary btn-small" id="preset-background-btn" title="Choose background colour">#000000</button>
|
||||
<button type="button" class="btn btn-secondary btn-small" id="preset-background-from-palette-btn">From Palette</button>
|
||||
<input type="color" id="preset-background-input" value="#000000" title="Background colour used in patterns with background support" style="position:absolute;opacity:0;pointer-events:none;width:1px;height:1px;">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user