Skip to content

Commit e76906c

Browse files
committed
refactor(datagrid): extract filter tri-state logic and fix changelog sections
1 parent 3cd715a commit e76906c

4 files changed

Lines changed: 53 additions & 17 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- The tree sidebar can show only the databases you pick. Use the filter button to check the ones you want, with a search box for long lists. The choice is saved per connection. (#1667)
1313
- Closing a query tab no longer loses unsaved SQL. The next blank query tab you open for the same connection brings the last closed draft back. (#1686)
14+
- A checkbox in the filter panel header turns every filter row on or off at once. It shows a dash when only some rows are on.
15+
16+
### Changed
17+
18+
- The filter panel's "Unset" button is now "Clear". It keeps your filter rows and only drops the applied state, so the table returns to unfiltered results. To remove the rows themselves, use "Remove All Filters" in the filter options menu.
19+
- Apply a single filter on its own from a row's right-click menu with "Apply Only This Filter". The inline per-row Apply button is gone.
1420

1521
### Fixed
1622

17-
- Switcher, menus, and alerts now use each database's own container name: Dataset for BigQuery, Keyspace for Cassandra and ScyllaDB. (#509)
18-
- Filter panel header "Unset" renamed to "Clear": it now keeps filter rows in place and only removes the applied state, returning the table to unfiltered results. Use "Remove All Filters" in the filter options menu to discard all filter rows at once.
19-
- Per-row Apply and Applied buttons removed from the filter panel; "Apply Only This Filter" is now in each row's right-click context menu.
20-
- A tri-state checkbox in the filter panel header toggles all filter rows enabled or disabled at once.
2123
- Oracle connections no longer crash the app during connect. A short or unexpected handshake packet from the server (such as session-setup metadata or an error) now surfaces the error or continues instead of trapping. (#1683)
2224
- MongoDB filters on `_id` and other ObjectId fields now match. A 24-character hex value is matched as an ObjectId as well as a string, so filtering by `_id` returns the row instead of nothing. (#1682)
2325
- The sidebar and inspector keep their width per connection, the sidebar keeps its collapsed state, and the inspector keeps its selected tab, when you quit and reopen the app.

TablePro/Models/Database/TableFilter.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,4 +232,11 @@ struct TabFilterState: Equatable, Hashable, Codable {
232232
var hasAppliedFilters: Bool {
233233
!appliedFilters.isEmpty
234234
}
235+
236+
var allEnabledState: Bool? {
237+
guard !filters.isEmpty else { return false }
238+
if filters.allSatisfy({ $0.isEnabled }) { return true }
239+
if filters.allSatisfy({ !$0.isEnabled }) { return false }
240+
return nil
241+
}
235242
}

TablePro/Views/Filter/FilterPanelView.swift

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -68,24 +68,15 @@ struct FilterPanelView: View {
6868
}
6969

7070
private var allFiltersCheckboxImage: String {
71-
switch allFiltersEnabledState {
72-
case true: return "checkmark.square.fill"
73-
case false: return "square"
71+
switch filterState.allEnabledState {
72+
case .some(true): return "checkmark.square.fill"
73+
case .some(false): return "square"
7474
case .none: return "minus.square.fill"
7575
}
7676
}
7777

78-
private var allFiltersEnabledState: Bool? {
79-
guard !filterState.filters.isEmpty else { return false }
80-
let enabledCount = filterState.filters.count { $0.isEnabled }
81-
if enabledCount == filterState.filters.count { return true }
82-
if enabledCount == 0 { return false }
83-
return nil
84-
}
85-
8678
private func toggleAllFiltersEnabled() {
87-
let allEnabled = filterState.filters.allSatisfy { $0.isEnabled }
88-
let newState = !allEnabled
79+
let newState = filterState.allEnabledState != true
8980
for filter in filterState.filters {
9081
var updated = filter
9182
updated.isEnabled = newState

TableProTests/Models/TabFilterStateTests.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,42 @@ struct TabFilterStateTests {
7575
#expect(decoded.appliedFilters.map(\.id) == [filter.id])
7676
}
7777

78+
@Test("allEnabledState is false when there are no filters")
79+
func allEnabledStateEmpty() {
80+
let state = TabFilterState()
81+
#expect(state.allEnabledState == false)
82+
}
83+
84+
@Test("allEnabledState is true when every filter is enabled")
85+
func allEnabledStateAllOn() {
86+
var state = TabFilterState()
87+
state.filters = [
88+
TestFixtures.makeTableFilter(column: "id"),
89+
TestFixtures.makeTableFilter(column: "name")
90+
]
91+
#expect(state.allEnabledState == true)
92+
}
93+
94+
@Test("allEnabledState is false when every filter is disabled")
95+
func allEnabledStateAllOff() {
96+
var state = TabFilterState()
97+
state.filters = [
98+
TestFixtures.makeTableFilter(column: "id", isEnabled: false),
99+
TestFixtures.makeTableFilter(column: "name", isEnabled: false)
100+
]
101+
#expect(state.allEnabledState == false)
102+
}
103+
104+
@Test("allEnabledState is nil when filters are mixed")
105+
func allEnabledStateMixed() {
106+
var state = TabFilterState()
107+
state.filters = [
108+
TestFixtures.makeTableFilter(column: "id"),
109+
TestFixtures.makeTableFilter(column: "name", isEnabled: false)
110+
]
111+
#expect(state.allEnabledState == nil)
112+
}
113+
78114
@Test("browseSearch reads and writes the key pattern fields")
79115
func browseSearchAccessor() {
80116
var state = TabFilterState()

0 commit comments

Comments
 (0)