diff --git a/src/static/patterns.js b/src/static/patterns.js index a2df5b0..bd25e53 100644 --- a/src/static/patterns.js +++ b/src/static/patterns.js @@ -55,8 +55,8 @@ document.addEventListener('DOMContentLoaded', () => { if (mode === 'create') { if (labelEl) { - labelEl.textContent = ''; - labelEl.style.display = 'none'; + labelEl.textContent = `${key}:`; + labelEl.style.display = ''; } if (inputEl) { inputEl.value = ''; @@ -203,6 +203,17 @@ document.addEventListener('DOMContentLoaded', () => { }); } + /** on/off are implemented in driver firmware (presets.py), not as OTA ``.py`` files. */ + const FIRMWARE_BUILTIN_PATTERNS = new Set(['on', 'off']); + + const isFirmwareBuiltinPattern = (patternName) => { + const id = String(patternName || '') + .trim() + .replace(/\.py$/i, '') + .toLowerCase(); + return FIRMWARE_BUILTIN_PATTERNS.has(id); + }; + const sendPatternToDevices = async (patternName) => { const response = await fetch(`/patterns/${encodeURIComponent(patternName)}/send`, { method: 'POST', @@ -281,7 +292,9 @@ document.addEventListener('DOMContentLoaded', () => { } try { - const response = await fetch(`/patterns/ota/file/${encodeURIComponent(patternName)}.py`, { + const raw = String(patternName || '').trim(); + const fileSegment = /\.py$/i.test(raw) ? raw : `${raw}.py`; + const response = await fetch(`/patterns/ota/file/${encodeURIComponent(fileSegment)}`, { headers: { Accept: 'text/plain' }, }); if (!response.ok) { @@ -315,39 +328,41 @@ document.addEventListener('DOMContentLoaded', () => { const label = document.createElement('span'); label.textContent = patternName; - const details = document.createElement('span'); - const minDelay = data && data.min_delay !== undefined ? data.min_delay : '-'; - const maxDelay = data && data.max_delay !== undefined ? data.max_delay : '-'; - details.textContent = `${minDelay}–${maxDelay} ms`; - details.style.color = '#aaa'; - details.style.fontSize = '0.85em'; - - const sendBtn = document.createElement('button'); - sendBtn.className = 'btn btn-primary btn-small'; - sendBtn.textContent = 'Send'; - sendBtn.addEventListener('click', async () => { - try { - await sendPatternToDevices(patternName); - } catch (error) { - console.error('Send pattern failed:', error); - alert(error.message || 'Failed to send pattern.'); - } - }); - - const editBtn = document.createElement('button'); - editBtn.className = 'btn btn-secondary btn-small'; - editBtn.textContent = 'Edit'; - editBtn.addEventListener('click', async () => { - if (patternEditorModal) { - patternEditorModal.classList.add('active'); - } - await loadPatternIntoEditor(patternName, data || {}); - }); - row.appendChild(label); - row.appendChild(details); - row.appendChild(editBtn); - row.appendChild(sendBtn); + + if (isFirmwareBuiltinPattern(patternName)) { + const note = document.createElement('span'); + note.className = 'muted-text'; + note.style.fontSize = '0.85em'; + note.textContent = 'Built-in (no OTA module)'; + row.appendChild(note); + } else { + const sendBtn = document.createElement('button'); + sendBtn.className = 'btn btn-primary btn-small'; + sendBtn.textContent = 'Send'; + sendBtn.addEventListener('click', async () => { + try { + await sendPatternToDevices(patternName); + } catch (error) { + console.error('Send pattern failed:', error); + alert(error.message || 'Failed to send pattern.'); + } + }); + + const editBtn = document.createElement('button'); + editBtn.className = 'btn btn-secondary btn-small'; + editBtn.textContent = 'Edit'; + editBtn.addEventListener('click', async () => { + if (patternEditorModal) { + patternEditorModal.classList.add('active'); + } + await loadPatternIntoEditor(patternName, data || {}); + }); + + row.appendChild(editBtn); + row.appendChild(sendBtn); + } + patternsList.appendChild(row); }); }; diff --git a/src/static/style.css b/src/static/style.css index 70a3ce6..bc297a0 100644 --- a/src/static/style.css +++ b/src/static/style.css @@ -1288,6 +1288,12 @@ body.preset-ui-run .edit-mode-only { justify-content: stretch; } +#pattern-editor-modal .n-param-group:has(.pattern-n-readable-input) label { + flex: 0 0 auto; + min-width: 2.25rem; + font-weight: 500; +} + #pattern-editor-modal .pattern-n-readable-input { flex: 1 1 auto; width: 100%; diff --git a/src/templates/index.html b/src/templates/index.html index 468a207..c34cca1 100644 --- a/src/templates/index.html +++ b/src/templates/index.html @@ -259,14 +259,6 @@ -
- - - - - - -

Readable parameter names

@@ -305,6 +297,14 @@
+
+ + + + + + +