mirror of
https://github.com/open-webui/open-webui
synced 2024-12-29 07:12:07 +00:00
refac
This commit is contained in:
parent
acb61d3c42
commit
aed2caefe1
@ -5,6 +5,7 @@
|
|||||||
import FileItemModal from './FileItemModal.svelte';
|
import FileItemModal from './FileItemModal.svelte';
|
||||||
import GarbageBin from '../icons/GarbageBin.svelte';
|
import GarbageBin from '../icons/GarbageBin.svelte';
|
||||||
import Spinner from './Spinner.svelte';
|
import Spinner from './Spinner.svelte';
|
||||||
|
import Tooltip from './Tooltip.svelte';
|
||||||
|
|
||||||
const i18n = getContext('i18n');
|
const i18n = getContext('i18n');
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
@ -18,6 +19,7 @@
|
|||||||
|
|
||||||
export let item = null;
|
export let item = null;
|
||||||
export let edit = false;
|
export let edit = false;
|
||||||
|
export let small = false;
|
||||||
|
|
||||||
export let name: string;
|
export let name: string;
|
||||||
export let type: string;
|
export let type: string;
|
||||||
@ -31,7 +33,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="relative group p-1.5 {className} flex items-center {colorClassName} rounded-2xl text-left"
|
class="relative group p-1.5 {className} flex items-center gap-1 {colorClassName} rounded-xl text-left"
|
||||||
type="button"
|
type="button"
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
if (item?.file?.data?.content) {
|
if (item?.file?.data?.content) {
|
||||||
@ -49,6 +51,7 @@
|
|||||||
dispatch('click');
|
dispatch('click');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{#if !small}
|
||||||
<div class="p-3 bg-black/20 dark:bg-white/10 text-white rounded-xl">
|
<div class="p-3 bg-black/20 dark:bg-white/10 text-white rounded-xl">
|
||||||
{#if !loading}
|
{#if !loading}
|
||||||
<svg
|
<svg
|
||||||
@ -70,8 +73,10 @@
|
|||||||
<Spinner />
|
<Spinner />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<div class="flex flex-col justify-center -space-y-0.5 ml-1 px-2.5 w-full">
|
{#if !small}
|
||||||
|
<div class="flex flex-col justify-center -space-y-0.5 px-2.5 w-full">
|
||||||
<div class=" dark:text-gray-100 text-sm font-medium line-clamp-1 mb-1">
|
<div class=" dark:text-gray-100 text-sm font-medium line-clamp-1 mb-1">
|
||||||
{name}
|
{name}
|
||||||
</div>
|
</div>
|
||||||
@ -91,6 +96,16 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{:else}
|
||||||
|
<Tooltip content={name} className="flex flex-col w-full" placement="top-start">
|
||||||
|
<div class="flex flex-col justify-center -space-y-0.5 px-2.5 w-full">
|
||||||
|
<div class=" dark:text-gray-100 text-sm flex justify-between items-center">
|
||||||
|
<div class="font-medium line-clamp-1">{name}</div>
|
||||||
|
<div class="text-gray-500 text-xs capitalize shrink-0">{formatFileSize(size)}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
{/if}
|
||||||
|
|
||||||
{#if dismissible}
|
{#if dismissible}
|
||||||
<div class=" absolute -top-1 -right-1">
|
<div class=" absolute -top-1 -right-1">
|
||||||
|
@ -187,7 +187,7 @@
|
|||||||
: [])
|
: [])
|
||||||
],
|
],
|
||||||
content: content,
|
content: content,
|
||||||
autofocus: true,
|
autofocus: messageInput ? true : false,
|
||||||
onTransaction: () => {
|
onTransaction: () => {
|
||||||
// force re-render so `editor.isActive` works as expected
|
// force re-render so `editor.isActive` works as expected
|
||||||
editor = editor;
|
editor = editor;
|
||||||
@ -218,6 +218,7 @@
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
keydown: (view, event) => {
|
keydown: (view, event) => {
|
||||||
|
if (messageInput) {
|
||||||
// Handle Tab Key
|
// Handle Tab Key
|
||||||
if (event.key === 'Tab') {
|
if (event.key === 'Tab') {
|
||||||
const handled = selectNextTemplate(view.state, view.dispatch);
|
const handled = selectNextTemplate(view.state, view.dispatch);
|
||||||
@ -227,7 +228,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (messageInput) {
|
|
||||||
if (event.key === 'Enter') {
|
if (event.key === 'Enter') {
|
||||||
// Check if the current selection is inside a structured block (like codeBlock or list)
|
// Check if the current selection is inside a structured block (like codeBlock or list)
|
||||||
const { state } = view;
|
const { state } = view;
|
||||||
@ -317,7 +317,9 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (messageInput) {
|
||||||
selectTemplate();
|
selectTemplate();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
|
@ -600,7 +600,7 @@
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="flex flex-col w-full h-full max-h-[100dvh] translate-y-1" id="collection-container">
|
<div class="flex flex-col w-full translate-y-1" id="collection-container">
|
||||||
{#if id && knowledge}
|
{#if id && knowledge}
|
||||||
<AccessControlModal
|
<AccessControlModal
|
||||||
bind:show={showAccessControlModal}
|
bind:show={showAccessControlModal}
|
||||||
@ -657,122 +657,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-row flex-1 h-full max-h-full pb-2.5">
|
<div class="flex flex-row flex-1 h-full max-h-full pb-2.5 gap-3">
|
||||||
<PaneGroup direction="horizontal">
|
|
||||||
<Pane
|
|
||||||
bind:pane
|
|
||||||
defaultSize={minSize}
|
|
||||||
collapsible={true}
|
|
||||||
maxSize={50}
|
|
||||||
{minSize}
|
|
||||||
class="h-full"
|
|
||||||
onExpand={() => {
|
|
||||||
showSidepanel = true;
|
|
||||||
}}
|
|
||||||
onCollapse={() => {
|
|
||||||
showSidepanel = false;
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="{largeScreen ? 'flex-shrink-0' : 'flex-1'}
|
|
||||||
flex
|
|
||||||
py-2
|
|
||||||
rounded-2xl
|
|
||||||
border
|
|
||||||
border-gray-50
|
|
||||||
h-full
|
|
||||||
dark:border-gray-850"
|
|
||||||
>
|
|
||||||
<div class=" flex flex-col w-full space-x-2 rounded-lg h-full">
|
|
||||||
<div class="w-full h-full flex flex-col">
|
|
||||||
<div class=" px-3">
|
|
||||||
<div class="flex py-1">
|
|
||||||
<div class=" self-center ml-1 mr-3">
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="currentColor"
|
|
||||||
class="w-4 h-4"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fill-rule="evenodd"
|
|
||||||
d="M9 3.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM2 9a7 7 0 1112.452 4.391l3.328 3.329a.75.75 0 11-1.06 1.06l-3.329-3.328A7 7 0 012 9z"
|
|
||||||
clip-rule="evenodd"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<input
|
|
||||||
class=" w-full text-sm pr-4 py-1 rounded-r-xl outline-none bg-transparent"
|
|
||||||
bind:value={query}
|
|
||||||
placeholder={$i18n.t('Search Collection')}
|
|
||||||
on:focus={() => {
|
|
||||||
selectedFileId = null;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<AddContentMenu
|
|
||||||
on:upload={(e) => {
|
|
||||||
if (e.detail.type === 'directory') {
|
|
||||||
uploadDirectoryHandler();
|
|
||||||
} else if (e.detail.type === 'text') {
|
|
||||||
showAddTextContentModal = true;
|
|
||||||
} else {
|
|
||||||
document.getElementById('files-input').click();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
on:sync={(e) => {
|
|
||||||
showSyncConfirmModal = true;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{#if filteredItems.length > 0}
|
|
||||||
<div class=" flex overflow-y-auto h-full w-full scrollbar-hidden text-xs">
|
|
||||||
<Files
|
|
||||||
files={filteredItems}
|
|
||||||
{selectedFileId}
|
|
||||||
on:click={(e) => {
|
|
||||||
selectedFileId = selectedFileId === e.detail ? null : e.detail;
|
|
||||||
}}
|
|
||||||
on:delete={(e) => {
|
|
||||||
console.log(e.detail);
|
|
||||||
|
|
||||||
selectedFileId = null;
|
|
||||||
deleteFileHandler(e.detail);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<div
|
|
||||||
class="m-auto flex flex-col justify-center text-center text-gray-500 text-xs"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
{$i18n.t('No content found')}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mx-12 mt-2 text-center text-gray-200 dark:text-gray-700">
|
|
||||||
{$i18n.t('Drag and drop a file to upload or select a file to view')}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Pane>
|
|
||||||
|
|
||||||
{#if largeScreen}
|
{#if largeScreen}
|
||||||
<PaneResizer class="relative flex w-2 items-center justify-center bg-background group">
|
<div class="flex-1 flex justify-start w-full h-full max-h-full">
|
||||||
<div class="z-10 flex h-7 w-5 items-center justify-center rounded-sm">
|
|
||||||
<EllipsisVertical className="size-4 invisible group-hover:visible" />
|
|
||||||
</div>
|
|
||||||
</PaneResizer>
|
|
||||||
<Pane>
|
|
||||||
<div class="flex-1 flex justify-start h-full max-h-full">
|
|
||||||
{#if selectedFile}
|
{#if selectedFile}
|
||||||
<div class=" flex flex-col w-full h-full max-h-full ml-2.5">
|
<div class=" flex flex-col w-full h-full max-h-full">
|
||||||
<div class="flex-shrink-0 mb-2 flex items-center">
|
<div class="flex-shrink-0 mb-2 flex items-center">
|
||||||
{#if !showSidepanel}
|
{#if !showSidepanel}
|
||||||
<div class="-translate-x-2">
|
<div class="-translate-x-2">
|
||||||
@ -787,7 +676,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class=" flex-1 text-2xl font-medium">
|
<div class=" flex-1 text-xl font-medium">
|
||||||
<a
|
<a
|
||||||
class="hover:text-gray-500 hover:dark:text-gray-100 hover:underline flex-grow line-clamp-1"
|
class="hover:text-gray-500 hover:dark:text-gray-100 hover:underline flex-grow line-clamp-1"
|
||||||
href={selectedFile.id ? `/api/v1/files/${selectedFile.id}/content` : '#'}
|
href={selectedFile.id ? `/api/v1/files/${selectedFile.id}/content` : '#'}
|
||||||
@ -823,10 +712,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div></div>
|
<div class="h-full flex w-full">
|
||||||
|
<div class="m-auto text-xs text-center text-gray-200 dark:text-gray-700">
|
||||||
|
{$i18n.t('Drag and drop a file to upload or select a file to view')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</Pane>
|
|
||||||
{:else if !largeScreen && selectedFileId !== null}
|
{:else if !largeScreen && selectedFileId !== null}
|
||||||
<Drawer
|
<Drawer
|
||||||
className="h-full"
|
className="h-full"
|
||||||
@ -872,6 +764,7 @@
|
|||||||
className="input-prose-sm"
|
className="input-prose-sm"
|
||||||
bind:value={selectedFile.data.content}
|
bind:value={selectedFile.data.content}
|
||||||
placeholder={$i18n.t('Add content here')}
|
placeholder={$i18n.t('Add content here')}
|
||||||
|
preserveBreaks={true}
|
||||||
/>
|
/>
|
||||||
{/key}
|
{/key}
|
||||||
</div>
|
</div>
|
||||||
@ -879,7 +772,90 @@
|
|||||||
</div>
|
</div>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
{/if}
|
{/if}
|
||||||
</PaneGroup>
|
|
||||||
|
<div
|
||||||
|
class="{largeScreen ? 'flex-shrink-0 w-72 max-w-72' : 'flex-1'}
|
||||||
|
flex
|
||||||
|
py-2
|
||||||
|
rounded-2xl
|
||||||
|
border
|
||||||
|
border-gray-50
|
||||||
|
h-full
|
||||||
|
dark:border-gray-850"
|
||||||
|
>
|
||||||
|
<div class=" flex flex-col w-full space-x-2 rounded-lg h-full">
|
||||||
|
<div class="w-full h-full flex flex-col">
|
||||||
|
<div class=" px-3">
|
||||||
|
<div class="flex mb-0.5">
|
||||||
|
<div class=" self-center ml-1 mr-3">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
class="w-4 h-4"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M9 3.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM2 9a7 7 0 1112.452 4.391l3.328 3.329a.75.75 0 11-1.06 1.06l-3.329-3.328A7 7 0 012 9z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
class=" w-full text-sm pr-4 py-1 rounded-r-xl outline-none bg-transparent"
|
||||||
|
bind:value={query}
|
||||||
|
placeholder={$i18n.t('Search Collection')}
|
||||||
|
on:focus={() => {
|
||||||
|
selectedFileId = null;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<AddContentMenu
|
||||||
|
on:upload={(e) => {
|
||||||
|
if (e.detail.type === 'directory') {
|
||||||
|
uploadDirectoryHandler();
|
||||||
|
} else if (e.detail.type === 'text') {
|
||||||
|
showAddTextContentModal = true;
|
||||||
|
} else {
|
||||||
|
document.getElementById('files-input').click();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
on:sync={(e) => {
|
||||||
|
showSyncConfirmModal = true;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if filteredItems.length > 0}
|
||||||
|
<div class=" flex overflow-y-auto h-full w-full scrollbar-hidden text-xs">
|
||||||
|
<Files
|
||||||
|
small
|
||||||
|
files={filteredItems}
|
||||||
|
{selectedFileId}
|
||||||
|
on:click={(e) => {
|
||||||
|
selectedFileId = selectedFileId === e.detail ? null : e.detail;
|
||||||
|
}}
|
||||||
|
on:delete={(e) => {
|
||||||
|
console.log(e.detail);
|
||||||
|
|
||||||
|
selectedFileId = null;
|
||||||
|
deleteFileHandler(e.detail);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class="my-3 flex flex-col justify-center text-center text-gray-500 text-xs">
|
||||||
|
<div>
|
||||||
|
{$i18n.t('No content found')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<Spinner />
|
<Spinner />
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
export let selectedFileId = null;
|
export let selectedFileId = null;
|
||||||
export let files = [];
|
export let files = [];
|
||||||
|
|
||||||
|
export let small = false;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class=" max-h-full flex flex-col w-full">
|
<div class=" max-h-full flex flex-col w-full">
|
||||||
@ -16,6 +18,7 @@
|
|||||||
colorClassName="{selectedFileId === file.id
|
colorClassName="{selectedFileId === file.id
|
||||||
? ' bg-gray-50 dark:bg-gray-850'
|
? ' bg-gray-50 dark:bg-gray-850'
|
||||||
: 'bg-transparent'} hover:bg-gray-50 dark:hover:bg-gray-850 transition"
|
: 'bg-transparent'} hover:bg-gray-50 dark:hover:bg-gray-850 transition"
|
||||||
|
{small}
|
||||||
{file}
|
{file}
|
||||||
name={file?.name ?? file?.meta?.name}
|
name={file?.name ?? file?.meta?.name}
|
||||||
type="file"
|
type="file"
|
||||||
|
Loading…
Reference in New Issue
Block a user