feat: Refactor DocumentsPanel to use a shared application shell context for state management
This commit is contained in:
@@ -1,27 +1,29 @@
|
||||
import React, {
|
||||
useCallback,
|
||||
useMemo,
|
||||
useState,
|
||||
useRef,
|
||||
useEffect,
|
||||
useCallback,
|
||||
} from 'react';
|
||||
import TagRemovalZone from '../components/TagRemovalZone';
|
||||
import { DocumentsList, DocumentsGrid } from '../DocumentsView';
|
||||
import type { ReactNode } from 'react';
|
||||
import type {
|
||||
DocumentsListEntry,
|
||||
Correspondent,
|
||||
} from '../../types/documents';
|
||||
import type { Identifier } from '../../types/identifiers';
|
||||
|
||||
const EntryType = {
|
||||
folder: 'folder' as const,
|
||||
document: 'document' as const,
|
||||
};
|
||||
|
||||
import DesktopWorkspace from '../../desktop/components/DesktopWorkspace';
|
||||
import {
|
||||
WorkspaceSelectionProvider,
|
||||
useWorkspaceSelectionContext,
|
||||
type WorkspaceSelectionValue,
|
||||
} from '../../app/WorkspaceSelectionContext';
|
||||
import DocumentsPanelHeader, {
|
||||
DocumentsPanelHeaderConfig,
|
||||
DocumentsHeaderBreadcrumb,
|
||||
} from './DocumentsPanelHeader';
|
||||
import { SelectionFloatingPanel } from '../features/selection/SelectionFloatingActions';
|
||||
import { createDocumentsTableHeaderActions } from './DocumentsToolbar';
|
||||
@@ -35,58 +37,31 @@ import { DocumentsAssetContext } from '../context/DocumentsAssetContext';
|
||||
import { DocumentsViewStateContext } from '../context/DocumentsViewStateContext';
|
||||
import { DocumentsCommandContext } from '../context/DocumentsCommandContext';
|
||||
import { useDocumentsContextValues } from './useDocumentsContextValues';
|
||||
|
||||
const EntryType = {
|
||||
folder: 'folder' as const,
|
||||
document: 'document' as const,
|
||||
};
|
||||
|
||||
export interface DocumentsPanelInnerProps {
|
||||
headerLeading?: ReactNode;
|
||||
onBreadcrumbNavigate?: (crumb: DocumentsHeaderBreadcrumb) => void;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
interface DocumentsPanelProps extends DocumentsPanelInnerProps {
|
||||
selectionValue: WorkspaceSelectionValue;
|
||||
correspondentLookupById?: Map<Identifier, Correspondent>;
|
||||
}
|
||||
|
||||
import { useAppShell } from '../../lib/context/AppShellContext';
|
||||
import type { TagInteractionHandlers } from '../interactions/useTagInteractions';
|
||||
|
||||
export interface DocumentsViewProps {
|
||||
entries: DocumentsListEntry[];
|
||||
tagHandlers?: TagInteractionHandlers;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = (props) => {
|
||||
interface DocumentsPanelProps {
|
||||
headerLeading?: ReactNode;
|
||||
}
|
||||
|
||||
const DocumentsPanelInner: React.FC<DocumentsPanelProps> = (props) => {
|
||||
const { headerLeading } = props;
|
||||
const shell = useAppShell();
|
||||
const {
|
||||
headerLeading = null,
|
||||
onBreadcrumbNavigate,
|
||||
currentFolderName,
|
||||
breadcrumbs,
|
||||
subfolders,
|
||||
documents,
|
||||
searchResultIds,
|
||||
onRefresh = () => { },
|
||||
sortField,
|
||||
sortDirection,
|
||||
onSortFieldChange,
|
||||
onSortDirectionToggle,
|
||||
onDeleteSelection,
|
||||
documentLookup,
|
||||
tags,
|
||||
correspondents,
|
||||
onBulkTagAdd,
|
||||
onBulkTagRemove,
|
||||
onBulkCorrespondentAdd,
|
||||
onBulkCorrespondentRemove,
|
||||
onBulkReanalyze,
|
||||
folderOptions,
|
||||
onMoveDocumentsToFolder,
|
||||
viewMode = 'list',
|
||||
onViewModeChange,
|
||||
} = props;
|
||||
search: { documents, searchResultIds, documentsViewMode: viewMode, documentsSortField: sortField, documentsSortDirection: sortDirection, handleDocumentsViewModeChange: onViewModeChange, handleDocumentsSortFieldChange: onSortFieldChange, handleDocumentsSortDirectionToggle: onSortDirectionToggle },
|
||||
folderTree: { currentFolderName, breadcrumbs, currentSubfolders: subfolders, folderOptions, moveDocumentsToFolder: onMoveDocumentsToFolder, refreshCurrentFolder: onRefresh, handleBreadcrumbNavigate: onBreadcrumbNavigate },
|
||||
selection: { handleDeleteSelection: onDeleteSelection },
|
||||
managers: { documentLookup },
|
||||
tags: { tags, handleBulkTagAddFromDetail: onBulkTagAdd, handleBulkTagRemoveFromDetail: onBulkTagRemove },
|
||||
correspondents: { correspondents, handleBulkCorrespondentAdd: onBulkCorrespondentAdd, handleBulkCorrespondentRemove: onBulkCorrespondentRemove },
|
||||
mutations: { handleBulkSelectionReanalyze: onBulkReanalyze },
|
||||
} = shell as any;
|
||||
|
||||
const {
|
||||
assetContextValue,
|
||||
@@ -95,7 +70,7 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = (props) => {
|
||||
tagHandlers,
|
||||
scrollRef,
|
||||
hasDocumentEntries,
|
||||
} = useDocumentsContextValues(props);
|
||||
} = useDocumentsContextValues();
|
||||
|
||||
const {
|
||||
clearSelection,
|
||||
@@ -119,7 +94,6 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = (props) => {
|
||||
const showingSearchResults = Array.isArray(searchResultIds);
|
||||
const rows = showingSearchResults && searchDocuments ? searchDocuments : documents;
|
||||
|
||||
|
||||
const headerTitle = showingSearchResults
|
||||
? 'Search results'
|
||||
: currentFolderName || 'Documents';
|
||||
@@ -150,13 +124,16 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = (props) => {
|
||||
toggleIncludeDescendants,
|
||||
],
|
||||
);
|
||||
|
||||
const { tagLookupById, correspondentLookupById } = (shell as any).tags;
|
||||
|
||||
const floatingActions = useMemo(() => (
|
||||
<SelectionFloatingPanel
|
||||
documentLookup={documentLookup}
|
||||
tags={tags}
|
||||
tagLookupById={props.tagLookupById}
|
||||
tagLookupById={tagLookupById}
|
||||
correspondents={correspondents}
|
||||
correspondentLookupById={props.correspondentLookupById}
|
||||
correspondentLookupById={correspondentLookupById}
|
||||
onBulkTagAdd={onBulkTagAdd}
|
||||
onBulkTagRemove={onBulkTagRemove}
|
||||
onBulkCorrespondentAdd={onBulkCorrespondentAdd}
|
||||
@@ -170,9 +147,9 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = (props) => {
|
||||
), [
|
||||
documentLookup,
|
||||
tags,
|
||||
props.tagLookupById,
|
||||
tagLookupById,
|
||||
correspondents,
|
||||
props.correspondentLookupById,
|
||||
correspondentLookupById,
|
||||
onBulkTagAdd,
|
||||
onBulkTagRemove,
|
||||
onBulkCorrespondentAdd,
|
||||
@@ -183,6 +160,7 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = (props) => {
|
||||
onMoveDocumentsToFolder,
|
||||
clearSelection,
|
||||
]);
|
||||
|
||||
const headerConfig: DocumentsPanelHeaderConfig = useMemo(() => ({
|
||||
title: headerTitle,
|
||||
subtitle: null,
|
||||
@@ -230,14 +208,14 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = (props) => {
|
||||
const entries = useMemo(() => {
|
||||
const list: DocumentsListEntry[] = []; // Explicit type
|
||||
if (!showingSearchResults) {
|
||||
subfolders.forEach((folder: any) => {
|
||||
(subfolders || []).forEach((folder: any) => {
|
||||
if (!folder || !folder.id) {
|
||||
return;
|
||||
}
|
||||
list.push({ type: EntryType.folder, id: folder.id, key: `folder:${folder.id}`, folder });
|
||||
});
|
||||
}
|
||||
rows.forEach((doc: any) => {
|
||||
(rows || []).forEach((doc: any) => {
|
||||
if (!doc || !doc.id) {
|
||||
return;
|
||||
}
|
||||
@@ -261,7 +239,7 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = (props) => {
|
||||
desk: DEFAULT_DESKTOP_CARD_SIZE,
|
||||
});
|
||||
|
||||
const isSearchLoading = props.isSearchLoading || false;
|
||||
const isSearchLoading = (shell as any).search?.isSearchLoading || false;
|
||||
|
||||
const renderBody = () => {
|
||||
const hasEntries = entries.length > 0;
|
||||
@@ -328,10 +306,15 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
const DocumentsPanel: React.FC<DocumentsPanelProps> = ({ selectionValue, ...rest }) => (
|
||||
<WorkspaceSelectionProvider value={selectionValue}>
|
||||
<DocumentsPanelInner {...rest} />
|
||||
</WorkspaceSelectionProvider>
|
||||
);
|
||||
const DocumentsPanel: React.FC<DocumentsPanelProps> = (props) => {
|
||||
const shell = useAppShell();
|
||||
const selectionValue = (shell as any).selection?.selectionValue;
|
||||
|
||||
return (
|
||||
<WorkspaceSelectionProvider value={selectionValue}>
|
||||
<DocumentsPanelInner {...props} />
|
||||
</WorkspaceSelectionProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default DocumentsPanel;
|
||||
|
||||
Reference in New Issue
Block a user