This commit is contained in:
Timothy Jaeryang Baek
2026-06-29 01:41:43 -05:00
parent 3730a9eaac
commit 46c1d6591b
2 changed files with 63 additions and 17 deletions
+22 -8
View File
@@ -31,6 +31,7 @@ from sqlalchemy import (
update,
)
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import defer
log = logging.getLogger(__name__)
@@ -416,6 +417,7 @@ class KnowledgeTable:
if limit:
stmt = stmt.limit(limit)
stmt = stmt.options(defer(File.data))
result = await db.execute(stmt)
rows = result.all()
@@ -423,7 +425,13 @@ class KnowledgeTable:
for file, user, knowledge in rows:
items.append(
FileUserResponse(
**FileModel.model_validate(file).model_dump(),
id=file.id,
user_id=file.user_id,
hash=file.hash,
filename=file.filename,
meta=file.meta,
created_at=file.created_at,
updated_at=file.updated_at,
user=(UserResponse(**UserModel.model_validate(user).model_dump()) if user else None),
collection=(await self._to_knowledge_model(knowledge, db=db)).model_dump(),
)
@@ -603,17 +611,23 @@ class KnowledgeTable:
if limit:
stmt = stmt.limit(limit)
stmt = stmt.options(defer(File.data))
result = await db.execute(stmt)
items = result.all()
files = []
for file, user in items:
files.append(
FileUserResponse(
**FileModel.model_validate(file).model_dump(),
user=(UserResponse(**UserModel.model_validate(user).model_dump()) if user else None),
)
files = [
FileUserResponse(
id=file.id,
user_id=file.user_id,
hash=file.hash,
filename=file.filename,
meta=file.meta,
created_at=file.created_at,
updated_at=file.updated_at,
user=(UserResponse(**UserModel.model_validate(user).model_dump()) if user else None),
)
for file, user in items
]
return KnowledgeFileListResponse(
items=files,
@@ -113,6 +113,7 @@
let selectedFileId = null;
let selectedFile = null;
let selectedFileContent = '';
let loadingFileContent = false;
let inputFiles = null;
@@ -249,11 +250,29 @@
};
const fileSelectHandler = async (file) => {
selectedFile = file;
selectedFileContent = file?.data?.content ?? '';
loadingFileContent = false;
if (!file?.id || file?.data?.content !== undefined) {
return;
}
loadingFileContent = true;
try {
selectedFile = file;
selectedFileContent = selectedFile?.data?.content || '';
const fileWithContent = await getFileById(localStorage.token, file.id);
if (selectedFileId === file.id) {
selectedFile = fileWithContent ?? file;
selectedFileContent = fileWithContent?.data?.content ?? '';
}
} catch (e) {
toast.error($i18n.t('Failed to load file content.'));
if (selectedFileId === file.id) {
toast.error($i18n.t('Failed to load file content.'));
}
} finally {
if (selectedFileId === file.id) {
loadingFileContent = false;
}
}
};
@@ -825,6 +844,8 @@
currentPage = 1;
selectedFileId = null;
selectedFile = null;
selectedFileContent = '';
loadingFileContent = false;
getItemsPage();
};
@@ -953,8 +974,7 @@
let isSaving = false;
const updateFileContentHandler = async () => {
if (isSaving) {
console.log('Save operation already in progress, skipping...');
if (isSaving || loadingFileContent || !selectedFile?.id) {
return;
}
@@ -1414,6 +1434,9 @@
placeholder={$i18n.t('Search Collection')}
on:focus={() => {
selectedFileId = null;
selectedFile = null;
selectedFileContent = '';
loadingFileContent = false;
}}
/>
@@ -1578,13 +1601,18 @@
if (file) {
fileSelectHandler(file);
} else {
selectedFileId = null;
selectedFile = null;
selectedFileContent = '';
loadingFileContent = false;
}
}
}}
onDelete={(fileId) => {
selectedFileId = null;
selectedFile = null;
selectedFileContent = '';
loadingFileContent = false;
deleteFileHandler(fileId);
}}
@@ -1622,6 +1650,8 @@
onClose={() => {
selectedFileId = null;
selectedFile = null;
selectedFileContent = '';
loadingFileContent = false;
}}
>
<div class="flex flex-col justify-start h-full max-h-full">
@@ -1634,6 +1664,8 @@
on:click={() => {
selectedFileId = null;
selectedFile = null;
selectedFileContent = '';
loadingFileContent = false;
}}
>
<ChevronLeft strokeWidth="2.5" />
@@ -1647,7 +1679,7 @@
<div>
<button
class="flex self-center w-fit text-sm py-1 px-2.5 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-lg disabled:opacity-50 disabled:cursor-not-allowed"
disabled={isSaving}
disabled={isSaving || loadingFileContent}
on:click={() => {
updateFileContentHandler();
}}
@@ -1663,14 +1695,14 @@
{/if}
</div>
{#key selectedFile.id}
{#key selectedFile?.id}
<textarea
class="w-full h-full text-sm outline-none resize-none px-3 py-2"
bind:value={selectedFileContent}
disabled={!knowledge?.write_access}
disabled={!knowledge?.write_access || loadingFileContent}
aria-label={$i18n.t('File content')}
placeholder={$i18n.t('Add content here')}
/>
></textarea>
{/key}
</div>
</div>