style(ui): presets patterns and layout tweaks
Made-with: Cursor
This commit is contained in:
@@ -237,6 +237,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
const norm = raw.endsWith('.py') ? raw.slice(0, -3).trim() : raw;
|
const norm = raw.endsWith('.py') ? raw.slice(0, -3).trim() : raw;
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/patterns/definitions', {
|
const response = await fetch('/patterns/definitions', {
|
||||||
|
cache: 'no-store',
|
||||||
headers: { Accept: 'application/json' },
|
headers: { Accept: 'application/json' },
|
||||||
});
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@@ -376,6 +377,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/patterns', {
|
const response = await fetch('/patterns', {
|
||||||
|
cache: 'no-store',
|
||||||
headers: { Accept: 'application/json' },
|
headers: { Accept: 'application/json' },
|
||||||
});
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
|
|||||||
@@ -720,6 +720,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
// Load pattern definitions from pattern.json
|
// Load pattern definitions from pattern.json
|
||||||
let patternsPayload = null;
|
let patternsPayload = null;
|
||||||
let response = await fetch('/patterns/definitions', {
|
let response = await fetch('/patterns/definitions', {
|
||||||
|
cache: 'no-store',
|
||||||
headers: { Accept: 'application/json' },
|
headers: { Accept: 'application/json' },
|
||||||
});
|
});
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
@@ -730,6 +731,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
if (!Object.keys(normalized).length) {
|
if (!Object.keys(normalized).length) {
|
||||||
// Fallback when definitions route is unavailable or returns an empty map.
|
// Fallback when definitions route is unavailable or returns an empty map.
|
||||||
response = await fetch('/patterns', {
|
response = await fetch('/patterns', {
|
||||||
|
cache: 'no-store',
|
||||||
headers: { Accept: 'application/json' },
|
headers: { Accept: 'application/json' },
|
||||||
});
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@@ -1341,26 +1343,27 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
throw new Error('Failed to save preset');
|
throw new Error('Failed to save preset');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Same device targeting as Try: zone tab supplies names → /presets/push gets targets + select.
|
||||||
|
const section = document.querySelector('.presets-section[data-zone-id]');
|
||||||
|
const deviceNames = tabDeviceNamesFromSection(section);
|
||||||
|
|
||||||
// Use saved preset from server response for sending
|
// Use saved preset from server response for sending
|
||||||
const saved = await response.json().catch(() => null);
|
const saved = await response.json().catch(() => null);
|
||||||
if (saved && typeof saved === 'object') {
|
if (saved && typeof saved === 'object') {
|
||||||
if (currentEditId) {
|
if (currentEditId) {
|
||||||
// PUT returns the preset object directly; use the existing ID
|
// PUT returns the preset object directly; use the existing ID
|
||||||
// Save & Send should not force-select the preset on devices.
|
await sendPresetViaEspNow(currentEditId, saved, deviceNames, true, false);
|
||||||
await sendPresetViaEspNow(currentEditId, saved, [], true, false);
|
|
||||||
} else {
|
} else {
|
||||||
// POST returns { id: preset }
|
// POST returns { id: preset }
|
||||||
const entries = Object.entries(saved);
|
const entries = Object.entries(saved);
|
||||||
if (entries.length > 0) {
|
if (entries.length > 0) {
|
||||||
const [newId, presetData] = entries[0];
|
const [newId, presetData] = entries[0];
|
||||||
// Save & Send should not force-select the preset on devices.
|
await sendPresetViaEspNow(newId, presetData, deviceNames, true, false);
|
||||||
await sendPresetViaEspNow(newId, presetData, [], true, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Fallback: send what we just built
|
// Fallback: send what we just built
|
||||||
// Save & Send should not force-select the preset on devices.
|
await sendPresetViaEspNow(currentEditId || payload.name, payload, deviceNames, true, false);
|
||||||
await sendPresetViaEspNow(payload.name, payload, [], true, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await loadPresets();
|
await loadPresets();
|
||||||
|
|||||||
@@ -1253,24 +1253,32 @@ body.preset-ui-run .edit-mode-only {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Preset editor: brightness/delay field wrappers */
|
/* Preset editor: brightness/delay field wrappers */
|
||||||
.preset-editor-field {
|
#preset-editor-modal .preset-editor-field {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
min-width: 10rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-end;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preset-editor-field label {
|
#preset-editor-modal .preset-editor-field label {
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preset-editor-field input[type="number"] {
|
#preset-editor-modal .preset-editor-field input[type="number"] {
|
||||||
width: var(--n-input-width, 5ch);
|
width: 100%;
|
||||||
max-width: 100%;
|
min-width: 5.5rem;
|
||||||
|
max-width: 7rem;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Preset editor n-parameter inputs need extra room for values + spinner controls. */
|
||||||
|
#preset-editor-modal .n-input {
|
||||||
|
width: 6.5ch;
|
||||||
|
min-width: 5.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
/* Pattern editor: numeric metadata row */
|
/* Pattern editor: numeric metadata row */
|
||||||
#pattern-editor-modal input[type="number"] {
|
#pattern-editor-modal input[type="number"] {
|
||||||
width: var(--n-input-width, 5ch);
|
width: var(--n-input-width, 5ch);
|
||||||
|
|||||||
Reference in New Issue
Block a user