diff --git a/devtools/projects/ng-devtools/src/lib/application-operations/index.ts b/devtools/projects/ng-devtools/src/lib/application-operations/index.ts index ae00f791819f..dca0c90951f6 100644 --- a/devtools/projects/ng-devtools/src/lib/application-operations/index.ts +++ b/devtools/projects/ng-devtools/src/lib/application-operations/index.ts @@ -14,6 +14,8 @@ export abstract class ApplicationOperations { abstract selectDomElement(position: ElementPosition, target: Frame): void; abstract inspect(directivePosition: DirectivePosition, objectPath: string[], target: Frame): void; abstract inspectSignal(position: SignalNodePosition, target: Frame): void; + abstract setSignalBreakpoint(position: SignalNodePosition, target: Frame): void; + abstract removeSignalBreakpoint(position: SignalNodePosition, target: Frame): void; abstract viewSourceFromRouter(name: string, type: string, target: Frame): void; abstract setStorageItems(items: {[key: string]: unknown}): Promise; abstract getStorageItems(items: string[]): Promise<{[key: string]: unknown}>; diff --git a/devtools/projects/ng-devtools/src/lib/application-services/test-utils/app_operations_mock.ts b/devtools/projects/ng-devtools/src/lib/application-services/test-utils/app_operations_mock.ts index 7e3aff5a4550..eca8c2f8fa42 100644 --- a/devtools/projects/ng-devtools/src/lib/application-services/test-utils/app_operations_mock.ts +++ b/devtools/projects/ng-devtools/src/lib/application-services/test-utils/app_operations_mock.ts @@ -58,6 +58,14 @@ export class AppOperationsMock extends ApplicationOperations { throw new Error('Method not implemented.'); } + override setSignalBreakpoint(position: SignalNodePosition, target: Frame): void { + throw new Error('Method not implemented.'); + } + + override removeSignalBreakpoint(position: SignalNodePosition, target: Frame): void { + throw new Error('Method not implemented.'); + } + override viewSourceFromRouter(name: string, type: string, target: Frame): void { throw new Error('Method not implemented.'); } diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/signal-graph-pane/signal-graph-pane.component.html b/devtools/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/signal-graph-pane/signal-graph-pane.component.html index 8a58b84b2b1c..931e6ad4c7f1 100644 --- a/devtools/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/signal-graph-pane/signal-graph-pane.component.html +++ b/devtools/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/signal-graph-pane/signal-graph-pane.component.html @@ -14,7 +14,10 @@ [node]="node" [graph]="signalGraph.graph()!" [element]="signalGraph.element()!" + [hasBreakpoint]="hasBreakpoint(node)" (gotoSource)="gotoSource($event)" + (setBreakpoint)="setBreakpoint($event)" + (removeBreakpoint)="removeBreakpoint($event)" (expandCluster)="expandCluster($event)" (highlightDeps)="highlightDeps($event)" (close)="detailsVisible.set(false)" diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/signal-graph-pane/signal-graph-pane.component.ts b/devtools/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/signal-graph-pane/signal-graph-pane.component.ts index 87673a31e5cf..eb2ed8920ef9 100644 --- a/devtools/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/signal-graph-pane/signal-graph-pane.component.ts +++ b/devtools/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/signal-graph-pane/signal-graph-pane.component.ts @@ -86,6 +86,18 @@ export class SignalGraphPaneComponent { protected readonly detailsVisible = signal(false); + // Track active breakpoints for the current inspected element. + // Resets when the inspected element changes. + protected readonly activeBreakpoints = linkedSignal>({ + source: () => this.signalGraph.element(), + computation: () => new Set(), + }); + + protected hasBreakpoint(node: DevtoolsSignalGraphNode | undefined): boolean { + if (!node) return false; + return this.activeBreakpoints().has(node.id); + } + protected empty = computed(() => !(this.signalGraph.graph()?.nodes.length! > 0)); onNodeClick(node: DevtoolsSignalGraphNode) { @@ -104,6 +116,38 @@ export class SignalGraphPaneComponent { ); } + setBreakpoint(node: DevtoolsSignalGraphNode) { + const frame = this.frameManager.selectedFrame(); + this.appOperations.setSignalBreakpoint( + { + element: this.signalGraph.element()!, + signalId: node.id, + }, + frame!, + ); + this.activeBreakpoints.update((set) => { + const newSet = new Set(set); + newSet.add(node.id); + return newSet; + }); + } + + removeBreakpoint(node: DevtoolsSignalGraphNode) { + const frame = this.frameManager.selectedFrame(); + this.appOperations.removeSignalBreakpoint( + { + element: this.signalGraph.element()!, + signalId: node.id, + }, + frame!, + ); + this.activeBreakpoints.update((set) => { + const newSet = new Set(set); + newSet.delete(node.id); + return newSet; + }); + } + expandCluster(clusterId: string) { this.visualizer().expandCluster(clusterId); } diff --git a/devtools/projects/ng-devtools/src/lib/shared/signal-details/signal-details.component.html b/devtools/projects/ng-devtools/src/lib/shared/signal-details/signal-details.component.html index fb6e55b44e7e..f1e32ae76374 100644 --- a/devtools/projects/ng-devtools/src/lib/shared/signal-details/signal-details.component.html +++ b/devtools/projects/ng-devtools/src/lib/shared/signal-details/signal-details.component.html @@ -16,6 +16,17 @@ > code + } @else if (isClusterNode) {