diff --git a/src/lib/components/workspace/Models/SkillsSelector.svelte b/src/lib/components/workspace/Models/SkillsSelector.svelte index 01c38fd074..8eba2f018e 100644 --- a/src/lib/components/workspace/Models/SkillsSelector.svelte +++ b/src/lib/components/workspace/Models/SkillsSelector.svelte @@ -8,6 +8,7 @@ id: string; name?: string; description?: string; + is_active?: boolean; }; export let skills: Skill[] = []; @@ -15,11 +16,13 @@ const i18n = getContext('i18n') as any; - $: selectedSkills = skills.filter((skill) => selectedSkillIds.includes(skill.id)); - $: availableSkills = skills.filter((skill) => !selectedSkillIds.includes(skill.id)); + $: activeSkills = skills.filter((skill) => skill.is_active !== false); + $: selectedSkills = activeSkills.filter((skill) => selectedSkillIds.includes(skill.id)); - const selectSkill = (skill: Skill) => { - selectedSkillIds = [...selectedSkillIds, skill.id]; + const toggleSkill = (skill: Skill) => { + selectedSkillIds = selectedSkillIds.includes(skill.id) + ? selectedSkillIds.filter((id) => id !== skill.id) + : [...selectedSkillIds, skill.id]; }; @@ -29,14 +32,20 @@
- {#if skills.length > 0} + {#if activeSkills.length > 0} { - selectSkill(e.detail); + toggleSkill(e.detail); + }} + on:enableall={(e) => { + selectedSkillIds = [ + ...new Set([...selectedSkillIds, ...e.detail.map((skill) => skill.id)]) + ]; }} /> @@ -61,6 +70,18 @@
{/each} + + {#if selectedSkills.length > 0} + + {/if} {/if} diff --git a/src/lib/components/workspace/Models/TTSVoiceInput.svelte b/src/lib/components/workspace/Models/TTSVoiceInput.svelte index ee2d91622c..b094523275 100644 --- a/src/lib/components/workspace/Models/TTSVoiceInput.svelte +++ b/src/lib/components/workspace/Models/TTSVoiceInput.svelte @@ -15,8 +15,12 @@ export let voices: Voice[] = []; export let placeholder = ''; export let className = 'w-full'; + export let selectedIds: string[] | null = null; - const dispatch = createEventDispatcher<{ select: Voice }>(); + const dispatch = createEventDispatcher<{ + select: Voice; + enableall: Voice[]; + }>(); const listboxId = `${id}-options`; let inputElement: HTMLInputElement | null = null; @@ -24,18 +28,17 @@ let suggestionsOpen = false; $: query = value.trim().toLowerCase(); - $: filteredVoices = (voices ?? []) - .filter((voice) => { - const id = voice.id.toLowerCase(); - const name = (voice.name ?? '').toLowerCase(); - const description = (voice.description ?? voice.meta?.description ?? '').toLowerCase(); + $: matchedVoices = (voices ?? []).filter((voice) => { + const id = voice.id.toLowerCase(); + const name = (voice.name ?? '').toLowerCase(); + const description = (voice.description ?? voice.meta?.description ?? '').toLowerCase(); - return ( - query === '' || id.includes(query) || name.includes(query) || description.includes(query) - ); - }) - .slice(0, 8); - $: if (suggestionsOpen && filteredVoices.length > 0) { + return ( + query === '' || id.includes(query) || name.includes(query) || description.includes(query) + ); + }); + $: optionVoices = selectedIds === null ? matchedVoices.slice(0, 8) : matchedVoices; + $: if (suggestionsOpen && optionVoices.length > 0) { tick().then(positionPopup); } @@ -60,11 +63,18 @@ }; const selectVoice = (voice: Voice) => { - value = voice.id; + if (selectedIds === null) { + value = voice.id; + } suggestionsOpen = false; dispatch('select', voice); }; + const enableVoices = () => { + suggestionsOpen = false; + dispatch('enableall', matchedVoices); + }; + const handlePointerDown = (event: PointerEvent) => { if (!suggestionsOpen) return; @@ -93,7 +103,7 @@ role="combobox" aria-autocomplete="list" aria-controls={listboxId} - aria-expanded={suggestionsOpen && filteredVoices.length > 0} + aria-expanded={suggestionsOpen && optionVoices.length > 0} autocomplete="off" on:focus={() => { suggestionsOpen = true; @@ -117,7 +127,7 @@ }} /> -{#if suggestionsOpen && filteredVoices.length > 0} +{#if suggestionsOpen && optionVoices.length > 0}
- {#each filteredVoices as voice (voice.id)} + {#if selectedIds !== null} + {#if matchedVoices.length > 0} + + {/if} + {/if} + {#each optionVoices as voice (voice.id)}
{/each} + + {#if selectedTools.length > 0} + + {/if} {/if}
- {$i18n.t('To select toolkits here, add them to the "Tools" workspace first.')} + {$i18n.t( + 'To select toolkits here, add them to the "Tools" workspace or enable a tool server first.' + )}
diff --git a/src/lib/components/workspace/Models/TypeaheadSelector.svelte b/src/lib/components/workspace/Models/TypeaheadSelector.svelte index 047069b7bb..db5c45593d 100644 --- a/src/lib/components/workspace/Models/TypeaheadSelector.svelte +++ b/src/lib/components/workspace/Models/TypeaheadSelector.svelte @@ -15,8 +15,12 @@ export let placeholder = ''; export let id = 'typeahead-selector'; export let className = 'w-full'; + export let selectedIds: string[] | null = null; - const dispatch = createEventDispatcher<{ select: Item }>(); + const dispatch = createEventDispatcher<{ + select: Item; + enableall: Item[]; + }>(); let value = ''; @@ -26,10 +30,12 @@ voices={items} {placeholder} {className} + {selectedIds} bind:value on:select={(e) => { dispatch('select', e.detail); - value = ''; + if (selectedIds === null) value = ''; }} + on:enableall={(e) => dispatch('enableall', e.detail)} />