Move preview button to per-slot in edit form, remove card dropdown
Some checks failed
Validate / Hassfest (push) Has been cancelled

Each template slot now has its own Preview button next to the label.
Clicking it renders the current editor content via preview-raw API
and shows the result inline below the editor. Removed the old
per-card preview dropdown since preview is now part of editing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-19 19:20:48 +03:00
parent 6076e6d8ca
commit 68b104ed40

View File

@@ -21,9 +21,7 @@
let editing = $state<number | null>(null);
let error = $state('');
let confirmDelete = $state<any>(null);
let previewSlot = $state('message_assets_added');
let previewResult = $state('');
let previewId = $state<number | null>(null);
let slotPreview = $state<Record<string, string>>({});
const defaultForm = () => ({
name: '', icon: '',
@@ -80,12 +78,13 @@
} catch (err: any) { error = err.message; }
}
async function preview(id: number, slot: string) {
previewId = id; previewSlot = slot;
async function previewSlot(slotKey: string) {
const template = (form as any)[slotKey] || '';
if (!template) { slotPreview[slotKey] = '(empty)'; return; }
try {
const res = await api(`/template-configs/${id}/preview?slot=${slot}`, { method: 'POST' });
previewResult = res.rendered;
} catch (err: any) { previewResult = `Error: ${err.message}`; }
const res = await api('/template-configs/preview-raw', { method: 'POST', body: JSON.stringify({ template }) });
slotPreview[slotKey] = res.error ? `Error: ${res.error}` : res.rendered;
} catch (err: any) { slotPreview[slotKey] = `Error: ${err.message}`; }
}
function remove(id: number) {
@@ -131,13 +130,24 @@
<div>
<div class="flex items-center justify-between mb-1">
<label class="text-xs text-[var(--color-muted-foreground)]">{t(`templateConfig.${slot.label}`)}</label>
{#if varsRef[slot.key]}
<button type="button" onclick={() => showVarsFor = slot.key}
class="text-xs text-[var(--color-muted-foreground)] hover:underline">{'{{ }}'} Variables</button>
{/if}
<div class="flex items-center gap-2">
{#if (slot.rows || 2) > 2}
<button type="button" onclick={() => previewSlot(slot.key)}
class="text-xs text-[var(--color-muted-foreground)] hover:underline">{t('templateConfig.preview')}</button>
{/if}
{#if varsRef[slot.key]}
<button type="button" onclick={() => showVarsFor = slot.key}
class="text-xs text-[var(--color-muted-foreground)] hover:underline">{'{{ }}'}</button>
{/if}
</div>
</div>
{#if (slot.rows || 2) > 2}
<JinjaEditor value={(form as any)[slot.key] || ''} onchange={(v) => (form as any)[slot.key] = v} rows={slot.rows || 6} />
{#if slotPreview[slot.key]}
<div class="mt-1 p-2 bg-[var(--color-muted)] rounded text-sm">
<pre class="whitespace-pre-wrap">{slotPreview[slot.key]}</pre>
</div>
{/if}
{:else}
<input bind:value={(form as any)[slot.key]}
class="w-full px-2 py-1 border border-[var(--color-border)] rounded text-sm bg-[var(--color-background)] font-mono" />
@@ -168,32 +178,11 @@
{#if config.icon}<MdiIcon name={config.icon} />{/if}
<p class="font-medium">{config.name}</p>
</div>
<pre class="text-xs text-[var(--color-muted-foreground)] mt-1 whitespace-pre-wrap font-mono bg-[var(--color-muted)] rounded p-2">{config.message_assets_added?.slice(0, 120)}...</pre>
{#if previewResult && previewId === config.id}
<div class="mt-2 p-2 bg-[var(--color-success-bg)] rounded text-sm">
<p class="text-xs font-medium mb-1">{previewSlot}:</p>
<pre class="whitespace-pre-wrap">{previewResult}</pre>
</div>
{/if}
<pre class="text-xs text-[var(--color-muted-foreground)] mt-1 whitespace-pre-wrap font-mono bg-[var(--color-muted)] rounded p-2">{config.message_assets_added?.slice(0, 150)}...</pre>
</div>
<div class="flex flex-col items-end gap-2 ml-4">
<div class="flex items-center gap-3">
<button onclick={() => edit(config)} class="text-xs text-[var(--color-muted-foreground)] hover:underline">{t('common.edit')}</button>
<button onclick={() => remove(config.id)} class="text-xs text-[var(--color-destructive)] hover:underline">{t('common.delete')}</button>
</div>
<div class="flex items-center gap-1">
<select onchange={(e) => preview(config.id, e.currentTarget.value)}
class="text-xs px-1 py-0.5 border border-[var(--color-border)] rounded bg-[var(--color-background)]">
<option value="" disabled selected>{t('templateConfig.preview')}...</option>
<option value="message_assets_added">{t('templateConfig.assetsAdded')}</option>
<option value="message_assets_removed">{t('templateConfig.assetsRemoved')}</option>
<option value="message_album_renamed">{t('templateConfig.albumRenamed')}</option>
<option value="message_album_deleted">{t('templateConfig.albumDeleted')}</option>
<option value="periodic_summary_message">{t('templateConfig.periodicSummary')}</option>
<option value="scheduled_assets_message">{t('templateConfig.scheduledAssets')}</option>
<option value="memory_mode_message">{t('templateConfig.memoryMode')}</option>
</select>
</div>
<div class="flex items-center gap-3 ml-4">
<button onclick={() => edit(config)} class="text-xs text-[var(--color-muted-foreground)] hover:underline">{t('common.edit')}</button>
<button onclick={() => remove(config.id)} class="text-xs text-[var(--color-destructive)] hover:underline">{t('common.delete')}</button>
</div>
</div>
</Card>