Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,13 @@ const NodeListSearchFilter = ({
handleQueryParamsUpdate((queryObject) => {
const updatedQueryObject = structuredClone(queryObject)

if (filtersToApply.length) {
updatedQueryObject[nodeSearchKey] = filtersToApply.map(({ value }) => value).join(',')
// NOTE: drop any entry with a falsy value before persisting to the query string so a
// stray blank filter can never be appended alongside a real one (which would otherwise
// neutralize the filter entirely, since an empty value matches every node)
const nonEmptyFiltersToApply = filtersToApply.filter(({ value }) => !!value)

if (nonEmptyFiltersToApply.length) {
updatedQueryObject[nodeSearchKey] = nonEmptyFiltersToApply.map(({ value }) => value).join(',')
} else {
delete updatedQueryObject[nodeSearchKey]
}
Expand Down Expand Up @@ -223,10 +228,12 @@ const NodeListSearchFilter = ({
[NODE_SEARCH_KEYS.NODE_GROUP]: appliedFilters[NODE_SEARCH_KEYS.NODE_GROUP]
.filter(({ value }) => !!value)
.map(({ value }) => value),
[NODE_SEARCH_KEYS.LABEL]: appliedFilters[NODE_SEARCH_KEYS.LABEL].map(({ value }) => value),
[NODE_K8S_VERSION_FILTER_KEY]: appliedFilters[NODE_K8S_VERSION_FILTER_KEY].map(
({ value }) => value,
),
[NODE_SEARCH_KEYS.LABEL]: appliedFilters[NODE_SEARCH_KEYS.LABEL]
.filter(({ value }) => !!value)
.map(({ value }) => value),
[NODE_K8S_VERSION_FILTER_KEY]: appliedFilters[NODE_K8S_VERSION_FILTER_KEY].filter(
({ value }) => !!value,
).map(({ value }) => value),
}}
onRemoveFilter={handleRemoveFilter}
clearFilters={handleClearFilters}
Expand Down
9 changes: 7 additions & 2 deletions src/components/ResourceBrowser/ResourceList/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,10 @@ export const isItemASearchMatchForNodeListing = (item: Record<string, any>, sear
)
}

return String(item[objectKey] ?? '').includes(trimmedText) && isFound
// NOTE: exact match is required here since a substring/includes match would
// incorrectly match distinct but similarly named values (e.g. filtering by
// node group 'presto-gateway' should not also match 'presto-gateway-2')
return String(item[objectKey] ?? '') === trimmedText && isFound
})
}, true)

Expand Down Expand Up @@ -537,7 +540,9 @@ export const getNodeSearchKeysOptionsList = (rows: NodeListSearchFilterType['row
}
})

if (!acc.nodeGroups.has(curr.data.nodeGroup as string)) {
// NOTE: skip nodes without a node group (e.g. control-plane/master nodes) so an
// empty-value option never gets added to the node group filter list
if (curr.data.nodeGroup && !acc.nodeGroups.has(curr.data.nodeGroup as string)) {
acc.nodeGroups.set(curr.data.nodeGroup as string, {
label: `${curr.data.nodeGroup}`,
value: curr.data.nodeGroup as string,
Expand Down
Loading