This commit is contained in:
Timothy Jaeryang Baek 2025-12-10 23:28:33 -05:00
parent 6812d3b9d1
commit 0addc1ea46

View file

@ -7,7 +7,8 @@
dayjs.extend(relativeTime); dayjs.extend(relativeTime);
import { tick, getContext, onMount, onDestroy } from 'svelte'; import { tick, getContext, onMount, onDestroy } from 'svelte';
import { removeLastWordFromString, isValidHttpUrl, isYoutubeUrl } from '$lib/utils';
import { removeLastWordFromString, isValidHttpUrl, isYoutubeUrl, decodeString } from '$lib/utils';
import Tooltip from '$lib/components/common/Tooltip.svelte'; import Tooltip from '$lib/components/common/Tooltip.svelte';
import DocumentPage from '$lib/components/icons/DocumentPage.svelte'; import DocumentPage from '$lib/components/icons/DocumentPage.svelte';
import Database from '$lib/components/icons/Database.svelte'; import Database from '$lib/components/icons/Database.svelte';
@ -16,28 +17,18 @@
import { folders } from '$lib/stores'; import { folders } from '$lib/stores';
import Folder from '$lib/components/icons/Folder.svelte'; import Folder from '$lib/components/icons/Folder.svelte';
import { getFolders } from '$lib/apis/folders'; import { getFolders } from '$lib/apis/folders';
import { searchKnowledgeBases, searchKnowledgeFiles } from '$lib/apis/knowledge';
const i18n = getContext('i18n'); const i18n = getContext('i18n');
export let query = ''; export let query = '';
export let onSelect = (e) => {}; export let onSelect = (e) => {};
export let knowledge = [];
let selectedIdx = 0; let selectedIdx = 0;
let items = []; let items = [];
let fuse = null;
export let filteredItems = []; export let filteredItems = [];
$: if (fuse) { $: filteredItems = [
filteredItems = [
...(query
? fuse.search(query).map((e) => {
return e.item;
})
: items),
...(query.startsWith('http') ...(query.startsWith('http')
? isYoutubeUrl(query) ? isYoutubeUrl(query)
? [{ type: 'youtube', name: query, description: query }] ? [{ type: 'youtube', name: query, description: query }]
@ -48,9 +39,9 @@
description: query description: query
} }
] ]
: []) : []),
...items
]; ];
}
$: if (query) { $: if (query) {
selectedIdx = 0; selectedIdx = 0;
@ -72,11 +63,63 @@
item.click(); item.click();
} }
}; };
const decodeString = (str: string) => {
try { let folderItems = [];
return decodeURIComponent(str); let knowledgeItems = [];
} catch (e) { let fileItems = [];
return str;
$: items = [...folderItems, ...knowledgeItems, ...fileItems];
$: if (query !== null) {
getItems();
}
const getItems = () => {
getFolderItems();
getKnowledgeItems();
getKnowledgeFileItems();
};
const getFolderItems = async () => {
folderItems = $folders
.map((folder) => ({
...folder,
type: 'folder',
description: $i18n.t('Folder'),
title: folder.name
}))
.filter((folder) => folder.name.toLowerCase().includes(query.toLowerCase()));
};
const getKnowledgeItems = async () => {
const res = await searchKnowledgeBases(localStorage.token, query).catch(() => {
return null;
});
if (res) {
knowledgeItems = res.items.map((item) => {
return {
...item,
type: 'collection'
};
});
}
};
const getKnowledgeFileItems = async () => {
const res = await searchKnowledgeFiles(localStorage.token, query).catch(() => {
return null;
});
if (res) {
fileItems = res.items.map((item) => {
return {
...item,
type: 'file',
name: item.filename,
description: item.collection ? item.collection.name : ''
};
});
} }
}; };
@ -85,25 +128,6 @@
await folders.set(await getFolders(localStorage.token)); await folders.set(await getFolders(localStorage.token));
} }
let collections = knowledge
.filter((item) => !item?.meta?.document)
.map((item) => ({
...item,
type: 'collection'
}));
let folder_items = $folders.map((folder) => ({
...folder,
type: 'folder',
description: $i18n.t('Folder'),
title: folder.name
}));
items = [...folder_items, ...collections];
fuse = new Fuse(items, {
keys: ['name', 'description']
});
await tick(); await tick();
}); });
@ -122,12 +146,20 @@
}); });
</script> </script>
<div class="px-2 text-xs text-gray-500 py-1">
{$i18n.t('Knowledge')}
</div>
{#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}
<div class="px-2 text-xs text-gray-500 py-1">
{#if item?.type === 'folder'}
{$i18n.t('Folders')}
{:else if item?.type === 'collection'}
{$i18n.t('Collections')}
{:else if item?.type === 'file'}
{$i18n.t('Files')}
{/if}
</div>
{/if}
{#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=" px-2 py-1 rounded-xl w-full text-left flex justify-between items-center {idx ===