This commit is contained in:
2025-11-23 00:11:18 +01:00
parent 014f489857
commit 85afff2c19
12 changed files with 34 additions and 179 deletions
-6
View File
@@ -22,7 +22,6 @@ interface UseDocumentsSearchArgs {
documentsSortField?: string; documentsSortField?: string;
documentsSortDirection?: string; documentsSortDirection?: string;
notifyApiError: (error: unknown, message: string) => void; notifyApiError: (error: unknown, message: string) => void;
setLoading: (state: boolean) => void;
setSearchIncludeDescendants: (value: boolean) => void; setSearchIncludeDescendants: (value: boolean) => void;
documentsManager: { documentsManager: {
ingest: (docs: unknown[]) => { canonical: DocumentLike[]; changed: boolean }; ingest: (docs: unknown[]) => { canonical: DocumentLike[]; changed: boolean };
@@ -75,7 +74,6 @@ const useDocumentsSearch = ({
documentsSortField, documentsSortField,
documentsSortDirection, documentsSortDirection,
notifyApiError, notifyApiError,
setLoading,
setSearchIncludeDescendants, setSearchIncludeDescendants,
documentsManager, documentsManager,
}: UseDocumentsSearchArgs): UseDocumentsSearchResult => { }: UseDocumentsSearchArgs): UseDocumentsSearchResult => {
@@ -193,7 +191,6 @@ const useDocumentsSearch = ({
const debounce = setTimeout(async () => { const debounce = setTimeout(async () => {
started = true; started = true;
setLoading(true);
try { try {
const params: Record<string, unknown> = {}; const params: Record<string, unknown> = {};
const trimmedQuery = searchQuery.trim(); const trimmedQuery = searchQuery.trim();
@@ -248,7 +245,6 @@ const useDocumentsSearch = ({
setSearchResultIds(null); setSearchResultIds(null);
} finally { } finally {
if (!cancelled && started) { if (!cancelled && started) {
setLoading(false);
setSearchLoading(false); setSearchLoading(false);
} }
} }
@@ -258,7 +254,6 @@ const useDocumentsSearch = ({
cancelled = true; cancelled = true;
clearTimeout(debounce); clearTimeout(debounce);
if (started) { if (started) {
setLoading(false);
setSearchLoading(false); setSearchLoading(false);
} }
}; };
@@ -274,7 +269,6 @@ const useDocumentsSearch = ({
documentsSortDirection, documentsSortDirection,
selectedFolder, selectedFolder,
notifyApiError, notifyApiError,
setLoading,
documentsManager, documentsManager,
searchTrigger, searchTrigger,
]); ]);
@@ -7,7 +7,6 @@ import {
FolderOutlineIcon, FolderOutlineIcon,
TagIcon, TagIcon,
CorrespondentIcon, CorrespondentIcon,
LoaderIcon,
} from '../ui/icons'; } from '../ui/icons';
import SelectionAssignmentMenu, { SelectionAssignmentMenuItem } from './SelectionAssignmentMenu'; import SelectionAssignmentMenu, { SelectionAssignmentMenuItem } from './SelectionAssignmentMenu';
import SelectionSummary from './SelectionSummary'; import SelectionSummary from './SelectionSummary';
@@ -287,13 +286,11 @@ const SelectionFloatingActions: React.FC<SelectionFloatingActionsProps> = ({
const tagLookupMap = tagLookupById instanceof Map ? tagLookupById : null; const tagLookupMap = tagLookupById instanceof Map ? tagLookupById : null;
const [remoteFolderOptions, setRemoteFolderOptions] = useState<SelectionAssignmentMenuItem[] | null>(null); const [remoteFolderOptions, setRemoteFolderOptions] = useState<SelectionAssignmentMenuItem[] | null>(null);
const [loadingFolders, setLoadingFolders] = useState(false);
const folderTreeFetchRef = useRef<Promise<SelectionAssignmentMenuItem[]> | null>(null); const folderTreeFetchRef = useRef<Promise<SelectionAssignmentMenuItem[]> | null>(null);
useEffect(() => { useEffect(() => {
setRemoteFolderOptions(null); setRemoteFolderOptions(null);
folderTreeFetchRef.current = null; folderTreeFetchRef.current = null;
setLoadingFolders(false);
}, [tenantId, token]); }, [tenantId, token]);
const requestFolderTree = useCallback(async (): Promise<SelectionAssignmentMenuItem[]> => { const requestFolderTree = useCallback(async (): Promise<SelectionAssignmentMenuItem[]> => {
@@ -311,7 +308,6 @@ const SelectionFloatingActions: React.FC<SelectionFloatingActionsProps> = ({
} }
const fetchPromise = (async () => { const fetchPromise = (async () => {
setLoadingFolders(true);
try { try {
const data = await getFolderTree(); const data = await getFolderTree();
const options = buildFolderTreeOptions(data); const options = buildFolderTreeOptions(data);
@@ -322,7 +318,6 @@ const SelectionFloatingActions: React.FC<SelectionFloatingActionsProps> = ({
setRemoteFolderOptions([]); setRemoteFolderOptions([]);
return []; return [];
} finally { } finally {
setLoadingFolders(false);
folderTreeFetchRef.current = null; folderTreeFetchRef.current = null;
} }
})(); })();
@@ -521,19 +516,15 @@ const SelectionFloatingActions: React.FC<SelectionFloatingActionsProps> = ({
label="Move" label="Move"
triggerContent={( triggerContent={(
<span className="quick-add__chip-label" title="Move"> <span className="quick-add__chip-label" title="Move">
{loadingFolders ? ( <FolderOutlineIcon className="icon-inline" aria-hidden="true" />
<LoaderIcon className="icon-inline icon--spin" aria-hidden="true" />
) : (
<FolderOutlineIcon className="icon-inline" aria-hidden="true" />
)}
<span className="quick-add__chip-text" aria-hidden="true">Move</span> <span className="quick-add__chip-text" aria-hidden="true">Move</span>
</span> </span>
)} )}
items={moveAssignments} items={moveAssignments}
placeholder="Search folders…" placeholder="Search folders…"
emptyMessage={loadingFolders ? 'Loading folders…' : 'No folders'} emptyMessage="No folders"
onToggle={(item) => handleMoveSelectionToFolder(item?.payload || item)} onToggle={(item) => handleMoveSelectionToFolder(item?.payload || item)}
disabled={!documentCount || (loadingFolders && !moveAssignments.length)} disabled={!documentCount}
createLabel={null} createLabel={null}
showStateIndicators={false} showStateIndicators={false}
showCounts={false} showCounts={false}
@@ -19,10 +19,9 @@ interface UseBulkDocumentActionsArgs {
setStatusMessage: (message: string, variant?: string) => void; setStatusMessage: (message: string, variant?: string) => void;
selectedDocumentIds?: Identifier[]; selectedDocumentIds?: Identifier[];
selectedFolderIds?: Identifier[]; selectedFolderIds?: Identifier[];
handleDocumentsDelete: (ids: Identifier[], options?: { showMessage?: boolean; manageLoading?: boolean }) => Promise<boolean>; handleDocumentsDelete: (ids: Identifier[], options?: { showMessage?: boolean }) => Promise<boolean>;
handleFolderDelete: (id: Identifier, options?: { showMessage?: boolean; manageLoading?: boolean }) => Promise<boolean>; handleFolderDelete: (id: Identifier, options?: { showMessage?: boolean }) => Promise<boolean>;
clearDocumentSelection: () => void; clearDocumentSelection: () => void;
setLoading: (value: boolean) => void;
updateDocumentCaches?: (id: Identifier, updater: (doc: any) => any) => void; updateDocumentCaches?: (id: Identifier, updater: (doc: any) => any) => void;
} }
@@ -36,7 +35,6 @@ const useBulkDocumentActions = ({
handleDocumentsDelete, handleDocumentsDelete,
handleFolderDelete, handleFolderDelete,
clearDocumentSelection, clearDocumentSelection,
setLoading,
updateDocumentCaches, updateDocumentCaches,
}: UseBulkDocumentActionsArgs) => { }: UseBulkDocumentActionsArgs) => {
const handleBulkCorrespondentAdd = useCallback( const handleBulkCorrespondentAdd = useCallback(
@@ -202,25 +200,20 @@ const useBulkDocumentActions = ({
return; return;
} }
setLoading(true);
let docsOk = true; let docsOk = true;
let foldersOk = true; let foldersOk = true;
try { if (docIds.length) {
if (docIds.length) { docsOk = await handleDocumentsDelete(docIds, { showMessage: false });
docsOk = await handleDocumentsDelete(docIds, { showMessage: false, manageLoading: false }); }
}
if (folderIds.length) { if (folderIds.length) {
for (const folderId of folderIds) { for (const folderId of folderIds) {
const success = await handleFolderDelete(folderId, { showMessage: false, manageLoading: false }); const success = await handleFolderDelete(folderId, { showMessage: false });
if (!success) { if (!success) {
foldersOk = false; foldersOk = false;
}
} }
} }
} finally {
setLoading(false);
} }
if (!docsOk || !foldersOk) { if (!docsOk || !foldersOk) {
@@ -245,7 +238,6 @@ const useBulkDocumentActions = ({
handleFolderDelete, handleFolderDelete,
selectedDocumentIds, selectedDocumentIds,
selectedFolderIds, selectedFolderIds,
setLoading,
setStatusMessage, setStatusMessage,
]); ]);
@@ -8,14 +8,11 @@ type AppDispatch = (action: { type: string; [key: string]: unknown }) => void;
type SetStatusMessage = (message: string, variant?: string) => void; type SetStatusMessage = (message: string, variant?: string) => void;
type SetLoading = (state: boolean) => void;
interface UseAuthManagerArgs { interface UseAuthManagerArgs {
token?: string | null; token?: string | null;
appStatus: AppStatus; appStatus: AppStatus;
appDispatch: AppDispatch; appDispatch: AppDispatch;
setStatusMessage: SetStatusMessage; setStatusMessage: SetStatusMessage;
setLoading: SetLoading;
} }
interface UseAuthManagerResult { interface UseAuthManagerResult {
@@ -29,7 +26,6 @@ const useAuthManager = ({
appStatus, appStatus,
appDispatch, appDispatch,
setStatusMessage, setStatusMessage,
setLoading,
}: UseAuthManagerArgs): UseAuthManagerResult => { }: UseAuthManagerArgs): UseAuthManagerResult => {
const tokenRef = useRef<string | null>(token); const tokenRef = useRef<string | null>(token);
const initialRefreshAttemptedRef = useRef(Boolean(token)); const initialRefreshAttemptedRef = useRef(Boolean(token));
@@ -71,17 +67,15 @@ const useAuthManager = ({
const handleLogout = useCallback(async () => { const handleLogout = useCallback(async () => {
try { try {
setLoading(true);
await logoutSession(); await logoutSession();
} catch (error) { } catch (error) {
console.warn('[Auth] Failed to revoke refresh token during logout', error); console.warn('[Auth] Failed to revoke refresh token during logout', error);
} finally { } finally {
clearAuthToken(); clearAuthToken();
setLoading(false);
appDispatch({ type: 'LOGOUT' }); appDispatch({ type: 'LOGOUT' });
setStatusMessage('Logged out.', 'info'); setStatusMessage('Logged out.', 'info');
} }
}, [appDispatch, setLoading, setStatusMessage]); }, [appDispatch, setStatusMessage]);
return { tokenRef, refreshAccessToken, handleLogout }; return { tokenRef, refreshAccessToken, handleLogout };
}; };
@@ -90,7 +90,6 @@ interface DocumentTagExtras {
interface DeleteOptions { interface DeleteOptions {
showMessage?: boolean; showMessage?: boolean;
manageLoading?: boolean;
} }
interface TagAttachArgs { interface TagAttachArgs {
@@ -106,7 +105,6 @@ interface TagRemoveOptions {
interface FolderDeleteOptions { interface FolderDeleteOptions {
showMessage?: boolean; showMessage?: boolean;
manageLoading?: boolean;
} }
interface UseDocumentMutationsArgs { interface UseDocumentMutationsArgs {
@@ -129,7 +127,6 @@ interface UseDocumentMutationsArgs {
focusedRowKey: string | null; focusedRowKey: string | null;
notifyApiError: NotifyApiError; notifyApiError: NotifyApiError;
setStatusMessage: SetStatusMessage; setStatusMessage: SetStatusMessage;
setLoading: (next: boolean) => void;
mapDocumentCaches: MapDocumentCaches; mapDocumentCaches: MapDocumentCaches;
applySelectedFolder: ApplySelectedFolder; applySelectedFolder: ApplySelectedFolder;
folderNodes: Map<FolderId, FolderNode>; folderNodes: Map<FolderId, FolderNode>;
@@ -204,7 +201,6 @@ const useDocumentMutations = ({
focusedRowKey, focusedRowKey,
notifyApiError, notifyApiError,
setStatusMessage, setStatusMessage,
setLoading,
mapDocumentCaches, mapDocumentCaches,
applySelectedFolder, applySelectedFolder,
folderNodes, folderNodes,
@@ -285,8 +281,6 @@ const useDocumentMutations = ({
const id = getRowId(key); const id = getRowId(key);
return id ? !uniqueIdSet.has(id as DocumentId) : true; return id ? !uniqueIdSet.has(id as DocumentId) : true;
}); });
setLoading(true);
try { try {
if (uniqueIds.length === 1) { if (uniqueIds.length === 1) {
await moveDocumentToFolder(uniqueIds[0], target); await moveDocumentToFolder(uniqueIds[0], target);
@@ -377,8 +371,6 @@ const useDocumentMutations = ({
} catch (error) { } catch (error) {
const message = (error as Record<string, any>)?.response?.data?.error || 'Failed to move documents.'; const message = (error as Record<string, any>)?.response?.data?.error || 'Failed to move documents.';
notifyApiError(error, message); notifyApiError(error, message);
} finally {
setLoading(false);
} }
}, },
[ [
@@ -399,7 +391,6 @@ const useDocumentMutations = ({
focusedRowKey, focusedRowKey,
notifyApiError, notifyApiError,
setStatusMessage, setStatusMessage,
setLoading,
mapDocumentCaches, mapDocumentCaches,
], ],
); );
@@ -410,7 +401,6 @@ const useDocumentMutations = ({
setStatusMessage('Log in to manage assets.', 'error'); setStatusMessage('Log in to manage assets.', 'error');
return; return;
} }
setLoading(true);
try { try {
await queueDocumentReanalysis(documentId, { force: true }); await queueDocumentReanalysis(documentId, { force: true });
setStatusMessage('Document re-analysis queued.', 'info'); setStatusMessage('Document re-analysis queued.', 'info');
@@ -418,15 +408,13 @@ const useDocumentMutations = ({
} catch (error) { } catch (error) {
const message = (error as Record<string, any>)?.response?.data?.error || 'Failed to request thumbnail generation.'; const message = (error as Record<string, any>)?.response?.data?.error || 'Failed to request thumbnail generation.';
notifyApiError(error, message); notifyApiError(error, message);
} finally {
setLoading(false);
} }
}, },
[token, refreshCurrentFolder, notifyApiError, setStatusMessage, setLoading], [token, refreshCurrentFolder, notifyApiError, setStatusMessage],
); );
const handleDocumentsDelete = useCallback( const handleDocumentsDelete = useCallback(
async (documentIds: DocumentId[], { showMessage = true, manageLoading = true }: DeleteOptions = {}) => { async (documentIds: DocumentId[], { showMessage = true }: DeleteOptions = {}) => {
if (!documentIds || documentIds.length === 0) { if (!documentIds || documentIds.length === 0) {
return false; return false;
} }
@@ -436,10 +424,6 @@ const useDocumentMutations = ({
return false; return false;
} }
if (manageLoading) {
setLoading(true);
}
try { try {
await Promise.all(documentIds.map((documentId) => trashDocument(documentId))); await Promise.all(documentIds.map((documentId) => trashDocument(documentId)));
@@ -458,10 +442,6 @@ const useDocumentMutations = ({
const message = (error as Record<string, any>)?.response?.data?.error || 'Failed to delete documents.'; const message = (error as Record<string, any>)?.response?.data?.error || 'Failed to delete documents.';
notifyApiError(error, message); notifyApiError(error, message);
return false; return false;
} finally {
if (manageLoading) {
setLoading(false);
}
} }
}, },
[ [
@@ -471,7 +451,6 @@ const useDocumentMutations = ({
closeDocumentPreview, closeDocumentPreview,
notifyApiError, notifyApiError,
setStatusMessage, setStatusMessage,
setLoading,
], ],
); );
@@ -482,8 +461,6 @@ const useDocumentMutations = ({
setStatusMessage('Document title cannot be empty.', 'error'); setStatusMessage('Document title cannot be empty.', 'error');
return false; return false;
} }
setLoading(true);
try { try {
const data = await updateDocument(documentId, { title: trimmed }); const data = await updateDocument(documentId, { title: trimmed });
const updatedDocument = extractDocumentFromResponse?.(data); const updatedDocument = extractDocumentFromResponse?.(data);
@@ -505,24 +482,19 @@ const useDocumentMutations = ({
const message = (error as Record<string, any>)?.response?.data?.error || 'Failed to update document title.'; const message = (error as Record<string, any>)?.response?.data?.error || 'Failed to update document title.';
notifyApiError(error, message); notifyApiError(error, message);
return false; return false;
} finally {
setLoading(false);
} }
}, },
[ [
extractDocumentFromResponse, extractDocumentFromResponse,
ingestDocuments, ingestDocuments,
notifyApiError, notifyApiError,
setLoading,
setStatusMessage, setStatusMessage,
updateDocumentCaches, updateDocumentCaches,
], ],
); );
const handleDocumentIssuedUpdate = useCallback( const handleDocumentIssuedUpdate = useCallback(
async (documentId: DocumentId, nextIssuedDate: number | null) => { async (documentId: DocumentId, nextIssuedDate: number | null) => {const payload = { issued_at: nextIssuedDate || null };
setLoading(true);
const payload = { issued_at: nextIssuedDate || null };
try { try {
const data = await updateDocument(documentId, payload); const data = await updateDocument(documentId, payload);
const updatedDocument = extractDocumentFromResponse?.(data); const updatedDocument = extractDocumentFromResponse?.(data);
@@ -545,15 +517,12 @@ const useDocumentMutations = ({
const message = (error as Record<string, any>)?.response?.data?.error || 'Failed to update issued date.'; const message = (error as Record<string, any>)?.response?.data?.error || 'Failed to update issued date.';
notifyApiError(error, message); notifyApiError(error, message);
return false; return false;
} finally {
setLoading(false);
} }
}, },
[ [
extractDocumentFromResponse, extractDocumentFromResponse,
ingestDocuments, ingestDocuments,
notifyApiError, notifyApiError,
setLoading,
setStatusMessage, setStatusMessage,
updateDocumentCaches, updateDocumentCaches,
], ],
@@ -719,7 +688,7 @@ const useDocumentMutations = ({
); );
const handleFolderDelete = useCallback( const handleFolderDelete = useCallback(
async (folderId?: FolderId, { showMessage = true, manageLoading = true }: FolderDeleteOptions = {}) => { async (folderId?: FolderId, { showMessage = true }: FolderDeleteOptions = {}) => {
if (!token) { if (!token) {
if (showMessage) { if (showMessage) {
setStatusMessage('Log in to manage folders.', 'error'); setStatusMessage('Log in to manage folders.', 'error');
@@ -733,10 +702,6 @@ const useDocumentMutations = ({
return false; return false;
} }
if (manageLoading) {
setLoading(true);
}
try { try {
const contents = await ensureFolderData(folderId, { const contents = await ensureFolderData(folderId, {
force: true, force: true,
@@ -802,10 +767,6 @@ const useDocumentMutations = ({
setStatusMessage(message, 'error'); setStatusMessage(message, 'error');
} }
return false; return false;
} finally {
if (manageLoading) {
setLoading(false);
}
} }
}, },
[ [
@@ -819,7 +780,6 @@ const useDocumentMutations = ({
setFolderContents, setFolderContents,
notifyApiError, notifyApiError,
setStatusMessage, setStatusMessage,
setLoading,
], ],
); );
@@ -24,7 +24,6 @@ interface UseDocumentTaggingArgs {
resolveTargetDocumentIds: (ids?: Identifier[] | null) => Identifier[]; resolveTargetDocumentIds: (ids?: Identifier[] | null) => Identifier[];
notifyApiError: (error: unknown, message: string) => void; notifyApiError: (error: unknown, message: string) => void;
setStatusMessage: (message: string, variant?: string) => void; setStatusMessage: (message: string, variant?: string) => void;
setLoading: (state: boolean) => void;
updateDocumentCaches?: (id: Identifier, updater: (doc: TagRecord | null) => TagRecord | null) => void; updateDocumentCaches?: (id: Identifier, updater: (doc: TagRecord | null) => TagRecord | null) => void;
} }
@@ -50,7 +49,6 @@ const useDocumentTagging = ({
resolveTargetDocumentIds, resolveTargetDocumentIds,
notifyApiError, notifyApiError,
setStatusMessage, setStatusMessage,
setLoading,
updateDocumentCaches, updateDocumentCaches,
}: UseDocumentTaggingArgs) => { }: UseDocumentTaggingArgs) => {
const bulkTagOperation = useCallback( const bulkTagOperation = useCallback(
@@ -80,7 +78,6 @@ const useDocumentTagging = ({
}).filter(Boolean); }).filter(Boolean);
} }
setLoading(true);
try { try {
if (action === 'add') { if (action === 'add') {
const createdIds: Identifier[] = []; const createdIds: Identifier[] = [];
@@ -175,8 +172,6 @@ const useDocumentTagging = ({
(action === 'add' ? 'Failed to assign tags.' : 'Failed to remove tags.'); (action === 'add' ? 'Failed to assign tags.' : 'Failed to remove tags.');
notifyApiError(error, message); notifyApiError(error, message);
return { ok: false, reason: 'request-failed' }; return { ok: false, reason: 'request-failed' };
} finally {
setLoading(false);
} }
}, },
[ [
@@ -184,7 +179,6 @@ const useDocumentTagging = ({
tags, tags,
refreshTags, refreshTags,
notifyApiError, notifyApiError,
setLoading,
tagManager, tagManager,
apiClient, apiClient,
updateDocumentCaches, updateDocumentCaches,
@@ -265,7 +259,6 @@ const useDocumentTagging = ({
return; return;
} }
setLoading(true);
try { try {
const response = await apiClient.post<{ queued?: number }>( const response = await apiClient.post<{ queued?: number }>(
'/documents/bulk/reanalyze', '/documents/bulk/reanalyze',
@@ -286,11 +279,9 @@ const useDocumentTagging = ({
const message = const message =
error.response?.data?.error || 'Failed to queue document re-analysis.'; error.response?.data?.error || 'Failed to queue document re-analysis.';
notifyApiError(error, message); notifyApiError(error, message);
} finally {
setLoading(false);
} }
}, },
[resolveTargetDocumentIds, notifyApiError, setStatusMessage, setLoading, apiClient], [resolveTargetDocumentIds, notifyApiError, setStatusMessage, apiClient],
); );
return { return {
@@ -102,7 +102,6 @@ interface UseDocumentUploadsArgs {
currentFolderName?: string | null; currentFolderName?: string | null;
ensureFolderData: (folderId: FolderId, options?: { force?: boolean; prefetchDepth?: number }) => Promise<void>; ensureFolderData: (folderId: FolderId, options?: { force?: boolean; prefetchDepth?: number }) => Promise<void>;
refreshCurrentFolder: () => Promise<void>; refreshCurrentFolder: () => Promise<void>;
setLoading: (state: boolean) => void;
shellRef: MutableRefObject<HTMLElement | null>; shellRef: MutableRefObject<HTMLElement | null>;
notifyApiError?: NotifyApiError; notifyApiError?: NotifyApiError;
setStatusMessage?: SetStatusMessage; setStatusMessage?: SetStatusMessage;
@@ -133,7 +132,6 @@ const useDocumentUploads = ({
currentFolderName, currentFolderName,
ensureFolderData, ensureFolderData,
refreshCurrentFolder, refreshCurrentFolder,
setLoading,
shellRef, shellRef,
notifyApiError, notifyApiError,
setStatusMessage, setStatusMessage,
@@ -395,8 +393,6 @@ const useDocumentUploads = ({
return; return;
} }
setLoading(true);
try { try {
folderPathCacheRef.current.clear(); folderPathCacheRef.current.clear();
@@ -472,8 +468,6 @@ const useDocumentUploads = ({
Object.assign(item, patch); Object.assign(item, patch);
}); });
console.error('[Uploads] batch failed', error); console.error('[Uploads] batch failed', error);
} finally {
setLoading(false);
} }
}, },
[ [
@@ -483,7 +477,6 @@ const useDocumentUploads = ({
refreshCurrentFolder, refreshCurrentFolder,
selectedFolder, selectedFolder,
ensureFolderData, ensureFolderData,
setLoading,
appendQueueItems, appendQueueItems,
updateQueueItem, updateQueueItem,
], ],
@@ -179,14 +179,12 @@ const useDocumentsWorkspace = ({
reportApiError(error, { message: fallbackMessage, variant }), reportApiError(error, { message: fallbackMessage, variant }),
[reportApiError], [reportApiError],
); );
const [loading, setLoading] = useState(false);
const [creatingFolder, setCreatingFolder] = useState(false); const [creatingFolder, setCreatingFolder] = useState(false);
const { tokenRef, handleLogout } = useAuthManager({ const { tokenRef, handleLogout } = useAuthManager({
token, token,
appStatus, appStatus,
appDispatch, appDispatch,
setStatusMessage, setStatusMessage,
setLoading,
}); });
const breadcrumbFetchRef = useRef(new Set()); const breadcrumbFetchRef = useRef(new Set());
@@ -384,7 +382,6 @@ const useDocumentsWorkspace = ({
documentsSortField, documentsSortField,
documentsSortDirection, documentsSortDirection,
notifyApiError, notifyApiError,
setLoading,
setSearchIncludeDescendants, setSearchIncludeDescendants,
documentsManager, documentsManager,
}); });
@@ -590,19 +587,12 @@ const useDocumentsWorkspace = ({
); );
const refreshCurrentFolder = useCallback(async () => { const refreshCurrentFolder = useCallback(async () => {
setLoading(true); const contents = await ensureFolderData(selectedFolder, {
try { force: true,
const contents = await ensureFolderData(selectedFolder, { prefetchDepth: 1,
force: true, });
prefetchDepth: 1, applySelectedFolder(selectedFolder, contents);
}); }, [selectedFolder, ensureFolderData, applySelectedFolder]);
applySelectedFolder(selectedFolder, contents);
} catch (error) {
notifyApiError(error, 'Failed to refresh folder.');
} finally {
setLoading(false);
}
}, [selectedFolder, ensureFolderData, applySelectedFolder, notifyApiError]);
const { const {
handleBulkTagAddFromDetail, handleBulkTagAddFromDetail,
@@ -616,7 +606,6 @@ const useDocumentsWorkspace = ({
resolveTargetDocumentIds, resolveTargetDocumentIds,
notifyApiError, notifyApiError,
setStatusMessage, setStatusMessage,
setLoading,
updateDocumentCaches, updateDocumentCaches,
}); });
@@ -636,7 +625,6 @@ const useDocumentsWorkspace = ({
refreshCurrentFolder, refreshCurrentFolder,
notifyApiError, notifyApiError,
setStatusMessage, setStatusMessage,
setLoading,
shellRef, shellRef,
}); });
@@ -838,7 +826,6 @@ const useDocumentsWorkspace = ({
focusedRowKey, focusedRowKey,
notifyApiError, notifyApiError,
setStatusMessage, setStatusMessage,
setLoading,
mapDocumentCaches, mapDocumentCaches,
applySelectedFolder, applySelectedFolder,
folderNodes, folderNodes,
@@ -875,7 +862,6 @@ const useDocumentsWorkspace = ({
applySelectedFolder, applySelectedFolder,
notifyApiError, notifyApiError,
setStatusMessage, setStatusMessage,
setLoading,
setFolderContents, setFolderContents,
setCurrentFolder, setCurrentFolder,
setSearchResultIds, setSearchResultIds,
@@ -914,18 +900,10 @@ const useDocumentsWorkspace = ({
isFolderRowKey, isFolderRowKey,
}); });
const initializeAfterLogin = useCallback(async () => { const initializeAfterLogin = useCallback(async () => {
setLoading(true); await Promise.all([refreshTags(), refreshCorrespondents()]);
try { const initialFolder = routeFolderId && routeFolderId !== 'root' ? routeFolderId : 'root';
await Promise.all([refreshTags(), refreshCorrespondents()]); await loadFolder(initialFolder, {} );
const initialFolder = routeFolderId && routeFolderId !== 'root' ? routeFolderId : 'root'; }, [refreshTags, refreshCorrespondents, routeFolderId, loadFolder]);
await loadFolder(initialFolder, { showLoading: false });
} catch (error) {
notifyApiError(error, 'Failed to initialize data.');
throw error;
} finally {
setLoading(false);
}
}, [refreshTags, refreshCorrespondents, routeFolderId, loadFolder, notifyApiError]);
useEffect(() => { useEffect(() => {
if (!token) { if (!token) {
@@ -1007,7 +985,6 @@ const useDocumentsWorkspace = ({
handleDocumentsDelete, handleDocumentsDelete,
handleFolderDelete, handleFolderDelete,
clearDocumentSelection, clearDocumentSelection,
setLoading,
updateDocumentCaches, updateDocumentCaches,
}); });
@@ -1380,7 +1357,6 @@ const useDocumentsWorkspace = ({
resetWorkspaceState, resetWorkspaceState,
setStatusMessage, setStatusMessage,
notifyApiError, notifyApiError,
setLoading,
refreshTags, refreshTags,
refreshCorrespondents, refreshCorrespondents,
loadFolder, loadFolder,
@@ -1552,7 +1528,6 @@ const useDocumentsWorkspace = ({
correspondents, correspondents,
handleCorrespondentCreate, handleCorrespondentCreate,
appStatus, appStatus,
loading,
previewActive, previewActive,
handleLogout, handleLogout,
status, status,
@@ -35,7 +35,6 @@ interface EnsureFolderOptions {
} }
interface LoadFolderOptions { interface LoadFolderOptions {
showLoading?: boolean;
preserveSearch?: boolean; preserveSearch?: boolean;
} }
@@ -64,7 +63,6 @@ interface UseFolderTreeActionsOptions {
applySelectedFolder: (folderId: FolderKey, contents: any) => void; applySelectedFolder: (folderId: FolderKey, contents: any) => void;
notifyApiError: (error: unknown, message?: string) => void; notifyApiError: (error: unknown, message?: string) => void;
setStatusMessage: (message: string, level?: string) => void; setStatusMessage: (message: string, level?: string) => void;
setLoading: (value: boolean) => void;
setFolderContents: ( setFolderContents: (
updater: (prev: Map<FolderKey, FolderContentsState>) => Map<FolderKey, FolderContentsState>, updater: (prev: Map<FolderKey, FolderContentsState>) => Map<FolderKey, FolderContentsState>,
) => void; ) => void;
@@ -94,7 +92,6 @@ const useFolderTreeActions = ({
applySelectedFolder, applySelectedFolder,
notifyApiError, notifyApiError,
setStatusMessage, setStatusMessage,
setLoading,
setFolderContents, setFolderContents,
setCurrentFolder, setCurrentFolder,
setSearchResultIds, setSearchResultIds,
@@ -211,12 +208,11 @@ const useFolderTreeActions = ({
); );
const loadFolder = useCallback( const loadFolder = useCallback(
async (folderId: FolderKey | null, { showLoading = true, preserveSearch = false }: LoadFolderOptions = {}) => { async (folderId: FolderKey | null, { preserveSearch = false }: LoadFolderOptions = {}) => {
const targetId = folderId || 'root'; const targetId = folderId || 'root';
setSelectedFolder(targetId); setSelectedFolder(targetId);
await ensureFolderAncestorsLoaded(targetId); await ensureFolderAncestorsLoaded(targetId);
expandFolderAncestors(targetId); expandFolderAncestors(targetId);
if (showLoading) setLoading(true);
try { try {
const contents = await ensureFolderData(targetId, { force: true, prefetchDepth: 1 }); const contents = await ensureFolderData(targetId, { force: true, prefetchDepth: 1 });
if (targetId !== 'root') { if (targetId !== 'root') {
@@ -236,8 +232,6 @@ const useFolderTreeActions = ({
} }
} catch (error) { } catch (error) {
notifyApiError(error, 'Failed to load folder contents.'); notifyApiError(error, 'Failed to load folder contents.');
} finally {
if (showLoading) setLoading(false);
} }
}, },
[ [
@@ -246,7 +240,6 @@ const useFolderTreeActions = ({
ensureFolderData, ensureFolderData,
expandFolderAncestors, expandFolderAncestors,
notifyApiError, notifyApiError,
setLoading,
setSearchResultIds, setSearchResultIds,
setSelectedFolder, setSelectedFolder,
], ],
@@ -289,8 +282,6 @@ const useFolderTreeActions = ({
setStatusMessage('Folder name cannot be empty.', 'error'); setStatusMessage('Folder name cannot be empty.', 'error');
return false; return false;
} }
setLoading(true);
try { try {
await renameFolderRequest(folderId, trimmed); await renameFolderRequest(folderId, trimmed);
@@ -323,8 +314,6 @@ const useFolderTreeActions = ({
const message = error.response?.data?.error || 'Failed to rename folder.'; const message = error.response?.data?.error || 'Failed to rename folder.';
notifyApiError(error, message); notifyApiError(error, message);
return false; return false;
} finally {
setLoading(false);
} }
}, },
[ [
@@ -332,7 +321,6 @@ const useFolderTreeActions = ({
setCurrentFolder, setCurrentFolder,
setFolderContents, setFolderContents,
setFolderNodes, setFolderNodes,
setLoading,
setStatusMessage, setStatusMessage,
token, token,
], ],
@@ -412,7 +400,7 @@ const useFolderTreeActions = ({
); );
const handleFolderDelete = useCallback( const handleFolderDelete = useCallback(
async (folderId: FolderKey, { showMessage = true, manageLoading = true }: { showMessage?: boolean; manageLoading?: boolean } = {}) => { async (folderId: FolderKey, { showMessage = true }: { showMessage?: boolean } = {}) => {
if (!token) { if (!token) {
if (showMessage) { if (showMessage) {
setStatusMessage('Log in to manage folders.', 'error'); setStatusMessage('Log in to manage folders.', 'error');
@@ -426,10 +414,6 @@ const useFolderTreeActions = ({
return false; return false;
} }
if (manageLoading) {
setLoading(true);
}
try { try {
const contents = await ensureFolderData(folderId, { const contents = await ensureFolderData(folderId, {
force: true, force: true,
@@ -495,10 +479,6 @@ const useFolderTreeActions = ({
setStatusMessage(message, 'error'); setStatusMessage(message, 'error');
} }
return false; return false;
} finally {
if (manageLoading) {
setLoading(false);
}
} }
}, },
[ [
@@ -510,7 +490,6 @@ const useFolderTreeActions = ({
selectedFolder, selectedFolder,
setFolderContents, setFolderContents,
setFolderNodes, setFolderNodes,
setLoading,
setSelectedFolder, setSelectedFolder,
setStatusMessage, setStatusMessage,
], ],
@@ -19,10 +19,9 @@ interface UseTenantManagerOptions {
resetWorkspaceState: () => void; resetWorkspaceState: () => void;
setStatusMessage: (message: string, variant?: string) => void; setStatusMessage: (message: string, variant?: string) => void;
notifyApiError: (error: unknown, message: string) => void; notifyApiError: (error: unknown, message: string) => void;
setLoading: (state: boolean) => void;
refreshTags: () => Promise<void>; refreshTags: () => Promise<void>;
refreshCorrespondents: () => Promise<void>; refreshCorrespondents: () => Promise<void>;
loadFolder: (folderId: string, options?: { showLoading?: boolean; preserveSearch?: boolean }) => Promise<void>; loadFolder: (folderId: string, options?: { preserveSearch?: boolean }) => Promise<void>;
handleDocumentsViewModeChange: (mode: string) => void; handleDocumentsViewModeChange: (mode: string) => void;
navigate: NavigateFunction; navigate: NavigateFunction;
tokenRef?: MutableRefObject<string | null>; tokenRef?: MutableRefObject<string | null>;
@@ -36,7 +35,6 @@ const useTenantManager = ({
resetWorkspaceState, resetWorkspaceState,
setStatusMessage, setStatusMessage,
notifyApiError, notifyApiError,
setLoading,
refreshTags, refreshTags,
refreshCorrespondents, refreshCorrespondents,
loadFolder, loadFolder,
@@ -52,7 +50,6 @@ const useTenantManager = ({
return; return;
} }
setLoading(true);
try { try {
if (!refreshOnly) { if (!refreshOnly) {
setStatusMessage('Switching tenant…', 'info'); setStatusMessage('Switching tenant…', 'info');
@@ -99,14 +96,12 @@ const useTenantManager = ({
navigate('/documents', { replace: true }); navigate('/documents', { replace: true });
await Promise.all([refreshTags(), refreshCorrespondents()]); await Promise.all([refreshTags(), refreshCorrespondents()]);
await loadFolder('root', { showLoading: false, preserveSearch: false }); await loadFolder('root', { preserveSearch: false });
const tenantLabel = data?.tenant?.name || data?.tenant?.id || 'tenant'; const tenantLabel = data?.tenant?.name || data?.tenant?.id || 'tenant';
setStatusMessage(`Switched to ${tenantLabel}.`, 'info'); setStatusMessage(`Switched to ${tenantLabel}.`, 'info');
} catch (error) { } catch (error) {
notifyApiError(error, 'Failed to switch tenant.'); notifyApiError(error, 'Failed to switch tenant.');
} finally {
setLoading(false);
} }
}, },
[ [
@@ -120,7 +115,6 @@ const useTenantManager = ({
refreshCorrespondents, refreshCorrespondents,
refreshTags, refreshTags,
resetWorkspaceState, resetWorkspaceState,
setLoading,
setStatusMessage, setStatusMessage,
tenantIdRef, tenantIdRef,
tokenRef, tokenRef,
+1 -4
View File
@@ -40,7 +40,7 @@ interface UseApiTokensResult {
const useApiTokens = ({ notifyApiError, setStatusMessage, token }: UseApiTokensArgs): UseApiTokensResult => { const useApiTokens = ({ notifyApiError, setStatusMessage, token }: UseApiTokensArgs): UseApiTokensResult => {
const [tokens, setTokens] = useState<ApiTokenRecord[]>([]); const [tokens, setTokens] = useState<ApiTokenRecord[]>([]);
const [loading, setLoading] = useState(false); const [loading] = useState(false);
const [creating, setCreating] = useState(false); const [creating, setCreating] = useState(false);
const [deletingId, setDeletingId] = useState<string | number | null>(null); const [deletingId, setDeletingId] = useState<string | number | null>(null);
const [regeneratingId, setRegeneratingId] = useState<string | number | null>(null); const [regeneratingId, setRegeneratingId] = useState<string | number | null>(null);
@@ -50,14 +50,11 @@ const useApiTokens = ({ notifyApiError, setStatusMessage, token }: UseApiTokensA
if (!token) { if (!token) {
return; return;
} }
setLoading(true);
try { try {
const data = await listApiTokens(); const data = await listApiTokens();
setTokens(Array.isArray(data) ? data : []); setTokens(Array.isArray(data) ? data : []);
} catch (error) { } catch (error) {
notifyApiError?.(error, 'Failed to load API tokens.'); notifyApiError?.(error, 'Failed to load API tokens.');
} finally {
setLoading(false);
} }
}, [notifyApiError, token]); }, [notifyApiError, token]);
-5
View File
@@ -88,7 +88,6 @@ interface UseSidebarPropsArgs {
| null | null
| void; | void;
appStatus: string; appStatus: string;
loading: boolean;
previewActive: boolean; previewActive: boolean;
handleLogout: () => void | Promise<void>; handleLogout: () => void | Promise<void>;
status: StatusMessage | null; status: StatusMessage | null;
@@ -122,7 +121,6 @@ interface SidebarHookResult {
correspondents: CorrespondentOption[]; correspondents: CorrespondentOption[];
onCreateCorrespondent: (name: string) => void; onCreateCorrespondent: (name: string) => void;
appStatus: string; appStatus: string;
loading: boolean;
previewActive: boolean; previewActive: boolean;
onLogout: UseSidebarPropsArgs['handleLogout']; onLogout: UseSidebarPropsArgs['handleLogout'];
status: StatusMessage | null; status: StatusMessage | null;
@@ -151,7 +149,6 @@ const useSidebarProps = ({
correspondents, correspondents,
handleCorrespondentCreate, handleCorrespondentCreate,
appStatus, appStatus,
loading,
previewActive, previewActive,
handleLogout, handleLogout,
status, status,
@@ -185,7 +182,6 @@ const useSidebarProps = ({
correspondents, correspondents,
onCreateCorrespondent: (name) => handleCorrespondentCreate({ name }), onCreateCorrespondent: (name) => handleCorrespondentCreate({ name }),
appStatus, appStatus,
loading,
previewActive, previewActive,
onLogout: handleLogout, onLogout: handleLogout,
status, status,
@@ -228,7 +224,6 @@ const useSidebarProps = ({
handlePromptCreateFolder, handlePromptCreateFolder,
handleTagCreate, handleTagCreate,
handleTenantSelect, handleTenantSelect,
loading,
openSettings, openSettings,
previewActive, previewActive,
draggedFolderId, draggedFolderId,