diff --git a/frontend/src/pages/admin/projects/ProjectCockpitPage.tsx b/frontend/src/pages/admin/projects/ProjectCockpitPage.tsx index 61da0582..5e7dc3ab 100644 --- a/frontend/src/pages/admin/projects/ProjectCockpitPage.tsx +++ b/frontend/src/pages/admin/projects/ProjectCockpitPage.tsx @@ -83,14 +83,16 @@ const KIND_ICON: Record> = hours: Clock, }; -/** Neutralise links for a read-only preview: force every anchor to target a - * new tab so the sandboxed iframe (no allow-popups) blocks the navigation - * entirely. Without this, clicking "Accept"/"Decline" in the preview would - * hit the live action URLs and actually change the quote's state. */ -function neutralizeLinks(html: string): string { - const base = ''; - if (/]*>/i.test(html)) return html.replace(/]*>/i, (m) => m + base); - return base + html; +/** Prepare the rendered email for a read-only preview: + * - `` so the sandboxed iframe (no allow-popups) blocks + * every link, preventing accidental clicks on the live Accept/Decline URLs. + * - `overflow-wrap:break-word` so a long unbreakable token (e.g. the gallery + * link) wraps inside the container instead of forcing horizontal scroll. + * break-word only kicks in on overflow, so it won't disturb table layout. */ +function preparePreviewHtml(html: string): string { + const inject = ''; + if (/]*>/i.test(html)) return html.replace(/]*>/i, (m) => m + inject); + return inject + html; } function minutesToHours(min: number): string { @@ -463,7 +465,7 @@ export const ProjectCockpitPage: React.FC = () => { clicking inside the preview. Scrolling still works. */}