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:
2026-03-02 01:09:27 +03:00
parent f08117eb7b
commit fddbd771f2
28 changed files with 78 additions and 211 deletions

View File

@@ -113,6 +113,9 @@ function createAutomationCard(automation, sceneMap = new Map()) {
if (c.condition_type === 'always') {
return `<span class="stream-card-prop">${ICON_OK} ${t('automations.condition.always')}</span>`;
}
if (c.condition_type === 'startup') {
return `<span class="stream-card-prop">${ICON_START} ${t('automations.condition.startup')}</span>`;
}
if (c.condition_type === 'application') {
const apps = (c.apps || []).join(', ');
const matchLabel = t('automations.condition.application.match_type.' + (c.match_type || 'running'));
@@ -384,6 +387,7 @@ function addAutomationConditionRow(condition) {
<div class="condition-header">
<select class="condition-type-select">
<option value="always" ${condType === 'always' ? 'selected' : ''}>${t('automations.condition.always')}</option>
<option value="startup" ${condType === 'startup' ? 'selected' : ''}>${t('automations.condition.startup')}</option>
<option value="application" ${condType === 'application' ? 'selected' : ''}>${t('automations.condition.application')}</option>
<option value="time_of_day" ${condType === 'time_of_day' ? 'selected' : ''}>${t('automations.condition.time_of_day')}</option>
<option value="system_idle" ${condType === 'system_idle' ? 'selected' : ''}>${t('automations.condition.system_idle')}</option>
@@ -404,6 +408,10 @@ function addAutomationConditionRow(condition) {
container.innerHTML = `<small class="condition-always-desc">${t('automations.condition.always.hint')}</small>`;
return;
}
if (type === 'startup') {
container.innerHTML = `<small class="condition-always-desc">${t('automations.condition.startup.hint')}</small>`;
return;
}
if (type === 'time_of_day') {
const startTime = data.start_time || '00:00';
const endTime = data.end_time || '23:59';
@@ -612,6 +620,8 @@ function getAutomationEditorConditions() {
const condType = typeSelect ? typeSelect.value : 'application';
if (condType === 'always') {
conditions.push({ condition_type: 'always' });
} else if (condType === 'startup') {
conditions.push({ condition_type: 'startup' });
} else if (condType === 'time_of_day') {
conditions.push({
condition_type: 'time_of_day',