diff --git a/projects/components/src/table/controls/table-controls-api.ts b/projects/components/src/table/controls/table-controls-api.ts index 1b5cdc995..149fa04e7 100644 --- a/projects/components/src/table/controls/table-controls-api.ts +++ b/projects/components/src/table/controls/table-controls-api.ts @@ -14,18 +14,21 @@ export interface TableFilterControlOption { type: TableControlOptionType.Filter; label: string; metaValue: TableFilter; + applied?: boolean; } export interface TableUnsetControlOption { type: TableControlOptionType.Unset; label: string; metaValue: string; + applied?: boolean; } export interface TablePropertyControlOption { type: TableControlOptionType.Property; label: string; metaValue: Dictionary; + applied?: boolean; } /* diff --git a/projects/components/src/table/controls/table-controls.component.ts b/projects/components/src/table/controls/table-controls.component.ts index 4fb0bc007..caaff7710 100644 --- a/projects/components/src/table/controls/table-controls.component.ts +++ b/projects/components/src/table/controls/table-controls.component.ts @@ -44,6 +44,7 @@ import { = new EventEmitter(); + private readonly selectSelections: Map = new Map< + TableSelectControl, + TableSelectControlOption[] + >(); + public checkboxSelections: string[] = []; private readonly checkboxDiffer?: IterableDiffer; @@ -160,6 +166,10 @@ export class TableControlsComponent implements OnChanges { } public ngOnChanges(changes: TypedSimpleChanges): void { + if (changes.selectControls) { + this.diffSelections(); + } + if (changes.checkboxControls) { this.diffCheckboxes(); } @@ -169,6 +179,16 @@ export class TableControlsComponent implements OnChanges { } } + private diffSelections(): void { + this.selectSelections.clear(); + this.selectControls?.forEach(selectControl => { + this.selectSelections.set( + selectControl, + selectControl.options.filter(option => option.applied) + ); + }); + } + private diffCheckboxes(): void { this.checkboxSelections = this.checkboxControls ? this.checkboxControls.filter(control => control.value).map(control => control.label) @@ -177,6 +197,10 @@ export class TableControlsComponent implements OnChanges { this.checkboxDiffer?.diff(this.checkboxSelections); } + public appliedFilters(selectControl: TableSelectControl): TableSelectControlOption[] | undefined { + return this.selectSelections.get(selectControl); + } + private setActiveViewItem(): void { if (this.viewItems !== undefined) { this.activeViewItem = this.viewItems.find(item => item === this.activeViewItem) ?? this.viewItems[0]; diff --git a/projects/distributed-tracing/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts b/projects/distributed-tracing/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts index 3b8fc9d9c..7e6eb5082 100644 --- a/projects/distributed-tracing/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts +++ b/projects/distributed-tracing/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts @@ -30,9 +30,9 @@ import { import { WidgetRenderer } from '@hypertrace/dashboards'; import { Renderer } from '@hypertrace/hyperdash'; import { RendererApi, RENDERER_API } from '@hypertrace/hyperdash-angular'; -import { capitalize, isEmpty, pick } from 'lodash-es'; +import { capitalize, isEmpty, isEqual, pick } from 'lodash-es'; import { BehaviorSubject, combineLatest, Observable, of, Subject } from 'rxjs'; -import { filter, map, pairwise, share, startWith, switchMap, take, tap } from 'rxjs/operators'; +import { filter, map, pairwise, share, startWith, switchMap, take, tap, withLatestFrom } from 'rxjs/operators'; import { AttributeMetadata, toFilterAttributeType } from '../../../graphql/model/metadata/attribute-metadata'; import { MetadataService } from '../../../services/metadata/metadata.service'; import { InteractionHandler } from '../../interaction/interaction-handler'; @@ -173,15 +173,34 @@ export class TableWidgetRendererComponent // Fetch the values for the selectFilter dropdown selectControlModel.getOptions().pipe( take(1), - map(options => ({ + withLatestFrom(this.selectFilterSubject), + map(([options, filters]) => ({ placeholder: selectControlModel.placeholder, - options: options + options: options.map(option => ({ + ...option, + applied: this.isFilterApplied(option.metaValue, filters) + })) })) ) ) ); } + private isFilterApplied(filterOption: TableFilter, appliedFilters: TableFilter[]): boolean { + // This gets just a little tricky because multiple options for a single select could be IN filtered together + return ( + appliedFilters.find(f => { + if (isEqual(f, filterOption)) { + return true; + } + + if (f.field === filterOption.field && f.operator === FilterOperator.In) { + return Array.isArray(f.value) && f.value.find(value => value === filterOption.value); + } + }) !== undefined + ); + } + protected fetchAndPopulateCheckboxControls(): void { this.checkboxControls$ = forkJoinSafeEmpty( this.model