The staff-report iframe is expanded to full content height (no nested
scrollbar), so a modal <dialog> centered in its viewport landed in the
middle of the whole document and sat off-screen unless the parent page
was scrolled there. Cross-origin means the iframe can't read the
parent's scroll position itself.
Tab.tpl now broadcasts the iframe's visible slice (webform-mw-viewport,
rAF-throttled on scroll/resize/load and after each height change), and
AttachmentLightbox pins to that slice and fills its height. Falls back
to a fixed box when no viewport message arrives (older extension), and
standalone mode keeps native centering at a taller 85vh.
Extension bumped to 0.3.1 (template change -> re-copy + cv flush on
prod). PRODUCTION_CUTOVER.md change log updated.
Three quick fixes off first-deploy testing:
1. /api/staff/file 404'd for valid files. Refactor fileBelongsToOrg
to SELECT the org's and activities' file columns and JS-compare
instead of WHERE ... OR with custom field refs (APIv4 fragility
around nested OR + dotted custom fields). Same ownership probe,
same shape /api/staff/report itself uses to read file values.
2. Lightbox ballooned to full report height because the staff iframe
auto-grows to fit content (often 3000+ px). Cap to a fixed
640px x min(92vw, 900px) box so it stays a reasonable preview
regardless of iframe document size.
3. Production frame-ancestors blocked crm.fci.coop from iframing
survey.fci.coop -- the CSP only included the dev Civi origin
derived from CIVI_BASE_URL. Add CIVI_FRAME_ALLOWED_ORIGINS
(comma-separated) so one app deploy can be embedded by both
dev and prod Civi. Falls back to CIVI_BASE_URL for single-Civi
compatibility.
PRODUCTION_CUTOVER.md updated inline and in the change log.
Adds a /api/staff/file proxy that re-streams Civi attachments with
Content-Disposition: inline so a native <dialog> lightbox can preview
images and PDFs in place. Office docs keep their plain download link
and gain a "View in Google Docs" secondary link (uses the Civi-signed
URL so Google can fetch without our staff key).
Also threads mime through /api/staff/report (Attachment.get mime_type)
so the dispatcher picks the right affordance without relying solely on
filename inference.