-
Notifications
You must be signed in to change notification settings - Fork 7
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
feat: add custom filter function #632
base: development
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
src/components/Search/utils.ts
Outdated
let searchTerm = text || '' | ||
let nestedQuery | ||
if (tags) { | ||
filters.push(getFilterTerm('metadata.tags.keyword', tags)) | ||
} else if (gaiax) { |
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.
question(blocking): Is this query not compatible with tags or why is it only applied if tags
is falsy?
src/@utils/aquarius/index.ts
Outdated
export function getFilter(...args: any[]) { | ||
let filters = [] | ||
if (typeof args[0] === 'object') { | ||
args[0].forEach((arg) => { |
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.
suggestion(blocking): In general prefer usage of for...of
over forEach
for readability and performance. More context: https://biomejs.dev/linter/rules/no-for-each/
This comment applies to all places in the code where forEach
is being used.
…ery interface and FILTER_VALUES, update getSearchQuery function
interface BoolFilter { | ||
bool: BoolFilterQuery | ||
} | ||
|
||
interface BoolFilterQuery { | ||
must: { | ||
exists: { | ||
field: string | ||
} | ||
} | ||
must_not?: { | ||
term: { | ||
[key: string]: string | ||
} | ||
} | ||
} | ||
|
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.
suggestion(blocking): The BoolFilterQuery
type is named to generally for what it does. Specifically these are the type definitions for the new must_exist
and must_exits_and_not_empty
filters of this PR. Naming these accordingly is suggested (e.g. MustExistQuery
and MustNotTermQuery
or similar)
I also suggest to rename the key
identifier to field
to better communicate what value is expected here.
interface BoolFilter { | ||
bool: BoolFilterQuery | ||
} | ||
|
||
interface BoolFilterQuery { | ||
must: { | ||
exists: { | ||
field: string | ||
} | ||
} | ||
must_not?: { | ||
term: { | ||
[key: string]: string | ||
} | ||
} | ||
} |
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.
suggestion(non-blocking): this is also a nice use-case for typescript generics
In our case, these filters should always be used on a field path that is to be defined by the user. We expect a certain behaviour though, e.g. something like the following could improve DX with TS, as it helps enforcing correct types (in this case the field path value).
type FieldPath = string
interface BoolFilter<T extends FieldPath> {
bool: MustExistQuery<T> & MustNotTermQuery<T>
}
interface MustExistQuery<T extends FieldPath> {
must: {
exists: {
field: T
}
}
}
interface MustNotTermQuery<T extends FieldPath> {
must_not?: {
term: {
[field in T]: string
}
}
}
@@ -11,6 +28,7 @@ interface BaseQueryParams { | |||
sortOptions?: SortOptions | |||
aggs?: any | |||
filters?: FilterTerm[] | |||
boolFilter?: BoolFilter[] |
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.
issue(blocking): i don't think this is supported by elasticsearch (array of bool
) and should be adjusted.
suggestion: we could treat it like filters, where we define what the BoolTerm
should look like and then allow passing an array BoolTerm[]
here.
Also possible is to only allow the defined type to be passed, e.g. BoolFilter
src/@utils/aquarius/index.ts
Outdated
@@ -56,6 +57,39 @@ export function getFilterTerm( | |||
} | |||
} | |||
|
|||
export function getFilter(...args: any[]) { |
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.
issue(blocking): we should try not to use any
as type here. If it is needed, we need to add a comment disabling eslint for this line and describing why the any
type is used
src/@utils/aquarius/index.ts
Outdated
const filter = arg.split('=') | ||
filters = [...filters, 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.
suggestion(blocking): move this code to a named function and reuse it to increase readability
src/@utils/aquarius/index.ts
Outdated
@@ -160,7 +197,8 @@ export function generateBaseQuery( | |||
...(baseQueryParams.showSaas === false ? [saasFieldExists] : []) | |||
] | |||
} | |||
} | |||
}, | |||
...(baseQueryParams.boolFilter || []) |
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.
suggestion(non-blocking): use an empty object rather than empty array for better readability of the code.
src/components/Search/Filter.tsx
Outdated
let updatedFilters | ||
if (option.queryPath) { | ||
updatedFilters = filters[filterId].includes( | ||
`${option.queryPath}=${option.value}` |
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.
suggestion(blocking): make this re-usable by wrapping it into a named function. Can then be accessed in the various places in code (e.g. getFilterQueryString
or similar)
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.
this also will get more readable once adapting existing filters to the new, more flexible structure and a lot of code can be removed here.
src/components/Search/Filter.tsx
Outdated
? { | ||
...filters, | ||
[filterId]: filters[filterId].filter( | ||
(e) => e !== `${option.queryPath}=${option.value}` |
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.
suggestion(blocking): avoid shorthand variable name and replace with more readable variant
filters.config.js
Outdated
{ | ||
id: 'serviceType', | ||
label: 'Service Type', | ||
type: 'filterList', | ||
options: [ | ||
{ label: 'datasets', value: FilterByTypeOptions.Data }, | ||
{ label: 'algorithms', value: FilterByTypeOptions.Algorithm }, | ||
{ label: 'saas', value: FilterByTypeOptions.Saas } | ||
] | ||
}, | ||
{ | ||
id: 'accessType', | ||
label: 'Access Type', | ||
type: 'filterList', | ||
options: [ | ||
{ label: 'download', value: FilterByAccessOptions.Download }, | ||
{ label: 'compute', value: FilterByAccessOptions.Compute } | ||
] | ||
}, |
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.
suggestion(blocking): to reduce complexity and avoid having to define filters differently depending on the id
we should simply move these filters over to the new specs. This would then look something like the example in the issue:
{
id: 'serviceType',
label: 'Service Type',
type: 'filterList',
// add a "global" query path that gets used as fallback if options have none defined
queryPath: 'metadata.type',
options: [
{ label: 'datasets', value: FilterByTypeOptions.Data },
{ label: 'algorithms', value: FilterByTypeOptions.Algorithm },
{ label: 'saas', value: FilterByTypeOptions.Saas }
]
},
//...
…ved type handling
Implements #614
Proposed Changes