Move preview button to per-slot in edit form, remove card dropdown
Some checks failed
Validate / Hassfest (push) Has been cancelled
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:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user