diff --git a/projects/components/src/list-view/list-view-value-renderer.directive.ts b/projects/components/src/list-view/list-view-value-renderer.directive.ts new file mode 100644 index 000000000..040fd4323 --- /dev/null +++ b/projects/components/src/list-view/list-view-value-renderer.directive.ts @@ -0,0 +1,12 @@ +import { Directive, TemplateRef } from '@angular/core'; + +@Directive({ + selector: '[htListViewValueRenderer]' +}) +export class ListViewValueRendererDirective { + public constructor(private readonly templateRef: TemplateRef) {} + + public getTemplateRef(): TemplateRef { + return this.templateRef; + } +} diff --git a/projects/components/src/list-view/list-view.component.scss b/projects/components/src/list-view/list-view.component.scss index e52468408..cbc523154 100644 --- a/projects/components/src/list-view/list-view.component.scss +++ b/projects/components/src/list-view/list-view.component.scss @@ -1,8 +1,7 @@ -@import 'font'; -@import 'color-palette'; +@import 'mixins'; $key-width: 40%; -$value-width: 60%; +$value-width: auto; $horizontal-offset: 12px; @mixin grid-view { diff --git a/projects/components/src/list-view/list-view.component.test.ts b/projects/components/src/list-view/list-view.component.test.ts index f4343f829..8678b0755 100644 --- a/projects/components/src/list-view/list-view.component.test.ts +++ b/projects/components/src/list-view/list-view.component.test.ts @@ -1,6 +1,8 @@ import { CommonModule } from '@angular/common'; import { Component } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { NavigationService } from '@hypertrace/common'; +import { mockProvider } from '@ngneat/spectator/jest'; import { ListViewComponent, ListViewHeader, ListViewRecord } from './list-view.component'; describe('List View Component', () => { @@ -32,7 +34,8 @@ describe('List View Component', () => { beforeEach(() => { TestBed.configureTestingModule({ declarations: [TestHostComponent, ListViewComponent], - imports: [CommonModule] + imports: [CommonModule], + providers: [mockProvider(NavigationService)] }); fixture = TestBed.createComponent(TestHostComponent); diff --git a/projects/components/src/list-view/list-view.component.ts b/projects/components/src/list-view/list-view.component.ts index a25c37bca..58cf8e8d1 100644 --- a/projects/components/src/list-view/list-view.component.ts +++ b/projects/components/src/list-view/list-view.component.ts @@ -1,10 +1,13 @@ -import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; - +import { ChangeDetectionStrategy, Component, ContentChild, Input } from '@angular/core'; +import { ListViewValueRendererDirective } from './list-view-value-renderer.directive'; @Component({ selector: 'ht-list-view', styleUrls: ['./list-view.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, template: ` + {{ record.value }}
@@ -19,7 +22,12 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; {{ record.key }}
- {{ record.value }} +
@@ -31,6 +39,9 @@ export class ListViewComponent { @Input() public records?: ListViewRecord[]; + + @ContentChild(ListViewValueRendererDirective) + public valueRenderer?: ListViewValueRendererDirective; } export interface ListViewHeader { diff --git a/projects/components/src/list-view/list-view.module.ts b/projects/components/src/list-view/list-view.module.ts index 60e655c20..6d71b637b 100644 --- a/projects/components/src/list-view/list-view.module.ts +++ b/projects/components/src/list-view/list-view.module.ts @@ -1,10 +1,11 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; +import { ListViewValueRendererDirective } from './list-view-value-renderer.directive'; import { ListViewComponent } from './list-view.component'; @NgModule({ - declarations: [ListViewComponent], - exports: [ListViewComponent], + declarations: [ListViewComponent, ListViewValueRendererDirective], + exports: [ListViewComponent, ListViewValueRendererDirective], imports: [CommonModule] }) export class ListViewModule {} diff --git a/projects/components/src/public-api.ts b/projects/components/src/public-api.ts index 8bbf6d651..a8bd27c84 100644 --- a/projects/components/src/public-api.ts +++ b/projects/components/src/public-api.ts @@ -167,8 +167,8 @@ export * from './link/link.component'; export * from './link/link.module'; // List View -export { ListViewComponent, ListViewHeader, ListViewRecord } from './list-view/list-view.component'; -export { ListViewModule } from './list-view/list-view.module'; +export * from './list-view/list-view.component'; +export * from './list-view/list-view.module'; // Load Async export { LoadAsyncDirective } from './load-async/load-async.directive'; diff --git a/projects/observability/src/shared/components/span-detail/span-detail.component.test.ts b/projects/observability/src/shared/components/span-detail/span-detail.component.test.ts index 430205f59..22b8fb71c 100644 --- a/projects/observability/src/shared/components/span-detail/span-detail.component.test.ts +++ b/projects/observability/src/shared/components/span-detail/span-detail.component.test.ts @@ -1,20 +1,14 @@ -import { HttpClientTestingModule } from '@angular/common/http/testing'; import { fakeAsync } from '@angular/core/testing'; -import { IconLibraryTestingModule } from '@hypertrace/assets-library'; -import { NavigationService } from '@hypertrace/common'; -import { createHostFactory, mockProvider, Spectator } from '@ngneat/spectator/jest'; +import { createHostFactory, Spectator } from '@ngneat/spectator/jest'; import { SpanData } from './span-data'; import { SpanDetailComponent } from './span-detail.component'; -import { SpanDetailModule } from './span-detail.module'; describe('Span detail component', () => { let spectator: Spectator; const createHost = createHostFactory({ component: SpanDetailComponent, - imports: [SpanDetailModule, HttpClientTestingModule, IconLibraryTestingModule], - declareComponent: false, - providers: [mockProvider(NavigationService)] + shallow: true }); test('should display child components', () => { diff --git a/projects/observability/src/shared/components/span-detail/tags/span-tags-detail.component.scss b/projects/observability/src/shared/components/span-detail/tags/span-tags-detail.component.scss index d2275d916..15f2032c4 100644 --- a/projects/observability/src/shared/components/span-detail/tags/span-tags-detail.component.scss +++ b/projects/observability/src/shared/components/span-detail/tags/span-tags-detail.component.scss @@ -7,4 +7,19 @@ height: 100%; width: 100%; overflow: auto; + + .tag-value { + width: 100%; + display: grid; + grid-template-columns: auto min-content; + + .filter-link { + visibility: hidden; + margin-left: 12px; + } + + &:hover .filter-link { + visibility: visible; + } + } } diff --git a/projects/observability/src/shared/components/span-detail/tags/span-tags-detail.component.test.ts b/projects/observability/src/shared/components/span-detail/tags/span-tags-detail.component.test.ts index 0a9e12601..5a4528f6b 100644 --- a/projects/observability/src/shared/components/span-detail/tags/span-tags-detail.component.test.ts +++ b/projects/observability/src/shared/components/span-detail/tags/span-tags-detail.component.test.ts @@ -1,7 +1,6 @@ import { CommonModule } from '@angular/common'; import { HttpClientTestingModule } from '@angular/common/http/testing'; -import { createHostFactory, Spectator } from '@ngneat/spectator/jest'; - +import { MemoizeModule } from '@hypertrace/common'; import { JsonViewerModule, LabelModule, @@ -10,6 +9,10 @@ import { LoadAsyncModule, ToggleButtonModule } from '@hypertrace/components'; +import { createHostFactory, mockProvider, Spectator } from '@ngneat/spectator/jest'; +import { MockComponent } from 'ng-mocks'; +import { ExplorerService } from '../../../../pages/explorer/explorer-service'; +import { ExploreFilterLinkComponent } from '../../explore-filter-link/explore-filter-link.component'; import { SpanTagsDetailComponent } from './span-tags-detail.component'; describe('Span Tags Detail Component', () => { @@ -24,8 +27,11 @@ describe('Span Tags Detail Component', () => { JsonViewerModule, LabelModule, LoadAsyncModule, - HttpClientTestingModule - ] + HttpClientTestingModule, + MemoizeModule + ], + declarations: [MockComponent(ExploreFilterLinkComponent)], + providers: [mockProvider(ExplorerService)] }); test('should display tag records', () => { diff --git a/projects/observability/src/shared/components/span-detail/tags/span-tags-detail.component.ts b/projects/observability/src/shared/components/span-detail/tags/span-tags-detail.component.ts index 3d42eaa2b..cae342b35 100644 --- a/projects/observability/src/shared/components/span-detail/tags/span-tags-detail.component.ts +++ b/projects/observability/src/shared/components/span-detail/tags/span-tags-detail.component.ts @@ -1,8 +1,10 @@ import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'; -import { Dictionary, TypedSimpleChanges } from '@hypertrace/common'; -import { ListViewRecord } from '@hypertrace/components'; +import { Dictionary, NavigationParams, TypedSimpleChanges } from '@hypertrace/common'; +import { FilterOperator, ListViewRecord } from '@hypertrace/components'; import { isNil } from 'lodash-es'; import { EMPTY, Observable, of } from 'rxjs'; +import { ExplorerService } from '../../../../pages/explorer/explorer-service'; +import { ScopeQueryParam } from '../../../../pages/explorer/explorer.component'; @Component({ selector: 'ht-span-tags-detail', @@ -11,7 +13,16 @@ import { EMPTY, Observable, of } from 'rxjs'; template: `
- +
+
{{ record.value }}
+ +
` @@ -22,12 +33,19 @@ export class SpanTagsDetailComponent implements OnChanges { public tagRecords$?: Observable; + public constructor(private readonly explorerService: ExplorerService) {} + public ngOnChanges(changes: TypedSimpleChanges): void { if (changes.tags && this.tags) { this.buildTagRecords(); } } + public getExploreNavigationParams = (tag: ListViewRecord): Observable => + this.explorerService.buildNavParamsWithFilters(ScopeQueryParam.EndpointTraces, [ + { field: 'tags', operator: FilterOperator.ContainsKeyValue, value: [tag.key, tag.value] } + ]); + private buildTagRecords(): void { if (isNil(this.tags)) { this.tagRecords$ = EMPTY; diff --git a/projects/observability/src/shared/components/span-detail/tags/span-tags-detail.module.ts b/projects/observability/src/shared/components/span-detail/tags/span-tags-detail.module.ts index 8db8ed9d4..6d748c339 100644 --- a/projects/observability/src/shared/components/span-detail/tags/span-tags-detail.module.ts +++ b/projects/observability/src/shared/components/span-detail/tags/span-tags-detail.module.ts @@ -1,11 +1,21 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; -import { LabelModule, ListViewModule, LoadAsyncModule } from '@hypertrace/components'; +import { MemoizeModule } from '@hypertrace/common'; +import { LabelModule, ListViewModule, LoadAsyncModule, TooltipModule } from '@hypertrace/components'; +import { ExploreFilterLinkModule } from '../../explore-filter-link/explore-filter-link.module'; import { SpanTagsDetailComponent } from './span-tags-detail.component'; @NgModule({ - imports: [CommonModule, ListViewModule, LabelModule, LoadAsyncModule], + imports: [ + CommonModule, + ExploreFilterLinkModule, + ListViewModule, + LabelModule, + LoadAsyncModule, + MemoizeModule, + TooltipModule + ], declarations: [SpanTagsDetailComponent], exports: [SpanTagsDetailComponent] })