[PR #7304] [MERGED] Fix filter operator switching behavior #37266

Closed
opened 2026-04-21 00:11:39 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/actualbudget/actual/pull/7304
Author: @sk10727-a11y
Created: 3/27/2026
Status: Merged
Merged: 4/16/2026
Merged by: @matt-fidd

Base: masterHead: filter-fix


📝 Commits (10+)

  • ac1c1fc [autofix.ci] apply automated fixes
  • 837b9d5 Fix render condition (code rabbit)
  • e49e7aa [autofix.ci] apply automated fixes
  • 85309cd Fix filter operator switching behavior
  • afc0336 fixed merge conflicts
  • fc803bb [autofix.ci] apply automated fixes
  • 8bf8014 Fix Account filter input not rendering due to incorrect conditional logic
  • 4ecfc7a [autofix.ci] apply automated fixes
  • d6b778c Rename isPayeeIdOp to isIdOp for clarity
  • 2f17298 [autofix.ci] apply automated fixes

📊 Changes

2 files changed (+228 additions, -37 deletions)

View changed files

📝 packages/desktop-client/src/components/filters/FiltersMenu.tsx (+222 -37)
upcoming-release-notes/7304.md (+6 -0)

📄 Description

Description

Fixes an issue where switching filter operators between exact-match (is, one of) and text-based operators (contains, matches) would populate the input with UUIDs instead of human-readable names.

This PR adds logic to correctly transform values when switching between operator types for ID-based fields (accounts, categories, category groups, payees):

  • Single-ID → text: Converts stored ID → text, since there is a one-to-one mapping
  • Text → Single-ID: Converts text → ID (if uniquely matched), ensuring correctness without guessing
  • Multi-ID → text: If the array size is 1, resolves ID to text (if uniquely matched); otherwise, clears the value, since multiple IDs cannot be reliably represented as a single string
  • Text → Multi-ID: Resolves text to a single ID (if uniquely matched) and wraps it in an array, matching the expected multi-value format

Unique to the accounts filter, there are account no-value operators (is on budget, is off budget):

  • No-value → text: Converts preserved ID(s) → text when possible
  • No-value → Single-ID: Converts preserved text → ID when a unique match exists
  • No-value → Multi-ID: Resolves preserved text to a single ID (if uniquely matched) and wraps it in an array; otherwise clears the value

Note:

  • Single-ID exact-match operators: is, is not → store a single ID value
  • Multi-ID exact-match operators: one of, not one of → store an array of IDs
  • Text-based operators: contains, matches, does not contain → store plain strings
  • Account no-value operators: is on budget, is off budget → do not use input values but preserve state for future conversions

This ensures the input always matches the expected format for the selected operator and prevents UUID leakage in the UI.

Fixes #7123.

Testing

Tested the following transitions across accounts, categories, category groups, and payees:

  • is → contains, matches, does not contain: ID correctly converted to text
  • is not → text operators: same behavior as above
  • contains / matches → is, is not: text converted back to ID when an exact match exists
  • contains / matches → one of: text converted to single ID and wrapped in array
  • one of / not one of → text operators: prevented invalid conversion (cleared value)
  • is → one of: single ID preserved and wrapped in array

Account-specific cases:

  • is → is on budget / is off budget → contains: correctly converts back to text
  • one of → is on budget / is off budget → text: clears or converts appropriately
  • text → is on budget / is off budget → is: attempts to resolve back to ID

How to test

  1. Navigate to an account
  2. Create or edit a filter on an ID-based field (accounts, category, category group, payees)
  3. Switch between operators
  4. Verify the input remains human-readable and matches the outlined behavior

Checklist

  • Release notes added (see link above)
  • No obvious regressions in affected areas
  • Self-review has been performed - I understand what each change in the code does and why it is needed

Bundle Stats

Bundle Files count Total bundle size % Changed
desktop-client 34 12.93 MB → 12.94 MB (+4 kB) +0.03%
loot-core 1 4.85 MB 0%
api 1 3.88 MB 0%
cli 1 7.91 MB 0%
View detailed bundle stats

desktop-client

Total

Files count Total bundle size % Changed
34 12.93 MB → 12.94 MB (+4 kB) +0.03%
Changeset
File Δ Size
src/components/filters/FiltersMenu.tsx 📈 +4 kB (+22.96%) 17.41 kB → 21.41 kB
View detailed bundle breakdown

Added
No assets were added

Removed
No assets were removed

Bigger

Asset File Size % Changed
static/js/chart-theme.js 705.55 kB → 709.55 kB (+4 kB) +0.57%

Smaller
No assets were smaller

Unchanged

Asset File Size % Changed
static/js/index.js 1.85 MB 0%
static/js/BackgroundImage.js 121.09 kB 0%
static/js/FormulaEditor.js 814.39 kB 0%
static/js/PayeeRuleCountLabel.js 52.12 kB 0%
static/js/ReportRouter.js 1.18 MB 0%
static/js/ScheduleEditForm.js 136.13 kB 0%
static/js/TransactionEdit.js 185.13 kB 0%
static/js/TransactionList.js 82.8 kB 0%
static/js/Value.js 4.34 MB 0%
static/js/ca.js 191.72 kB 0%
static/js/client.js 450.92 kB 0%
static/js/da.js 104.4 kB 0%
static/js/de.js 174.12 kB 0%
static/js/en-GB.js 8.2 kB 0%
static/js/en.js 176.5 kB 0%
static/js/es.js 181.54 kB 0%
static/js/extends.js 486.5 kB 0%
static/js/fr.js 176.79 kB 0%
static/js/indexeddb-main-thread-worker-e59fee74.js 13.46 kB 0%
static/js/it.js 165.68 kB 0%
static/js/narrow.js 363.68 kB 0%
static/js/nb-NO.js 151.58 kB 0%
static/js/nl.js 108.66 kB 0%
static/js/pl.js 88.34 kB 0%
static/js/pt-BR.js 193.49 kB 0%
static/js/resize-observer.js 18.06 kB 0%
static/js/th.js 178.91 kB 0%
static/js/theme.js 30.79 kB 0%
static/js/uk.js 212.28 kB 0%
static/js/useFormatList.js 9.86 kB 0%
static/js/wide.js 292 B 0%
static/js/workbox-window.prod.es5.js 7.33 kB 0%
static/js/zh-Hans.js 110.19 kB 0%

loot-core

Total

Files count Total bundle size % Changed
1 4.85 MB 0%
View detailed bundle breakdown

Added
No assets were added

Removed
No assets were removed

Bigger
No assets were bigger

Smaller
No assets were smaller

Unchanged

Asset File Size % Changed
kcab.worker.BLXvyUAG.js 4.85 MB 0%

api

Total

Files count Total bundle size % Changed
1 3.88 MB 0%
View detailed bundle breakdown

Added
No assets were added

Removed
No assets were removed

Bigger
No assets were bigger

Smaller
No assets were smaller

Unchanged

Asset File Size % Changed
index.js 3.88 MB 0%

cli

Total

Files count Total bundle size % Changed
1 7.91 MB 0%
View detailed bundle breakdown

Added
No assets were added

Removed
No assets were removed

Bigger
No assets were bigger

Smaller
No assets were smaller

Unchanged

Asset File Size % Changed
cli.js 7.91 MB 0%

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/actualbudget/actual/pull/7304 **Author:** [@sk10727-a11y](https://github.com/sk10727-a11y) **Created:** 3/27/2026 **Status:** ✅ Merged **Merged:** 4/16/2026 **Merged by:** [@matt-fidd](https://github.com/matt-fidd) **Base:** `master` ← **Head:** `filter-fix` --- ### 📝 Commits (10+) - [`ac1c1fc`](https://github.com/actualbudget/actual/commit/ac1c1fc54d49f8974cad867da37b585d5a9fbf15) [autofix.ci] apply automated fixes - [`837b9d5`](https://github.com/actualbudget/actual/commit/837b9d5f59c40b326d8b93f35d2f6db3137623fe) Fix render condition (code rabbit) - [`e49e7aa`](https://github.com/actualbudget/actual/commit/e49e7aabecae54c5367d2b7c9aa1b841b8329759) [autofix.ci] apply automated fixes - [`85309cd`](https://github.com/actualbudget/actual/commit/85309cd0190b79b022311924d38bdc8d794f0216) Fix filter operator switching behavior - [`afc0336`](https://github.com/actualbudget/actual/commit/afc0336edbc3bd0555b396088d453799772b2b07) fixed merge conflicts - [`fc803bb`](https://github.com/actualbudget/actual/commit/fc803bb3ce924c2f0801a57d1177f9340c617594) [autofix.ci] apply automated fixes - [`8bf8014`](https://github.com/actualbudget/actual/commit/8bf8014920044c83c47e85c9ff27b08f00fe395e) Fix Account filter input not rendering due to incorrect conditional logic - [`4ecfc7a`](https://github.com/actualbudget/actual/commit/4ecfc7a048497730c684d4a71287b139eb6a0821) [autofix.ci] apply automated fixes - [`d6b778c`](https://github.com/actualbudget/actual/commit/d6b778c88ee2d97dc48f130dabe0c0960ce4ca67) Rename isPayeeIdOp to isIdOp for clarity - [`2f17298`](https://github.com/actualbudget/actual/commit/2f1729810d53ab02ee20394fd8413195084abddb) [autofix.ci] apply automated fixes ### 📊 Changes **2 files changed** (+228 additions, -37 deletions) <details> <summary>View changed files</summary> 📝 `packages/desktop-client/src/components/filters/FiltersMenu.tsx` (+222 -37) ➕ `upcoming-release-notes/7304.md` (+6 -0) </details> ### 📄 Description ## Description Fixes an issue where switching filter operators between exact-match (is, one of) and text-based operators (contains, matches) would populate the input with UUIDs instead of human-readable names. This PR adds logic to correctly transform values when switching between operator types for ID-based fields (accounts, categories, category groups, payees): - Single-ID → text: Converts stored ID → text, since there is a one-to-one mapping - Text → Single-ID: Converts text → ID (if uniquely matched), ensuring correctness without guessing - Multi-ID → text: If the array size is 1, resolves ID to text (if uniquely matched); otherwise, clears the value, since multiple IDs cannot be reliably represented as a single string - Text → Multi-ID: Resolves text to a single ID (if uniquely matched) and wraps it in an array, matching the expected multi-value format **Unique to the accounts filter, there are account no-value operators (is on budget, is off budget):** - No-value → text: Converts preserved ID(s) → text when possible - No-value → Single-ID: Converts preserved text → ID when a unique match exists - No-value → Multi-ID: Resolves preserved text to a single ID (if uniquely matched) and wraps it in an array; otherwise clears the value **Note:** - Single-ID exact-match operators: is, is not → store a single ID value - Multi-ID exact-match operators: one of, not one of → store an array of IDs - Text-based operators: contains, matches, does not contain → store plain strings - Account no-value operators: is on budget, is off budget → do not use input values but preserve state for future conversions This ensures the input always matches the expected format for the selected operator and prevents UUID leakage in the UI. ## Related issue(s) Fixes #7123. ## Testing Tested the following transitions across accounts, categories, category groups, and payees: - is → contains, matches, does not contain: ID correctly converted to text - is not → text operators: same behavior as above - contains / matches → is, is not: text converted back to ID when an exact match exists - contains / matches → one of: text converted to single ID and wrapped in array - one of / not one of → text operators: prevented invalid conversion (cleared value) - is → one of: single ID preserved and wrapped in array **Account-specific cases:** - is → is on budget / is off budget → contains: correctly converts back to text - one of → is on budget / is off budget → text: clears or converts appropriately - text → is on budget / is off budget → is: attempts to resolve back to ID ## How to test 1. Navigate to an account 2. Create or edit a filter on an ID-based field (accounts, category, category group, payees) 3. Switch between operators 4. Verify the input remains human-readable and matches the outlined behavior ## Checklist - [X] Release notes added (see link above) - [X] No obvious regressions in affected areas - [X] Self-review has been performed - I understand what each change in the code does and why it is needed <!--- actual-bot-sections ---> <!--- bundlestats-action-comment key:combined start ---> ### Bundle Stats Bundle | Files count | Total bundle size | % Changed ------ | ----------- | ----------------- | --------- desktop-client | 34 | 12.93 MB → 12.94 MB (+4 kB) | +0.03% loot-core | 1 | 4.85 MB | 0% api | 1 | 3.88 MB | 0% cli | 1 | 7.91 MB | 0% <details> <summary>View detailed bundle stats</summary> #### desktop-client **Total** Files count | Total bundle size | % Changed ----------- | ----------------- | --------- 34 | 12.93 MB → 12.94 MB (+4 kB) | +0.03% <details> <summary>Changeset</summary> File | Δ | Size ---- | - | ---- `src/components/filters/FiltersMenu.tsx` | 📈 +4 kB (+22.96%) | 17.41 kB → 21.41 kB </details> <details> <summary>View detailed bundle breakdown</summary> <div> **Added** No assets were added **Removed** No assets were removed **Bigger** Asset | File Size | % Changed ----- | --------- | --------- static/js/chart-theme.js | 705.55 kB → 709.55 kB (+4 kB) | +0.57% **Smaller** No assets were smaller **Unchanged** Asset | File Size | % Changed ----- | --------- | --------- static/js/index.js | 1.85 MB | 0% static/js/BackgroundImage.js | 121.09 kB | 0% static/js/FormulaEditor.js | 814.39 kB | 0% static/js/PayeeRuleCountLabel.js | 52.12 kB | 0% static/js/ReportRouter.js | 1.18 MB | 0% static/js/ScheduleEditForm.js | 136.13 kB | 0% static/js/TransactionEdit.js | 185.13 kB | 0% static/js/TransactionList.js | 82.8 kB | 0% static/js/Value.js | 4.34 MB | 0% static/js/ca.js | 191.72 kB | 0% static/js/client.js | 450.92 kB | 0% static/js/da.js | 104.4 kB | 0% static/js/de.js | 174.12 kB | 0% static/js/en-GB.js | 8.2 kB | 0% static/js/en.js | 176.5 kB | 0% static/js/es.js | 181.54 kB | 0% static/js/extends.js | 486.5 kB | 0% static/js/fr.js | 176.79 kB | 0% static/js/indexeddb-main-thread-worker-e59fee74.js | 13.46 kB | 0% static/js/it.js | 165.68 kB | 0% static/js/narrow.js | 363.68 kB | 0% static/js/nb-NO.js | 151.58 kB | 0% static/js/nl.js | 108.66 kB | 0% static/js/pl.js | 88.34 kB | 0% static/js/pt-BR.js | 193.49 kB | 0% static/js/resize-observer.js | 18.06 kB | 0% static/js/th.js | 178.91 kB | 0% static/js/theme.js | 30.79 kB | 0% static/js/uk.js | 212.28 kB | 0% static/js/useFormatList.js | 9.86 kB | 0% static/js/wide.js | 292 B | 0% static/js/workbox-window.prod.es5.js | 7.33 kB | 0% static/js/zh-Hans.js | 110.19 kB | 0% </div> </details> --- #### loot-core **Total** Files count | Total bundle size | % Changed ----------- | ----------------- | --------- 1 | 4.85 MB | 0% <details> <summary>View detailed bundle breakdown</summary> <div> **Added** No assets were added **Removed** No assets were removed **Bigger** No assets were bigger **Smaller** No assets were smaller **Unchanged** Asset | File Size | % Changed ----- | --------- | --------- kcab.worker.BLXvyUAG.js | 4.85 MB | 0% </div> </details> --- #### api **Total** Files count | Total bundle size | % Changed ----------- | ----------------- | --------- 1 | 3.88 MB | 0% <details> <summary>View detailed bundle breakdown</summary> <div> **Added** No assets were added **Removed** No assets were removed **Bigger** No assets were bigger **Smaller** No assets were smaller **Unchanged** Asset | File Size | % Changed ----- | --------- | --------- index.js | 3.88 MB | 0% </div> </details> --- #### cli **Total** Files count | Total bundle size | % Changed ----------- | ----------------- | --------- 1 | 7.91 MB | 0% <details> <summary>View detailed bundle breakdown</summary> <div> **Added** No assets were added **Removed** No assets were removed **Bigger** No assets were bigger **Smaller** No assets were smaller **Unchanged** Asset | File Size | % Changed ----- | --------- | --------- cli.js | 7.91 MB | 0% </div> </details> </details> <!--- bundlestats-action-comment key:combined end ---> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-04-21 00:11:39 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/actual#37266