fix(redesign): EntitySelect for language pickers + portal Timezone picker
- Template editors (notification & command) now use EntitySelect for locale switching and default to the configured primary locale instead of always 'en' when opening, editing, or cloning a config. - LocaleSelector's add-flow uses EntitySelect for catalog pick; custom BCP-47 codes (e.g. de-CH) keep a small dedicated input. - TimezoneSelector dropdown was being clipped by Card's overflow:hidden and backdrop-filter; portalled to <body> with an overlay backdrop and styled as a centered modal palette (same pattern as EntitySelect). - Removed top padding on the timezone scroll list so sticky region group headers no longer leak rows above them. - Extracted shared locale catalog to lib/locales.ts.
This commit is contained in:
@@ -20,6 +20,8 @@
|
||||
import Modal from '$lib/components/Modal.svelte';
|
||||
import JinjaEditor from '$lib/components/JinjaEditor.svelte';
|
||||
import CollapsibleSlot from '$lib/components/CollapsibleSlot.svelte';
|
||||
import EntitySelect, { type EntityItem } from '$lib/components/EntitySelect.svelte';
|
||||
import { getLocaleMeta } from '$lib/locales';
|
||||
import { snackSuccess, snackError } from '$lib/stores/snackbar.svelte';
|
||||
import { highlightFromUrl } from '$lib/highlight';
|
||||
import { globalProviderFilter } from '$lib/stores/provider-filter.svelte';
|
||||
@@ -41,6 +43,7 @@
|
||||
}
|
||||
|
||||
let LOCALES = $derived(supportedLocalesCache.items);
|
||||
let primaryLocale = $derived(LOCALES[0] || 'en');
|
||||
|
||||
let allCmdTplConfigs = $state<CmdTemplateConfig[]>([]);
|
||||
let filterText = $state('');
|
||||
@@ -73,7 +76,18 @@
|
||||
});
|
||||
let varsRef = $state<Record<string, any>>({});
|
||||
let showVarsFor = $state<string | null>(null);
|
||||
let activeLocale = $state<string>('en');
|
||||
let activeLocale = $state<string>('');
|
||||
const localeItems = $derived<EntityItem[]>(LOCALES.map((code, i) => {
|
||||
const m = getLocaleMeta(code);
|
||||
return {
|
||||
value: code,
|
||||
label: m.native,
|
||||
desc: i === 0 ? `${code.toUpperCase()} · ${t('locales.primary')}` : code.toUpperCase(),
|
||||
};
|
||||
}));
|
||||
$effect(() => {
|
||||
if (!activeLocale && LOCALES.length > 0) activeLocale = primaryLocale;
|
||||
});
|
||||
let expandedSlots = $state<Set<string>>(new Set());
|
||||
let slotFilter = $state('');
|
||||
let showPreviewFor = $state<Set<string>>(new Set());
|
||||
@@ -215,7 +229,7 @@
|
||||
if (typesWithCmdSlots.length > 0) form.provider_type = typesWithCmdSlots[0];
|
||||
editing = null;
|
||||
showForm = true;
|
||||
activeLocale = 'en';
|
||||
activeLocale = primaryLocale;
|
||||
slotPreview = {};
|
||||
slotErrors = {};
|
||||
expandedSlots = new Set();
|
||||
@@ -238,7 +252,7 @@
|
||||
};
|
||||
editing = c.id;
|
||||
showForm = true;
|
||||
activeLocale = 'en';
|
||||
activeLocale = primaryLocale;
|
||||
slotPreview = {};
|
||||
slotErrors = {};
|
||||
expandedSlots = new Set();
|
||||
@@ -332,7 +346,7 @@
|
||||
};
|
||||
editing = null;
|
||||
showForm = true;
|
||||
activeLocale = 'en';
|
||||
activeLocale = primaryLocale;
|
||||
slotPreview = {};
|
||||
slotErrors = {};
|
||||
expandedSlots = new Set();
|
||||
@@ -414,15 +428,19 @@
|
||||
<legend class="text-sm font-medium px-1">{t('cmdTemplateConfig.commandResponses')}</legend>
|
||||
<p class="text-xs text-[var(--color-muted-foreground)] mb-2">{t('cmdTemplateConfig.commandResponsesHint')}</p>
|
||||
|
||||
<!-- Locale tabs -->
|
||||
<div class="flex items-center gap-1 mb-3 border-b border-[var(--color-border)]">
|
||||
{#each LOCALES as loc}
|
||||
<button type="button"
|
||||
class="px-3 py-1.5 text-xs font-medium rounded-t-md transition-colors {activeLocale === loc ? 'bg-[var(--color-primary)] text-[var(--color-primary-foreground)]' : 'text-[var(--color-muted-foreground)] hover:bg-[var(--color-muted)]'}"
|
||||
onclick={() => { activeLocale = loc; refreshAllPreviews(); }}>
|
||||
{loc.toUpperCase()}
|
||||
</button>
|
||||
{/each}
|
||||
<!-- Language picker -->
|
||||
<div class="flex items-center gap-2 mb-3">
|
||||
<span class="text-xs font-medium text-[var(--color-muted-foreground)] shrink-0">
|
||||
{t('templateConfig.language')}
|
||||
</span>
|
||||
<div class="flex-1 max-w-xs">
|
||||
<EntitySelect
|
||||
items={localeItems}
|
||||
value={activeLocale}
|
||||
size="sm"
|
||||
onselect={(v) => { activeLocale = (v as string) || primaryLocale; refreshAllPreviews(); }}
|
||||
/>
|
||||
</div>
|
||||
{#if form.provider_type}
|
||||
<button type="button" onclick={resetAllToDefaults}
|
||||
title={t('templateConfig.resetAllToDefaults')}
|
||||
|
||||
Reference in New Issue
Block a user