-
Notifications
You must be signed in to change notification settings - Fork 11
Table multiselect filters #823
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6b15f78
9b944d5
04170b0
d38bb9d
21c070b
2f62087
9f3e276
ce59e8e
d352aa3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,58 +1,83 @@ | ||
import { Dictionary } from '@hypertrace/common'; | ||
import { SelectOption } from '../../select/select-option'; | ||
import { FilterOperator } from '../../filtering/filter/filter-operators'; | ||
import { TableFilter } from '../table-api'; | ||
|
||
export interface SelectControl { | ||
placeholder?: string; | ||
default?: SelectOption<TableControlOption>; | ||
options: SelectOption<TableControlOption>[]; | ||
export const enum TableControlOptionType { | ||
Filter = 'filter', | ||
Property = 'property', | ||
Unset = 'unset' | ||
} | ||
|
||
export interface SelectChange { | ||
select: SelectControl; | ||
value: TableControlOption; | ||
} | ||
export type TableControlOption = TableUnsetControlOption | TableFilterControlOption | TablePropertyControlOption; | ||
|
||
export interface CheckboxControl { | ||
export interface TableFilterControlOption { | ||
type: TableControlOptionType.Filter; | ||
label: string; | ||
value: boolean; | ||
options: TableCheckboxOptions; | ||
metaValue: TableFilter; | ||
} | ||
|
||
export interface CheckboxChange { | ||
checkbox: CheckboxControl; | ||
option: TableControlOption<boolean>; | ||
export interface TableUnsetControlOption { | ||
type: TableControlOptionType.Unset; | ||
label: string; | ||
metaValue: string; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is meta value supposed to do? How is it different than 'value' ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please see this comment below. |
||
} | ||
|
||
export const enum TableControlOptionType { | ||
Filter = 'filter', | ||
Property = 'property', | ||
UnsetFilter = 'unset-filter' | ||
export interface TablePropertyControlOption { | ||
type: TableControlOptionType.Property; | ||
label: string; | ||
metaValue: Dictionary<unknown>; | ||
} | ||
|
||
export type TableControlOption<T = unknown> = | ||
| TableUnsetFilterControlOption<T> | ||
| TableFilterControlOption<T> | ||
| TablePropertyControlOption<T>; | ||
/* | ||
* Select Control | ||
*/ | ||
|
||
interface TableControlOptionBase<T> { | ||
value?: T; | ||
export interface TableSelectControl { | ||
placeholder: string; | ||
options: TableSelectControlOption[]; | ||
} | ||
export interface TableUnsetFilterControlOption<T = unknown> extends TableControlOptionBase<T> { | ||
type: TableControlOptionType.UnsetFilter; | ||
metaValue: string; | ||
|
||
export interface TableSelectChange { | ||
select: TableSelectControl; | ||
values: TableSelectControlOption[]; | ||
} | ||
|
||
export interface TableFilterControlOption<T = unknown> extends TableControlOptionBase<T> { | ||
type: TableControlOptionType.Filter; | ||
metaValue: TableFilter; | ||
export type TableSelectControlOption = TableFilterControlOption; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we really need so many different types? Like below where you specify metaValue type
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't add them just for fun! 😂 But valid question. I explain a little more in this comment. |
||
|
||
/* | ||
* Checkbox Control | ||
*/ | ||
|
||
export interface TableCheckboxControl { | ||
label: string; | ||
value: boolean; | ||
options: TableCheckboxOptions; | ||
} | ||
|
||
export interface TablePropertyControlOption<T = unknown> extends TableControlOptionBase<T> { | ||
type: TableControlOptionType.Property; | ||
metaValue: Dictionary<unknown>; | ||
export interface TableCheckboxChange { | ||
checkbox: TableCheckboxControl; | ||
option: TableCheckboxControlOption; | ||
} | ||
|
||
export type TableCheckboxControlOption<T extends boolean> = TableControlOption<T> & { label: string }; | ||
export type TableCheckboxControlOption<T = boolean> = TableControlOption & { | ||
value: T; | ||
}; | ||
|
||
export type TableCheckboxOptions = [TableCheckboxControlOption<true>, TableCheckboxControlOption<false>]; | ||
|
||
/* | ||
* Util | ||
*/ | ||
|
||
export const toInFilter = (tableFilters: TableFilter[]): TableFilter => | ||
tableFilters.reduce((previousValue, currentValue) => { | ||
if (currentValue.operator !== FilterOperator.Equals || previousValue.field !== currentValue.field) { | ||
throw Error('Filters must all contain same field and use = operator'); | ||
} | ||
|
||
return { | ||
field: previousValue.field, | ||
operator: FilterOperator.In, | ||
value: [...(Array.isArray(previousValue.value) ? previousValue.value : [previousValue.value]), currentValue.value] | ||
}; | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,7 @@ | ||
import { TableControlOption } from '@hypertrace/components'; | ||
import { Observable } from 'rxjs'; | ||
import { LabeledTableControlOption } from '../../widgets/table/table-widget-control.model'; | ||
import { GraphQlDataSourceModel } from './graphql-data-source.model'; | ||
|
||
export abstract class GraphqlTableControlOptionsDataSourceModel extends GraphQlDataSourceModel< | ||
LabeledTableControlOption[] | ||
> { | ||
public abstract getData(): Observable<LabeledTableControlOption[]>; | ||
export abstract class GraphqlTableControlOptionsDataSourceModel extends GraphQlDataSourceModel<TableControlOption[]> { | ||
public abstract getData(): Observable<TableControlOption[]>; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import { TableCheckboxOptions, TableControlOption } from '@hypertrace/components'; | ||
import { hasOwnProperty } from '@hypertrace/common'; | ||
import { TableCheckboxControlOption, TableCheckboxOptions, TableControlOption } from '@hypertrace/components'; | ||
import { BOOLEAN_PROPERTY, Model, ModelProperty } from '@hypertrace/hyperdash'; | ||
import { Observable } from 'rxjs'; | ||
import { map } from 'rxjs/operators'; | ||
|
@@ -7,7 +8,7 @@ import { TableWidgetControlModel } from './table-widget-control.model'; | |
@Model({ | ||
type: 'table-widget-checkbox-option' | ||
}) | ||
export class TableWidgetControlCheckboxOptionModel extends TableWidgetControlModel { | ||
export class TableWidgetControlCheckboxOptionModel extends TableWidgetControlModel<TableCheckboxControlOption> { | ||
@ModelProperty({ | ||
key: 'checked', | ||
displayName: 'Checked', | ||
|
@@ -19,7 +20,7 @@ export class TableWidgetControlCheckboxOptionModel extends TableWidgetControlMod | |
public getOptions(): Observable<TableCheckboxOptions> { | ||
return super.getOptions().pipe( | ||
map(options => { | ||
if (!this.isValidCheckboxControlOption(options)) { | ||
if (!this.isValidCheckboxControlOptions(options)) { | ||
throw Error(`Invalid table widget checkbox data source for options '${JSON.stringify(options)}'`); | ||
} | ||
|
||
|
@@ -31,7 +32,10 @@ export class TableWidgetControlCheckboxOptionModel extends TableWidgetControlMod | |
); | ||
} | ||
|
||
private isValidCheckboxControlOption(options: TableControlOption[]): options is TableCheckboxOptions { | ||
return options.length === 2 && options.every(option => typeof option.value === 'boolean'); | ||
private isValidCheckboxControlOptions(options: TableControlOption[]): options is TableCheckboxOptions { | ||
return ( | ||
options.length === 2 && | ||
options.every(option => hasOwnProperty(option, 'value') && typeof option.value === 'boolean') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am yet to understand the inheritance in the table control options. value property seems to be defined at only one place. We can also use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, they are confusing. Fortunately it got a little bit cleaner with this PR. Correct, that Both select and checkbox controls have a There are two other cases with query info, but they are now only used for checkbox controls. In addition to the The So, the reason that checkbox has a Not sure if that explains it or makes it more confusing, but happy to expand on anything. |
||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,34 @@ | ||
import { TableControlOption, TableControlOptionType, TableSelectControlOption } from '@hypertrace/components'; | ||
import { Model, ModelProperty, STRING_PROPERTY } from '@hypertrace/hyperdash'; | ||
import { Observable } from 'rxjs'; | ||
import { map } from 'rxjs/operators'; | ||
import { TableWidgetControlModel } from './table-widget-control.model'; | ||
|
||
@Model({ | ||
type: 'table-widget-select-option' | ||
}) | ||
export class TableWidgetControlSelectOptionModel extends TableWidgetControlModel { | ||
export class TableWidgetControlSelectOptionModel extends TableWidgetControlModel<TableSelectControlOption> { | ||
@ModelProperty({ | ||
key: 'placeholder', | ||
displayName: 'Placeholder', | ||
type: STRING_PROPERTY.type | ||
type: STRING_PROPERTY.type, | ||
required: true | ||
}) | ||
public placeholder?: string; | ||
public placeholder!: string; | ||
|
||
public getOptions(): Observable<TableSelectControlOption[]> { | ||
return super.getOptions().pipe( | ||
map(options => { | ||
if (!this.isValidSelectControlOptions(options)) { | ||
throw Error(`Invalid table widget select data source for options '${JSON.stringify(options)}'`); | ||
} | ||
|
||
return options; | ||
}) | ||
); | ||
} | ||
|
||
private isValidSelectControlOptions(options: TableControlOption[]): options is TableSelectControlOption[] { | ||
return options.every(option => option.type === TableControlOptionType.Filter); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is a property control option? any visual example?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see this comment below.