console: CNS-144 - Filter controls for Cluster List table - #38470
Conversation
…n be filtered by usage metric thresholds, e.g. >70% Memory.
QA LLM Review1. MEDIUM -- A restored page can hide every matching replica
The URL's page index is restored without clamping it to the filtered row count. Opening a stale bookmark or carrying the URL to a smaller environment can land beyond the last page and render a header-only table even though matching replicas exist, while the pagination controls can disappear entirely. DetailsThe new URL writer persists every nonzero page at |
…nation had the potential to display tables with zero rows. That case is now caught and the table displays its last available page instead.
QA LLM Review1. MEDIUM -- Clamping while the rows are still loading throws away the bookmarked page
The new clamp also fires on the first commit, when a table's row model is still empty because its data has not arrived, so it rewrites a URL-restored page index to 0 and drops Details
This PR's own table takes the same path. An empty row model does not distinguish "there is no page 2" from "there are no rows yet", so it is not a safe thing to clamp against: if (tableOptions.manualPagination) return;
+ // An empty row model is also what a table shows before its data (or the
+ // query a filter reads) has arrived, so clamping here would discard a page
+ // restored from the URL.
+ if (pageCount === 0) return;
const lastPage = Math.max(0, pageCount - 1);With that guard both URLs restore, and |
…s to match Maintained Objects table behavior.
|
both issues fixed & pushed to branch |
QA LLM Review1. MEDIUM -- The filter panel can show a threshold that is not the one in force
The panel's draft is only re-seeded when the applied filter value changes, but the header popover keeps the panel mounted between opens, so an edit that is never applied outlives every close. Blank the threshold of an applied Details
Confirmed against this commit with a minimal table wired through The same root causes a second symptom: Fix: give the header popover |
This fixes a bug where a filter control could be opened in a statw that does not match the actual filtered state of the table. Fix applies to Maintained Objects filters as well as Cluster table filters.
|
|
||
| import { | ||
| Button, | ||
| HStack, |
There was a problem hiding this comment.
| HStack, | |
| HStack, | |
| Icon, |
| import { Column } from "@tanstack/react-table"; | ||
| import React from "react"; | ||
|
|
||
| import { MaterializeTheme } from "~/theme"; |
There was a problem hiding this comment.
| import { MaterializeTheme } from "~/theme"; | |
| import { ChevronDownIcon } from "~/icons"; | |
| import { MaterializeTheme } from "~/theme"; |
| <Select | ||
| size="sm" | ||
| maxW="16" | ||
| fontWeight="700" |
There was a problem hiding this comment.
| fontWeight="700" |
| <NumberInputStepper> | ||
| <NumberIncrementStepper | ||
| aria-label={`Increase ${label} threshold`} | ||
| /> | ||
| <NumberDecrementStepper | ||
| aria-label={`Decrease ${label} threshold`} | ||
| /> | ||
| </NumberInputStepper> |
There was a problem hiding this comment.
| <NumberInputStepper> | |
| <NumberIncrementStepper | |
| aria-label={`Increase ${label} threshold`} | |
| /> | |
| <NumberDecrementStepper | |
| aria-label={`Decrease ${label} threshold`} | |
| /> | |
| </NumberInputStepper> | |
| <NumberInputStepper> | |
| <NumberIncrementStepper | |
| aria-label={`Increase ${label} threshold`} | |
| border="none" | |
| color={colors.foreground.secondary} | |
| > | |
| <Icon | |
| as={ChevronDownIcon} | |
| boxSize="3" | |
| transform="rotate(180deg)" | |
| /> | |
| </NumberIncrementStepper> | |
| <NumberDecrementStepper | |
| aria-label={`Decrease ${label} threshold`} | |
| border="none" | |
| color={colors.foreground.secondary} | |
| > | |
| <Icon as={ChevronDownIcon} boxSize="3" /> | |
| </NumberDecrementStepper> | |
| </NumberInputStepper> |
There was a problem hiding this comment.
Overall this looks good. The URL round-trip and the pagination clamp are well reasoned and thoroughly tested, and the filter state follows the guide-tanstack-table pattern. The URL sync is safe too: nothing else on this route reads search params, and TanStack ignores unknown sort ids from stale URLs.
Couple of nits:
nit: UtilizationFilterPanel and FreshnessFilterPanel duplicate the same Clear/Apply footer, worth extracting it in a common component
| const clearFilter = () => { | ||
| column.setFilterValue(undefined); | ||
| }; |
There was a problem hiding this comment.
If you type a value and click Clear without applying, the field keeps the value: no filter was ever set, so nothing resets the draft. FreshnessFilterPanel resets its draft explicitly, and the same works here:
FreshnessFilterPanel resets its draft explicitly in its clearFilter; the same works here (and is harmless in the applied case, where the effect resets the drafts anyway):
| const clearFilter = () => { | |
| column.setFilterValue(undefined); | |
| }; | |
| const clearFilter = () => { | |
| setComparison(DEFAULT_COMPARISON); | |
| setPercent(""); | |
| column.setFilterValue(undefined); | |
| }; |
There was a problem hiding this comment.
Percentage_not_clearing.mov
Here is the bug to be clear
There was a problem hiding this comment.
Fixed in latest commit. Thanks!
|
|
||
| // The panel stays mounted between opens, so it has to follow the filter |
There was a problem hiding this comment.
Stale since the lazy-unmount commit: the panel now remounts on each open, so what this covers is the filter changing while the panel is open (or the seed on remount).
| // The panel stays mounted between opens, so it has to follow the filter | |
| // The panel has to follow the filter rather than hold the value the chip | |
| // just removed. |
…panel field could not be cleared in certain conditions.
…ter panels. Filters now use ≥ only.
…ed flags for felxible deployment.

Motivation
Closes: https://linear.app/materializeinc/issue/CNS-144/add-filters-to-cluster-replica-table
Context: https://linear.app/materializeinc/project/improved-cluster-overview-page-792c294165da/overview
Also fixes a bug that was found during development - a stale bookmark could render a header-only table with no pagination control if the bookmark pointed to a page that no longer exists in a new result set. For example,
page=2might be valid on a result set of 21 rows, but the next day that set might only have 18 rows. This fix touches the Maintained Objects table, which had also been affected by the bug.Description
The Clusters list can now be filtered by a threshold on any replica utilization metric (CPU, memory, disk, heap). Filters live in the column headers, appear as removable chips, and are reflected in the URL so a filtered view can be bookmarked or shared.


Verification
Automated tests added for filter and related URL functionality. Verified locally.