| import html as _html |
| import json, pathlib |
| from astranexus.core.schema import CanvasGraph |
|
|
| _TEMPLATE = pathlib.Path(__file__).resolve().parents[1] / "assets" / "vis_canvas.html" |
|
|
|
|
| def render_html(g: CanvasGraph) -> str: |
| payload = { |
| "nodes": [n.__dict__ for n in g.nodes], |
| "edges": [{"src": e.src, "dst": e.dst, "kind": e.kind} for e in g.edges], |
| "clusters": [{"id": c.id, "name": c.name, "count": len(c.email_ids), |
| "rationale": c.rationale, "urgency": c.urgency} |
| for c in g.clusters], |
| } |
| template = _TEMPLATE.read_text(encoding="utf-8") |
| return template.replace("__GRAPH_JSON__", json.dumps(payload)) |
|
|
|
|
| def render_iframe(g: CanvasGraph, height: int = 620) -> str: |
| """Wrap the canvas doc in an <iframe srcdoc> so its <script> runs. |
| |
| gr.HTML (Gradio 6) injects via innerHTML and does NOT execute inline |
| <script>; an iframe is a separate document that does. The vis-network |
| template already targets window.parent, so it was built for this. |
| """ |
| srcdoc = _html.escape(render_html(g), quote=True) |
| return (f'<iframe srcdoc="{srcdoc}" ' |
| f'style="width:100%;height:{height}px;border:0;background:#0a0e17" ' |
| f'sandbox="allow-scripts"></iframe>') |
|
|