This commit is contained in:
2025-10-28 01:38:19 +01:00
parent 7df9a6415a
commit 1e177580c9
6 changed files with 211 additions and 82 deletions
+77 -27
View File
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useMemo } from 'react';
import { resolveDocumentAssetUrl } from '../asset_manager';
import { formatFileSize } from '../utils/format';
import { DownloadIcon, TextScanIcon, AnalyzeIcon, CloseIcon } from '../ui/icons';
@@ -17,10 +17,59 @@ const PreviewWorkspace = ({
const sizeLabel = sizeBytes > 0 ? formatFileSize(sizeBytes) : null;
const metadata =
document.metadata && Object.keys(document.metadata).length > 0 ? document.metadata : null;
const folderName = document.folder_path || document.folder_name || null;
const issuedAt = document.issued_at || document.current_version?.issued_at || null;
const createdAt = document.created_at || null;
const updatedAt = document.updated_at || null;
const tags = Array.isArray(document.tags) ? document.tags : [];
const correspondents = Array.isArray(document.correspondents) ? document.correspondents : [];
const metadataSummary = useMemo(() => {
const rows = [];
if (mime) rows.push(['Type', mime]);
if (sizeLabel) rows.push(['Size', sizeLabel]);
if (issuedAt) rows.push(['Issued', new Date(issuedAt).toLocaleString()]);
if (createdAt) rows.push(['Created', new Date(createdAt).toLocaleString()]);
if (updatedAt) rows.push(['Updated', new Date(updatedAt).toLocaleString()]);
if (folderName) rows.push(['Folder', folderName]);
if (tags.length) {
rows.push(['Tags', tags.map((tag) => tag.label || tag.name || tag.slug).filter(Boolean).join(', ')]);
}
if (correspondents.length) {
rows.push([
'Correspondents',
correspondents
.map((entry) => entry.name || entry.label || entry.slug)
.filter(Boolean)
.join(', '),
]);
}
return rows;
}, [mime, sizeLabel, issuedAt, createdAt, updatedAt, folderName, tags, correspondents]);
return (
<section className="preview-workspace">
<div className="preview-workspace__body">
<aside className="preview-workspace__sidebar">
<div className="preview-workspace__info">
{metadataSummary.length ? (
<dl className="preview-workspace__summary">
{metadataSummary.map(([label, value]) => (
<div className="preview-workspace__summary-row" key={label}>
<dt>{label}</dt>
<dd>{value || '—'}</dd>
</div>
))}
</dl>
) : null}
</div>
{metadata ? (
<section className="preview-workspace__metadata">
<h4>Metadata payload</h4>
<pre>{JSON.stringify(metadata, null, 2)}</pre>
</section>
) : null}
</aside>
<div className="preview-workspace__viewer">
{!previewEntry?.url ? (
<div className="preview-workspace__message">Loading preview</div>
) : (
@@ -31,14 +80,6 @@ const PreviewWorkspace = ({
/>
)}
</div>
{metadata ? (
<section className="preview-workspace__metadata">
<h3>Metadata</h3>
{sizeLabel ? <p><strong>Size:</strong> {sizeLabel}</p> : null}
<p><strong>Type:</strong> {mime}</p>
<pre>{JSON.stringify(metadata, null, 2)}</pre>
</section>
) : null}
</section>
);
};
@@ -52,7 +93,6 @@ export const createPreviewWorkspaceHeaderActions = ({
resolveApiPath,
notifyApiError,
onRegenerate,
onClose,
}) => {
if (!document) {
return null;
@@ -101,11 +141,11 @@ export const createPreviewWorkspaceHeaderActions = ({
</a>
) : null}
{hasOcr ? (
<button
type="button"
className="icon-button ghost"
onClick={handleOcrClick}
aria-label="View OCR text"
<button
type="button"
className="icon-button ghost"
onClick={handleOcrClick}
aria-label="View OCR text"
title="View OCR text"
>
<TextScanIcon />
@@ -120,15 +160,6 @@ export const createPreviewWorkspaceHeaderActions = ({
>
<AnalyzeIcon />
</button>
<button
type="button"
className="icon-button ghost"
onClick={() => onClose?.()}
aria-label="Close preview"
title="Close preview"
>
<CloseIcon />
</button>
</>
);
};
@@ -150,7 +181,27 @@ export const createPreviewSurface = ({
const title = document.title || document.original_name || 'Document preview';
const sidebarToggle = renderSidebarToggle ? renderSidebarToggle() : null;
const leading = sidebarToggle ? <>{sidebarToggle}</> : null;
const closeButton = onClose
? (
<button
type="button"
className="icon-button ghost"
onClick={() => onClose?.()}
aria-label="Close preview"
title="Close preview"
>
<CloseIcon />
</button>
)
: null;
const leading = sidebarToggle || closeButton
? (
<>
{sidebarToggle}
{closeButton}
</>
)
: null;
const header = {
title,
subtitle: null,
@@ -162,7 +213,6 @@ export const createPreviewSurface = ({
resolveApiPath,
notifyApiError,
onRegenerate,
onClose,
}),
};