MishkaCmsCoreWeb. Live. Admin. Components. RuntimePreviewModal
(Mishka CMS Core v0.0.1)
Copy Markdown
View Source
Tabbed inspector modal for a single module-backed runtime record (Page / Component / Layout / ErrorPage), opened from a table's "Preview" row action.
Six tabs — Overview (stored details + a sample metrics card), Preview (the
rendered output in a sandboxed <iframe srcdoc> with Desktop/Tablet/Mobile widths),
Code (raw source, copy button), Versions (recent AshPaperTrail versions),
Pipeline (the live RuntimeStatusTimeline), and Configuration (the resource's
MishkaGervaz.Form.Web.Live form — this modal is where a record is edited, so there is no
second form modal on the page).
Two header actions carry the record's runtime cost, and both are deliberate clicks rather than
anything the modal does by opening: Visual Editor leaves for the builder, and Force compile
builds the record's module now even when it is marked lazy (see
MishkaCmsCoreWeb.Live.Admin.Dashboard.Runtime.PreviewHelpers.force_compile/1). A component also
offers Duplicate, which writes a new component from this one and closes the modal on it (see
MishkaCmsCoreWeb.Live.Admin.Dashboard.Runtime.PreviewHelpers.duplicate/1).
Driven entirely by the :preview map that
MishkaCmsCoreWeb.Live.Admin.Dashboard.Runtime.PreviewHelpers maintains. The shell uses
the runtime-preview-modal id family so MishkaCmsCore.CoreComponents.show_modal/1 /
hide_modal/1 drive it, like the form modal.
See MishkaCmsCore.Runtime.RuntimePreview (renders the iframe document + Overview rows).
No style attribute
This modal renders in the admin document, which is served the compiled admin.css, so every rule
here is a Tailwind class and a Content-Security-Policy can drop style-src-attr 'unsafe-inline' —
it has no nonce to offer an attribute. The two values that vary are written as whole literal
classes, one function clause each, because Tailwind reads SOURCE TEXT and a class with an
interpolation hole gets no rule at all: device_class/1 sizes the preview frame (in step with
MishkaCmsCore.Runtime.RuntimePreview.device_width/1) and bar_height_class/1 draws the four
priority bars.
The document INSIDE the frame is a separate matter — see RuntimePreview, which styles its own
chrome with a <style> element because a class of ours reaches nothing in there. That element is
nonced: srcdoc inherits the ADMIN policy of the page framing it, so an unnonced one is refused
and the preview renders bare. The nonce is not this component's to pass, though — the modal only
hands the finished @html / @edit_html to the frame, and
MishkaCmsCoreWeb.Live.Admin.Dashboard.Runtime.PreviewHelpers, which builds those strings, reads
socket.assigns[:csp_nonce] off the LiveView that renders this modal.