This commit is contained in:
2025-11-11 15:23:07 +01:00
parent a8589a864a
commit 5333de0e89
5 changed files with 137 additions and 58 deletions
+11 -6
View File
@@ -83,12 +83,17 @@ const createDesktopSurface = ({
const sidebarToggle = renderSidebarToggle ? renderSidebarToggle() : null; const sidebarToggle = renderSidebarToggle ? renderSidebarToggle() : null;
const detail = detailOpen && detailProps const detail = detailOpen && detailProps
? ( ? (() => {
<DocumentViewerPanel const { onClose, onOpenPreview, ...restDetailProps } = detailProps;
variant="sidebar" return (
{...detailProps} <DocumentViewerPanel
/> variant="sidebar"
) onCollapsePanel={onClose}
onMaximizePanel={onOpenPreview}
{...restDetailProps}
/>
);
})()
: null; : null;
const surfaceConfig = createWorkspaceSurfaceConfig({ const surfaceConfig = createWorkspaceSurfaceConfig({
key: 'workspace', key: 'workspace',
+1 -1
View File
@@ -237,7 +237,7 @@ const useDetailWorkspace = ({
onUpdateIssued: handleDocumentIssuedUpdate, onUpdateIssued: handleDocumentIssuedUpdate,
ensureAssetUrl, ensureAssetUrl,
getDocumentAsset, getDocumentAsset,
hydrateDocument: ensurePreviewData, hydrateDocument: ensurePreviewData,
correspondents, correspondents,
onCorrespondentAdd: handleCorrespondentAdd, onCorrespondentAdd: handleCorrespondentAdd,
onCorrespondentRemove: handleCorrespondentRemove, onCorrespondentRemove: handleCorrespondentRemove,
@@ -92,12 +92,17 @@ const createDocumentsSurface = ({
const sidebarToggle = renderSidebarToggle ? renderSidebarToggle() : null; const sidebarToggle = renderSidebarToggle ? renderSidebarToggle() : null;
const detail = detailOpen && detailProps const detail = detailOpen && detailProps
? ( ? (() => {
<DocumentViewerPanel const { onClose, onOpenPreview, ...restDetailProps } = detailProps;
variant="sidebar" return (
{...detailProps} <DocumentViewerPanel
/> variant="sidebar"
) onCollapsePanel={onClose}
onMaximizePanel={onOpenPreview}
{...restDetailProps}
/>
);
})()
: null; : null;
return createWorkspaceSurfaceConfig({ return createWorkspaceSurfaceConfig({
+112 -43
View File
@@ -6,7 +6,13 @@ import React, {
useState, useState,
} from 'react'; } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { DownloadIcon, CloseIcon, IconZoomInArea } from '../ui/icons'; import {
DownloadIcon,
CloseIcon,
IconZoomInArea,
DetailPanelCollapseIcon,
WindowMaximizeIcon,
} from '../ui/icons';
import PreviewZoomOverlay from '../detail/PreviewZoomOverlay'; import PreviewZoomOverlay from '../detail/PreviewZoomOverlay';
import { import {
buildCorrespondentOptions, buildCorrespondentOptions,
@@ -79,7 +85,6 @@ const DocumentViewerPanel = ({
onCorrespondentRemove, onCorrespondentRemove,
onUpdateTitle, onUpdateTitle,
onUpdateIssued, onUpdateIssued,
hasOcr = false,
ensureAssetUrl, ensureAssetUrl,
getDocumentAsset, getDocumentAsset,
ensurePreviewData, ensurePreviewData,
@@ -88,8 +93,12 @@ const DocumentViewerPanel = ({
sidebarToggle = null, sidebarToggle = null,
onClosePanel, onClosePanel,
resolveFolderPath, resolveFolderPath,
variant = 'viewer',
onCollapsePanel,
onMaximizePanel,
}) => { }) => {
const navigate = useNavigate(); const navigate = useNavigate();
const isSidebarVariant = variant === 'sidebar';
const sortedCorrespondents = useMemo( const sortedCorrespondents = useMemo(
() => sortCorrespondents(document?.correspondents || []), () => sortCorrespondents(document?.correspondents || []),
[document], [document],
@@ -105,6 +114,13 @@ const DocumentViewerPanel = ({
[document], [document],
); );
const hasOcr = useMemo(() => {
if (!document || typeof getDocumentAsset !== 'function') {
return false;
}
return Boolean(getDocumentAsset(document, 'ocr-text'));
}, [document, getDocumentAsset]);
const summaryProps = useMemo( const summaryProps = useMemo(
() => ({ () => ({
tagLookupById, tagLookupById,
@@ -331,7 +347,38 @@ const DocumentViewerPanel = ({
canZoom: Boolean(zoomDisplay), canZoom: Boolean(zoomDisplay),
}); });
const closeButton = onClosePanel const collapseButton = isSidebarVariant && typeof onCollapsePanel === 'function'
? (
<button
type="button"
className="icon-button"
onClick={() => onCollapsePanel?.()}
aria-label="Close detail panel"
title="Close detail panel"
>
<DetailPanelCollapseIcon />
</button>
)
: null;
const maximizeButton = isSidebarVariant && typeof onMaximizePanel === 'function'
? (
<button
type="button"
className="icon-button"
onClick={(event) => {
event.stopPropagation();
onMaximizePanel?.(document?.id);
}}
aria-label="Maximize"
title="Maximize"
>
<WindowMaximizeIcon className="icon--flip-y" />
</button>
)
: null;
const closeButton = !isSidebarVariant && onClosePanel
? ( ? (
<button <button
type="button" type="button"
@@ -345,7 +392,9 @@ const DocumentViewerPanel = ({
) )
: null; : null;
const headerLeadingButtons = [sidebarToggle, closeButton].filter(Boolean); const headerLeadingButtons = isSidebarVariant
? [collapseButton, maximizeButton].filter(Boolean)
: [sidebarToggle, closeButton].filter(Boolean);
const headerLeadingContent = headerLeadingButtons.length const headerLeadingContent = headerLeadingButtons.length
? ( ? (
<> <>
@@ -354,36 +403,76 @@ const DocumentViewerPanel = ({
) )
: null; : null;
if (!document) { const loadingSection = (
return ( <div className="document-viewer-panel__body">
<section className="document-viewer-panel" ref={panelRef}> <section className="document-viewer document-viewer--loading">
<PanelHeader title="Document preview" /> <div className="document-viewer__details-pane">
<div className="document-viewer-panel__body"> <div className="document-viewer__details">
<section className="document-viewer document-viewer--loading"> <div className="document-viewer__message">Loading document</div>
<div className="document-viewer__details-pane"> </div>
<div className="document-viewer__details"> </div>
<div className="document-viewer__message">Loading document</div> <div className="document-viewer__viewport">
</div> <div className="document-viewer__message">Preparing preview</div>
</div>
<div className="document-viewer__viewport">
<div className="document-viewer__message">Preparing preview</div>
</div>
</section>
</div> </div>
</section> </section>
); </div>
} );
const viewerSection = document ? (
<div
className={isStackedLayout
? 'document-viewer-panel__body document-viewer-panel__body--stacked'
: 'document-viewer-panel__body'}
>
<section className={viewerClassName}>
<DocumentViewerLayout
document={document}
previewEntry={previewEntry}
summaryProps={summaryProps}
metadataPayload={metadataPayload}
contentTabConfig={contentTabConfig}
previewLoadingMessage="Loading preview…"
/>
</section>
</div>
) : loadingSection;
const headerTitle = breadcrumbTrailEntries.length ? ( const headerTitle = breadcrumbTrailEntries.length ? (
<BreadcrumbTrail <BreadcrumbTrail
entries={breadcrumbTrailEntries} entries={breadcrumbTrailEntries}
separator="/" separator="/"
className="panel-header__breadcrumbs" className="panel-header__breadcrumbs"
truncateFromStart={isSidebarVariant}
/> />
) : ( ) : (
document?.title || 'Document preview' document?.title || 'Document preview'
); );
const overlay = (
<PreviewZoomOverlay
open={Boolean(zoomOverlayOpen && zoomDisplay)}
display={zoomDisplay}
onClose={handleZoomClose}
/>
);
if (isSidebarVariant) {
return (
<>
<aside className="detail-panel panel" ref={panelRef}>
<PanelHeader
leading={headerLeadingContent}
title={headerTitle}
titleTag="h3"
actions={headerActions}
/>
<div className="panel-body detail-panel__content">{viewerSection}</div>
</aside>
{overlay}
</>
);
}
return ( return (
<> <>
<section className="document-viewer-panel" ref={panelRef}> <section className="document-viewer-panel" ref={panelRef}>
@@ -393,24 +482,9 @@ const DocumentViewerPanel = ({
titleTag="h3" titleTag="h3"
actions={headerActions} actions={headerActions}
/> />
<div className="document-viewer-panel__body"> {viewerSection}
<section className={viewerClassName}>
<DocumentViewerLayout
document={document}
previewEntry={previewEntry}
summaryProps={summaryProps}
metadataPayload={metadataPayload}
contentTabConfig={contentTabConfig}
previewLoadingMessage="Loading preview…"
/>
</section>
</div>
</section> </section>
<PreviewZoomOverlay {overlay}
open={Boolean(zoomOverlayOpen && zoomDisplay)}
display={zoomDisplay}
onClose={handleZoomClose}
/>
</> </>
); );
}; };
@@ -442,10 +516,6 @@ export const createDocumentViewerSurface = ({
return null; return null;
} }
const hasOcr = typeof getDocumentAsset === 'function'
? Boolean(getDocumentAsset(document, 'ocr-text'))
: false;
const sidebarToggle = typeof renderSidebarToggle === 'function' const sidebarToggle = typeof renderSidebarToggle === 'function'
? renderSidebarToggle() ? renderSidebarToggle()
: null; : null;
@@ -468,7 +538,6 @@ export const createDocumentViewerSurface = ({
onCorrespondentRemove={onCorrespondentRemove} onCorrespondentRemove={onCorrespondentRemove}
onUpdateTitle={onUpdateTitle} onUpdateTitle={onUpdateTitle}
onUpdateIssued={onUpdateIssued} onUpdateIssued={onUpdateIssued}
hasOcr={hasOcr}
ensureAssetUrl={ensureAssetUrl} ensureAssetUrl={ensureAssetUrl}
getDocumentAsset={getDocumentAsset} getDocumentAsset={getDocumentAsset}
ensurePreviewData={ensurePreviewData} ensurePreviewData={ensurePreviewData}
+2 -2
View File
@@ -347,8 +347,8 @@
display: flex; display: flex;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
align-items: stretch; align-items: flex-start;
justify-content: center; justify-content: flex-start;
max-height: 100%; max-height: 100%;
grid-area: viewport; grid-area: viewport;
} }