From 9914980a43f5af747c0fa629e164568a5347e4b2 Mon Sep 17 00:00:00 2001 From: Fernando Maclen Date: Fri, 29 Nov 2024 12:36:16 -0500 Subject: [PATCH] fix: UX improvements to `FieldSelectModel` and minor bug fixes (#247) - Fixes #238 - Fixes #244 - Fixes #242 - Refactor components to Svelte 5 - Hides "**Recently used models**" group when there are no recently used models. --- src/lib/components/ButtonNew.svelte | 4 +-- src/lib/components/ButtonNew.ts | 4 +-- src/lib/components/FieldSelectModel.svelte | 31 +++++++++++++-------- src/lib/connections.ts | 4 ++- src/lib/utils.ts | 2 +- src/routes/sessions/[id]/Prompt.svelte | 15 +++++----- tests/attachments.test.ts | 9 +++--- tests/docs.test.ts | 4 +-- tests/docs.test.ts-snapshots/motd.png | Bin 158354 -> 163791 bytes tests/openai.test.ts | 2 +- tests/servers.test.ts | 26 +++++++++++++++++ tests/session-interaction.test.ts | 21 ++++++++------ tests/ui.test.ts | 6 +--- tests/utils.ts | 4 +-- 14 files changed, 81 insertions(+), 51 deletions(-) diff --git a/src/lib/components/ButtonNew.svelte b/src/lib/components/ButtonNew.svelte index 481ac45b..43fe1d8f 100644 --- a/src/lib/components/ButtonNew.svelte +++ b/src/lib/components/ButtonNew.svelte @@ -3,7 +3,7 @@ import LL from '$i18n/i18n-svelte'; import { Sitemap } from '$lib/sitemap'; - import { generateStorageId } from '$lib/utils'; + import { generateRandomId } from '$lib/utils'; import Button from './Button.svelte'; import { generateNewUrl } from './ButtonNew'; @@ -13,7 +13,7 @@ let href: string; function setId() { - newId = generateStorageId(); + newId = generateRandomId(); href = generateNewUrl(sitemap, newId); } diff --git a/src/lib/components/ButtonNew.ts b/src/lib/components/ButtonNew.ts index b45a311b..bdbcdd3c 100644 --- a/src/lib/components/ButtonNew.ts +++ b/src/lib/components/ButtonNew.ts @@ -1,6 +1,6 @@ import { type Sitemap } from '$lib/sitemap'; -import { generateStorageId } from '$lib/utils'; +import { generateRandomId } from '$lib/utils'; export function generateNewUrl(sitemap: Sitemap, id?: string): string { - return `/${sitemap}/${id ? id : generateStorageId()}`; + return `/${sitemap}/${id ? id : generateRandomId()}`; } diff --git a/src/lib/components/FieldSelectModel.svelte b/src/lib/components/FieldSelectModel.svelte index 347ff48b..46283996 100644 --- a/src/lib/components/FieldSelectModel.svelte +++ b/src/lib/components/FieldSelectModel.svelte @@ -5,8 +5,19 @@ import FieldSelect from './FieldSelect.svelte'; - export let isLabelVisible: boolean | undefined = true; - export let value: string | undefined; + interface Props { + isLabelVisible?: boolean; + value?: string; + } + + let { isLabelVisible = true, value = $bindable() }: Props = $props(); + + const disabled = $derived(!$settingsStore.models?.length); + const models = $derived($settingsStore.models?.map(formatModelToSelectOption)); + const lastUsedModels = $derived($settingsStore.lastUsedModels?.map(formatModelToSelectOption)); + const otherModels = $derived( + models?.filter((m) => !lastUsedModels?.some((lm) => lm.value === m.value)) || [] + ); type ModelOption = { value: string; @@ -14,11 +25,6 @@ badge?: string | string[]; }; - let disabled: boolean; - let models: ModelOption[] = []; - let lastUsedModels: ModelOption[] = []; - let otherModels: ModelOption[] = []; - function formatModelToSelectOption(model: Model): ModelOption { const badges: string[] = []; const modelServer = $serversStore.find((s) => s.id === model.serverId); @@ -27,10 +33,10 @@ return { value: model.name, label: model.name, badge: badges }; } - $: disabled = !$settingsStore.models?.length; - $: models = $settingsStore.models?.map(formatModelToSelectOption); - $: lastUsedModels = $settingsStore.lastUsedModels?.map(formatModelToSelectOption); - $: otherModels = models?.filter((m) => !lastUsedModels?.some((lm) => lm.value === m.value)) || []; + // Auto-select model when there is only one available + $effect(() => { + if (!value && otherModels?.length === 1) value = otherModels[0].value; + }); + ${a.knowledge.name} + ${a.knowledge.content} + ` }); }); @@ -213,7 +212,7 @@ ${a.knowledge.content}