From 4dcec495dc28dd8f3588b998785ed5847fd9a954 Mon Sep 17 00:00:00 2001 From: Jake Bassett Date: Thu, 7 Oct 2021 15:23:21 -0700 Subject: [PATCH 1/7] feat: clean up table widget preferences storage --- .../controls/table-controls.component.ts | 2 + projects/dashboards/src/widgets/base.model.ts | 4 + .../table/table-widget-renderer.component.ts | 115 +++++++++++------- .../table/table-widget-view-toggle.model.ts | 4 + .../widgets/table/table-widget.model.ts | 4 + 5 files changed, 83 insertions(+), 46 deletions(-) diff --git a/projects/components/src/table/controls/table-controls.component.ts b/projects/components/src/table/controls/table-controls.component.ts index 6289032b4..44a6bf249 100644 --- a/projects/components/src/table/controls/table-controls.component.ts +++ b/projects/components/src/table/controls/table-controls.component.ts @@ -92,6 +92,8 @@ import { }) export class TableControlsComponent implements OnChanges { public readonly DEFAULT_SEARCH_PLACEHOLDER: string = 'Search...'; + @Input() + public persistenceId?: string; @Input() public searchEnabled?: boolean; diff --git a/projects/dashboards/src/widgets/base.model.ts b/projects/dashboards/src/widgets/base.model.ts index 69659ca54..05a49b25e 100644 --- a/projects/dashboards/src/widgets/base.model.ts +++ b/projects/dashboards/src/widgets/base.model.ts @@ -15,4 +15,8 @@ export abstract class BaseModel { type: STRING_PROPERTY.type }) public id?: string; + + public getId(): string | undefined { + return this.id; + } } diff --git a/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts b/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts index 7e6eb5082..6a2f11f06 100644 --- a/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts +++ b/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts @@ -32,7 +32,7 @@ import { Renderer } from '@hypertrace/hyperdash'; import { RendererApi, RENDERER_API } from '@hypertrace/hyperdash-angular'; 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, withLatestFrom } from 'rxjs/operators'; +import { filter, first, 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'; @@ -98,6 +98,10 @@ import { TableWidgetModel } from './table-widget.model'; export class TableWidgetRendererComponent extends WidgetRenderer | undefined> implements OnInit { + private static readonly DEFAULT_PREFERENCES: TableWidgetPreferences = { + columns: [] + }; + public viewItems: ToggleItem[] = []; public selectControls$!: Observable; @@ -111,9 +115,7 @@ export class TableWidgetRendererComponent private readonly searchFilterSubject: Subject = new BehaviorSubject([]); private readonly selectFilterSubject: BehaviorSubject = new BehaviorSubject([]); - private readonly queryPropertiesSubject: BehaviorSubject> = new BehaviorSubject< - Dictionary - >({}); + private readonly queryPropertiesSubject: BehaviorSubject> = new BehaviorSubject>({}); public queryProperties$: Observable> = this.queryPropertiesSubject.asObservable(); private selectedRowInteractionHandler?: InteractionHandler; @@ -131,10 +133,8 @@ export class TableWidgetRendererComponent super.ngOnInit(); this.metadata$ = this.getScopeAttributes(); - this.columnConfigs$ = (isNonEmptyString(this.model.id) - ? this.preferenceService.get(this.model.id, []) - : of([]) - ).pipe(switchMap(persistedColumns => this.getColumnConfigs(persistedColumns))); + + this.columnConfigs$ = this.getColumnConfigs(); this.combinedFilters$ = combineLatest([ this.toggleFilterSubject, @@ -237,41 +237,29 @@ export class TableWidgetRendererComponent return this.data$!.pipe(map(data => data?.getScope?.())); } - private getColumnConfigs(persistedColumns: TableColumnConfig[] = []): Observable { - return combineLatest([ - this.getScope(), - this.api.change$.pipe( - map(() => true), - startWith(true) - ) - ]).pipe( - switchMap(([scope]) => this.model.getColumns(scope)), - startWith([]), - map((columns: SpecificationBackedTableColumnDef[]) => - this.applySavedColumnPreferences(columns, persistedColumns) - ), - pairwise(), - filter(([previous, current]) => !isEqualIgnoreFunctions(previous, current)), - map(([_, current]) => current), - share(), - tap(() => this.onDashboardRefresh()) + private getColumnConfigs(): Observable { + return this.getPreferences(TableWidgetRendererComponent.DEFAULT_PREFERENCES).pipe( + switchMap(preferences => combineLatest([ + this.getScope(), + this.api.change$.pipe( + map(() => true), + startWith(true) + ) + ]).pipe( + switchMap(([scope]) => this.model.getColumns(scope)), + startWith([]), + map((columns: SpecificationBackedTableColumnDef[]) => + this.hydratePersistedColumnConfigs(columns, preferences.columns) + ), + pairwise(), + filter(([previous, current]) => !isEqualIgnoreFunctions(previous, current)), + map(([_, current]) => current), + share(), + tap(() => this.onDashboardRefresh()) + )) ); } - private applySavedColumnPreferences( - columns: SpecificationBackedTableColumnDef[], - persistedColumns: TableColumnConfig[] - ): SpecificationBackedTableColumnDef[] { - return columns.map(column => { - const found = persistedColumns.find(persistedColumn => persistedColumn.id === column.id); - - return { - ...column, // Apply default column config - ...(found ? found : {}) // Override with any saved properties - }; - }); - } - private getScopeAttributes(): Observable { return this.getScope().pipe( switchMap(scope => { @@ -360,11 +348,10 @@ export class TableWidgetRendererComponent } public onColumnsChange(columns: TableColumnConfig[]): void { - if (isNonEmptyString(this.model.id)) { - this.preferenceService.set( - this.model.id, - columns.map(column => this.pickPersistColumnProperties(column)) - ); + if (isNonEmptyString(this.model.getId())) { + this.setPreferences({ + columns: columns.map(column => this.dehydratePersistedColumnConfig(column)) + }); } } @@ -392,7 +379,21 @@ export class TableWidgetRendererComponent return !isEmpty(matchedSelectionHandlers) ? matchedSelectionHandlers[0].handler : undefined; } - private pickPersistColumnProperties(column: TableColumnConfig): Pick { + private hydratePersistedColumnConfigs( + columns: SpecificationBackedTableColumnDef[], + persistedColumns: TableColumnConfig[] + ): SpecificationBackedTableColumnDef[] { + return columns.map(column => { + const found = persistedColumns.find(persistedColumn => persistedColumn.id === column.id); + + return { + ...column, // Apply default column config + ...(found ? found : {}) // Override with any saved properties + }; + }); + } + + private dehydratePersistedColumnConfig(column: TableColumnConfig): PersistedTableColumnConfig { /* * Note: The table columns have nested methods, so those are lost here when persistService uses JSON.stringify * to convert and store. We want to just pluck the relevant properties that are required to be saved. @@ -400,6 +401,22 @@ export class TableWidgetRendererComponent return pick(column, ['id', 'visible']); } + private getPreferences(defaultPreferences: TableWidgetPreferences): Observable { + return isNonEmptyString(this.model.getId()) + ? this.preferenceService.get(this.model.getId()!, defaultPreferences).pipe( + first(), + tap(preferences => console.debug('getPreferences', this.model.getId(), preferences)) + ) + : of(defaultPreferences); + } + + private setPreferences(preferences: TableWidgetPreferences): void { + console.debug('setPreferences', this.model.getId(), preferences); + if (isNonEmptyString(this.model.getId())) { + this.preferenceService.set(this.model.getId()!, preferences); + } + } + private mergeFilters(tableFilter: TableFilter): TableFilter[] { const existingSelectFiltersWithChangedRemoved = this.removeFilters(tableFilter.field); @@ -417,3 +434,9 @@ export class TableWidgetRendererComponent }; } } + +interface TableWidgetPreferences { + columns: PersistedTableColumnConfig[]; +} + +type PersistedTableColumnConfig = Pick; diff --git a/projects/observability/src/shared/dashboard/widgets/table/table-widget-view-toggle.model.ts b/projects/observability/src/shared/dashboard/widgets/table/table-widget-view-toggle.model.ts index d8a1cd484..95c2009ce 100644 --- a/projects/observability/src/shared/dashboard/widgets/table/table-widget-view-toggle.model.ts +++ b/projects/observability/src/shared/dashboard/widgets/table/table-widget-view-toggle.model.ts @@ -61,6 +61,10 @@ export class TableWidgetViewToggleModel extends TableWidgetModel implements Mode return found ? this.api.createChild(found.template) : undefined; } + public getId(): string | undefined { + return this.delegateModel && this.delegateModel?.getId(); + } + public getData(): Observable> { return this.delegateModel ? this.delegateModel?.getData() : NEVER; } diff --git a/projects/observability/src/shared/dashboard/widgets/table/table-widget.model.ts b/projects/observability/src/shared/dashboard/widgets/table/table-widget.model.ts index e6b7f8efe..cde3b8462 100644 --- a/projects/observability/src/shared/dashboard/widgets/table/table-widget.model.ts +++ b/projects/observability/src/shared/dashboard/widgets/table/table-widget.model.ts @@ -93,6 +93,10 @@ export class TableWidgetModel extends TableWidgetBaseModel { @ModelInject(TableWidgetColumnsService) private readonly tableWidgetColumnsService!: TableWidgetColumnsService; + public getId(): string | undefined { + return this.id; + } + public getData(): Observable> { return this.api.getData>(); } From 868097cb8da52a6e695d31d6317fd7a80f6619d3 Mon Sep 17 00:00:00 2001 From: Jake Bassett Date: Fri, 8 Oct 2021 13:10:50 -0700 Subject: [PATCH 2/7] feat: add view toggle preference --- .../controls/table-controls.component.ts | 13 +-- .../widgets/table/table-widget-base.model.ts | 12 +++ .../table/table-widget-renderer.component.ts | 80 ++++++++++++++++--- 3 files changed, 88 insertions(+), 17 deletions(-) diff --git a/projects/components/src/table/controls/table-controls.component.ts b/projects/components/src/table/controls/table-controls.component.ts index 44a6bf249..c3fd9605d 100644 --- a/projects/components/src/table/controls/table-controls.component.ts +++ b/projects/components/src/table/controls/table-controls.component.ts @@ -10,6 +10,7 @@ import { } from '@angular/core'; import { IconType } from '@hypertrace/assets-library'; import { TypedSimpleChanges } from '@hypertrace/common'; +import { isEqual } from 'lodash-es'; import { IconSize } from '../../icon/icon-size'; import { MultiSelectJustify } from '../../multi-select/multi-select-justify'; import { MultiSelectSearchMode, TriggerLabelDisplayMode } from '../../multi-select/multi-select.component'; @@ -128,10 +129,8 @@ export class TableControlsComponent implements OnChanges { @Output() public readonly viewChange: EventEmitter = new EventEmitter(); - private readonly selectSelections: Map = new Map< - TableSelectControl, - TableSelectControlOption[] - >(); + private readonly selectSelections: Map = new Map(); public checkboxSelections: string[] = []; private readonly checkboxDiffer?: IterableDiffer; @@ -194,7 +193,7 @@ export class TableControlsComponent implements OnChanges { private setActiveViewItem(): void { if (this.viewItems !== undefined) { - this.activeViewItem = this.viewItems.find(item => item === this.activeViewItem) ?? this.viewItems[0]; + this.activeViewItem = this.findViewItem(this.activeViewItem); } } @@ -246,4 +245,8 @@ export class TableControlsComponent implements OnChanges { public onViewChange(item: ToggleItem): void { this.viewChange.emit(item.value); } + + private findViewItem(viewItem?: ToggleItem): ToggleItem | undefined { + return this.viewItems?.find(item => isEqual(item, viewItem)) ?? this.viewItems![0]; + } } diff --git a/projects/observability/src/shared/dashboard/widgets/table/table-widget-base.model.ts b/projects/observability/src/shared/dashboard/widgets/table/table-widget-base.model.ts index cb499423b..e40eceb54 100644 --- a/projects/observability/src/shared/dashboard/widgets/table/table-widget-base.model.ts +++ b/projects/observability/src/shared/dashboard/widgets/table/table-widget-base.model.ts @@ -23,6 +23,13 @@ import { TableWidgetControlCheckboxOptionModel } from './table-widget-control-ch import { TableWidgetControlSelectOptionModel } from './table-widget-control-select-option.model'; export abstract class TableWidgetBaseModel extends BaseModel { + @ModelProperty({ + key: 'viewId', + displayName: 'Model View ID', + type: STRING_PROPERTY.type + }) + public viewId?: string; + @ModelProperty({ // tslint:disable-next-line: no-object-literal-type-assertion type: { @@ -131,6 +138,11 @@ export abstract class TableWidgetBaseModel extends BaseModel { return TableSelectionMode.Single; } + public getViewId(): string | undefined { + // No-op here, but can be overridden + return this.viewId; + } + public setView(_view: string): void { // No-op here, but can be overridden return; diff --git a/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts b/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts index 6a2f11f06..641d225fe 100644 --- a/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts +++ b/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts @@ -62,6 +62,7 @@ import { TableWidgetModel } from './table-widget.model'; [selectControls]="this.selectControls$ | async" [checkboxControls]="this.checkboxControls$ | async" [viewItems]="this.viewItems" + [activeViewItem]="this.activeViewItem$ | async" (searchChange)="this.onSearchChange($event)" (selectChange)="this.onSelectChange($event)" (checkboxChange)="this.onCheckboxChange($event)" @@ -102,7 +103,10 @@ export class TableWidgetRendererComponent columns: [] }; + private static readonly DEFAULT_TAB_INDEX: number = 0; + public viewItems: ToggleItem[] = []; + public activeViewItem$!: Observable>; public selectControls$!: Observable; public checkboxControls$!: Observable; @@ -132,8 +136,12 @@ export class TableWidgetRendererComponent public ngOnInit(): void { super.ngOnInit(); + this.viewItems = this.model.getViewOptions().map(viewOption => this.buildViewItem(viewOption)); + this.metadata$ = this.getScopeAttributes(); + this.activeViewItem$ = this.getActiveViewItem(); + this.columnConfigs$ = this.getColumnConfigs(); this.combinedFilters$ = combineLatest([ @@ -143,11 +151,6 @@ export class TableWidgetRendererComponent ]).pipe( map(([toggleFilters, searchFilters, selectFilters]) => [...toggleFilters, ...searchFilters, ...selectFilters]) ); - - this.viewItems = this.model.getViewOptions().map(viewOption => ({ - label: capitalize(viewOption), - value: viewOption - })); } public getChildModel = (row: TableRow): object | undefined => this.model.getChildModel(row); @@ -237,8 +240,14 @@ export class TableWidgetRendererComponent return this.data$!.pipe(map(data => data?.getScope?.())); } + private getActiveViewItem(): Observable> { + return this.getViewPreferences().pipe( + map(preferences => this.hydratePersistedActiveViewItem(this.viewItems, preferences.activeViewItem)) + ); + } + private getColumnConfigs(): Observable { - return this.getPreferences(TableWidgetRendererComponent.DEFAULT_PREFERENCES).pipe( + return this.getPreferences().pipe( switchMap(preferences => combineLatest([ this.getScope(), this.api.change$.pipe( @@ -344,14 +353,25 @@ export class TableWidgetRendererComponent public onViewChange(view: string): void { this.model.setView(view); + if (isNonEmptyString(this.model.getId())) { + this.getViewPreferences().subscribe( + preferences => this.setViewPreferences({ + ...preferences, + activeViewItem: view + }) + ); + } this.columnConfigs$ = this.getColumnConfigs(); } public onColumnsChange(columns: TableColumnConfig[]): void { if (isNonEmptyString(this.model.getId())) { - this.setPreferences({ - columns: columns.map(column => this.dehydratePersistedColumnConfig(column)) - }); + this.getPreferences().subscribe( + preferences => this.setPreferences({ + ...preferences, + columns: columns.map(column => this.dehydratePersistedColumnConfig(column)) + }) + ); } } @@ -379,6 +399,13 @@ export class TableWidgetRendererComponent return !isEmpty(matchedSelectionHandlers) ? matchedSelectionHandlers[0].handler : undefined; } + private hydratePersistedActiveViewItem( + viewItems: ToggleItem[], + persistedActiveViewItem?: string + ): ToggleItem { + return persistedActiveViewItem ? this.buildViewItem(persistedActiveViewItem) : viewItems[TableWidgetRendererComponent.DEFAULT_TAB_INDEX]; + } + private hydratePersistedColumnConfigs( columns: SpecificationBackedTableColumnDef[], persistedColumns: TableColumnConfig[] @@ -401,22 +428,47 @@ export class TableWidgetRendererComponent return pick(column, ['id', 'visible']); } - private getPreferences(defaultPreferences: TableWidgetPreferences): Observable { + private getViewPreferences(): Observable { + return isNonEmptyString(this.model.viewId) + ? this.preferenceService.get(this.model.viewId!, {}).pipe( + first(), + tap(preferences => console.debug('getViewPreferences', this.model.viewId, preferences)) + ) + : of({}); + } + + private setViewPreferences(preferences: TableWidgetViewPreferences): void { + console.debug('setViewPreferences', this.model.viewId, preferences); + if (isNonEmptyString(this.model.viewId)) { + this.preferenceService.set(this.model.viewId!, preferences); + } + } + + private getPreferences( + defaultPreferences: TableWidgetPreferences = TableWidgetRendererComponent.DEFAULT_PREFERENCES + ): Observable { return isNonEmptyString(this.model.getId()) ? this.preferenceService.get(this.model.getId()!, defaultPreferences).pipe( first(), - tap(preferences => console.debug('getPreferences', this.model.getId(), preferences)) + tap(preferences => console.info('getPreferences', this.model.getId(), preferences)) ) : of(defaultPreferences); } private setPreferences(preferences: TableWidgetPreferences): void { - console.debug('setPreferences', this.model.getId(), preferences); + console.info('setPreferences', this.model.getId(), preferences); if (isNonEmptyString(this.model.getId())) { this.preferenceService.set(this.model.getId()!, preferences); } } + private buildViewItem(viewOption: string): ToggleItem { + return ({ + label: capitalize(viewOption), + value: viewOption + }); + } + private mergeFilters(tableFilter: TableFilter): TableFilter[] { const existingSelectFiltersWithChangedRemoved = this.removeFilters(tableFilter.field); @@ -435,6 +487,10 @@ export class TableWidgetRendererComponent } } +interface TableWidgetViewPreferences { + activeViewItem?: string; +} + interface TableWidgetPreferences { columns: PersistedTableColumnConfig[]; } From c539278a92c90eb81e4759d7034391c412e6908c Mon Sep 17 00:00:00 2001 From: Jake Bassett Date: Mon, 11 Oct 2021 13:52:53 -0700 Subject: [PATCH 3/7] feat: add checkbox preferences --- .../controls/table-controls.component.ts | 1 + .../table/table-widget-renderer.component.ts | 167 ++++++++++-------- 2 files changed, 95 insertions(+), 73 deletions(-) diff --git a/projects/components/src/table/controls/table-controls.component.ts b/projects/components/src/table/controls/table-controls.component.ts index c3fd9605d..3064e0aa4 100644 --- a/projects/components/src/table/controls/table-controls.component.ts +++ b/projects/components/src/table/controls/table-controls.component.ts @@ -161,6 +161,7 @@ export class TableControlsComponent implements OnChanges { } if (changes.checkboxControls) { + console.info('checkboxControl change', this.checkboxControls); this.diffCheckboxes(); } diff --git a/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts b/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts index 641d225fe..a296630c5 100644 --- a/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts +++ b/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts @@ -12,7 +12,8 @@ import { FilterOperator, StatefulTableRow, TableCheckboxChange, - TableCheckboxControl, + TableCheckboxControl, TableCheckboxControlOption, + TableCheckboxOptions, TableColumnConfig, TableControlOption, TableControlOptionType, @@ -100,7 +101,8 @@ export class TableWidgetRendererComponent extends WidgetRenderer | undefined> implements OnInit { private static readonly DEFAULT_PREFERENCES: TableWidgetPreferences = { - columns: [] + columns: [], + checkboxes: [] }; private static readonly DEFAULT_TAB_INDEX: number = 0; @@ -204,34 +206,6 @@ export class TableWidgetRendererComponent ); } - protected fetchAndPopulateCheckboxControls(): void { - this.checkboxControls$ = forkJoinSafeEmpty( - this.model - .getCheckboxControlOptions() - .filter(checkboxControlModel => checkboxControlModel.visible) - .map(checkboxControlModel => - checkboxControlModel.getOptions().pipe( - take(1), - map(options => ({ - label: checkboxControlModel.checked ? options[0].label : options[1].label, - value: checkboxControlModel.checked, - options: options - })) - ) - ) - ).pipe( - tap((checkboxControls: TableCheckboxControl[]) => { - // Apply initial values for checkboxes - checkboxControls.forEach(checkboxControl => { - this.onCheckboxChange({ - checkbox: checkboxControl, - option: checkboxControl.value ? checkboxControl.options[0] : checkboxControl.options[1] - }); - }); - }) - ); - } - public get syncWithUrl(): boolean { return this.model.style === TableStyle.FullPage; } @@ -242,7 +216,7 @@ export class TableWidgetRendererComponent private getActiveViewItem(): Observable> { return this.getViewPreferences().pipe( - map(preferences => this.hydratePersistedActiveViewItem(this.viewItems, preferences.activeViewItem)) + map(preferences => this.hydratePersistedActiveView(this.viewItems, preferences.activeView)) ); } @@ -258,7 +232,7 @@ export class TableWidgetRendererComponent switchMap(([scope]) => this.model.getColumns(scope)), startWith([]), map((columns: SpecificationBackedTableColumnDef[]) => - this.hydratePersistedColumnConfigs(columns, preferences.columns) + this.hydratePersistedColumnConfigs(columns, preferences.columns ?? []) ), pairwise(), filter(([previous, current]) => !isEqualIgnoreFunctions(previous, current)), @@ -299,40 +273,93 @@ export class TableWidgetRendererComponent this.selectFilterSubject.next(this.mergeFilters(toInFilter(tableFilters))); } - public onCheckboxChange(changed: TableCheckboxChange): void { - switch (changed.option.type) { + protected fetchAndPopulateCheckboxControls(): void { + this.checkboxControls$ = this.getCheckboxControls() + .pipe( + tap((checkboxControls: TableCheckboxControl[]) => { + checkboxControls.forEach(checkboxControl => + this.publishCheckboxOptionChange(checkboxControl.value ? checkboxControl.options[0] : checkboxControl.options[1]) + // this.onCheckboxChange({ + // checkbox: checkboxControl, + // option: checkboxControl.value ? checkboxControl.options[0] : checkboxControl.options[1] + // }, false); + ); + }) + ); + } + + private publishCheckboxOptionChange(option: TableCheckboxControlOption): void { + switch (option.type) { case TableControlOptionType.Property: - this.queryPropertiesSubject.next(this.mergeQueryProperties(changed.option.metaValue)); + this.queryPropertiesSubject.next(this.mergeQueryProperties(option.metaValue)); break; case TableControlOptionType.Filter: - this.selectFilterSubject.next(this.mergeFilters(changed.option.metaValue)); + this.selectFilterSubject.next(this.mergeFilters(option.metaValue)); break; case TableControlOptionType.Unset: - this.selectFilterSubject.next(this.removeFilters(changed.option.metaValue)); + this.selectFilterSubject.next(this.removeFilters(option.metaValue)); break; default: - assertUnreachable(changed.option); + assertUnreachable(option); } + } - // Update checkbox option label - - this.checkboxControls$ = forkJoinSafeEmpty( - this.model.getCheckboxControlOptions().map(checkboxControlModel => - checkboxControlModel.getOptions().pipe( - take(1), - map(options => { - options.forEach(option => { - if (this.isLabeledOptionMatch(option, changed.option)) { - checkboxControlModel.checked = changed.option.value; - } - }); - - return { - label: checkboxControlModel.checked ? options[0].label : options[1].label, - value: checkboxControlModel.checked, - options: options - }; - }) + public onCheckboxChange(changed: TableCheckboxChange): void { + this.publishCheckboxOptionChange(changed.option); + + this.checkboxControls$ = this.getCheckboxControls(changed).pipe( + tap(tableCheckboxControls => this.updateCheckboxPreferences(tableCheckboxControls)) + ); + } + + private updateCheckboxPreferences(tableCheckboxControls: TableCheckboxControl[]): void { + if (isNonEmptyString(this.model.getId())) { + this.getPreferences().subscribe( + preferences => this.setPreferences({ + ...preferences, + checkboxes: tableCheckboxControls + }) + ); + } + } + + private getCheckboxControls(changed?: TableCheckboxChange): Observable { + return this.getPreferences().pipe( + switchMap(preferences => forkJoinSafeEmpty( + this.model + .getCheckboxControlOptions() + .filter(checkboxControlModel => checkboxControlModel.visible) + .map(checkboxControlModel => + checkboxControlModel.getOptions().pipe( + take(1), + map((options: TableCheckboxOptions) => { + if (changed !== undefined) { + options.forEach(option => { + if (this.isLabeledOptionMatch(option, changed.option)) { + checkboxControlModel.checked = changed.option.value; + } + }); + + return { + label: checkboxControlModel.checked ? options[0].label : options[1].label, + value: checkboxControlModel.checked, + options: options + }; + } + + const found = preferences.checkboxes ? preferences.checkboxes + .find(tableCheckboxControl => options + .some(option => option.label === tableCheckboxControl.label)) + : undefined; + + return found ?? { + label: checkboxControlModel.checked ? options[0].label : options[1].label, + value: checkboxControlModel.checked, + options: options + }; + }) + ) + ) ) ) ); @@ -357,7 +384,7 @@ export class TableWidgetRendererComponent this.getViewPreferences().subscribe( preferences => this.setViewPreferences({ ...preferences, - activeViewItem: view + activeView: view }) ); } @@ -399,11 +426,11 @@ export class TableWidgetRendererComponent return !isEmpty(matchedSelectionHandlers) ? matchedSelectionHandlers[0].handler : undefined; } - private hydratePersistedActiveViewItem( + private hydratePersistedActiveView( viewItems: ToggleItem[], - persistedActiveViewItem?: string + persistedActiveView?: string ): ToggleItem { - return persistedActiveViewItem ? this.buildViewItem(persistedActiveViewItem) : viewItems[TableWidgetRendererComponent.DEFAULT_TAB_INDEX]; + return persistedActiveView ? this.buildViewItem(persistedActiveView) : viewItems[TableWidgetRendererComponent.DEFAULT_TAB_INDEX]; } private hydratePersistedColumnConfigs( @@ -430,15 +457,11 @@ export class TableWidgetRendererComponent private getViewPreferences(): Observable { return isNonEmptyString(this.model.viewId) - ? this.preferenceService.get(this.model.viewId!, {}).pipe( - first(), - tap(preferences => console.debug('getViewPreferences', this.model.viewId, preferences)) - ) + ? this.preferenceService.get(this.model.viewId!, {}).pipe(first()) : of({}); } private setViewPreferences(preferences: TableWidgetViewPreferences): void { - console.debug('setViewPreferences', this.model.viewId, preferences); if (isNonEmptyString(this.model.viewId)) { this.preferenceService.set(this.model.viewId!, preferences); } @@ -448,15 +471,12 @@ export class TableWidgetRendererComponent defaultPreferences: TableWidgetPreferences = TableWidgetRendererComponent.DEFAULT_PREFERENCES ): Observable { return isNonEmptyString(this.model.getId()) - ? this.preferenceService.get(this.model.getId()!, defaultPreferences).pipe( - first(), - tap(preferences => console.info('getPreferences', this.model.getId(), preferences)) - ) + ? this.preferenceService.get(this.model.getId()!, defaultPreferences).pipe(first()) : of(defaultPreferences); } private setPreferences(preferences: TableWidgetPreferences): void { - console.info('setPreferences', this.model.getId(), preferences); + console.trace('setPreferences', this.model.getId(), preferences); if (isNonEmptyString(this.model.getId())) { this.preferenceService.set(this.model.getId()!, preferences); } @@ -488,11 +508,12 @@ export class TableWidgetRendererComponent } interface TableWidgetViewPreferences { - activeViewItem?: string; + activeView?: string; } interface TableWidgetPreferences { - columns: PersistedTableColumnConfig[]; + columns?: PersistedTableColumnConfig[]; + checkboxes?: TableCheckboxControl[]; } type PersistedTableColumnConfig = Pick; From dab238b6a6e78f4b4aaf9685c9bbac46e83fe2c2 Mon Sep 17 00:00:00 2001 From: Jake Bassett Date: Fri, 22 Oct 2021 13:03:15 -0700 Subject: [PATCH 4/7] feat: add persistance for select filters --- .../controls/table-controls.component.ts | 1 - .../table/table-widget-renderer.component.ts | 119 ++++++++++++------ 2 files changed, 84 insertions(+), 36 deletions(-) diff --git a/projects/components/src/table/controls/table-controls.component.ts b/projects/components/src/table/controls/table-controls.component.ts index 3064e0aa4..c3fd9605d 100644 --- a/projects/components/src/table/controls/table-controls.component.ts +++ b/projects/components/src/table/controls/table-controls.component.ts @@ -161,7 +161,6 @@ export class TableControlsComponent implements OnChanges { } if (changes.checkboxControls) { - console.info('checkboxControl change', this.checkboxControls); this.diffCheckboxes(); } diff --git a/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts b/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts index a296630c5..0030b2059 100644 --- a/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts +++ b/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts @@ -23,6 +23,7 @@ import { TableRow, TableSelectChange, TableSelectControl, + TableSelectControlOption, TableSelectionMode, TableStyle, ToggleItem, @@ -170,24 +171,60 @@ export class TableWidgetRendererComponent } protected fetchAndPopulateSelectControls(): void { - this.selectControls$ = forkJoinSafeEmpty( - this.model - .getSelectControlOptions() - .filter(checkboxControlModel => checkboxControlModel.visible) - .map(selectControlModel => - // Fetch the values for the selectFilter dropdown - selectControlModel.getOptions().pipe( - take(1), - withLatestFrom(this.selectFilterSubject), - map(([options, filters]) => ({ - placeholder: selectControlModel.placeholder, - options: options.map(option => ({ - ...option, - applied: this.isFilterApplied(option.metaValue, filters) - })) - })) - ) - ) + this.selectControls$ = this.getSelectControls().pipe( + tap((selectControls: TableSelectControl[]) => { + selectControls.forEach(selectControl => + this.publishSelectValuesChange(selectControl.options[0].metaValue.field, selectControl.options) + ); + }) + ); + } + + protected fetchAndPopulateCheckboxControls(): void { + this.checkboxControls$ = this.getCheckboxControls().pipe( + tap((checkboxControls: TableCheckboxControl[]) => { + checkboxControls.forEach(checkboxControl => + this.publishCheckboxOptionChange(checkboxControl.value ? checkboxControl.options[0] : checkboxControl.options[1]) + ); + }) + ); + } + + + private getSelectControls(changed?: TableSelectControl): Observable { + return this.getPreferences().pipe( + take(1), + switchMap(preferences => forkJoinSafeEmpty( + this.model + .getSelectControlOptions() + .filter(selectControlModel => selectControlModel.visible) + .map(selectControlModel => { + + if (selectControlModel.placeholder === changed?.placeholder) { + return of(changed); + } + + // Fetch the values for the selectFilter dropdown + return selectControlModel.getOptions().pipe( + take(1), + withLatestFrom(this.selectFilterSubject), + map(([options, filters]) => { + + const foundPreferences = preferences.selections ? preferences.selections + .find(preferencesSelectionControl => (selectControlModel.placeholder === preferencesSelectionControl.placeholder)) + : undefined; + + return foundPreferences ?? { + placeholder: selectControlModel.placeholder, + options: options.map(option => ({ + ...option, + applied: this.isFilterApplied(option.metaValue, filters) + })) + }; + }) + ); + }) + )) ); } @@ -262,30 +299,41 @@ export class TableWidgetRendererComponent } public onSelectChange(changed: TableSelectChange): void { - if (changed.values.length === 0) { - this.selectFilterSubject.next(this.removeFilters(changed.select.options[0].metaValue.field)); + /* + * The caller doesn't modify the values, it just returns an array of which values are selected. + * We must apply the value change to the object, so we set all to false unless found in the changed value array. + */ + changed.select.options.forEach(option => + option.applied = changed.values.find(changedOption => changedOption.label === option.label) !== undefined + ); + this.publishSelectValuesChange(changed.select.options[0].metaValue.field, changed.values); + + this.getSelectControls(changed.select).subscribe(tableSelectControls => + this.updateSelectionPreferences(tableSelectControls) + ); + } + + private publishSelectValuesChange(field: string, values: TableSelectControlOption[]): void { + if (values.length === 0) { + this.selectFilterSubject.next(this.removeFilters(field)); return; } - const tableFilters: TableFilter[] = changed.values.map((option: TableFilterControlOption) => option.metaValue); + const tableFilters: TableFilter[] = values.map((option: TableFilterControlOption) => option.metaValue); this.selectFilterSubject.next(this.mergeFilters(toInFilter(tableFilters))); } - protected fetchAndPopulateCheckboxControls(): void { - this.checkboxControls$ = this.getCheckboxControls() - .pipe( - tap((checkboxControls: TableCheckboxControl[]) => { - checkboxControls.forEach(checkboxControl => - this.publishCheckboxOptionChange(checkboxControl.value ? checkboxControl.options[0] : checkboxControl.options[1]) - // this.onCheckboxChange({ - // checkbox: checkboxControl, - // option: checkboxControl.value ? checkboxControl.options[0] : checkboxControl.options[1] - // }, false); - ); + private updateSelectionPreferences(tableSelectControls: TableSelectControl[]): void { + if (isNonEmptyString(this.model.getId())) { + this.getPreferences().subscribe( + preferences => this.setPreferences({ + ...preferences, + selections: tableSelectControls }) ); + } } private publishCheckboxOptionChange(option: TableCheckboxControlOption): void { @@ -348,8 +396,8 @@ export class TableWidgetRendererComponent } const found = preferences.checkboxes ? preferences.checkboxes - .find(tableCheckboxControl => options - .some(option => option.label === tableCheckboxControl.label)) + .find(preferencesCheckboxControl => options + .some(option => (option.label === preferencesCheckboxControl.label))) : undefined; return found ?? { @@ -476,7 +524,7 @@ export class TableWidgetRendererComponent } private setPreferences(preferences: TableWidgetPreferences): void { - console.trace('setPreferences', this.model.getId(), preferences); + // console.trace('setPreferences', this.model.getId(), preferences); if (isNonEmptyString(this.model.getId())) { this.preferenceService.set(this.model.getId()!, preferences); } @@ -514,6 +562,7 @@ interface TableWidgetViewPreferences { interface TableWidgetPreferences { columns?: PersistedTableColumnConfig[]; checkboxes?: TableCheckboxControl[]; + selections?: TableSelectControl[]; } type PersistedTableColumnConfig = Pick; From 349a3b7d84643202f94670371ebf272da8f98bed Mon Sep 17 00:00:00 2001 From: Jake Bassett Date: Fri, 22 Oct 2021 13:25:25 -0700 Subject: [PATCH 5/7] feat: fix publishSelectValues call --- .../dashboard/widgets/table/table-widget-renderer.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts b/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts index bdd609c7b..2785b4453 100644 --- a/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts +++ b/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts @@ -186,7 +186,7 @@ export class TableWidgetRendererComponent this.selectControls$ = this.getSelectControls().pipe( tap((selectControls: TableSelectControl[]) => { selectControls.forEach(selectControl => - this.publishSelectValuesChange(selectControl.options[0].metaValue.field, selectControl.options) + this.publishSelectValuesChange(selectControl.options[0].metaValue.field, selectControl.options.filter(o => o.applied)) ); }) ); From b4bc59a877f0544559755d9b16ba770c4f41259a Mon Sep 17 00:00:00 2001 From: Jake Bassett Date: Fri, 22 Oct 2021 13:31:12 -0700 Subject: [PATCH 6/7] style: prettier --- .../controls/table-controls.component.ts | 6 +- .../table/table-widget-renderer.component.ts | 221 ++++++++++-------- 2 files changed, 125 insertions(+), 102 deletions(-) diff --git a/projects/components/src/table/controls/table-controls.component.ts b/projects/components/src/table/controls/table-controls.component.ts index 003aa5732..1606362e0 100644 --- a/projects/components/src/table/controls/table-controls.component.ts +++ b/projects/components/src/table/controls/table-controls.component.ts @@ -144,8 +144,10 @@ export class TableControlsComponent implements OnChanges { @Output() public readonly viewChange: EventEmitter = new EventEmitter(); - private readonly selectSelections: Map = new Map(); + private readonly selectSelections: Map = new Map< + TableSelectControl, + TableSelectControlOption[] + >(); public checkboxSelections: string[] = []; private readonly checkboxDiffer?: IterableDiffer; diff --git a/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts b/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts index 2785b4453..514980fe2 100644 --- a/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts +++ b/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts @@ -12,7 +12,8 @@ import { FilterOperator, StatefulTableRow, TableCheckboxChange, - TableCheckboxControl, TableCheckboxControlOption, + TableCheckboxControl, + TableCheckboxControlOption, TableCheckboxOptions, TableColumnConfig, TableControlOption, @@ -43,6 +44,7 @@ import { SpecificationBackedTableColumnDef } from './table-widget-column.model'; import { TableWidgetViewToggleModel } from './table-widget-view-toggle.model'; import { TableWidgetModel } from './table-widget.model'; +// tslint:disable: max-file-line-count @Renderer({ modelClass: TableWidgetModel }) @Renderer({ modelClass: TableWidgetViewToggleModel }) @Component({ @@ -131,7 +133,9 @@ export class TableWidgetRendererComponent private readonly searchFilterSubject: Subject = new BehaviorSubject([]); private readonly selectFilterSubject: BehaviorSubject = new BehaviorSubject([]); - private readonly queryPropertiesSubject: BehaviorSubject> = new BehaviorSubject>({}); + private readonly queryPropertiesSubject: BehaviorSubject> = new BehaviorSubject< + Dictionary + >({}); public queryProperties$: Observable> = this.queryPropertiesSubject.asObservable(); public constructor( @@ -186,7 +190,10 @@ export class TableWidgetRendererComponent this.selectControls$ = this.getSelectControls().pipe( tap((selectControls: TableSelectControl[]) => { selectControls.forEach(selectControl => - this.publishSelectValuesChange(selectControl.options[0].metaValue.field, selectControl.options.filter(o => o.applied)) + this.publishSelectValuesChange( + selectControl.options[0].metaValue.field, + selectControl.options.filter(o => o.applied) + ) ); }) ); @@ -196,47 +203,53 @@ export class TableWidgetRendererComponent this.checkboxControls$ = this.getCheckboxControls().pipe( tap((checkboxControls: TableCheckboxControl[]) => { checkboxControls.forEach(checkboxControl => - this.publishCheckboxOptionChange(checkboxControl.value ? checkboxControl.options[0] : checkboxControl.options[1]) + this.publishCheckboxOptionChange( + checkboxControl.value ? checkboxControl.options[0] : checkboxControl.options[1] + ) ); }) ); } - private getSelectControls(changed?: TableSelectControl): Observable { return this.getPreferences().pipe( take(1), - switchMap(preferences => forkJoinSafeEmpty( - this.model - .getSelectControlOptions() - .filter(selectControlModel => selectControlModel.visible) - .map(selectControlModel => { - - if (selectControlModel.placeholder === changed?.placeholder) { - return of(changed); - } - - // Fetch the values for the selectFilter dropdown - return selectControlModel.getOptions().pipe( - take(1), - withLatestFrom(this.selectFilterSubject), - map(([options, filters]) => { - - const foundPreferences = preferences.selections ? preferences.selections - .find(preferencesSelectionControl => (selectControlModel.placeholder === preferencesSelectionControl.placeholder)) - : undefined; - - return foundPreferences ?? { - placeholder: selectControlModel.placeholder, - options: options.map(option => ({ - ...option, - applied: this.isFilterApplied(option.metaValue, filters) - })) - }; - }) - ); - }) - )) + switchMap(preferences => + forkJoinSafeEmpty( + this.model + .getSelectControlOptions() + .filter(selectControlModel => selectControlModel.visible) + .map(selectControlModel => { + if (selectControlModel.placeholder === changed?.placeholder) { + return of(changed); + } + + // Fetch the values for the selectFilter dropdown + return selectControlModel.getOptions().pipe( + take(1), + withLatestFrom(this.selectFilterSubject), + map(([options, filters]) => { + const foundPreferences = preferences.selections + ? preferences.selections.find( + preferencesSelectionControl => + selectControlModel.placeholder === preferencesSelectionControl.placeholder + ) + : undefined; + + return ( + foundPreferences ?? { + placeholder: selectControlModel.placeholder, + options: options.map(option => ({ + ...option, + applied: this.isFilterApplied(option.metaValue, filters) + })) + } + ); + }) + ); + }) + ) + ) ); } @@ -271,24 +284,26 @@ export class TableWidgetRendererComponent private getColumnConfigs(): Observable { return this.getPreferences().pipe( - switchMap(preferences => combineLatest([ - this.getScope(), - this.api.change$.pipe( - map(() => true), - startWith(true) + switchMap(preferences => + combineLatest([ + this.getScope(), + this.api.change$.pipe( + map(() => true), + startWith(true) + ) + ]).pipe( + switchMap(([scope]) => this.model.getColumns(scope)), + startWith([]), + map((columns: SpecificationBackedTableColumnDef[]) => + this.hydratePersistedColumnConfigs(columns, preferences.columns ?? []) + ), + pairwise(), + filter(([previous, current]) => !isEqualIgnoreFunctions(previous, current)), + map(([_, current]) => current), + share(), + tap(() => this.onDashboardRefresh()) ) - ]).pipe( - switchMap(([scope]) => this.model.getColumns(scope)), - startWith([]), - map((columns: SpecificationBackedTableColumnDef[]) => - this.hydratePersistedColumnConfigs(columns, preferences.columns ?? []) - ), - pairwise(), - filter(([previous, current]) => !isEqualIgnoreFunctions(previous, current)), - map(([_, current]) => current), - share(), - tap(() => this.onDashboardRefresh()) - )) + ) ); } @@ -315,8 +330,9 @@ export class TableWidgetRendererComponent * The caller doesn't modify the values, it just returns an array of which values are selected. * We must apply the value change to the object, so we set all to false unless found in the changed value array. */ - changed.select.options.forEach(option => - option.applied = changed.values.find(changedOption => changedOption.label === option.label) !== undefined + changed.select.options.forEach( + option => + (option.applied = changed.values.find(changedOption => changedOption.label === option.label) !== undefined) ); this.publishSelectValuesChange(changed.select.options[0].metaValue.field, changed.values); @@ -339,8 +355,8 @@ export class TableWidgetRendererComponent private updateSelectionPreferences(tableSelectControls: TableSelectControl[]): void { if (isNonEmptyString(this.model.getId())) { - this.getPreferences().subscribe( - preferences => this.setPreferences({ + this.getPreferences().subscribe(preferences => + this.setPreferences({ ...preferences, selections: tableSelectControls }) @@ -374,8 +390,8 @@ export class TableWidgetRendererComponent private updateCheckboxPreferences(tableCheckboxControls: TableCheckboxControl[]): void { if (isNonEmptyString(this.model.getId())) { - this.getPreferences().subscribe( - preferences => this.setPreferences({ + this.getPreferences().subscribe(preferences => + this.setPreferences({ ...preferences, checkboxes: tableCheckboxControls }) @@ -385,41 +401,45 @@ export class TableWidgetRendererComponent private getCheckboxControls(changed?: TableCheckboxChange): Observable { return this.getPreferences().pipe( - switchMap(preferences => forkJoinSafeEmpty( - this.model - .getCheckboxControlOptions() - .filter(checkboxControlModel => checkboxControlModel.visible) - .map(checkboxControlModel => - checkboxControlModel.getOptions().pipe( - take(1), - map((options: TableCheckboxOptions) => { - if (changed !== undefined) { - options.forEach(option => { - if (this.isLabeledOptionMatch(option, changed.option)) { - checkboxControlModel.checked = changed.option.value; + switchMap(preferences => + forkJoinSafeEmpty( + this.model + .getCheckboxControlOptions() + .filter(checkboxControlModel => checkboxControlModel.visible) + .map(checkboxControlModel => + checkboxControlModel.getOptions().pipe( + take(1), + map((options: TableCheckboxOptions) => { + if (changed !== undefined) { + options.forEach(option => { + if (this.isLabeledOptionMatch(option, changed.option)) { + checkboxControlModel.checked = changed.option.value; + } + }); + + return { + label: checkboxControlModel.checked ? options[0].label : options[1].label, + value: checkboxControlModel.checked, + options: options + }; + } + + const found = preferences.checkboxes + ? preferences.checkboxes.find(preferencesCheckboxControl => + options.some(option => option.label === preferencesCheckboxControl.label) + ) + : undefined; + + return ( + found ?? { + label: checkboxControlModel.checked ? options[0].label : options[1].label, + value: checkboxControlModel.checked, + options: options } - }); - - return { - label: checkboxControlModel.checked ? options[0].label : options[1].label, - value: checkboxControlModel.checked, - options: options - }; - } - - const found = preferences.checkboxes ? preferences.checkboxes - .find(preferencesCheckboxControl => options - .some(option => (option.label === preferencesCheckboxControl.label))) - : undefined; - - return found ?? { - label: checkboxControlModel.checked ? options[0].label : options[1].label, - value: checkboxControlModel.checked, - options: options - }; - }) + ); + }) + ) ) - ) ) ) ); @@ -441,8 +461,8 @@ export class TableWidgetRendererComponent public onViewChange(view: string): void { this.model.setView(view); if (isNonEmptyString(this.model.getId())) { - this.getViewPreferences().subscribe( - preferences => this.setViewPreferences({ + this.getViewPreferences().subscribe(preferences => + this.setViewPreferences({ ...preferences, activeView: view }) @@ -453,8 +473,8 @@ export class TableWidgetRendererComponent public onColumnsChange(columns: TableColumnConfig[]): void { if (isNonEmptyString(this.model.getId())) { - this.getPreferences().subscribe( - preferences => this.setPreferences({ + this.getPreferences().subscribe(preferences => + this.setPreferences({ ...preferences, columns: columns.map(column => this.dehydratePersistedColumnConfig(column)) }) @@ -492,7 +512,9 @@ export class TableWidgetRendererComponent viewItems: ToggleItem[], persistedActiveView?: string ): ToggleItem { - return persistedActiveView ? this.buildViewItem(persistedActiveView) : viewItems[TableWidgetRendererComponent.DEFAULT_TAB_INDEX]; + return persistedActiveView !== undefined + ? this.buildViewItem(persistedActiveView) + : viewItems[TableWidgetRendererComponent.DEFAULT_TAB_INDEX]; } private hydratePersistedColumnConfigs( @@ -538,17 +560,16 @@ export class TableWidgetRendererComponent } private setPreferences(preferences: TableWidgetPreferences): void { - // console.trace('setPreferences', this.model.getId(), preferences); if (isNonEmptyString(this.model.getId())) { this.preferenceService.set(this.model.getId()!, preferences); } } private buildViewItem(viewOption: string): ToggleItem { - return ({ + return { label: capitalize(viewOption), value: viewOption - }); + }; } private mergeFilters(tableFilter: TableFilter): TableFilter[] { From 400548e7da3dc0706c25056fd2ce7df8e058575d Mon Sep 17 00:00:00 2001 From: Jake Bassett Date: Fri, 22 Oct 2021 14:14:10 -0700 Subject: [PATCH 7/7] style: linting --- .../widgets/table/table-widget-renderer.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts b/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts index 514980fe2..7202d1b3c 100644 --- a/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts +++ b/projects/observability/src/shared/dashboard/widgets/table/table-widget-renderer.component.ts @@ -541,13 +541,13 @@ export class TableWidgetRendererComponent private getViewPreferences(): Observable { return isNonEmptyString(this.model.viewId) - ? this.preferenceService.get(this.model.viewId!, {}).pipe(first()) + ? this.preferenceService.get(this.model.viewId, {}).pipe(first()) : of({}); } private setViewPreferences(preferences: TableWidgetViewPreferences): void { if (isNonEmptyString(this.model.viewId)) { - this.preferenceService.set(this.model.viewId!, preferences); + this.preferenceService.set(this.model.viewId, preferences); } }