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 validateTimers: Record<string, ReturnType<typeof setTimeout>> = {};
|
||||
|
||||
function validateSlot(slotKey: string, template: string) {
|
||||
function validateSlot(slotKey: string, template: string, immediate = false) {
|
||||
// Clear previous timer
|
||||
if (validateTimers[slotKey]) clearTimeout(validateTimers[slotKey]);
|
||||
if (!template) {
|
||||
@@ -40,8 +40,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// Debounce 800ms
|
||||
validateTimers[slotKey] = setTimeout(async () => {
|
||||
const doValidate = async () => {
|
||||
try {
|
||||
const res = await api('/template-configs/preview-raw', { method: 'POST', body: JSON.stringify({ template, target_type: previewTargetType }) });
|
||||
slotErrors = { ...slotErrors, [slotKey]: res.error || '' };
|
||||
@@ -60,7 +59,21 @@
|
||||
slotErrorLines = { ...slotErrorLines, [slotKey]: null };
|
||||
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 = () => ({
|
||||
@@ -181,17 +194,12 @@
|
||||
|
||||
<!-- Target type selector for preview -->
|
||||
<div class="flex items-center gap-2">
|
||||
<label class="text-sm font-medium">{t('templateConfig.previewAs')}:</label>
|
||||
<div class="flex gap-1">
|
||||
<button type="button" onclick={() => previewTargetType = 'telegram'}
|
||||
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)]'}">
|
||||
Telegram
|
||||
</button>
|
||||
<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>
|
||||
<label for="preview-target" class="text-sm font-medium">{t('templateConfig.previewAs')}:</label>
|
||||
<select id="preview-target" bind:value={previewTargetType} onchange={refreshAllPreviews}
|
||||
class="px-2 py-1 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]">
|
||||
<option value="telegram">Telegram</option>
|
||||
<option value="webhook">Webhook</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{#each templateSlots as group}
|
||||
|
||||
Reference in New Issue
Block a user