Replace auto-start with startup automation, add card colors to dashboard
- Add `startup` automation condition type that activates on server boot, replacing the per-target `auto_start` flag - Remove `auto_start` field from targets, scene snapshots, and all API layers - Remove auto-start UI section and star buttons from dashboard and target cards - Remove `color` field from scene presets (backend, API, modal, frontend) - Add card color support to scene preset cards (color picker + border style) - Show localStorage-backed card colors on all dashboard cards (targets, automations, sync clocks, scene presets) - Fix card color picker updating wrong card when duplicate data attributes exist by using closest() from picker wrapper instead of global querySelector - Add sync clocks step to Sources tab tutorial - Bump SW cache v9 → v10 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ import {
|
||||
ICON_SCENE, ICON_CAPTURE, ICON_START, ICON_EDIT, ICON_REFRESH, ICON_TARGET,
|
||||
} from '../core/icons.js';
|
||||
import { scenePresetsCache } from '../core/state.js';
|
||||
import { cardColorStyle, cardColorButton } from '../core/card-colors.js';
|
||||
|
||||
let _editingId = null;
|
||||
let _allTargets = []; // fetched on capture open
|
||||
@@ -24,7 +25,6 @@ class ScenePresetEditorModal extends Modal {
|
||||
return {
|
||||
name: document.getElementById('scene-preset-editor-name').value,
|
||||
description: document.getElementById('scene-preset-editor-description').value,
|
||||
color: document.getElementById('scene-preset-editor-color').value,
|
||||
targets: items,
|
||||
};
|
||||
}
|
||||
@@ -40,7 +40,6 @@ export const csScenes = new CardSection('scenes', {
|
||||
|
||||
export function createSceneCard(preset) {
|
||||
const targetCount = (preset.targets || []).length;
|
||||
const colorStyle = `border-left: 3px solid ${escapeHtml(preset.color || '#4fc3f7')}`;
|
||||
|
||||
const meta = [
|
||||
targetCount > 0 ? `${ICON_TARGET} ${targetCount} ${t('scenes.targets_count')}` : null,
|
||||
@@ -48,7 +47,8 @@ export function createSceneCard(preset) {
|
||||
|
||||
const updated = preset.updated_at ? new Date(preset.updated_at).toLocaleString() : '';
|
||||
|
||||
return `<div class="card" data-scene-id="${preset.id}" style="${colorStyle}">
|
||||
const colorStyle = cardColorStyle(preset.id);
|
||||
return `<div class="card" data-scene-id="${preset.id}"${colorStyle ? ` style="${colorStyle}"` : ''}>
|
||||
<div class="card-top-actions">
|
||||
<button class="card-remove-btn" onclick="deleteScenePreset('${preset.id}', '${escapeHtml(preset.name)}')" title="${t('scenes.delete')}">✕</button>
|
||||
</div>
|
||||
@@ -64,6 +64,7 @@ export function createSceneCard(preset) {
|
||||
<button class="btn btn-icon btn-secondary" onclick="editScenePreset('${preset.id}')" title="${t('scenes.edit')}">${ICON_EDIT}</button>
|
||||
<button class="btn btn-icon btn-secondary" onclick="recaptureScenePreset('${preset.id}')" title="${t('scenes.recapture')}">${ICON_REFRESH}</button>
|
||||
<button class="btn btn-icon btn-success" onclick="activateScenePreset('${preset.id}')" title="${t('scenes.activate')}">${ICON_START}</button>
|
||||
${cardColorButton(preset.id, 'data-scene-id')}
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
@@ -84,14 +85,14 @@ export function renderScenePresetsSection(presets) {
|
||||
}
|
||||
|
||||
function _renderDashboardPresetCard(preset) {
|
||||
const borderStyle = `border-left: 3px solid ${escapeHtml(preset.color)}`;
|
||||
const targetCount = (preset.targets || []).length;
|
||||
|
||||
const subtitle = [
|
||||
targetCount > 0 ? `${targetCount} ${t('scenes.targets_count')}` : null,
|
||||
].filter(Boolean).join(' \u00b7 ');
|
||||
|
||||
return `<div class="dashboard-target dashboard-scene-preset dashboard-card-link" data-scene-id="${preset.id}" style="${borderStyle}" onclick="if(!event.target.closest('button')){navigateToCard('automations',null,'scenes','data-scene-id','${preset.id}')}">
|
||||
const pStyle = cardColorStyle(preset.id);
|
||||
return `<div class="dashboard-target dashboard-scene-preset dashboard-card-link" data-scene-id="${preset.id}" onclick="if(!event.target.closest('button')){navigateToCard('automations',null,'scenes','data-scene-id','${preset.id}')}"${pStyle ? ` style="${pStyle}"` : ''}>
|
||||
<div class="dashboard-target-info">
|
||||
<span class="dashboard-target-icon">${ICON_SCENE}</span>
|
||||
<div>
|
||||
@@ -113,7 +114,7 @@ export async function openScenePresetCapture() {
|
||||
document.getElementById('scene-preset-editor-id').value = '';
|
||||
document.getElementById('scene-preset-editor-name').value = '';
|
||||
document.getElementById('scene-preset-editor-description').value = '';
|
||||
document.getElementById('scene-preset-editor-color').value = '#4fc3f7';
|
||||
|
||||
document.getElementById('scene-preset-editor-error').style.display = 'none';
|
||||
|
||||
const titleEl = document.querySelector('#scene-preset-editor-title span[data-i18n]');
|
||||
@@ -149,7 +150,6 @@ export async function editScenePreset(presetId) {
|
||||
document.getElementById('scene-preset-editor-id').value = presetId;
|
||||
document.getElementById('scene-preset-editor-name').value = preset.name;
|
||||
document.getElementById('scene-preset-editor-description').value = preset.description || '';
|
||||
document.getElementById('scene-preset-editor-color').value = preset.color || '#4fc3f7';
|
||||
document.getElementById('scene-preset-editor-error').style.display = 'none';
|
||||
|
||||
// Hide target selector in edit mode (metadata only)
|
||||
@@ -168,7 +168,6 @@ export async function editScenePreset(presetId) {
|
||||
export async function saveScenePreset() {
|
||||
const name = document.getElementById('scene-preset-editor-name').value.trim();
|
||||
const description = document.getElementById('scene-preset-editor-description').value.trim();
|
||||
const color = document.getElementById('scene-preset-editor-color').value;
|
||||
const errorEl = document.getElementById('scene-preset-editor-error');
|
||||
|
||||
if (!name) {
|
||||
@@ -182,14 +181,14 @@ export async function saveScenePreset() {
|
||||
if (_editingId) {
|
||||
resp = await fetchWithAuth(`/scene-presets/${_editingId}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({ name, description, color }),
|
||||
body: JSON.stringify({ name, description }),
|
||||
});
|
||||
} else {
|
||||
const target_ids = [...document.querySelectorAll('#scene-target-list .scene-target-item')]
|
||||
.map(el => el.dataset.targetId);
|
||||
resp = await fetchWithAuth('/scene-presets', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ name, description, color, target_ids }),
|
||||
body: JSON.stringify({ name, description, target_ids }),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user