Use combobox for target type selector, refresh previews on change
All checks were successful
Validate / Hassfest (push) Successful in 3s
All checks were successful
Validate / Hassfest (push) Successful in 3s
- Replace toggle buttons with <select> dropdown for target type - Add refreshAllPreviews() that immediately re-renders all open previews when target type changes (no 800ms debounce) - validateSlot() now accepts optional immediate flag Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -28,7 +28,7 @@
|
|||||||
let slotErrorTypes = $state<Record<string, string>>({});
|
let slotErrorTypes = $state<Record<string, string>>({});
|
||||||
let validateTimers: Record<string, ReturnType<typeof setTimeout>> = {};
|
let validateTimers: Record<string, ReturnType<typeof setTimeout>> = {};
|
||||||
|
|
||||||
function validateSlot(slotKey: string, template: string) {
|
function validateSlot(slotKey: string, template: string, immediate = false) {
|
||||||
// Clear previous timer
|
// Clear previous timer
|
||||||
if (validateTimers[slotKey]) clearTimeout(validateTimers[slotKey]);
|
if (validateTimers[slotKey]) clearTimeout(validateTimers[slotKey]);
|
||||||
if (!template) {
|
if (!template) {
|
||||||
@@ -40,8 +40,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debounce 800ms
|
const doValidate = async () => {
|
||||||
validateTimers[slotKey] = setTimeout(async () => {
|
|
||||||
try {
|
try {
|
||||||
const res = await api('/template-configs/preview-raw', { method: 'POST', body: JSON.stringify({ template, target_type: previewTargetType }) });
|
const res = await api('/template-configs/preview-raw', { method: 'POST', body: JSON.stringify({ template, target_type: previewTargetType }) });
|
||||||
slotErrors = { ...slotErrors, [slotKey]: res.error || '' };
|
slotErrors = { ...slotErrors, [slotKey]: res.error || '' };
|
||||||
@@ -60,7 +59,21 @@
|
|||||||
slotErrorLines = { ...slotErrorLines, [slotKey]: null };
|
slotErrorLines = { ...slotErrorLines, [slotKey]: null };
|
||||||
slotErrorTypes = { ...slotErrorTypes, [slotKey]: '' };
|
slotErrorTypes = { ...slotErrorTypes, [slotKey]: '' };
|
||||||
}
|
}
|
||||||
}, 800);
|
};
|
||||||
|
if (immediate) { doValidate(); }
|
||||||
|
else { validateTimers[slotKey] = setTimeout(doValidate, 800); }
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshAllPreviews() {
|
||||||
|
// Re-validate and re-preview all slots that have content (immediate, no debounce)
|
||||||
|
for (const group of templateSlots) {
|
||||||
|
for (const slot of group.slots) {
|
||||||
|
const template = (form as any)[slot.key];
|
||||||
|
if (template && slot.key !== 'date_format') {
|
||||||
|
validateSlot(slot.key, template, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultForm = () => ({
|
const defaultForm = () => ({
|
||||||
@@ -181,17 +194,12 @@
|
|||||||
|
|
||||||
<!-- Target type selector for preview -->
|
<!-- Target type selector for preview -->
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<label class="text-sm font-medium">{t('templateConfig.previewAs')}:</label>
|
<label for="preview-target" class="text-sm font-medium">{t('templateConfig.previewAs')}:</label>
|
||||||
<div class="flex gap-1">
|
<select id="preview-target" bind:value={previewTargetType} onchange={refreshAllPreviews}
|
||||||
<button type="button" onclick={() => previewTargetType = 'telegram'}
|
class="px-2 py-1 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]">
|
||||||
class="px-3 py-1 text-xs rounded-md transition-colors {previewTargetType === 'telegram' ? 'bg-[var(--color-primary)] text-[var(--color-primary-foreground)]' : 'bg-[var(--color-muted)] text-[var(--color-muted-foreground)]'}">
|
<option value="telegram">Telegram</option>
|
||||||
Telegram
|
<option value="webhook">Webhook</option>
|
||||||
</button>
|
</select>
|
||||||
<button type="button" onclick={() => previewTargetType = 'webhook'}
|
|
||||||
class="px-3 py-1 text-xs rounded-md transition-colors {previewTargetType === 'webhook' ? 'bg-[var(--color-primary)] text-[var(--color-primary-foreground)]' : 'bg-[var(--color-muted)] text-[var(--color-muted-foreground)]'}">
|
|
||||||
Webhook
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#each templateSlots as group}
|
{#each templateSlots as group}
|
||||||
|
|||||||
Reference in New Issue
Block a user