Skip to content

feat: Column organization overflow and undo/redo#2546

Merged
mattrunyon merged 13 commits intodeephaven:mainfrom
mattrunyon:column-organization-overflow
Oct 15, 2025
Merged

feat: Column organization overflow and undo/redo#2546
mattrunyon merged 13 commits intodeephaven:mainfrom
mattrunyon:column-organization-overflow

Conversation

@mattrunyon
Copy link
Copy Markdown
Collaborator

@mattrunyon mattrunyon commented Oct 8, 2025

Adds column order and visibilty overflow menu with show hidden columns (for the visibility menu only) and undo/redo.

Moves in the menu or on the grid add to the undo/redo stack.
Hiding/unhiding adds to the undo/redo stack.
Creating a new group will add to the stack as a whole action when it is named (moving columns + naming the group)

Unchecking the "Show hidden columns" option will hide the hidden column/group entries in the menu. The setting is reset on menu open.

@mattrunyon mattrunyon requested a review from a team October 8, 2025 04:59
@mattrunyon mattrunyon self-assigned this Oct 8, 2025
@mattrunyon mattrunyon requested review from bmingles and removed request for a team October 8, 2025 04:59
@codecov
Copy link
Copy Markdown

codecov Bot commented Oct 8, 2025

Codecov Report

❌ Patch coverage is 90.50279% with 17 lines in your changes missing coverage. Please review.
✅ Project coverage is 44.04%. Comparing base (28d6377) to head (8960487).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
packages/iris-grid/src/IrisGrid.tsx 10.00% 9 Missing ⚠️
...ity-ordering-builder/VisibilityOrderingBuilder.tsx 95.72% 4 Missing and 1 partial ⚠️
packages/iris-grid/src/ColumnHeaderGroup.ts 0.00% 2 Missing ⚠️
...d/src/mouse-handlers/GridColumnMoveMouseHandler.ts 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2546      +/-   ##
==========================================
- Coverage   44.15%   44.04%   -0.12%     
==========================================
  Files         763      764       +1     
  Lines       42906    43041     +135     
  Branches    11011    10866     -145     
==========================================
+ Hits        18944    18956      +12     
- Misses      23916    24069     +153     
+ Partials       46       16      -30     
Flag Coverage Δ
unit 44.04% <90.50%> (-0.12%) ⬇️

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

☔ View full report in Codecov by Sentry.
📢 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.

@mattrunyon mattrunyon marked this pull request as ready for review October 9, 2025 17:15
Comment thread packages/components/src/spectrum/SpectrumMenu.scss
Comment thread packages/grid/src/GridUtils.ts Outdated

const undoBtn = screen.getByLabelText('Undo');
await user.click(undoBtn);
expect(mockGroupHandler).toHaveBeenCalledWith([]);
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.

If I'm understanding correctly, this test proves it results in an empty array if only 1 action had occurred. I'm assuming if the stack had multiple items, it would show an array containing all but the last one? If so, might be good to test this just to prove the undo doesn't always undo everything in the stack. Same for the keyboard tests.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes. I'll add a test for multiple changes. The hook has a test for multiple items, but might as well test the implementation too

}

onColumnHeaderGroupChanged(newGroups);
endUndoGroup();
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.

Are there any edge cases where handleGroupNameChange might not get called after startUndoGroup has been called resutling in endUndoGroup not being called?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good call. I found one potential if you created a new group and deleted it without ever saving.

So the only way to start the grouping is to create a new column group.
The only ways out of creating a column group are save the group or delete it. Both call endUndoGroup now

Comment thread packages/grid/src/GridUtils.ts Outdated
Comment thread packages/grid/src/GridUtils.ts Outdated
Comment thread packages/iris-grid/src/IrisGrid.tsx Outdated
Comment thread packages/react-hooks/src/useUndoRedo.test.ts
Comment thread packages/react-hooks/src/useUndoRedo.ts
Copy link
Copy Markdown
Contributor

@bmingles bmingles left a comment

Choose a reason for hiding this comment

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

General logic seems solid. I left a few questions / suggestions.

Copy link
Copy Markdown
Contributor

@bmingles bmingles left a comment

Choose a reason for hiding this comment

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

General logic looks good. Left a few questions / suggestions.

@mattrunyon mattrunyon requested a review from bmingles October 14, 2025 03:30
],
[]
);
return items
Copy link
Copy Markdown
Contributor

@bmingles bmingles Oct 15, 2025

Choose a reason for hiding this comment

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

May not be worth changing if the depth / number of items is relatively small, but I typically like to use stack / queues for tree traversal:

Note this is mostly just to capture my thoughts on this. Not a change required for this PR.

I haven't tested, but I think this is functionally equivalent:

// DFS tree traversal to flatten a tree
function flatten<T>(items: ReadonlyTreeItems<T>): FlattenedItem<T>[] {
  const result: FlattenedItem<T>[] = [];
  const stack: [parentId: string | null, depth: number, item: TreeItem<T>][] =
    [];

  // Initialize the stack with the root items in reverse order so they can be
  // popped in forward order
  for (let i = items.length - 1; i >= 0; i -= 1) {
    stack.push([null, 0, items[i]]);
  }

  let index = 0;
  while (stack.length) {
    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
    const [parentId, depth, item] = stack.pop()!;

    if (item.children.length) {
      for (let i = item.children.length - 1; i >= 0; i -= 1) {
        stack.push([item.id, depth + 1, item.children[i]]);
      }
    }

    result.push({ ...item, depth, parentId, index });
    index += 1;
  }

  return result;
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Depth should be < 10 and almost certainly like 2 at most. Deeply nested groups can be hard to use and I'd be surprised if people have more than a couple layers of grouping on a table

Copy link
Copy Markdown
Contributor

@bmingles bmingles left a comment

Choose a reason for hiding this comment

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

Left a comment about tree traversal, but not a blocker for the PR

@mattrunyon mattrunyon merged commit 5ef19c2 into deephaven:main Oct 15, 2025
10 of 11 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 15, 2025
@mattrunyon mattrunyon deleted the column-organization-overflow branch October 15, 2025 18:46
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.

2 participants