Files
nexarch/web/mail-search/app/mail/[messageId]/AttachmentList.tsx
T
patrickandClaude Sonnet 5 f63fcb8a2d
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Canceled after 0s
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (pull_request) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (push) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Canceled after 0s
CI / Connect Security-Test-Gate (QA-01 AC4, Merge-Gate) (push) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Canceled after 0s
CI / Web (dms-browser) (push) Canceled after 0s
CI / Web (pdf-viewer) (push) Canceled after 0s
CI / Web (shl) (push) Canceled after 0s
Supply-Chain-Scan (npm) / npm-audit (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (pull_request) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (pull_request) Canceled after 0s
CI / Connect Security-Test-Gate (QA-01 AC4, Merge-Gate) (pull_request) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (pull_request) Canceled after 0s
CI / Web (dms-browser) (pull_request) Canceled after 0s
CI / Web (pdf-viewer) (pull_request) Canceled after 0s
CI / Web (shl) (pull_request) Canceled after 0s
Core-Schnittstellen-Vertragstests / contract-tests (pull_request) Canceled after 0s
Supply-Chain-Scan (Go) / govulncheck (pull_request) Canceled after 0s
Mail-Pflichttest-Gate / pflichttest-gate (pull_request) Canceled after 0s
Supply-Chain-Scan (npm) / npm-audit (pull_request) Canceled after 0s
Core-Pflichttest-Gate / pflichttest-gate (pull_request) Canceled after 0s
RBAC-Rollenhierarchie-Pflichtgate / rbac-policy-invariant (pull_request) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (pull_request) Canceled after 0s
UX-03: anhang-vorschau
Frontend (web/mail-search): Anhang-Vorschau fuer PDF (Canvas-Rendering
via pdfjs-dist, gleiches Muster wie DOC-05s web/pdf-viewer/PdfViewer.tsx
-- kein aequivalentes PdfCanvasPreview im Repo gefunden, daher PdfViewer
als Vorlage uebernommen statt neu erfunden) und Bilder (<img> auf einem
authentifiziert geladenen Blob). Die Vorschauart haengt ausschliesslich
vom serverseitig per Magic-Bytes bestimmten contentType ab, nie von
einem Dateinamen (den es an der Schnittstelle gar nicht gibt); nicht
unterstuetzte Typen werden nur als Hinweistext angezeigt, nie
eingebettet. Kein iframe/<object>/dangerouslySetInnerHTML -- durch
automatisierten Sicherheitsreview-Test abgesichert. Neue lib/http.ts
(authentifizierter Zugriff ueber @nexarch/shl, identisch zu
web/pdf-viewer/lib/http.ts) und lib/attachments.ts (Anhangsliste/
-inhalt der Mail-API). Pruefprotokoll in mail/docs/UX-03-PRUEFPROTOKOLL.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-16 06:51:29 +00:00

51 lines
1.4 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import { fetchAttachmentList, type AttachmentListResult } from "../../../lib/attachments";
import { AttachmentPreview } from "./AttachmentPreview";
export interface AttachmentListProps {
messageId: string;
}
// UX-03 Akzeptanzkriterium 1: laedt die Anhangsliste und zeigt je Anhang
// eine Vorschau. Ein Ausfall der Mail-API blockiert die uebrige
// Mailanzeige nicht (gleiche Konvention wie CaseContextPanel).
export function AttachmentList({ messageId }: AttachmentListProps) {
const [result, setResult] = useState<AttachmentListResult | null>(null);
useEffect(() => {
let cancelled = false;
setResult(null);
fetchAttachmentList(messageId).then((r) => {
if (!cancelled) setResult(r);
});
return () => {
cancelled = true;
};
}, [messageId]);
if (result === null) {
return null;
}
if (result.status === "unavailable") {
return (
<section aria-label="Anhänge" style={{ marginTop: 24 }}>
<p>Anhänge konnten nicht geladen werden.</p>
</section>
);
}
if (result.attachments.length === 0) {
return null;
}
return (
<section aria-label="Anhänge" style={{ marginTop: 24 }}>
<h2>Anhänge</h2>
{result.attachments.map((attachment) => (
<AttachmentPreview key={attachment.index} messageId={messageId} attachment={attachment} />
))}
</section>
);
}