This commit is contained in:
2025-11-18 00:41:49 +01:00
parent bc9be96123
commit 0b0a1a88fd
11 changed files with 253 additions and 702 deletions
-22
View File
@@ -130,8 +130,6 @@ interface DesktopWorkspaceProps {
activeTagIds?: Array<Identifier | null>;
selectedDocumentIds?: Identifier[];
onClearSelection?: () => void;
detailPanelOpen?: boolean;
onCloseDetailPanel?: () => void;
tenantId?: Identifier | null;
viewId?: string | null;
}
@@ -175,8 +173,6 @@ interface DesktopWorkspaceViewProps {
onPromoteSelection?: DesktopWorkspaceProps['onPromoteSelection'];
selectedDocumentIds: Identifier[];
onClearSelection?: DesktopWorkspaceProps['onClearSelection'];
detailPanelOpen: boolean;
onCloseDetailPanel?: DesktopWorkspaceProps['onCloseDetailPanel'];
documentLookup: Map<string, DeskDocument>;
resolveBaseMetrics: (doc: DeskDocument | null, cardWidth: number, cardHeight: number) => {
baseWidth: number;
@@ -210,8 +206,6 @@ const DesktopWorkspace: React.FC<DesktopWorkspaceProps> = ({
activeTagIds = [],
selectedDocumentIds = [],
onClearSelection = null,
detailPanelOpen = false,
onCloseDetailPanel = null,
tenantId = null,
viewId = 'default',
previewEntries,
@@ -788,8 +782,6 @@ const DesktopWorkspace: React.FC<DesktopWorkspaceProps> = ({
onPromoteSelection,
selectedDocumentIds,
onClearSelection,
detailPanelOpen,
onCloseDetailPanel,
documentLookup,
resolveBaseMetrics,
bringToFront,
@@ -831,7 +823,6 @@ const DesktopWorkspace: React.FC<DesktopWorkspaceProps> = ({
layoutRef,
layoutSnapshot,
onClearSelection,
onCloseDetailPanel,
onDocumentStackSelect,
onEntryPointer,
onPromoteSelection,
@@ -847,7 +838,6 @@ const DesktopWorkspace: React.FC<DesktopWorkspaceProps> = ({
resolveBaseMetrics,
setDraggingId,
selectedDocumentIds,
detailPanelOpen,
onInspectDocument,
markLayoutDirty,
tagDropTargetId,
@@ -895,8 +885,6 @@ function DesktopWorkspaceView({
onPromoteSelection,
selectedDocumentIds,
onClearSelection,
detailPanelOpen,
onCloseDetailPanel,
documentLookup,
resolveBaseMetrics,
bringToFront,
@@ -951,8 +939,6 @@ function DesktopWorkspaceView({
onPromoteSelection,
onInspectDocument,
selectedDocumentIds,
detailPanelOpen,
onCloseDetailPanel,
openOverlayForDoc,
}) as {
getCardPointerHandlers: (doc: DeskDocument) => React.HTMLAttributes<HTMLDivElement>;
@@ -970,14 +956,6 @@ function DesktopWorkspaceView({
}
}, [focusShell, selectedDocumentIds.length]);
useEffect(() => {
if (!detailPanelOpen) {
focusShell();
}
}, [detailPanelOpen, focusShell]);
const allSizesReady = items.every((doc) => Boolean(ensureDocumentSize(doc)));
return (
@@ -1,124 +0,0 @@
import React, { ReactNode } from 'react';
import { SelectionFloatingPanel } from '../documents/SelectionFloatingActions';
import { createDocumentsTableHeaderActions } from '../documents/DocumentsPanel';
import createWorkspaceSurfaceConfig from '../documents/workspaceHeader';
import DocumentViewerPanel from '../preview/DocumentViewerPanel';
import DesktopWorkspace from './DesktopWorkspace';
type WorkspaceProps = Record<string, any>;
interface DetailProps extends Record<string, any> {
onClose?: () => void;
onOpenPreview?: () => void;
tags?: unknown;
}
interface CreateDesktopSurfaceArgs {
workspaceProps?: WorkspaceProps | null;
renderSidebarToggle?: () => ReactNode;
detailProps?: DetailProps | null;
detailOpen?: boolean;
}
const createDesktopSurface = ({
workspaceProps,
renderSidebarToggle,
detailProps = null,
detailOpen = false,
}: CreateDesktopSurfaceArgs) => {
if (!workspaceProps) {
return null;
}
const {
currentFolderName,
searchResults,
onRefresh,
viewMode,
onViewModeChange,
onDeleteSelection,
tags,
correspondents,
documentLookup,
tagLookupById,
onBulkTagAdd,
onBulkTagRemove,
onBulkCorrespondentAdd,
onBulkCorrespondentRemove,
onBulkReanalyze,
folderOptions,
onMoveDocumentsToFolder,
searchIncludeDescendants,
onToggleSearchIncludeDescendants,
} = workspaceProps;
const title = Array.isArray(searchResults) ? 'Search results' : currentFolderName;
const subtitle = Array.isArray(searchResults)
? `${searchResults.length} matching document${searchResults.length === 1 ? '' : 's'}`
: null;
const actions = createDocumentsTableHeaderActions({
viewMode: viewMode || 'desk',
onViewModeChange,
onRefresh,
includeDescendants: searchIncludeDescendants,
onToggleIncludeDescendants: onToggleSearchIncludeDescendants,
});
const floatingActions = (
<SelectionFloatingPanel
documentLookup={documentLookup}
tags={tags}
tagLookupById={tagLookupById}
correspondents={correspondents}
onBulkTagAdd={onBulkTagAdd}
onBulkTagRemove={onBulkTagRemove}
onBulkCorrespondentAdd={onBulkCorrespondentAdd}
onBulkCorrespondentRemove={onBulkCorrespondentRemove}
onBulkReanalyze={onBulkReanalyze}
onDeleteSelection={onDeleteSelection}
folderOptions={folderOptions}
onMoveDocumentsToFolder={onMoveDocumentsToFolder}
/>
);
const sidebarToggle = renderSidebarToggle ? renderSidebarToggle() : null;
const detail = detailOpen && detailProps
? (() => {
const { onClose, onOpenPreview, tags: tagOptions, ...restDetailProps } = detailProps;
return (
<DocumentViewerPanel
variant="sidebar"
onCollapsePanel={onClose}
onMaximizePanel={onOpenPreview}
tagOptions={tagOptions}
{...restDetailProps}
/>
);
})()
: null;
const surfaceConfig = createWorkspaceSurfaceConfig({
key: 'workspace',
variant: 'workspace',
title,
subtitle,
sidebarToggle,
actions,
breadcrumbs: workspaceProps?.breadcrumbs || null,
selectionLabel: null,
floatingActions,
content: (
<DesktopWorkspace
{...workspaceProps}
/>
),
detail,
});
return {
...surfaceConfig,
supportsDetail: Boolean(detailProps),
};
};
export default createDesktopSurface;
@@ -37,8 +37,6 @@ export const useDeskPointer = ({
onPromoteSelection,
onInspectDocument,
selectedDocumentIds,
detailPanelOpen,
onCloseDetailPanel,
openOverlayForDoc = null,
}) => {
const pointerIntentRef = useRef(null);
@@ -404,12 +402,8 @@ export const useDeskPointer = ({
return;
}
if (detailPanelOpen) {
event.preventDefault();
safeInvoke(onCloseDetailPanel);
}
},
[detailPanelOpen, onCloseDetailPanel, openOverlayForDoc, selectedDocumentIds],
[openOverlayForDoc, selectedDocumentIds],
);
return {
@@ -1,255 +0,0 @@
import { useCallback, useMemo } from 'react';
type Identifier = string | number;
type DocumentEntry = { id?: Identifier } & Record<string, unknown>;
type InspectTarget = DocumentEntry | Identifier | null;
type WorkspaceViewMode = 'desk' | 'grid' | 'list' | string;
type DeskDocumentStackSelectHandler = (docIds: Identifier[]) => void;
type ResolveRowKey = (id: Identifier) => Identifier | string | null;
type ApplySelection = (
keys: Array<Identifier | string>,
options: { anchor?: Identifier | string | null; interactedKeys?: Array<Identifier | string> },
) => void;
interface UseDeskWorkspacePropsArgs {
documents?: DocumentEntry[];
searchResults?: DocumentEntry[];
breadcrumbs?: unknown[];
currentFolderName?: string | null;
documentsViewMode?: WorkspaceViewMode;
handleDocumentsViewModeChange?: (mode: WorkspaceViewMode) => void;
handleDeskExit?: () => void;
refreshCurrentFolder?: () => Promise<void> | void;
inspectDocument?: (doc: InspectTarget) => void;
handleEntryPointerCore?: (...args: unknown[]) => void;
promoteSelectionOrder?: (...args: unknown[]) => void;
currentTenantId?: Identifier | null;
selectedDocumentIds?: Identifier[];
selectedFolderIds?: Identifier[];
clearDocumentSelection?: () => void;
detailPanelOpen?: boolean;
handleDetailPanelClose?: () => void;
resolveThumbnailUrlForDoc?: (doc: DocumentEntry) => string | null;
handleDocumentTagDrop?: (...args: unknown[]) => void;
ensureAssetUrl?: (...args: unknown[]) => void;
getDocumentAsset?: (...args: unknown[]) => unknown;
activeTagFilters?: Identifier[];
handleDeleteSelection?: () => void;
tags?: unknown[];
correspondents?: unknown[];
documentLookup?: unknown;
tagLookupById?: unknown;
handleBulkTagAddFromDetail?: (...args: unknown[]) => void;
handleBulkTagRemoveFromDetail?: (...args: unknown[]) => void;
handleBulkCorrespondentAdd?: (...args: unknown[]) => void;
handleBulkCorrespondentRemove?: (...args: unknown[]) => void;
handleBulkSelectionReanalyze?: (...args: unknown[]) => void;
folderOptions?: unknown[];
moveDocumentsToFolder?: (...args: unknown[]) => void;
searchIncludeDescendants?: boolean;
toggleSearchIncludeDescendants?: () => void;
selectedEntries?: Array<Identifier | string>;
selectionAnchorRef: { current: Identifier | string | null };
applySelection: ApplySelection;
resolveDocumentRowKey: ResolveRowKey;
showingSearchResults?: boolean;
searchQuery?: string;
activeCorrespondentFilters?: Identifier[];
selectedFolder?: Identifier | string | null;
previewEntries?: Map<Identifier, { url?: string | null; contentType?: string | null }>;
ensureDownloadUrl?: (documentId: Identifier, options?: { force?: boolean }) => Promise<{ url?: string | null; contentType?: string | null } | null>;
}
const useDeskWorkspaceProps = ({
documents,
searchResults,
breadcrumbs,
currentFolderName,
documentsViewMode = 'desk',
handleDocumentsViewModeChange,
handleDeskExit,
refreshCurrentFolder,
inspectDocument,
handleEntryPointerCore,
promoteSelectionOrder,
currentTenantId,
selectedDocumentIds,
selectedFolderIds,
clearDocumentSelection,
detailPanelOpen,
handleDetailPanelClose,
resolveThumbnailUrlForDoc,
handleDocumentTagDrop,
ensureAssetUrl,
getDocumentAsset,
activeTagFilters = [],
handleDeleteSelection,
tags,
correspondents,
documentLookup,
tagLookupById,
handleBulkTagAddFromDetail,
handleBulkTagRemoveFromDetail,
handleBulkCorrespondentAdd,
handleBulkCorrespondentRemove,
handleBulkSelectionReanalyze,
folderOptions,
moveDocumentsToFolder,
searchIncludeDescendants,
toggleSearchIncludeDescendants,
selectedEntries = [],
selectionAnchorRef,
applySelection,
resolveDocumentRowKey,
showingSearchResults = false,
searchQuery = '',
activeCorrespondentFilters = [],
selectedFolder,
previewEntries,
ensureDownloadUrl,
}: UseDeskWorkspacePropsArgs) => {
const handleDeskDocumentStackSelect: DeskDocumentStackSelectHandler = useCallback(
(docIds) => {
if (!Array.isArray(docIds) || docIds.length === 0) {
return;
}
const rowKeys = docIds
.map((id) => resolveDocumentRowKey(id))
.filter((value): value is Identifier | string => Boolean(value));
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 Identifier | string | null;
applySelection(nextKeys, {
anchor,
interactedKeys: rowKeys,
});
},
[applySelection, resolveDocumentRowKey, 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,
]);
return useMemo(
() => ({
documents,
searchResults,
breadcrumbs,
currentFolderName,
viewMode: documentsViewMode,
onViewModeChange: handleDocumentsViewModeChange,
onExit: handleDeskExit,
onRefresh: refreshCurrentFolder,
onInspectDocument: inspectDocument,
onEntryPointer: handleEntryPointerCore,
onDocumentStackSelect: handleDeskDocumentStackSelect,
onPromoteSelection: promoteSelectionOrder,
tenantId: currentTenantId,
viewId: deskViewId,
selectedDocumentIds,
selectedFolderIds,
onClearSelection: clearDocumentSelection,
detailPanelOpen,
onCloseDetailPanel: handleDetailPanelClose,
resolveThumbnailUrl: resolveThumbnailUrlForDoc,
onAssignTagToDocument: handleDocumentTagDrop,
ensureAssetUrl,
getDocumentAsset,
activeTagIds: activeTagFilters,
onDeleteSelection: handleDeleteSelection,
tags,
correspondents,
documentLookup,
tagLookupById,
onBulkTagAdd: handleBulkTagAddFromDetail,
onBulkTagRemove: handleBulkTagRemoveFromDetail,
onBulkCorrespondentAdd: handleBulkCorrespondentAdd,
onBulkCorrespondentRemove: handleBulkCorrespondentRemove,
onBulkReanalyze: handleBulkSelectionReanalyze,
folderOptions,
onMoveDocumentsToFolder: moveDocumentsToFolder,
searchIncludeDescendants,
onToggleSearchIncludeDescendants: toggleSearchIncludeDescendants,
previewEntries,
ensureDownloadUrl,
}),
[
documents,
searchResults,
breadcrumbs,
currentFolderName,
documentsViewMode,
handleDocumentsViewModeChange,
handleDeskExit,
refreshCurrentFolder,
inspectDocument,
handleEntryPointerCore,
handleDeskDocumentStackSelect,
promoteSelectionOrder,
currentTenantId,
deskViewId,
selectedDocumentIds,
selectedFolderIds,
clearDocumentSelection,
detailPanelOpen,
handleDetailPanelClose,
resolveThumbnailUrlForDoc,
handleDocumentTagDrop,
ensureAssetUrl,
getDocumentAsset,
activeTagFilters,
handleDeleteSelection,
tags,
correspondents,
documentLookup,
tagLookupById,
handleBulkTagAddFromDetail,
handleBulkTagRemoveFromDetail,
handleBulkCorrespondentAdd,
handleBulkCorrespondentRemove,
handleBulkSelectionReanalyze,
folderOptions,
moveDocumentsToFolder,
searchIncludeDescendants,
toggleSearchIncludeDescendants,
previewEntries,
ensureDownloadUrl,
],
);
};
export default useDeskWorkspaceProps;