diff --git a/nextjs_space/app/api/super-admin/email-templates/preview/route.ts b/nextjs_space/app/api/super-admin/email-templates/preview/route.ts index 956105bf..b26b2a3c 100644 --- a/nextjs_space/app/api/super-admin/email-templates/preview/route.ts +++ b/nextjs_space/app/api/super-admin/email-templates/preview/route.ts @@ -67,6 +67,8 @@ export const POST = withSuperAdmin(async (req, { user }) => { category: category !== undefined ? category : owner?.category, tenantId: owner?.tenantId ?? null, businessName: tenant?.businessName, + // Same reason as the tenant route: the srcdoc pane inherits the admin CSP. + baseUrlOverride: req.nextUrl.origin, }); return NextResponse.json({ html }); diff --git a/nextjs_space/app/api/tenant-admin/email-templates/preview/route.ts b/nextjs_space/app/api/tenant-admin/email-templates/preview/route.ts index 495d3ae1..3fe073f3 100644 --- a/nextjs_space/app/api/tenant-admin/email-templates/preview/route.ts +++ b/nextjs_space/app/api/tenant-admin/email-templates/preview/route.ts @@ -74,6 +74,10 @@ export const POST = requirePermission( category: existing ? existing.category : category, tenantId, businessName: tenant?.businessName, + // Assets resolve against the origin the author is on: the pane's + // srcdoc iframe inherits THIS page's CSP, which has no tenant hosts in + // img-src, so tenant-domain URLs would render as broken images. + baseUrlOverride: req.nextUrl.origin, }); return NextResponse.json({ html }); diff --git a/nextjs_space/app/super-admin/emails/[id]/client.tsx b/nextjs_space/app/super-admin/emails/[id]/client.tsx index fc2654ce..06add789 100644 --- a/nextjs_space/app/super-admin/emails/[id]/client.tsx +++ b/nextjs_space/app/super-admin/emails/[id]/client.tsx @@ -65,34 +65,41 @@ export function EditTemplateClient({ } }; + // The same sized-wrapper shape as the tenant-admin email screens: the editor + // is h-full and fills a `flex-1 overflow-hidden` box instead of guessing the + // viewport, so the Save header can never be scrolled out of reach. return ( -
- -