Add clone support for scene presets and update TODO

- Add clone_preset() to ScenePresetStore with deep copy of target snapshots
- Add POST /scene-presets/{id}/clone API endpoint
- Add clone button to scene preset cards in Automations tab
- Add i18n keys for clone feedback in all 3 locales
- Add TODO items for dashboard stats collapse and protocol badge review

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 20:17:09 +03:00
parent fddbd771f2
commit 80b48e3618
8 changed files with 74 additions and 3 deletions

View File

@@ -9,7 +9,7 @@ import { showToast, showConfirm } from '../core/ui.js';
import { Modal } from '../core/modal.js';
import { CardSection } from '../core/card-sections.js';
import {
ICON_SCENE, ICON_CAPTURE, ICON_START, ICON_EDIT, ICON_REFRESH, ICON_TARGET,
ICON_SCENE, ICON_CAPTURE, ICON_START, ICON_EDIT, ICON_REFRESH, ICON_TARGET, ICON_CLONE,
} from '../core/icons.js';
import { scenePresetsCache } from '../core/state.js';
import { cardColorStyle, cardColorButton } from '../core/card-colors.js';
@@ -61,6 +61,7 @@ export function createSceneCard(preset) {
${updated ? `<span class="stream-card-prop">${updated}</span>` : ''}
</div>
<div class="card-actions">
<button class="btn btn-icon btn-secondary" onclick="cloneScenePreset('${preset.id}')" title="${t('common.clone')}">${ICON_CLONE}</button>
<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>
@@ -304,6 +305,26 @@ export async function recaptureScenePreset(presetId) {
}
}
// ===== Clone =====
export async function cloneScenePreset(presetId) {
try {
const resp = await fetchWithAuth(`/scene-presets/${presetId}/clone`, {
method: 'POST',
});
if (resp.ok) {
showToast(t('scenes.cloned'), 'success');
_reloadScenesTab();
} else {
const err = await resp.json().catch(() => ({}));
showToast(err.detail || t('scenes.error.clone_failed'), 'error');
}
} catch (error) {
if (error.isAuth) return;
showToast(t('scenes.error.clone_failed'), 'error');
}
}
// ===== Delete =====
export async function deleteScenePreset(presetId) {