feat: add auto-name generation to all remaining creation modals
Some checks failed
Lint & Test / test (push) Failing after 27s

Audio sources: type + device/parent/channel/band detail
Weather sources: provider + coordinates (updates on geolocation)
Sync clocks: "Sync Clocks · Nx" (updates on speed slider)
Automations: scene name + condition count/logic
Scene presets: "Scenes · N targets" (updates on add/remove)
Pattern templates: "Pattern Templates · N rects" (updates on add/remove)

All follow the same pattern: name auto-generates on create, stops
when user manually edits the name field.
This commit is contained in:
2026-03-24 21:44:28 +03:00
parent d6f796a499
commit 347b252f06
7 changed files with 163 additions and 6 deletions

View File

@@ -23,6 +23,27 @@ import type { Automation } from '../types.ts';
let _automationTagsInput: any = null;
// ── Auto-name ──
let _autoNameManuallyEdited = false;
function _autoGenerateAutomationName() {
if (_autoNameManuallyEdited) return;
if ((document.getElementById('automation-editor-id') as HTMLInputElement).value) return;
const sceneSel = document.getElementById('automation-scene-id') as HTMLSelectElement | null;
const sceneName = sceneSel?.selectedOptions[0]?.textContent?.trim() || '';
const logic = (document.getElementById('automation-editor-logic') as HTMLSelectElement).value;
const condCount = document.querySelectorAll('#automation-conditions-list .condition-row').length;
let name = '';
if (sceneName) name = sceneName;
if (condCount > 0) {
const logicLabel = logic === 'and' ? 'AND' : 'OR';
const suffix = `${condCount} ${logicLabel}`;
name = name ? `${name} · ${suffix}` : suffix;
}
(document.getElementById('automation-editor-name') as HTMLInputElement).value = name || t('automations.add');
}
class AutomationEditorModal extends Modal {
constructor() { super('automation-editor-modal'); }
@@ -395,6 +416,12 @@ export async function openAutomationEditor(automationId?: any, cloneData?: any)
// Wire up deactivation mode change
(document.getElementById('automation-deactivation-mode') as HTMLSelectElement).onchange = _onDeactivationModeChange;
// Auto-name wiring
_autoNameManuallyEdited = !!(automationId || cloneData);
nameInput.oninput = () => { _autoNameManuallyEdited = true; };
(window as any)._autoGenerateAutomationName = _autoGenerateAutomationName;
if (!automationId && !cloneData) _autoGenerateAutomationName();
automationModal.open();
modal!.querySelectorAll('[data-i18n]').forEach(el => {
el.textContent = t(el.getAttribute('data-i18n')!);
@@ -453,7 +480,12 @@ function _initSceneSelector(selectId: any, selectedId: any) {
allowNone: true,
noneLabel: t('automations.scene.none_selected'),
} as any);
if (isMain) _sceneEntitySelect = es; else _fallbackSceneEntitySelect = es;
if (isMain) {
_sceneEntitySelect = es;
sel.onchange = () => _autoGenerateAutomationName();
} else {
_fallbackSceneEntitySelect = es;
}
}
// ===== Deactivation mode IconSelect =====
@@ -480,6 +512,7 @@ function _ensureDeactivationModeIconSelect() {
export function addAutomationCondition() {
addAutomationConditionRow({ condition_type: 'application', apps: [], match_type: 'running' });
_autoGenerateAutomationName();
}
const CONDITION_TYPE_KEYS = ['always', 'startup', 'application', 'time_of_day', 'system_idle', 'display_state', 'mqtt', 'webhook'];
@@ -577,7 +610,7 @@ function addAutomationConditionRow(condition: any) {
<select class="condition-type-select">
${CONDITION_TYPE_KEYS.map(k => `<option value="${k}" ${condType === k ? 'selected' : ''}>${t('automations.condition.' + k)}</option>`).join('')}
</select>
<button type="button" class="btn-remove-condition" onclick="this.closest('.automation-condition-row').remove()" title="Remove">&#x2715;</button>
<button type="button" class="btn-remove-condition" onclick="this.closest('.automation-condition-row').remove(); if(window._autoGenerateAutomationName) window._autoGenerateAutomationName();" title="Remove">&#x2715;</button>
</div>
<div class="condition-fields-container"></div>
`;