mirror of
https://github.com/open-webui/open-webui
synced 2025-06-26 18:26:48 +00:00
Merge remote-tracking branch 'upstream/dev' into feat/oauth
This commit is contained in:
@@ -36,6 +36,9 @@
|
||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||
import { getBanners } from '$lib/apis/configs';
|
||||
import { getUserSettings } from '$lib/apis/users';
|
||||
import Help from '$lib/components/layout/Help.svelte';
|
||||
import AccountPending from '$lib/components/layout/Overlay/AccountPending.svelte';
|
||||
import { error } from '@sveltejs/kit';
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
@@ -73,7 +76,10 @@
|
||||
// IndexedDB Not Found
|
||||
}
|
||||
|
||||
const userSettings = await getUserSettings(localStorage.token);
|
||||
const userSettings = await getUserSettings(localStorage.token).catch((error) => {
|
||||
console.error(error);
|
||||
return null;
|
||||
});
|
||||
|
||||
if (userSettings) {
|
||||
await settings.set(userSettings.ui);
|
||||
@@ -160,7 +166,7 @@
|
||||
if (isCtrlPressed && event.key === '/') {
|
||||
event.preventDefault();
|
||||
console.log('showShortcuts');
|
||||
showShortcutsButtonElement.click();
|
||||
document.getElementById('show-shortcuts-button')?.click();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -175,69 +181,17 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class=" hidden lg:flex fixed bottom-0 right-0 px-2 py-2 z-10">
|
||||
<Tooltip content={$i18n.t('Help')} placement="left">
|
||||
<button
|
||||
id="show-shortcuts-button"
|
||||
bind:this={showShortcutsButtonElement}
|
||||
class="text-gray-600 dark:text-gray-300 bg-gray-300/20 size-5 flex items-center justify-center text-[0.7rem] rounded-full"
|
||||
on:click={() => {
|
||||
showShortcuts = !showShortcuts;
|
||||
}}
|
||||
>
|
||||
?
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<ShortcutsModal bind:show={showShortcuts} />
|
||||
<Help />
|
||||
<SettingsModal bind:show={$showSettings} />
|
||||
<ChangelogModal bind:show={$showChangelog} />
|
||||
|
||||
<div class="app relative">
|
||||
<div
|
||||
class=" text-gray-700 dark:text-gray-100 bg-white dark:bg-gray-900 min-h-screen overflow-auto flex flex-row"
|
||||
class=" text-gray-700 dark:text-gray-100 bg-white dark:bg-gray-900 h-screen max-h-[100dvh] overflow-auto flex flex-row"
|
||||
>
|
||||
{#if loaded}
|
||||
{#if !['user', 'admin'].includes($user.role)}
|
||||
<div class="fixed w-full h-full flex z-[999]">
|
||||
<div
|
||||
class="absolute w-full h-full backdrop-blur-lg bg-white/10 dark:bg-gray-900/50 flex justify-center"
|
||||
>
|
||||
<div class="m-auto pb-10 flex flex-col justify-center">
|
||||
<div class="max-w-md">
|
||||
<div class="text-center dark:text-white text-2xl font-medium z-50">
|
||||
Account Activation Pending<br /> Contact Admin for WebUI Access
|
||||
</div>
|
||||
|
||||
<div class=" mt-4 text-center text-sm dark:text-gray-200 w-full">
|
||||
Your account status is currently pending activation. To access the WebUI, please
|
||||
reach out to the administrator. Admins can manage user statuses from the Admin
|
||||
Panel.
|
||||
</div>
|
||||
|
||||
<div class=" mt-6 mx-auto relative group w-fit">
|
||||
<button
|
||||
class="relative z-20 flex px-5 py-2 rounded-full bg-white border border-gray-100 dark:border-none hover:bg-gray-100 text-gray-700 transition font-medium text-sm"
|
||||
on:click={async () => {
|
||||
location.href = '/';
|
||||
}}
|
||||
>
|
||||
{$i18n.t('Check Again')}
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="text-xs text-center w-full mt-2 text-gray-400 underline"
|
||||
on:click={async () => {
|
||||
localStorage.removeItem('token');
|
||||
location.href = '/auth';
|
||||
}}>{$i18n.t('Sign Out')}</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AccountPending />
|
||||
{:else if localDBChats.length > 0}
|
||||
<div class="fixed w-full h-full flex z-50">
|
||||
<div
|
||||
|
||||
@@ -303,6 +303,31 @@
|
||||
</svg>
|
||||
</button>
|
||||
</Tooltip>
|
||||
{:else}
|
||||
<Tooltip content={$i18n.t('Edit User')}>
|
||||
<button
|
||||
class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
|
||||
on:click={async () => {
|
||||
showEditUserModal = !showEditUserModal;
|
||||
selectedUser = user;
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="w-4 h-4"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</Tooltip>
|
||||
{/if}
|
||||
</div>
|
||||
</td>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
import AdvancedParams from '$lib/components/chat/Settings/Advanced/AdvancedParams.svelte';
|
||||
import Checkbox from '$lib/components/common/Checkbox.svelte';
|
||||
import Tags from '$lib/components/common/Tags.svelte';
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
@@ -56,6 +57,20 @@
|
||||
id = name.replace(/\s+/g, '-').toLowerCase();
|
||||
}
|
||||
|
||||
let baseModel = null;
|
||||
$: {
|
||||
baseModel = $models.find((m) => m.id === info.base_model_id);
|
||||
console.log(baseModel);
|
||||
if (baseModel) {
|
||||
if (baseModel.owned_by === 'openai') {
|
||||
capabilities.usage = baseModel.info?.meta?.capabilities?.usage ?? false;
|
||||
} else {
|
||||
delete capabilities.usage;
|
||||
}
|
||||
capabilities = capabilities;
|
||||
}
|
||||
}
|
||||
|
||||
const submitHandler = async () => {
|
||||
loading = true;
|
||||
|
||||
@@ -64,6 +79,12 @@
|
||||
info.meta.capabilities = capabilities;
|
||||
info.params.stop = params.stop ? params.stop.split(',').filter((s) => s.trim()) : null;
|
||||
|
||||
Object.keys(info.params).forEach((key) => {
|
||||
if (info.params[key] === '' || info.params[key] === null) {
|
||||
delete info.params[key];
|
||||
}
|
||||
});
|
||||
|
||||
if ($models.find((m) => m.id === info.id)) {
|
||||
toast.error(
|
||||
`Error: A model with the ID '${info.id}' already exists. Please select a different ID to proceed.`
|
||||
@@ -87,9 +108,9 @@
|
||||
});
|
||||
|
||||
if (res) {
|
||||
await models.set(await getModels(localStorage.token));
|
||||
toast.success('Model created successfully!');
|
||||
await goto('/workspace/models');
|
||||
await models.set(await getModels(localStorage.token));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,13 +138,9 @@
|
||||
onMount(async () => {
|
||||
window.addEventListener('message', async (event) => {
|
||||
if (
|
||||
![
|
||||
'https://ollamahub.com',
|
||||
'https://www.ollamahub.com',
|
||||
'https://openwebui.com',
|
||||
'https://www.openwebui.com',
|
||||
'http://localhost:5173'
|
||||
].includes(event.origin)
|
||||
!['https://openwebui.com', 'https://www.openwebui.com', 'http://localhost:5173'].includes(
|
||||
event.origin
|
||||
)
|
||||
)
|
||||
return;
|
||||
|
||||
@@ -248,7 +265,7 @@
|
||||
<button
|
||||
class=" {info.meta.profile_image_url
|
||||
? ''
|
||||
: 'p-6'} rounded-full dark:bg-gray-700 border border-dashed border-gray-200"
|
||||
: 'p-4'} rounded-full dark:bg-gray-700 border border-dashed border-gray-200 flex items-center"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
filesInputElement.click();
|
||||
@@ -258,7 +275,7 @@
|
||||
<img
|
||||
src={info.meta.profile_image_url}
|
||||
alt="modelfile profile"
|
||||
class=" rounded-full w-20 h-20 object-cover"
|
||||
class=" rounded-full size-16 object-cover"
|
||||
/>
|
||||
{:else}
|
||||
<svg
|
||||
@@ -324,18 +341,40 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-2">
|
||||
<div class=" text-sm font-semibold mb-2">{$i18n.t('Description')}</div>
|
||||
<div class="my-1">
|
||||
<div class="flex w-full justify-between items-center mb-1">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('Description')}</div>
|
||||
|
||||
<div>
|
||||
<button
|
||||
class="p-1 text-xs flex rounded transition"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
if (info.meta.description === null) {
|
||||
info.meta.description = '';
|
||||
} else {
|
||||
info.meta.description = null;
|
||||
}
|
||||
}}
|
||||
>
|
||||
{#if info.meta.description === null}
|
||||
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
|
||||
{:else}
|
||||
<span class="ml-2 self-center">{$i18n.t('Custom')}</span>
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if info.meta.description !== null}
|
||||
<input
|
||||
class="px-3 py-1.5 text-sm w-full bg-transparent border dark:border-gray-600 outline-none rounded-lg"
|
||||
placeholder={$i18n.t('Add a short description about what this model does')}
|
||||
bind:value={info.meta.description}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<hr class=" dark:border-gray-850 my-1" />
|
||||
|
||||
<div class="my-2">
|
||||
<div class="flex w-full justify-between">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('Model Params')}</div>
|
||||
@@ -387,7 +426,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-2">
|
||||
<hr class=" dark:border-gray-850 my-1" />
|
||||
|
||||
<div class="my-1">
|
||||
<div class="flex w-full justify-between items-center">
|
||||
<div class="flex w-full justify-between items-center">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('Prompt suggestions')}</div>
|
||||
@@ -477,8 +518,8 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="my-2">
|
||||
<div class="flex w-full justify-between">
|
||||
<div class="my-1">
|
||||
<div class="flex w-full justify-between mb-1">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('Capabilities')}</div>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
@@ -491,7 +532,7 @@
|
||||
}}
|
||||
/>
|
||||
|
||||
<div class=" py-1.5 text-sm w-full capitalize">
|
||||
<div class=" py-0.5 text-sm w-full capitalize">
|
||||
{$i18n.t(capability)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -499,7 +540,30 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-2 text-gray-500">
|
||||
<div class="my-1">
|
||||
<div class="flex w-full justify-between items-center">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('Tags')}</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-2">
|
||||
<Tags
|
||||
tags={info?.meta?.tags ?? []}
|
||||
deleteTag={(tagName) => {
|
||||
info.meta.tags = info.meta.tags.filter((tag) => tag.name !== tagName);
|
||||
}}
|
||||
addTag={(tagName) => {
|
||||
console.log(tagName);
|
||||
if (!(info?.meta?.tags ?? null)) {
|
||||
info.meta.tags = [{ name: tagName }];
|
||||
} else {
|
||||
info.meta.tags = [...info.meta.tags, { name: tagName }];
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-2 text-gray-300 dark:text-gray-700">
|
||||
<div class="flex w-full justify-between mb-2">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('JSON Preview')}</div>
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
import AdvancedParams from '$lib/components/chat/Settings/Advanced/AdvancedParams.svelte';
|
||||
import { getModels } from '$lib/apis';
|
||||
import Checkbox from '$lib/components/common/Checkbox.svelte';
|
||||
import Tags from '$lib/components/common/Tags.svelte';
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
@@ -44,7 +45,8 @@
|
||||
meta: {
|
||||
profile_image_url: '/favicon.png',
|
||||
description: '',
|
||||
suggestion_prompts: null
|
||||
suggestion_prompts: null,
|
||||
tags: []
|
||||
},
|
||||
params: {
|
||||
system: ''
|
||||
@@ -65,12 +67,18 @@
|
||||
info.meta.capabilities = capabilities;
|
||||
info.params.stop = params.stop ? params.stop.split(',').filter((s) => s.trim()) : null;
|
||||
|
||||
Object.keys(info.params).forEach((key) => {
|
||||
if (info.params[key] === '' || info.params[key] === null) {
|
||||
delete info.params[key];
|
||||
}
|
||||
});
|
||||
|
||||
const res = await updateModelById(localStorage.token, info.id, info);
|
||||
|
||||
if (res) {
|
||||
await models.set(await getModels(localStorage.token));
|
||||
toast.success('Model updated successfully');
|
||||
await goto('/workspace/models');
|
||||
await models.set(await getModels(localStorage.token));
|
||||
}
|
||||
|
||||
loading = false;
|
||||
@@ -105,7 +113,15 @@
|
||||
}
|
||||
|
||||
params = { ...params, ...model?.info?.params };
|
||||
params.stop = params?.stop ? (params?.stop ?? []).join(',') : null;
|
||||
params.stop = params?.stop
|
||||
? (typeof params.stop === 'string' ? params.stop.split(',') : params?.stop ?? []).join(
|
||||
','
|
||||
)
|
||||
: null;
|
||||
|
||||
if (model?.owned_by === 'openai') {
|
||||
capabilities.usage = false;
|
||||
}
|
||||
|
||||
if (model?.info?.meta?.capabilities) {
|
||||
capabilities = { ...capabilities, ...model?.info?.meta?.capabilities };
|
||||
@@ -219,26 +235,26 @@
|
||||
<div class="flex justify-center my-4">
|
||||
<div class="self-center">
|
||||
<button
|
||||
class=" {info?.meta?.profile_image_url
|
||||
class=" {info.meta.profile_image_url
|
||||
? ''
|
||||
: 'p-6'} rounded-full dark:bg-gray-700 border border-dashed border-gray-200"
|
||||
: 'p-4'} rounded-full dark:bg-gray-700 border border-dashed border-gray-200 flex items-center"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
filesInputElement.click();
|
||||
}}
|
||||
>
|
||||
{#if info?.meta?.profile_image_url}
|
||||
{#if info.meta.profile_image_url}
|
||||
<img
|
||||
src={info?.meta?.profile_image_url}
|
||||
src={info.meta.profile_image_url}
|
||||
alt="modelfile profile"
|
||||
class=" rounded-full w-20 h-20 object-cover"
|
||||
class=" rounded-full size-16 object-cover"
|
||||
/>
|
||||
{:else}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
class="w-8"
|
||||
class="size-8"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
@@ -251,9 +267,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-2 flex space-x-2">
|
||||
<div class="mt-2 my-1 flex space-x-2">
|
||||
<div class="flex-1">
|
||||
<div class=" text-sm font-semibold mb-2">{$i18n.t('Name')}*</div>
|
||||
<div class=" text-sm font-semibold mb-1">{$i18n.t('Name')}*</div>
|
||||
|
||||
<div>
|
||||
<input
|
||||
@@ -266,7 +282,7 @@
|
||||
</div>
|
||||
|
||||
<div class="flex-1">
|
||||
<div class=" text-sm font-semibold mb-2">{$i18n.t('Model ID')}*</div>
|
||||
<div class=" text-sm font-semibold mb-1">{$i18n.t('Model ID')}*</div>
|
||||
|
||||
<div>
|
||||
<input
|
||||
@@ -281,8 +297,8 @@
|
||||
</div>
|
||||
|
||||
{#if model.preset}
|
||||
<div class="my-2">
|
||||
<div class=" text-sm font-semibold mb-2">{$i18n.t('Base Model (From)')}</div>
|
||||
<div class="my-1">
|
||||
<div class=" text-sm font-semibold mb-1">{$i18n.t('Base Model (From)')}</div>
|
||||
|
||||
<div>
|
||||
<select
|
||||
@@ -300,18 +316,40 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="my-2">
|
||||
<div class=" text-sm font-semibold mb-2">{$i18n.t('Description')}</div>
|
||||
<div class="my-1">
|
||||
<div class="flex w-full justify-between items-center">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('Description')}</div>
|
||||
|
||||
<div>
|
||||
<button
|
||||
class="p-1 text-xs flex rounded transition"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
if (info.meta.description === null) {
|
||||
info.meta.description = '';
|
||||
} else {
|
||||
info.meta.description = null;
|
||||
}
|
||||
}}
|
||||
>
|
||||
{#if info.meta.description === null}
|
||||
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
|
||||
{:else}
|
||||
<span class="ml-2 self-center">{$i18n.t('Custom')}</span>
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if info.meta.description !== null}
|
||||
<input
|
||||
class="px-3 py-1.5 text-sm w-full bg-transparent border dark:border-gray-600 outline-none rounded-lg"
|
||||
class="mt-1 px-3 py-1.5 text-sm w-full bg-transparent border dark:border-gray-600 outline-none rounded-lg"
|
||||
placeholder={$i18n.t('Add a short description about what this model does')}
|
||||
bind:value={info.meta.description}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<hr class=" dark:border-gray-850 my-1" />
|
||||
|
||||
<div class="my-2">
|
||||
<div class="flex w-full justify-between">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('Model Params')}</div>
|
||||
@@ -365,7 +403,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-2">
|
||||
<hr class=" dark:border-gray-850 my-1" />
|
||||
|
||||
<div class="my-1">
|
||||
<div class="flex w-full justify-between items-center">
|
||||
<div class="flex w-full justify-between items-center">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('Prompt suggestions')}</div>
|
||||
@@ -455,8 +495,8 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="my-2">
|
||||
<div class="flex w-full justify-between">
|
||||
<div class="my-1">
|
||||
<div class="flex w-full justify-between mb-1">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('Capabilities')}</div>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
@@ -469,7 +509,7 @@
|
||||
}}
|
||||
/>
|
||||
|
||||
<div class=" py-1.5 text-sm w-full capitalize">
|
||||
<div class=" py-0.5 text-sm w-full capitalize">
|
||||
{$i18n.t(capability)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -477,7 +517,30 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-2 text-gray-500">
|
||||
<div class="my-1">
|
||||
<div class="flex w-full justify-between items-center">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('Tags')}</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-2">
|
||||
<Tags
|
||||
tags={info?.meta?.tags ?? []}
|
||||
deleteTag={(tagName) => {
|
||||
info.meta.tags = info.meta.tags.filter((tag) => tag.name !== tagName);
|
||||
}}
|
||||
addTag={(tagName) => {
|
||||
console.log(tagName);
|
||||
if (!(info?.meta?.tags ?? null)) {
|
||||
info.meta.tags = [{ name: tagName }];
|
||||
} else {
|
||||
info.meta.tags = [...info.meta.tags, { name: tagName }];
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-2 text-gray-300 dark:text-gray-700">
|
||||
<div class="flex w-full justify-between mb-2">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('JSON Preview')}</div>
|
||||
|
||||
|
||||
@@ -57,13 +57,9 @@
|
||||
onMount(async () => {
|
||||
window.addEventListener('message', async (event) => {
|
||||
if (
|
||||
![
|
||||
'https://ollamahub.com',
|
||||
'https://www.ollamahub.com',
|
||||
'https://openwebui.com',
|
||||
'https://www.openwebui.com',
|
||||
'http://localhost:5173'
|
||||
].includes(event.origin)
|
||||
!['https://openwebui.com', 'https://www.openwebui.com', 'http://localhost:5173'].includes(
|
||||
event.origin
|
||||
)
|
||||
)
|
||||
return;
|
||||
const prompt = JSON.parse(event.data);
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
<script>
|
||||
import { io } from 'socket.io-client';
|
||||
|
||||
import { onMount, tick, setContext } from 'svelte';
|
||||
import { config, user, theme, WEBUI_NAME, mobile } from '$lib/stores';
|
||||
import {
|
||||
config,
|
||||
user,
|
||||
theme,
|
||||
WEBUI_NAME,
|
||||
mobile,
|
||||
socket,
|
||||
activeUserCount,
|
||||
USAGE_POOL
|
||||
} from '$lib/stores';
|
||||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { Toaster, toast } from 'svelte-sonner';
|
||||
@@ -13,7 +24,7 @@
|
||||
|
||||
import 'tippy.js/dist/tippy.css';
|
||||
|
||||
import { WEBUI_BASE_URL } from '$lib/constants';
|
||||
import { WEBUI_BASE_URL, WEBUI_HOSTNAME } from '$lib/constants';
|
||||
import i18n, { initI18n, getLanguages } from '$lib/i18n';
|
||||
|
||||
setContext('i18n', i18n);
|
||||
@@ -56,10 +67,30 @@
|
||||
if (backendConfig) {
|
||||
// Save Backend Status to Store
|
||||
await config.set(backendConfig);
|
||||
|
||||
await WEBUI_NAME.set(backendConfig.name);
|
||||
|
||||
if ($config) {
|
||||
const _socket = io(`${WEBUI_BASE_URL}`, {
|
||||
path: '/ws/socket.io',
|
||||
auth: { token: localStorage.token }
|
||||
});
|
||||
|
||||
_socket.on('connect', () => {
|
||||
console.log('connected');
|
||||
});
|
||||
|
||||
await socket.set(_socket);
|
||||
|
||||
_socket.on('user-count', (data) => {
|
||||
console.log('user-count', data);
|
||||
activeUserCount.set(data.count);
|
||||
});
|
||||
|
||||
_socket.on('usage', (data) => {
|
||||
console.log('usage', data);
|
||||
USAGE_POOL.set(data['models']);
|
||||
});
|
||||
|
||||
if (localStorage.token) {
|
||||
// Get Session User Info
|
||||
const sessionUser = await getSessionUser(localStorage.token).catch((error) => {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { getSessionUser, userSignIn, userSignUp } from '$lib/apis/auths';
|
||||
import Spinner from '$lib/components/common/Spinner.svelte';
|
||||
import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
|
||||
import { WEBUI_NAME, config, user } from '$lib/stores';
|
||||
import { WEBUI_NAME, config, user, socket } from '$lib/stores';
|
||||
import { onMount, getContext } from 'svelte';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import { generateInitialsImage, canvasPixelTest } from '$lib/utils';
|
||||
@@ -25,6 +25,8 @@
|
||||
if (sessionUser.token) {
|
||||
localStorage.token = sessionUser.token;
|
||||
}
|
||||
|
||||
$socket.emit('user-join', { auth: { token: sessionUser.token } });
|
||||
await user.set(sessionUser);
|
||||
goto('/');
|
||||
}
|
||||
@@ -246,7 +248,7 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{#if Object.keys($config?.oauth?.providers ?? {}).length > 0 }
|
||||
{#if Object.keys($config?.oauth?.providers ?? {}).length > 0}
|
||||
<div class="inline-flex items-center justify-center w-full">
|
||||
<hr class="w-64 h-px my-8 bg-gray-200 border-0 dark:bg-gray-700" />
|
||||
<span
|
||||
@@ -255,7 +257,7 @@
|
||||
>
|
||||
</div>
|
||||
<div class="flex flex-col space-y-2">
|
||||
{#if $config?.oauth?.providers?.google }
|
||||
{#if $config?.oauth?.providers?.google}
|
||||
<button
|
||||
class="flex items-center px-6 border-2 dark:border-gray-800 duration-300 dark:bg-gray-900 hover:bg-gray-100 dark:hover:bg-gray-800 w-full rounded-2xl dark:text-white text-sm py-3 transition"
|
||||
on:click={() => {
|
||||
@@ -280,7 +282,7 @@
|
||||
<span>{$i18n.t('Continue with {{provider}}', { provider: 'Google' })}</span>
|
||||
</button>
|
||||
{/if}
|
||||
{#if $config?.oauth?.providers?.microsoft }
|
||||
{#if $config?.oauth?.providers?.microsoft}
|
||||
<button
|
||||
class="flex items-center px-6 border-2 dark:border-gray-800 duration-300 dark:bg-gray-900 hover:bg-gray-100 dark:hover:bg-gray-800 w-full rounded-2xl dark:text-white text-sm py-3 transition"
|
||||
on:click={() => {
|
||||
@@ -305,7 +307,7 @@
|
||||
<span>{$i18n.t('Continue with {{provider}}', { provider: 'Microsoft' })}</span>
|
||||
</button>
|
||||
{/if}
|
||||
{#if $config?.oauth?.providers?.oidc }
|
||||
{#if $config?.oauth?.providers?.oidc}
|
||||
<button
|
||||
class="flex items-center px-6 border-2 dark:border-gray-800 duration-300 dark:bg-gray-900 hover:bg-gray-100 dark:hover:bg-gray-800 w-full rounded-2xl dark:text-white text-sm py-3 transition"
|
||||
on:click={() => {
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
onMount(async () => {
|
||||
window.addEventListener('message', async (event) => {
|
||||
if (
|
||||
![
|
||||
'https://ollamahub.com',
|
||||
'https://www.ollamahub.com',
|
||||
'https://openwebui.com',
|
||||
'https://www.openwebui.com',
|
||||
'http://localhost:5173'
|
||||
].includes(event.origin)
|
||||
)
|
||||
return;
|
||||
const prompts = JSON.parse(event.data);
|
||||
sessionStorage.modelfile = JSON.stringify(prompts);
|
||||
|
||||
goto('/workspace/prompts/create');
|
||||
});
|
||||
|
||||
if (window.opener ?? false) {
|
||||
window.opener.postMessage('loaded', '*');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user