Skip to content

fix: DH-22976: control IrisGrid sorts and filters - #2737

Merged
mofojed merged 4 commits into
deephaven:mainfrom
SimonVutov:DH-22976-controlled-grid-state
Aug 20, 2026
Merged

fix: DH-22976: control IrisGrid sorts and filters#2737
mofojed merged 4 commits into
deephaven:mainfrom
SimonVutov:DH-22976-controlled-grid-state

Conversation

@SimonVutov

Copy link
Copy Markdown
Contributor

Adds controlled sorts and quick filters to IrisGrid. User changes are reported through callbacks without updating internal state, while uncontrolled behavior remains unchanged.

This PR should be merged and released before deephaven-plugins#1377.

@codecov

codecov Bot commented Aug 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 54.45545% with 46 lines in your changes missing coverage. Please review.
✅ Project coverage is 51.69%. Comparing base (251c39a) to head (ef9c5d6).

Files with missing lines Patch % Lines
packages/iris-grid/src/IrisGrid.tsx 52.08% 46 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2737      +/-   ##
==========================================
+ Coverage   51.39%   51.69%   +0.30%     
==========================================
  Files         797      797              
  Lines       45887    45928      +41     
  Branches    11733    11942     +209     
==========================================
+ Hits        23582    23744     +162     
+ Misses      22286    22138     -148     
- Partials       19       46      +27     
Flag Coverage Δ
unit 51.69% <54.45%> (+0.30%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds controlled sorting and quick-filter behavior to IrisGrid, supporting the upcoming deephaven-plugins integration while preserving uncontrolled behavior.

Changes:

  • Adds controlled-state flags and change callbacks.
  • Synchronizes filter input text with external values.
  • Adds controlled-state and input synchronization tests.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
IrisGrid.tsx Implements controlled sorts and quick filters.
IrisGrid.test.tsx Tests controlled and uncontrolled behavior.
FilterInputField.tsx Synchronizes external filter values.
FilterInputField.test.tsx Tests external value synchronization.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/iris-grid/src/IrisGrid.tsx
Comment thread packages/iris-grid/src/IrisGrid.tsx
Comment thread packages/iris-grid/src/IrisGrid.tsx

@dgodinez-dh dgodinez-dh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AI pointed this out, but it looks like applyInputFilters, rebuildFilters, and setFilters call setState on quickFilters. Also handleUpdateCustomColumns calls setState on quickFilters and sorts. I think this need to be requests.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (2)

packages/iris-grid/src/IrisGrid.tsx:1040

  • Controlled state can still diverge after rollback(): that method directly replaces sorts and quickFilters from lastLoadedConfig (or clears them), then this condition and the quick-filter equivalent below skip resynchronization because the controlled prop references and flags did not change. A request failure or Cancel can therefore leave the grid/model different from its parent-owned values. The rollback path needs to preserve or explicitly propose controlled values instead of silently overwriting them.
    if (
      sorts !== prevProps.sorts ||
      (!prevProps.isSortsControlled && isSortsControlled)
    ) {
      this.updateSorts(sorts);

packages/iris-grid/src/IrisGrid.tsx:1841

  • In controlled quick-filter mode, didQuickFiltersChange can be true even though requestQuickFiltersChange deliberately does not update state. The caller at lines 1018–1024 interprets this return value as an applied change and starts loading; if the parent omits or rejects the callback, no model request occurs to stop that loader. Report a change here only when quick filters were actually applied internally (advanced-filter changes should still return true).
    return didQuickFiltersChange || didAdvancedFiltersChange;

Comment thread packages/iris-grid/src/IrisGrid.tsx
with only advanced filters, there is no quick-filter change to trigger it

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

packages/iris-grid/src/IrisGrid.tsx:3036

  • The controlled guard is bypassed by rollback(), which still writes both sorts and quickFilters directly with setState (lines 2570-2598). After a model request fails, the grid can therefore render a rolled-back value while the unchanged controlled props still contain the parent-owned value; reference checks in componentDidUpdate will not resynchronize it. Make rollback respect controlled ownership and notify/reconcile the parent so props and internal state cannot remain divergent.
  requestSortsChange(sorts: readonly SortDescriptor[]): void {
    const { isSortsControlled, onSortsChange } = this.props;
    onSortsChange?.(sorts);
    if (!isSortsControlled) {
      this.updateSorts(sorts);

Comment thread packages/iris-grid/src/IrisGrid.tsx Outdated

@dgodinez-dh dgodinez-dh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left one more comment.
Additionally, there are a lot of AI comments on this review. You should either address them or close them as not relevant.

Comment thread packages/iris-grid/src/IrisGrid.tsx Outdated
Copilot AI review requested due to automatic review settings August 20, 2026 13:28
@SimonVutov
SimonVutov requested a review from dgodinez-dh August 20, 2026 13:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (2)

packages/iris-grid/src/IrisGrid.tsx:305

  • The new controlled-sort contract is bypassed by rollback(): both rollback branches still assign state.sorts directly. After a request failure or user cancellation, the grid can therefore display/apply rolled-back sorts while the unchanged controlled sorts prop still contains the parent-owned value, and componentDidUpdate will not resynchronize it because the prop reference did not change. Rollback needs to preserve controlled ownership (for example, report the rollback value to the parent or define an explicit failure callback) rather than silently diverging.
  isSortsControlled: boolean;
  onSortsChange?: (sorts: readonly SortDescriptor[]) => void;

packages/iris-grid/src/IrisGrid.tsx:2118

  • rebuildFilters is an internal regeneration of the existing conditions (for example after a time-zone or table change), not a user edit. Routing it through the controlled-change gate means a controlled grid does not install newQuickFilters; with no change handler it also leaves the loading scrim started above even though the model will never receive a new filter. Apply the rebuilt map directly here so controlled filters are regenerated too.
      this.requestQuickFiltersChange(newQuickFilters);

@mofojed
mofojed merged commit 7635d2a into deephaven:main Aug 20, 2026
11 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants