This commit is contained in:
Timothy Jaeryang Baek
2026-02-22 17:26:59 -06:00
parent 0ca2e46ade
commit 1cd26372fb
5 changed files with 122 additions and 94 deletions

View File

@@ -1,7 +1,8 @@
<script lang="ts">
import DOMPurify from 'dompurify';
import { v4 as uuidv4 } from 'uuid';
import { getVersionUpdates, getWebhookUrl, updateWebhookUrl } from '$lib/apis';
import { getBackendConfig, getVersionUpdates, getWebhookUrl, updateWebhookUrl } from '$lib/apis';
import {
getAdminConfig,
getLdapConfig,
@@ -10,16 +11,19 @@
updateLdapConfig,
updateLdapServer
} from '$lib/apis/auths';
import { getBanners, setBanners } from '$lib/apis/configs';
import { getGroups } from '$lib/apis/groups';
import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
import Switch from '$lib/components/common/Switch.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte';
import { WEBUI_BUILD_HASH, WEBUI_VERSION } from '$lib/constants';
import { config, showChangelog } from '$lib/stores';
import { banners as _banners, config, showChangelog } from '$lib/stores';
import type { Banner } from '$lib/types';
import { compareVersion } from '$lib/utils';
import { onMount, getContext } from 'svelte';
import { toast } from 'svelte-sonner';
import Textarea from '$lib/components/common/Textarea.svelte';
import Banners from './Interface/Banners.svelte';
const i18n = getContext('i18n');
@@ -35,6 +39,8 @@
let webhookUrl = '';
let groups = [];
let banners: Banner[] = [];
// LDAP
let ENABLE_LDAP = false;
let LDAP_SERVER = {
@@ -78,12 +84,20 @@
}
};
const updateBanners = async () => {
_banners.set(await setBanners(localStorage.token, banners));
};
const updateHandler = async () => {
webhookUrl = await updateWebhookUrl(localStorage.token, webhookUrl);
const res = await updateAdminConfig(localStorage.token, adminConfig);
await updateLdapConfig(localStorage.token, ENABLE_LDAP);
await updateLdapServerHandler();
await updateBanners();
await config.set(await getBackendConfig());
if (res) {
saveHandler();
} else {
@@ -114,6 +128,8 @@
const ldapConfig = await getLdapConfig(localStorage.token);
ENABLE_LDAP = ldapConfig.ENABLE_LDAP;
banners = await getBanners(localStorage.token);
});
</script>
@@ -811,6 +827,53 @@
</div>
</div>
</div>
<div class="mb-3.5">
<div class=" mt-0.5 mb-2.5 text-base font-medium">{$i18n.t('UI')}</div>
<hr class=" border-gray-100/30 dark:border-gray-850/30 my-2" />
<div class="mb-2.5">
<div class="flex w-full justify-between">
<div class=" self-center text-xs">
{$i18n.t('Banners')}
</div>
<button
class="p-1 px-3 text-xs flex rounded-sm transition"
type="button"
on:click={() => {
if (banners.length === 0 || banners.at(-1).content !== '') {
banners = [
...banners,
{
id: uuidv4(),
type: '',
title: '',
content: '',
dismissible: true,
timestamp: Math.floor(Date.now() / 1000)
}
];
}
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"
/>
</svg>
</button>
</div>
<Banners bind:banners />
</div>
</div>
</div>
{/if}
</div>

View File

@@ -1,27 +1,14 @@
<script lang="ts">
import fileSaver from 'file-saver';
const { saveAs } = fileSaver;
import { v4 as uuidv4 } from 'uuid';
import { toast } from 'svelte-sonner';
import { getBackendConfig, getModels, getTaskConfig, updateTaskConfig } from '$lib/apis';
import { setDefaultPromptSuggestions } from '$lib/apis/configs';
import { config, settings, user } from '$lib/stores';
import { getModels, getTaskConfig, updateTaskConfig } from '$lib/apis';
import { config, settings } from '$lib/stores';
import { createEventDispatcher, onMount, getContext } from 'svelte';
import { banners as _banners } from '$lib/stores';
import type { Banner } from '$lib/types';
import { getBaseModels } from '$lib/apis/models';
import { getBanners, setBanners } from '$lib/apis/configs';
import Tooltip from '$lib/components/common/Tooltip.svelte';
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 Banners from './Interface/Banners.svelte';
import PromptSuggestions from '$lib/components/workspace/Models/PromptSuggestions.svelte';
const dispatch = createEventDispatcher();
@@ -46,22 +33,10 @@
VOICE_MODE_PROMPT_TEMPLATE: ''
};
let promptSuggestions = [];
let banners: Banner[] = [];
const updateInterfaceHandler = async () => {
taskConfig = await updateTaskConfig(localStorage.token, taskConfig);
promptSuggestions = promptSuggestions.filter((p) => p.content !== '');
promptSuggestions = await setDefaultPromptSuggestions(localStorage.token, promptSuggestions);
await updateBanners();
await config.set(await getBackendConfig());
};
const updateBanners = async () => {
_banners.set(await setBanners(localStorage.token, banners));
};
let workspaceModels = null;
let baseModels = null;
@@ -70,8 +45,6 @@
const init = async () => {
taskConfig = await getTaskConfig(localStorage.token);
promptSuggestions = $config?.default_prompt_suggestions ?? [];
banners = await getBanners(localStorage.token);
workspaceModels = await getBaseModels(localStorage.token);
baseModels = await getModels(localStorage.token, null, false);
@@ -435,63 +408,6 @@
</Tooltip>
</div>
</div>
<div class="mb-3.5">
<div class=" mt-0.5 mb-2.5 text-base font-medium">{$i18n.t('UI')}</div>
<hr class=" border-gray-100/30 dark:border-gray-850/30 my-2" />
<div class="mb-2.5">
<div class="flex w-full justify-between">
<div class=" self-center text-xs">
{$i18n.t('Banners')}
</div>
<button
class="p-1 px-3 text-xs flex rounded-sm transition"
type="button"
on:click={() => {
if (banners.length === 0 || banners.at(-1).content !== '') {
banners = [
...banners,
{
id: uuidv4(),
type: '',
title: '',
content: '',
dismissible: true,
timestamp: Math.floor(Date.now() / 1000)
}
];
}
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"
/>
</svg>
</button>
</div>
<Banners bind:banners />
</div>
{#if $user?.role === 'admin'}
<PromptSuggestions bind:promptSuggestions />
{#if promptSuggestions.length > 0}
<div class="text-xs text-left w-full mt-2">
{$i18n.t('Adjusting these settings will apply changes universally to all users.')}
</div>
{/if}
{/if}
</div>
</div>
<div class="flex justify-end text-sm font-medium">

View File

@@ -537,8 +537,9 @@
className=" w-fit"
placement="top-start"
>
<div class="font-medium line-clamp-1 flex items-center gap-1.5">
<div class="font-medium line-clamp-1 flex items-center gap-2">
{model.name}
<Badge
type={(model?.access_grants ?? []).some(
(g) =>
@@ -559,7 +560,9 @@
/>
</div>
</Tooltip>
<div class=" text-xs overflow-hidden text-ellipsis line-clamp-1 text-gray-500">
<div
class=" text-xs overflow-hidden text-ellipsis line-clamp-1 flex items-center gap-1 text-gray-500"
>
<span class=" line-clamp-1">
{!!model?.meta?.description
? model?.meta?.description

View File

@@ -5,10 +5,11 @@
const i18n = getContext('i18n');
const dispatch = createEventDispatcher();
import { models } from '$lib/stores';
import { models, config as _config } from '$lib/stores';
import { DEFAULT_CAPABILITIES } from '$lib/constants';
import { deleteAllModels } from '$lib/apis/models';
import { getModelsConfig, setModelsConfig } from '$lib/apis/configs';
import { getModelsConfig, setModelsConfig, setDefaultPromptSuggestions } from '$lib/apis/configs';
import { getBackendConfig } from '$lib/apis';
import Modal from '$lib/components/common/Modal.svelte';
import ConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
@@ -27,6 +28,7 @@
import Capabilities from '$lib/components/workspace/Models/Capabilities.svelte';
import DefaultFeatures from '$lib/components/workspace/Models/DefaultFeatures.svelte';
import BuiltinTools from '$lib/components/workspace/Models/BuiltinTools.svelte';
import PromptSuggestions from '$lib/components/workspace/Models/PromptSuggestions.svelte';
import AdjustmentsHorizontal from '$lib/components/icons/AdjustmentsHorizontal.svelte';
import Eye from '$lib/components/icons/Eye.svelte';
@@ -53,11 +55,13 @@
let showResetModal = false;
let showDefaultCapabilities = false;
let showDefaultParams = false;
let showDefaultPromptSuggestions = false;
let defaultCapabilities = {};
let defaultFeatureIds = [];
let defaultParams = {};
let builtinTools = {};
let promptSuggestions = [];
$: if (show) {
init();
@@ -104,6 +108,8 @@
builtinTools = {};
}
defaultParams = config?.DEFAULT_MODEL_PARAMS ?? {};
promptSuggestions = $_config?.default_prompt_suggestions ?? [];
};
const submitHandler = async () => {
loading = true;
@@ -125,6 +131,10 @@
});
if (res) {
promptSuggestions = promptSuggestions.filter((p) => p.content !== '');
promptSuggestions = await setDefaultPromptSuggestions(localStorage.token, promptSuggestions);
await _config.set(await getBackendConfig());
toast.success($i18n.t('Models configuration saved successfully'));
initHandler();
show = false;
@@ -241,6 +251,43 @@
<hr class=" border-gray-50 dark:border-gray-800/10 my-2.5 w-full" />
<div>
<button
class="flex w-full justify-between items-center"
type="button"
on:click={() => {
showDefaultPromptSuggestions = !showDefaultPromptSuggestions;
}}
>
<div class="text-xs text-gray-500 font-medium">
{$i18n.t('Prompt Suggestions')}
</div>
<div>
{#if showDefaultPromptSuggestions}
<ChevronUp className="size-3" />
{:else}
<ChevronDown className="size-3" />
{/if}
</div>
</button>
{#if showDefaultPromptSuggestions}
<div class="mt-2">
<PromptSuggestions bind:promptSuggestions />
{#if promptSuggestions.length > 0}
<div class="text-xs text-left w-full mt-2 text-gray-500">
{$i18n.t(
'Adjusting these settings will apply changes universally to all users.'
)}
</div>
{/if}
</div>
{/if}
</div>
<hr class=" border-gray-50 dark:border-gray-800/10 my-2.5 w-full" />
<div>
<button
class="flex w-full justify-between items-center"
@@ -369,7 +416,6 @@
<ModelList bind:modelIds />
</div>
</div>
{/if}
</div>

View File

@@ -13,7 +13,7 @@
<div
class=" text-xs font-medium {classNames[type] ??
classNames['info']} w-fit px-1.5 py-[1px] rounded-lg uppercase line-clamp-1 mr-0.5"
classNames['info']} w-fit px-[5px] rounded uppercase line-clamp-1 mr-0.5"
>
{content}
</div>