feat: refactor frontend document sorting preferences and sidebar utilities.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import React, { useCallback, useEffect } from 'react';
|
import React, { useCallback, useEffect } from 'react';
|
||||||
import type { ReactNode, ComponentProps } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
DocumentsFilterProvider,
|
DocumentsFilterProvider,
|
||||||
@@ -15,8 +15,7 @@ import useDocumentsShell from './useDocumentsShell';
|
|||||||
const DocumentsInner: React.FC<{
|
const DocumentsInner: React.FC<{
|
||||||
surfaceConfig: any;
|
surfaceConfig: any;
|
||||||
onNavigate: (documentId: string) => void;
|
onNavigate: (documentId: string) => void;
|
||||||
sidebarProps: ComponentProps<typeof Sidebar> | null;
|
}> = ({ surfaceConfig, onNavigate }) => {
|
||||||
}> = ({ surfaceConfig, onNavigate, sidebarProps }) => {
|
|
||||||
const { openPreview } = usePreviewContext();
|
const { openPreview } = usePreviewContext();
|
||||||
const { collapsed: sidebarCollapsed } = useSidebarContext();
|
const { collapsed: sidebarCollapsed } = useSidebarContext();
|
||||||
const {
|
const {
|
||||||
@@ -57,7 +56,7 @@ const DocumentsInner: React.FC<{
|
|||||||
const renderSurface = () => {
|
const renderSurface = () => {
|
||||||
const detailMode = surface?.detailMode ?? null;
|
const detailMode = surface?.detailMode ?? null;
|
||||||
const layoutClass = `documents-main${sidebarHidden ? ' documents-main--sidebar-hidden' : ''}${detailMode === 'overlay' ? ' documents-main--overlay-detail' : ''}`;
|
const layoutClass = `documents-main${sidebarHidden ? ' documents-main--sidebar-hidden' : ''}${detailMode === 'overlay' ? ' documents-main--overlay-detail' : ''}`;
|
||||||
const sidebarNode = !sidebarHidden && sidebarProps ? <Sidebar {...sidebarProps} /> : null;
|
const sidebarNode = !sidebarHidden ? <Sidebar /> : null;
|
||||||
const surfaceDetail = surface && (surface as { detail?: ReactNode }).detail ? (surface as { detail?: ReactNode }).detail : null;
|
const surfaceDetail = surface && (surface as { detail?: ReactNode }).detail ? (surface as { detail?: ReactNode }).detail : null;
|
||||||
const surfaceBody = surface ? surface.content : null;
|
const surfaceBody = surface ? surface.content : null;
|
||||||
|
|
||||||
@@ -85,7 +84,6 @@ const DocumentsInner: React.FC<{
|
|||||||
|
|
||||||
const DocumentsRouteContent: React.FC = () => {
|
const DocumentsRouteContent: React.FC = () => {
|
||||||
const {
|
const {
|
||||||
sidebarProps,
|
|
||||||
surfaceConfig,
|
surfaceConfig,
|
||||||
documentsFilter,
|
documentsFilter,
|
||||||
} = useDocumentsShell();
|
} = useDocumentsShell();
|
||||||
@@ -103,7 +101,6 @@ const DocumentsRouteContent: React.FC = () => {
|
|||||||
<DocumentsInner
|
<DocumentsInner
|
||||||
surfaceConfig={surfaceConfig}
|
surfaceConfig={surfaceConfig}
|
||||||
onNavigate={handleDocumentNavigate}
|
onNavigate={handleDocumentNavigate}
|
||||||
sidebarProps={sidebarProps}
|
|
||||||
/>
|
/>
|
||||||
</PreviewProvider>
|
</PreviewProvider>
|
||||||
</DocumentsFilterProvider>
|
</DocumentsFilterProvider>
|
||||||
|
|||||||
@@ -60,9 +60,7 @@ export const useDocumentsPreferences = () => {
|
|||||||
const stored = readSessionStorage(SORT_FIELD_STORAGE_KEY);
|
const stored = readSessionStorage(SORT_FIELD_STORAGE_KEY);
|
||||||
return SORT_FIELD_VALUES.includes(stored) ? stored : DEFAULT_SORT_FIELD;
|
return SORT_FIELD_VALUES.includes(stored) ? stored : DEFAULT_SORT_FIELD;
|
||||||
});
|
});
|
||||||
const documentsSortFieldRef = useRef(documentsSortField);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
documentsSortFieldRef.current = documentsSortField;
|
|
||||||
writeSessionStorage(SORT_FIELD_STORAGE_KEY, documentsSortField);
|
writeSessionStorage(SORT_FIELD_STORAGE_KEY, documentsSortField);
|
||||||
}, [documentsSortField]);
|
}, [documentsSortField]);
|
||||||
|
|
||||||
@@ -70,9 +68,8 @@ export const useDocumentsPreferences = () => {
|
|||||||
const stored = readSessionStorage(SORT_DIRECTION_STORAGE_KEY);
|
const stored = readSessionStorage(SORT_DIRECTION_STORAGE_KEY);
|
||||||
return stored === 'desc' || stored === 'asc' ? stored : DEFAULT_SORT_DIRECTION;
|
return stored === 'desc' || stored === 'asc' ? stored : DEFAULT_SORT_DIRECTION;
|
||||||
});
|
});
|
||||||
const documentsSortDirectionRef = useRef(documentsSortDirection);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
documentsSortDirectionRef.current = documentsSortDirection;
|
|
||||||
writeSessionStorage(SORT_DIRECTION_STORAGE_KEY, documentsSortDirection);
|
writeSessionStorage(SORT_DIRECTION_STORAGE_KEY, documentsSortDirection);
|
||||||
}, [documentsSortDirection]);
|
}, [documentsSortDirection]);
|
||||||
|
|
||||||
@@ -102,21 +99,16 @@ export const useDocumentsPreferences = () => {
|
|||||||
setSearchIncludeDescendants((previous) => !previous);
|
setSearchIncludeDescendants((previous) => !previous);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const sortRefreshReadyRef = useRef(false);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
documentsViewMode,
|
documentsViewMode,
|
||||||
handleDocumentsViewModeChange: setDocumentsViewMode,
|
handleDocumentsViewModeChange: setDocumentsViewMode,
|
||||||
handleDeskExit,
|
handleDeskExit,
|
||||||
documentsSortField,
|
documentsSortField,
|
||||||
documentsSortDirection,
|
documentsSortDirection,
|
||||||
documentsSortFieldRef,
|
|
||||||
documentsSortDirectionRef,
|
|
||||||
handleDocumentsSortFieldChange,
|
handleDocumentsSortFieldChange,
|
||||||
handleDocumentsSortDirectionToggle,
|
handleDocumentsSortDirectionToggle,
|
||||||
searchIncludeDescendants,
|
searchIncludeDescendants,
|
||||||
setSearchIncludeDescendants,
|
setSearchIncludeDescendants,
|
||||||
toggleSearchIncludeDescendants,
|
toggleSearchIncludeDescendants,
|
||||||
sortRefreshReadyRef,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import type { ComponentProps } from 'react';
|
|
||||||
import { useAppShell } from '../lib/context/AppShellContext';
|
import { useAppShell } from '../lib/context/AppShellContext';
|
||||||
import type { DocumentsFilterValue } from '../documents/context/DocumentsFilterContext';
|
import type { DocumentsFilterValue } from '../documents/context/DocumentsFilterContext';
|
||||||
import type Sidebar from '../sidebar/Sidebar';
|
|
||||||
import type { UseWorkspaceSurfaceArgs } from './useWorkspaceSurface';
|
import type { UseWorkspaceSurfaceArgs } from './useWorkspaceSurface';
|
||||||
import type { Identifier } from '../types/identifiers';
|
import type { Identifier } from '../types/identifiers';
|
||||||
|
|
||||||
|
import useDocumentsPanelProps from '../documents/logic/useDocumentsPanelProps';
|
||||||
|
|
||||||
type WorkspaceSurfaceConfig = Omit<UseWorkspaceSurfaceArgs, 'sidebarHidden' | 'onExpandSidebar'> & {
|
type WorkspaceSurfaceConfig = Omit<UseWorkspaceSurfaceArgs, 'sidebarHidden' | 'onExpandSidebar'> & {
|
||||||
openDetailPanel?: (documentId: Identifier) => void;
|
openDetailPanel?: (documentId: Identifier) => void;
|
||||||
closeDetailPanel?: () => void;
|
closeDetailPanel?: () => void;
|
||||||
@@ -13,20 +13,19 @@ type WorkspaceSurfaceConfig = Omit<UseWorkspaceSurfaceArgs, 'sidebarHidden' | 'o
|
|||||||
};
|
};
|
||||||
|
|
||||||
interface DocumentsShellView {
|
interface DocumentsShellView {
|
||||||
sidebarProps: ComponentProps<typeof Sidebar> | null;
|
|
||||||
surfaceConfig: WorkspaceSurfaceConfig;
|
surfaceConfig: WorkspaceSurfaceConfig;
|
||||||
documentsFilter: DocumentsFilterValue;
|
documentsFilter: DocumentsFilterValue;
|
||||||
documentsManager: any;
|
documentsManager: any;
|
||||||
foldersManager: any; // Using any to avoid circular dependency
|
foldersManager: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useDocumentsShell = (): DocumentsShellView => {
|
const useDocumentsShell = (): DocumentsShellView => {
|
||||||
const shell = useAppShell();
|
const shell = useAppShell();
|
||||||
|
const documentsPanelProps = useDocumentsPanelProps(shell as any);
|
||||||
|
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
const sidebar = (shell.sidebarProps as ComponentProps<typeof Sidebar> | undefined) || null;
|
|
||||||
const surfaceConfig: WorkspaceSurfaceConfig = {
|
const surfaceConfig: WorkspaceSurfaceConfig = {
|
||||||
documentsTableProps: (shell.documentsTableProps ?? null) as WorkspaceSurfaceConfig['documentsTableProps'],
|
documentsTableProps: documentsPanelProps,
|
||||||
detailPanelProps: (shell.detailPanelProps ?? null) as WorkspaceSurfaceConfig['detailPanelProps'],
|
detailPanelProps: (shell.detailPanelProps ?? null) as WorkspaceSurfaceConfig['detailPanelProps'],
|
||||||
detailPanelOpen: Boolean(shell.detailPanelOpen),
|
detailPanelOpen: Boolean(shell.detailPanelOpen),
|
||||||
openDetailPanel: shell.openDetailPanel as WorkspaceSurfaceConfig['openDetailPanel'],
|
openDetailPanel: shell.openDetailPanel as WorkspaceSurfaceConfig['openDetailPanel'],
|
||||||
@@ -41,22 +40,13 @@ const useDocumentsShell = (): DocumentsShellView => {
|
|||||||
handleBreadcrumbNavigate: shell.handleBreadcrumbNavigate as WorkspaceSurfaceConfig['handleBreadcrumbNavigate'],
|
handleBreadcrumbNavigate: shell.handleBreadcrumbNavigate as WorkspaceSurfaceConfig['handleBreadcrumbNavigate'],
|
||||||
};
|
};
|
||||||
|
|
||||||
const sidebarWithActions = sidebar
|
|
||||||
? {
|
|
||||||
...sidebar,
|
|
||||||
onManageTags: shell.openTagsModal as (() => void) | undefined,
|
|
||||||
onManageCorrespondents: shell.openCorrespondentsModal as (() => void) | undefined,
|
|
||||||
}
|
|
||||||
: null;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sidebarProps: sidebarWithActions,
|
|
||||||
surfaceConfig,
|
surfaceConfig,
|
||||||
documentsFilter: shell.documentsFilter as DocumentsFilterValue,
|
documentsFilter: shell.documentsFilter as DocumentsFilterValue,
|
||||||
documentsManager: shell.documentsManager,
|
documentsManager: shell.documentsManager,
|
||||||
foldersManager: shell.foldersManager,
|
foldersManager: shell.foldersManager,
|
||||||
};
|
};
|
||||||
}, [shell]);
|
}, [shell, documentsPanelProps]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useDocumentsShell;
|
export default useDocumentsShell;
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
Dispatch,
|
|
||||||
SetStateAction,
|
|
||||||
useCallback,
|
useCallback,
|
||||||
useEffect,
|
useEffect,
|
||||||
useRef,
|
useRef,
|
||||||
@@ -10,18 +8,11 @@ import DocumentsManager from '../DocumentsManager';
|
|||||||
import type { DocumentId } from '../../types/identifiers';
|
import type { DocumentId } from '../../types/identifiers';
|
||||||
import type { Document } from '../../types/documents';
|
import type { Document } from '../../types/documents';
|
||||||
|
|
||||||
interface FolderContentsEntry {
|
|
||||||
documents?: Document[];
|
|
||||||
[key: string]: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface UseDocumentsOptions {
|
interface UseDocumentsOptions {
|
||||||
setFolderContents: Dispatch<SetStateAction<Map<string, FolderContentsEntry>>>;
|
|
||||||
fetchDocumentById?: (id: DocumentId) => Promise<Document | null>;
|
fetchDocumentById?: (id: DocumentId) => Promise<Document | null>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useDocuments = ({
|
const useDocuments = ({
|
||||||
setFolderContents,
|
|
||||||
fetchDocumentById,
|
fetchDocumentById,
|
||||||
}: UseDocumentsOptions) => {
|
}: UseDocumentsOptions) => {
|
||||||
const managerRef = useRef(
|
const managerRef = useRef(
|
||||||
@@ -75,46 +66,8 @@ const useDocuments = ({
|
|||||||
});
|
});
|
||||||
return changed ? next : prev;
|
return changed ? next : prev;
|
||||||
});
|
});
|
||||||
setFolderContents((prev) => {
|
|
||||||
if (!prev.size) {
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
let changed = false;
|
|
||||||
const next = new Map();
|
|
||||||
prev.forEach((contents, key) => {
|
|
||||||
const docs = Array.isArray(contents?.documents) ? contents.documents : null;
|
|
||||||
if (!docs || docs.length === 0) {
|
|
||||||
next.set(key, contents);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let docsChanged = false;
|
|
||||||
const updatedDocs = docs.map((doc) => {
|
|
||||||
const id = doc?.id;
|
|
||||||
if (id != null && lookupSnapshot.has(id as DocumentId)) {
|
|
||||||
const canonical = lookupSnapshot.get(id as DocumentId) as Document;
|
|
||||||
if (canonical !== doc) {
|
|
||||||
docsChanged = true;
|
|
||||||
}
|
|
||||||
return canonical;
|
|
||||||
}
|
|
||||||
const updated = mapper(doc);
|
|
||||||
const nextDoc = updated === undefined ? doc : updated;
|
|
||||||
if (nextDoc !== doc) {
|
|
||||||
docsChanged = true;
|
|
||||||
}
|
|
||||||
return nextDoc;
|
|
||||||
});
|
|
||||||
if (docsChanged) {
|
|
||||||
changed = true;
|
|
||||||
next.set(key, { ...contents, documents: updatedDocs });
|
|
||||||
} else {
|
|
||||||
next.set(key, contents);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return changed ? next : prev;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
[setFolderContents],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
const updateDocumentCaches = useCallback(
|
const updateDocumentCaches = useCallback(
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
MutableRefObject,
|
|
||||||
useCallback,
|
useCallback,
|
||||||
useEffect,
|
useEffect,
|
||||||
useMemo,
|
useMemo,
|
||||||
@@ -25,9 +24,7 @@ import { useEntryPointer as useEntryPointerCore } from '../features/selection/us
|
|||||||
import { isTagTransferEvent } from '../features/tagging/tagTransfer';
|
import { isTagTransferEvent } from '../features/tagging/tagTransfer';
|
||||||
import useDocumentsSelection from '../features/selection/useDocumentsSelection';
|
import useDocumentsSelection from '../features/selection/useDocumentsSelection';
|
||||||
import useBulkDocumentActions from './useBulkDocumentActions';
|
import useBulkDocumentActions from './useBulkDocumentActions';
|
||||||
import useDocumentsPanelProps from '../logic/useDocumentsPanelProps';
|
|
||||||
import useDocumentPreview from '../../app/useDocumentPreview';
|
import useDocumentPreview from '../../app/useDocumentPreview';
|
||||||
import useSidebarProps from '../../sidebar/useSidebarProps';
|
|
||||||
import {
|
import {
|
||||||
DEFAULT_SORT_DIRECTION,
|
DEFAULT_SORT_DIRECTION,
|
||||||
DEFAULT_SORT_FIELD,
|
DEFAULT_SORT_FIELD,
|
||||||
@@ -69,19 +66,8 @@ const EntryType = Object.freeze({
|
|||||||
|
|
||||||
const noop = () => { };
|
const noop = () => { };
|
||||||
|
|
||||||
|
|
||||||
import type { Document } from '../../types/documents';
|
import type { Document } from '../../types/documents';
|
||||||
|
|
||||||
interface FolderContentsEntry {
|
|
||||||
folder?: { id?: FolderNodeId; name?: string | null } | null;
|
|
||||||
documents?: Document[];
|
|
||||||
subfolders?: Array<{ id?: FolderNodeId; name?: string | null;[key: string]: unknown }>;
|
|
||||||
__includesDocuments?: boolean;
|
|
||||||
__sortField?: string | null;
|
|
||||||
__sortDirection?: string | null;
|
|
||||||
[key: string]: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TenantOption {
|
interface TenantOption {
|
||||||
id?: Identifier | null;
|
id?: Identifier | null;
|
||||||
name?: string | null;
|
name?: string | null;
|
||||||
@@ -93,8 +79,6 @@ interface UseDocumentsWorkspaceOptions {
|
|||||||
documentsViewMode?: string;
|
documentsViewMode?: string;
|
||||||
documentsSortField?: string;
|
documentsSortField?: string;
|
||||||
documentsSortDirection?: string;
|
documentsSortDirection?: string;
|
||||||
documentsSortFieldRef?: MutableRefObject<string>;
|
|
||||||
documentsSortDirectionRef?: MutableRefObject<string>;
|
|
||||||
onDocumentsViewModeChange?: (mode: string) => void;
|
onDocumentsViewModeChange?: (mode: string) => void;
|
||||||
onDocumentsSortFieldChange?: (field: string) => void;
|
onDocumentsSortFieldChange?: (field: string) => void;
|
||||||
onDocumentsSortDirectionToggle?: () => void;
|
onDocumentsSortDirectionToggle?: () => void;
|
||||||
@@ -106,8 +90,6 @@ const useDocumentsWorkspace = ({
|
|||||||
documentsViewMode = 'list',
|
documentsViewMode = 'list',
|
||||||
documentsSortField = DEFAULT_SORT_FIELD,
|
documentsSortField = DEFAULT_SORT_FIELD,
|
||||||
documentsSortDirection = DEFAULT_SORT_DIRECTION,
|
documentsSortDirection = DEFAULT_SORT_DIRECTION,
|
||||||
documentsSortFieldRef,
|
|
||||||
documentsSortDirectionRef,
|
|
||||||
onDocumentsViewModeChange,
|
onDocumentsViewModeChange,
|
||||||
onDocumentsSortFieldChange,
|
onDocumentsSortFieldChange,
|
||||||
onDocumentsSortDirectionToggle,
|
onDocumentsSortDirectionToggle,
|
||||||
@@ -119,17 +101,15 @@ const useDocumentsWorkspace = ({
|
|||||||
const handleDocumentsSortDirectionToggle = onDocumentsSortDirectionToggle || noop;
|
const handleDocumentsSortDirectionToggle = onDocumentsSortDirectionToggle || noop;
|
||||||
const setSearchIncludeDescendants = onSetSearchIncludeDescendants || noop;
|
const setSearchIncludeDescendants = onSetSearchIncludeDescendants || noop;
|
||||||
|
|
||||||
const fallbackSortFieldRef = useRef(documentsSortField);
|
const activeSortFieldRef = useRef(documentsSortField);
|
||||||
const activeSortFieldRef = documentsSortFieldRef || fallbackSortFieldRef;
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
activeSortFieldRef.current = documentsSortField;
|
activeSortFieldRef.current = documentsSortField;
|
||||||
}, [documentsSortField, activeSortFieldRef]);
|
}, [documentsSortField]);
|
||||||
|
|
||||||
const fallbackSortDirectionRef = useRef(documentsSortDirection);
|
const activeSortDirectionRef = useRef(documentsSortDirection);
|
||||||
const activeSortDirectionRef = documentsSortDirectionRef || fallbackSortDirectionRef;
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
activeSortDirectionRef.current = documentsSortDirection;
|
activeSortDirectionRef.current = documentsSortDirection;
|
||||||
}, [documentsSortDirection, activeSortDirectionRef]);
|
}, [documentsSortDirection]);
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
@@ -172,7 +152,7 @@ const useDocumentsWorkspace = ({
|
|||||||
},
|
},
|
||||||
[showToast],
|
[showToast],
|
||||||
);
|
);
|
||||||
const status = null; // No longer used, kept for backward compatibility
|
|
||||||
const handleApiReport = useCallback(
|
const handleApiReport = useCallback(
|
||||||
({ message, variant }) => setStatusMessage(message, variant),
|
({ message, variant }) => setStatusMessage(message, variant),
|
||||||
[setStatusMessage],
|
[setStatusMessage],
|
||||||
@@ -193,7 +173,7 @@ const useDocumentsWorkspace = ({
|
|||||||
setStatusMessage,
|
setStatusMessage,
|
||||||
});
|
});
|
||||||
|
|
||||||
const breadcrumbFetchRef = useRef(new Set());
|
|
||||||
const tagRemovalCursorActiveRef = useRef(false);
|
const tagRemovalCursorActiveRef = useRef(false);
|
||||||
const tenantIdRef = useRef(currentTenantId);
|
const tenantIdRef = useRef(currentTenantId);
|
||||||
const detailPanelControlRef = useRef({ open: () => { }, close: () => { } });
|
const detailPanelControlRef = useRef({ open: () => { }, close: () => { } });
|
||||||
@@ -282,14 +262,6 @@ const useDocumentsWorkspace = ({
|
|||||||
configureSelectionEnvironment,
|
configureSelectionEnvironment,
|
||||||
} = selection;
|
} = selection;
|
||||||
|
|
||||||
const [folderContents, setFolderContents] = useState<Map<FolderNodeId, FolderContentsEntry>>(
|
|
||||||
() => new Map(),
|
|
||||||
);
|
|
||||||
const folderContentsRef = useRef(folderContents);
|
|
||||||
useEffect(() => {
|
|
||||||
folderContentsRef.current = folderContents;
|
|
||||||
}, [folderContents]);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
documents,
|
documents,
|
||||||
setDocuments,
|
setDocuments,
|
||||||
@@ -298,7 +270,6 @@ const useDocumentsWorkspace = ({
|
|||||||
updateDocumentCaches,
|
updateDocumentCaches,
|
||||||
documentsManager,
|
documentsManager,
|
||||||
} = useDocuments({
|
} = useDocuments({
|
||||||
setFolderContents,
|
|
||||||
fetchDocumentById,
|
fetchDocumentById,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -328,7 +299,7 @@ const useDocumentsWorkspace = ({
|
|||||||
foldersManager,
|
foldersManager,
|
||||||
});
|
});
|
||||||
|
|
||||||
const [currentSubfolders, setCurrentSubfolders] = useState<FolderContentsEntry['subfolders']>([]);
|
const [currentSubfolders, setCurrentSubfolders] = useState<Array<{ id?: FolderNodeId; name?: string | null;[key: string]: unknown }>>([]);
|
||||||
|
|
||||||
const ensureFolderData = useCallback(
|
const ensureFolderData = useCallback(
|
||||||
async (
|
async (
|
||||||
@@ -699,7 +670,7 @@ const useDocumentsWorkspace = ({
|
|||||||
resetPreviewState();
|
resetPreviewState();
|
||||||
resetUploadsState();
|
resetUploadsState();
|
||||||
clearUploadQueue();
|
clearUploadQueue();
|
||||||
breadcrumbFetchRef.current = new Set();
|
|
||||||
detailFolderFetchRef.current = new Set();
|
detailFolderFetchRef.current = new Set();
|
||||||
bootstrapInitializedRef.current = false;
|
bootstrapInitializedRef.current = false;
|
||||||
selectionInitializedRef.current = false;
|
selectionInitializedRef.current = false;
|
||||||
@@ -1166,94 +1137,61 @@ const useDocumentsWorkspace = ({
|
|||||||
tenantIdRef,
|
tenantIdRef,
|
||||||
});
|
});
|
||||||
|
|
||||||
const documentsPanelProps = useDocumentsPanelProps({
|
const sessionContext = {
|
||||||
currentFolderName,
|
|
||||||
breadcrumbs,
|
|
||||||
refreshCurrentFolder,
|
|
||||||
currentSubfolders,
|
|
||||||
documents: viewDocuments,
|
|
||||||
searchQuery,
|
|
||||||
searchResultIds,
|
|
||||||
folderClickHandlers,
|
|
||||||
selectedFolder,
|
|
||||||
handleFolderDragStart,
|
|
||||||
handleFolderDragEnd,
|
|
||||||
draggedFolderId,
|
|
||||||
handleFolderRename,
|
|
||||||
handleDocumentTitleUpdate,
|
|
||||||
draggedDocumentIds,
|
|
||||||
handleDocumentDragStart,
|
|
||||||
handleDocumentDragEnd,
|
|
||||||
searchLoading,
|
|
||||||
tagLookupById,
|
|
||||||
activeTagFilters,
|
|
||||||
activeCorrespondentFilters,
|
|
||||||
ensureAssetUrl,
|
|
||||||
getDocumentAsset,
|
|
||||||
handleDocumentTagAttach,
|
|
||||||
handleDocumentTagDetach: handleTagRemove,
|
|
||||||
documentsViewMode,
|
|
||||||
documentsSortField,
|
|
||||||
documentsSortDirection,
|
|
||||||
handleDocumentsSortFieldChange,
|
|
||||||
handleDocumentsSortDirectionToggle,
|
|
||||||
handleDocumentsViewModeChange,
|
|
||||||
clearDocumentSelection,
|
|
||||||
handleDeleteSelection,
|
|
||||||
handleEntryPointerCore,
|
|
||||||
tags,
|
|
||||||
correspondents,
|
|
||||||
documentLookup,
|
|
||||||
handleBulkTagAddFromDetail,
|
|
||||||
handleBulkTagRemoveFromDetail,
|
|
||||||
handleBulkCorrespondentAdd,
|
|
||||||
handleBulkCorrespondentRemove,
|
|
||||||
handleBulkSelectionReanalyze,
|
|
||||||
folderOptions,
|
|
||||||
moveDocumentsToFolder,
|
|
||||||
selectFolder,
|
|
||||||
selectionValue: selection,
|
|
||||||
});
|
|
||||||
const documentsTableProps = useMemo(
|
|
||||||
() => ({
|
|
||||||
...documentsPanelProps,
|
|
||||||
}),
|
|
||||||
[documentsPanelProps],
|
|
||||||
);
|
|
||||||
|
|
||||||
const sidebarProps = useSidebarProps({
|
|
||||||
folderClickHandlers,
|
|
||||||
handleFolderDelete,
|
|
||||||
handleFolderRename,
|
|
||||||
selectedFolder,
|
|
||||||
handleFolderDragStart,
|
|
||||||
handleFolderDragEnd,
|
|
||||||
draggedFolderId,
|
|
||||||
handlePromptCreateFolder,
|
|
||||||
creatingFolder,
|
|
||||||
});
|
|
||||||
|
|
||||||
const contextValue = {
|
|
||||||
token,
|
token,
|
||||||
appStatus,
|
appStatus,
|
||||||
status,
|
|
||||||
setStatusMessage,
|
|
||||||
dropOverlayState,
|
|
||||||
handleLogout,
|
handleLogout,
|
||||||
sidebarProps,
|
tenant: tenantRecord,
|
||||||
|
tenants: tenantOptions,
|
||||||
|
tenantOptions,
|
||||||
|
handleTenantSelect,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uiContext = {
|
||||||
|
setStatusMessage,
|
||||||
|
notifyApiError,
|
||||||
|
settingsOpen,
|
||||||
|
openSettings,
|
||||||
|
closeSettings,
|
||||||
|
managementModals,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadContext = {
|
||||||
|
dropOverlayState,
|
||||||
|
uploadQueue,
|
||||||
|
clearUploadQueue,
|
||||||
|
handleFileSelection,
|
||||||
|
};
|
||||||
|
|
||||||
|
const tagsContext = {
|
||||||
tags,
|
tags,
|
||||||
refreshTags,
|
refreshTags,
|
||||||
|
tagLookupById,
|
||||||
|
activeTagFilters,
|
||||||
handleTagUpdate,
|
handleTagUpdate,
|
||||||
handleTagDelete,
|
handleTagDelete,
|
||||||
handleDocumentTagDrop: handleDocumentTagAttach,
|
handleDocumentTagDrop: handleDocumentTagAttach,
|
||||||
|
handleBulkTagAddFromDetail,
|
||||||
|
handleBulkTagRemoveFromDetail,
|
||||||
|
openTagsModal,
|
||||||
|
};
|
||||||
|
|
||||||
|
const correspondentsContext = {
|
||||||
correspondents,
|
correspondents,
|
||||||
refreshCorrespondents,
|
refreshCorrespondents,
|
||||||
|
activeCorrespondentFilters,
|
||||||
handleCorrespondentUpdate,
|
handleCorrespondentUpdate,
|
||||||
handleCorrespondentCreate,
|
handleCorrespondentCreate,
|
||||||
handleCorrespondentDelete,
|
handleCorrespondentDelete,
|
||||||
handleDocumentCorrespondentAttach,
|
handleDocumentCorrespondentAttach,
|
||||||
handleCorrespondentRemove,
|
handleCorrespondentRemove,
|
||||||
handleCorrespondentAdd,
|
handleCorrespondentAdd,
|
||||||
|
handleBulkCorrespondentAdd,
|
||||||
|
handleBulkCorrespondentRemove,
|
||||||
|
openCorrespondentsModal,
|
||||||
|
};
|
||||||
|
|
||||||
|
const passkeysContext = {
|
||||||
passkeys,
|
passkeys,
|
||||||
passkeysSupported,
|
passkeysSupported,
|
||||||
passkeysLoading,
|
passkeysLoading,
|
||||||
@@ -1262,34 +1200,94 @@ const useDocumentsWorkspace = ({
|
|||||||
refreshPasskeys,
|
refreshPasskeys,
|
||||||
registerPasskey,
|
registerPasskey,
|
||||||
revokePasskey,
|
revokePasskey,
|
||||||
|
};
|
||||||
|
|
||||||
|
const previewContext = {
|
||||||
previewActive,
|
previewActive,
|
||||||
previewWorkspaceDocument,
|
previewWorkspaceDocument,
|
||||||
previewDocumentId,
|
previewDocumentId,
|
||||||
closeDocumentPreview,
|
closeDocumentPreview,
|
||||||
handleThumbnailRegeneration,
|
|
||||||
documentsTableProps,
|
|
||||||
detailPanelProps,
|
|
||||||
documentsViewMode,
|
|
||||||
ensureAssetUrl,
|
ensureAssetUrl,
|
||||||
resolveFolderPath,
|
|
||||||
getDocumentAsset,
|
getDocumentAsset,
|
||||||
notifyApiError,
|
handleThumbnailRegeneration,
|
||||||
openTagsModal,
|
};
|
||||||
openCorrespondentsModal,
|
|
||||||
openSettings,
|
const detailPanelContext = {
|
||||||
|
detailPanelProps,
|
||||||
detailPanelOpen,
|
detailPanelOpen,
|
||||||
openDetailPanel,
|
openDetailPanel,
|
||||||
uploadQueue,
|
};
|
||||||
clearUploadQueue,
|
|
||||||
|
const searchContext = {
|
||||||
|
searchQuery,
|
||||||
documentsFilter,
|
documentsFilter,
|
||||||
documentsManager,
|
searchLoading,
|
||||||
|
documentsViewMode,
|
||||||
|
handleDocumentsViewModeChange,
|
||||||
|
documentsSortField,
|
||||||
|
documentsSortDirection,
|
||||||
|
handleDocumentsSortFieldChange,
|
||||||
|
handleDocumentsSortDirectionToggle,
|
||||||
|
searchResultIds,
|
||||||
|
documents: viewDocuments,
|
||||||
|
};
|
||||||
|
|
||||||
|
const folderTreeContext = {
|
||||||
foldersManager,
|
foldersManager,
|
||||||
|
selectedFolder,
|
||||||
|
currentFolderName,
|
||||||
|
folderOptions,
|
||||||
handleBreadcrumbNavigate,
|
handleBreadcrumbNavigate,
|
||||||
tenant: tenantRecord,
|
resolveFolderPath,
|
||||||
tenants: tenantOptions,
|
selectFolder,
|
||||||
tenantOptions,
|
moveDocumentsToFolder,
|
||||||
handleTenantSelect,
|
folderClickHandlers,
|
||||||
handleFileSelection,
|
handleFolderRename,
|
||||||
|
handleFolderDelete,
|
||||||
|
handleFolderDragStart,
|
||||||
|
handleFolderDragEnd,
|
||||||
|
draggedFolderId,
|
||||||
|
handlePromptCreateFolder,
|
||||||
|
creatingFolder,
|
||||||
|
currentSubfolders,
|
||||||
|
breadcrumbs,
|
||||||
|
refreshCurrentFolder,
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectionContext = {
|
||||||
|
clearDocumentSelection,
|
||||||
|
handleDeleteSelection,
|
||||||
|
handleEntryPointerCore,
|
||||||
|
handleBulkSelectionReanalyze,
|
||||||
|
selectionValue: selection,
|
||||||
|
};
|
||||||
|
|
||||||
|
const documentMutations = {
|
||||||
|
handleDocumentTitleUpdate,
|
||||||
|
handleDocumentDragStart,
|
||||||
|
handleDocumentDragEnd,
|
||||||
|
draggedDocumentIds,
|
||||||
|
};
|
||||||
|
|
||||||
|
const managers = {
|
||||||
|
documentsManager,
|
||||||
|
documentLookup,
|
||||||
|
};
|
||||||
|
|
||||||
|
const contextValue = {
|
||||||
|
...sessionContext,
|
||||||
|
...uiContext,
|
||||||
|
...uploadContext,
|
||||||
|
...tagsContext,
|
||||||
|
...correspondentsContext,
|
||||||
|
...passkeysContext,
|
||||||
|
...previewContext,
|
||||||
|
...detailPanelContext,
|
||||||
|
...searchContext,
|
||||||
|
...folderTreeContext,
|
||||||
|
...selectionContext,
|
||||||
|
...documentMutations,
|
||||||
|
...managers,
|
||||||
};
|
};
|
||||||
|
|
||||||
// hook callers handle rendering / routing
|
// hook callers handle rendering / routing
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
import type { FolderNode } from '../../types/documents';
|
import type { FolderNode } from '../../types/documents';
|
||||||
import type { FolderNodeId } from '../../types/identifiers';
|
import type { FolderNodeId } from '../../types/identifiers';
|
||||||
|
|
||||||
export type Breadcrumb = FolderNode;
|
|
||||||
|
|
||||||
export const resolveBreadcrumbs = (
|
export const resolveBreadcrumbs = (
|
||||||
startFolderId: FolderNodeId,
|
startFolderId: FolderNodeId,
|
||||||
folderNodes: Map<FolderNodeId, FolderNode>
|
folderNodes: Map<FolderNodeId, FolderNode>
|
||||||
): Breadcrumb[] => {
|
): FolderNode[] => {
|
||||||
const chain: Breadcrumb[] = [];
|
const chain: FolderNode[] = [];
|
||||||
const seen = new Set<FolderNodeId>();
|
const seen = new Set<FolderNodeId>();
|
||||||
let currentId: FolderNodeId | null = startFolderId;
|
let currentId: FolderNodeId | null = startFolderId;
|
||||||
let guard = 0;
|
let guard = 0;
|
||||||
@@ -25,7 +23,7 @@ export const resolveBreadcrumbs = (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ordered: Breadcrumb[] = [];
|
const ordered: FolderNode[] = [];
|
||||||
const seenOrdered = new Set<FolderNodeId>();
|
const seenOrdered = new Set<FolderNodeId>();
|
||||||
|
|
||||||
for (let i = chain.length - 1; i >= 0; i--) {
|
for (let i = chain.length - 1; i >= 0; i--) {
|
||||||
|
|||||||
@@ -37,14 +37,11 @@ const AppLayout: React.FC = () => {
|
|||||||
documentsViewMode: documentsPreferences.documentsViewMode,
|
documentsViewMode: documentsPreferences.documentsViewMode,
|
||||||
documentsSortField: documentsPreferences.documentsSortField,
|
documentsSortField: documentsPreferences.documentsSortField,
|
||||||
documentsSortDirection: documentsPreferences.documentsSortDirection,
|
documentsSortDirection: documentsPreferences.documentsSortDirection,
|
||||||
documentsSortFieldRef: documentsPreferences.documentsSortFieldRef,
|
|
||||||
documentsSortDirectionRef: documentsPreferences.documentsSortDirectionRef,
|
|
||||||
onDocumentsViewModeChange: documentsPreferences.handleDocumentsViewModeChange,
|
onDocumentsViewModeChange: documentsPreferences.handleDocumentsViewModeChange,
|
||||||
onDocumentsSortFieldChange: documentsPreferences.handleDocumentsSortFieldChange,
|
onDocumentsSortFieldChange: documentsPreferences.handleDocumentsSortFieldChange,
|
||||||
onDocumentsSortDirectionToggle: documentsPreferences.handleDocumentsSortDirectionToggle,
|
onDocumentsSortDirectionToggle: documentsPreferences.handleDocumentsSortDirectionToggle,
|
||||||
searchIncludeDescendants: documentsPreferences.searchIncludeDescendants,
|
searchIncludeDescendants: documentsPreferences.searchIncludeDescendants,
|
||||||
onSetSearchIncludeDescendants: documentsPreferences.setSearchIncludeDescendants,
|
onSetSearchIncludeDescendants: documentsPreferences.setSearchIncludeDescendants,
|
||||||
sortRefreshReadyRef: documentsPreferences.sortRefreshReadyRef,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (['logged-out', 'authenticating', 'selecting-tenant'].includes(appStatus)) {
|
if (['logged-out', 'authenticating', 'selecting-tenant'].includes(appStatus)) {
|
||||||
|
|||||||
@@ -1,44 +1,14 @@
|
|||||||
import React, { useRef } from 'react';
|
import React, { useRef } from 'react';
|
||||||
import { useAppShell } from '../lib/context/AppShellContext';
|
import { useAppShell } from '../lib/context/AppShellContext';
|
||||||
import { usePanelResizeBindings } from '../app/PanelManagerContext';
|
import { usePanelResizeBindings } from '../app/PanelManagerContext';
|
||||||
import type { Identifier } from '../types/identifiers';
|
|
||||||
import SidebarFolderList from './components/SidebarFolderList';
|
import SidebarFolderList from './components/SidebarFolderList';
|
||||||
import SidebarTagList from './components/SidebarTagList';
|
import SidebarTagList from './components/SidebarTagList';
|
||||||
import SidebarCorrespondentList from './components/SidebarCorrespondentList';
|
import SidebarCorrespondentList from './components/SidebarCorrespondentList';
|
||||||
import { FolderIdentifier } from './components/SidebarFolderNode';
|
|
||||||
import { TenantOption } from './components/SidebarMenu';
|
import { TenantOption } from './components/SidebarMenu';
|
||||||
import SidebarHeader from './components/SidebarHeader';
|
import SidebarHeader from './components/SidebarHeader';
|
||||||
import SidebarSearch from './components/SidebarSearch';
|
import SidebarSearch from './components/SidebarSearch';
|
||||||
|
|
||||||
interface SidebarProps {
|
const Sidebar: React.FC = () => {
|
||||||
onSelect: (folderId: FolderIdentifier) => void;
|
|
||||||
onDrop: (event: React.DragEvent<HTMLDivElement>, folderId: FolderIdentifier) => void;
|
|
||||||
onDragOver: (event: React.DragEvent<HTMLDivElement>, folderId: FolderIdentifier) => void;
|
|
||||||
onDragLeave: (event: React.DragEvent<HTMLDivElement>) => void;
|
|
||||||
onDeleteFolder: (folderId: FolderIdentifier) => void;
|
|
||||||
onRenameFolder?: (folderId: FolderIdentifier, name: string) => void;
|
|
||||||
selectedFolder?: FolderIdentifier | null;
|
|
||||||
onFolderDragStart?: (event: React.DragEvent<HTMLDivElement>, folderId: FolderIdentifier) => void;
|
|
||||||
onFolderDragEnd?: (event: React.DragEvent<HTMLDivElement>) => void;
|
|
||||||
draggedFolderId?: FolderIdentifier | null;
|
|
||||||
onCreateFolder?: (parentId?: Identifier | null) => void;
|
|
||||||
creatingFolder?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Sidebar: React.FC<SidebarProps> = ({
|
|
||||||
onSelect,
|
|
||||||
onDrop,
|
|
||||||
onDragOver,
|
|
||||||
onDragLeave,
|
|
||||||
onDeleteFolder,
|
|
||||||
onRenameFolder,
|
|
||||||
selectedFolder = null,
|
|
||||||
onFolderDragStart,
|
|
||||||
onFolderDragEnd,
|
|
||||||
draggedFolderId = null,
|
|
||||||
onCreateFolder,
|
|
||||||
creatingFolder = false,
|
|
||||||
}) => {
|
|
||||||
const {
|
const {
|
||||||
sidebarSuppressed,
|
sidebarSuppressed,
|
||||||
openTagsModal,
|
openTagsModal,
|
||||||
@@ -52,7 +22,22 @@ const Sidebar: React.FC<SidebarProps> = ({
|
|||||||
handleTenantSelect,
|
handleTenantSelect,
|
||||||
openSettings,
|
openSettings,
|
||||||
handleFileSelection, // Used for upload
|
handleFileSelection, // Used for upload
|
||||||
} = useAppShell();
|
// Folder Tree Context Props
|
||||||
|
folderClickHandlers = {},
|
||||||
|
handleFolderDelete,
|
||||||
|
handleFolderRename,
|
||||||
|
selectedFolder = null,
|
||||||
|
handleFolderDragStart,
|
||||||
|
handleFolderDragEnd,
|
||||||
|
draggedFolderId = null,
|
||||||
|
handlePromptCreateFolder,
|
||||||
|
creatingFolder = false,
|
||||||
|
} = useAppShell() as any;
|
||||||
|
|
||||||
|
const onSelect = folderClickHandlers.onSelect;
|
||||||
|
const onDrop = folderClickHandlers.onDrop;
|
||||||
|
const onDragOver = folderClickHandlers.onDragOver;
|
||||||
|
const onDragLeave = folderClickHandlers.onDragLeave;
|
||||||
|
|
||||||
const onManageTags = openTagsModal;
|
const onManageTags = openTagsModal;
|
||||||
const onManageCorrespondents = openCorrespondentsModal;
|
const onManageCorrespondents = openCorrespondentsModal;
|
||||||
@@ -110,12 +95,12 @@ const Sidebar: React.FC<SidebarProps> = ({
|
|||||||
onDrop={onDrop}
|
onDrop={onDrop}
|
||||||
onDragOver={onDragOver}
|
onDragOver={onDragOver}
|
||||||
onDragLeave={onDragLeave}
|
onDragLeave={onDragLeave}
|
||||||
onDeleteFolder={onDeleteFolder}
|
onDeleteFolder={handleFolderDelete}
|
||||||
onRenameFolder={onRenameFolder}
|
onRenameFolder={handleFolderRename}
|
||||||
onFolderDragStart={onFolderDragStart}
|
onFolderDragStart={handleFolderDragStart}
|
||||||
onFolderDragEnd={onFolderDragEnd}
|
onFolderDragEnd={handleFolderDragEnd}
|
||||||
draggedFolderId={draggedFolderId}
|
draggedFolderId={draggedFolderId}
|
||||||
onCreateFolder={onCreateFolder}
|
onCreateFolder={handlePromptCreateFolder}
|
||||||
creatingFolder={creatingFolder}
|
creatingFolder={creatingFolder}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
import { useMemo } from 'react';
|
|
||||||
import type { DragEvent } from 'react';
|
|
||||||
import type { Identifier } from '../types/identifiers';
|
|
||||||
|
|
||||||
type FolderDropHandler = (
|
|
||||||
event: DragEvent<HTMLElement>,
|
|
||||||
folderId: Identifier,
|
|
||||||
) => void | Promise<void>;
|
|
||||||
|
|
||||||
interface FolderClickHandlers {
|
|
||||||
onSelect: (folderId: Identifier | null) => void;
|
|
||||||
onDrop: FolderDropHandler;
|
|
||||||
onDragOver: (event: DragEvent<HTMLElement>, folderId: Identifier) => void;
|
|
||||||
onDragLeave: (event: DragEvent<HTMLElement>) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
interface UseSidebarPropsArgs {
|
|
||||||
folderClickHandlers: FolderClickHandlers;
|
|
||||||
handleFolderDelete: (folderId: Identifier) => void | Promise<void>;
|
|
||||||
handleFolderRename: (folderId: Identifier, name: string) => void | Promise<void>;
|
|
||||||
selectedFolder: Identifier | null;
|
|
||||||
handleFolderDragStart: (event: DragEvent<HTMLElement>, folderId: Identifier) => void;
|
|
||||||
handleFolderDragEnd: (event: DragEvent<HTMLElement>) => void;
|
|
||||||
draggedFolderId: Identifier | null;
|
|
||||||
handlePromptCreateFolder?: (parentId?: Identifier | null) => void;
|
|
||||||
creatingFolder: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SidebarHookResult {
|
|
||||||
onSelect: FolderClickHandlers['onSelect'];
|
|
||||||
onDrop: FolderClickHandlers['onDrop'];
|
|
||||||
onDragOver: FolderClickHandlers['onDragOver'];
|
|
||||||
onDragLeave: FolderClickHandlers['onDragLeave'];
|
|
||||||
onDeleteFolder: UseSidebarPropsArgs['handleFolderDelete'];
|
|
||||||
onRenameFolder: UseSidebarPropsArgs['handleFolderRename'];
|
|
||||||
selectedFolder: Identifier | null;
|
|
||||||
onFolderDragStart: UseSidebarPropsArgs['handleFolderDragStart'];
|
|
||||||
onFolderDragEnd: UseSidebarPropsArgs['handleFolderDragEnd'];
|
|
||||||
draggedFolderId: Identifier | null;
|
|
||||||
onCreateFolder: UseSidebarPropsArgs['handlePromptCreateFolder'];
|
|
||||||
creatingFolder: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const useSidebarProps = (args: UseSidebarPropsArgs): SidebarHookResult =>
|
|
||||||
useMemo(
|
|
||||||
() => ({
|
|
||||||
onSelect: args.folderClickHandlers.onSelect,
|
|
||||||
onDrop: args.folderClickHandlers.onDrop,
|
|
||||||
onDragOver: args.folderClickHandlers.onDragOver,
|
|
||||||
onDragLeave: args.folderClickHandlers.onDragLeave,
|
|
||||||
onDeleteFolder: args.handleFolderDelete,
|
|
||||||
onRenameFolder: args.handleFolderRename,
|
|
||||||
selectedFolder: args.selectedFolder,
|
|
||||||
onFolderDragStart: args.handleFolderDragStart,
|
|
||||||
onFolderDragEnd: args.handleFolderDragEnd,
|
|
||||||
draggedFolderId: args.draggedFolderId,
|
|
||||||
onCreateFolder: (parentId) => args.handlePromptCreateFolder?.(parentId),
|
|
||||||
creatingFolder: args.creatingFolder,
|
|
||||||
}),
|
|
||||||
[args],
|
|
||||||
);
|
|
||||||
|
|
||||||
export default useSidebarProps;
|
|
||||||
Reference in New Issue
Block a user