Skip to content

feat: [DHIS2-19940] Implement the "No value" filtering component for all filter types in the working list#4468

Draft
henrikmv wants to merge 2 commits intohv/feat/DHIS2-12881_AddFilterForAllTypesfrom
hv/feat/DHIS2-19940_EmptyValueFiltersForAllValueTypes
Draft

feat: [DHIS2-19940] Implement the "No value" filtering component for all filter types in the working list#4468
henrikmv wants to merge 2 commits intohv/feat/DHIS2-12881_AddFilterForAllTypesfrom
hv/feat/DHIS2-19940_EmptyValueFiltersForAllValueTypes

Conversation

@henrikmv
Copy link
Contributor

@henrikmv henrikmv commented Feb 27, 2026

DHIS2-19940

Summary

Extends the existing "No value" (isEmpty) filtering — previously only available for Text and Numeric filters — to all remaining filter types in the working list:

  • Date / DateTime / Time
  • Boolean / TrueOnly
  • OptionSet (single & multi-select)
  • Assignee
  • OrgUnit
  • Username

Each filter type follows the same pattern established by the Text filter:

  1. EmptyValueFilterCheckboxes rendered at the top of the filter UI
  2. Checkbox handlers using makeCheckboxHandler from the shared EmptyValue module
  3. Data getter converts isEmpty string values to API-compatible filter data with isEmpty flag and display label
  4. Manager's calculateDefaultState converts isEmpty: true/false back to the corresponding string constants when restoring filter state
  5. Button text converters return the isEmpty label when the filter has an isEmpty property

Additionally:

  • Centralized isEmpty handling added in buildButtonText so all filter types are covered
  • Removed stray console.log from numericConverter
  • Cleaned up numericConverter implementation

Review & Testing Checklist for Human

  • Verify each filter type renders the "Is empty" / "Is not empty" checkboxes at the top when opened — test Date, DateTime, Time, Boolean, TrueOnly, OptionSet, Assignee, OrgUnit, and Username filters in a working list
  • Verify isEmpty filter round-trips correctly: select "Is empty", apply, then reopen filter — the checkbox should remain checked
  • Verify button text displays correctly for isEmpty selections (should show "Is empty" or "Is not empty" label)
  • Verify normal (non-isEmpty) filtering still works for each filter type — existing behavior should not regress
  • Review orgUnitConverter change: non-isEmpty path changed from return filter.value to return filter.name ?? filter.value — verify this doesn't break existing org unit filter button text
  • Review numericConverter rewrite: the function was refactored beyond the console.log removal — verify edge cases (e.g., ge === 0, le === 0) still display correctly
  • Review booleanConverter type change: type annotation changed from BooleanFilterData to any — consider whether a union type would be more appropriate

Suggested Test Plan

  1. Open a working list that has columns with different data types
  2. For each filter type, open the filter and verify the two checkboxes appear
  3. Select "Is empty", apply — verify the filter button shows "Is empty"
  4. Reopen the filter — verify the checkbox is still checked
  5. Clear and select "Is not empty" — verify same behavior
  6. Clear isEmpty and use a normal filter value — verify it still works as before

Notes

@henrikmv henrikmv changed the base branch from master to hv/feat/DHIS2-12881_AddFilterForAllTypes February 28, 2026 14:06
Add EmptyValueFilterCheckboxes to DateTime, Time, Boolean, TrueOnly,
OptionSet, Assignee, OrgUnit, and Username filters following the
existing Text filter pattern.

Each filter type now:
- Renders isEmpty/isNotEmpty checkboxes at the top
- Handles isEmpty string values in data getters
- Converts isEmpty flags back to string values in managers
- Supports isEmpty display in button text converters

Also removes console.log from numericConverter and adds centralized
isEmpty handling in buildButtonText.

Co-Authored-By: henrik.vadet@dhis2.org <henrik@devOtta.no>
@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 1, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
4 New issues
4 New Code Smells (required ≤ 0)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

View 6 additional findings in Devin Review.

Open in Devin Review

Copy link
Contributor

Choose a reason for hiding this comment

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

🟡 DateTimeFilter.getDateLogicError() shows spurious error when empty value filter is selected after a failed submit

When value is a string (an empty value filter like 'EMPTY_VALUE_FILTER'), getDateLogicError() at DateTimeFilter.component.tsx:155-169 accesses value?.from and value?.to, which return undefined on a string primitive. If submitAttempted was set to true by a prior failed validation (e.g., the user entered an invalid date range where from > to, clicked Update, then selected the "Is empty" checkbox), the condition !from?.date && !to?.date evaluates to true and the method returns i18n.t('Please specify a date'), showing an incorrect error message alongside the empty value filter selection.

Other filters handle this correctly: TimeFilter.getTimeLogicError() has typeof values === 'string' guard (TimeFilter.component.tsx:163), NumericFilter.getErrors() has typeof committed === 'string' guard (NumericFilter.component.tsx:194-196), and DateFilter.getErrors() is safe because mainValue resolves to undefined which doesn't match any range option.

(Refers to lines 155-169)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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