Skip to content

perf(treemap): on-demand subtree fetch + visible directory labels#120

Merged
aksOps merged 1 commit into
mainfrom
perf/treemap-on-demand-subtree
May 5, 2026
Merged

perf(treemap): on-demand subtree fetch + visible directory labels#120
aksOps merged 1 commit into
mainfrom
perf/treemap-on-demand-subtree

Conversation

@aksOps
Copy link
Copy Markdown
Contributor

@aksOps aksOps commented May 5, 2026

Summary

Two related improvements to the dashboard treemap, building on the depth-8 cap shipped in v0.2.1:

Phase 2 — backend path-rooted subtree

Adds an optional `path` query parameter to `GET /api/file-tree` so the frontend can fetch a focused subtree instead of the whole tree. Cypher filters via `STARTS WITH path/`, the tree builder strips the prefix during walk so the local root represents the focused directory, and `@Cacheable` is keyed on path so different anchors are cached separately. Path inputs are normalized + validated in the controller (no `..`, no leading slash, ≤1024 chars).

Phase 3 — frontend on-demand drill

When the user clicks a directory rendered as a depth-cap leaf (type=directory, no children, nodeCount > 0), Dashboard fetches its subtree via the new path endpoint, splices the response into the in-memory tree at that node, and drills into it in the same gesture. A small loading indicator appears in the breadcrumb during the fetch. Concurrent clicks dedupe via a ref-tracked in-flight set; failures clear the flag so retries work.

UX fix — labels on directory cells

The design-system Treemap canvas only paints names on `isLeaf` cells (line 114 of its canvas paint), so directories at the visible drill level showed as unlabelled rectangles — names only appeared on hover. Dashboard now feeds the treemap a render-only flat copy of the focused level: directories are stripped of their children and given a pre-aggregated value so the canvas treats them as leaves and paints the label. The original TreemapNode (with intact children) stays in `focusedRoot` and is recovered via a `renderToOriginal` WeakMap in the click handler so drill-down keeps working.

Test plan

  • `mvn test -Dfrontend.skip=true` — 3706 / 3706 pass, 32 expected skips
  • `npm run build` — 197.47 kB / 63.02 kB gzip (+0.5 kB vs main)
  • 4 new `GraphControllerTest` cases: path passthrough, trailing-slash normalization, `..` traversal → 400, overlong path → 400
  • Deploy + verify treemap shows directory names by default
  • Manual: drill into a depth-8 truncated directory, observe subtree-loading indicator, confirm subtree appears and drill continues

🤖 Generated with Claude Code

Two related improvements to the dashboard treemap, building on the
depth-8 cap shipped in v0.2.1:

**Phase 2 — backend path-rooted subtree.** Adds an optional `path`
query parameter to `GET /api/file-tree` so the frontend can fetch
just a focused subtree instead of the whole tree. The Cypher query
filters by `STARTS WITH path/`, the tree builder strips the prefix
during walk so the local root represents the focused directory, and
`@Cacheable` is keyed on path so different anchors are cached
separately. Path inputs are normalized + validated in the controller
(no `..`, no leading slash, ≤1024 chars) before reaching the query
layer.

**Phase 3 — frontend on-demand drill.** When the user clicks a
directory rendered as a depth-cap leaf (type=directory, no children,
nodeCount > 0), Dashboard fetches its subtree via the new path
endpoint, splices the response into the in-memory tree at that node,
and drills into it in the same gesture. A small loading indicator
appears in the breadcrumb during the fetch. Concurrent clicks on the
same path dedupe via a ref-tracked in-flight set; failures clear the
flag so retries work.

**UX fix — labels on directory cells.** The design-system Treemap
canvas only paints names on `isLeaf` cells, so directories at the
visible drill level rendered as unlabelled rectangles (names only
appeared on hover). Dashboard now feeds the treemap a render-only
flat copy of the focused level — directories are stripped of their
children and given a pre-aggregated value so the canvas treats them
as leaves and paints the label, while the original TreemapNode
(with intact children) stays in `focusedRoot` and is recovered via
a `renderToOriginal` WeakMap in the click handler so drill-down
keeps working.

Test plan:
- mvn test (3706 / 3706 pass; 32 expected skips)
- npm run build (197.47 kB / 63.02 kB gzip — +0.5 kB vs main)
- 4 new GraphControllerTest cases covering path passthrough,
  trailing-slash normalization, `..` traversal rejection, overlong
  path rejection
- Manual: deploy + verify treemap shows directory names by default,
  drill into a depth-8 truncated directory triggers a fetch and
  shows children

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@aksOps aksOps enabled auto-merge (squash) May 5, 2026 03:32
@aksOps aksOps merged commit f7e792e into main May 5, 2026
13 checks passed
@aksOps aksOps deleted the perf/treemap-on-demand-subtree branch May 5, 2026 03:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant