-
Notifications
You must be signed in to change notification settings - Fork 158
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
Add filtering by undefined and fix searching by name #2714
Conversation
return f.sortValue(row) === value; | ||
} | ||
}); | ||
fields.forEach((field) => { |
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.
I think this needs to be simplified further. Let's say that both name and namespace (in that order) is text searchable. If you search for 1 text filter that matches the name, then I think the namespace would set matches back to false. So I think the matches filter needs to be more carefully passed from "layer to layer", instead of just building up one value as we loop.
The text filters seem like they should be ANDed based on the tests, so I'm going to assume that's correct.
To make this work properly, I think we need to:
- First (inner-most) OR each field together - any field that matches a single text filter means that the whole row matches that filter.
- Then, AND the filters together.
- And only then do we decide if the row as a whole matches the filters as a whole.
We're currently merging the filters before we're merging the columns, which I think doesn't work properly with multiple textSearchable columns - if again name and namespace are searchable, you wouldn't get a hit if one filter matches name and one filter matches namespace, only if all filters matches either name or namespace.
So I would change this whole loop to:
return rows.filter((row) => {
return textFilters.every((filter) => {
return fields.some((field) => {
if (!field.textSearchable) return false;
let value;
if (field.sortValue) {
value = field.sortValue(row);
} else if (typeof field.value === "function") {
value = field.value(row);
} else {
value = row[field.value];
}
return value.includes(filter);
});
});
});
Perhaps we could even turn that value
extraction into some helper function.
I like chaining together every
and some
because they help separate "checking the condition" from "combining the outputs" so they take care of the matches
malarkey for us - we only return a boolean, and the right thing comes out, and they even handles short-circuiting for us.
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.
I don't think it was ever intended to text search any column other than name - I took a look through and no tables have more than one column searchable. I'm down to add this because why not - but to me it'd be weird to have something be filterable AND text searchable.
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.
Text search let you do substring matches, the filter UI doesn't - so you can't filter for "all namespaces with denim in the name" without going through them all.
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.
Should I add textSearchable on all Namespace and Cluster columns? Any other columns that might be useful?
ui/components/ChipGroup.tsx
Outdated
<Chip label={chip} onDelete={() => onChipRemove([chip])} /> | ||
<Chip | ||
label={ | ||
chip.slice(-filterSeparator.length) === `${filterSeparator}` |
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.
Either do something like chip.indexOf(filterSeparator) == chip.length - filterSeparator.length
(I probably have an off-by-one in there, I haven't tried it) so it 100% only manipulates empty chip values, or just drop this.
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.
@joshri why are you using a template literal
`${filterSeparator}`
here instead of just filterSeparator
? Was the comparison not working?
How can the user determine which fields are searchable? I see the textSearchable prop, but only as a developer, is there a visual indication for the fields you can search? The first thing I tried searching was by channel and type, it didn't work. Then I read that search is enabled only for names. |
If using the Chip component imported from Material-UI causes such problems, can we just create our own Chip component which has two props, |
Created some follow-up issues - for now I've removed the hack in |
…s in the frontend, and allow for undefined values as - in filters
d1a2c86
to
5a4d7bb
Compare
The ChipGroup tests are failing, including locally for me. |
ui/components/DataTable.tsx
Outdated
if (field.sortValue) { | ||
value = field.sortValue(row); | ||
} else { | ||
typeof field.value === "function" |
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.
Can we re-write this ternary as:
value = typeof field.value === "function"
? field.value(row)
: row[field.value];
It's a standard form of an assignment with ternary instead of having multiple assignments.
ui/components/DataTable.tsx
Outdated
for (const filterString of textFilters) { | ||
if (_.includes(value, filterString)) { | ||
for (let i = 0; i < textFilters.length; i++) { | ||
if (value.includes(textFilters[i])) { |
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 can be refactored as
matches = value.includes(textFilters[i]);
if (!matches) {
break;
}
It would be easier to read.
Is it expected behavior that an empty filter dialog is displayed for the events table? I don't think it's specific to this PR. I remember fixing sorting in the events table but don't remember working with filters in it. Is the events table supposed to have filters or should we add hiding the filter dialog button for it? |
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.
Tested it, have not found a way to break anything! 🎉 Except for the failing test, LGTM.
"Not Ready" wrapping - I don't believe it's intentional that it's wrapping, but I also don't see any limits on the width of the status column Events Table empty filters - we aren't providing a filter state to the table so it makes sense that it's empty. We should probably disable search and filtering on this table with a boolean prop on DataTable |
We decided to make the filter dialog optional on the data table since the events table has never had any filtering functionality |
Closes #2711
Closes #2712
-
filterText
function that didn't allow searching by name with the new object structure (name can be a function instead of a string). The function now finds the row's value as other filtering functions do - withfield.value(row)
orrow[field.value]
, which supports both strings and functions.ChipGroup
to test if changing chips that end with the filter separator add a-
to properly display undefined.Quick vid showing filtering and searching on the notifications page:
FilterUndefined.mov