Unverified Commit 38ff3209 authored by Timothy Jaeryang Baek's avatar Timothy Jaeryang Baek Committed by GitHub
Browse files

Merge pull request #1881 from open-webui/dev

0.1.123
parents c9589e21 2789102d
...@@ -137,20 +137,22 @@ ...@@ -137,20 +137,22 @@
.getElementById(`message-${message.id}`) .getElementById(`message-${message.id}`)
?.getElementsByClassName('chat-assistant'); ?.getElementsByClassName('chat-assistant');
for (const element of chatMessageElements) { if (chatMessageElements) {
auto_render(element, { for (const element of chatMessageElements) {
// customised options auto_render(element, {
// • auto-render specific keys, e.g.: // customised options
delimiters: [ // • auto-render specific keys, e.g.:
{ left: '$$', right: '$$', display: false }, delimiters: [
{ left: '$ ', right: ' $', display: false }, { left: '$$', right: '$$', display: false },
{ left: '\\(', right: '\\)', display: false }, { left: '$ ', right: ' $', display: false },
{ left: '\\[', right: '\\]', display: false }, { left: '\\(', right: '\\)', display: false },
{ left: '[ ', right: ' ]', display: false } { left: '\\[', right: '\\]', display: false },
], { left: '[ ', right: ' ]', display: false }
// • rendering keys, e.g.: ],
throwOnError: false // • rendering keys, e.g.:
}); throwOnError: false
});
}
} }
}; };
...@@ -325,7 +327,8 @@ ...@@ -325,7 +327,8 @@
{#key message.id} {#key message.id}
<div class=" flex w-full message-{message.id}" id="message-{message.id}"> <div class=" flex w-full message-{message.id}" id="message-{message.id}">
<ProfileImage <ProfileImage
src={modelfiles[message.model]?.imageUrl ?? `${WEBUI_BASE_URL}/static/favicon.png`} src={modelfiles[message.model]?.imageUrl ??
($i18n.language === 'dg-DG' ? `/doge.png` : `${WEBUI_BASE_URL}/static/favicon.png`)}
/> />
<div class="w-full overflow-hidden"> <div class="w-full overflow-hidden">
...@@ -377,7 +380,7 @@ ...@@ -377,7 +380,7 @@
<div class=" mt-2 mb-1 flex justify-center space-x-2 text-sm font-medium"> <div class=" mt-2 mb-1 flex justify-center space-x-2 text-sm font-medium">
<button <button
class="px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg-lg" class="px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
on:click={() => { on:click={() => {
editMessageConfirmHandler(); editMessageConfirmHandler();
}} }}
...@@ -492,7 +495,7 @@ ...@@ -492,7 +495,7 @@
{/if} {/if}
{#if !readOnly} {#if !readOnly}
<Tooltip content="Edit" placement="bottom"> <Tooltip content={$i18n.t('Edit')} placement="bottom">
<button <button
class="{isLastMessage class="{isLastMessage
? 'visible' ? 'visible'
...@@ -519,7 +522,7 @@ ...@@ -519,7 +522,7 @@
</Tooltip> </Tooltip>
{/if} {/if}
<Tooltip content="Copy" placement="bottom"> <Tooltip content={$i18n.t('Copy')} placement="bottom">
<button <button
class="{isLastMessage class="{isLastMessage
? 'visible' ? 'visible'
...@@ -546,7 +549,7 @@ ...@@ -546,7 +549,7 @@
</Tooltip> </Tooltip>
{#if !readOnly} {#if !readOnly}
<Tooltip content="Good Response" placement="bottom"> <Tooltip content={$i18n.t('Good Response')} placement="bottom">
<button <button
class="{isLastMessage class="{isLastMessage
? 'visible' ? 'visible'
...@@ -581,7 +584,7 @@ ...@@ -581,7 +584,7 @@
</button> </button>
</Tooltip> </Tooltip>
<Tooltip content="Bad Response" placement="bottom"> <Tooltip content={$i18n.t('Bad Response')} placement="bottom">
<button <button
class="{isLastMessage class="{isLastMessage
? 'visible' ? 'visible'
...@@ -616,7 +619,7 @@ ...@@ -616,7 +619,7 @@
</Tooltip> </Tooltip>
{/if} {/if}
<Tooltip content="Read Aloud" placement="bottom"> <Tooltip content={$i18n.t('Read Aloud')} placement="bottom">
<button <button
id="speak-button-{message.id}" id="speak-button-{message.id}"
class="{isLastMessage class="{isLastMessage
...@@ -765,7 +768,7 @@ ...@@ -765,7 +768,7 @@
{/if} {/if}
{#if message.info} {#if message.info}
<Tooltip content="Generation Info" placement="bottom"> <Tooltip content={$i18n.t('Generation Info')} placement="bottom">
<button <button
class=" {isLastMessage class=" {isLastMessage
? 'visible' ? 'visible'
...@@ -794,7 +797,7 @@ ...@@ -794,7 +797,7 @@
{/if} {/if}
{#if isLastMessage && !readOnly} {#if isLastMessage && !readOnly}
<Tooltip content="Continue Response" placement="bottom"> <Tooltip content={$i18n.t('Continue Response')} placement="bottom">
<button <button
type="button" type="button"
class="{isLastMessage class="{isLastMessage
...@@ -826,7 +829,7 @@ ...@@ -826,7 +829,7 @@
</button> </button>
</Tooltip> </Tooltip>
<Tooltip content="Regenerate" placement="bottom"> <Tooltip content={$i18n.t('Regenerate')} placement="bottom">
<button <button
type="button" type="button"
class="{isLastMessage class="{isLastMessage
......
...@@ -193,7 +193,7 @@ ...@@ -193,7 +193,7 @@
<div class=" mt-2 mb-1 flex justify-center space-x-2 text-sm font-medium"> <div class=" mt-2 mb-1 flex justify-center space-x-2 text-sm font-medium">
<button <button
id="save-edit-message-button" id="save-edit-message-button"
class="px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg-lg" class="px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
on:click={() => { on:click={() => {
editMessageConfirmHandler(); editMessageConfirmHandler();
}} }}
...@@ -266,7 +266,7 @@ ...@@ -266,7 +266,7 @@
{/if} {/if}
{#if !readOnly} {#if !readOnly}
<Tooltip content="Edit" placement="bottom"> <Tooltip content={$i18n.t('Edit')} placement="bottom">
<button <button
class="invisible group-hover:visible p-1 rounded dark:hover:text-white hover:text-black transition edit-user-message-button" class="invisible group-hover:visible p-1 rounded dark:hover:text-white hover:text-black transition edit-user-message-button"
on:click={() => { on:click={() => {
...@@ -291,7 +291,7 @@ ...@@ -291,7 +291,7 @@
</Tooltip> </Tooltip>
{/if} {/if}
<Tooltip content="Copy" placement="bottom"> <Tooltip content={$i18n.t('Copy')} placement="bottom">
<button <button
class="invisible group-hover:visible p-1 rounded dark:hover:text-white hover:text-black transition" class="invisible group-hover:visible p-1 rounded dark:hover:text-white hover:text-black transition"
on:click={() => { on:click={() => {
...@@ -316,7 +316,7 @@ ...@@ -316,7 +316,7 @@
</Tooltip> </Tooltip>
{#if !isFirstMessage && !readOnly} {#if !isFirstMessage && !readOnly}
<Tooltip content="Delete" placement="bottom"> <Tooltip content={$i18n.t('Delete')} placement="bottom">
<button <button
class="invisible group-hover:visible p-1 rounded dark:hover:text-white hover:text-black transition" class="invisible group-hover:visible p-1 rounded dark:hover:text-white hover:text-black transition"
on:click={() => { on:click={() => {
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
export let selectedModels = ['']; export let selectedModels = [''];
export let disabled = false; export let disabled = false;
export let showSetDefault = true;
const saveDefaultModel = async () => { const saveDefaultModel = async () => {
const hasEmptyModel = selectedModels.filter((it) => it === ''); const hasEmptyModel = selectedModels.filter((it) => it === '');
if (hasEmptyModel.length) { if (hasEmptyModel.length) {
...@@ -38,9 +40,9 @@ ...@@ -38,9 +40,9 @@
<div class="flex flex-col mt-0.5 w-full"> <div class="flex flex-col mt-0.5 w-full">
{#each selectedModels as selectedModel, selectedModelIdx} {#each selectedModels as selectedModel, selectedModelIdx}
<div class="flex w-full"> <div class="flex w-full max-w-fit">
<div class="overflow-hidden w-full"> <div class="overflow-hidden w-full">
<div class="mr-0.5 max-w-full"> <div class="mr-1 max-w-full">
<Selector <Selector
placeholder={$i18n.t('Select a model')} placeholder={$i18n.t('Select a model')}
items={$models items={$models
...@@ -57,7 +59,7 @@ ...@@ -57,7 +59,7 @@
{#if selectedModelIdx === 0} {#if selectedModelIdx === 0}
<div class=" self-center mr-2 disabled:text-gray-600 disabled:hover:text-gray-600"> <div class=" self-center mr-2 disabled:text-gray-600 disabled:hover:text-gray-600">
<Tooltip content="Add Model"> <Tooltip content={$i18n.t('Add Model')}>
<button <button
class=" " class=" "
{disabled} {disabled}
...@@ -69,9 +71,9 @@ ...@@ -69,9 +71,9 @@
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
fill="none" fill="none"
viewBox="0 0 24 24" viewBox="0 0 24 24"
stroke-width="1.5" stroke-width="2"
stroke="currentColor" stroke="currentColor"
class="w-4 h-4" class="size-3.5"
> >
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v12m6-6H6" /> <path stroke-linecap="round" stroke-linejoin="round" d="M12 6v12m6-6H6" />
</svg> </svg>
...@@ -92,9 +94,9 @@ ...@@ -92,9 +94,9 @@
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
fill="none" fill="none"
viewBox="0 0 24 24" viewBox="0 0 24 24"
stroke-width="1.5" stroke-width="2"
stroke="currentColor" stroke="currentColor"
class="w-4 h-4" class="size-3.5"
> >
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 12h-15" /> <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 12h-15" />
</svg> </svg>
...@@ -106,6 +108,8 @@ ...@@ -106,6 +108,8 @@
{/each} {/each}
</div> </div>
<div class="text-left mt-0.5 ml-1 text-[0.7rem] text-gray-500"> {#if showSetDefault}
<button on:click={saveDefaultModel}> {$i18n.t('Set as default')}</button> <div class="text-left mt-0.5 ml-1 text-[0.7rem] text-gray-500">
</div> <button on:click={saveDefaultModel}> {$i18n.t('Set as default')}</button>
</div>
{/if}
<script lang="ts"> <script lang="ts">
import { Select } from 'bits-ui'; import { DropdownMenu } from 'bits-ui';
import { flyAndScale } from '$lib/utils/transitions'; import { flyAndScale } from '$lib/utils/transitions';
import { createEventDispatcher, onMount, getContext, tick } from 'svelte'; import { createEventDispatcher, onMount, getContext, tick } from 'svelte';
...@@ -21,10 +21,15 @@ ...@@ -21,10 +21,15 @@
export let value = ''; export let value = '';
export let placeholder = 'Select a model'; export let placeholder = 'Select a model';
export let searchEnabled = true; export let searchEnabled = true;
export let searchPlaceholder = 'Search a model'; export let searchPlaceholder = $i18n.t('Search a model');
export let items = [{ value: 'mango', label: 'Mango' }]; export let items = [{ value: 'mango', label: 'Mango' }];
export let className = 'max-w-lg';
let selectedModel = '';
$: selectedModel = items.find((item) => item.value === value) ?? '';
let searchValue = ''; let searchValue = '';
let ollamaVersion = null; let ollamaVersion = null;
...@@ -175,27 +180,28 @@ ...@@ -175,27 +180,28 @@
}; };
</script> </script>
<Select.Root <DropdownMenu.Root
{items}
onOpenChange={async () => { onOpenChange={async () => {
searchValue = ''; searchValue = '';
window.setTimeout(() => document.getElementById('model-search-input')?.focus(), 0); window.setTimeout(() => document.getElementById('model-search-input')?.focus(), 0);
}} }}
selected={items.find((item) => item.value === value) ?? ''}
onSelectedChange={(selectedItem) => {
value = selectedItem.value;
}}
> >
<Select.Trigger class="relative w-full" aria-label={placeholder}> <DropdownMenu.Trigger class="relative w-full" aria-label={placeholder}>
<Select.Value <div
class="flex text-left px-0.5 outline-none bg-transparent truncate text-lg font-semibold placeholder-gray-400 focus:outline-none" class="flex w-full text-left px-0.5 outline-none bg-transparent truncate text-lg font-semibold placeholder-gray-400 focus:outline-none"
{placeholder} >
/> {#if selectedModel}
<ChevronDown className="absolute end-2 top-1/2 -translate-y-[45%] size-3.5" strokeWidth="2.5" /> {selectedModel.label}
</Select.Trigger> {:else}
<Select.Content {placeholder}
class=" z-40 w-full rounded-lg bg-white dark:bg-gray-900 dark:text-white shadow-lg border border-gray-300/30 dark:border-gray-700/50 outline-none" {/if}
<ChevronDown className=" self-center ml-2 size-3" strokeWidth="2.5" />
</div>
</DropdownMenu.Trigger>
<DropdownMenu.Content
class=" z-40 w-full {className} justify-start rounded-lg bg-white dark:bg-gray-900 dark:text-white shadow-lg border border-gray-300/30 dark:border-gray-700/50 outline-none "
transition={flyAndScale} transition={flyAndScale}
side={'bottom-start'}
sideOffset={4} sideOffset={4}
> >
<slot> <slot>
...@@ -214,12 +220,13 @@ ...@@ -214,12 +220,13 @@
<hr class="border-gray-100 dark:border-gray-800" /> <hr class="border-gray-100 dark:border-gray-800" />
{/if} {/if}
<div class="px-3 my-2 max-h-72 overflow-y-auto"> <div class="px-3 my-2 max-h-72 overflow-y-auto scrollbar-none">
{#each filteredItems as item} {#each filteredItems as item}
<Select.Item <DropdownMenu.Item
class="flex w-full font-medium line-clamp-1 select-none items-center rounded-button py-2 pl-3 pr-1.5 text-sm text-gray-700 dark:text-gray-100 outline-none transition-all duration-75 hover:bg-gray-100 dark:hover:bg-gray-850 rounded-lg cursor-pointer data-[highlighted]:bg-muted" class="flex w-full font-medium line-clamp-1 select-none items-center rounded-button py-2 pl-3 pr-1.5 text-sm text-gray-700 dark:text-gray-100 outline-none transition-all duration-75 hover:bg-gray-100 dark:hover:bg-gray-850 rounded-lg cursor-pointer data-[highlighted]:bg-muted"
value={item.value} on:click={() => {
label={item.label} value = item.value;
}}
> >
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<div class="line-clamp-1"> <div class="line-clamp-1">
...@@ -287,7 +294,7 @@ ...@@ -287,7 +294,7 @@
<Check /> <Check />
</div> </div>
{/if} {/if}
</Select.Item> </DropdownMenu.Item>
{:else} {:else}
<div> <div>
<div class="block px-3 py-2 text-sm text-gray-700 dark:text-gray-100"> <div class="block px-3 py-2 text-sm text-gray-700 dark:text-gray-100">
...@@ -385,5 +392,16 @@ ...@@ -385,5 +392,16 @@
{/each} {/each}
</div> </div>
</slot> </slot>
</Select.Content> </DropdownMenu.Content>
</Select.Root> </DropdownMenu.Root>
<style>
.scrollbar-none:active::-webkit-scrollbar-thumb,
.scrollbar-none:focus::-webkit-scrollbar-thumb,
.scrollbar-none:hover::-webkit-scrollbar-thumb {
visibility: visible;
}
.scrollbar-none::-webkit-scrollbar-thumb {
visibility: hidden;
}
</style>
...@@ -492,8 +492,8 @@ ...@@ -492,8 +492,8 @@
<input <input
id="steps-range" id="steps-range"
type="range" type="range"
min="1" min="-1"
max="16000" max="10240000"
step="1" step="1"
bind:value={options.num_ctx} bind:value={options.num_ctx}
class="w-full h-2 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" class="w-full h-2 rounded-lg appearance-none cursor-pointer dark:bg-gray-700"
...@@ -504,9 +504,8 @@ ...@@ -504,9 +504,8 @@
bind:value={options.num_ctx} bind:value={options.num_ctx}
type="number" type="number"
class=" bg-transparent text-center w-14" class=" bg-transparent text-center w-14"
min="1" min="-1"
max="16000" step="10"
step="1"
/> />
</div> </div>
</div> </div>
......
...@@ -106,6 +106,7 @@ ...@@ -106,6 +106,7 @@
responseAutoCopy = settings.responseAutoCopy ?? false; responseAutoCopy = settings.responseAutoCopy ?? false;
showUsername = settings.showUsername ?? false; showUsername = settings.showUsername ?? false;
fullScreenMode = settings.fullScreenMode ?? false; fullScreenMode = settings.fullScreenMode ?? false;
splitLargeChunks = settings.splitLargeChunks ?? false;
}); });
</script> </script>
......
...@@ -35,8 +35,8 @@ ...@@ -35,8 +35,8 @@
</script> </script>
<Modal bind:show> <Modal bind:show>
<div> <div class="text-gray-700 dark:text-gray-100">
<div class=" flex justify-between dark:text-gray-300 px-5 py-4"> <div class=" flex justify-between dark:text-gray-300 px-5 pt-4 pb-1">
<div class=" text-lg font-medium self-center">{$i18n.t('Settings')}</div> <div class=" text-lg font-medium self-center">{$i18n.t('Settings')}</div>
<button <button
class="self-center" class="self-center"
...@@ -56,7 +56,6 @@ ...@@ -56,7 +56,6 @@
</svg> </svg>
</button> </button>
</div> </div>
<hr class=" dark:border-gray-800" />
<div class="flex flex-col md:flex-row w-full p-4 md:space-x-4"> <div class="flex flex-col md:flex-row w-full p-4 md:space-x-4">
<div <div
......
...@@ -71,7 +71,7 @@ ...@@ -71,7 +71,7 @@
<Modal bind:show size="sm"> <Modal bind:show size="sm">
<div> <div>
<div class=" flex justify-between dark:text-gray-300 px-5 py-4"> <div class=" flex justify-between dark:text-gray-300 px-5 pt-4 pb-0.5">
<div class=" text-lg font-medium self-center">{$i18n.t('Share Chat')}</div> <div class=" text-lg font-medium self-center">{$i18n.t('Share Chat')}</div>
<button <button
class="self-center" class="self-center"
...@@ -91,10 +91,9 @@ ...@@ -91,10 +91,9 @@
</svg> </svg>
</button> </button>
</div> </div>
<hr class=" dark:border-gray-800" />
{#if chat} {#if chat}
<div class="px-4 pt-4 pb-5 w-full flex flex-col justify-center"> <div class="px-5 pt-4 pb-5 w-full flex flex-col justify-center">
<div class=" text-sm dark:text-gray-300 mb-1"> <div class=" text-sm dark:text-gray-300 mb-1">
{#if chat.share_id} {#if chat.share_id}
<a href="/s/{chat.share_id}" target="_blank" <a href="/s/{chat.share_id}" target="_blank"
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
</script> </script>
<Modal bind:show> <Modal bind:show>
<div> <div class="text-gray-700 dark:text-gray-100">
<div class=" flex justify-between dark:text-gray-300 px-5 py-4"> <div class=" flex justify-between dark:text-gray-300 px-5 pt-4">
<div class=" text-lg font-medium self-center">{$i18n.t('Keyboard shortcuts')}</div> <div class=" text-lg font-medium self-center">{$i18n.t('Keyboard shortcuts')}</div>
<button <button
class="self-center" class="self-center"
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
</svg> </svg>
</button> </button>
</div> </div>
<hr class=" dark:border-gray-800" />
<div class="flex flex-col md:flex-row w-full p-5 md:space-x-4 dark:text-gray-200"> <div class="flex flex-col md:flex-row w-full p-5 md:space-x-4 dark:text-gray-200">
<div class=" flex flex-col w-full sm:flex-row sm:justify-center sm:space-x-6"> <div class=" flex flex-col w-full sm:flex-row sm:justify-center sm:space-x-6">
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
bind:this={modalElement} bind:this={modalElement}
class=" fixed top-0 right-0 left-0 bottom-0 bg-black/60 w-full min-h-screen h-screen flex justify-center z-[9999] overflow-hidden overscroll-contain" class=" fixed top-0 right-0 left-0 bottom-0 bg-black/60 w-full min-h-screen h-screen flex justify-center z-[9999] overflow-hidden overscroll-contain"
in:fade={{ duration: 10 }} in:fade={{ duration: 10 }}
on:click={() => { on:mousedown={() => {
show = false; show = false;
}} }}
> >
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
size size
)} mx-2 bg-gray-50 dark:bg-gray-900 shadow-3xl" )} mx-2 bg-gray-50 dark:bg-gray-900 shadow-3xl"
in:flyAndScale in:flyAndScale
on:click={(e) => { on:mousedown={(e) => {
e.stopPropagation(); e.stopPropagation();
}} }}
> >
......
<script lang="ts"> <script lang="ts">
import TagInput from './Tags/TagInput.svelte'; import TagInput from './Tags/TagInput.svelte';
import TagList from './Tags/TagList.svelte'; import TagList from './Tags/TagList.svelte';
import { getContext } from 'svelte';
const i18n = getContext('i18n');
export let tags = []; export let tags = [];
...@@ -17,7 +20,7 @@ ...@@ -17,7 +20,7 @@
/> />
<TagInput <TagInput
label={tags.length == 0 ? 'Add Tags' : ''} label={tags.length == 0 ? $i18n.t('Add Tags') : ''}
on:add={(e) => { on:add={(e) => {
addTag(e.detail); addTag(e.detail);
}} }}
......
...@@ -96,7 +96,7 @@ ...@@ -96,7 +96,7 @@
<Modal size="sm" bind:show> <Modal size="sm" bind:show>
<div> <div>
<div class=" flex justify-between dark:text-gray-300 px-5 py-4"> <div class=" flex justify-between dark:text-gray-300 px-5 pt-4">
<div class=" text-lg font-medium self-center">{$i18n.t('Add Docs')}</div> <div class=" text-lg font-medium self-center">{$i18n.t('Add Docs')}</div>
<button <button
class="self-center" class="self-center"
...@@ -116,8 +116,6 @@ ...@@ -116,8 +116,6 @@
</svg> </svg>
</button> </button>
</div> </div>
<hr class=" dark:border-gray-800" />
<div class="flex flex-col md:flex-row w-full px-5 py-4 md:space-x-4 dark:text-gray-200"> <div class="flex flex-col md:flex-row w-full px-5 py-4 md:space-x-4 dark:text-gray-200">
<div class=" flex flex-col w-full sm:flex-row sm:justify-center sm:space-x-6"> <div class=" flex flex-col w-full sm:flex-row sm:justify-center sm:space-x-6">
<form <form
......
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
<Modal size="sm" bind:show> <Modal size="sm" bind:show>
<div> <div>
<div class=" flex justify-between dark:text-gray-300 px-5 py-4"> <div class=" flex justify-between dark:text-gray-300 px-5 pt-4">
<div class=" text-lg font-medium self-center">{$i18n.t('Edit Doc')}</div> <div class=" text-lg font-medium self-center">{$i18n.t('Edit Doc')}</div>
<button <button
class="self-center" class="self-center"
...@@ -95,8 +95,6 @@ ...@@ -95,8 +95,6 @@
</svg> </svg>
</button> </button>
</div> </div>
<hr class=" dark:border-gray-800" />
<div class="flex flex-col md:flex-row w-full px-5 py-4 md:space-x-4 dark:text-gray-200"> <div class="flex flex-col md:flex-row w-full px-5 py-4 md:space-x-4 dark:text-gray-200">
<div class=" flex flex-col w-full sm:flex-row sm:justify-center sm:space-x-6"> <div class=" flex flex-col w-full sm:flex-row sm:justify-center sm:space-x-6">
<form <form
...@@ -111,28 +109,18 @@ ...@@ -111,28 +109,18 @@
<div class="flex flex-1"> <div class="flex flex-1">
<div <div
class="bg-gray-200 dark:bg-gray-600 font-bold px-3 py-1 border border-r-0 dark:border-gray-600 rounded-l-lg flex items-center" class="bg-gray-200 dark:bg-gray-800 font-bold px-3 py-0.5 border border-r-0 dark:border-gray-800 rounded-l-xl flex items-center"
> >
# #
</div> </div>
<input <input
class="w-full rounded-r-lg py-2.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-800 disabled:text-gray-500 dark:disabled:text-gray-500 outline-none" class="w-full rounded-r-xl py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 disabled:text-gray-500 dark:disabled:text-gray-500 outline-none"
type="text" type="text"
bind:value={doc.name} bind:value={doc.name}
autocomplete="off" autocomplete="off"
required required
/> />
</div> </div>
<!-- <div class="flex-1">
<input
class="w-full rounded py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-800 disabled:text-gray-500 dark:disabled:text-gray-500 outline-none"
type="text"
bind:value={doc.name}
autocomplete="off"
required
/>
</div> -->
</div> </div>
<div class="flex flex-col w-full"> <div class="flex flex-col w-full">
...@@ -140,7 +128,7 @@ ...@@ -140,7 +128,7 @@
<div class="flex-1"> <div class="flex-1">
<input <input
class="w-full rounded-lg py-2.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-800 outline-none" class="w-full rounded-xl py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
type="text" type="text"
bind:value={doc.title} bind:value={doc.title}
autocomplete="off" autocomplete="off"
...@@ -150,7 +138,7 @@ ...@@ -150,7 +138,7 @@
</div> </div>
<div class="flex flex-col w-full"> <div class="flex flex-col w-full">
<div class=" mb-1.5 text-xs text-gray-500">{$i18n.t('Tags')}</div> <div class=" mb-2 text-xs text-gray-500">{$i18n.t('Tags')}</div>
<Tags {tags} addTag={addTagHandler} deleteTag={deleteTagHandler} /> <Tags {tags} addTag={addTagHandler} deleteTag={deleteTagHandler} />
</div> </div>
......
...@@ -137,9 +137,15 @@ ...@@ -137,9 +137,15 @@
if (res) { if (res) {
console.log('rerankingModelUpdateHandler:', res); console.log('rerankingModelUpdateHandler:', res);
if (res.status === true) { if (res.status === true) {
toast.success($i18n.t('Reranking model set to "{{reranking_model}}"', res), { if (rerankingModel === '') {
duration: 1000 * 10 toast.success($i18n.t('Reranking model disabled', res), {
}); duration: 1000 * 10
});
} else {
toast.success($i18n.t('Reranking model set to "{{reranking_model}}"', res), {
duration: 1000 * 10
});
}
} }
} }
}; };
...@@ -584,12 +590,12 @@ ...@@ -584,12 +590,12 @@
<hr class=" dark:border-gray-700 my-3" /> <hr class=" dark:border-gray-700 my-3" />
<div> <div class=" ">
<div class=" text-sm font-medium">{$i18n.t('Query Params')}</div> <div class=" text-sm font-medium">{$i18n.t('Query Params')}</div>
<div class=" flex"> <div class=" flex">
<div class=" flex w-full justify-between"> <div class=" flex w-full justify-between">
<div class="self-center text-xs font-medium flex-1">{$i18n.t('Top K')}</div> <div class="self-center text-xs font-medium min-w-fit">{$i18n.t('Top K')}</div>
<div class="self-center p-3"> <div class="self-center p-3">
<input <input
...@@ -602,13 +608,11 @@ ...@@ -602,13 +608,11 @@
/> />
</div> </div>
</div> </div>
</div>
{#if querySettings.hybrid === true} {#if querySettings.hybrid === true}
<div class=" flex"> <div class="flex w-full">
<div class=" flex w-full justify-between"> <div class=" self-center text-xs font-medium min-w-fit">
<div class="self-center text-xs font-medium flex-1"> {$i18n.t('Minimum Score')}
{$i18n.t('Relevance Threshold')}
</div> </div>
<div class="self-center p-3"> <div class="self-center p-3">
...@@ -616,14 +620,25 @@ ...@@ -616,14 +620,25 @@
class=" w-full rounded-lg py-1.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none" class=" w-full rounded-lg py-1.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
type="number" type="number"
step="0.01" step="0.01"
placeholder={$i18n.t('Enter Relevance Threshold')} placeholder={$i18n.t('Enter Score')}
bind:value={querySettings.r} bind:value={querySettings.r}
autocomplete="off" autocomplete="off"
min="0.0" min="0.0"
title={$i18n.t('The score should be a value between 0.0 (0%) and 1.0 (100%).')}
/> />
</div> </div>
</div> </div>
{/if}
</div>
{#if querySettings.hybrid === true}
<div class="mt-2 mb-1 text-xs text-gray-400 dark:text-gray-500">
{$i18n.t(
'Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.'
)}
</div> </div>
<hr class=" dark:border-gray-700 my-3" />
{/if} {/if}
<div> <div>
...@@ -636,8 +651,6 @@ ...@@ -636,8 +651,6 @@
</div> </div>
</div> </div>
<hr class=" dark:border-gray-700 my-3" />
{#if showResetConfirm} {#if showResetConfirm}
<div class="flex justify-between rounded-md items-center py-2 px-3.5 w-full transition"> <div class="flex justify-between rounded-md items-center py-2 px-3.5 w-full transition">
<div class="flex items-center space-x-3"> <div class="flex items-center space-x-3">
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
<Modal bind:show> <Modal bind:show>
<div> <div>
<div class=" flex justify-between dark:text-gray-300 px-5 py-4"> <div class=" flex justify-between dark:text-gray-300 px-5 pt-4">
<div class=" text-lg font-medium self-center">{$i18n.t('Document Settings')}</div> <div class=" text-lg font-medium self-center">{$i18n.t('Document Settings')}</div>
<button <button
class="self-center" class="self-center"
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
</svg> </svg>
</button> </button>
</div> </div>
<hr class=" dark:border-gray-800" />
<div class="flex flex-col md:flex-row w-full p-4 md:space-x-4"> <div class="flex flex-col md:flex-row w-full p-4 md:space-x-4">
<div <div
......
<script lang="ts">
export let className = 'size-3';
export let strokeWidth = '1.5';
</script>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width={strokeWidth}
stroke="currentColor"
class={className}
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="m3.75 13.5 10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75Z"
/>
</svg>
<script lang="ts">
export let className = 'size-3.5';
export let strokeWidth = '2';
</script>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width={strokeWidth}
stroke="currentColor"
class={className}
>
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
</svg>
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
import ModelSelector from '../chat/ModelSelector.svelte'; import ModelSelector from '../chat/ModelSelector.svelte';
import Tooltip from '../common/Tooltip.svelte'; import Tooltip from '../common/Tooltip.svelte';
import Menu from './Navbar/Menu.svelte'; import Menu from './Navbar/Menu.svelte';
import { page } from '$app/stores';
const i18n = getContext('i18n'); const i18n = getContext('i18n');
...@@ -27,22 +28,19 @@ ...@@ -27,22 +28,19 @@
<ShareChatModal bind:show={showShareChatModal} chatId={$chatId} /> <ShareChatModal bind:show={showShareChatModal} chatId={$chatId} />
<nav id="nav" class=" sticky py-2.5 top-0 flex flex-row justify-center z-30"> <nav id="nav" class=" sticky py-2.5 top-0 flex flex-row justify-center z-30">
<div <div class=" flex max-w-full w-full mx-auto px-5 pt-0.5 md:px-[1.3rem]">
class=" flex {$settings?.fullScreenMode ?? null ? 'max-w-full' : 'max-w-3xl'}
w-full mx-auto px-3"
>
<div class="flex items-center w-full max-w-full"> <div class="flex items-center w-full max-w-full">
<div class="flex-1 overflow-hidden max-w-full"> <div class="flex-1 overflow-hidden max-w-full">
{#if showModelSelector} {#if showModelSelector}
<ModelSelector bind:selectedModels /> <ModelSelector bind:selectedModels showSetDefault={!shareEnabled} />
{/if} {/if}
</div> </div>
<div class="self-start flex flex-none items-center"> <div class="self-start flex flex-none items-center">
<div class="flex self-center w-[1px] h-5 mx-2 bg-gray-300 dark:bg-stone-700" /> <div class="md:hidden flex self-center w-[1px] h-5 mx-2 bg-gray-300 dark:bg-stone-700" />
{#if !shareEnabled} {#if !shareEnabled}
<Tooltip content="Settings"> <Tooltip content={$i18n.t('Settings')}>
<button <button
class="cursor-pointer p-1.5 flex dark:hover:bg-gray-700 rounded-full transition" class="cursor-pointer p-1.5 flex dark:hover:bg-gray-700 rounded-full transition"
id="open-settings-button" id="open-settings-button"
...@@ -104,7 +102,7 @@ ...@@ -104,7 +102,7 @@
</button> </button>
</Menu> </Menu>
{/if} {/if}
<Tooltip content="New Chat"> <Tooltip content={$i18n.t('New Chat')}>
<button <button
id="new-chat-button" id="new-chat-button"
class=" cursor-pointer p-1.5 flex dark:hover:bg-gray-700 rounded-full transition" class=" cursor-pointer p-1.5 flex dark:hover:bg-gray-700 rounded-full transition"
......
<script lang="ts"> <script lang="ts">
import { DropdownMenu } from 'bits-ui'; import { DropdownMenu } from 'bits-ui';
import { getContext } from 'svelte';
import fileSaver from 'file-saver'; import fileSaver from 'file-saver';
const { saveAs } = fileSaver; const { saveAs } = fileSaver;
...@@ -12,6 +13,8 @@ ...@@ -12,6 +13,8 @@
import { downloadChatAsPDF } from '$lib/apis/utils'; import { downloadChatAsPDF } from '$lib/apis/utils';
const i18n = getContext('i18n');
export let shareEnabled: boolean = false; export let shareEnabled: boolean = false;
export let shareHandler: Function; export let shareHandler: Function;
export let downloadHandler: Function; export let downloadHandler: Function;
...@@ -104,7 +107,7 @@ ...@@ -104,7 +107,7 @@
d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"
/> />
</svg> </svg>
<div class="flex items-center">Settings</div> <div class="flex items-center">{$i18n.t('Settings')}</div>
</DropdownMenu.Item> </DropdownMenu.Item>
{#if shareEnabled} {#if shareEnabled}
...@@ -126,7 +129,7 @@ ...@@ -126,7 +129,7 @@
clip-rule="evenodd" clip-rule="evenodd"
/> />
</svg> </svg>
<div class="flex items-center">Share</div> <div class="flex items-center">{$i18n.t('Share')}</div>
</DropdownMenu.Item> </DropdownMenu.Item>
<!-- <DropdownMenu.Item <!-- <DropdownMenu.Item
...@@ -154,7 +157,7 @@ ...@@ -154,7 +157,7 @@
/> />
</svg> </svg>
<div class="flex items-center">Download</div> <div class="flex items-center">{$i18n.t('Download')}</div>
</DropdownMenu.SubTrigger> </DropdownMenu.SubTrigger>
<DropdownMenu.SubContent <DropdownMenu.SubContent
class="w-full rounded-lg px-1 py-1.5 border border-gray-300/30 dark:border-gray-700/50 z-50 bg-white dark:bg-gray-900 dark:text-white shadow-lg" class="w-full rounded-lg px-1 py-1.5 border border-gray-300/30 dark:border-gray-700/50 z-50 bg-white dark:bg-gray-900 dark:text-white shadow-lg"
...@@ -167,7 +170,7 @@ ...@@ -167,7 +170,7 @@
downloadTxt(); downloadTxt();
}} }}
> >
<div class="flex items-center line-clamp-1">Plain text (.txt)</div> <div class="flex items-center line-clamp-1">{$i18n.t('Plain text (.txt)')}</div>
</DropdownMenu.Item> </DropdownMenu.Item>
<DropdownMenu.Item <DropdownMenu.Item
...@@ -176,7 +179,7 @@ ...@@ -176,7 +179,7 @@
downloadPdf(); downloadPdf();
}} }}
> >
<div class="flex items-center line-clamp-1">PDF document (.pdf)</div> <div class="flex items-center line-clamp-1">{$i18n.t('PDF document (.pdf)')}</div>
</DropdownMenu.Item> </DropdownMenu.Item>
</DropdownMenu.SubContent> </DropdownMenu.SubContent>
</DropdownMenu.Sub> </DropdownMenu.Sub>
......
<script lang="ts"> <script lang="ts">
import { v4 as uuidv4 } from 'uuid'; import { goto } from '$app/navigation';
import { user, chats, settings, showSettings, chatId, tags, showSidebar } from '$lib/stores';
import fileSaver from 'file-saver';
const { saveAs } = fileSaver;
import { goto, invalidateAll } from '$app/navigation';
import { page } from '$app/stores';
import { user, chats, settings, showSettings, chatId, tags } from '$lib/stores';
import { onMount, getContext } from 'svelte'; import { onMount, getContext } from 'svelte';
const i18n = getContext('i18n'); const i18n = getContext('i18n');
...@@ -30,6 +24,7 @@ ...@@ -30,6 +24,7 @@
import ArchivedChatsModal from './Sidebar/ArchivedChatsModal.svelte'; import ArchivedChatsModal from './Sidebar/ArchivedChatsModal.svelte';
const BREAKPOINT = 1024; const BREAKPOINT = 1024;
let show = false; let show = false;
let navElement; let navElement;
...@@ -50,48 +45,49 @@ ...@@ -50,48 +45,49 @@
let isEditing = false; let isEditing = false;
onMount(async () => { onMount(async () => {
show = window.innerWidth > BREAKPOINT; showSidebar.set(window.innerWidth > BREAKPOINT);
await chats.set(await getChatList(localStorage.token)); await chats.set(await getChatList(localStorage.token));
let touchstartX = 0; let touchstart;
let touchendX = 0; let touchend;
function checkDirection() { function checkDirection() {
const screenWidth = window.innerWidth; const screenWidth = window.innerWidth;
const swipeDistance = Math.abs(touchendX - touchstartX); const swipeDistance = Math.abs(touchend.screenX - touchstart.screenX);
if (swipeDistance >= screenWidth / 4) { if (touchstart.clientX < 40 && swipeDistance >= screenWidth / 8) {
if (touchendX < touchstartX) { if (touchend.screenX < touchstart.screenX) {
show = false; showSidebar.set(false);
} }
if (touchendX > touchstartX) { if (touchend.screenX > touchstart.screenX) {
show = true; showSidebar.set(true);
} }
} }
} }
const onTouchStart = (e) => { const onTouchStart = (e) => {
touchstartX = e.changedTouches[0].screenX; touchstart = e.changedTouches[0];
console.log(touchstart.clientX);
}; };
const onTouchEnd = (e) => { const onTouchEnd = (e) => {
touchendX = e.changedTouches[0].screenX; touchend = e.changedTouches[0];
checkDirection(); checkDirection();
}; };
const onResize = () => { const onResize = () => {
if (show && window.innerWidth < BREAKPOINT) { if ($showSidebar && window.innerWidth < BREAKPOINT) {
show = false; showSidebar.set(false);
} }
}; };
document.addEventListener('touchstart', onTouchStart); window.addEventListener('touchstart', onTouchStart);
document.addEventListener('touchend', onTouchEnd); window.addEventListener('touchend', onTouchEnd);
window.addEventListener('resize', onResize); window.addEventListener('resize', onResize);
return () => { return () => {
document.removeEventListener('touchstart', onTouchStart); window.removeEventListener('touchstart', onTouchStart);
document.removeEventListener('touchend', onTouchEnd); window.removeEventListener('touchend', onTouchEnd);
document.removeEventListener('resize', onResize); window.removeEventListener('resize', onResize);
}; };
}); });
...@@ -166,13 +162,15 @@ ...@@ -166,13 +162,15 @@
<div <div
bind:this={navElement} bind:this={navElement}
class="h-screen max-h-[100dvh] min-h-screen {show id="sidebar"
class="h-screen max-h-[100dvh] min-h-screen {$showSidebar
? 'lg:relative w-[260px]' ? 'lg:relative w-[260px]'
: '-translate-x-[260px] w-[0px]'} bg-gray-50 text-gray-900 dark:bg-gray-950 dark:text-gray-200 text-sm transition fixed z-50 top-0 left-0 : '-translate-x-[260px] w-[0px]'} bg-gray-50 text-gray-900 dark:bg-gray-950 dark:text-gray-200 text-sm transition fixed z-50 top-0 left-0 rounded-r-2xl
" "
data-state={$showSidebar}
> >
<div <div
class="py-2.5 my-auto flex flex-col justify-between h-screen max-h-[100dvh] w-[260px] {show class="py-2.5 my-auto flex flex-col justify-between h-screen max-h-[100dvh] w-[260px] {$showSidebar
? '' ? ''
: 'invisible'}" : 'invisible'}"
> >
...@@ -419,7 +417,7 @@ ...@@ -419,7 +417,7 @@
</div> </div>
{/if} {/if}
<div class="pl-2 my-2 flex-1 flex flex-col space-y-1 overflow-y-auto"> <div class="pl-2 my-2 flex-1 flex flex-col space-y-1 overflow-y-auto scrollbar-none">
{#each $chats.filter((chat) => { {#each $chats.filter((chat) => {
if (search === '') { if (search === '') {
return true; return true;
...@@ -465,7 +463,7 @@ ...@@ -465,7 +463,7 @@
on:click={() => { on:click={() => {
selectedChatId = chat.id; selectedChatId = chat.id;
if (window.innerWidth < 1024) { if (window.innerWidth < 1024) {
show = false; showSidebar.set(false);
} }
}} }}
draggable="false" draggable="false"
...@@ -610,7 +608,7 @@ ...@@ -610,7 +608,7 @@
</button> </button>
</ChatMenu> </ChatMenu>
<Tooltip content="Archive"> <Tooltip content={$i18n.t('Archive')}>
<button <button
aria-label="Archive" aria-label="Archive"
class=" self-center dark:hover:text-white transition" class=" self-center dark:hover:text-white transition"
...@@ -621,6 +619,27 @@ ...@@ -621,6 +619,27 @@
<ArchiveBox /> <ArchiveBox />
</button> </button>
</Tooltip> </Tooltip>
{#if chat.id === $chatId}
<button
id="delete-chat-button"
class="hidden"
on:click={() => {
chatDeleteId = chat.id;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M2 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM6.5 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM12.5 6.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Z"
/>
</svg>
</button>
{/if}
</div> </div>
{/if} {/if}
</div> </div>
...@@ -802,14 +821,14 @@ ...@@ -802,14 +821,14 @@
> >
<Tooltip <Tooltip
placement="right" placement="right"
content={`${show ? $i18n.t('Close') : $i18n.t('Open')} ${$i18n.t('sidebar')}`} content={`${$showSidebar ? $i18n.t('Close') : $i18n.t('Open')} ${$i18n.t('sidebar')}`}
touch={false} touch={false}
> >
<button <button
id="sidebar-toggle-button" id="sidebar-toggle-button"
class=" group" class=" group"
on:click={() => { on:click={() => {
show = !show; showSidebar.set(!$showSidebar);
}} }}
><span class="" data-state="closed" ><span class="" data-state="closed"
><div ><div
...@@ -833,3 +852,14 @@ ...@@ -833,3 +852,14 @@
</Tooltip> </Tooltip>
</div> </div>
</div> </div>
<style>
.scrollbar-none:active::-webkit-scrollbar-thumb,
.scrollbar-none:focus::-webkit-scrollbar-thumb,
.scrollbar-none:hover::-webkit-scrollbar-thumb {
visibility: visible;
}
.scrollbar-none::-webkit-scrollbar-thumb {
visibility: hidden;
}
</style>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment