This commit is contained in:
Timothy Jaeryang Baek
2026-07-14 01:34:41 -04:00
parent a9617ca218
commit 34813573fa
34 changed files with 554 additions and 652 deletions
+40 -43
View File
@@ -29,6 +29,7 @@
import Tooltip from '../common/Tooltip.svelte';
import XMark from '../icons/XMark.svelte';
import ViewSelector from './common/ViewSelector.svelte';
import TagSelector from './common/TagSelector.svelte';
import Loader from '../common/Loader.svelte';
type KnowledgeListItem = {
@@ -187,7 +188,7 @@
}}
/>
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-3">
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-2">
<div class="flex justify-between items-center">
<div class="flex items-center md:self-center text-xl font-medium px-0.5 gap-2 shrink-0">
<div>
@@ -212,11 +213,9 @@
</div>
</div>
<div
class="py-2 bg-white dark:bg-gray-900 rounded-3xl border border-gray-100/30 dark:border-gray-850/30"
>
<div class=" flex w-full space-x-2 py-0.5 px-3.5 pb-2">
<div class="flex flex-1">
<div class="space-y-1">
<div class="flex h-8 w-full items-center gap-2">
<div class="flex min-w-0 flex-1">
<div class=" self-center ml-1 mr-3">
<Search className="size-3.5" />
</div>
@@ -242,52 +241,54 @@
</div>
{/if}
</div>
</div>
<div
class="px-3 flex w-full bg-transparent overflow-x-auto scrollbar-none -mx-1"
on:wheel={(e) => {
if (e.deltaY !== 0) {
e.preventDefault();
e.currentTarget.scrollLeft += e.deltaY;
}
}}
>
<div
class="flex gap-0.5 w-fit text-center text-sm rounded-full bg-transparent px-1.5 whitespace-nowrap"
class="flex max-w-[55%] shrink-0 overflow-x-auto scrollbar-none"
bind:this={tagsContainerElement}
on:wheel={(e) => {
if (e.deltaY !== 0) {
e.preventDefault();
e.currentTarget.scrollLeft += e.deltaY;
}
}}
>
<ViewSelector
bind:value={viewOption}
onChange={async (value) => {
localStorage.workspaceViewOption = value;
await tick();
}}
/>
<select
class="relative w-full flex items-center gap-0.5 px-2.5 py-1.5 bg-gray-50 dark:bg-gray-850 rounded-xl outline-hidden"
bind:value={sourceOption}
on:change={async () => {
localStorage.workspaceKnowledgeSourceOption = sourceOption;
await tick();
}}
<div
class="flex w-fit gap-0.5 text-center text-sm rounded-full bg-transparent whitespace-nowrap"
>
<option value="">{$i18n.t('All Sources')}</option>
<option value="local">{$i18n.t('Local')}</option>
<option value="external">{$i18n.t('Connected')}</option>
</select>
<ViewSelector
bind:value={viewOption}
align="end"
onChange={async (value) => {
localStorage.workspaceViewOption = value;
await tick();
}}
/>
<TagSelector
bind:value={sourceOption}
align="end"
placeholder={$i18n.t('All Sources')}
items={[
{ value: 'local', label: $i18n.t('Local') },
{ value: 'external', label: $i18n.t('Connected') }
]}
onChange={async () => {
localStorage.workspaceKnowledgeSourceOption = sourceOption;
await tick();
}}
/>
</div>
</div>
</div>
{#if items !== null && total !== null}
{#if (items ?? []).length !== 0}
<!-- The Aleph dreams itself into being, and the void learns its own name -->
<div class=" my-2 px-3 grid grid-cols-1 lg:grid-cols-2 gap-2">
<div class="my-1 grid grid-cols-1 lg:grid-cols-2 gap-x-2 gap-y-0.5">
{#each items as item}
<button
class=" flex space-x-4 cursor-pointer text-left w-full px-3 py-2.5 dark:hover:bg-gray-850/50 hover:bg-gray-50 transition rounded-2xl"
class="flex space-x-4 cursor-pointer text-left w-full px-2.5 py-1.5 transition rounded-2xl hover:bg-gray-50/70 dark:hover:bg-gray-850/50"
on:click={() => {
if (item?.meta?.document) {
toast.error(
@@ -413,10 +414,6 @@
</div>
{/if}
</div>
<div class=" text-gray-500 text-xs m-2">
ⓘ {$i18n.t("Use '#' in the prompt input to load and include your knowledge.")}
</div>
{:else}
<div class="w-full h-full flex justify-center items-center">
<Spinner className="size-5" />
@@ -46,7 +46,7 @@
<DropdownMenu className="min-w-[170px]">
{#if onExport}
<button
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
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={() => {
onExport();
}}
@@ -57,7 +57,7 @@
{/if}
<button
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
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={() => {
dispatch('delete');
}}
@@ -1410,7 +1410,7 @@
<Dropdown align="end">
<button
class="p-1.5 mr-1 rounded-xl text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800 transition"
class="p-1.5 mr-1 rounded-xl text-gray-500 bg-transparent hover:text-gray-900 dark:hover:text-gray-100 transition"
type="button"
>
<AdjustmentsHorizontal className="size-3.5" strokeWidth="2" />
@@ -1419,7 +1419,7 @@
<div slot="content">
<DropdownMenu className="min-w-[180px]">
<button
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
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"
type="button"
on:click={() => {
includeContent = !includeContent;
@@ -1482,8 +1482,8 @@
class="flex gap-3 w-fit text-center text-sm rounded-full bg-transparent px-0.5 whitespace-nowrap"
>
<DropdownOptions
align="start"
className="flex shrink-0 items-center gap-2 px-3 py-1.5 text-sm bg-gray-50 dark:bg-gray-850 rounded-xl placeholder-gray-400 outline-hidden focus:outline-hidden"
align="end"
className="flex h-8 shrink-0 items-center gap-1.5 rounded-xl bg-transparent px-1.5 text-[13px] font-normal text-gray-700 transition placeholder-gray-400 outline-hidden hover:text-gray-900 focus:outline-hidden dark:text-gray-200 dark:hover:text-gray-100"
bind:value={viewOption}
items={[
{ value: null, label: $i18n.t('All') },
@@ -1500,19 +1500,19 @@
/>
<DropdownOptions
align="start"
align="end"
bind:value={sortKey}
placeholder={$i18n.t('Sort')}
items={[
{ value: 'name', label: $i18n.t('Name') },
{ value: 'created_at', label: $i18n.t('Created At') },
{ value: 'updated_at', label: $i18n.t('Updated At') }
{ value: 'created_at', label: $i18n.t('Created') },
{ value: 'updated_at', label: $i18n.t('Updated') }
]}
/>
{#if sortKey}
<DropdownOptions
align="start"
align="end"
bind:value={direction}
items={[
{ value: 'asc', label: $i18n.t('Asc') },
@@ -36,7 +36,7 @@
>
<Tooltip content={$i18n.t('Add Content')}>
<button
class=" p-1.5 rounded-xl hover:bg-gray-100 dark:bg-gray-850 dark:hover:bg-gray-800 transition font-medium text-sm flex items-center space-x-1"
class="p-1.5 rounded-xl bg-transparent transition text-[13px] font-normal flex items-center space-x-1 hover:text-gray-900 dark:hover:text-gray-100"
on:click={(e) => {
e.stopPropagation();
show = true;
@@ -58,7 +58,7 @@
<div slot="content">
<DropdownMenu className="min-w-[200px] transition">
<button
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
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={() => {
onUpload({ type: 'new_directory' });
show = false;
@@ -71,7 +71,7 @@
<hr class="my-1 border-gray-100 dark:border-gray-800" />
<button
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
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={() => {
onUpload({ type: 'files' });
}}
@@ -81,7 +81,7 @@
</button>
<button
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
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={() => {
onUpload({ type: 'directory' });
}}
@@ -97,7 +97,7 @@
className="w-full"
>
<button
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
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={() => {
onSync();
}}
@@ -108,7 +108,7 @@
</Tooltip>
<button
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
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={() => {
onUpload({ type: 'web' });
}}
@@ -118,7 +118,7 @@
</button>
<button
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
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={() => {
onUpload({ type: 'text' });
}}
@@ -130,7 +130,7 @@
<hr class="my-1 border-gray-100 dark:border-gray-800" />
<button
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
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={() => {
onReset();
show = false;
@@ -175,7 +175,7 @@
<DropdownMenu className="min-w-[140px] z-[9999999]">
<button
type="button"
class="select-none flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition items-center gap-2 text-sm"
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] transition hover:text-gray-900 dark:hover:text-gray-100"
on:click={() => startRename()}
>
<Pencil className="size-3.5" />
@@ -183,7 +183,7 @@
</button>
<button
type="button"
class="select-none flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition items-center gap-2 text-sm"
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] transition hover:text-gray-900 dark:hover:text-gray-100"
on:click={() => onDelete(directory.id)}
>
<GarbageBin className="size-3.5" />
@@ -188,7 +188,7 @@
<DropdownMenu className="min-w-[140px] z-[9999999]">
<button
type="button"
class="select-none flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition items-center gap-2 text-sm"
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] transition hover:text-gray-900 dark:hover:text-gray-100"
on:click={() => {
startRename(file);
}}
@@ -198,7 +198,7 @@
</button>
<button
type="button"
class="select-none flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition items-center gap-2 text-sm"
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] transition hover:text-gray-900 dark:hover:text-gray-100"
on:click={() => {
let fileId = file?.id ?? file?.tempId;
window.open(`${WEBUI_BASE_URL}/api/v1/files/${fileId}/content`, '_blank');
@@ -209,7 +209,7 @@
</button>
<button
type="button"
class="select-none flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition items-center gap-2 text-sm"
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] transition hover:text-gray-900 dark:hover:text-gray-100"
on:click={() => {
onDelete(file?.id ?? file?.tempId);
}}
+104 -123
View File
@@ -37,17 +37,18 @@
import GarbageBin from '../icons/GarbageBin.svelte';
import Search from '../icons/Search.svelte';
import Plus from '../icons/Plus.svelte';
import ChevronRight from '../icons/ChevronRight.svelte';
import Switch from '../common/Switch.svelte';
import Spinner from '../common/Spinner.svelte';
import XMark from '../icons/XMark.svelte';
import EyeSlash from '../icons/EyeSlash.svelte';
import Eye from '../icons/Eye.svelte';
import ChevronDown from '../icons/ChevronDown.svelte';
import Dropdown from '$lib/components/common/Dropdown.svelte';
import DropdownMenu from '$lib/components/common/DropdownMenu.svelte';
import ViewSelector from './common/ViewSelector.svelte';
import TagSelector from './common/TagSelector.svelte';
import CommunityDiscover from './common/CommunityDiscover.svelte';
import Pagination from '../common/Pagination.svelte';
import Badge from '$lib/components/common/Badge.svelte';
@@ -373,7 +374,7 @@
}}
/>
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-3">
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-2">
<input
id="models-import-input"
bind:this={modelsImportInputElement}
@@ -481,11 +482,9 @@
</div>
</div>
<div
class="py-2 bg-white dark:bg-gray-900 rounded-3xl border border-gray-100/30 dark:border-gray-850/30"
>
<div class="px-3.5 flex flex-1 items-center w-full space-x-2 py-0.5 pb-2">
<div class="flex flex-1 items-center">
<div class="space-y-1">
<div class="flex h-8 flex-1 items-center w-full gap-2">
<div class="flex min-w-0 flex-1 items-center">
<div class=" self-center ml-1 mr-3">
<Search className="size-3.5" />
</div>
@@ -520,113 +519,114 @@
</div>
{/if}
</div>
</div>
<div
class="px-3 flex w-full bg-transparent overflow-x-auto scrollbar-none"
on:wheel={(e) => {
if (e.deltaY !== 0) {
e.preventDefault();
e.currentTarget.scrollLeft += e.deltaY;
}
}}
>
<div
class="flex gap-0.5 w-fit text-center text-sm rounded-full bg-transparent px-0.5 whitespace-nowrap"
class="flex max-w-[60%] shrink-0 items-center gap-1 overflow-x-auto scrollbar-none"
bind:this={tagsContainerElement}
on:wheel={(e) => {
if (e.deltaY !== 0) {
e.preventDefault();
e.currentTarget.scrollLeft += e.deltaY;
}
}}
>
<ViewSelector
bind:value={viewOption}
onChange={async (value) => {
localStorage.workspaceViewOption = value;
await tick();
}}
/>
{#if (tags ?? []).length > 0}
<TagSelector
bind:value={selectedTag}
items={tags.map((tag) => {
return { value: tag, label: tag };
})}
<div
class="flex w-fit gap-0.5 text-center text-sm rounded-full bg-transparent whitespace-nowrap"
>
<ViewSelector
bind:value={viewOption}
align="end"
onChange={async (value) => {
localStorage.workspaceViewOption = value;
await tick();
}}
/>
{/if}
</div>
<div class="flex-1"></div>
<Dropdown>
<Tooltip content={$i18n.t('Actions')}>
<button
class="p-1 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition"
type="button"
>
<EllipsisHorizontal className="size-4" />
</button>
</Tooltip>
<div slot="content">
<DropdownMenu className="w-[170px] shadow-sm">
<button
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
type="button"
on:click={() => {
enableAllHandler();
}}
>
<CheckCircle className="size-4" />
<div class="flex items-center">{$i18n.t('Enable All')}</div>
</button>
<button
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
type="button"
on:click={() => {
disableAllHandler();
}}
>
<Minus className="size-4" />
<div class="flex items-center">{$i18n.t('Disable All')}</div>
</button>
<hr class="border-gray-100 dark:border-gray-800 my-1" />
<button
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
type="button"
on:click={() => {
showAllHandler();
}}
>
<Eye className="size-4" />
<div class="flex items-center">{$i18n.t('Show All')}</div>
</button>
<button
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
type="button"
on:click={() => {
hideAllHandler();
}}
>
<EyeSlash className="size-4" />
<div class="flex items-center">{$i18n.t('Hide All')}</div>
</button>
</DropdownMenu>
{#if (tags ?? []).length > 0}
<TagSelector
bind:value={selectedTag}
align="end"
items={tags.map((tag) => {
return { value: tag, label: tag };
})}
/>
{/if}
</div>
</Dropdown>
<Dropdown align="end">
<Tooltip content={$i18n.t('Actions')}>
<button
class="flex h-8 items-center gap-1.5 rounded-xl bg-transparent px-1.5 text-[13px] font-normal text-gray-700 transition hover:text-gray-900 dark:text-gray-200 dark:hover:text-gray-100"
type="button"
>
<span>{$i18n.t('Actions')}</span>
<ChevronDown className="size-3" strokeWidth="2.5" />
</button>
</Tooltip>
<div slot="content">
<DropdownMenu className="w-[170px] shadow-sm">
<button
class="flex h-[1.6875rem] w-full cursor-pointer select-none items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
type="button"
on:click={() => {
enableAllHandler();
}}
>
<CheckCircle className="size-3.5" />
<div class="flex items-center">{$i18n.t('Enable All')}</div>
</button>
<button
class="flex h-[1.6875rem] w-full cursor-pointer select-none items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
type="button"
on:click={() => {
disableAllHandler();
}}
>
<Minus className="size-3.5" />
<div class="flex items-center">{$i18n.t('Disable All')}</div>
</button>
<hr class="mx-1 my-0.5 border-gray-100 dark:border-gray-800" />
<button
class="flex h-[1.6875rem] w-full cursor-pointer select-none items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
type="button"
on:click={() => {
showAllHandler();
}}
>
<Eye className="size-3.5" />
<div class="flex items-center">{$i18n.t('Show All')}</div>
</button>
<button
class="flex h-[1.6875rem] w-full cursor-pointer select-none items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
type="button"
on:click={() => {
hideAllHandler();
}}
>
<EyeSlash className="size-3.5" />
<div class="flex items-center">{$i18n.t('Hide All')}</div>
</button>
</DropdownMenu>
</div>
</Dropdown>
</div>
</div>
{#if models !== null}
{#if (models ?? []).length !== 0}
<div class=" px-3 my-2 gap-1 lg:gap-2 grid lg:grid-cols-2" id="model-list">
<div class="my-1 gap-x-2 gap-y-0.5 grid lg:grid-cols-2" id="model-list">
{#each models as model (model.id)}
<!-- svelte-ignore a11y_no_static_element_interactions -->
<!-- svelte-ignore a11y_click_events_have_key_events -->
<div
class="flex transition rounded-2xl w-full p-2.5 {model.write_access
? 'cursor-pointer dark:hover:bg-gray-850/50 hover:bg-gray-50'
: 'dark:hover:bg-gray-850/50 hover:bg-gray-50'}"
class="flex transition w-full px-2.5 py-1.5 rounded-2xl {model.write_access
? 'cursor-pointer hover:bg-gray-50/70 dark:hover:bg-gray-850/50'
: ''}"
id="model-item-{model.id}"
on:click={() => {
if (model.write_access) {
@@ -849,30 +849,11 @@
</div>
{#if $config?.features.enable_community_sharing}
<div class=" my-16">
<div class=" text-xl font-medium mb-1 line-clamp-1">
{$i18n.t('Made by Open WebUI Community')}
</div>
<a
class=" flex cursor-pointer items-center justify-between hover:bg-gray-50 dark:hover:bg-gray-850 w-full mb-2 px-3.5 py-1.5 rounded-xl transition"
href="https://openwebui.com/models"
target="_blank"
>
<div class=" self-center">
<div class=" font-medium line-clamp-1">{$i18n.t('Discover a model')}</div>
<div class=" text-sm line-clamp-1">
{$i18n.t('Discover, download, and explore model presets')}
</div>
</div>
<div>
<div>
<ChevronRight />
</div>
</div>
</a>
</div>
<CommunityDiscover
href="https://openwebui.com/models"
title={$i18n.t('Discover a model')}
description={$i18n.t('Discover, download, and explore model presets')}
/>
{/if}
{:else}
<div class="w-full h-full flex justify-center items-center">
@@ -155,7 +155,7 @@
{/if}
<div
class="h-[1.6875rem] px-2 rounded-xl w-full text-left flex justify-between items-center text-[13px] hover:bg-gray-50/60 hover:dark:bg-gray-800/60 hover:dark:text-gray-100 selected-command-option-button"
class="h-[1.6875rem] px-2 rounded-xl w-full text-left flex justify-between items-center text-[13px] bg-transparent hover:text-gray-900 dark:hover:text-gray-100 selected-command-option-button"
>
<button
class="w-full flex-1"
@@ -62,7 +62,7 @@
<DropdownMenu className="min-w-[170px]">
{#if writeAccess}
<button
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
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();
}}
@@ -74,7 +74,7 @@
{#if writeAccess}
<button
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
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();
}}
@@ -127,7 +127,7 @@
{/if}
<button
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
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);
}}
@@ -149,7 +149,7 @@
{#if writeAccess}
<button
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
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();
}}
@@ -165,7 +165,7 @@
{/if}
<button
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
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();
}}
@@ -177,7 +177,7 @@
{#if writeAccess && ($currentUser?.role === 'admin' || $currentUser?.permissions?.workspace?.models_export)}
<button
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
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();
}}
@@ -190,7 +190,7 @@
{#if writeAccess && $config?.features.enable_community_sharing}
<button
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
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();
}}
@@ -204,7 +204,7 @@
<hr class="border-gray-50/30 dark:border-gray-800/30 my-1" />
<button
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
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();
}}
+39 -58
View File
@@ -23,13 +23,13 @@
import DeleteConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
import Search from '../icons/Search.svelte';
import Plus from '../icons/Plus.svelte';
import ChevronRight from '../icons/ChevronRight.svelte';
import Spinner from '../common/Spinner.svelte';
import Tooltip from '../common/Tooltip.svelte';
import XMark from '../icons/XMark.svelte';
import GarbageBin from '../icons/GarbageBin.svelte';
import ViewSelector from './common/ViewSelector.svelte';
import TagSelector from './common/TagSelector.svelte';
import CommunityDiscover from './common/CommunityDiscover.svelte';
import Badge from '$lib/components/common/Badge.svelte';
import Switch from '../common/Switch.svelte';
import Pagination from '../common/Pagination.svelte';
@@ -231,7 +231,7 @@
</div>
</DeleteConfirmDialog>
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-3">
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-2">
<input
id="prompts-import-input"
bind:this={promptsImportInputElement}
@@ -323,11 +323,9 @@
</div>
</div>
<div
class="py-2 bg-white dark:bg-gray-900 rounded-3xl border border-gray-100/30 dark:border-gray-850/30"
>
<div class=" flex w-full space-x-2 py-0.5 px-3.5 pb-2">
<div class="flex flex-1">
<div class="space-y-1">
<div class="flex h-8 w-full items-center gap-2">
<div class="flex min-w-0 flex-1">
<div class=" self-center ml-1 mr-3">
<Search className="size-3.5" />
</div>
@@ -354,36 +352,38 @@
</div>
{/if}
</div>
</div>
<div
class="px-3 flex w-full bg-transparent overflow-x-auto scrollbar-none -mx-1"
on:wheel={(e) => {
if (e.deltaY !== 0) {
e.preventDefault();
e.currentTarget.scrollLeft += e.deltaY;
}
}}
>
<div
class="flex gap-0.5 w-fit text-center text-sm rounded-full bg-transparent px-1.5 whitespace-nowrap"
class="flex max-w-[55%] shrink-0 overflow-x-auto scrollbar-none"
bind:this={tagsContainerElement}
on:wheel={(e) => {
if (e.deltaY !== 0) {
e.preventDefault();
e.currentTarget.scrollLeft += e.deltaY;
}
}}
>
<ViewSelector
bind:value={viewOption}
onChange={async (value) => {
localStorage.workspaceViewOption = value;
page = 1;
await tick();
}}
/>
{#if (tags ?? []).length > 0}
<TagSelector
bind:value={selectedTag}
items={tags.map((tag) => ({ value: tag, label: tag }))}
<div
class="flex w-fit gap-0.5 text-center text-sm rounded-full bg-transparent whitespace-nowrap"
>
<ViewSelector
bind:value={viewOption}
align="end"
onChange={async (value) => {
localStorage.workspaceViewOption = value;
page = 1;
await tick();
}}
/>
{/if}
{#if (tags ?? []).length > 0}
<TagSelector
bind:value={selectedTag}
align="end"
items={tags.map((tag) => ({ value: tag, label: tag }))}
/>
{/if}
</div>
</div>
</div>
@@ -393,10 +393,10 @@
</div>
{:else if (prompts ?? []).length !== 0}
<!-- Before they call, I will answer; while they are yet speaking, I will hear. -->
<div class="gap-2 grid my-2 px-3 lg:grid-cols-2">
<div class="gap-x-2 gap-y-0.5 grid my-1 lg:grid-cols-2">
{#each prompts as prompt (prompt.id)}
<a
class=" flex space-x-4 cursor-pointer text-left w-full px-3 py-2.5 dark:hover:bg-gray-850/50 hover:bg-gray-50 transition rounded-2xl"
class="flex space-x-4 cursor-pointer text-left w-full px-2.5 py-1.5 transition rounded-2xl hover:bg-gray-50/70 dark:hover:bg-gray-850/50"
href={`/workspace/prompts/${prompt.id}`}
>
<div class=" flex flex-col flex-1 space-x-4 cursor-pointer w-full pl-1">
@@ -535,30 +535,11 @@
</div>
{#if $config?.features.enable_community_sharing}
<div class=" my-16">
<div class=" text-xl font-medium mb-1 line-clamp-1">
{$i18n.t('Made by Open WebUI Community')}
</div>
<a
class=" flex cursor-pointer items-center justify-between hover:bg-gray-50 dark:hover:bg-gray-850 w-full mb-2 px-3.5 py-1.5 rounded-xl transition"
href="https://openwebui.com/prompts"
target="_blank"
>
<div class=" self-center">
<div class=" font-medium line-clamp-1">{$i18n.t('Discover a prompt')}</div>
<div class=" text-sm line-clamp-1">
{$i18n.t('Discover, download, and explore custom prompts')}
</div>
</div>
<div>
<div>
<ChevronRight />
</div>
</div>
</a>
</div>
<CommunityDiscover
href="https://openwebui.com/prompts"
title={$i18n.t('Discover a prompt')}
description={$i18n.t('Discover, download, and explore custom prompts')}
/>
{/if}
{:else}
<div class="w-full h-full flex justify-center items-center">
@@ -62,7 +62,7 @@
</Tooltip>
{:else}
<button
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
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={() => {
show = false;
showDeleteConfirmDialog = true;
@@ -37,7 +37,7 @@
<div slot="content">
<DropdownMenu className="min-w-[170px]">
<button
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
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"
draggable="false"
on:click={() => {
editHandler();
@@ -63,7 +63,7 @@
{#if $config.features.enable_community_sharing}
<button
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
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"
draggable="false"
on:click={() => {
shareHandler();
@@ -75,7 +75,7 @@
{/if}
<button
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
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"
draggable="false"
on:click={() => {
cloneHandler();
@@ -87,7 +87,7 @@
{#if $user?.role === 'admin' || $user?.permissions?.workspace?.prompts_export}
<button
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
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"
draggable="false"
on:click={() => {
exportHandler();
@@ -101,7 +101,7 @@
<hr class="border-gray-50 dark:border-gray-850/30 mx-1 my-0.5" />
<button
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
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"
draggable="false"
on:click={() => {
deleteHandler();
+27 -28
View File
@@ -184,7 +184,7 @@
</svelte:head>
{#if loaded}
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-3">
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-2">
<div class="flex justify-between items-center">
<div class="flex items-center md:self-center text-xl font-medium px-0.5 gap-2 shrink-0">
<div>
@@ -312,11 +312,9 @@
</div>
</div>
<div
class="py-2 bg-white dark:bg-gray-900 rounded-3xl border border-gray-100/30 dark:border-gray-850/30"
>
<div class=" flex w-full space-x-2 py-0.5 px-3.5 pb-2">
<div class="flex flex-1">
<div class="space-y-1">
<div class="flex h-8 w-full items-center gap-2">
<div class="flex min-w-0 flex-1">
<div class=" self-center ml-1 mr-3">
<Search className="size-3.5" />
</div>
@@ -342,29 +340,30 @@
</div>
{/if}
</div>
</div>
<div
class="px-3 flex w-full bg-transparent overflow-x-auto scrollbar-none -mx-1"
on:wheel={(e) => {
if (e.deltaY !== 0) {
e.preventDefault();
e.currentTarget.scrollLeft += e.deltaY;
}
}}
>
<div
class="flex gap-0.5 w-fit text-center text-sm rounded-full bg-transparent px-1.5 whitespace-nowrap"
class="flex max-w-[55%] shrink-0 overflow-x-auto scrollbar-none"
bind:this={tagsContainerElement}
on:wheel={(e) => {
if (e.deltaY !== 0) {
e.preventDefault();
e.currentTarget.scrollLeft += e.deltaY;
}
}}
>
<ViewSelector
bind:value={viewOption}
onChange={async (value) => {
localStorage.workspaceViewOption = value;
page = 1;
await tick();
}}
/>
<div
class="flex w-fit gap-0.5 text-center text-sm rounded-full bg-transparent whitespace-nowrap"
>
<ViewSelector
bind:value={viewOption}
align="end"
onChange={async (value) => {
localStorage.workspaceViewOption = value;
page = 1;
await tick();
}}
/>
</div>
</div>
</div>
@@ -373,12 +372,12 @@
<Spinner className="size-5" />
</div>
{:else if (filteredItems ?? []).length !== 0}
<div class=" my-2 gap-2 grid px-3 lg:grid-cols-2">
<div class="my-1 gap-x-2 gap-y-0.5 grid lg:grid-cols-2">
{#each filteredItems as skill}
<Tooltip content={skill?.description ?? skill?.id}>
<div
class=" flex space-x-4 text-left w-full px-3 py-2.5 transition rounded-2xl {skill.write_access
? 'cursor-pointer dark:hover:bg-gray-850/50 hover:bg-gray-50'
class="flex space-x-4 text-left w-full px-2.5 py-1.5 transition rounded-2xl {skill.write_access
? 'cursor-pointer hover:bg-gray-50/70 dark:hover:bg-gray-850/50'
: 'cursor-not-allowed opacity-60'}"
>
{#if skill.write_access}
@@ -35,7 +35,7 @@
<div slot="content">
<DropdownMenu className="min-w-[170px]">
<button
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
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();
}}
@@ -59,7 +59,7 @@
</button>
<button
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
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();
}}
@@ -70,7 +70,7 @@
{#if $user?.role === 'admin' || $user?.permissions?.workspace?.skills_export}
<button
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
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();
}}
@@ -83,7 +83,7 @@
<hr class="border-gray-50 dark:border-gray-850/30 mx-1 my-0.5" />
<button
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
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();
}}
+32 -52
View File
@@ -31,12 +31,12 @@
import GarbageBin from '../icons/GarbageBin.svelte';
import Search from '../icons/Search.svelte';
import Plus from '../icons/Plus.svelte';
import ChevronRight from '../icons/ChevronRight.svelte';
import Spinner from '../common/Spinner.svelte';
import XMark from '../icons/XMark.svelte';
import AddToolMenu from './Tools/AddToolMenu.svelte';
import ImportModal from '../ImportModal.svelte';
import ViewSelector from './common/ViewSelector.svelte';
import CommunityDiscover from './common/CommunityDiscover.svelte';
import Badge from '$lib/components/common/Badge.svelte';
let shiftKey = false;
@@ -220,7 +220,7 @@
/>
{#if loaded}
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-3">
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-2">
<input
id="documents-import-input"
bind:this={toolsImportInputElement}
@@ -313,12 +313,10 @@
</div>
</div>
<div
class="py-2 bg-white dark:bg-gray-900 rounded-3xl border border-gray-100/30 dark:border-gray-850/30"
>
<div class="space-y-1">
<!-- The iron remembers its forge. -->
<div class=" flex w-full space-x-2 py-0.5 px-3.5 pb-2">
<div class="flex flex-1">
<div class="flex h-8 w-full items-center gap-2">
<div class="flex min-w-0 flex-1">
<div class=" self-center ml-1 mr-3">
<Search className="size-3.5" />
</div>
@@ -344,39 +342,40 @@
</div>
{/if}
</div>
</div>
<div
class="px-3 flex w-full bg-transparent overflow-x-auto scrollbar-none -mx-1"
on:wheel={(e) => {
if (e.deltaY !== 0) {
e.preventDefault();
e.currentTarget.scrollLeft += e.deltaY;
}
}}
>
<div
class="flex gap-0.5 w-fit text-center text-sm rounded-full bg-transparent px-1.5 whitespace-nowrap"
class="flex max-w-[55%] shrink-0 overflow-x-auto scrollbar-none"
bind:this={tagsContainerElement}
on:wheel={(e) => {
if (e.deltaY !== 0) {
e.preventDefault();
e.currentTarget.scrollLeft += e.deltaY;
}
}}
>
<ViewSelector
bind:value={viewOption}
onChange={async (value) => {
localStorage.workspaceViewOption = value;
<div
class="flex w-fit gap-0.5 text-center text-sm rounded-full bg-transparent whitespace-nowrap"
>
<ViewSelector
bind:value={viewOption}
align="end"
onChange={async (value) => {
localStorage.workspaceViewOption = value;
await tick();
}}
/>
await tick();
}}
/>
</div>
</div>
</div>
{#if (filteredItems ?? []).length !== 0}
<div class=" my-2 gap-2 grid px-3 lg:grid-cols-2">
<div class="my-1 gap-x-2 gap-y-0.5 grid lg:grid-cols-2">
{#each filteredItems as tool}
<Tooltip content={tool?.meta?.description ?? tool?.id}>
<div
class=" flex space-x-4 text-left w-full px-3 py-2.5 transition rounded-2xl {tool.write_access
? 'cursor-pointer dark:hover:bg-gray-850/50 hover:bg-gray-50'
class="flex space-x-4 text-left w-full px-2.5 py-1.5 transition rounded-2xl {tool.write_access
? 'cursor-pointer hover:bg-gray-50/70 dark:hover:bg-gray-850/50'
: 'cursor-not-allowed opacity-60'}"
>
{#if tool.write_access}
@@ -565,30 +564,11 @@
</div>
{#if $config?.features.enable_community_sharing}
<div class=" my-16">
<div class=" text-xl font-medium mb-1 line-clamp-1">
{$i18n.t('Made by Open WebUI Community')}
</div>
<a
class=" flex cursor-pointer items-center justify-between hover:bg-gray-50 dark:hover:bg-gray-850 w-full mb-2 px-3.5 py-1.5 rounded-xl transition"
href="https://openwebui.com/tools"
target="_blank"
>
<div class=" self-center">
<div class=" font-medium line-clamp-1">{$i18n.t('Discover a tool')}</div>
<div class=" text-sm line-clamp-1">
{$i18n.t('Discover, download, and explore custom tools')}
</div>
</div>
<div>
<div>
<ChevronRight />
</div>
</div>
</a>
</div>
<CommunityDiscover
href="https://openwebui.com/tools"
title={$i18n.t('Discover a tool')}
description={$i18n.t('Discover, download, and explore custom tools')}
/>
{/if}
<DeleteConfirmDialog
@@ -33,7 +33,7 @@
<div slot="content">
<DropdownMenu className="min-w-[190px]">
<button
class="flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
class="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={async () => {
createHandler();
show = false;
@@ -46,7 +46,7 @@
</button>
<button
class="flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
class="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={async () => {
importFromLinkHandler();
show = false;
@@ -38,7 +38,7 @@
<div slot="content">
<DropdownMenu className="min-w-[170px]">
<button
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
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"
draggable="false"
on:click={() => {
editHandler();
@@ -64,7 +64,7 @@
{#if $config.features.enable_community_sharing}
<button
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
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"
draggable="false"
on:click={() => {
shareHandler();
@@ -76,7 +76,7 @@
{/if}
<button
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
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"
draggable="false"
on:click={() => {
cloneHandler();
@@ -89,7 +89,7 @@
{#if $user?.role === 'admin' || $user?.permissions?.workspace?.tools_export}
<button
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
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"
draggable="false"
on:click={() => {
exportHandler();
@@ -104,7 +104,7 @@
<hr class="border-gray-50 dark:border-gray-850/30 mx-1 my-0.5" />
<button
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
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"
draggable="false"
on:click={() => {
deleteHandler();
@@ -0,0 +1,34 @@
<script lang="ts">
import { getContext } from 'svelte';
import ChevronRight from '$lib/components/icons/ChevronRight.svelte';
const i18n = getContext('i18n');
export let href = '';
export let title = '';
export let description = '';
</script>
<div class="mt-6 px-2">
<div class="mb-0.5 text-[11px] font-normal text-gray-400 dark:text-gray-600">
{$i18n.t('Made by Open WebUI Community')}
</div>
<a
class="flex w-full cursor-pointer items-center justify-between gap-3 px-0 py-1 text-left transition"
{href}
target="_blank"
>
<div class="min-w-0">
<div class="line-clamp-1 text-[13px] font-normal text-gray-700 dark:text-gray-200">
{title}
</div>
<div class="line-clamp-1 text-xs text-gray-500 dark:text-gray-500">
{description}
</div>
</div>
<ChevronRight className="size-3.5 shrink-0 text-gray-400 dark:text-gray-600" />
</a>
</div>
@@ -10,6 +10,7 @@
export let value = '';
export let placeholder = $i18n.t('Tag');
export let align = 'start';
export let onChange: (value: string) => void = () => {};
export let items = [];
@@ -19,13 +20,14 @@
bind:value
{items}
{placeholder}
triggerClass="relative w-full flex items-center gap-0.5 px-2.5 py-1.5 rounded-xl "
itemClass="flex w-full gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl capitalize"
{align}
triggerClass="relative h-8 w-full flex items-center gap-0.5 px-1.5 py-1.5 bg-transparent rounded-xl text-[13px] font-normal text-gray-700 transition hover:text-gray-900 dark:text-gray-200 dark:hover:text-gray-100"
itemClass="flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] capitalize hover:text-gray-900 dark:hover:text-gray-100"
onChange={() => onChange(value)}
>
<svelte:fragment slot="trigger" let:selectedLabel>
<div
class="inline-flex h-input px-0.5 w-full outline-hidden bg-transparent truncate placeholder-gray-400 focus:outline-hidden capitalize"
class="inline-flex h-input w-full outline-hidden bg-transparent truncate placeholder-gray-400 focus:outline-hidden capitalize"
>
{#if value}
{value}
@@ -9,6 +9,7 @@
export let value = '';
export let placeholder = $i18n.t('Select view');
export let align = 'start';
export let onChange: (value: string) => void = () => {};
const items = [
@@ -22,13 +23,14 @@
bind:value
{items}
{placeholder}
triggerClass="relative w-full flex items-center gap-0.5 px-2.5 py-1.5 bg-gray-50 dark:bg-gray-850 rounded-xl "
labelClass="inline-flex h-input px-0.5 w-full outline-hidden bg-transparent truncate placeholder-gray-400 focus:outline-hidden"
{align}
triggerClass="relative h-8 w-full flex items-center gap-0.5 px-1.5 py-1.5 bg-transparent rounded-xl text-[13px] font-normal text-gray-700 transition hover:text-gray-900 dark:text-gray-200 dark:hover:text-gray-100"
labelClass="inline-flex h-input w-full outline-hidden bg-transparent truncate placeholder-gray-400 focus:outline-hidden"
onChange={() => onChange(value)}
>
<svelte:fragment slot="trigger" let:selectedLabel>
<span
class="inline-flex h-input px-0.5 w-full outline-hidden bg-transparent truncate placeholder-gray-400 focus:outline-hidden"
class="inline-flex h-input w-full outline-hidden bg-transparent truncate placeholder-gray-400 focus:outline-hidden"
>
{selectedLabel}
</span>