Skip to content

feat(datagrid): apply filters individually (enable, disable, solo) (#1561)#1562

Merged
datlechin merged 2 commits into
mainfrom
feat/individual-filter-toggle
Jun 2, 2026
Merged

feat(datagrid): apply filters individually (enable, disable, solo) (#1561)#1562
datlechin merged 2 commits into
mainfrom
feat/individual-filter-toggle

Conversation

@datlechin

Copy link
Copy Markdown
Member

Closes #1561.

What this adds

Apply filters individually instead of all-or-nothing.

  • Each filter row has a checkbox to turn it on or off. Apply runs only the active (checked) filters; disabled rows stay in the panel for later use, and survive reopening the table.
  • Each row has its own Apply button that filters by just that row (solo). It does not change the other rows' checkboxes; the soloed row shows Applied (accent) so you can see what the grid reflects.
  • Cmd+Return applies all active filters.

Refactor (no behavior regressions)

The model already carried isEnabled; this surfaces it and cleans up the surrounding state model.

  • Single source of truth for what is applied. TabFilterState.appliedFilters is now a computed property derived from filters + a commit: FilterCommit? (.all / .solo(id)). The two arrays can no longer drift apart, and every apply path goes through commit instead of assigning appliedFilters directly.
  • Consistent commit model. Changing an enum value no longer auto-applies; everything waits for Apply. Removed the double-apply path on Return.
  • Dialect by capability. Raw SQL completion is gated on sqlDialect(for:) != nil instead of matching the language display string.
  • Removed dead code. Dropped the unused isSelected field and TabFilterState.hasChanges.

Native macOS / HIG

  • Filter rows size to content (measured) and scroll past a cap, with no hardcoded row-height estimate.
  • Add/remove use square buttons; removed an em dash placeholder.
  • AND/OR is now a Match all / Match any popup, matching Finder and Mail.

Tests

  • New TabFilterStateTests for the commit to appliedFilters derivation, solo behavior, and Codable round-trip.
  • Updated filter restore, tab-switch, row-count, and SQL-generator tests for the new model.
  • Removed a stale duplicate test that asserted invalid SQL (col = NULL); the correct IS NULL test already exists.

Deferred

  • Unifying the macOS TableFilter with the iOS (TableProModels) copy is a separate cross-platform task; this PR is macOS-only and does not touch the iOS app.
  • FilterValueTextField stays a custom NSViewRepresentable: it bridges async, schema-aware autocomplete that native sync completion cannot provide.

Verification

Build, filter test suites, and swiftlint --strict on the changed files all pass.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f4785f30d7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +198 to +200
var appliedFilters: [TableFilter] {
guard let commit else { return [] }
return Self.resolve(commit, in: filters)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve the applied filter snapshot until Apply

Because appliedFilters is now derived from the editable filters array, editing an already-applied row changes what the app considers applied before the user clicks Apply. For example, after applying name = 'Alice', changing the value to Bob without applying leaves the displayed query at Alice, but any later rebuild path that reads tab.filterState.appliedFilters (pagination/sort/refresh via rebuildTableQuery) will silently query Bob. The Apply button no longer represents the boundary between draft and applied filters, so keep a snapshot of applied values or otherwise separate draft edits from committed filters.

Useful? React with 👍 / 👎.

Comment on lines 338 to 340
FilterSettingsStorage.shared.saveLastFilters(
tab.filterState.appliedFilters,
tab.filterState.filters.filter(\.isValid),
for: tableName,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep disabled filters saved when switching tabs

This path saves all valid rows so disabled filters can be restored, but switching away from the tab still calls FilterSettingsStorage.saveLastFilters(tabManager.tabs[oldIndex].filterState.appliedFilters, ...) in MainContentCoordinator+TabSwitch.swift, which resolves .all to enabled filters only. In the common flow of disabling a valid row, clicking Apply, and then switching tabs, that tab-switch save overwrites the file written here and drops the disabled row before the table is reopened. Update the tab-switch persistence to use the same full valid filter list.

Useful? React with 👍 / 👎.

@datlechin datlechin merged commit c2274a8 into main Jun 2, 2026
4 checks passed
@datlechin datlechin deleted the feat/individual-filter-toggle branch June 2, 2026 19:18
@mintlify

mintlify Bot commented Jun 2, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
TablePro 🔴 Failed Jun 2, 2026, 7:21 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c53dd634a3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +296 to 298
state.commit = .solo(filter.id)
}
saveLastFiltersForActiveTable()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve solo commits when saving last filters

When the last action is a per-row Apply, this saves through saveLastFiltersForActiveTable(), which persists tab.filterState.filters.filter(\.isValid) without the .solo(filter.id) commit. On a later table restore, restoreLastFilters rebuilds the state with commit = .all, so a table that was last queried by only one soloed row reopens/apply-rebuilds with every enabled valid row instead. Persist the commit separately or save a last-applied snapshot for solo restores while keeping the full draft panel rows elsewhere.

Useful? React with 👍 / 👎.

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.

Individual Filter Application (Apply Per Filter / Apply Selected Filters)

1 participant