refac
This commit is contained in:
@@ -119,7 +119,11 @@ async def _verify_knowledge_file_access(
|
||||
PAGE_ITEM_COUNT = 30
|
||||
|
||||
|
||||
@router.get('/list', response_model=ModelAccessListResponse) # do NOT use "/" as path, conflicts with main.py
|
||||
@router.get(
|
||||
'/list',
|
||||
response_model=ModelAccessListResponse,
|
||||
response_model_exclude={'items': {'__all__': {'meta': {'profile_image_url'}}}},
|
||||
) # do NOT use "/" as path, conflicts with main.py
|
||||
async def get_models(
|
||||
query: str | None = None,
|
||||
view_option: str | None = None,
|
||||
@@ -415,7 +419,10 @@ async def import_models(
|
||||
continue
|
||||
|
||||
# Update existing model
|
||||
model_data['meta'] = model_data.get('meta', {})
|
||||
model_data['meta'] = {
|
||||
**existing_model.meta.model_dump(),
|
||||
**(model_data.get('meta') or {}),
|
||||
}
|
||||
model_data['params'] = model_data.get('params', {})
|
||||
|
||||
updated_model = ModelForm(**{**existing_model.model_dump(), **model_data})
|
||||
|
||||
@@ -7,12 +7,13 @@
|
||||
import { onMount, onDestroy, getContext, tick } from 'svelte';
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
import { config, models as _models, settings, user } from '$lib/stores';
|
||||
import { config, models as _models, settings, showSettings, user } from '$lib/stores';
|
||||
import {
|
||||
createNewModel,
|
||||
deleteAllModels,
|
||||
getBaseModelTags,
|
||||
getBaseModels,
|
||||
getModelById,
|
||||
toggleModelById,
|
||||
updateModelById,
|
||||
updateModelAccessGrants,
|
||||
@@ -228,6 +229,7 @@
|
||||
};
|
||||
|
||||
const downloadModels = async (models) => {
|
||||
models = await Promise.all(models.map(getFullModel));
|
||||
let blob = new Blob([JSON.stringify(models)], {
|
||||
type: 'application/json'
|
||||
});
|
||||
@@ -483,22 +485,30 @@
|
||||
};
|
||||
|
||||
const hideModelHandler = async (model) => {
|
||||
model.meta = {
|
||||
...model.meta,
|
||||
hidden: !(model?.meta?.hidden ?? false)
|
||||
const updatedModel = {
|
||||
...model,
|
||||
meta: {
|
||||
...model.meta,
|
||||
hidden: !(model?.meta?.hidden ?? false)
|
||||
}
|
||||
};
|
||||
|
||||
console.debug(model);
|
||||
|
||||
upsertModelHandler(model, { meta: model.meta }, false);
|
||||
await upsertModelHandler(updatedModel, { meta: updatedModel.meta }, false);
|
||||
models = models.map((model) => (model.id === updatedModel.id ? updatedModel : model));
|
||||
_models.set(
|
||||
await getModels(
|
||||
localStorage.token,
|
||||
$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
|
||||
)
|
||||
);
|
||||
|
||||
toast.success(
|
||||
model.meta.hidden
|
||||
updatedModel.meta.hidden
|
||||
? $i18n.t(`Model {{name}} is now hidden`, {
|
||||
name: model.id
|
||||
name: updatedModel.id
|
||||
})
|
||||
: $i18n.t(`Model {{name}} is now visible`, {
|
||||
name: model.id
|
||||
name: updatedModel.id
|
||||
})
|
||||
);
|
||||
};
|
||||
@@ -551,17 +561,25 @@
|
||||
}
|
||||
};
|
||||
|
||||
const getFullModel = async (model) =>
|
||||
workspaceModels.some((workspaceModel) => workspaceModel.id === model.id)
|
||||
? ((await getModelById(localStorage.token, model.id).catch(() => null)) ?? model)
|
||||
: model;
|
||||
|
||||
const cloneHandler = async (model) => {
|
||||
model = await getFullModel(model);
|
||||
sessionStorage.model = JSON.stringify({
|
||||
...model,
|
||||
base_model_id: model.id,
|
||||
id: `${model.id}-clone`,
|
||||
name: `${model.name} (Clone)`
|
||||
});
|
||||
goto('/workspace/models/create');
|
||||
showSettings.set(false);
|
||||
await goto('/workspace/models/create');
|
||||
};
|
||||
|
||||
const exportModelHandler = async (model) => {
|
||||
model = await getFullModel(model);
|
||||
let blob = new Blob([JSON.stringify([model])], {
|
||||
type: 'application/json'
|
||||
});
|
||||
|
||||
@@ -41,6 +41,11 @@
|
||||
|
||||
let show = false;
|
||||
|
||||
const runAndClose = async (handler: Function) => {
|
||||
show = false;
|
||||
await handler();
|
||||
};
|
||||
|
||||
const isPublicModel = (model) =>
|
||||
(model?.access_grants ?? []).some(
|
||||
(g) => g.principal_type === 'user' && g.principal_id === '*' && g.permission === 'read'
|
||||
@@ -63,9 +68,7 @@
|
||||
<DropdownMenu className="min-w-[170px]">
|
||||
<button
|
||||
class="select-none flex w-full gap-2 items-center h-[1.6875rem] px-2 text-[13px] font-normal cursor-pointer hover:bg-gray-50/40 dark:hover:bg-gray-800/40 rounded-xl"
|
||||
on:click={() => {
|
||||
hideHandler();
|
||||
}}
|
||||
on:click={() => runAndClose(hideHandler)}
|
||||
>
|
||||
{#if model?.meta?.hidden ?? false}
|
||||
<svg
|
||||
@@ -115,10 +118,7 @@
|
||||
|
||||
<button
|
||||
class="select-none flex w-full gap-2 items-center h-[1.6875rem] px-2 text-[13px] font-normal cursor-pointer hover:bg-gray-50/40 dark:hover:bg-gray-800/40 rounded-xl"
|
||||
on:click={async () => {
|
||||
show = false;
|
||||
await defaultSelectedHandler();
|
||||
}}
|
||||
on:click={() => runAndClose(defaultSelectedHandler)}
|
||||
>
|
||||
<Check className="size-3.5" />
|
||||
|
||||
@@ -133,10 +133,7 @@
|
||||
|
||||
<button
|
||||
class="select-none flex w-full gap-2 items-center h-[1.6875rem] px-2 text-[13px] font-normal cursor-pointer hover:bg-gray-50/40 dark:hover:bg-gray-800/40 rounded-xl"
|
||||
on:click={async () => {
|
||||
show = false;
|
||||
await defaultPinnedHandler();
|
||||
}}
|
||||
on:click={() => runAndClose(defaultPinnedHandler)}
|
||||
>
|
||||
{#if isDefaultPinned}
|
||||
<PinSlash className="size-3.5" />
|
||||
@@ -155,9 +152,7 @@
|
||||
|
||||
<button
|
||||
class="select-none flex w-full gap-2 items-center h-[1.6875rem] px-2 text-[13px] font-normal cursor-pointer hover:bg-gray-50/40 dark:hover:bg-gray-800/40 rounded-xl"
|
||||
on:click={() => {
|
||||
privacyHandler();
|
||||
}}
|
||||
on:click={() => runAndClose(privacyHandler)}
|
||||
>
|
||||
{#if isPublicModel(model)}
|
||||
<LockClosed className="size-3.5" />
|
||||
@@ -176,9 +171,7 @@
|
||||
|
||||
<button
|
||||
class="select-none flex w-full gap-2 items-center h-[1.6875rem] px-2 text-[13px] font-normal cursor-pointer hover:bg-gray-50/40 dark:hover:bg-gray-800/40 rounded-xl"
|
||||
on:click={() => {
|
||||
pinModelHandler(model?.id);
|
||||
}}
|
||||
on:click={() => runAndClose(() => pinModelHandler(model?.id))}
|
||||
>
|
||||
{#if ($settings?.pinnedModels ?? []).includes(model?.id)}
|
||||
<PinSlash />
|
||||
@@ -197,9 +190,7 @@
|
||||
|
||||
<button
|
||||
class="select-none flex w-full gap-2 items-center h-[1.6875rem] px-2 text-[13px] font-normal cursor-pointer hover:bg-gray-50/40 dark:hover:bg-gray-800/40 rounded-xl"
|
||||
on:click={() => {
|
||||
copyLinkHandler();
|
||||
}}
|
||||
on:click={() => runAndClose(copyLinkHandler)}
|
||||
>
|
||||
<Link />
|
||||
|
||||
@@ -209,9 +200,7 @@
|
||||
{#if model?.is_active ?? true}
|
||||
<button
|
||||
class="select-none flex w-full gap-2 items-center h-[1.6875rem] px-2 text-[13px] font-normal cursor-pointer hover:bg-gray-50/40 dark:hover:bg-gray-800/40 rounded-xl"
|
||||
on:click={() => {
|
||||
cloneHandler();
|
||||
}}
|
||||
on:click={() => runAndClose(cloneHandler)}
|
||||
>
|
||||
<DocumentDuplicate />
|
||||
|
||||
@@ -221,9 +210,7 @@
|
||||
|
||||
<button
|
||||
class="select-none flex w-full gap-2 items-center h-[1.6875rem] px-2 text-[13px] font-normal cursor-pointer hover:bg-gray-50/40 dark:hover:bg-gray-800/40 rounded-xl"
|
||||
on:click={() => {
|
||||
exportHandler();
|
||||
}}
|
||||
on:click={() => runAndClose(exportHandler)}
|
||||
>
|
||||
<Download />
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
import {
|
||||
createNewModel,
|
||||
deleteModelById,
|
||||
getModelById,
|
||||
getModelItems as getWorkspaceModels,
|
||||
getModelTags,
|
||||
toggleModelById,
|
||||
@@ -196,7 +197,11 @@
|
||||
);
|
||||
};
|
||||
|
||||
const getFullModel = async (model) =>
|
||||
(await getModelById(localStorage.token, model.id).catch(() => null)) ?? model;
|
||||
|
||||
const cloneModelHandler = async (model) => {
|
||||
model = await getFullModel(model);
|
||||
sessionStorage.model = JSON.stringify({
|
||||
...model,
|
||||
id: `${model.id}-clone`,
|
||||
@@ -209,13 +214,14 @@
|
||||
toast.success($i18n.t('Redirecting you to Open WebUI Community'));
|
||||
|
||||
const url = 'https://openwebui.com';
|
||||
const fullModel = getFullModel(model);
|
||||
|
||||
const tab = await window.open(`${url}/post?type=model`, '_blank');
|
||||
|
||||
const messageHandler = (event) => {
|
||||
const messageHandler = async (event) => {
|
||||
if (event.origin !== url) return;
|
||||
if (event.data === 'loaded') {
|
||||
tab.postMessage(JSON.stringify(model), '*');
|
||||
tab.postMessage(JSON.stringify(await fullModel), '*');
|
||||
window.removeEventListener('message', messageHandler);
|
||||
}
|
||||
};
|
||||
@@ -224,25 +230,27 @@
|
||||
};
|
||||
|
||||
const hideModelHandler = async (model) => {
|
||||
model.meta = {
|
||||
...model.meta,
|
||||
hidden: !(model?.meta?.hidden ?? false)
|
||||
const updatedModel = {
|
||||
...model,
|
||||
meta: {
|
||||
...model.meta,
|
||||
hidden: !(model?.meta?.hidden ?? false)
|
||||
}
|
||||
};
|
||||
|
||||
console.log(model);
|
||||
|
||||
const res = await updateModelById(localStorage.token, model.id, model);
|
||||
const res = await updateModelById(localStorage.token, updatedModel.id, updatedModel);
|
||||
|
||||
if (res) {
|
||||
models = models.map((model) => (model.id === updatedModel.id ? updatedModel : model));
|
||||
toast.success(
|
||||
$i18n.t(`Model {{name}} is now {{status}}`, {
|
||||
name: model.id,
|
||||
status: model.meta.hidden ? 'hidden' : 'visible'
|
||||
name: updatedModel.id,
|
||||
status: updatedModel.meta.hidden ? 'hidden' : 'visible'
|
||||
})
|
||||
);
|
||||
|
||||
page = 1;
|
||||
getModelList();
|
||||
await getModelList();
|
||||
}
|
||||
|
||||
await _models.set(
|
||||
@@ -265,6 +273,7 @@
|
||||
};
|
||||
|
||||
const downloadModels = async (models) => {
|
||||
models = await Promise.all(models.map(getFullModel));
|
||||
let blob = new Blob([JSON.stringify(models)], {
|
||||
type: 'application/json'
|
||||
});
|
||||
@@ -272,6 +281,7 @@
|
||||
};
|
||||
|
||||
const exportModelHandler = async (model) => {
|
||||
model = await getFullModel(model);
|
||||
let blob = new Blob([JSON.stringify([model])], {
|
||||
type: 'application/json'
|
||||
});
|
||||
|
||||
@@ -37,6 +37,11 @@
|
||||
export let writeAccess: boolean = true;
|
||||
|
||||
let show = false;
|
||||
|
||||
const runAndClose = async (handler: Function) => {
|
||||
show = false;
|
||||
await handler();
|
||||
};
|
||||
</script>
|
||||
|
||||
<Dropdown
|
||||
@@ -63,9 +68,7 @@
|
||||
{#if writeAccess}
|
||||
<button
|
||||
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||
on:click={() => {
|
||||
editHandler();
|
||||
}}
|
||||
on:click={() => runAndClose(editHandler)}
|
||||
>
|
||||
<Pencil />
|
||||
<div class="flex items-center">{$i18n.t('Edit')}</div>
|
||||
@@ -75,9 +78,7 @@
|
||||
{#if writeAccess}
|
||||
<button
|
||||
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||
on:click={() => {
|
||||
hideHandler();
|
||||
}}
|
||||
on:click={() => runAndClose(hideHandler)}
|
||||
>
|
||||
{#if model?.meta?.hidden ?? false}
|
||||
<svg
|
||||
@@ -128,9 +129,7 @@
|
||||
|
||||
<button
|
||||
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||
on:click={() => {
|
||||
pinModelHandler(model?.id);
|
||||
}}
|
||||
on:click={() => runAndClose(() => pinModelHandler(model?.id))}
|
||||
>
|
||||
{#if ($settings?.pinnedModels ?? []).includes(model?.id)}
|
||||
<PinSlash />
|
||||
@@ -150,9 +149,7 @@
|
||||
{#if writeAccess}
|
||||
<button
|
||||
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||
on:click={() => {
|
||||
cloneHandler();
|
||||
}}
|
||||
on:click={() => runAndClose(cloneHandler)}
|
||||
>
|
||||
<DocumentDuplicate />
|
||||
|
||||
@@ -166,9 +163,7 @@
|
||||
|
||||
<button
|
||||
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||
on:click={() => {
|
||||
copyLinkHandler();
|
||||
}}
|
||||
on:click={() => runAndClose(copyLinkHandler)}
|
||||
>
|
||||
<Link />
|
||||
|
||||
@@ -178,9 +173,7 @@
|
||||
{#if writeAccess && ($currentUser?.role === 'admin' || $currentUser?.permissions?.workspace?.models_export)}
|
||||
<button
|
||||
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||
on:click={() => {
|
||||
exportHandler();
|
||||
}}
|
||||
on:click={() => runAndClose(exportHandler)}
|
||||
>
|
||||
<Download />
|
||||
|
||||
@@ -191,9 +184,7 @@
|
||||
{#if writeAccess && $config?.features.enable_community_sharing}
|
||||
<button
|
||||
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||
on:click={() => {
|
||||
shareHandler();
|
||||
}}
|
||||
on:click={() => runAndClose(shareHandler)}
|
||||
>
|
||||
<Share />
|
||||
<div class="flex items-center">{$i18n.t('Share')}</div>
|
||||
@@ -205,9 +196,7 @@
|
||||
|
||||
<button
|
||||
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||
on:click={() => {
|
||||
deleteHandler();
|
||||
}}
|
||||
on:click={() => runAndClose(deleteHandler)}
|
||||
>
|
||||
<GarbageBin />
|
||||
<div class="flex items-center">{$i18n.t('Delete')}</div>
|
||||
|
||||
Reference in New Issue
Block a user