Files
papercrate/frontend/src/app/DocumentsRoute.tsx
T

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;