Skip to content

feat(tables): saved views with filter, sort, and column presets - #5961

Open
TheodoreSpeaks wants to merge 15 commits into
stagingfrom
feat/table-views
Open

feat(tables): saved views with filter, sort, and column presets#5961
TheodoreSpeaks wants to merge 15 commits into
stagingfrom
feat/table-views

Conversation

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator

Summary

  • Saved views on tables: name a filter + sort + column-visibility preset, switch between them from a View dropdown in the options bar
  • New Columns menu to show/hide columns, with workflow outputs nested under their group (hiding all of a group's children drops its spanning header)
  • Save button appears only when the current state diverges from the active view — ad-hoc filtering stays throwaway
  • Backed by a new table_views table; "All" is the absence of a view, so no backfill and the table is always reachable unfiltered
  • Gated behind the table-views feature flag (UI only — routes and migration ship ungated so a view saved during rollout survives the flag being turned off)

Type of Change

  • New feature

Testing

Tested manually. bun run type-check, bun run lint, all 11 CI audits, and check:migrations origin/staging pass. 29 unit tests across the views service, API contracts, and feature flags.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Jul 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment Jul 28, 2026 4:35pm

Request Review

@cursor

cursor Bot commented Jul 25, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches table query/layout state, URL sync, and new persisted config with merge semantics; auth follows existing table access checks, but view-switch and dirty-state edge cases are non-trivial.

Overview
Saved table views let users name and switch presets that bundle filter, sort, column visibility, and grid layout (widths, order, pins). "All" stays the default unfiltered state; views are optional rows in a new table_views table with JSON config, workspace-scoped auth on new list/create/PATCH/DELETE routes, server-side configPatch merges for concurrent layout writes, and pruneViewConfig on read when columns disappear.

The table detail UI gains a Views dropdown (create/rename/delete, URL ?table-view=), a Columns show/hide menu (workflow groups nest with parent toggles), and a Save / Save as view chip when live state diverges from the active view. Resource.Options adds asideEnd and trailing slots for that bar layout. TableGrid respects hiddenColumns, seeds layout from the active view via viewLayout / onPersistLayout, and auto-appends new columns to stored order when a view is active.

Rollout is gated by the table-views feature flag (UI + fetch only; API and migration ship enabled so saved data survives flag-off). Embedded mothership tables keep the old bar when the flag is off.

Reviewed by Cursor Bugbot for commit da8a17a. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread apps/sim/hooks/queries/tables.ts
Comment thread apps/sim/lib/table/views/service.ts
Comment thread apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx
@greptile-apps

greptile-apps Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds feature-flagged table saved views.

  • Persists named filter, sort, hidden-column, and column-layout presets.
  • Adds view and column menus plus create, rename, update, and delete flows.
  • Introduces table-view API contracts, query hooks, storage service, schema, and migration.

Confidence Score: 3/5

The PR is not yet safe to merge because saved layouts can still be captured stale and undo or redo can persist layout into the wrong storage scope.

A new view can copy lagging activeView.config instead of the grid's accumulated live layout, and the undo subsystem still bypasses the active-view persistence sink by mutating shared table metadata directly.

Files Needing Attention: apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx, apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/table-grid.tsx, apps/sim/hooks/use-table-undo.ts

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx Coordinates saved-view state and persistence, but the prior layout-capture issue remains reachable while a layout patch is in flight.
apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/table-grid.tsx Adds view-owned layout seeding and persistence routing, while the previously reported undo bypass remains unresolved.
apps/sim/hooks/use-table-undo.ts Undo and redo continue to write layout fields through the shared table-metadata mutation.
apps/sim/lib/table/views/service.ts Implements validated view persistence and server-side JSONB patch merging for independently owned config fields.
packages/db/migrations/0271_table_views.sql Adds the table_views persistence table and supporting constraints and indexes.

Sequence Diagram

sequenceDiagram
  participant User
  participant Table as Table UI
  participant API as View API
  participant DB as table_views
  User->>Table: Select or edit saved view
  Table->>API: Create or patch view config
  API->>DB: Persist config
  DB-->>API: Return saved view
  API-->>Table: Refresh active view
  Table-->>User: Apply filter, sort, visibility, and layout
Loading

Reviews (11): Last reviewed commit: "fix(tables): guard default demotion, use..." | Re-trigger Greptile

Comment thread apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx
Comment thread apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx
Comment thread apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@cursor review

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx Outdated
Comment thread apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile

Comment thread apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx
# Conflicts:
#	apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/table-grid.tsx
#	apps/sim/app/workspace/[workspaceId]/tables/[tableId]/page.tsx
#	apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx
#	apps/sim/lib/core/config/env.ts
#	apps/sim/lib/core/config/feature-flags.ts
#	packages/db/migrations/meta/0270_snapshot.json
#	packages/db/migrations/meta/_journal.json
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx
Comment thread apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx
Comment thread apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/lib/table/views/service.ts
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/lib/table/views/service.ts
Comment thread apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx Outdated
Comment thread apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit da8a17a. Configure here.

seededViewIdRef.current = null
setTableParams({ view: ALL_VIEW_PARAM })
applyViewConfig(null)
return

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Deleted view leaves filter stuck

High Severity

The view resolution effect has an early return condition (seededViewIdRef.current === activeViewId) meant for view creation. This condition also triggers when the active view is deleted externally, preventing cleanup. As a result, the filter, sort, and hidden column states from the deleted view remain applied, while the ViewsMenu incorrectly shows "All".

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit da8a17a. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant