This commit is contained in:
Timothy Jaeryang Baek 2024-11-30 15:44:04 -08:00
parent acb61d3c42
commit aed2caefe1
4 changed files with 256 additions and 260 deletions

View File

@ -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">

View File

@ -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(() => {

View File

@ -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 />

View File

@ -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"