Remove asset/document hydration pipeline and introduce client-side cache updates for correspondents, tags, and search results

This commit is contained in:
2025-11-20 02:18:33 +01:00
parent b76f1df27f
commit 0eb4c0a294
14 changed files with 316 additions and 329 deletions
@@ -134,6 +134,7 @@ interface UseDocumentMutationsArgs {
closeDocumentPreview: CloseDocumentPreview;
previewDocumentId?: DocumentId | null;
refreshCurrentFolder: () => Promise<void>;
refreshVisibleDocuments: () => Promise<void>;
documentsViewMode?: string;
updateDocumentCaches: UpdateDocumentCaches;
tagLookupById: Map<DocumentId, Tag>;
@@ -141,6 +142,7 @@ interface UseDocumentMutationsArgs {
refreshTags: () => Promise<void>;
tagManager: TagManager;
extractDocumentFromResponse?: (payload: unknown) => DocumentLike | null;
ingestDocuments?: (docs: unknown[]) => { canonical: DocumentLike[]; changed: boolean };
}
interface UseDocumentMutationsResult {
@@ -210,6 +212,7 @@ const useDocumentMutations = ({
closeDocumentPreview,
previewDocumentId,
refreshCurrentFolder,
refreshVisibleDocuments,
documentsViewMode,
updateDocumentCaches,
tagLookupById,
@@ -217,6 +220,7 @@ const useDocumentMutations = ({
refreshTags,
tagManager,
extractDocumentFromResponse,
ingestDocuments,
}: UseDocumentMutationsArgs): UseDocumentMutationsResult => {
const moveDocumentsToFolder = useCallback(
async (documentIds: Array<DocumentId | DocumentLike>, targetFolderId?: NullableFolderId) => {
@@ -492,12 +496,16 @@ const useDocumentMutations = ({
const { data } = await api.patch(`/documents/${documentId}`, { title: trimmed });
const updatedDocument = extractDocumentFromResponse?.(data);
updateDocumentCaches(documentId, (doc) => {
if (updatedDocument) {
return { ...doc, ...updatedDocument };
}
return { ...doc, title: trimmed };
});
if (updatedDocument && ingestDocuments) {
ingestDocuments([updatedDocument]);
} else {
updateDocumentCaches(documentId, (doc) => {
if (updatedDocument) {
return { ...doc, ...updatedDocument };
}
return { ...doc, title: trimmed };
});
}
setStatusMessage('Document title updated.', 'success');
return true;
@@ -509,7 +517,15 @@ const useDocumentMutations = ({
setLoading(false);
}
},
[api, extractDocumentFromResponse, notifyApiError, setLoading, setStatusMessage, updateDocumentCaches],
[
api,
extractDocumentFromResponse,
ingestDocuments,
notifyApiError,
setLoading,
setStatusMessage,
updateDocumentCaches,
],
);
const handleDocumentIssuedUpdate = useCallback(
@@ -520,12 +536,16 @@ const useDocumentMutations = ({
const { data } = await api.patch(`/documents/${documentId}`, payload);
const updatedDocument = extractDocumentFromResponse?.(data);
updateDocumentCaches(documentId, (doc) => {
if (updatedDocument) {
return { ...doc, ...updatedDocument };
}
return { ...doc, issued_at: payload.issued_at };
});
if (updatedDocument && ingestDocuments) {
ingestDocuments([updatedDocument]);
} else {
updateDocumentCaches(documentId, (doc) => {
if (updatedDocument) {
return { ...doc, ...updatedDocument };
}
return { ...doc, issued_at: payload.issued_at };
});
}
const message = payload.issued_at ? 'Issued date updated.' : 'Issued date cleared.';
setStatusMessage(message, 'success');
@@ -538,7 +558,56 @@ const useDocumentMutations = ({
setLoading(false);
}
},
[api, extractDocumentFromResponse, notifyApiError, setLoading, setStatusMessage, updateDocumentCaches],
[
api,
extractDocumentFromResponse,
ingestDocuments,
notifyApiError,
setLoading,
setStatusMessage,
updateDocumentCaches,
],
);
const attachTagToDocument = useCallback(
async ({
documentId,
tag,
}: {
documentId?: DocumentId;
tag?: Tag | null;
}) => {
if (!documentId || !tag?.id) {
return false;
}
const cachedTag: Tag = {
id: tag.id,
label: tag.label,
color: Object.prototype.hasOwnProperty.call(tag, 'color') ? tag.color ?? null : null,
};
try {
await api.post(`/documents/${documentId}/tags`, { tag_ids: [cachedTag.id] });
updateDocumentCaches(documentId, (doc) => {
if (!doc) {
return doc;
}
const currentTags = Array.isArray(doc.tags) ? doc.tags : [];
if (currentTags.some((entry) => entry?.id === cachedTag.id)) {
return doc;
}
return { ...doc, tags: [...currentTags, cachedTag] };
});
setStatusMessage('Tag assigned.', 'success');
return true;
} catch (error) {
const message = (error as Record<string, any>)?.response?.data?.error || 'Failed to assign tag.';
notifyApiError(error, message);
return false;
}
},
[api, notifyApiError, setStatusMessage, updateDocumentCaches],
);
const handleDocumentTagAdd = useCallback(
@@ -561,17 +630,18 @@ const useDocumentMutations = ({
tag = data as Tag;
await refreshTags();
}
await api.post(`/documents/${document.id}/tags`, { tag_ids: [tag.id] });
setStatusMessage('Tag assigned.', 'success');
await attachTagToDocument({
documentId: document.id as DocumentId,
tag,
});
if (input && Object(input) === input && 'value' in (input as Record<string, unknown>)) {
(input as { value?: string }).value = '';
}
await refreshCurrentFolder();
} catch (error) {
notifyApiError(error, 'Failed to assign tag.');
}
},
[api, tags, refreshTags, refreshCurrentFolder, notifyApiError, setStatusMessage, tagManager],
[api, tags, refreshTags, attachTagToDocument, notifyApiError, setStatusMessage, tagManager],
);
const handleDocumentTagAttach = useCallback(
@@ -597,40 +667,14 @@ const useDocumentMutations = ({
};
};
try {
await api.post(`/documents/${documentId}/tags`, { tag_ids: [tagId] });
updateDocumentCaches(documentId, (doc) => {
if (!doc) {
return doc;
}
const currentTags = Array.isArray(doc.tags) ? doc.tags : [];
if (currentTags.some((existing) => existing?.id === tagId)) {
return doc;
}
const resolvedTag = resolveTagForCache();
if (!resolvedTag) {
return doc;
}
return { ...doc, tags: [...currentTags, resolvedTag] };
});
setStatusMessage('Tag assigned.', 'success');
if (documentsViewMode !== 'desk') {
await refreshCurrentFolder();
}
return true;
} catch (error) {
const message = (error as Record<string, any>)?.response?.data?.error || 'Failed to assign tag.';
notifyApiError(error, message);
return false;
}
const resolvedTag = resolveTagForCache();
return attachTagToDocument({
documentId,
tag: resolvedTag,
});
},
[
api,
refreshCurrentFolder,
documentsViewMode,
notifyApiError,
setStatusMessage,
updateDocumentCaches,
attachTagToDocument,
tagLookupById,
],
);