Skip to content

Commit 97213da

Browse files
authored
Fix to retain table control filters on refresh (#923)
* fix: retain applied filters in table controls * style: linting
1 parent d02e165 commit 97213da

File tree

3 files changed

+50
-4
lines changed

3 files changed

+50
-4
lines changed

projects/components/src/table/controls/table-controls-api.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,21 @@ export interface TableFilterControlOption {
1414
type: TableControlOptionType.Filter;
1515
label: string;
1616
metaValue: TableFilter;
17+
applied?: boolean;
1718
}
1819

1920
export interface TableUnsetControlOption {
2021
type: TableControlOptionType.Unset;
2122
label: string;
2223
metaValue: string;
24+
applied?: boolean;
2325
}
2426

2527
export interface TablePropertyControlOption {
2628
type: TableControlOptionType.Property;
2729
label: string;
2830
metaValue: Dictionary<unknown>;
31+
applied?: boolean;
2932
}
3033

3134
/*

projects/components/src/table/controls/table-controls.component.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import {
4444
<!-- Selects -->
4545
<ht-multi-select
4646
*ngFor="let selectControl of this.selectControls"
47+
[selected]="this.appliedFilters(selectControl)"
4748
[placeholder]="selectControl.placeholder"
4849
class="control select"
4950
showBorder="true"
@@ -127,6 +128,11 @@ export class TableControlsComponent implements OnChanges {
127128
@Output()
128129
public readonly viewChange: EventEmitter<string> = new EventEmitter<string>();
129130

131+
private readonly selectSelections: Map<TableSelectControl, TableSelectControlOption[]> = new Map<
132+
TableSelectControl,
133+
TableSelectControlOption[]
134+
>();
135+
130136
public checkboxSelections: string[] = [];
131137
private readonly checkboxDiffer?: IterableDiffer<string>;
132138

@@ -160,6 +166,10 @@ export class TableControlsComponent implements OnChanges {
160166
}
161167

162168
public ngOnChanges(changes: TypedSimpleChanges<this>): void {
169+
if (changes.selectControls) {
170+
this.diffSelections();
171+
}
172+
163173
if (changes.checkboxControls) {
164174
this.diffCheckboxes();
165175
}
@@ -169,6 +179,16 @@ export class TableControlsComponent implements OnChanges {
169179
}
170180
}
171181

182+
private diffSelections(): void {
183+
this.selectSelections.clear();
184+
this.selectControls?.forEach(selectControl => {
185+
this.selectSelections.set(
186+
selectControl,
187+
selectControl.options.filter(option => option.applied)
188+
);
189+
});
190+
}
191+
172192
private diffCheckboxes(): void {
173193
this.checkboxSelections = this.checkboxControls
174194
? this.checkboxControls.filter(control => control.value).map(control => control.label)
@@ -177,6 +197,10 @@ export class TableControlsComponent implements OnChanges {
177197
this.checkboxDiffer?.diff(this.checkboxSelections);
178198
}
179199

200+
public appliedFilters(selectControl: TableSelectControl): TableSelectControlOption[] | undefined {
201+
return this.selectSelections.get(selectControl);
202+
}
203+
180204
private setActiveViewItem(): void {
181205
if (this.viewItems !== undefined) {
182206
this.activeViewItem = this.viewItems.find(item => item === this.activeViewItem) ?? this.viewItems[0];

projects/distributed-tracing/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ import {
3030
import { WidgetRenderer } from '@hypertrace/dashboards';
3131
import { Renderer } from '@hypertrace/hyperdash';
3232
import { RendererApi, RENDERER_API } from '@hypertrace/hyperdash-angular';
33-
import { capitalize, isEmpty, pick } from 'lodash-es';
33+
import { capitalize, isEmpty, isEqual, pick } from 'lodash-es';
3434
import { BehaviorSubject, combineLatest, Observable, of, Subject } from 'rxjs';
35-
import { filter, map, pairwise, share, startWith, switchMap, take, tap } from 'rxjs/operators';
35+
import { filter, map, pairwise, share, startWith, switchMap, take, tap, withLatestFrom } from 'rxjs/operators';
3636
import { AttributeMetadata, toFilterAttributeType } from '../../../graphql/model/metadata/attribute-metadata';
3737
import { MetadataService } from '../../../services/metadata/metadata.service';
3838
import { InteractionHandler } from '../../interaction/interaction-handler';
@@ -173,15 +173,34 @@ export class TableWidgetRendererComponent
173173
// Fetch the values for the selectFilter dropdown
174174
selectControlModel.getOptions().pipe(
175175
take(1),
176-
map(options => ({
176+
withLatestFrom(this.selectFilterSubject),
177+
map(([options, filters]) => ({
177178
placeholder: selectControlModel.placeholder,
178-
options: options
179+
options: options.map(option => ({
180+
...option,
181+
applied: this.isFilterApplied(option.metaValue, filters)
182+
}))
179183
}))
180184
)
181185
)
182186
);
183187
}
184188

189+
private isFilterApplied(filterOption: TableFilter, appliedFilters: TableFilter[]): boolean {
190+
// This gets just a little tricky because multiple options for a single select could be IN filtered together
191+
return (
192+
appliedFilters.find(f => {
193+
if (isEqual(f, filterOption)) {
194+
return true;
195+
}
196+
197+
if (f.field === filterOption.field && f.operator === FilterOperator.In) {
198+
return Array.isArray(f.value) && f.value.find(value => value === filterOption.value);
199+
}
200+
}) !== undefined
201+
);
202+
}
203+
185204
protected fetchAndPopulateCheckboxControls(): void {
186205
this.checkboxControls$ = forkJoinSafeEmpty(
187206
this.model

0 commit comments

Comments
 (0)