typescript

This commit is contained in:
2025-11-13 01:07:55 +01:00
parent b812d748ea
commit ada089c05b
147 changed files with 7427 additions and 2534 deletions
+189
View File
@@ -0,0 +1,189 @@
import React, { useCallback, useEffect, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { useAppShell } from '../appShellContext';
import DocumentsLayout from './DocumentsLayout';
import { useWorkspaceSurface } from './useWorkspaceSurface';
import PanelHeader from '../ui/PanelHeader';
import BreadcrumbTrail from '../ui/BreadcrumbTrail';
import { SidebarProvider, useSidebarContext } from '../sidebar/SidebarContext';
import { PanelManagerProvider, usePanelManager } from './PanelManagerContext';
type Breadcrumb = { id?: string | number; name?: string; label?: string; title?: string };
const DocumentsRouteContent: React.FC = () => {
const {
sidebarProps,
documentsTableProps,
detailPanelProps,
detailPanelOpen,
documentsViewMode,
deskWorkspaceProps,
openTagsModal,
openCorrespondentsModal,
previewWorkspaceDocument,
previewWorkspaceEntry,
previewDocumentId,
closeDocumentPreview,
ensurePreviewData,
resolveApiPath,
ensureAssetUrl,
getDocumentAsset,
notifyApiError,
} = useAppShell();
const navigate = useNavigate();
const { collapsed: sidebarCollapsed } = useSidebarContext();
const {
sidebarSuppressed,
expandSidebar,
} = usePanelManager();
const sidebarPropsWithActions = useMemo(
() => ({
...sidebarProps,
onManageTags: openTagsModal,
onManageCorrespondents: openCorrespondentsModal,
}),
[sidebarProps, openTagsModal, openCorrespondentsModal],
);
const sidebarHidden = sidebarCollapsed || sidebarSuppressed;
const breadcrumbs = documentsTableProps?.breadcrumbs || null;
const parentBreadcrumb = useMemo(() => {
if (!Array.isArray(breadcrumbs) || breadcrumbs.length <= 1) {
return null;
}
return breadcrumbs[breadcrumbs.length - 2];
}, [breadcrumbs]);
const handleNavigateParent = useCallback(() => {
if (!parentBreadcrumb) {
return;
}
const target = parentBreadcrumb.id === 'root'
? '/documents'
: `/documents/folder/${parentBreadcrumb.id}`;
navigate(target);
}, [navigate, parentBreadcrumb]);
const handleHeaderBreadcrumbClick = useCallback((crumb: Breadcrumb) => {
if (!crumb || !crumb.id) {
return;
}
const target = crumb.id === 'root' ? '/documents' : `/documents/folder/${crumb.id}`;
navigate(target);
}, [navigate]);
const { surface } = useWorkspaceSurface({
sidebarHidden,
onExpandSidebar: expandSidebar,
documentsTableProps,
detailPanelProps,
detailPanelOpen,
viewMode: documentsViewMode,
deskWorkspaceProps,
previewWorkspaceDocument,
previewWorkspaceEntry,
previewDocumentId,
ensureAssetUrl,
ensurePreviewData,
getDocumentAsset,
resolveApiPath,
notifyApiError,
closeDocumentPreview,
parentBreadcrumb,
onNavigateParent: handleNavigateParent,
});
useEffect(() => {
document.body.classList.add('has-main-content');
return () => {
document.body.classList.remove('has-main-content');
};
}, []);
if (!surface) {
return (
<DocumentsLayout sidebarProps={sidebarPropsWithActions}>
<div className="main-content main-content--documents">
<div className="main-content__body main-content__body--documents" />
</div>
</DocumentsLayout>
);
}
const variant = surface.variant || 'documents';
const mainContentClass = `main-content main-content--${variant}${
surface.detail ? ' main-content--has-detail' : ''
}`;
const bodyClass = `main-content__body main-content__body--${variant}${
surface.detail ? ' main-content__body--has-detail' : ''
}`;
const header = surface.header || null;
let headerTitle: React.ReactNode = null;
if (header) {
const breadcrumbEntries = Array.isArray(header.breadcrumbs) ? header.breadcrumbs.filter(Boolean) : [];
const lastIndex = breadcrumbEntries.length - 1;
const trailEntries = breadcrumbEntries.length
? breadcrumbEntries.map((crumb, index) => ({
id: crumb.id ?? index,
label: crumb.name ?? crumb.label ?? crumb.title ?? '',
onClick: index < lastIndex ? () => handleHeaderBreadcrumbClick(crumb) : null,
}))
: [{ id: 'current-location', label: header.title }];
headerTitle = (
<h2 className="main-content__title">
<BreadcrumbTrail
entries={trailEntries}
className="main-content__breadcrumbs"
separator="/"
/>
{header.subtitle ? (
<span className="main-content__subtitle">{header.subtitle}</span>
) : null}
</h2>
);
}
return (
<DocumentsLayout sidebarProps={sidebarPropsWithActions}>
<div className={mainContentClass}>
{header ? (
<div className="main-content__header-wrapper">
{(header.selectionLabel || header.floatingActions) ? (
<div className="panel-floating" aria-live="polite" aria-atomic="true">
{header.selectionLabel ? (
<span className="panel-floating__label">{header.selectionLabel}</span>
) : null}
{header.floatingActions || null}
</div>
) : null}
<PanelHeader
className="main-content__header"
leading={header.leading}
title={headerTitle}
titleTag="h2"
actions={header.actions}
/>
</div>
) : null}
<div className={bodyClass}>{surface.content}</div>
{surface.detail || null}
</div>
</DocumentsLayout>
);
};
const DocumentsRoute: React.FC = () => (
<SidebarProvider>
<PanelManagerProvider>
<DocumentsRouteContent />
</PanelManagerProvider>
</SidebarProvider>
);
export default DocumentsRoute;