File tree Expand file tree Collapse file tree
python-wrapper/src/neo4j_viz Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -28,30 +28,23 @@ def _load_template() -> str:
2828
2929
3030class NVL :
31- """HTML fallback renderer for standalone HTML / Streamlit.
32-
33- Uses the same Vite-built HTML template as the dev harness (index.html).
34- Python injects graph data via window.__NEO4J_VIZ_DATA__ — no blob URLs,
35- no manual JS/CSS inlining.
36- """
37-
3831 def __init__ (self ) -> None :
3932 self ._template = _load_template ()
4033
4134 def render (
4235 self ,
4336 nodes : list [Node ],
4437 relationships : list [Relationship ],
38+ render_options : dict [str , object ] | None ,
4539 width : str ,
4640 height : str ,
47- options : dict [str , object ] | None = None ,
4841 ) -> HTML :
4942 data_dict : dict [str , object ] = {
5043 "nodes" : [_serialize_entity (node ) for node in nodes ],
5144 "relationships" : [_serialize_entity (rel ) for rel in relationships ],
5245 "width" : width ,
5346 "height" : height ,
54- "options" : options or {},
47+ "options" : render_options or {},
5548 }
5649 data_json = json .dumps (data_dict )
5750 container_id = f"neo4j-viz-{ uuid .uuid4 ().hex [:12 ]} "
Original file line number Diff line number Diff line change 1717 LayoutOptions ,
1818 Renderer ,
1919 RenderOptions ,
20+ construct_layout_options ,
2021)
2122from .relationship import Relationship
2223from .widget import GraphWidget
@@ -106,12 +107,22 @@ def _build_js_options(
106107
107108 Renderer .check (renderer , num_nodes )
108109
110+ if not layout :
111+ layout = Layout .FORCE_DIRECTED
112+ if not layout_options :
113+ layout_options = {}
114+
115+ if isinstance (layout_options , dict ):
116+ layout_options_typed = construct_layout_options (layout , layout_options )
117+ else :
118+ layout_options_typed = layout_options
119+
109120 render_options = RenderOptions (
110121 layout = layout ,
111- layout_options = layout_options if not isinstance ( layout_options , dict ) else None ,
122+ layout_options = layout_options_typed ,
112123 renderer = renderer ,
113- pan_X = pan_position [0 ] if pan_position else None ,
114- pan_Y = pan_position [1 ] if pan_position else None ,
124+ pan_X = pan_position [0 ] if pan_position is not None else None ,
125+ pan_Y = pan_position [1 ] if pan_position is not None else None ,
115126 initial_zoom = initial_zoom ,
116127 min_zoom = min_zoom ,
117128 max_zoom = max_zoom ,
@@ -178,9 +189,9 @@ def render(
178189 return NVL ().render (
179190 self .nodes ,
180191 self .relationships ,
192+ js_options ,
181193 width ,
182194 height ,
183- options = js_options ,
184195 )
185196
186197 def render_widget (
Original file line number Diff line number Diff line change 1212
1313
1414def _serialize_entity (entity : Union [Node , Relationship ]) -> dict [str , object ]:
15+ """Convert a Node or Relationship to a JSON-serializable dict.
16+
17+ Returns a dict (not a JSON string) because traitlets.List expects Python objects,
18+ not pre-serialized strings. Traitlets handles JSON serialization for transport to JS.
19+ See: https://traitlets.readthedocs.io/en/stable/config.html#serializing-values
20+ """
1521 try :
1622 entity_dict = entity .to_dict ()
1723 # Verify it's JSON-serializable
You can’t perform that action at this time.
0 commit comments