enhancement(tables): one DataTable for paged and virtualized views with a shared feature set - #579
Merged
Conversation
…single component One DataTable with a discriminated union: the default paged <table> engine, or the windowed infinite-scroll engine via the virtualized parameter. Both engines share extracted internals (dataTableShared.tsx); per-mode DOM, test ids, and localStorage formats are unchanged. Dead paged props (relatedFieldKey, canEdit, subRowColumns, cellPinningStyleFn, and the Set-based expansion trio) are removed; paged mode gains emptyMessage and getRowId.
…solves Branch the repository total on the id-resolved-sort MODE instead of the resolved ids' presence. The ids flicker to undefined during a page flip, and the old presence branch fell back to the list query's page-sized totalCount in that gap - collapsing totalPages to 1 and letting the page clamp yank the user back to page 1. The count-only query now also starts as soon as the mode is active rather than waiting for the ids.
… virtualized tables Ports the paged engine's drag-to-reorder to virtualized mode through a shared usePersistedColumnOrder hook: grip handles on non-pinned headers, order remembered per surface under the same key as widths, on by default wherever the table already persists state. The flex column also becomes resizable - the drag seeds from the rendered width so it tracks what is on screen, and the chosen width becomes its minimum while it keeps absorbing slack.
Ports the paged engine's per-column header menu (explicit sort direction plus Hide column) to virtualized mode. The menu items are extracted into a shared ColumnMenuItems component used by both engines; the menu appears on a surface once it wires onSortColumn/onHideColumn, and Hide routes through the Columns control via hideColumnRef so persistence and the checkboxes stay in sync. Wires the admin users page as the first surface.
…d of re-sorting The engine passed controlled sorting state into TanStack with getSortedRowModel and without manualSorting, so loaded rows were re-sorted client-side by each column's accessor - fighting the server's order. Enum columns (user access, integration/issue status) sort by Postgres enum order server-side but alphabetically client-side, and infinite-scroll page seams could be scrambled. Callers own row order (server orderBy or their own sort), so the engine now renders it verbatim; audited all 33 virtualized call sites - none relied on the client re-sort.
The column shows Yes/No but sorted by the hidden scimGivenName text with nulls always last, so ascending and descending looked identical - the SCIM block stayed on top either way. Direction now means what it says: ascending puts non-SCIM (No) first, descending puts SCIM-managed (Yes) first, with the given name ordering rows within the SCIM block.
The item clears the active sort and returns to the surface's default order, which only the repository reads as manual order - everywhere else the old label was a puzzle. Includes the i18n sync's reconciliation of the run-completion notification key rename in the non-English locales.
schema.zmodel already declares NONE, USER, PROJECTADMIN, ADMIN, but the live type has NONE appended at the end (enum values can only be added, not reordered, in place) - so access sorts put No Access after System Admin. The migration recreates the type in the declared order and re-points the four dependent columns, dropping and restoring their defaults around the swap. Data values are unchanged.
The inbox fetched the whole result set and rendered every row through the paged engine with no pagination controls, so a large inbox put every row in the DOM. The table now renders in virtualized mode (windowed rows, viewport-filling scroll region) and gains column drag-reorder and width persistence. The per-tab pin swap, server-owned sorting, details-panel row highlight, and row test ids are unchanged; the paged-era row-height and table-width CSS hacks are gone.
The list pane rendered the No pending reviews empty copy while the query was still in flight; it now shows the shared Loading component until the result lands. Adds the same muted showing/total line the other virtualized list pages carry.
…cell The inbox wrapped UserNameCell in a one-off bg-secondary pill, which no other surface does - and the cell's current-user star and deleted-user label, colored for the plain row surface, fell below contrast on the pill in dark themes. The pill is gone; both columns now render the bare cell exactly like the fourteen other user-name columns.
…lumn Sort ascending / Sort descending / Remove sort is now the standard header control wherever a column is sortable, in both engines. Every surface that owns sort state gains an explicit-direction handler whose Remove branch restores that page's own default order; pages that already render a Columns control also gain Hide column through the visibility owner. The paged engine's menu default now matches the virtualized engine (on when a handler is wired). The two remaining opt-outs are deliberate: the workflows drag-order list, where sorting would fight manual ordering, and the sort-less statuses table.
…ecords per fetch The drawer rendered every loaded record through the paged engine and drove pagination with its own IntersectionObserver, so a large drill-down piled thousands of rows into the DOM 50 at a time. The table now renders in virtualized mode - the engine owns the fetch-on-scroll trigger and the loading-more skeleton - and each fetch brings 500 records. The header shows the standard Showing loaded-of-total line instead of a bare count.
# Conflicts: # testplanit/app/[locale]/projects/repository/[projectId]/Cases.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Merges the two data-table components (
DataTableandVirtualizedDataTable) into a singleDataTablewhose rendering mode is selected by avirtualizedparameter, then uses the shared foundation to level the feature set across every table surface.The merge
<table>engine, or the windowed infinite-scroll engine viavirtualizeddataTableShared.tsx): sorting adapter, pinning init, expander column, grouped-cell rendering, column-order persistence, header menu itemsFeatures leveled up during UAT
Correctness fixes surfaced by UAT
manualSorting) — fixes enum-column sort order and infinite-scroll page-seam scrambling; audited all 33 virtualized call sites for client-sort reliance firstAccessenum is rebuilt in least-to-most-privilege order (migration included, values unchanged)executedAt descdefaultRelated Issue
N/A — interactive UAT session.
Type of Change
How Has This Been Tested?
Test Configuration:
Checklist