diff --git a/src/lib/components/admin/Settings/Models.svelte b/src/lib/components/admin/Settings/Models.svelte index d107e09f70..5e7f74b3d1 100644 --- a/src/lib/components/admin/Settings/Models.svelte +++ b/src/lib/components/admin/Settings/Models.svelte @@ -40,6 +40,10 @@ import Eye from '$lib/components/icons/Eye.svelte'; import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants'; import { goto } from '$app/navigation'; + import { DropdownMenu } from 'bits-ui'; + import { flyAndScale } from '$lib/utils/transitions'; + import Dropdown from '$lib/components/common/Dropdown.svelte'; + import AdminViewSelector from './Models/AdminViewSelector.svelte'; let shiftKey = false; @@ -58,21 +62,43 @@ let showConfigModal = false; let showManageModal = false; + let viewOption = ''; // '' = All, 'enabled', 'disabled', 'visible', 'hidden' + $: if (models) { filteredModels = models .filter((m) => searchValue === '' || m.name.toLowerCase().includes(searchValue.toLowerCase())) + .filter((m) => { + if (viewOption === 'enabled') return m?.is_active ?? true; + if (viewOption === 'disabled') return !(m?.is_active ?? true); + if (viewOption === 'visible') return !(m?.meta?.hidden ?? false); + if (viewOption === 'hidden') return m?.meta?.hidden === true; + return true; // All + }) .sort((a, b) => { - // // Check if either model is inactive and push them to the bottom - // if ((a.is_active ?? true) !== (b.is_active ?? true)) { - // return (b.is_active ?? true) - (a.is_active ?? true); - // } - // If both models' active states are the same, sort alphabetically return (a?.name ?? a?.id ?? '').localeCompare(b?.name ?? b?.id ?? ''); }); } let searchValue = ''; + const enableAllHandler = async () => { + const modelsToEnable = filteredModels.filter((m) => !(m.is_active ?? true)); + // Optimistic UI update + modelsToEnable.forEach((m) => (m.is_active = true)); + models = models; + // Sync with server + await Promise.all(modelsToEnable.map((model) => toggleModelById(localStorage.token, model.id))); + }; + + const disableAllHandler = async () => { + const modelsToDisable = filteredModels.filter((m) => m.is_active ?? true); + // Optimistic UI update + modelsToDisable.forEach((m) => (m.is_active = false)); + models = models; + // Sync with server + await Promise.all(modelsToDisable.map((model) => toggleModelById(localStorage.token, model.id))); + }; + const downloadModels = async (models) => { let blob = new Blob([JSON.stringify(models)], { type: 'application/json' @@ -308,8 +334,12 @@ + -
+
+
@@ -333,156 +363,215 @@ {/if}
-
-
- {#if models.length > 0} - {#each filteredModels as model, modelIdx (`${model.id}-${modelIdx}`)} -
+
+
+ +
+ +
+ + + -
- {#if shiftKey} - + + +
+ + { + enableAllHandler(); + }} + > + +
{$i18n.t('Enable All')}
+
+ + { + disableAllHandler(); + }} + > + +
{$i18n.t('Disable All')}
+
+
+
+ +
+ +
+ {#if filteredModels.length > 0} + {#each filteredModels as model, modelIdx (`${model.id}-${modelIdx}`)} +
+ +
+ {#if shiftKey} + + + + {:else} - - {:else} - - { - exportModelHandler(model); - }} - hideHandler={() => { - hideModelHandler(model); - }} - pinModelHandler={() => { - pinModelHandler(model.id); - }} - copyLinkHandler={() => { - copyLinkHandler(model); - }} - cloneHandler={() => { - cloneHandler(model); - }} - onClose={() => {}} - > - - + + -
- - { - toggleModelHandler(model); - }} - /> - -
- {/if} +
+ + { + toggleModelHandler(model); + }} + /> + +
+ {/if} +
+
+ {/each} + {:else} +
+
+
😕
+
{$i18n.t('No models found')}
+
+ {$i18n.t('Try adjusting your search or filter to find what you are looking for.')} +
- {/each} - {:else} -
-
- {$i18n.t('No models found')} -
-
- {/if} + {/if} +
{#if $user?.role === 'admin'} diff --git a/src/lib/components/admin/Settings/Models/AdminViewSelector.svelte b/src/lib/components/admin/Settings/Models/AdminViewSelector.svelte new file mode 100644 index 0000000000..5778ba21ab --- /dev/null +++ b/src/lib/components/admin/Settings/Models/AdminViewSelector.svelte @@ -0,0 +1,63 @@ + + + item.value === value)} + {items} + onSelectedChange={(selectedItem) => { + value = selectedItem.value; + onChange(value); + }} +> + + + + + + + {#each items as item} + + {item.label} + + {#if value === item.value} +
+ +
+ {/if} +
+ {/each} +
+