feat: update frontend document management components.

This commit is contained in:
2025-12-09 13:49:07 +01:00
parent 8a16293f0e
commit ce821c1817
13 changed files with 264 additions and 292 deletions
@@ -223,9 +223,6 @@ const useDocumentsWorkspace = ({
const {
documents,
setDocuments,
removeDocumentsFromLookup,
mapDocumentCaches,
updateDocumentCaches,
documentsManager,
} = useDocuments({
fetchDocumentById,
@@ -264,6 +261,23 @@ const useDocumentsWorkspace = ({
const [currentSubfolders, setCurrentSubfolders] = useState<Array<{ id?: FolderNodeId; name?: string | null;[key: string]: unknown }>>([]);
const foldersSnapshot = useSyncExternalStore(
useCallback((cb) => foldersManager.subscribe(cb), [foldersManager]),
() => foldersManager.getSnapshot(),
() => foldersManager.getSnapshot(),
);
const visibleSubfolders = useMemo(() => {
return currentSubfolders.map((folder) => {
if (!folder?.id) return folder;
const live = foldersSnapshot.get(folder.id);
if (live) {
return { ...folder, ...live };
}
return folder;
});
}, [currentSubfolders, foldersSnapshot]);
const reconcileSelectionWithFolderData = useCallback(
(currentSelection: string[], docs: Document[], subfolders: any[]) => {
const availableDocKeys = docs
@@ -383,15 +397,30 @@ const useDocumentsWorkspace = ({
const documentsFilter = documentsFilterValue;
const showingSearchResults = searchResultIds !== null;
// Live Filter: Ensure we only show documents that actually belong to the current folder.
// Since 'documents' is reactive, if a document is moved, its folder_id updates immediately.
// We must filter out any documents that no longer match the selectedFolder.
const liveFilteredDocuments = useMemo(() => {
if (showingSearchResults) {
return documents;
}
const targetFolder = selectedFolder || 'root';
return documents.filter((doc) => {
if (!doc) return false;
const docFolder = doc.folder_id || 'root';
return docFolder === targetFolder;
});
}, [documents, showingSearchResults, selectedFolder]);
const {
viewDocuments,
visibleEntryKeySet,
} = useWorkspaceViewData({
documents,
documents: liveFilteredDocuments,
documentLookup,
searchResultIds,
showingSearchResults,
currentSubfolders,
currentSubfolders: visibleSubfolders,
});
const {
@@ -445,7 +474,7 @@ const useDocumentsWorkspace = ({
tenantIdRef,
tagManager,
setActiveTagFilters,
mapDocumentCaches,
documentsManager,
});
const {
tags,
@@ -476,7 +505,7 @@ const useDocumentsWorkspace = ({
const correspondentsStateRaw = useCorrespondents({
tenantIdRef,
mapDocumentCaches,
documentsManager,
});
const {
correspondents,
@@ -495,7 +524,7 @@ const useDocumentsWorkspace = ({
} = useDocumentCorrespondentActions({
correspondents,
handleCorrespondentCreate,
updateDocumentCaches,
documentsManager,
});
const {
@@ -548,7 +577,7 @@ const useDocumentsWorkspace = ({
tagManager,
refreshTags,
resolveTargetDocumentIds,
updateDocumentCaches,
documentsManager,
});
const {
@@ -642,40 +671,11 @@ const useDocumentsWorkspace = ({
}
}, [appStatus, resetWorkspaceState, foldersManager]);
const removeDocumentsFromCaches = useCallback(
(documentIds: DocumentId[]) => {
if (!documentIds.length) {
return;
}
const idSet = new Set<DocumentId>(documentIds);
setDocuments((prev) => prev.filter((doc) => !idSet.has(doc.id)));
setSearchResultIds((prev) => {
if (!Array.isArray(prev)) {
return prev;
}
const filtered = prev.filter((id) => !idSet.has(id as DocumentId));
return filtered.length === prev.length ? prev : filtered;
});
removeDocumentsFromLookup(Array.from(idSet));
},
[
setDocuments,
setSearchResultIds,
removeDocumentsFromLookup,
],
);
const documentsState = {
documentLookup,
setDocuments,
setSearchResultIds,
removeDocumentsFromCaches,
updateDocumentCaches,
mapDocumentCaches,
documentsManager,
extractDocumentFromResponse,
ingestDocuments: (docs: unknown[]) => documentsManager.ingest(docs),
};
@@ -732,7 +732,7 @@ const useDocumentsWorkspace = ({
clearDocumentSelection,
} = useDocumentsSelection({
showingSearchResults,
currentSubfolders,
currentSubfolders: visibleSubfolders,
visibleDocuments: viewDocuments,
configureSelectionEnvironment,
visibleEntryKeySet,
@@ -834,7 +834,7 @@ const useDocumentsWorkspace = ({
handleDocumentsDelete,
handleFolderDelete,
clearDocumentSelection,
updateDocumentCaches,
documentsManager,
});
const ensureAssetUrl = useCallback(
@@ -852,7 +852,10 @@ const useDocumentsWorkspace = ({
return null;
}
updateDocumentCaches(documentId, (doc) => mergeAssetIntoDocument(doc, entry));
documentsManager.map((doc) => {
if (doc.id !== documentId) return undefined;
return mergeAssetIntoDocument(doc, entry);
});
return entry;
} catch (error) {
@@ -860,7 +863,7 @@ const useDocumentsWorkspace = ({
throw error;
}
},
[assetManager, updateDocumentCaches, notifyApiError],
[assetManager, documentsManager, notifyApiError],
);
const handlePromptCreateFolder = useCallback(async (parentId?: Identifier | null) => {
@@ -1097,7 +1100,7 @@ const useDocumentsWorkspace = ({
draggedFolderId,
handlePromptCreateFolder,
creatingFolder,
currentSubfolders,
currentSubfolders: visibleSubfolders,
breadcrumbs,
};