refactor: Move DocumentsListProps to DocumentsPanel and implement desk view selection and ID generation.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import type { DragEvent, MouseEvent, RefObject } from 'react';
|
||||
import type { MouseEvent } from 'react';
|
||||
import { FolderIcon, CheckIcon, CloseIcon } from '../ui/icons';
|
||||
import { getTagColorStyle } from '../utils/colors';
|
||||
import { formatDate } from '../utils/date';
|
||||
@@ -10,6 +10,7 @@ import { writeTagTransferData } from './tagTransfer';
|
||||
import useInlineRename from './useInlineRename';
|
||||
import { useWorkspaceSelectionContext } from '../app/WorkspaceSelectionContext';
|
||||
import type { Identifier } from '../types/identifiers';
|
||||
import type { DocumentsListProps } from './panel/DocumentsPanel';
|
||||
|
||||
export interface FolderLike {
|
||||
id?: Identifier | 'root';
|
||||
@@ -57,36 +58,6 @@ export type DocumentsListEntry = FolderEntry | DocumentEntry;
|
||||
export type FolderEventHandler = (folder: FolderLike, event: MouseEvent<HTMLTableRowElement>) => void;
|
||||
export type DocumentEventHandler = (document: DocumentLike, event: MouseEvent<HTMLTableRowElement>) => void;
|
||||
|
||||
export interface DocumentsListProps {
|
||||
entries: DocumentsListEntry[];
|
||||
draggingDocumentIdsSet?: Set<Identifier> | null;
|
||||
draggedFolderId?: Identifier | 'root' | null;
|
||||
ensureAssetUrl?: (...args: any[]) => unknown;
|
||||
getDocumentAsset?: (...args: any[]) => unknown;
|
||||
onFolderClick?: FolderEventHandler;
|
||||
onFolderSelect?: (folderId: Identifier | 'root') => void;
|
||||
onFolderDragOver?: (event: DragEvent<HTMLTableRowElement>, folderId: Identifier | 'root') => void;
|
||||
onFolderDragLeave?: (event: DragEvent<HTMLTableRowElement>) => void;
|
||||
onFolderDrop?: (event: DragEvent<HTMLTableRowElement>, folderId: Identifier | 'root') => void;
|
||||
onFolderDragStart?: (event: DragEvent<HTMLTableRowElement>, folderId: Identifier | 'root') => void;
|
||||
onFolderDragEnd?: (event: DragEvent<HTMLTableRowElement>) => void;
|
||||
onFolderRename?: (folderId: Identifier | 'root', nextName: string) => Promise<boolean> | boolean;
|
||||
onDocumentClick?: DocumentEventHandler;
|
||||
onDocumentActivate?: DocumentEventHandler;
|
||||
onDocumentDragStart?: (event: DragEvent<HTMLTableRowElement>, document: DocumentLike) => void;
|
||||
onDocumentDragEnd?: (event: DragEvent<HTMLTableRowElement>) => void;
|
||||
onDocumentTagDragOver?: (event: DragEvent<HTMLTableRowElement>) => void;
|
||||
onDocumentTagDragLeave?: (event: DragEvent<HTMLTableRowElement>) => void;
|
||||
onDocumentTagDrop?: (event: DragEvent<HTMLTableRowElement>, documentId: Identifier) => void;
|
||||
onDocumentRename?: (documentId: Identifier, nextTitle: string) => Promise<boolean> | boolean;
|
||||
tagLookupById?: Map<Identifier, DocumentTag> | null;
|
||||
onTagClick?: (tagId: Identifier) => void;
|
||||
onCorrespondentClick?: (correspondentId: Identifier) => void;
|
||||
activeCorrespondentIdSet?: Set<Identifier> | null;
|
||||
scrollRef?: RefObject<HTMLElement | null>;
|
||||
}
|
||||
|
||||
|
||||
const DocumentsList: React.FC<DocumentsListProps> = ({
|
||||
entries,
|
||||
draggingDocumentIdsSet,
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import DocumentsGrid from '../DocumentsGrid';
|
||||
import DocumentsList from '../DocumentsList';
|
||||
import type { DragEvent, ReactNode, RefObject } from 'react';
|
||||
import type {
|
||||
DocumentsListEntry,
|
||||
FolderEventHandler,
|
||||
DocumentEventHandler,
|
||||
DocumentLike,
|
||||
DocumentTag,
|
||||
} from '../DocumentsList';
|
||||
import DesktopWorkspace from '../../desktop/DesktopWorkspace';
|
||||
import { isTagTransferEvent } from '../tagTransfer';
|
||||
import { isTagTransferEvent, parseTagTransferPayload } from '../tagTransfer';
|
||||
import PreviewZoomOverlay from '../../detail/PreviewZoomOverlay';
|
||||
import { isPointerModifierEvent, isPrimaryPointerEvent } from '../useEntryPointer';
|
||||
import {
|
||||
@@ -16,6 +23,7 @@ import DocumentsPanelHeader, {
|
||||
DocumentsHeaderBreadcrumb,
|
||||
} from './DocumentsPanelHeader';
|
||||
import { SelectionFloatingPanel } from '../SelectionFloatingActions';
|
||||
import { createDocumentEntryKey } from '../../app/entryKey';
|
||||
import { createDocumentsTableHeaderActions } from './DocumentsToolbar';
|
||||
import { useDocumentsFilter } from '../context/DocumentsFilterContext';
|
||||
import { DEFAULT_GRID_ICON_SIZE } from '../../constants/documents';
|
||||
@@ -41,34 +49,32 @@ const defaultGetDocumentAsset = (_doc?: unknown, _type?: string) => null;
|
||||
export type DocumentLinkLike = { url?: string | null; mimeType?: string | null };
|
||||
|
||||
export interface DocumentsListProps {
|
||||
entries: Array<{ type: string; id: Identifier; key: string; folder?: any; document?: any }>;
|
||||
draggingDocumentIdsSet: Set<Identifier>;
|
||||
draggedFolderId: Identifier | 'root' | null;
|
||||
onFolderClick: (folder: any, event: React.MouseEvent) => void;
|
||||
onFolderSelect?: (id: Identifier) => void;
|
||||
onFolderDragOver?: (event: React.DragEvent, folder: any) => void;
|
||||
onFolderDragLeave?: (event: React.DragEvent) => void;
|
||||
onFolderDrop?: (event: React.DragEvent, folder: any) => void;
|
||||
onFolderDragStart?: (event: React.DragEvent, folder: any) => void;
|
||||
onFolderDragEnd?: (event: React.DragEvent) => void;
|
||||
onDocumentClick: (doc: any, event: React.MouseEvent) => void;
|
||||
onDocumentActivate: (doc: any, event?: React.MouseEvent | KeyboardEvent) => void;
|
||||
onDocumentDragStart?: (event: React.DragEvent, doc: any) => void;
|
||||
onDocumentDragEnd?: (event: React.DragEvent) => void;
|
||||
onDocumentTagDragOver?: (event: React.DragEvent) => void;
|
||||
onDocumentTagDragLeave?: (event: React.DragEvent) => void;
|
||||
onDocumentTagDrop?: (event: React.DragEvent, docId: Identifier) => void;
|
||||
ensureAssetUrl?: any;
|
||||
getDocumentAsset?: any;
|
||||
tagLookupById?: any;
|
||||
entries: DocumentsListEntry[];
|
||||
draggingDocumentIdsSet?: Set<Identifier> | null;
|
||||
draggedFolderId?: Identifier | 'root' | null;
|
||||
ensureAssetUrl?: (...args: any[]) => unknown;
|
||||
getDocumentAsset?: (...args: any[]) => unknown;
|
||||
onFolderClick?: FolderEventHandler;
|
||||
onFolderSelect?: (folderId: Identifier | 'root') => void;
|
||||
onFolderDragOver?: (event: DragEvent<HTMLTableRowElement>, folderId: Identifier | 'root') => void;
|
||||
onFolderDragLeave?: (event: DragEvent<HTMLTableRowElement>) => void;
|
||||
onFolderDrop?: (event: DragEvent<HTMLTableRowElement>, folderId: Identifier | 'root') => void;
|
||||
onFolderDragStart?: (event: DragEvent<HTMLTableRowElement>, folderId: Identifier | 'root') => void;
|
||||
onFolderDragEnd?: (event: DragEvent<HTMLTableRowElement>) => void;
|
||||
onFolderRename?: (folderId: Identifier | 'root', nextName: string) => Promise<boolean> | boolean;
|
||||
onDocumentClick?: DocumentEventHandler;
|
||||
onDocumentActivate?: DocumentEventHandler;
|
||||
onDocumentDragStart?: (event: DragEvent<HTMLTableRowElement>, document: DocumentLike) => void;
|
||||
onDocumentDragEnd?: (event: DragEvent<HTMLTableRowElement>) => void;
|
||||
onDocumentTagDragOver?: (event: DragEvent<HTMLTableRowElement>) => void;
|
||||
onDocumentTagDragLeave?: (event: DragEvent<HTMLTableRowElement>) => void;
|
||||
onDocumentTagDrop?: (event: DragEvent<HTMLTableRowElement>, documentId: Identifier) => void;
|
||||
onDocumentRename?: (documentId: Identifier, nextTitle: string) => Promise<boolean> | boolean;
|
||||
tagLookupById?: Map<Identifier, DocumentTag> | null;
|
||||
onTagClick?: (tagId: Identifier) => void;
|
||||
scrollRef?: React.RefObject<HTMLElement>;
|
||||
onCorrespondentClick?: (correspondentId: Identifier) => void;
|
||||
activeCorrespondentIdSet?: Set<Identifier>;
|
||||
onDocumentRename?: (id: Identifier, name: string) => void;
|
||||
onFolderRename?: (id: Identifier, name: string) => void;
|
||||
focusedRowKey?: string | null;
|
||||
gridIconSize?: number;
|
||||
activeCorrespondentIdSet?: Set<Identifier> | null;
|
||||
scrollRef?: RefObject<HTMLElement | null>;
|
||||
}
|
||||
|
||||
const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
|
||||
@@ -98,12 +104,10 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
|
||||
ensureAssetUrl = null,
|
||||
getDocumentAsset = defaultGetDocumentAsset,
|
||||
isSearchLoading = false,
|
||||
onDocumentTagDrop,
|
||||
viewMode = 'list',
|
||||
onViewModeChange,
|
||||
documentLinks,
|
||||
ensureDownloadUrl,
|
||||
deskWorkspaceProps = null,
|
||||
onRefresh = () => { },
|
||||
sortField,
|
||||
sortDirection,
|
||||
@@ -120,6 +124,13 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
|
||||
onBulkReanalyze,
|
||||
folderOptions,
|
||||
onMoveDocumentsToFolder,
|
||||
searchQuery,
|
||||
activeTagFilters,
|
||||
activeCorrespondentFilters,
|
||||
selectedFolder,
|
||||
promoteSelectionOrder,
|
||||
onDocumentTagDrop,
|
||||
currentTenantId,
|
||||
}): ReactNode => {
|
||||
const {
|
||||
selectedEntries,
|
||||
@@ -127,6 +138,8 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
|
||||
setFocusedRowKey,
|
||||
handleEntrySelection,
|
||||
clearSelection,
|
||||
selectionAnchorRef,
|
||||
applySelection,
|
||||
} = useWorkspaceSelectionContext();
|
||||
const {
|
||||
isActive: isFilterActive,
|
||||
@@ -144,10 +157,63 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
|
||||
: null,
|
||||
[searchResultIds, documentLookup],
|
||||
);
|
||||
|
||||
const showingSearchResults = Array.isArray(searchResultIds);
|
||||
const rows = showingSearchResults && searchDocuments ? searchDocuments : documents;
|
||||
const documentLinkMap = documentLinks instanceof Map ? documentLinks : null;
|
||||
const searchResultCount = Array.isArray(searchResultIds) ? searchResultIds.length : 0;
|
||||
|
||||
const handleDeskDocumentStackSelect = useCallback(
|
||||
(docIds: Array<Identifier | string>) => {
|
||||
if (!Array.isArray(docIds) || docIds.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rowKeys = docIds
|
||||
.map((id) => createDocumentEntryKey(id as Identifier))
|
||||
.filter((value): value is string => typeof value === 'string');
|
||||
|
||||
if (!rowKeys.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextKeys = [...selectedEntries];
|
||||
rowKeys.forEach((key) => {
|
||||
if (!nextKeys.includes(key)) {
|
||||
nextKeys.push(key);
|
||||
}
|
||||
});
|
||||
|
||||
const anchor = (rowKeys[0]
|
||||
|| selectionAnchorRef.current
|
||||
|| nextKeys[nextKeys.length - 1]) as string | null;
|
||||
|
||||
applySelection(nextKeys, {
|
||||
anchor,
|
||||
interactedKeys: rowKeys,
|
||||
});
|
||||
},
|
||||
[applySelection, selectedEntries, selectionAnchorRef],
|
||||
);
|
||||
|
||||
const deskViewId = useMemo(() => {
|
||||
if (showingSearchResults) {
|
||||
const trimmedQuery = searchQuery.trim();
|
||||
const tagsKey = [...activeTagFilters].sort().join(',');
|
||||
const correspondentsKey = [...activeCorrespondentFilters].sort().join(',');
|
||||
return `search:${trimmedQuery}|tags:${tagsKey}|corr:${correspondentsKey}`;
|
||||
}
|
||||
|
||||
const folderKey = selectedFolder && selectedFolder !== '' ? selectedFolder : 'root';
|
||||
return `folder:${folderKey}`;
|
||||
}, [
|
||||
showingSearchResults,
|
||||
searchQuery,
|
||||
activeTagFilters,
|
||||
activeCorrespondentFilters,
|
||||
selectedFolder,
|
||||
]);
|
||||
|
||||
const headerTitle = showingSearchResults
|
||||
? 'Search results'
|
||||
: currentFolderName || 'Documents';
|
||||
@@ -286,6 +352,7 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
|
||||
const suppressDocumentClickRef = useRef(false);
|
||||
const isGridView = viewMode === 'grid';
|
||||
const isDeskView = viewMode === 'desk';
|
||||
const gridIconSize = DEFAULT_GRID_ICON_SIZE;
|
||||
|
||||
type ZoomSource = { url: string; alt?: string | null; mimeType?: string | null };
|
||||
|
||||
@@ -545,8 +612,6 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
|
||||
],
|
||||
);
|
||||
|
||||
const gridIconSize = DEFAULT_GRID_ICON_SIZE;
|
||||
|
||||
const scrollToTop = useCallback(() => {
|
||||
if (scrollRef.current) {
|
||||
scrollRef.current.scrollTop = 0;
|
||||
@@ -650,32 +715,6 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
|
||||
[isTagDragEvent],
|
||||
);
|
||||
|
||||
const handleDocumentTagDrop = useCallback(
|
||||
(event, documentId) => {
|
||||
if (!isTagDragEvent(event)) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
event.currentTarget.classList.remove('tag-drop-target');
|
||||
const payload =
|
||||
event.dataTransfer.getData('application/x-papercrate-tag') ||
|
||||
event.dataTransfer.getData('text/papercrate-tag');
|
||||
if (!payload) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const parsed = JSON.parse(payload);
|
||||
if (parsed?.id && onDocumentTagDrop) {
|
||||
onDocumentTagDrop(documentId, parsed);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('[documents] Failed to parse tag drop payload', error);
|
||||
}
|
||||
},
|
||||
[isTagDragEvent, onDocumentTagDrop],
|
||||
);
|
||||
|
||||
const handleDocumentClick = useCallback(
|
||||
(doc, event) => {
|
||||
if (!doc || suppressDocumentClickRef.current || !onEntryPointer) {
|
||||
@@ -738,6 +777,81 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
|
||||
[entries],
|
||||
);
|
||||
|
||||
const handleListDocumentTagDrop = useCallback(
|
||||
(event: React.DragEvent<HTMLElement>, docId: Identifier) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const payload = parseTagTransferPayload(event);
|
||||
if (payload && onDocumentTagDrop) {
|
||||
onDocumentTagDrop(docId, payload);
|
||||
}
|
||||
},
|
||||
[onDocumentTagDrop],
|
||||
);
|
||||
|
||||
const deskWorkspaceProps = useMemo(
|
||||
() => ({
|
||||
entries: rows,
|
||||
onDocumentActivate,
|
||||
onDocumentClick: onEntryPointer,
|
||||
onDocumentStackSelect: handleDeskDocumentStackSelect,
|
||||
onPromoteSelection: promoteSelectionOrder,
|
||||
onDocumentTagDrop,
|
||||
ensureAssetUrl,
|
||||
getDocumentAsset,
|
||||
activeTagFilters,
|
||||
tenantId: currentTenantId,
|
||||
viewId: deskViewId,
|
||||
documentLinks: documentLinkMap,
|
||||
ensureDownloadUrl,
|
||||
}),
|
||||
[
|
||||
rows,
|
||||
onDocumentActivate,
|
||||
onEntryPointer,
|
||||
handleDeskDocumentStackSelect,
|
||||
promoteSelectionOrder,
|
||||
onDocumentTagDrop,
|
||||
ensureAssetUrl,
|
||||
getDocumentAsset,
|
||||
activeTagFilters,
|
||||
currentTenantId,
|
||||
deskViewId,
|
||||
documentLinkMap,
|
||||
ensureDownloadUrl,
|
||||
],
|
||||
);
|
||||
|
||||
const listProps: DocumentsListProps = {
|
||||
entries,
|
||||
draggingDocumentIdsSet: draggingSet,
|
||||
draggedFolderId,
|
||||
onFolderClick: handleFolderClick,
|
||||
onFolderSelect,
|
||||
onFolderDragOver,
|
||||
onFolderDragLeave,
|
||||
onFolderDrop,
|
||||
onFolderDragStart,
|
||||
onFolderDragEnd,
|
||||
onDocumentClick: handleDocumentClick,
|
||||
onDocumentActivate: handleDocumentActivate,
|
||||
onDocumentDragStart: handleDocumentDragStartLocal,
|
||||
onDocumentDragEnd: handleDocumentDragEndLocal,
|
||||
onDocumentTagDragOver: handleDocumentTagDragOver,
|
||||
onDocumentTagDragLeave: handleDocumentTagDragLeave,
|
||||
onDocumentTagDrop: handleListDocumentTagDrop,
|
||||
onDocumentRename,
|
||||
onFolderRename,
|
||||
ensureAssetUrl,
|
||||
getDocumentAsset,
|
||||
tagLookupById,
|
||||
onTagClick: toggleTagFilter,
|
||||
onCorrespondentClick: toggleCorrespondentFilter,
|
||||
activeCorrespondentIdSet: activeCorrespondentIdSet,
|
||||
scrollRef,
|
||||
};
|
||||
|
||||
const renderBody = () => {
|
||||
const hasEntries = entries.length > 0;
|
||||
const isSearchEmpty = (showingSearchResults || isFilterActive) && !hasDocumentEntries && !isSearchLoading;
|
||||
@@ -751,47 +865,18 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
|
||||
}
|
||||
|
||||
if (!hasEntries) {
|
||||
<div className="empty-state">
|
||||
No documents to show here yet. Drop files to make this space come alive.
|
||||
</div>
|
||||
return (
|
||||
<div className="empty-state">
|
||||
No documents to show here yet. Drop files to make this space come alive.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const listProps: DocumentsListProps = {
|
||||
entries,
|
||||
draggingDocumentIdsSet: draggingSet,
|
||||
draggedFolderId,
|
||||
onFolderClick: handleFolderClick,
|
||||
onFolderSelect,
|
||||
onFolderDragOver,
|
||||
onFolderDragLeave,
|
||||
onFolderDrop,
|
||||
onFolderDragStart,
|
||||
onFolderDragEnd,
|
||||
onDocumentClick: handleDocumentClick,
|
||||
onDocumentActivate: handleDocumentActivate,
|
||||
onDocumentDragStart: handleDocumentDragStartLocal,
|
||||
onDocumentDragEnd: handleDocumentDragEndLocal,
|
||||
onDocumentTagDragOver: handleDocumentTagDragOver,
|
||||
onDocumentTagDragLeave: handleDocumentTagDragLeave,
|
||||
onDocumentTagDrop: handleDocumentTagDrop,
|
||||
onDocumentRename,
|
||||
onFolderRename,
|
||||
ensureAssetUrl,
|
||||
getDocumentAsset,
|
||||
tagLookupById,
|
||||
onTagClick: toggleTagFilter,
|
||||
onCorrespondentClick: toggleCorrespondentFilter,
|
||||
activeCorrespondentIdSet: activeCorrespondentIdSet,
|
||||
scrollRef,
|
||||
focusedRowKey,
|
||||
gridIconSize,
|
||||
};
|
||||
|
||||
switch (viewMode) {
|
||||
case 'desk':
|
||||
return <DesktopWorkspace {...deskWorkspaceProps} />;
|
||||
case 'grid':
|
||||
return <DocumentsGrid {...listProps} />;
|
||||
return <DocumentsGrid {...listProps} gridIconSize={gridIconSize} />;
|
||||
case 'list':
|
||||
default:
|
||||
return <DocumentsList {...listProps} />;
|
||||
|
||||
@@ -50,7 +50,6 @@ import useDocumentMutations from './useDocumentMutations';
|
||||
import useDetailWorkspace from '../../detail/useDetailWorkspace';
|
||||
import useWorkspaceTaxonomies from './useWorkspaceTaxonomies';
|
||||
import useWorkspaceBreadcrumbs from './useWorkspaceBreadcrumbs';
|
||||
import useWorkspaceDeskProps from './useWorkspaceDeskProps';
|
||||
import useWorkspaceSelectionSync from './useWorkspaceSelectionSync';
|
||||
import type { DocumentId, FolderId as FolderIdentifier, Identifier } from '../../types/identifiers';
|
||||
|
||||
@@ -351,7 +350,6 @@ const useDocumentsWorkspace = ({
|
||||
searchResultIds,
|
||||
setSearchResultIds,
|
||||
searchLoading,
|
||||
activeTagFilters,
|
||||
setActiveTagFilters,
|
||||
activeCorrespondentFilters,
|
||||
setActiveCorrespondentFilters,
|
||||
@@ -807,7 +805,6 @@ const useDocumentsWorkspace = ({
|
||||
});
|
||||
|
||||
const {
|
||||
promoteSelectionOrder,
|
||||
clearDocumentSelection,
|
||||
} = useDocumentsSelection({
|
||||
showingSearchResults,
|
||||
@@ -1157,22 +1154,6 @@ const useDocumentsWorkspace = ({
|
||||
tagLookupById,
|
||||
});
|
||||
|
||||
const inspectDocumentForDesk = useCallback(
|
||||
(docOrId?: DocumentLike | Identifier | null) => {
|
||||
if (docOrId == null) {
|
||||
return;
|
||||
}
|
||||
const docId: Identifier | null = Object(docOrId) === docOrId
|
||||
? (docOrId as DocumentLike)?.id ?? null
|
||||
: (docOrId as Identifier | null);
|
||||
if (docId == null) {
|
||||
return;
|
||||
}
|
||||
inspectDocument(docId);
|
||||
},
|
||||
[inspectDocument],
|
||||
);
|
||||
|
||||
const handleEntryPointerCore = useEntryPointerCore({
|
||||
onSelectEntry: (entry, event, { rowKey, modifierClick, primaryClick }) => {
|
||||
const { type, id } = entry;
|
||||
@@ -1211,28 +1192,6 @@ const useDocumentsWorkspace = ({
|
||||
tenantIdRef,
|
||||
});
|
||||
|
||||
|
||||
const deskWorkspaceProps = useWorkspaceDeskProps({
|
||||
viewDocuments,
|
||||
inspectDocumentForDesk,
|
||||
handleEntryPointer: handleEntryPointerCore,
|
||||
selectedEntries,
|
||||
selectionAnchorRef,
|
||||
applySelection,
|
||||
showingSearchResults,
|
||||
searchQuery,
|
||||
activeTagFilters,
|
||||
activeCorrespondentFilters,
|
||||
selectedFolder,
|
||||
promoteSelectionOrder,
|
||||
handleDocumentTagDrop,
|
||||
ensureAssetUrl,
|
||||
getDocumentAsset,
|
||||
currentTenantId,
|
||||
documentLinks,
|
||||
ensureDownloadUrl,
|
||||
});
|
||||
|
||||
const documentsPanelProps = useDocumentsPanelProps({
|
||||
currentFolderName,
|
||||
breadcrumbs,
|
||||
@@ -1281,13 +1240,11 @@ const useDocumentsWorkspace = ({
|
||||
ensureDownloadUrl,
|
||||
selectionValue: selection,
|
||||
});
|
||||
|
||||
const documentsTableProps = useMemo(
|
||||
() => ({
|
||||
...documentsPanelProps,
|
||||
deskWorkspaceProps,
|
||||
}),
|
||||
[documentsPanelProps, deskWorkspaceProps],
|
||||
[documentsPanelProps],
|
||||
);
|
||||
|
||||
const sidebarProps = useSidebarProps({
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import type { MutableRefObject } from 'react';
|
||||
import { createDocumentEntryKey } from '../../app/entryKey';
|
||||
import type { Identifier } from '../../types/identifiers';
|
||||
|
||||
interface ApplySelectionFn {
|
||||
(keys: string[], options?: { anchor: string | null; interactedKeys?: string[] }): unknown;
|
||||
}
|
||||
|
||||
interface UseWorkspaceDeskPropsArgs {
|
||||
viewDocuments: unknown[];
|
||||
inspectDocumentForDesk?: (id: Identifier | null) => void;
|
||||
handleEntryPointer: (params: { rowKey?: string | null; id?: Identifier | null; type?: string; event?: any }) => void;
|
||||
selectedEntries: string[];
|
||||
selectionAnchorRef: MutableRefObject<Identifier | string | null>;
|
||||
applySelection: ApplySelectionFn;
|
||||
showingSearchResults: boolean;
|
||||
searchQuery: string;
|
||||
activeTagFilters: Array<string>;
|
||||
activeCorrespondentFilters: Array<string>;
|
||||
selectedFolder: Identifier | 'root' | null;
|
||||
promoteSelectionOrder: () => void;
|
||||
handleDocumentTagDrop: (docId: Identifier, tagId: Identifier) => Promise<void> | void;
|
||||
ensureAssetUrl: (docId: Identifier, asset: any, options?: Record<string, unknown>) => Promise<any> | null;
|
||||
getDocumentAsset: (doc: any, type: string) => any;
|
||||
currentTenantId: Identifier | null;
|
||||
documentLinks: Map<Identifier, unknown> | null;
|
||||
ensureDownloadUrl?: (docId: Identifier, options?: { force?: boolean }) => Promise<unknown>;
|
||||
}
|
||||
|
||||
const useWorkspaceDeskProps = ({
|
||||
viewDocuments,
|
||||
inspectDocumentForDesk,
|
||||
handleEntryPointer,
|
||||
selectedEntries,
|
||||
selectionAnchorRef,
|
||||
applySelection,
|
||||
showingSearchResults,
|
||||
searchQuery,
|
||||
activeTagFilters,
|
||||
activeCorrespondentFilters,
|
||||
selectedFolder,
|
||||
promoteSelectionOrder,
|
||||
handleDocumentTagDrop,
|
||||
ensureAssetUrl,
|
||||
getDocumentAsset,
|
||||
currentTenantId,
|
||||
documentLinks,
|
||||
ensureDownloadUrl,
|
||||
}: UseWorkspaceDeskPropsArgs) => {
|
||||
const handleDeskDocumentStackSelect = useCallback(
|
||||
(docIds: Array<Identifier | string>) => {
|
||||
if (!Array.isArray(docIds) || docIds.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rowKeys = docIds
|
||||
.map((id) => createDocumentEntryKey(id as Identifier))
|
||||
.filter((value): value is string => typeof value === 'string');
|
||||
|
||||
if (!rowKeys.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextKeys = [...selectedEntries];
|
||||
rowKeys.forEach((key) => {
|
||||
if (!nextKeys.includes(key)) {
|
||||
nextKeys.push(key);
|
||||
}
|
||||
});
|
||||
|
||||
const anchor = (rowKeys[0]
|
||||
|| selectionAnchorRef.current
|
||||
|| nextKeys[nextKeys.length - 1]) as string | null;
|
||||
|
||||
applySelection(nextKeys, {
|
||||
anchor,
|
||||
interactedKeys: rowKeys,
|
||||
});
|
||||
},
|
||||
[applySelection, selectedEntries, selectionAnchorRef],
|
||||
);
|
||||
|
||||
const deskViewId = useMemo(() => {
|
||||
if (showingSearchResults) {
|
||||
const trimmedQuery = searchQuery.trim();
|
||||
const tagsKey = [...activeTagFilters].sort().join(',');
|
||||
const correspondentsKey = [...activeCorrespondentFilters].sort().join(',');
|
||||
return `search:${trimmedQuery}|tags:${tagsKey}|corr:${correspondentsKey}`;
|
||||
}
|
||||
|
||||
const folderKey = selectedFolder && selectedFolder !== '' ? selectedFolder : 'root';
|
||||
return `folder:${folderKey}`;
|
||||
}, [
|
||||
showingSearchResults,
|
||||
searchQuery,
|
||||
activeTagFilters,
|
||||
activeCorrespondentFilters,
|
||||
selectedFolder,
|
||||
]);
|
||||
|
||||
const deskWorkspaceProps = useMemo(
|
||||
() => ({
|
||||
entries: viewDocuments,
|
||||
onDocumentActivate: inspectDocumentForDesk,
|
||||
onDocumentClick: handleEntryPointer,
|
||||
onDocumentStackSelect: handleDeskDocumentStackSelect,
|
||||
onPromoteSelection: promoteSelectionOrder,
|
||||
onDocumentTagDrop: handleDocumentTagDrop,
|
||||
ensureAssetUrl,
|
||||
getDocumentAsset,
|
||||
activeTagFilters,
|
||||
tenantId: currentTenantId,
|
||||
viewId: deskViewId,
|
||||
documentLinks,
|
||||
ensureDownloadUrl,
|
||||
}),
|
||||
[
|
||||
viewDocuments,
|
||||
inspectDocumentForDesk,
|
||||
handleEntryPointer,
|
||||
handleDeskDocumentStackSelect,
|
||||
promoteSelectionOrder,
|
||||
handleDocumentTagDrop,
|
||||
ensureAssetUrl,
|
||||
getDocumentAsset,
|
||||
activeTagFilters,
|
||||
currentTenantId,
|
||||
deskViewId,
|
||||
documentLinks,
|
||||
ensureDownloadUrl,
|
||||
],
|
||||
);
|
||||
|
||||
return deskWorkspaceProps;
|
||||
};
|
||||
|
||||
export default useWorkspaceDeskProps;
|
||||
Reference in New Issue
Block a user