refac
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
import type { Writable } from 'svelte/store';
|
||||
import type { i18n as i18nType } from 'i18next';
|
||||
import Textarea from '$lib/components/common/Textarea.svelte';
|
||||
import SettingsSelect from '$lib/components/common/SettingsSelect.svelte';
|
||||
|
||||
const i18n = getContext<Writable<i18nType>>('i18n');
|
||||
|
||||
@@ -266,18 +267,14 @@
|
||||
{$i18n.t('Speech-to-Text Engine')}
|
||||
</div>
|
||||
<div class="flex items-center relative">
|
||||
<select
|
||||
class="cursor-pointer w-fit pr-8 rounded-lg px-2 p-1 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
|
||||
bind:value={STT_ENGINE}
|
||||
placeholder={$i18n.t('Select an engine')}
|
||||
>
|
||||
<SettingsSelect bind:value={STT_ENGINE} placeholder={$i18n.t('Select an engine')}>
|
||||
<option value="">{$i18n.t('Whisper (Local)')}</option>
|
||||
<option value="openai">{$i18n.t('OpenAI')}</option>
|
||||
<option value="web">{$i18n.t('Web API')}</option>
|
||||
<option value="deepgram">{$i18n.t('Deepgram')}</option>
|
||||
<option value="azure">{$i18n.t('Azure AI Speech')}</option>
|
||||
<option value="mistral">{$i18n.t('MistralAI')}</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -300,13 +297,10 @@
|
||||
{$i18n.t('Request Format')}
|
||||
</div>
|
||||
<div class="flex items-center relative">
|
||||
<select
|
||||
class="cursor-pointer w-fit pr-8 rounded-lg px-2 p-1 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
|
||||
bind:value={STT_OPENAI_API_REQUEST_FORMAT}
|
||||
>
|
||||
<SettingsSelect bind:value={STT_OPENAI_API_REQUEST_FORMAT}>
|
||||
<option value="multipart">{$i18n.t('Multipart Upload')}</option>
|
||||
<option value="json">{$i18n.t('JSON Base64')}</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -562,8 +556,7 @@
|
||||
{$i18n.t('Text-to-Speech Engine')}
|
||||
</div>
|
||||
<div class="flex items-center relative">
|
||||
<select
|
||||
class="w-fit pr-8 cursor-pointer rounded-lg px-2 p-1 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
|
||||
<SettingsSelect
|
||||
bind:value={TTS_ENGINE}
|
||||
placeholder={$i18n.t('Select a mode')}
|
||||
on:change={async (e) => {
|
||||
@@ -589,7 +582,7 @@
|
||||
<option value="elevenlabs">{$i18n.t('ElevenLabs')}</option>
|
||||
<option value="azure">{$i18n.t('Azure AI Speech')}</option>
|
||||
<option value="mistral">{$i18n.t('MistralAI')}</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -671,10 +664,7 @@
|
||||
</div>
|
||||
<div class="flex w-full">
|
||||
<div class="flex-1">
|
||||
<select
|
||||
class="w-full rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500"
|
||||
bind:value={TTS_VOICE}
|
||||
>
|
||||
<SettingsSelect bind:value={TTS_VOICE} className="w-full">
|
||||
<option value="" selected={TTS_VOICE !== ''}>{$i18n.t('Default')}</option>
|
||||
{#each voices as voice}
|
||||
<option
|
||||
@@ -683,7 +673,7 @@
|
||||
selected={TTS_VOICE === voice.voiceURI}>{voice.name}</option
|
||||
>
|
||||
{/each}
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -912,8 +902,7 @@
|
||||
{$i18n.t('Response splitting')}
|
||||
</div>
|
||||
<div class="flex items-center relative">
|
||||
<select
|
||||
class="w-fit pr-8 cursor-pointer rounded-lg px-2 p-1 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
|
||||
<SettingsSelect
|
||||
aria-label={$i18n.t('Select how to split message text for TTS requests')}
|
||||
bind:value={TTS_SPLIT_ON}
|
||||
>
|
||||
@@ -922,7 +911,7 @@
|
||||
>{$i18n.t(split.charAt(0).toUpperCase() + split.slice(1))}</option
|
||||
>
|
||||
{/each}
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2 mb-1 text-xs text-gray-400 dark:text-gray-500">
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
import AdminSettingField from './AdminSettingField.svelte';
|
||||
import AdminSettingRow from './AdminSettingRow.svelte';
|
||||
import AdminSettingSection from './AdminSettingSection.svelte';
|
||||
import SettingsSelect from '$lib/components/common/SettingsSelect.svelte';
|
||||
|
||||
const i18n: any = getContext('i18n');
|
||||
|
||||
@@ -49,8 +50,6 @@
|
||||
'w-full h-7 rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 text-xs text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500';
|
||||
const textareaClass =
|
||||
'w-full rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-xs text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500';
|
||||
const selectClass =
|
||||
'h-7 rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 pe-8 text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500';
|
||||
|
||||
const updateLdapServerHandler = async () => {
|
||||
await updateLdapConfig(localStorage.token, ENABLE_LDAP);
|
||||
@@ -126,20 +125,19 @@
|
||||
{#if adminConfig !== null}
|
||||
<AdminSettingSection title={$i18n.t('User Access')} first>
|
||||
<AdminSettingRow label={$i18n.t('Default User Role')}>
|
||||
<select
|
||||
class={`${selectClass} pr-8 text-right`}
|
||||
<SettingsSelect
|
||||
bind:value={adminConfig.DEFAULT_USER_ROLE}
|
||||
placeholder={$i18n.t('Select a role')}
|
||||
>
|
||||
<option value="pending">{$i18n.t('pending')}</option>
|
||||
<option value="user">{$i18n.t('user')}</option>
|
||||
<option value="admin">{$i18n.t('admin')}</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</AdminSettingRow>
|
||||
|
||||
<AdminSettingRow label={$i18n.t('Default Group')}>
|
||||
<select
|
||||
class={`${selectClass} max-w-48 truncate pr-8 text-right`}
|
||||
<SettingsSelect
|
||||
className="w-fit max-w-48"
|
||||
bind:value={adminConfig.DEFAULT_GROUP_ID}
|
||||
placeholder={$i18n.t('Select a group')}
|
||||
>
|
||||
@@ -147,7 +145,7 @@
|
||||
{#each groups as group}
|
||||
<option value={group.id}>{group.name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</AdminSettingRow>
|
||||
|
||||
<AdminSettingRow label={$i18n.t('Enable New Sign Ups')}>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
import AdminSettingField from './AdminSettingField.svelte';
|
||||
import AdminSettingRow from './AdminSettingRow.svelte';
|
||||
import AdminSettingSection from './AdminSettingSection.svelte';
|
||||
import SettingsSelect from '$lib/components/common/SettingsSelect.svelte';
|
||||
|
||||
const i18n: any = getContext('i18n');
|
||||
|
||||
@@ -24,8 +25,6 @@
|
||||
'w-full rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-xs text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500';
|
||||
const inlineInputClass =
|
||||
'w-fit h-7 rounded-lg border border-transparent bg-transparent px-2 text-xs text-gray-600 outline-hidden transition-colors hover:bg-black/5 focus:border-blue-400 dark:text-gray-400 dark:hover:bg-white/5 dark:focus:border-blue-500';
|
||||
const selectClass =
|
||||
'h-7 rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 pe-8 text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500';
|
||||
|
||||
const submitHandler = async () => {
|
||||
const res = await setCodeExecutionConfig(localStorage.token, config);
|
||||
@@ -67,8 +66,7 @@
|
||||
)
|
||||
: ''}
|
||||
>
|
||||
<select
|
||||
class={selectClass}
|
||||
<SettingsSelect
|
||||
bind:value={config.CODE_EXECUTION_ENGINE}
|
||||
placeholder={$i18n.t('Select a engine')}
|
||||
required
|
||||
@@ -77,7 +75,7 @@
|
||||
{#each engines as engine}
|
||||
<option value={engine}>{engine}{engine === 'jupyter' ? ' (Legacy)' : ''}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</AdminSettingRow>
|
||||
|
||||
{#if config.CODE_EXECUTION_ENGINE === 'jupyter'}
|
||||
@@ -92,15 +90,14 @@
|
||||
</AdminSettingField>
|
||||
|
||||
<AdminSettingRow label={$i18n.t('Jupyter Auth')}>
|
||||
<select
|
||||
class={selectClass}
|
||||
<SettingsSelect
|
||||
bind:value={config.CODE_EXECUTION_JUPYTER_AUTH}
|
||||
placeholder={$i18n.t('Select an auth method')}
|
||||
>
|
||||
<option selected value="">{$i18n.t('None')}</option>
|
||||
<option value="token">{$i18n.t('Token')}</option>
|
||||
<option value="password">{$i18n.t('Password')}</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</AdminSettingRow>
|
||||
|
||||
{#if config.CODE_EXECUTION_JUPYTER_AUTH}
|
||||
@@ -160,8 +157,7 @@
|
||||
)
|
||||
: ''}
|
||||
>
|
||||
<select
|
||||
class={selectClass}
|
||||
<SettingsSelect
|
||||
bind:value={config.CODE_INTERPRETER_ENGINE}
|
||||
placeholder={$i18n.t('Select a engine')}
|
||||
required
|
||||
@@ -170,7 +166,7 @@
|
||||
{#each engines as engine}
|
||||
<option value={engine}>{engine}{engine === 'jupyter' ? ' (Legacy)' : ''}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</AdminSettingRow>
|
||||
|
||||
{#if config.CODE_INTERPRETER_ENGINE === 'jupyter'}
|
||||
@@ -185,15 +181,14 @@
|
||||
</AdminSettingField>
|
||||
|
||||
<AdminSettingRow label={$i18n.t('Jupyter Auth')}>
|
||||
<select
|
||||
class={selectClass}
|
||||
<SettingsSelect
|
||||
bind:value={config.CODE_INTERPRETER_JUPYTER_AUTH}
|
||||
placeholder={$i18n.t('Select an auth method')}
|
||||
>
|
||||
<option selected value="">{$i18n.t('None')}</option>
|
||||
<option value="token">{$i18n.t('Token')}</option>
|
||||
<option value="password">{$i18n.t('Password')}</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</AdminSettingRow>
|
||||
|
||||
{#if config.CODE_INTERPRETER_JUPYTER_AUTH}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
import Switch from '$lib/components/common/Switch.svelte';
|
||||
import Textarea from '$lib/components/common/Textarea.svelte';
|
||||
import Spinner from '$lib/components/common/Spinner.svelte';
|
||||
import SettingsSelect from '$lib/components/common/SettingsSelect.svelte';
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
@@ -386,10 +387,7 @@
|
||||
{$i18n.t('Content Extraction Engine')}
|
||||
</div>
|
||||
<div class="">
|
||||
<select
|
||||
class="w-fit pr-8 rounded-lg px-2 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
|
||||
bind:value={RAGConfig.CONTENT_EXTRACTION_ENGINE}
|
||||
>
|
||||
<SettingsSelect bind:value={RAGConfig.CONTENT_EXTRACTION_ENGINE}>
|
||||
<option value="">{$i18n.t('Default')}</option>
|
||||
<option value="external">{$i18n.t('External')}</option>
|
||||
<option value="tika">{$i18n.t('Tika')}</option>
|
||||
@@ -399,7 +397,7 @@
|
||||
<option value="mistral_ocr">{$i18n.t('Mistral OCR')}</option>
|
||||
<option value="paddleocr_vl">{$i18n.t('PaddleOCR-vl')}</option>
|
||||
<option value="mineru">{$i18n.t('MinerU')}</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -428,13 +426,10 @@
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div class="">
|
||||
<select
|
||||
class="w-fit pr-8 rounded-lg px-2 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
|
||||
bind:value={RAGConfig.PDF_LOADER_MODE}
|
||||
>
|
||||
<SettingsSelect bind:value={RAGConfig.PDF_LOADER_MODE}>
|
||||
<option value="page">{$i18n.t('Page')}</option>
|
||||
<option value="single">{$i18n.t('Single')}</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -600,14 +595,11 @@
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div class="">
|
||||
<select
|
||||
class="w-fit pr-8 rounded-lg px-2 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
|
||||
bind:value={RAGConfig.DATALAB_MARKER_OUTPUT_FORMAT}
|
||||
>
|
||||
<SettingsSelect bind:value={RAGConfig.DATALAB_MARKER_OUTPUT_FORMAT}>
|
||||
<option value="markdown">{$i18n.t('Markdown')}</option>
|
||||
<option value="json">{$i18n.t('JSON')}</option>
|
||||
<option value="html">{$i18n.t('HTML')}</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
{:else if RAGConfig.CONTENT_EXTRACTION_ENGINE === 'external'}
|
||||
@@ -797,8 +789,7 @@
|
||||
<div class="self-center text-xs text-gray-600 dark:text-gray-400">
|
||||
{$i18n.t('API Mode')}
|
||||
</div>
|
||||
<select
|
||||
class="w-fit pr-8 rounded-lg px-2 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
|
||||
<SettingsSelect
|
||||
bind:value={RAGConfig.MINERU_API_MODE}
|
||||
on:change={() => {
|
||||
// Auto-update URL when switching modes if it's empty or matches the opposite mode's default
|
||||
@@ -818,7 +809,7 @@
|
||||
>
|
||||
<option value="local">{$i18n.t('local')}</option>
|
||||
<option value="cloud">{$i18n.t('cloud')}</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -925,16 +916,13 @@
|
||||
{$i18n.t('Text Splitter')}
|
||||
</div>
|
||||
<div class="flex items-center relative">
|
||||
<select
|
||||
class="w-fit pr-8 rounded-lg px-2 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
|
||||
bind:value={RAGConfig.TEXT_SPLITTER}
|
||||
>
|
||||
<SettingsSelect bind:value={RAGConfig.TEXT_SPLITTER}>
|
||||
<option value="">{$i18n.t('Default')} ({$i18n.t('Character')})</option>
|
||||
<option value="token">{$i18n.t('Token')} ({$i18n.t('Tiktoken')})</option>
|
||||
<option value="token_transformers">
|
||||
{$i18n.t('Token')} ({$i18n.t('Transformers')})
|
||||
</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1055,8 +1043,7 @@
|
||||
{$i18n.t('Embedding Model Engine')}
|
||||
</div>
|
||||
<div class="flex items-center relative">
|
||||
<select
|
||||
class="w-fit pr-8 rounded-lg px-2 p-1 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
|
||||
<SettingsSelect
|
||||
bind:value={RAG_EMBEDDING_ENGINE}
|
||||
placeholder={$i18n.t('Select an embedding model engine')}
|
||||
on:change={(e) => {
|
||||
@@ -1075,7 +1062,7 @@
|
||||
<option value="ollama">{$i18n.t('Ollama')}</option>
|
||||
<option value="openai">{$i18n.t('OpenAI')}</option>
|
||||
<option value="azure_openai">{$i18n.t('Azure OpenAI')}</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1317,8 +1304,7 @@
|
||||
{$i18n.t('Reranking Engine')}
|
||||
</div>
|
||||
<div class="flex items-center relative">
|
||||
<select
|
||||
class="w-fit pr-8 rounded-lg px-2 p-1 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
|
||||
<SettingsSelect
|
||||
bind:value={RAGConfig.RAG_RERANKING_ENGINE}
|
||||
placeholder={$i18n.t('Select a reranking model engine')}
|
||||
on:change={(e) => {
|
||||
@@ -1331,7 +1317,7 @@
|
||||
>
|
||||
<option value="">{$i18n.t('Default (SentenceTransformers)')}</option>
|
||||
<option value="external">{$i18n.t('External')}</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
import ConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
|
||||
import XMark from '$lib/components/icons/XMark.svelte';
|
||||
import { WEBUI_BASE_URL } from '$lib/constants';
|
||||
import SettingsSelect from '$lib/components/common/SettingsSelect.svelte';
|
||||
|
||||
export let show = false;
|
||||
export let edit = false;
|
||||
@@ -349,17 +350,16 @@
|
||||
<hr class=" border-gray-100 dark:border-gray-700/10 my-2.5 w-full" />
|
||||
|
||||
<div class="flex items-center">
|
||||
<select
|
||||
class="w-full rounded-lg border border-gray-100/50 !bg-gray-50/40 px-2 py-1.5 text-sm text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500 {selectedModelId
|
||||
? ''
|
||||
: 'text-gray-500'} placeholder:text-gray-300 dark:placeholder:text-gray-700 outline-hidden"
|
||||
<SettingsSelect
|
||||
bind:value={selectedModelId}
|
||||
className="w-full"
|
||||
selectClassName="text-sm"
|
||||
>
|
||||
<option value="">{$i18n.t('Select a model')}</option>
|
||||
{#each $models.filter((m) => m?.owned_by !== 'arena') as model}
|
||||
<option value={model.id} class="bg-gray-50 dark:bg-gray-700">{model.name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
|
||||
<div>
|
||||
<button
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
import Cog6 from '$lib/components/icons/Cog6.svelte';
|
||||
import XMark from '$lib/components/icons/XMark.svelte';
|
||||
import { settings } from '$lib/stores';
|
||||
import SettingsSelect from '$lib/components/common/SettingsSelect.svelte';
|
||||
|
||||
const i18n = getContext<Writable<i18nType>>('i18n');
|
||||
|
||||
@@ -454,14 +455,11 @@
|
||||
<div class={`text-xs text-gray-500`}>
|
||||
{$i18n.t('Send events for')}
|
||||
</div>
|
||||
<select
|
||||
class="rounded-lg border border-gray-100/50 !bg-gray-50/40 px-2 py-1.5 text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500"
|
||||
bind:value={targetMode}
|
||||
>
|
||||
<SettingsSelect bind:value={targetMode}>
|
||||
<option value="all">{$i18n.t('All users and system events')}</option>
|
||||
<option value="system">{$i18n.t('System events only')}</option>
|
||||
<option value="selected">{$i18n.t('Specific users or groups')}</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
|
||||
<div class="mt-1 text-xs text-gray-500">
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
updateExternalKnowledgeConnection,
|
||||
updateExternalKnowledgeSource
|
||||
} from '$lib/apis/knowledge';
|
||||
import SettingsSelect from '$lib/components/common/SettingsSelect.svelte';
|
||||
|
||||
const i18n = getContext<Writable<i18nType>>('i18n');
|
||||
|
||||
@@ -458,16 +459,17 @@
|
||||
>
|
||||
</div>
|
||||
<div class="flex flex-1 items-center">
|
||||
<select
|
||||
<SettingsSelect
|
||||
id="external-source-provider"
|
||||
class="w-full rounded-lg border border-gray-100/50 !bg-gray-50/40 px-2 py-1.5 text-sm text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500"
|
||||
bind:value={sourceForm.provider}
|
||||
on:change={updateProvider}
|
||||
className="w-full"
|
||||
selectClassName="text-sm"
|
||||
>
|
||||
<option value="qdrant">Qdrant</option>
|
||||
<option value="milvus">Milvus</option>
|
||||
<option value="pgvector">pgvector</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||
import Textarea from '$lib/components/common/Textarea.svelte';
|
||||
import CodeEditorModal from '$lib/components/common/CodeEditorModal.svelte';
|
||||
import SettingsSelect from '$lib/components/common/SettingsSelect.svelte';
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
@@ -403,8 +404,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<select
|
||||
class="w-fit pr-8 cursor-pointer rounded-lg px-2 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
|
||||
<SettingsSelect
|
||||
bind:value={config.IMAGE_GENERATION_ENGINE}
|
||||
placeholder={$i18n.t('Select Engine')}
|
||||
>
|
||||
@@ -412,7 +412,7 @@
|
||||
<option value="comfyui">{$i18n.t('ComfyUI')}</option>
|
||||
<option value="automatic1111">{$i18n.t('Automatic1111')}</option>
|
||||
<option value="gemini">{$i18n.t('Gemini')}</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -868,14 +868,13 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<select
|
||||
class="w-fit pr-8 cursor-pointer rounded-lg px-2 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
|
||||
<SettingsSelect
|
||||
bind:value={config.IMAGES_GEMINI_ENDPOINT_METHOD}
|
||||
placeholder={$i18n.t('Select Method')}
|
||||
>
|
||||
<option value="predict">predict</option>
|
||||
<option value="generateContent">generateContent</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -951,15 +950,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<select
|
||||
class="w-fit pr-8 cursor-pointer rounded-lg px-2 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
|
||||
<SettingsSelect
|
||||
bind:value={config.IMAGE_EDIT_ENGINE}
|
||||
placeholder={$i18n.t('Select Engine')}
|
||||
>
|
||||
<option value="openai">{$i18n.t('Default (Open AI)')}</option>
|
||||
<option value="comfyui">{$i18n.t('ComfyUI')}</option>
|
||||
<option value="gemini">{$i18n.t('Gemini')}</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
import Switch from '$lib/components/common/Switch.svelte';
|
||||
import Textarea from '$lib/components/common/Textarea.svelte';
|
||||
import Spinner from '$lib/components/common/Spinner.svelte';
|
||||
import SettingsSelect from '$lib/components/common/SettingsSelect.svelte';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
@@ -145,8 +146,8 @@
|
||||
<div class=" mb-2.5 flex w-full gap-2">
|
||||
<div class="flex-1">
|
||||
<div class=" text-xs mb-1">{$i18n.t('Local Task Model')}</div>
|
||||
<select
|
||||
class="w-full rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500"
|
||||
<SettingsSelect
|
||||
className="w-full"
|
||||
bind:value={taskConfig.TASK_MODEL}
|
||||
placeholder={$i18n.t('Select a model')}
|
||||
on:change={() => {
|
||||
@@ -183,13 +184,13 @@
|
||||
{model?.connection_type === 'local' ? `(${$i18n.t('Local')})` : ''}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
|
||||
<div class="flex-1">
|
||||
<div class=" text-xs mb-1">{$i18n.t('External Task Model')}</div>
|
||||
<select
|
||||
class="w-full rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500"
|
||||
<SettingsSelect
|
||||
className="w-full"
|
||||
bind:value={taskConfig.TASK_MODEL_EXTERNAL}
|
||||
placeholder={$i18n.t('Select a model')}
|
||||
on:change={() => {
|
||||
@@ -226,7 +227,7 @@
|
||||
{model?.connection_type === 'local' ? `(${$i18n.t('Local')})` : ''}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import XMark from '$lib/components/icons/XMark.svelte';
|
||||
import Sortable from 'sortablejs';
|
||||
import { getContext } from 'svelte';
|
||||
import SettingsSelect from '$lib/components/common/SettingsSelect.svelte';
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
export let banners = [];
|
||||
@@ -59,17 +60,13 @@
|
||||
<EllipsisVertical className="size-4 cursor-move item-handle" />
|
||||
|
||||
<div class="flex flex-row flex-1 gap-2 items-start">
|
||||
<select
|
||||
class="w-fit capitalize rounded-xl text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 pl-1 pr-5"
|
||||
bind:value={banner.type}
|
||||
required
|
||||
>
|
||||
<SettingsSelect bind:value={banner.type} required selectClassName="capitalize">
|
||||
<option value="" disabled hidden class="text-gray-900">{$i18n.t('Type')}</option>
|
||||
<option value="info" class="text-gray-900">{$i18n.t('Info')}</option>
|
||||
<option value="warning" class="text-gray-900">{$i18n.t('Warning')}</option>
|
||||
<option value="error" class="text-gray-900">{$i18n.t('Error')}</option>
|
||||
<option value="success" class="text-gray-900">{$i18n.t('Success')}</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
|
||||
<Textarea
|
||||
className="mr-2 text-xs w-full border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 resize-none"
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
import ManageOllama from './ManageOllama.svelte';
|
||||
import SettingsSelect from '$lib/components/common/SettingsSelect.svelte';
|
||||
|
||||
export let ollamaConfig = null;
|
||||
|
||||
@@ -11,15 +12,16 @@
|
||||
|
||||
{#if ollamaConfig}
|
||||
<div class="flex-1 mb-2.5 pr-1.5 rounded-lg bg-gray-50 dark:text-gray-300 dark:bg-gray-850">
|
||||
<select
|
||||
class="w-full py-2 px-4 text-sm outline-hidden border border-gray-100/50 !bg-gray-50/40 dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
|
||||
<SettingsSelect
|
||||
bind:value={selectedUrlIdx}
|
||||
placeholder={$i18n.t('Select an Ollama instance')}
|
||||
className="w-full"
|
||||
selectClassName="text-sm"
|
||||
>
|
||||
{#each ollamaConfig.OLLAMA_BASE_URLS as url, idx}
|
||||
<option value={idx}>{url}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||
import ModelDeleteConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
|
||||
import Spinner from '$lib/components/common/Spinner.svelte';
|
||||
import SettingsSelect from '$lib/components/common/SettingsSelect.svelte';
|
||||
|
||||
let modelUploadInputElement: HTMLInputElement;
|
||||
let showModelDeleteConfirm = false;
|
||||
@@ -811,10 +812,11 @@
|
||||
<div
|
||||
class="flex-1 mr-2 pr-1.5 rounded-lg bg-gray-50 dark:text-gray-300 dark:bg-gray-850"
|
||||
>
|
||||
<select
|
||||
class="w-full py-2 px-4 text-sm outline-hidden border border-gray-100/50 !bg-gray-50/40 dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
|
||||
<SettingsSelect
|
||||
bind:value={deleteModelTag}
|
||||
placeholder={$i18n.t('Select a model')}
|
||||
className="w-full"
|
||||
selectClassName="text-sm"
|
||||
>
|
||||
<option value="" disabled selected>{$i18n.t('Select a model')}</option>
|
||||
|
||||
@@ -823,7 +825,7 @@
|
||||
>{model.name + ' (' + (model.size / 1024 ** 3).toFixed(1) + ' GB)'}</option
|
||||
>
|
||||
{/each}
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
<Tooltip content={$i18n.t('Delete Model')} placement="top">
|
||||
<button
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
import Minus from '$lib/components/icons/Minus.svelte';
|
||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||
import SettingsSelect from '$lib/components/common/SettingsSelect.svelte';
|
||||
|
||||
export let title = '';
|
||||
export let tooltip = '';
|
||||
@@ -40,10 +41,9 @@
|
||||
</div>
|
||||
|
||||
<div class="flex items-center -mr-1">
|
||||
<select
|
||||
class="w-full py-1 text-sm rounded-lg border border-gray-100/50 !bg-gray-50/40 dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 {selectedModelId
|
||||
? ''
|
||||
: 'text-gray-500'} placeholder:text-gray-300 dark:placeholder:text-gray-700 outline-hidden"
|
||||
<SettingsSelect
|
||||
className="w-full"
|
||||
selectClassName="text-sm"
|
||||
bind:value={selectedModelId}
|
||||
on:change={() => {
|
||||
if (selectedModelId && !modelIds.includes(selectedModelId)) {
|
||||
@@ -58,7 +58,7 @@
|
||||
<option value={model.id} class="bg-gray-50 dark:bg-gray-700">{model.name}</option>
|
||||
{/if}
|
||||
{/each}
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
|
||||
<!-- <hr class=" border-gray-100 dark:border-gray-700/10 my-2.5 w-full" /> -->
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
import Switch from '$lib/components/common/Switch.svelte';
|
||||
import AdminSettingField from './AdminSettingField.svelte';
|
||||
import AdminSettingRow from './AdminSettingRow.svelte';
|
||||
import SettingsSelect from '$lib/components/common/SettingsSelect.svelte';
|
||||
|
||||
const i18n: Writable<i18nType> = getContext('i18n');
|
||||
|
||||
@@ -42,8 +43,6 @@
|
||||
let pipelineDownloadUrl = '';
|
||||
const inputClass =
|
||||
'w-full h-7 rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 text-xs text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500';
|
||||
const selectClass =
|
||||
'w-full h-7 rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 pe-8 text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500';
|
||||
const actionButtonClass =
|
||||
'rounded-lg px-2 py-1 text-xs text-gray-500 transition-colors hover:bg-black/5 hover:text-gray-900 disabled:opacity-50 dark:text-gray-500 dark:hover:bg-white/5 dark:hover:text-white';
|
||||
const iconButtonClass =
|
||||
@@ -253,8 +252,8 @@
|
||||
|
||||
<div class="flex flex-col gap-2.5">
|
||||
<AdminSettingField label={$i18n.t('Pipeline URL')}>
|
||||
<select
|
||||
class={selectClass}
|
||||
<SettingsSelect
|
||||
className="w-full"
|
||||
bind:value={selectedPipelinesUrlIdx}
|
||||
placeholder={$i18n.t('Select a pipeline url')}
|
||||
on:change={async () => {
|
||||
@@ -271,7 +270,7 @@
|
||||
>{pipelines.url}</option
|
||||
>
|
||||
{/each}
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</AdminSettingField>
|
||||
|
||||
<AdminSettingField label={$i18n.t('Upload Pipeline')}>
|
||||
@@ -330,8 +329,8 @@
|
||||
{#if pipelines.length > 0}
|
||||
<AdminSettingField label={$i18n.t('Pipeline')}>
|
||||
<div class="flex gap-2">
|
||||
<select
|
||||
class={selectClass}
|
||||
<SettingsSelect
|
||||
className="w-full"
|
||||
bind:value={selectedPipelineIdx}
|
||||
placeholder={$i18n.t('Select a pipeline')}
|
||||
on:change={async () => {
|
||||
@@ -344,7 +343,7 @@
|
||||
{pipeline.name} ({pipeline.type ?? 'pipe'})
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
|
||||
<button
|
||||
class={actionButtonClass}
|
||||
@@ -379,13 +378,13 @@
|
||||
{#if (valves[property] ?? null) !== null}
|
||||
<div class="mt-1">
|
||||
{#if valves_spec.properties[property]?.enum ?? null}
|
||||
<select class={selectClass} bind:value={valves[property]}>
|
||||
<SettingsSelect bind:value={valves[property]} className="w-full">
|
||||
{#each valves_spec.properties[property].enum as option}
|
||||
<option value={option} selected={option === valves[property]}>
|
||||
{option}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
{:else if (valves_spec.properties[property]?.type ?? null) === 'boolean'}
|
||||
<AdminSettingRow
|
||||
label={valves[property] ? $i18n.t('Enabled') : $i18n.t('Disabled')}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
|
||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||
import Textarea from '$lib/components/common/Textarea.svelte';
|
||||
import SettingsSelect from '$lib/components/common/SettingsSelect.svelte';
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
@@ -198,8 +199,7 @@
|
||||
{$i18n.t('Web Search Engine')}
|
||||
</div>
|
||||
<div class="flex items-center relative">
|
||||
<select
|
||||
class="w-fit pr-8 rounded-lg px-2 p-1 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
|
||||
<SettingsSelect
|
||||
bind:value={webConfig.WEB_SEARCH_ENGINE}
|
||||
placeholder={$i18n.t('Select a engine')}
|
||||
required
|
||||
@@ -214,7 +214,7 @@
|
||||
<option value={engine}>{engine}</option>
|
||||
{/if}
|
||||
{/each}
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -731,14 +731,14 @@
|
||||
<div class=" self-center text-xs text-gray-600 dark:text-gray-400 mb-1">
|
||||
{$i18n.t('Perplexity Search Context Usage')}
|
||||
</div>
|
||||
<select
|
||||
class="w-full rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500"
|
||||
<SettingsSelect
|
||||
bind:value={webConfig.PERPLEXITY_SEARCH_CONTEXT_USAGE}
|
||||
className="w-full"
|
||||
>
|
||||
<option value="low">{$i18n.t('Low')}</option>
|
||||
<option value="medium">{$i18n.t('Medium')}</option>
|
||||
<option value="high">{$i18n.t('High')}</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
{:else if webConfig.WEB_SEARCH_ENGINE === 'microsoft_web_iq'}
|
||||
@@ -992,10 +992,7 @@
|
||||
|
||||
<div class="flex w-full">
|
||||
<div class="flex-1">
|
||||
<select
|
||||
class="w-full rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500"
|
||||
bind:value={webConfig.DDGS_BACKEND}
|
||||
>
|
||||
<SettingsSelect bind:value={webConfig.DDGS_BACKEND} className="w-full">
|
||||
<option value="auto">{$i18n.t('Auto (Random)')}</option>
|
||||
<option value="bing">{$i18n.t('Bing')}</option>
|
||||
<option value="brave">{$i18n.t('Brave')}</option>
|
||||
@@ -1006,7 +1003,7 @@
|
||||
<option value="wikipedia">{$i18n.t('Wikipedia')}</option>
|
||||
<option value="yahoo">{$i18n.t('Yahoo')}</option>
|
||||
<option value="yandex">{$i18n.t('Yandex')}</option>
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1151,8 +1148,7 @@
|
||||
{$i18n.t('Web Loader Engine')}
|
||||
</div>
|
||||
<div class="flex items-center relative">
|
||||
<select
|
||||
class="w-fit pr-8 rounded-lg px-2 p-1 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
|
||||
<SettingsSelect
|
||||
bind:value={webConfig.WEB_LOADER_ENGINE}
|
||||
placeholder={$i18n.t('Select a engine')}
|
||||
>
|
||||
@@ -1160,7 +1156,7 @@
|
||||
{#each webLoaderEngines as engine}
|
||||
<option value={engine}>{engine}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</SettingsSelect>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import UserProfileImage from './Account/UserProfileImage.svelte';
|
||||
import UserSettingField from './UserSettingField.svelte';
|
||||
import UserSettingRow from './UserSettingRow.svelte';
|
||||
import UserSettingSelect from './UserSettingSelect.svelte';
|
||||
import SettingsSelect from '$lib/components/common/SettingsSelect.svelte';
|
||||
import UserSettingSection from './UserSettingSection.svelte';
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
@@ -172,7 +172,7 @@
|
||||
label={$i18n.t('Gender')}
|
||||
description={$i18n.t('Choose the gender value stored on your profile.')}
|
||||
>
|
||||
<UserSettingSelect
|
||||
<SettingsSelect
|
||||
className="w-full"
|
||||
bind:value={_gender}
|
||||
ariaLabel={$i18n.t('Gender')}
|
||||
@@ -191,7 +191,7 @@
|
||||
<option value="male">{$i18n.t('Male')}</option>
|
||||
<option value="female">{$i18n.t('Female')}</option>
|
||||
<option value="custom">{$i18n.t('Custom')}</option>
|
||||
</UserSettingSelect>
|
||||
</SettingsSelect>
|
||||
|
||||
{#if _gender === 'custom'}
|
||||
<input
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||
import UserSettingField from './UserSettingField.svelte';
|
||||
import UserSettingRow from './UserSettingRow.svelte';
|
||||
import UserSettingSelect from './UserSettingSelect.svelte';
|
||||
import SettingsSelect from '$lib/components/common/SettingsSelect.svelte';
|
||||
import UserSettingSection from './UserSettingSection.svelte';
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
@@ -192,14 +192,14 @@
|
||||
label={$i18n.t('Speech-to-Text Engine')}
|
||||
description={$i18n.t('Choose the engine used to transcribe voice input.')}
|
||||
>
|
||||
<UserSettingSelect
|
||||
<SettingsSelect
|
||||
bind:value={STTEngine}
|
||||
ariaLabel={$i18n.t('Speech-to-Text Engine')}
|
||||
placeholder={$i18n.t('Select an engine')}
|
||||
>
|
||||
<option value="">{$i18n.t('Default')}</option>
|
||||
<option value="web">{$i18n.t('Web API')}</option>
|
||||
</UserSettingSelect>
|
||||
</SettingsSelect>
|
||||
</UserSettingRow>
|
||||
|
||||
<UserSettingRow
|
||||
@@ -250,14 +250,14 @@
|
||||
label={$i18n.t('Text-to-Speech Engine')}
|
||||
description={$i18n.t('Choose the engine used to read assistant responses aloud.')}
|
||||
>
|
||||
<UserSettingSelect
|
||||
<SettingsSelect
|
||||
bind:value={TTSEngine}
|
||||
ariaLabel={$i18n.t('Text-to-Speech Engine')}
|
||||
placeholder={$i18n.t('Select an engine')}
|
||||
>
|
||||
<option value="">{$i18n.t('Default')}</option>
|
||||
<option value="browser-kokoro">{$i18n.t('Kokoro.js (Browser)')}</option>
|
||||
</UserSettingSelect>
|
||||
</SettingsSelect>
|
||||
</UserSettingRow>
|
||||
|
||||
{#if TTSEngine === 'browser-kokoro'}
|
||||
@@ -265,7 +265,7 @@
|
||||
label={$i18n.t('Kokoro.js Dtype')}
|
||||
description={$i18n.t('Select the local model precision used by Kokoro.js.')}
|
||||
>
|
||||
<UserSettingSelect
|
||||
<SettingsSelect
|
||||
bind:value={TTSEngineConfig.dtype}
|
||||
ariaLabel={$i18n.t('Kokoro.js Dtype')}
|
||||
placeholder={$i18n.t('Select dtype')}
|
||||
@@ -275,7 +275,7 @@
|
||||
<option value="fp16">fp16</option>
|
||||
<option value="q8">q8</option>
|
||||
<option value="q4">q4</option>
|
||||
</UserSettingSelect>
|
||||
</SettingsSelect>
|
||||
</UserSettingRow>
|
||||
{/if}
|
||||
|
||||
@@ -360,7 +360,7 @@
|
||||
label={$i18n.t('Set Voice')}
|
||||
description={$i18n.t('Choose the browser voice used for speech output.')}
|
||||
>
|
||||
<UserSettingSelect className="w-full" bind:value={voice} ariaLabel={$i18n.t('Voice')}>
|
||||
<SettingsSelect className="w-full" bind:value={voice} ariaLabel={$i18n.t('Voice')}>
|
||||
<option value="" selected={voice !== ''}>{$i18n.t('Default')}</option>
|
||||
{#each voices.filter((v) => nonLocalVoices || v.localService === true) as _voice}
|
||||
<option
|
||||
@@ -369,7 +369,7 @@
|
||||
selected={voice === _voice.name}>{_voice.name}</option
|
||||
>
|
||||
{/each}
|
||||
</UserSettingSelect>
|
||||
</SettingsSelect>
|
||||
</UserSettingField>
|
||||
<UserSettingRow
|
||||
label={$i18n.t('Allow non-local voices')}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
import UserSettingField from './UserSettingField.svelte';
|
||||
import UserSettingRow from './UserSettingRow.svelte';
|
||||
import UserSettingSection from './UserSettingSection.svelte';
|
||||
import UserSettingSelect from './UserSettingSelect.svelte';
|
||||
import SettingsSelect from '$lib/components/common/SettingsSelect.svelte';
|
||||
export let saveSettings: Function;
|
||||
export let getModels: Function;
|
||||
|
||||
@@ -223,7 +223,7 @@
|
||||
label={$i18n.t('Theme')}
|
||||
description={$i18n.t('Choose the color theme used by the interface.')}
|
||||
>
|
||||
<UserSettingSelect
|
||||
<SettingsSelect
|
||||
bind:value={selectedTheme}
|
||||
ariaLabel={$i18n.t('Theme')}
|
||||
placeholder={$i18n.t('Select a theme')}
|
||||
@@ -236,14 +236,14 @@
|
||||
{#if $config?.features?.enable_easter_eggs}
|
||||
<option value="her">🌷 Her</option>
|
||||
{/if}
|
||||
</UserSettingSelect>
|
||||
</SettingsSelect>
|
||||
</UserSettingRow>
|
||||
|
||||
<UserSettingRow
|
||||
label={$i18n.t('Language')}
|
||||
description={$i18n.t('Choose the language used for interface text.')}
|
||||
>
|
||||
<UserSettingSelect
|
||||
<SettingsSelect
|
||||
bind:value={lang}
|
||||
ariaLabel={$i18n.t('Language')}
|
||||
className="w-48"
|
||||
@@ -255,7 +255,7 @@
|
||||
{#each languages as language}
|
||||
<option value={language['code']}>{language['title']}</option>
|
||||
{/each}
|
||||
</UserSettingSelect>
|
||||
</SettingsSelect>
|
||||
</UserSettingRow>
|
||||
{#if $i18n.language === 'en-US' && !($config?.license_metadata ?? false)}
|
||||
<div class="-mt-1 text-[0.6875rem] text-gray-400 dark:text-gray-600">
|
||||
|
||||
@@ -109,9 +109,9 @@
|
||||
const settingRowClass = 'flex items-center justify-between gap-2.5';
|
||||
const settingLabelClass = 'min-w-0 text-xs text-gray-600 dark:text-gray-400';
|
||||
const settingControlClass = 'flex shrink-0 items-center justify-end gap-1.5';
|
||||
const sectionHeadingClass = 'mt-2 text-xs text-gray-400 dark:text-gray-600';
|
||||
const sectionHeadingClass = 'mt-4 text-xs text-gray-400 dark:text-gray-600';
|
||||
const firstSectionHeadingClass = 'text-xs text-gray-400 dark:text-gray-600';
|
||||
const settingDescriptionClass = '-mt-1 text-[0.6875rem] text-gray-400 dark:text-gray-600';
|
||||
const settingDescriptionClass = 'mt-1.5 text-[0.6875rem] text-gray-400 dark:text-gray-600';
|
||||
const actionButtonClass =
|
||||
'text-xs text-gray-500 transition-colors hover:text-gray-900 dark:text-gray-500 dark:hover:text-white';
|
||||
|
||||
@@ -1229,7 +1229,7 @@
|
||||
{$i18n.t('Floating Quick Actions')}
|
||||
</label>
|
||||
|
||||
<div class="flex shrink-0 items-center gap-3">
|
||||
<div class={settingControlClass}>
|
||||
{#if showFloatingActionButtons}
|
||||
<button
|
||||
class={actionButtonClass}
|
||||
@@ -1546,7 +1546,7 @@
|
||||
{$i18n.t('Image Compression')}
|
||||
</div>
|
||||
|
||||
<div class="flex shrink-0 items-center gap-3">
|
||||
<div class={settingControlClass}>
|
||||
{#if imageCompression}
|
||||
<button
|
||||
class={actionButtonClass}
|
||||
|
||||
+11
-2
@@ -1,17 +1,26 @@
|
||||
<script lang="ts">
|
||||
export let value = '';
|
||||
export let value: string | number | boolean = '';
|
||||
export let id = '';
|
||||
export let name = '';
|
||||
export let ariaLabel = '';
|
||||
export let placeholder = '';
|
||||
export let required = false;
|
||||
export let disabled = false;
|
||||
export let className = 'w-fit min-w-32';
|
||||
export let selectClassName = '';
|
||||
</script>
|
||||
|
||||
<div class="relative inline-flex {className}">
|
||||
<select
|
||||
{...$$restProps}
|
||||
bind:value
|
||||
id={id || undefined}
|
||||
name={name || undefined}
|
||||
aria-label={ariaLabel || undefined}
|
||||
title={placeholder || undefined}
|
||||
class="h-7 w-full truncate rounded-lg border border-gray-100/50 !bg-gray-50/40 ps-2.5 pe-9 text-left text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500 {selectClassName}"
|
||||
{required}
|
||||
{disabled}
|
||||
class="h-7 w-full truncate rounded-lg border border-gray-100/50 !bg-gray-50/40 ps-2.5 pe-9 text-left text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 disabled:opacity-50 dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500 {selectClassName}"
|
||||
on:change
|
||||
>
|
||||
<slot />
|
||||
Reference in New Issue
Block a user