102 lines
3.3 KiB
TypeScript
102 lines
3.3 KiB
TypeScript
import React, { useCallback, useEffect, useMemo } from 'react';
|
|
import type { ReactNode } from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import {
|
|
DocumentsFilterProvider,
|
|
} from '../documents/context/DocumentsFilterContext';
|
|
import { PreviewProvider } from '../preview/PreviewContext';
|
|
import { useWorkspaceSurface } from './useWorkspaceSurface';
|
|
import { DocumentsHeaderBreadcrumb } from '../documents/panel/DocumentsPanelHeader';
|
|
import { SidebarProvider, useSidebarContext } from '../sidebar/SidebarContext';
|
|
import { PanelManagerProvider, usePanelManager } from './PanelManagerContext';
|
|
import Sidebar from '../sidebar/Sidebar';
|
|
import useDocumentsShell from './useDocumentsShell';
|
|
|
|
const DocumentsRouteContent: React.FC = () => {
|
|
const {
|
|
sidebarProps,
|
|
surfaceConfig,
|
|
documentsFilter,
|
|
} = useDocumentsShell();
|
|
const navigate = useNavigate();
|
|
const { collapsed: sidebarCollapsed } = useSidebarContext();
|
|
const {
|
|
sidebarSuppressed,
|
|
expandSidebar,
|
|
} = usePanelManager();
|
|
|
|
const sidebarHidden = sidebarCollapsed || sidebarSuppressed;
|
|
|
|
const handleHeaderBreadcrumbClick = useCallback((crumb: DocumentsHeaderBreadcrumb) => {
|
|
if (!crumb || !crumb.id) {
|
|
return;
|
|
}
|
|
const target = crumb.id === 'root' ? '/documents' : `/documents/folder/${crumb.id}`;
|
|
navigate(target);
|
|
}, [navigate]);
|
|
|
|
const handleDocumentNavigate = useCallback((documentId: string) => {
|
|
navigate(`/documents/${documentId}`);
|
|
}, [navigate]);
|
|
|
|
const documentsTablePropsWithNav = useMemo(() => (
|
|
surfaceConfig.documentsTableProps
|
|
? { ...surfaceConfig.documentsTableProps, onBreadcrumbNavigate: handleHeaderBreadcrumbClick }
|
|
: null
|
|
), [surfaceConfig.documentsTableProps, handleHeaderBreadcrumbClick]);
|
|
|
|
const { surface } = useWorkspaceSurface({
|
|
sidebarHidden,
|
|
onExpandSidebar: expandSidebar,
|
|
...surfaceConfig,
|
|
documentsTableProps: documentsTablePropsWithNav,
|
|
});
|
|
|
|
useEffect(() => {
|
|
document.body.classList.add('has-main-content');
|
|
return () => {
|
|
document.body.classList.remove('has-main-content');
|
|
};
|
|
}, []);
|
|
|
|
const renderSurface = () => {
|
|
const detailMode = surface?.detailMode ?? null;
|
|
const layoutClass = `documents-main${sidebarHidden ? ' documents-main--sidebar-hidden' : ''}${detailMode === 'overlay' ? ' documents-main--overlay-detail' : ''}`;
|
|
const sidebarNode = !sidebarHidden && sidebarProps ? <Sidebar {...sidebarProps} /> : null;
|
|
const surfaceDetail = surface && (surface as { detail?: ReactNode }).detail ? (surface as { detail?: ReactNode }).detail : null;
|
|
const surfaceBody = surface ? surface.content : null;
|
|
|
|
return (
|
|
<main className={layoutClass}>
|
|
{sidebarNode}
|
|
<div className="main-content">
|
|
{surfaceBody}
|
|
</div>
|
|
{surfaceDetail}
|
|
</main>
|
|
);
|
|
};
|
|
|
|
const content = renderSurface();
|
|
return (
|
|
<DocumentsFilterProvider value={documentsFilter}>
|
|
<PreviewProvider
|
|
ensureDownloadUrl={surfaceConfig.documentsTableProps?.ensureDownloadUrl}
|
|
onNavigate={handleDocumentNavigate}
|
|
>
|
|
{content}
|
|
</PreviewProvider>
|
|
</DocumentsFilterProvider>
|
|
);
|
|
};
|
|
|
|
const DocumentsRoute: React.FC = () => (
|
|
<SidebarProvider>
|
|
<PanelManagerProvider>
|
|
<DocumentsRouteContent />
|
|
</PanelManagerProvider>
|
|
</SidebarProvider>
|
|
);
|
|
|
|
export default DocumentsRoute;
|