commit 7f48eba36823231f96fdc606f025caa35219c816
parent e5f295ca7831ce47a57f0dd4975764bfe27dd620
Author: Andy Khramtsov <>
Date: Sat, 30 May 2026 04:53:42 +0300
docs: add ui docs
Diffstat:
3 files changed, 111 insertions(+), 49 deletions(-)
diff --git a/src/deps/aio_components/collapse_aio.py b/src/deps/aio_components/collapse_aio.py
@@ -57,11 +57,25 @@ class CollapseAIO(html.Div):
ids = ids
- def __init__(self, aio_id=None, label="Collapse", content=None, default_hidden: bool = False):
+ def __init__(
+ self,
+ aio_id=None,
+ label="Collapse",
+ content=None,
+ default_hidden: bool = False,
+ button_wrapper=None,
+ ):
if content is None:
content = []
if aio_id is None:
aio_id = str(uuid.uuid4())
+
+ button = dcc.Button(
+ id=self.ids.button(aio_id),
+ className="collapse-button",
+ children=[html.Div(id=self.ids.arrow(aio_id), className="collapse-button__arrow-right"), label],
+ )
+
super().__init__(
children=[
dcc.Store(
@@ -70,11 +84,7 @@ class CollapseAIO(html.Div):
data={"default_hidden": default_hidden},
),
dcc.Store(id=self.ids.store(aio_id), storage_type="local", data={}),
- dcc.Button(
- id=self.ids.button(aio_id),
- className="collapse-button",
- children=[html.Div(id=self.ids.arrow(aio_id), className="collapse-button__arrow-right"), label],
- ),
+ button if button_wrapper is None else button_wrapper(button),
html.Div(
id=self.ids.content(aio_id),
className="",
diff --git a/src/deps/dash_app.py b/src/deps/dash_app.py
@@ -30,7 +30,7 @@ def main():
html.Div(
className="horizontal-content horizontal-content_large-gap",
children=[
- html.Div(children="Dash App"),
+ html.Div(children="Cargo.lock visualizer"),
html.Div(
className="horizontal-content",
children=[
diff --git a/src/deps/pages/home.py b/src/deps/pages/home.py
@@ -80,44 +80,61 @@ def layout():
return html.Div(
className="padded-box vertical-content vertical-content_large-gap",
children=[
- html.H2("Cargo dependency visualisation"),
dcc.Store(id=ids.cache_store, storage_type="memory"),
dcc.Store(id=ids.selected_node_store, storage_type="memory"),
html.Div(
+ className="horizontal-content horizontal-content_center",
+ children=[
+ html.H2("Cargo dependency visualisation"),
+ html.Abbr(
+ "?",
+ title="Upload Cargo.lock and optionally Cargo.toml to see the full dependency graph. "
+ "Multiple select avaliable for file upload. Or just paste the contents into the fields.\n\n"
+ "It is possible to render the dependency graph of many projects because there is "
+ "only one Cargo.lock.\n\n"
+ "Note: Cargo.toml is only used for coloring [dependencies]. "
+ "The implementation of Cargo.toml parsing is primitive, it will not work on many projects. "
+ "But it is only the coloring feature, the graph is still fun to see.\n\n"
+ "Text fields are used as storage and the source of truth, they persist data in local storage.",
+ className="help-icon",
+ ),
+ ],
+ ),
+ html.Div(
className="vertical-content",
children=[
dcc.Upload(
className="button",
id=ids.upload_files,
children=[
- "Upload Cargo.toml and Cargo.lock",
+ "Upload Cargo.lock and optionally Cargo.toml",
],
multiple=True,
),
- html.Div("Cargo.toml:"),
+ html.Div("Cargo.lock (required):"),
dcc.Textarea(
- id=ids.cargo_toml_textarea,
- placeholder="Cargo.toml contents",
+ id=ids.cargo_lock_textarea,
+ placeholder="Cargo.lock contents",
persistence=True,
),
html.Div(
html.Button(
className="button",
- id=ids.cargo_toml_clear,
- children="Clear Cargo.toml",
+ id=ids.cargo_lock_clear,
+ children="Clear Cargo.lock",
),
),
- html.Div("Cargo.lock:"),
+ html.Div("Cargo.toml (optional):"),
dcc.Textarea(
- id=ids.cargo_lock_textarea,
- placeholder="Cargo.lock contents",
+ id=ids.cargo_toml_textarea,
+ placeholder="Cargo.toml contents",
persistence=True,
),
html.Div(
html.Button(
className="button",
- id=ids.cargo_lock_clear,
- children="Clear Cargo.lock",
+ id=ids.cargo_toml_clear,
+ children="Clear Cargo.toml",
),
),
],
@@ -126,42 +143,77 @@ def layout():
aio_id=ids.collapse_tables,
label="Table view",
default_hidden=True,
+ button_wrapper=lambda button: html.Div(
+ className="horizontal-content horizontal-content_center",
+ children=[
+ button,
+ html.Abbr(
+ "?",
+ title="Cargo.toml and Cargo.lock dataframes in table form.\n"
+ "This is what gets rendered into the graph below.",
+ className="help-icon",
+ ),
+ ],
+ ),
content=[
- html.Button(
- className="button",
- id=ids.recalculate_button,
- children="Recalculate",
- ),
- html.H3("Cargo toml dependencies"),
- TableAIO(
- aio_id=ids.cargo_toml_table,
- column_defs=[
- {"field": i, "colId": i}
- for i in [
- "name",
- ]
- ],
- ),
- html.H3("Cargo lock packages"),
- TableAIO(
- aio_id=ids.cargo_lock_table,
- column_defs=[
- {"field": i, "colId": i}
- for i in [
- "name",
- "version",
- "source",
- "checksum",
- "dependencies",
- ]
+ html.Div(
+ className="vertical-content",
+ children=[
+ html.Button(
+ className="button",
+ id=ids.recalculate_button,
+ children="Recalculate",
+ ),
+ html.H3("Cargo toml dependencies"),
+ TableAIO(
+ aio_id=ids.cargo_toml_table,
+ column_defs=[
+ {"field": i, "colId": i}
+ for i in [
+ "name",
+ ]
+ ],
+ ),
+ html.H3("Cargo lock packages"),
+ TableAIO(
+ aio_id=ids.cargo_lock_table,
+ column_defs=[
+ {"field": i, "colId": i}
+ for i in [
+ "name",
+ "version",
+ "source",
+ "checksum",
+ "dependencies",
+ ]
+ ],
+ ),
],
- ),
+ )
],
),
html.Div(
className="vertical-content",
children=[
- html.H3("Dependency graph"),
+ html.Div(
+ className="horizontal-content horizontal-content_center",
+ children=[
+ html.H3("Dependency graph"),
+ html.Abbr(
+ "?",
+ title="Click on 'Generate' to generate Cargo.lock graph (it is normal for it to take "
+ "some time).\n\n"
+ "Graph is Left-to-Right, meaning nodes (packages) to the right are dependencies of "
+ "nodes (packages) to the left, if they are connected with an arc (edge).\n"
+ "Or you can think of the graph as if all the edges are directed only to the right or "
+ "only to the left, it doesn't matter.\n\n"
+ "Click on any node to see its neighbors. Click it again to deselect, or use the "
+ "'Deselect' button.\n\n"
+ "Packages from [dependencies] in Cargo.toml are colored red.",
+ className="help-icon",
+ ),
+ ],
+ ),
html.Div(
className="horizontal-content horizontal-content_small-gap",
children=[
@@ -173,7 +225,7 @@ def layout():
html.Button(
className="button",
id=ids.reset_highlight_button,
- children="Reset highlight",
+ children="Deselect",
),
],
),