From 3b150c785822a2da1a16e663c754caa37b3cc2c1 Mon Sep 17 00:00:00 2001 From: Nicola Vitucci Date: Wed, 30 Apr 2025 15:27:08 +0100 Subject: [PATCH 1/8] Add screenshot and zoom buttons --- python-wrapper/src/neo4j_viz/nvl.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/python-wrapper/src/neo4j_viz/nvl.py b/python-wrapper/src/neo4j_viz/nvl.py index ca1a0f5f..bfddd628 100644 --- a/python-wrapper/src/neo4j_viz/nvl.py +++ b/python-wrapper/src/neo4j_viz/nvl.py @@ -56,8 +56,14 @@ def render( hover_element = "null" hover_div = "" + # Using a different varname for every instance, so that a notebook + # can use several instances without unwanted interactions. + # The first part of the UUID should be "unique enough" in this context. + nvl_varname = "graph_" + container_id.split("-")[0] + download_name = nvl_varname + ".png" + js_code = f""" - var myNvl = new NVLBase.NVL( + var {nvl_varname} = new NVLBase.NVL( document.getElementById('{container_id}'), {hover_element}, {nodes_json}, @@ -66,7 +72,23 @@ def render( ); """ full_code = self.library_code + js_code + + # Although a ` +
+ + +
{hover_div}
+ """ + return HTML(html_output) # type: ignore[no-untyped-call] diff --git a/python-wrapper/src/neo4j_viz/resources/screenshot.svg b/python-wrapper/src/neo4j_viz/resources/screenshot.svg new file mode 100644 index 00000000..bb430762 --- /dev/null +++ b/python-wrapper/src/neo4j_viz/resources/screenshot.svg @@ -0,0 +1,3 @@ + + + diff --git a/python-wrapper/src/neo4j_viz/resources/styles.css b/python-wrapper/src/neo4j_viz/resources/styles.css new file mode 100644 index 00000000..053d0837 --- /dev/null +++ b/python-wrapper/src/neo4j_viz/resources/styles.css @@ -0,0 +1,28 @@ +:root, +:root.light { + --button-hover-bg-color: #f3f3f3; + --button-active-bg-color: #d3d3d3; + --text-color: #4D5157; +} + +:root.dark { + --button-hover-bg-color: #5b5b5b; + --button-active-bg-color: #8c8c8c; + --text-color: #d2d2d2; +} + +button.icon { + stroke: var(--text-color); + background-color: inherit; + padding: .4rem .41rem .19rem 0.41rem; + border: 1.3px solid #bcbcbc; + border-radius: 10px; +} + +button.icon:hover { + background-color: var(--button-hover-bg-color) +} + +button.icon:active { + background-color: var(--button-active-bg-color) +} diff --git a/python-wrapper/src/neo4j_viz/resources/zoom-in.svg b/python-wrapper/src/neo4j_viz/resources/zoom-in.svg new file mode 100644 index 00000000..f18170b9 --- /dev/null +++ b/python-wrapper/src/neo4j_viz/resources/zoom-in.svg @@ -0,0 +1,3 @@ + + + diff --git a/python-wrapper/src/neo4j_viz/resources/zoom-out.svg b/python-wrapper/src/neo4j_viz/resources/zoom-out.svg new file mode 100644 index 00000000..e736a492 --- /dev/null +++ b/python-wrapper/src/neo4j_viz/resources/zoom-out.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file From 6e8390f78e24f86cb2d0e2888ff3e16d5e8d6ee6 Mon Sep 17 00:00:00 2001 From: Adam Schill Collberg Date: Fri, 9 May 2025 17:29:24 +0200 Subject: [PATCH 4/8] Refactor and improve button styling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Florentin Dörre --- python-wrapper/src/neo4j_viz/nvl.py | 54 +++++++++---------- .../resources/{ => icons}/screenshot.svg | 0 .../resources/{ => icons}/zoom-in.svg | 0 .../resources/{ => icons}/zoom-out.svg | 0 .../src/neo4j_viz/resources/styles.css | 28 ---------- 5 files changed, 26 insertions(+), 56 deletions(-) rename python-wrapper/src/neo4j_viz/resources/{ => icons}/screenshot.svg (100%) rename python-wrapper/src/neo4j_viz/resources/{ => icons}/zoom-in.svg (100%) rename python-wrapper/src/neo4j_viz/resources/{ => icons}/zoom-out.svg (100%) delete mode 100644 python-wrapper/src/neo4j_viz/resources/styles.css diff --git a/python-wrapper/src/neo4j_viz/nvl.py b/python-wrapper/src/neo4j_viz/nvl.py index 05643b86..e4800c74 100644 --- a/python-wrapper/src/neo4j_viz/nvl.py +++ b/python-wrapper/src/neo4j_viz/nvl.py @@ -19,10 +19,27 @@ def __init__(self) -> None: nvl_entry_point = resource_folder / "nvl_entrypoint" js_path = nvl_entry_point / "base.js" - with js_path.open("r", encoding="utf-8") as file: self.library_code = file.read() + styles_path = nvl_entry_point / "styles.css" + with styles_path.open("r", encoding="utf-8") as file: + self.styles = file.read() + + icons = resource_folder / "icons" + + zoom_in_path = icons / "zoom-in.svg" + with zoom_in_path.open("r", encoding="utf-8") as file: + self.zoom_in_svg = file.read() + + zoom_out_path = icons / "zoom-out.svg" + with zoom_out_path.open("r", encoding="utf-8") as file: + self.zoom_out_svg = file.read() + + screenshot_path = icons / "screenshot.svg" + with screenshot_path.open("r", encoding="utf-8") as file: + self.screenshot_svg = file.read() + def unsupported_field_type_error(self, e: TypeError, entity: str) -> Exception: if "not JSON serializable" in str(e): return ValueError(f"A field of a {entity} object is not supported: {str(e)}") @@ -51,7 +68,7 @@ def render( if show_hover_tooltip: hover_element = f"document.getElementById('{container_id}-tooltip')" - hover_div = f'' + hover_div = f'