diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/BUILD.bazel b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/BUILD.bazel index bfc097a3e50..942e155b4f3 100644 --- a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/BUILD.bazel +++ b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/BUILD.bazel @@ -1,7 +1,7 @@ -load("//devtools/tools:ng_module.bzl", "ng_module") load("@io_bazel_rules_sass//:defs.bzl", "sass_binary") -load("//devtools/tools:typescript.bzl", "ts_library", "ts_test_library") load("//devtools/tools:defaults.bzl", "karma_web_test_suite") +load("//devtools/tools:ng_module.bzl", "ng_module") +load("//devtools/tools:typescript.bzl", "ts_library", "ts_test_library") package(default_visibility = ["//:__subpackages__"]) @@ -20,10 +20,10 @@ ng_module( "injector-tree.component.html", ], deps = [ - ":injector_providers", ":injector_tree_fns", "//devtools/projects/ng-devtools/src/lib/devtools-tabs/dependency-injection:injector_tree_visualizer", "//devtools/projects/ng-devtools/src/lib/devtools-tabs/dependency-injection:resolution_path", + "//devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers", "//devtools/projects/ng-devtools/src/lib/vendor/angular-split", "//devtools/projects/protocol", "//packages/common", @@ -35,21 +35,6 @@ ng_module( ], ) -ng_module( - name = "injector_providers", - srcs = [ - "injector-providers.component.ts", - ], - deps = [ - "//devtools/projects/ng-devtools/src/lib/devtools-tabs/dependency-injection:resolution_path", - "//devtools/projects/protocol", - "//packages/animations", - "//packages/common", - "//packages/core", - "@npm//@angular/material", - ], -) - karma_web_test_suite( name = "test", deps = [ diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers.component.ts b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers.component.ts deleted file mode 100644 index 3653fc885ca..00000000000 --- a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers.component.ts +++ /dev/null @@ -1,205 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.dev/license - */ - -import {Component, computed, inject, input, signal} from '@angular/core'; -import {MatOption} from '@angular/material/core'; -import {MatFormField, MatLabel} from '@angular/material/form-field'; -import {MatIcon} from '@angular/material/icon'; -import {MatInput} from '@angular/material/input'; -import {MatSelect} from '@angular/material/select'; -import {MatTableModule} from '@angular/material/table'; -import {MatTooltip} from '@angular/material/tooltip'; -import {Events, MessageBus, SerializedInjector, SerializedProviderRecord} from 'protocol'; - -@Component({ - selector: 'ng-injector-providers', - template: ` -

Providers for {{ injector()?.name }}

- @if (injector()) { -
- - Search by token - - close - - - Search by type - - None - @for (type of providerTypes; track type) { - {{ $any(providerTypeToLabel)[type] }} - } - - - @if (visibleProviders().length > 0) { - - - - - - - - - - - - - - - - - - - -

Token

{{ provider.token }}

Type

- @if (provider.type === 'multi') { multi (x{{ provider.index.length }}) } @else { - {{ $any(providerTypeToLabel)[provider.type] }} - } -

Is View Provider

- {{ provider.isViewProvider ? 'check_circle' : 'cancel' }} -

- send -
- } -
- } - `, - styles: [ - ` - .select { - cursor: pointer; - } - - :host { - display: block; - padding: 16px; - } - - .form-field-spacer { - margin: 0 4px 0 4px; - } - - table { - width: 100%; - } - - .column-title { - margin: 0; - } - - tr.example-detail-row { - height: 0; - } - - .example-element-row td { - border-bottom-width: 0; - cursor: pointer; - } - - .example-element-detail { - overflow: hidden; - display: flex; - } - - .example-element-diagram { - min-width: 80px; - border: 2px solid black; - padding: 8px; - font-weight: lighter; - margin: 8px 0; - height: 104px; - } - - .example-element-symbol { - font-weight: bold; - font-size: 40px; - line-height: normal; - } - - .example-element-description { - padding: 16px; - } - - .example-element-description-attribution { - opacity: 0.5; - } - - :host-context(.dark-theme) { - .providers-title { - color: #ffffff; - } - } - `, - ], - imports: [ - MatTableModule, - MatIcon, - MatTooltip, - MatInput, - MatSelect, - MatFormField, - MatLabel, - MatOption, - ], -}) -export class InjectorProvidersComponent { - readonly injector = input.required(); - readonly providers = input([]); - - readonly searchToken = signal(''); - readonly searchType = signal(''); - readonly visibleProviders = computed(() => { - const searchToken = this.searchToken().toLowerCase(); - const searchType = this.searchType(); - - const predicates: ((provider: SerializedProviderRecord) => boolean)[] = []; - searchToken && - predicates.push((provider) => provider.token.toLowerCase().includes(searchToken)); - searchType && predicates.push((provider) => provider.type === searchType); - - return this.providers().filter((provider) => - predicates.every((predicate) => predicate(provider)), - ); - }); - - providerTypeToLabel = { - type: 'Type', - existing: 'useExisting', - factory: 'useFactory', - class: 'useClass', - value: 'useValue', - }; - - providerTypes = Object.keys(this.providerTypeToLabel); - - messageBus = inject>(MessageBus); - - select(row: SerializedProviderRecord) { - const {id, type, name} = this.injector(); - this.messageBus.emit('logProvider', [{id, type, name}, row]); - } - - get displayedColumns(): string[] { - if (this.injector()?.type === 'element') { - return ['token', 'type', 'isViewProvider', 'log']; - } - return ['token', 'type', 'log']; - } -} diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/BUILD.bazel b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/BUILD.bazel new file mode 100644 index 00000000000..31cd6c2b28e --- /dev/null +++ b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/BUILD.bazel @@ -0,0 +1,32 @@ +load("@io_bazel_rules_sass//:defs.bzl", "sass_binary") +load("//devtools/tools:ng_module.bzl", "ng_module") + +package(default_visibility = ["//visibility:public"]) + +sass_binary( + name = "injector_providers_component_styles", + src = "injector-providers.component.scss", + include_paths = [ + "external/npm/node_modules", + ], + deps = ["//devtools:material_sass_deps"], +) + +ng_module( + name = "injector-providers", + srcs = [ + "injector-providers.component.ts", + ], + angular_assets = [ + "injector-providers.component.html", + ":injector_providers_component_styles", + ], + deps = [ + "//devtools/projects/ng-devtools/src/lib/devtools-tabs/dependency-injection:resolution_path", + "//devtools/projects/protocol", + "//packages/animations", + "//packages/common", + "//packages/core", + "@npm//@angular/material", + ], +) diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/injector-providers.component.html b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/injector-providers.component.html new file mode 100644 index 00000000000..aa022c8ea8c --- /dev/null +++ b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/injector-providers.component.html @@ -0,0 +1,65 @@ +

Providers for {{ injector()?.name }}

+@if (injector()) { +
+
+ + Search by token + + close + + + Search by type + + None + @for (type of providerTypes; track type) { + {{ $any(providerTypeToLabel)[type] }} + } + + +
+ @if (visibleProviders().length > 0) { + + + + + + + + + + + + + + + + + + + +

Token

{{ provider.token }}

Type

+ @if (provider.type === 'multi') { + multi (x{{ provider.index.length }}) + } @else { + {{ $any(providerTypeToLabel)[provider.type] }} + } +

Is View Provider

+ {{ provider.isViewProvider ? 'check_circle' : 'cancel' }} +

+ send +
+ } +
+} diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/injector-providers.component.scss b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/injector-providers.component.scss new file mode 100644 index 00000000000..a5867686b19 --- /dev/null +++ b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/injector-providers.component.scss @@ -0,0 +1,89 @@ +@use '@angular/material' as mat; + +h2 { + font-size: 0.875rem; +} + +.select { + cursor: pointer; +} + +:host { + display: block; + padding: 16px; +} + +.filter { + display: flex; + gap: 0.5rem; + + mat-form-field { + @include mat.form-field-density(-5); + @include mat.form-field-overrides( + ( + container-text-size: 0.8rem, + outlined-label-text-size: 0.8rem, + ) + ); + + &:first-child { + flex: 1; + } + } +} + +table { + width: 100%; + --mat-table-row-item-label-text-size: 0.8rem; + --mat-table-header-container-height: 42px; + --mat-table-row-item-container-height: 42px; +} + +.column-title { + margin: 0; + font-size: 0.8rem; + font-weight: bold; +} + +tr.example-detail-row { + height: 0; +} + +.example-element-row td { + border-bottom-width: 0; + cursor: pointer; +} + +.example-element-detail { + overflow: hidden; + display: flex; +} + +.example-element-diagram { + min-width: 80px; + border: 2px solid black; + padding: 8px; + font-weight: lighter; + margin: 8px 0; + height: 104px; +} + +.example-element-symbol { + font-weight: bold; + font-size: 40px; + line-height: normal; +} + +.example-element-description { + padding: 16px; +} + +.example-element-description-attribution { + opacity: 0.5; +} + +:host-context(.dark-theme) { + .providers-title { + color: #ffffff; + } +} diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/injector-providers.component.ts b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/injector-providers.component.ts new file mode 100644 index 00000000000..1299a2c4ad5 --- /dev/null +++ b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/injector-providers.component.ts @@ -0,0 +1,77 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import {Component, computed, inject, input, signal} from '@angular/core'; +import {MatOption} from '@angular/material/core'; +import {MatFormField, MatLabel} from '@angular/material/form-field'; +import {MatIcon} from '@angular/material/icon'; +import {MatInput} from '@angular/material/input'; +import {MatSelect} from '@angular/material/select'; +import {MatTableModule} from '@angular/material/table'; +import {MatTooltip} from '@angular/material/tooltip'; +import {Events, MessageBus, SerializedInjector, SerializedProviderRecord} from 'protocol'; + +@Component({ + selector: 'ng-injector-providers', + templateUrl: './injector-providers.component.html', + styleUrl: './injector-providers.component.scss', + imports: [ + MatTableModule, + MatIcon, + MatTooltip, + MatInput, + MatSelect, + MatFormField, + MatLabel, + MatOption, + ], +}) +export class InjectorProvidersComponent { + readonly injector = input.required(); + readonly providers = input([]); + + readonly searchToken = signal(''); + readonly searchType = signal(''); + readonly visibleProviders = computed(() => { + const searchToken = this.searchToken().toLowerCase(); + const searchType = this.searchType(); + + const predicates: ((provider: SerializedProviderRecord) => boolean)[] = []; + searchToken && + predicates.push((provider) => provider.token.toLowerCase().includes(searchToken)); + searchType && predicates.push((provider) => provider.type === searchType); + + return this.providers().filter((provider) => + predicates.every((predicate) => predicate(provider)), + ); + }); + + providerTypeToLabel = { + type: 'Type', + existing: 'useExisting', + factory: 'useFactory', + class: 'useClass', + value: 'useValue', + }; + + providerTypes = Object.keys(this.providerTypeToLabel); + + messageBus = inject>(MessageBus); + + select(row: SerializedProviderRecord) { + const {id, type, name} = this.injector(); + this.messageBus.emit('logProvider', [{id, type, name}, row]); + } + + get displayedColumns(): string[] { + if (this.injector()?.type === 'element') { + return ['token', 'type', 'isViewProvider', 'log']; + } + return ['token', 'type', 'log']; + } +} diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-tree.component.html b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-tree.component.html index 45cbbaacb83..a044dc3676b 100644 --- a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-tree.component.html +++ b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-tree.component.html @@ -11,10 +11,14 @@ [disabled]="true" > - - Hide injectors with no providers - - Hide framework injectors +
+ + Hide injectors with no providers + + + Hide framework injectors + +
@@ -23,7 +27,7 @@

- Environment Hierarchy + Environment Hierarchy

- Element Hierarchy + Element Hierarchy