Commit 985f9e6
authored
feat(tables): saved views with filter, sort, and column presets (#5961)
* feat(tables): saved views with filter, sort, and column presets
* fix(tables): views own column layout, preserve deep-linked sort, seed update cache
* fix(tables): merge view layout writes server-side, keep layout on save-from-All
* fix(tables): send view saves as a merge patch so concurrent writes can't clobber
* fix(tables): persist explicit All selection, prune view state for deleted columns
* fix(tables): key-order-stable dirty check, reset layout when switching to All
* fix(tables): return 404 when patching a missing view
* improvement(tables): order the bar filter, sort, columns and drop the hidden count
* fix(tables): record newly created columns in the active view's order
* fix(tables): don't write layout as a reader, clear dead sort, reset dead view id
* feat(tables): add New view to the views menu, starting from All
* chore(api): bump route-count baseline to 981 after staging merge
* fix(tables): guard default demotion, use the applied filter for dirty/save
* fix(tables): clear state when the active view is deleted externally
* revert(tables): drop the ineffective rows-query gate for view resolution
* feat(tables): enable saved views in the embedded mothership table
* fix(tables): resolve the views flag on the chat route too
* improvement(tables): right-align the embedded run/stop control
* fix(tables): live layout on new views, prune stored config, order cache writes
* fix(tables): live layout on save-as-view, reset it per view, ignore inherited param when embedded
* fix(tables): route undo/redo column-layout writes to the active view
* fix(tables): scope layout undo to the view that recorded it
Layout is view-owned, but UndoEntry carried no owner, so the persistence
sink — rebound every render to the active view — decided the target at undo
time rather than at record time. Reordering in view A then undoing from view
B wrote A's column order into B and left A unchanged.
Entries are now stamped with the active view id, and the three layout-bearing
action types (create-column, delete-column, reorder-columns) are pruned from
both stacks when the active view changes. Row and schema actions are
table-scoped and survive the switch untouched. Inert when views are disabled:
the id is always null, so nothing is ever pruned.
* fix(tables): send only the layout keys an action changes
Pin, reorder, and insert-column each shipped a full columnWidths snapshot
they never modified. Both sinks merge at top-level key granularity, so an
earlier-issued patch landing after a concurrent resize replaced the newer
width map with its stale copy.
Resize, auto-resize, and delete-column still send columnWidths — those
genuinely change it.
* fix(tables): don't strand layout writes while views load, keep schema undos across views
Two more instances of layout being written without a known owner.
The sink was left unbound until a view resolved, so a resize/reorder/pin (or
the column-append effect) during the views fetch fell through to the table's
shared metadata — corrupting All for a table about to adopt a view, and losing
the edit to the re-seed. The sink is now bound while the query is in flight and
suppresses the write. An error counts as settled, so a failed views fetch falls
back to All instead of suppressing layout writes for the session.
Pruning was also too broad: create-column and delete-column are table-scoped
schema ops that merely have a layout side-effect, so dropping them on a view
switch made a deleted column unrecoverable. Only reorder-columns is purely
layout and still prunes; the other two survive and have just their layout half
suppressed at replay when the recorded view isn't active.
* fix(tables): flush layout buffered during load when the owner settles to All
Suppressing the write while the views query was in flight stopped All from
being corrupted, but nothing resolved the buffer afterwards, so a resize during
load looked applied and vanished on refresh.
Settling on All re-seeds nothing (viewLayoutKey never changed), so the gesture
is still on screen and is now persisted to shared metadata. Adopting a view
re-seeds the grid from that view and has already replaced the gesture on
screen, so the buffer is dropped to match.
* fix(tables): resolve undo layout ownership at write time, not dispatch time
The layout writes for column create/delete happen in mutation success
callbacks, and persistLayoutRef is rebound every render. Resolving
entryOwnsLayout up front meant the guard could still hold from before a view
switch while the sink it guarded already pointed at the destination, writing
the recorded view's layout into whichever view was now active.
Now a function, so the guard and the sink are read at the same moment: switch
away mid-mutation and the schema half still lands while the layout half is
dropped, matching the rule that undo only ever affects the view on screen.
* fix(tables): read layout from the grid instead of mirroring it
The wrapper kept two shadow copies of the grid's column layout — liveLayoutRef
and pendingLayoutRef — and all three of this round's findings were that mirror
going stale:
- liveLayoutRef was only cleared on activeView.id change, so widths buffered
before the views query settled survived into All, where layout writes bypass
the mirror entirely. Both create paths spread it last, so a saved view stored
those snapped-back widths.
- currentViewConfig memoized a spread of that ref, and mutating a ref doesn't
re-run a memo, so Save as view sent the pre-gesture layout.
- The flush effect keyed on activeView, but adoption writes the view id through
the URL, so for one render the query had settled while activeView was still
null — flushing to All in exactly the case that had to drop.
The grid owns this state, so it now publishes a reader through a sink ref and
the wrapper asks at the moment it needs a value. Nothing to keep in sync, so
nothing to go stale. Only whether an unowned change happened is tracked, and
the resolve effect — which is what actually picks the owner — decides to
persist or drop.
* fix(tables): flush unowned layout when the views fetch fails
The resolve effect is the only caller of resolvePendingLayout and gated on
isSuccess, which never becomes true on a query error — so layout touched
during the load window was never persisted on the error path, even though
the table had already settled to All and later writes worked.
The error branch now flushes to shared metadata, matching the rest of the
error path's fall-back-to-All behavior.
* fix(tables): gate the on-screen layout restore by ownership, not just the persist
The undo success callbacks applied the recorded view's order/widths/pinning to
the grid unconditionally and only gated the PATCH, so switching views before a
column create/delete mutation resolved left the destination displaying the
origin view's layout until switched away and back.
Each callback now checks ownership where its layout work begins: three are
purely layout and return at the top; delete-column undo restores cell data
first (row data, runs everywhere) and gates only the layout block below it.
In a non-owning view the restored column still appears via the grid's append
effect — at the end, leaving that view's layout untouched.
* fix(tables): route all layout writes through one owner-aware sink, reconcile order at seed
Two holes closed:
The sink binding toggled on activeView, leaving a render-frame gap after the
views query settled but before the resolve effect adopted a default — writes in
that gap fell through to shared metadata. The sink is now always bound while
views are enabled and handlePersistLayout is the single router, reading the
owner at call time: unresolved buffers, a view patches the view, All writes
metadata. The error branch stamps the owner so post-error writes stop
buffering.
The append effect only fires when the schema changes, so a column that arrived
while another source owned the layout rendered via the displayColumns fallback
but was never written into the adopted owner's stored order until a drag
happened to heal it. Seeding now reconciles the incoming order against the
schema and persists the appended tail through the current sink.
* fix(tables): capture the layout owner when a schema action is dispatched
Insert-column and the delete chain persist layout from mutation callbacks
through updateMetadataRef, which always targets the current sink — so a view
switch mid-flight wrote the origin view's order/widths/pins into the
destination. Undo got this guard already; the live paths never did.
Both now capture viewLayoutKey at dispatch and compare at the callback. On a
mismatch the layout work is skipped: the destination re-seeded its own layout,
the new column lands there via the append effect when the refetch arrives, and
the deleted column's dangling keys are pruned on read.
pushUndo also takes the captured owner as an override — stamped at callback
time it would record the destination, letting a later undo apply the origin's
layout to it.
* fix(tables): resolve views on list availability, not query success
A failed background refetch flips isError while the cached list stays usable,
and every view mutation invalidates the views query — so one blip made the
resolve effect treat views as terminally failed and stop applying switches
until the next successful refetch.
The axis is now whether a list exists: error with no list ever fetched settles
to All; error with a cached list resolves normally against the cache; owner is
unknown only while the initial fetch is in flight.
* ci: raise Build App timeout to 25 minutes
The build outgrew the 15-minute cap over the last two days of merges:
10m02 (c6acc62), then 14m44 after the folders/desktop/library batch
(adc557a, 16s under the limit), then two consecutive timeouts on
7b1af41 after the outlook merge. Staging's own latest runs show the same
signature (one cancelled). GitHub labels a job timeout "cancelled", which is
why these read as cancellations.1 parent 0618541 commit 985f9e6
41 files changed
Lines changed: 20904 additions & 129 deletions
File tree
- .github/workflows
- apps/sim
- app
- api/table/[tableId]/views
- [viewId]
- workspace/[workspaceId]
- chat/[chatId]
- components/resource/components/resource-options
- home
- components/mothership-view
- components/resource-content
- tables/[tableId]
- components
- save-view-modal
- table-grid
- hooks
- queries
- utils
- lib
- api/contracts
- core/config
- table
- views
- stores/table
- packages/db
- migrations
- meta
- scripts
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
222 | 222 | | |
223 | 223 | | |
224 | 224 | | |
225 | | - | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
226 | 230 | | |
227 | 231 | | |
228 | 232 | | |
| |||
Lines changed: 106 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
Lines changed: 6 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
| |||
16 | 17 | | |
17 | 18 | | |
18 | 19 | | |
19 | | - | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
20 | 23 | | |
21 | 24 | | |
22 | 25 | | |
23 | 26 | | |
24 | 27 | | |
25 | 28 | | |
26 | | - | |
| 29 | + | |
| 30 | + | |
27 | 31 | | |
28 | 32 | | |
29 | 33 | | |
| |||
Lines changed: 27 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
91 | 91 | | |
92 | 92 | | |
93 | 93 | | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
94 | 106 | | |
95 | 107 | | |
96 | 108 | | |
| |||
99 | 111 | | |
100 | 112 | | |
101 | 113 | | |
| 114 | + | |
| 115 | + | |
102 | 116 | | |
103 | 117 | | |
104 | 118 | | |
| |||
111 | 125 | | |
112 | 126 | | |
113 | 127 | | |
114 | | - | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
115 | 136 | | |
116 | 137 | | |
117 | 138 | | |
118 | 139 | | |
119 | 140 | | |
120 | 141 | | |
121 | | - | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
122 | 145 | | |
123 | 146 | | |
124 | 147 | | |
| |||
177 | 200 | | |
178 | 201 | | |
179 | 202 | | |
| 203 | + | |
180 | 204 | | |
| 205 | + | |
181 | 206 | | |
182 | 207 | | |
183 | 208 | | |
| |||
Lines changed: 13 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
84 | 84 | | |
85 | 85 | | |
86 | 86 | | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
87 | 90 | | |
88 | 91 | | |
89 | 92 | | |
| |||
153 | 156 | | |
154 | 157 | | |
155 | 158 | | |
| 159 | + | |
156 | 160 | | |
157 | 161 | | |
158 | 162 | | |
| |||
223 | 227 | | |
224 | 228 | | |
225 | 229 | | |
226 | | - | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
227 | 239 | | |
228 | 240 | | |
229 | 241 | | |
| |||
Lines changed: 4 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
67 | 67 | | |
68 | 68 | | |
69 | 69 | | |
| 70 | + | |
| 71 | + | |
70 | 72 | | |
71 | 73 | | |
72 | 74 | | |
| |||
81 | 83 | | |
82 | 84 | | |
83 | 85 | | |
| 86 | + | |
84 | 87 | | |
85 | 88 | | |
86 | 89 | | |
| |||
189 | 192 | | |
190 | 193 | | |
191 | 194 | | |
| 195 | + | |
192 | 196 | | |
193 | 197 | | |
194 | 198 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
71 | 71 | | |
72 | 72 | | |
73 | 73 | | |
| 74 | + | |
| 75 | + | |
74 | 76 | | |
75 | 77 | | |
76 | | - | |
| 78 | + | |
77 | 79 | | |
78 | 80 | | |
79 | 81 | | |
| |||
523 | 525 | | |
524 | 526 | | |
525 | 527 | | |
| 528 | + | |
526 | 529 | | |
527 | 530 | | |
528 | 531 | | |
| |||
0 commit comments