Skip to content

Commit 225901a

Browse files
authored
feat: change table controls to more generic view toggle instead of mode (#523)
* feat: change table controls to more generic view toggle instead of mode * fix: add mode change and some other clean up * fix: prettier * fix: naming and removed trivial method
1 parent 326b173 commit 225901a

File tree

12 files changed

+197
-171
lines changed

12 files changed

+197
-171
lines changed

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ describe('Table Controls component', () => {
1717
[searchEnabled]="searchEnabled"
1818
[searchPlaceholder]="searchPlaceholder"
1919
[filterItems]="filterItems"
20-
[modeItems]="modeItems"
20+
[viewItems]="viewItems"
2121
(searchChange)="searchChange($event)"
2222
(filterChange)="filterChange($event)"
23-
(modeChange)="modeChange($event)"
23+
(viewChange)="viewChange($event)"
2424
>
2525
</ht-table-controls>
2626
`
@@ -103,10 +103,10 @@ describe('Table Controls component', () => {
103103
expect(onChangeSpy).toHaveBeenCalled();
104104
});
105105

106-
test('should provide toggle group items for each mode', () => {
106+
test('should provide toggle group items for each view', () => {
107107
const spectator = createHost(undefined, {
108108
hostProps: {
109-
modeItems: [
109+
viewItems: [
110110
{
111111
label: 'test1',
112112
value: 'TEST1'
@@ -122,12 +122,12 @@ describe('Table Controls component', () => {
122122
expect(spectator.query(ToggleGroupComponent)?.items?.length).toEqual(2);
123123
});
124124

125-
test('should emit mode when selected', () => {
125+
test('should emit view when selected', () => {
126126
const onChangeSpy = jest.fn();
127127

128128
const spectator = createHost(undefined, {
129129
hostProps: {
130-
modeItems: [
130+
viewItems: [
131131
{
132132
label: 'test1',
133133
value: 'TEST1'
@@ -137,7 +137,7 @@ describe('Table Controls component', () => {
137137
value: 'TEST2'
138138
}
139139
],
140-
modeChange: onChangeSpy
140+
viewChange: onChangeSpy
141141
}
142142
});
143143

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

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { isEmpty } from 'lodash-es';
55
import { Subject } from 'rxjs';
66
import { debounceTime } from 'rxjs/operators';
77
import { ToggleItem } from '../../toggle-group/toggle-item';
8-
import { TableMode } from '../table-api';
98
import { SelectChange, SelectFilter } from './table-controls-api';
109

1110
@Component({
@@ -60,10 +59,10 @@ import { SelectChange, SelectFilter } from './table-controls-api';
6059
6160
<!-- Mode Toggle -->
6261
<ht-toggle-group
63-
*ngIf="this.modeToggleEnabled"
62+
*ngIf="this.viewToggleEnabled"
6463
class="control mode-toggle-group"
65-
[items]="this.modeItems"
66-
[activeItem]="this.activeModeItem"
64+
[items]="this.viewItems"
65+
[activeItem]="this.activeViewItem"
6766
(activeItemChange)="this.onModeChange($event)"
6867
></ht-toggle-group>
6968
</div>
@@ -86,10 +85,10 @@ export class TableControlsComponent implements OnChanges {
8685
public activeFilterItem?: ToggleItem;
8786

8887
@Input()
89-
public modeItems?: ToggleItem[] = [];
88+
public viewItems?: ToggleItem[] = [];
9089

9190
@Input()
92-
public activeModeItem?: ToggleItem;
91+
public activeViewItem?: ToggleItem;
9392

9493
// Checkbox filter
9594
@Input()
@@ -111,10 +110,10 @@ export class TableControlsComponent implements OnChanges {
111110
public readonly filterChange: EventEmitter<ToggleItem> = new EventEmitter<ToggleItem>();
112111

113112
@Output()
114-
public readonly modeChange: EventEmitter<TableMode> = new EventEmitter<TableMode>();
113+
public readonly viewChange: EventEmitter<string> = new EventEmitter<string>();
115114

116-
public get modeToggleEnabled(): boolean {
117-
return !!this.modeItems && this.modeItems.length > 0;
115+
public get viewToggleEnabled(): boolean {
116+
return !!this.viewItems && this.viewItems.length > 0;
118117
}
119118

120119
public get checkboxEnabled(): boolean {
@@ -126,7 +125,7 @@ export class TableControlsComponent implements OnChanges {
126125
}
127126

128127
public get anyControlsEnabled(): boolean {
129-
return this.modeToggleEnabled || this.checkboxEnabled || this.filterItemsEnabled || !!this.searchEnabled;
128+
return this.viewToggleEnabled || this.checkboxEnabled || this.filterItemsEnabled || !!this.searchEnabled;
130129
}
131130

132131
private readonly searchDebounceSubject: Subject<string> = new Subject<string>();
@@ -142,8 +141,8 @@ export class TableControlsComponent implements OnChanges {
142141
this.setActiveFilterItem();
143142
}
144143

145-
if (changes.modeItems) {
146-
this.setActiveModeItem();
144+
if (changes.viewItems) {
145+
this.setActiveViewItem();
147146
}
148147
}
149148

@@ -153,9 +152,9 @@ export class TableControlsComponent implements OnChanges {
153152
}
154153
}
155154

156-
private setActiveModeItem(): void {
157-
if (this.modeItems !== undefined) {
158-
this.activeModeItem = this.modeItems.find(item => item === this.activeModeItem) ?? this.modeItems[0];
155+
private setActiveViewItem(): void {
156+
if (this.viewItems !== undefined) {
157+
this.activeViewItem = this.viewItems.find(item => item === this.activeViewItem) ?? this.viewItems[0];
159158
}
160159
}
161160

@@ -174,7 +173,7 @@ export class TableControlsComponent implements OnChanges {
174173
this.searchDebounceSubject.next(text);
175174
}
176175

177-
public onModeChange(item: ToggleItem<TableMode>): void {
178-
this.modeChange.emit(item.value);
176+
public onModeChange(item: ToggleItem<string>): void {
177+
this.viewChange.emit(item.value);
179178
}
180179
}

projects/distributed-tracing/src/shared/dashboard/widgets/table/table-widget-base.model.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,12 @@ export abstract class TableWidgetBaseModel extends BaseModel {
138138
return TableSelectionMode.Single;
139139
}
140140

141-
public setMode(_mode: TableMode): void {
141+
public setView(_view: string): void {
142142
// No-op here, but can be overridden
143143
return;
144144
}
145145

146-
public getModeOptions(): TableMode[] {
146+
public getViewOptions(): string[] {
147147
// No-op here, but can be overridden
148148
return [];
149149
}
@@ -152,6 +152,10 @@ export abstract class TableWidgetBaseModel extends BaseModel {
152152
return this.filterOptions;
153153
}
154154

155+
public getSearchAttribute(): string | undefined {
156+
return this.searchAttribute;
157+
}
158+
155159
public getCheckboxFilterOption(): TableWidgetCheckboxFilterModel | undefined {
156160
return this.checkboxFilterOption;
157161
}

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

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import {
1717
TableColumnConfig,
1818
TableDataSource,
1919
TableFilter,
20-
TableMode,
2120
TableRow,
2221
TableSelectionMode,
2322
TableStyle,
@@ -32,14 +31,14 @@ import { filter, first, map, pairwise, share, startWith, switchMap, tap } from '
3231
import { AttributeMetadata, toFilterAttributeType } from '../../../graphql/model/metadata/attribute-metadata';
3332
import { MetadataService } from '../../../services/metadata/metadata.service';
3433
import { InteractionHandler } from '../../interaction/interaction-handler';
35-
import { ModeToggleTableWidgetModel } from './mode-toggle-table-widget.model';
3634
import { TableWidgetBaseModel } from './table-widget-base.model';
3735
import { SpecificationBackedTableColumnDef } from './table-widget-column.model';
3836
import { TableWidgetFilterModel } from './table-widget-filter-model';
37+
import { TableWidgetViewToggleModel } from './table-widget-view-toggle.model';
3938
import { TableWidgetModel } from './table-widget.model';
4039

4140
@Renderer({ modelClass: TableWidgetModel })
42-
@Renderer({ modelClass: ModeToggleTableWidgetModel })
41+
@Renderer({ modelClass: TableWidgetViewToggleModel })
4342
@Component({
4443
selector: 'ht-table-widget-renderer',
4544
styleUrls: ['./table-widget-renderer.component.scss'],
@@ -53,17 +52,17 @@ import { TableWidgetModel } from './table-widget.model';
5352
<div class="table-content-container">
5453
<ht-table-controls
5554
class="table-controls"
56-
[searchEnabled]="!!this.api.model.searchAttribute"
55+
[searchEnabled]="!!this.api.model.getSearchAttribute()"
5756
[selectFilterItems]="this.selectFilterItems$ | async"
5857
[filterItems]="this.filterItems"
59-
[modeItems]="this.modeItems"
58+
[viewItems]="this.viewItems"
6059
[checkboxLabel]="this.model.getCheckboxFilterOption()?.label"
6160
[checkboxChecked]="this.model.getCheckboxFilterOption()?.checked"
6261
(checkboxCheckedChange)="this.onCheckboxCheckedChange($event)"
6362
(selectChange)="this.onSelectChange($event)"
6463
(searchChange)="this.onSearchChange($event)"
6564
(filterChange)="this.onFilterChange($event)"
66-
(modeChange)="this.onModeChange($event)"
65+
(viewChange)="this.onViewChange($event)"
6766
>
6867
</ht-table-controls>
6968
@@ -72,7 +71,7 @@ import { TableWidgetModel } from './table-widget.model';
7271
[ngClass]="{ 'header-margin': this.model.header?.topMargin }"
7372
[columnConfigs]="this.columnConfigs$ | async"
7473
[metadata]="this.metadata$ | async"
75-
[mode]="this.activeMode"
74+
[mode]="this.model.mode"
7675
[selectionMode]="this.model.getSelectionMode()"
7776
[display]="this.model.style"
7877
[data]="this.data$ | async"
@@ -96,8 +95,7 @@ export class TableWidgetRendererComponent
9695
extends WidgetRenderer<TableWidgetBaseModel, TableDataSource<TableRow> | undefined>
9796
implements OnInit {
9897
public filterItems: ToggleItem<TableWidgetFilterModel>[] = [];
99-
public modeItems: ToggleItem<TableMode>[] = [];
100-
public activeMode!: TableMode;
98+
public viewItems: ToggleItem<string>[] = [];
10199

102100
public selectFilterItems$!: Observable<SelectFilter[]>;
103101

@@ -124,8 +122,6 @@ export class TableWidgetRendererComponent
124122
public ngOnInit(): void {
125123
super.ngOnInit();
126124

127-
this.onModeChange(this.model.mode);
128-
129125
this.metadata$ = this.getScopeAttributes();
130126
this.columnConfigs$ = (isNonEmptyString(this.model.id)
131127
? this.preferenceService.get<TableColumnConfig[]>(this.model.id, [])
@@ -151,9 +147,9 @@ export class TableWidgetRendererComponent
151147
value: filterOption
152148
}));
153149

154-
this.modeItems = this.model.getModeOptions().map(modeOption => ({
155-
label: capitalize(modeOption),
156-
value: modeOption
150+
this.viewItems = this.model.getViewOptions().map(viewOption => ({
151+
label: capitalize(viewOption),
152+
value: viewOption
157153
}));
158154

159155
this.maybeEmitInitialCheckboxFilterChange();
@@ -321,16 +317,15 @@ export class TableWidgetRendererComponent
321317

322318
public onSearchChange(text: string): void {
323319
const searchFilter: TableFilter = {
324-
field: this.api.model.searchAttribute!,
320+
field: this.api.model.getSearchAttribute()!,
325321
operator: FilterOperator.Like,
326322
value: text
327323
};
328324
this.searchFilterSubject.next([searchFilter]);
329325
}
330326

331-
public onModeChange(mode: TableMode): void {
332-
this.activeMode = mode;
333-
this.model.setMode(mode);
327+
public onViewChange(view: string): void {
328+
this.model.setView(view);
334329
this.columnConfigs$ = this.getColumnConfigs();
335330
}
336331

projects/distributed-tracing/src/shared/dashboard/widgets/table/table-widget-select-filter.model.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { FilterOperator, TableFilter } from '@hypertrace/components';
33
import { Model, ModelApi, ModelProperty, STRING_PROPERTY } from '@hypertrace/hyperdash';
44
import { ModelInject, MODEL_API } from '@hypertrace/hyperdash-angular';
55
import { Observable } from 'rxjs';
6+
import { map } from 'rxjs/operators';
67

78
@Model({
89
type: 'table-widget-select-filter',
@@ -26,7 +27,15 @@ export class TableWidgetSelectFilterModel {
2627
protected readonly api!: ModelApi;
2728

2829
public getData(): Observable<PrimitiveValue[]> {
29-
return this.api.getData<PrimitiveValue[]>();
30+
return this.api.getData<PrimitiveValue[]>().pipe(
31+
map(values => values.filter(value => !this.isEmpty(value))),
32+
map(values => values.sort())
33+
);
34+
}
35+
36+
public isEmpty(value: unknown): boolean {
37+
// Empty values can't be queried through filtering yet, so need to remove them so they don't appear in the dropdown
38+
return value === undefined || value === null || value === '';
3039
}
3140

3241
public getTableFilter(value: unknown): TableFilter {

0 commit comments

Comments
 (0)