commit fbf864b32f697fe4f46caf44299522b64a399f17
parent 853c01f05eb699a038ebd4633ed23b0ca3c68c4d
Author: Andy Khramtsov <>
Date: Sun, 31 May 2026 15:13:24 +0300
feat: add subtree toggle
Diffstat:
1 file changed, 31 insertions(+), 7 deletions(-)
diff --git a/src/rsdeps/pages/home.py b/src/rsdeps/pages/home.py
@@ -30,23 +30,28 @@ class ids:
recalculate_button: str = "recalculate-button"
generate_button: str = "generate-button"
- dependency_graph: str = "dependency-graph"
reset_highlight_button: str = "reset-highlight-button"
+ toggles: str = "toggles"
+ dependency_graph: str = "dependency-graph"
selected_node_details: str = "selected-node-details"
cache_store: str = "cache-store"
selected_node_store: str = "selected-node-store"
+class toggle_values:
+ subtree: str = "subtree"
+
+
class colors:
background: str = "#FAFAFA"
outline: str = "#FFFFFF"
- outline_highlight: str = "#808080"
+ outline_highlight: str = "#8080B0"
node: str = "#B0D0F0"
node_main: str = "#F080A0"
node_faint: str = "#E0E0E0"
line: str = "#B0B0B0"
- line_highlight: str = "#808080"
+ line_highlight: str = "#8080B0"
line_faint: str = "#E0E0E0"
text: str = "#202020"
text_faint: str = "#B0B0B0"
@@ -239,6 +244,12 @@ def layout():
id=ids.reset_highlight_button,
children="Deselect",
),
+ dcc.Checklist(
+ id=ids.toggles,
+ inline=True,
+ persistence=True,
+ options=[dict(label="Subtree", value=toggle_values.subtree)],
+ ),
],
),
html.Div(
@@ -439,6 +450,7 @@ def draw_graph_figure(
positions: dict[str, tuple[float, float]],
adjacency_list: dict[str, set[str]],
selected_node=None,
+ subtree: bool = False,
) -> go.Figure:
highlight_nodes = set()
if selected_node and selected_node in adjacency_list:
@@ -709,7 +721,7 @@ def display_cargo_lock_packages(inputs, state):
),
prevent_initial_call=True,
)
-def generate(inputs, state):
+def graph_generate(inputs, state):
if not state["cargo_lock"]:
raise PreventUpdate
try:
@@ -754,6 +766,7 @@ def generate(inputs, state):
),
dict(
click_data=Input(ids.dependency_graph, "clickData"),
+ toggles=Input(ids.toggles, "value"),
reset_highlight_button=Input(ids.reset_highlight_button, "n_clicks"),
),
dict(
@@ -763,7 +776,7 @@ def generate(inputs, state):
),
prevent_initial_call=True,
)
-def update(inputs, state):
+def graph_update(inputs, state):
if (
not state["cache"]
or state["cache"].get("positions") is None
@@ -775,13 +788,24 @@ def update(inputs, state):
if ctx.triggered_id and ctx.triggered_id == ids.reset_highlight_button:
selected = None
- elif inputs["click_data"] and "points" in inputs["click_data"]:
+ elif (
+ ctx.triggered_id
+ and ctx.triggered_id == ids.dependency_graph
+ and inputs["click_data"]
+ and "points" in inputs["click_data"]
+ ):
point = inputs["click_data"]["points"][0]
selected = point.get("customdata", None)
else:
selected = None
+
if state["selected_node_store"] and state["selected_node_store"].get("selected") == selected:
selected = None
+ elif selected is None:
+ selected = state["selected_node_store"].get("selected")
+
+ toggles = inputs["toggles"] or []
+ subtree = toggle_values.subtree in toggles
positions = state["cache"]["positions"]
adjacency_list = unwrap_adjacency_list(state["cache"]["adjacency_list"])
@@ -803,7 +827,7 @@ def update(inputs, state):
old_fig = state["figure"]
uirevision = old_fig.get("layout", {}).get("uirevision", 0)
- fig = draw_graph_figure(df_graph, positions, adjacency_list, selected)
+ fig = draw_graph_figure(df_graph, positions, adjacency_list, selected, subtree)
fig.update_layout(uirevision=uirevision)
return dict(