Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- Switcher, menus, and alerts now use each database's own container name: Dataset for BigQuery, Keyspace for Cassandra and ScyllaDB. (#509)
- 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.
- 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.
- A tri-state checkbox in the filter panel header toggles all filter rows enabled or disabled at once.

### Fixed

Expand Down
53 changes: 49 additions & 4 deletions TablePro/Views/Filter/FilterPanelView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,43 @@ struct FilterPanelView: View {
.onPreferenceChange(FilterRowsHeightKey.self) { filterRowsHeight = $0 }
}

private var allFiltersCheckboxImage: String {
switch allFiltersEnabledState {
case true: return "checkmark.square.fill"
case false: return "square"
case .none: return "minus.square.fill"
}
}

private var allFiltersEnabledState: Bool? {
guard !filterState.filters.isEmpty else { return false }
let enabledCount = filterState.filters.count { $0.isEnabled }
if enabledCount == filterState.filters.count { return true }
if enabledCount == 0 { return false }
return nil
}

private func toggleAllFiltersEnabled() {
let allEnabled = filterState.filters.allSatisfy { $0.isEnabled }
let newState = !allEnabled
for filter in filterState.filters {
var updated = filter
updated.isEnabled = newState
coordinator.updateFilter(updated)
}
}

private var filterHeader: some View {
HStack(spacing: 8) {
if !filterState.filters.isEmpty {
Button(action: toggleAllFiltersEnabled) {
Image(systemName: allFiltersCheckboxImage)
.foregroundStyle(.primary)
}
.buttonStyle(.plain)
.help(String(localized: "Enable or disable all filters"))
}

Text("Filters")
.font(.callout.weight(.medium))

Expand All @@ -88,15 +123,15 @@ struct FilterPanelView: View {

filterOptionsMenu

Button("Unset") {
coordinator.clearFilterState()
Button("Clear") {
coordinator.clearAppliedFilters()
onUnset()
coordinator.focusActiveGrid()
}
.buttonStyle(.bordered)
.controlSize(.small)
.disabled(!filterState.hasAppliedFilters)
.help(String(localized: "Remove all filters and reload"))
.help(String(localized: "Clear applied filters without removing filter rows"))

Button("Apply") {
applyAllValidFilters()
Expand Down Expand Up @@ -172,6 +207,17 @@ struct FilterPanelView: View {

Divider()

Button(role: .destructive) {
coordinator.clearFilterState()
onUnset()
coordinator.focusActiveGrid()
} label: {
Label(String(localized: "Remove All Filters"), systemImage: "xmark.circle")
}
.disabled(filterState.filters.isEmpty)

Divider()

Button {
showSettingsPopover.toggle()
} label: {
Expand All @@ -198,7 +244,6 @@ struct FilterPanelView: View {
completions: completionItems(),
enumValuesByColumn: enumValuesByColumn,
rawSQLCompletionProvider: rawSQLCompletionProvider,
isApplied: filterState.commit == .solo(filter.id),
onAdd: {
coordinator.addFilter(columns: columns, primaryKeyColumn: primaryKeyColumn)
focusedFilterId = filterState.filters.last?.id
Expand Down
30 changes: 9 additions & 21 deletions TablePro/Views/Filter/FilterRowView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ struct FilterRowView: View {
let completions: [String]
var enumValuesByColumn: [String: [String]] = [:]
var rawSQLCompletionProvider: RawSQLFilterCompletionProvider?
let isApplied: Bool
let onAdd: () -> Void
let onDuplicate: () -> Void
let onRemove: () -> Void
Expand Down Expand Up @@ -160,28 +159,8 @@ struct FilterRowView: View {
}
}

@ViewBuilder
private var soloApplyButton: some View {
if isApplied {
Button(String(localized: "Applied"), action: onApply)
.buttonStyle(.borderedProminent)
} else {
Button(String(localized: "Apply"), action: onApply)
.buttonStyle(.bordered)
}
}

private var rowButtons: some View {
HStack(spacing: 4) {
soloApplyButton
.controlSize(.small)
.disabled(!filter.isValid)
.accessibilityLabel(String(localized: "Apply only this filter"))
.accessibilityValue(isApplied ? String(localized: "Applied") : "")
.help(isApplied
? String(localized: "Filtering by only this row")
: String(localized: "Filter by only this row"))

Button(action: onAdd) {
Image(systemName: "plus")
.frame(width: rowButtonGlyphSize, height: rowButtonGlyphSize)
Expand All @@ -204,6 +183,15 @@ struct FilterRowView: View {

@ViewBuilder
private var rowContextMenu: some View {
Button {
onApply()
} label: {
Label(String(localized: "Apply Only This Filter"), systemImage: "checkmark.circle")
}
.disabled(!filter.isValid)

Divider()

Button {
onAdd()
} label: {
Expand Down
Loading