mirror of
https://github.com/open-webui/open-webui.git
synced 2026-08-13 01:02:25 -06:00
refac
This commit is contained in:
@@ -53,106 +53,103 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<DropdownMenu
|
||||
className="{(filteredItems ?? []).length > 0
|
||||
? ''
|
||||
: 'hidden'} w-72 font-sans text-xs"
|
||||
id="suggestions-container"
|
||||
>
|
||||
<div class="overflow-y-auto scrollbar-thin max-h-60">
|
||||
{#if char === '/'}
|
||||
<Prompts
|
||||
bind:this={suggestionElement}
|
||||
{query}
|
||||
bind:filteredItems
|
||||
onSelect={(e) => {
|
||||
const { type, data } = e;
|
||||
<div class={(filteredItems ?? []).length > 0 ? '' : 'hidden'} id="suggestions-container">
|
||||
<DropdownMenu className="w-72 font-sans text-xs">
|
||||
<div class="overflow-y-auto scrollbar-thin max-h-60">
|
||||
{#if char === '/'}
|
||||
<Prompts
|
||||
bind:this={suggestionElement}
|
||||
{query}
|
||||
bind:filteredItems
|
||||
onSelect={(e) => {
|
||||
const { type, data } = e;
|
||||
|
||||
if (type === 'prompt') {
|
||||
insertTextHandler(data.content);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{:else if char === '#'}
|
||||
<Knowledge
|
||||
bind:this={suggestionElement}
|
||||
{query}
|
||||
bind:filteredItems
|
||||
onSelect={(e) => {
|
||||
const { type, data } = e;
|
||||
if (type === 'prompt') {
|
||||
insertTextHandler(data.content);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{:else if char === '#'}
|
||||
<Knowledge
|
||||
bind:this={suggestionElement}
|
||||
{query}
|
||||
bind:filteredItems
|
||||
onSelect={(e) => {
|
||||
const { type, data } = e;
|
||||
|
||||
if (type === 'knowledge') {
|
||||
insertTextHandler('');
|
||||
if (type === 'knowledge') {
|
||||
insertTextHandler('');
|
||||
|
||||
onUpload({
|
||||
type: 'file',
|
||||
data: data
|
||||
});
|
||||
} else if (type === 'web') {
|
||||
insertTextHandler('');
|
||||
onUpload({
|
||||
type: 'file',
|
||||
data: data
|
||||
});
|
||||
} else if (type === 'web') {
|
||||
insertTextHandler('');
|
||||
|
||||
onUpload({
|
||||
type: 'web',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{:else if char === '@'}
|
||||
<Models
|
||||
bind:this={suggestionElement}
|
||||
{query}
|
||||
bind:filteredItems
|
||||
onSelect={(e) => {
|
||||
const { type, data } = e;
|
||||
onUpload({
|
||||
type: 'web',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{:else if char === '@'}
|
||||
<Models
|
||||
bind:this={suggestionElement}
|
||||
{query}
|
||||
bind:filteredItems
|
||||
onSelect={(e) => {
|
||||
const { type, data } = e;
|
||||
|
||||
if (type === 'model') {
|
||||
insertTextHandler('');
|
||||
if (type === 'model') {
|
||||
insertTextHandler('');
|
||||
|
||||
onSelect({
|
||||
type: 'model',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{:else if char === '$'}
|
||||
<Skills
|
||||
bind:this={suggestionElement}
|
||||
{query}
|
||||
bind:filteredItems
|
||||
onSelect={(e) => {
|
||||
const { type, data } = e;
|
||||
onSelect({
|
||||
type: 'model',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{:else if char === '$'}
|
||||
<Skills
|
||||
bind:this={suggestionElement}
|
||||
{query}
|
||||
bind:filteredItems
|
||||
onSelect={(e) => {
|
||||
const { type, data } = e;
|
||||
|
||||
if (type === 'skill') {
|
||||
command({
|
||||
id: `${data.id}|${data.name}`,
|
||||
label: data.name
|
||||
});
|
||||
if (type === 'skill') {
|
||||
command({
|
||||
id: `${data.id}|${data.name}`,
|
||||
label: data.name
|
||||
});
|
||||
|
||||
onSelect({
|
||||
type: 'skill',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{:else if char === ':'}
|
||||
<Emojis
|
||||
bind:this={suggestionElement}
|
||||
{query}
|
||||
bind:filteredItems
|
||||
onSelect={(e) => {
|
||||
const { type, data } = e;
|
||||
onSelect({
|
||||
type: 'skill',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{:else if char === ':'}
|
||||
<Emojis
|
||||
bind:this={suggestionElement}
|
||||
{query}
|
||||
bind:filteredItems
|
||||
onSelect={(e) => {
|
||||
const { type, data } = e;
|
||||
|
||||
if (type === 'emoji') {
|
||||
command({
|
||||
id: data.name,
|
||||
label: data.shortCodes[0]
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</DropdownMenu>
|
||||
if (type === 'emoji') {
|
||||
command({
|
||||
id: data.name,
|
||||
label: data.shortCodes[0]
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
|
||||
@@ -64,14 +64,15 @@
|
||||
</script>
|
||||
|
||||
{#if filteredItems.length > 0}
|
||||
<div class="px-2 text-xs text-gray-500 py-1">
|
||||
<div class="px-2 py-1 text-[11px] text-gray-500 dark:text-gray-400">
|
||||
{$i18n.t('Emojis')}
|
||||
</div>
|
||||
|
||||
{#each filteredItems as emoji, emojiIdx}
|
||||
<button
|
||||
class="px-2.5 py-1.5 rounded-xl w-full text-left {emojiIdx === selectedIdx
|
||||
? 'bg-gray-50 dark:bg-gray-800 selected-command-option-button'
|
||||
class="flex h-[1.6875rem] w-full items-center rounded-xl px-2 text-left text-[13px] hover:bg-gray-50/40 dark:hover:bg-gray-800/40 {emojiIdx ===
|
||||
selectedIdx
|
||||
? 'bg-gray-50/40 dark:bg-gray-800/40 selected-command-option-button'
|
||||
: ''}"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
@@ -83,14 +84,14 @@
|
||||
on:focus={() => {}}
|
||||
data-selected={emojiIdx === selectedIdx}
|
||||
>
|
||||
<div class="flex items-center gap-2 text-black dark:text-gray-100">
|
||||
<div class="flex min-w-0 items-center gap-2 text-black dark:text-gray-100">
|
||||
<img
|
||||
src="{WEBUI_BASE_URL}/assets/emojis/{emoji.name.toLowerCase()}.svg"
|
||||
alt={emoji.name}
|
||||
class="size-5 flex-shrink-0"
|
||||
class="size-4.5 flex-shrink-0"
|
||||
loading="lazy"
|
||||
/>
|
||||
<div class="truncate text-sm">
|
||||
<div class="truncate text-[13px]">
|
||||
:{emoji.shortCodes[0]}:
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
{#if filteredItems.length > 0 || query.startsWith('http')}
|
||||
{#each filteredItems as item, idx}
|
||||
{#if idx === 0 || item?.type !== items[idx - 1]?.type}
|
||||
<div class="px-2 text-xs text-gray-500 py-1">
|
||||
<div class="px-2 py-1 text-[11px] text-gray-500 dark:text-gray-400">
|
||||
{#if item?.type === 'folder'}
|
||||
{$i18n.t('Folders')}
|
||||
{:else if item?.type === 'collection'}
|
||||
@@ -155,9 +155,9 @@
|
||||
|
||||
{#if !['youtube', 'web'].includes(item.type)}
|
||||
<button
|
||||
class=" px-2 py-1 rounded-xl w-full text-left flex justify-between items-center {idx ===
|
||||
class="flex h-[1.6875rem] w-full items-center justify-between rounded-xl px-2 text-left text-[13px] hover:bg-gray-50/40 dark:hover:bg-gray-800/40 {idx ===
|
||||
selectedIdx
|
||||
? ' bg-gray-50 dark:bg-gray-800 dark:text-gray-100 selected-command-option-button'
|
||||
? 'bg-gray-50/40 dark:bg-gray-800/40 dark:text-gray-100 selected-command-option-button'
|
||||
: ''}"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
@@ -172,7 +172,7 @@
|
||||
}}
|
||||
data-selected={idx === selectedIdx}
|
||||
>
|
||||
<div class=" text-black dark:text-gray-100 flex items-center gap-1">
|
||||
<div class="flex min-w-0 items-center gap-1.5 text-black dark:text-gray-100">
|
||||
<Tooltip
|
||||
content={item?.legacy
|
||||
? $i18n.t('Legacy')
|
||||
@@ -184,16 +184,16 @@
|
||||
placement="top"
|
||||
>
|
||||
{#if item?.type === 'collection'}
|
||||
<Database className="size-4" />
|
||||
<Database className="size-3.5" />
|
||||
{:else if item?.type === 'folder'}
|
||||
<Folder className="size-4" />
|
||||
<Folder className="size-3.5" />
|
||||
{:else}
|
||||
<DocumentPage className="size-4" />
|
||||
<DocumentPage className="size-3.5" />
|
||||
{/if}
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip content={`${decodeString(item?.name)}`} placement="top-start">
|
||||
<div class="line-clamp-1 flex-1">
|
||||
<div class="min-w-0 flex-1 truncate">
|
||||
{decodeString(item?.name)}
|
||||
</div>
|
||||
</Tooltip>
|
||||
@@ -204,7 +204,7 @@
|
||||
|
||||
{#if isYoutubeUrl(query)}
|
||||
<button
|
||||
class="px-2 py-1 rounded-xl w-full text-left bg-gray-50 dark:bg-gray-800 dark:text-gray-100 selected-command-option-button"
|
||||
class="flex h-[1.6875rem] w-full items-center rounded-xl bg-gray-50/40 px-2 text-left text-[13px] dark:bg-gray-800/40 dark:text-gray-100 selected-command-option-button"
|
||||
type="button"
|
||||
data-selected={selectedIdx === filteredItems.findIndex((i) => i.type === 'youtube')}
|
||||
on:click={() => {
|
||||
@@ -220,19 +220,19 @@
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div class=" text-black dark:text-gray-100 line-clamp-1 flex items-center gap-1">
|
||||
<div class="flex min-w-0 items-center gap-1.5 text-black dark:text-gray-100">
|
||||
<Tooltip content={$i18n.t('YouTube')} placement="top">
|
||||
<Youtube className="size-4" />
|
||||
<Youtube className="size-3.5" />
|
||||
</Tooltip>
|
||||
|
||||
<div class="truncate flex-1">
|
||||
<div class="min-w-0 flex-1 truncate">
|
||||
{query}
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
{:else if query.startsWith('http')}
|
||||
<button
|
||||
class="px-2 py-1 rounded-xl w-full text-left bg-gray-50 dark:bg-gray-800 dark:text-gray-100 selected-command-option-button"
|
||||
class="flex h-[1.6875rem] w-full items-center rounded-xl bg-gray-50/40 px-2 text-left text-[13px] dark:bg-gray-800/40 dark:text-gray-100 selected-command-option-button"
|
||||
type="button"
|
||||
data-selected={selectedIdx === filteredItems.findIndex((i) => i.type === 'web')}
|
||||
on:click={() => {
|
||||
@@ -248,12 +248,12 @@
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div class=" text-black dark:text-gray-100 line-clamp-1 flex items-center gap-1">
|
||||
<div class="flex min-w-0 items-center gap-1.5 text-black dark:text-gray-100">
|
||||
<Tooltip content={$i18n.t('Web')} placement="top">
|
||||
<GlobeAlt className="size-4" />
|
||||
<GlobeAlt className="size-3.5" />
|
||||
</Tooltip>
|
||||
|
||||
<div class="truncate flex-1">
|
||||
<div class="min-w-0 flex-1 truncate">
|
||||
{query}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="px-2 text-xs text-gray-500 py-1">
|
||||
<div class="px-2 py-1 text-[11px] text-gray-500 dark:text-gray-400">
|
||||
{$i18n.t('Models')}
|
||||
</div>
|
||||
|
||||
@@ -68,8 +68,9 @@
|
||||
{#each filteredItems as model, modelIdx}
|
||||
<Tooltip content={model.id} placement="top-start">
|
||||
<button
|
||||
class="px-2.5 py-1.5 rounded-xl w-full text-left {modelIdx === selectedIdx
|
||||
? 'bg-gray-50 dark:bg-gray-800 selected-command-option-button'
|
||||
class="flex h-[1.6875rem] w-full items-center rounded-xl px-2 text-left text-[13px] hover:bg-gray-50/40 dark:hover:bg-gray-800/40 {modelIdx ===
|
||||
selectedIdx
|
||||
? 'bg-gray-50/40 dark:bg-gray-800/40 selected-command-option-button'
|
||||
: ''}"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
@@ -81,16 +82,16 @@
|
||||
on:focus={() => {}}
|
||||
data-selected={modelIdx === selectedIdx}
|
||||
>
|
||||
<div class="flex text-black dark:text-gray-100 line-clamp-1">
|
||||
<div class="flex min-w-0 items-center text-black dark:text-gray-100">
|
||||
<img
|
||||
src={`${WEBUI_API_BASE_URL}/models/model/profile/image?id=${model.id}&lang=${$i18n.language}`}
|
||||
alt={model?.name ?? model.id}
|
||||
class="rounded-full size-5 items-center mr-2"
|
||||
class="mr-2 size-4.5 rounded-full object-cover"
|
||||
on:error={(e) => {
|
||||
e.currentTarget.src = '/favicon.png';
|
||||
}}
|
||||
/>
|
||||
<div class="truncate">
|
||||
<div class="min-w-0 truncate">
|
||||
{model.name}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -57,18 +57,19 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="px-2 text-xs text-gray-500 py-1">
|
||||
<div class="px-2 py-1 text-[11px] text-gray-500 dark:text-gray-400">
|
||||
{$i18n.t('Prompts')}
|
||||
</div>
|
||||
|
||||
{#if filteredItems.length > 0}
|
||||
<div class=" space-y-0.5 scrollbar-hidden">
|
||||
<div class="scrollbar-hidden">
|
||||
{#each filteredItems as promptItem, promptIdx}
|
||||
<Tooltip content={promptItem.name} placement="top-start">
|
||||
<button
|
||||
class=" px-3 py-1 rounded-xl w-full text-left {promptIdx === selectedPromptIdx
|
||||
? ' bg-gray-50 dark:bg-gray-800 selected-command-option-button'
|
||||
: ''} truncate"
|
||||
class="flex h-[1.6875rem] w-full items-center gap-1.5 rounded-xl px-2 text-left text-[13px] hover:bg-gray-50/40 dark:hover:bg-gray-800/40 {promptIdx ===
|
||||
selectedPromptIdx
|
||||
? 'bg-gray-50/40 dark:bg-gray-800/40 selected-command-option-button'
|
||||
: ''}"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
onSelect({ type: 'prompt', data: promptItem });
|
||||
@@ -79,11 +80,11 @@
|
||||
on:focus={() => {}}
|
||||
data-selected={promptIdx === selectedPromptIdx}
|
||||
>
|
||||
<span class=" font-normal text-black dark:text-gray-100">
|
||||
<span class="shrink-0 font-normal text-black dark:text-gray-100">
|
||||
{promptItem.command}
|
||||
</span>
|
||||
|
||||
<span class=" text-xs text-gray-600 dark:text-gray-100">
|
||||
<span class="min-w-0 truncate text-xs text-gray-500 dark:text-gray-400">
|
||||
{promptItem.name}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="px-2 text-xs text-gray-500 py-1">
|
||||
<div class="px-2 py-1 text-[11px] text-gray-500 dark:text-gray-400">
|
||||
{$i18n.t('Skills')}
|
||||
</div>
|
||||
|
||||
@@ -81,8 +81,9 @@
|
||||
tippyOptions={{ maxWidth: '20rem' }}
|
||||
>
|
||||
<button
|
||||
class="px-2.5 py-1.5 rounded-xl w-full text-left {skillIdx === selectedIdx
|
||||
? 'bg-gray-50 dark:bg-gray-800 selected-command-option-button'
|
||||
class="flex h-[1.6875rem] w-full items-center rounded-xl px-2 text-left text-[13px] hover:bg-gray-50/40 dark:hover:bg-gray-800/40 {skillIdx ===
|
||||
selectedIdx
|
||||
? 'bg-gray-50/40 dark:bg-gray-800/40 selected-command-option-button'
|
||||
: ''}"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
@@ -95,13 +96,13 @@
|
||||
data-selected={skillIdx === selectedIdx}
|
||||
>
|
||||
<div class="flex w-full min-w-0 items-center text-black dark:text-gray-100">
|
||||
<div class="flex items-center justify-center size-5 mr-2 shrink-0">
|
||||
<Cube className="size-4" />
|
||||
<div class="mr-2 flex size-4.5 shrink-0 items-center justify-center">
|
||||
<Cube className="size-3.5" />
|
||||
</div>
|
||||
<div class="truncate min-w-0 flex-1">
|
||||
{skill.name}
|
||||
</div>
|
||||
<div class="ml-2 max-w-24 shrink-0 truncate text-xs text-gray-500">
|
||||
<div class="ml-2 max-w-24 shrink-0 truncate text-xs text-gray-500 dark:text-gray-400">
|
||||
{skill.id}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user