From 4fa3b2673e7390e304f75e4e7004dcd09001d0db Mon Sep 17 00:00:00 2001 From: AleksanderBodurri Date: Sun, 7 Sep 2025 21:17:02 -0400 Subject: [PATCH] feat(devtools): display provider count on injector tree nodes (#63632) Allows the tree visualizer to display a sublabel for each node. Used by the injector tree to display provider count for each injector. PR Close #63632 --- .../devtools-tabs/injector-tree/injector-tree-fns.ts | 6 ++++++ .../tree-visualizer/tree-visualizer.component.scss | 12 ++++++++++++ .../lib/shared/tree-visualizer/tree-visualizer.ts | 9 +++++++++ 3 files changed, 27 insertions(+) diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-tree-fns.ts b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-tree-fns.ts index 7fca041d9a8..3ccd4bbd9f9 100644 --- a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-tree-fns.ts +++ b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-tree-fns.ts @@ -154,6 +154,12 @@ export function transformInjectorResolutionPathsIntoTree( injector, children: [], }; + + if (injector.providers !== undefined) { + const providerText = injector.providers === 1 ? 'Provider' : 'Providers'; + next.subLabel = `${injector.providers} ${providerText}`; + } + next.injector.node = injectorIdToNode.get(next.injector.id); currentLevel.push(next); currentLevel = next.children; diff --git a/devtools/projects/ng-devtools/src/lib/shared/tree-visualizer/tree-visualizer.component.scss b/devtools/projects/ng-devtools/src/lib/shared/tree-visualizer/tree-visualizer.component.scss index bd008944cfd..ed21b151cf2 100644 --- a/devtools/projects/ng-devtools/src/lib/shared/tree-visualizer/tree-visualizer.component.scss +++ b/devtools/projects/ng-devtools/src/lib/shared/tree-visualizer/tree-visualizer.component.scss @@ -17,6 +17,18 @@ background: var(--primary-contrast); } + .sub-label { + background-color: #fff; + padding: 1px 4px; + bottom: -8px; + right: -2px; + font-size: 14px; + position: absolute; + border-radius: 50px; + color: #000; + outline: 1px solid #000; + } + .arrow { fill: var(--full-contrast); } diff --git a/devtools/projects/ng-devtools/src/lib/shared/tree-visualizer/tree-visualizer.ts b/devtools/projects/ng-devtools/src/lib/shared/tree-visualizer/tree-visualizer.ts index 4a171c9d03f..2497e1d5b4f 100644 --- a/devtools/projects/ng-devtools/src/lib/shared/tree-visualizer/tree-visualizer.ts +++ b/devtools/projects/ng-devtools/src/lib/shared/tree-visualizer/tree-visualizer.ts @@ -18,6 +18,7 @@ const RESIZE_OBSERVER_DEBOUNCE = 250; export interface TreeNode { label: string; + subLabel?: string; children: TreeNode[]; } @@ -270,6 +271,7 @@ export class TreeVisualizer extends GraphRenderer .attr('y', -halfLabelHeight) .append('xhtml:div') .attr('class', 'node') + .style('position', 'relative') .text((node: TreeD3Node) => { const label = node.data.label; return label.length > MAX_NODE_LABEL_LENGTH @@ -277,6 +279,13 @@ export class TreeVisualizer extends GraphRenderer : label; }); + d3Node.each(function (node: TreeD3Node) { + const subLabel = node.data.subLabel; + if (subLabel) { + d3.select(this).append('div').attr('class', 'sub-label').text(subLabel); + } + }); + this.config.d3NodeModifier(d3Node); svg.attr('height', '100%').attr('width', '100%');