From a3a1fe3d7520197d3b7a8bfa121340efcd99bd66 Mon Sep 17 00:00:00 2001 From: "alexei.dolgolyov" Date: Sun, 22 Mar 2026 00:21:57 +0300 Subject: [PATCH] feat: EntitySelect palette-style entity picker, replace select dropdowns New EntitySelect component: modal palette with search, keyboard nav, current-value indicator (left border), smooth overlay. Replaces native + ESC + + +
+ {#if filtered.length === 0} +
No matches
+ {:else} + {#each filtered as item, i} + + {/each} + {/if} +
+ +{/if} + + diff --git a/frontend/src/routes/command-configs/+page.svelte b/frontend/src/routes/command-configs/+page.svelte index 52a9b10..4a6e44e 100644 --- a/frontend/src/routes/command-configs/+page.svelte +++ b/frontend/src/routes/command-configs/+page.svelte @@ -12,6 +12,7 @@ import ConfirmModal from '$lib/components/ConfirmModal.svelte'; import IconButton from '$lib/components/IconButton.svelte'; import CrossLink from '$lib/components/CrossLink.svelte'; + import EntitySelect from '$lib/components/EntitySelect.svelte'; import { snackSuccess, snackError } from '$lib/stores/snackbar.svelte'; import { highlightFromUrl } from '$lib/highlight'; @@ -23,6 +24,10 @@ let configs = $derived(commandConfigsCache.items); let cmdTemplateConfigs = $derived(commandTemplateConfigsCache.items); + const templateItems = $derived(cmdTemplateConfigs + .filter((c: any) => c.provider_type === form.provider_type) + .map((c: any) => ({ value: c.id, label: c.name + (c.user_id === 0 ? ' (System)' : ''), icon: c.icon || 'mdiCodeBracesBox', desc: c.provider_type })) + ); let loaded = $state(false); let showForm = $state(false); let editing = $state(null); @@ -180,13 +185,8 @@
- - + +
diff --git a/frontend/src/routes/command-trackers/+page.svelte b/frontend/src/routes/command-trackers/+page.svelte index d7e34df..2d1f0c5 100644 --- a/frontend/src/routes/command-trackers/+page.svelte +++ b/frontend/src/routes/command-trackers/+page.svelte @@ -13,6 +13,7 @@ import ConfirmModal from '$lib/components/ConfirmModal.svelte'; import IconButton from '$lib/components/IconButton.svelte'; import CrossLink from '$lib/components/CrossLink.svelte'; + import EntitySelect from '$lib/components/EntitySelect.svelte'; import { snackSuccess, snackError } from '$lib/stores/snackbar.svelte'; import { highlightFromUrl } from '$lib/highlight'; import type { ServiceProvider, TelegramBot } from '$lib/types'; @@ -21,6 +22,9 @@ let providers = $derived(providersCache.items); let commandConfigs = $derived(commandConfigsCache.items); let telegramBots = $derived(telegramBotsCache.items); + const providerItems = $derived(providers.map(p => ({ value: p.id, label: p.name, icon: p.icon || 'mdiServer', desc: p.type }))); + const configItems = $derived(filteredConfigs().map((c: any) => ({ value: c.id, label: c.name, icon: c.icon || 'mdiCog', desc: c.provider_type }))); + const botItems = $derived(telegramBots.map(b => ({ value: b.id, label: b.name, icon: b.icon || 'mdiRobot', desc: b.bot_username ? `@${b.bot_username}` : '' }))); let loaded = $state(false); let showForm = $state(false); let editing = $state(null); @@ -191,25 +195,13 @@
- - + +
- - + +