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