Skip to content

feat: format numeric values with digit group separator [PR3] [DHIS2-18242]#3647

Open
BRaimbault wants to merge 9 commits into
feat/DHIS2-18242-PR2from
feat/DHIS2-18242-PR3
Open

feat: format numeric values with digit group separator [PR3] [DHIS2-18242]#3647
BRaimbault wants to merge 9 commits into
feat/DHIS2-18242-PR2from
feat/DHIS2-18242-PR3

Conversation

@BRaimbault
Copy link
Copy Markdown
Collaborator

@BRaimbault BRaimbault commented Apr 26, 2026

Parent

Implements

  • DHIS2-18963: Digit groups separator functionality in maps

Overview

Third PR in the series extracted from the parent epic. Threads the system-configured digit group separator (keyAnalysisDigitGroupSeparator: NONE / SPACE / COMMA) through the maps app so all numeric output is formatted consistently with the rest of DHIS2.

No new behavior except formatting — every place a number renders to the user now respects the system setting.

Changes

Utility and plumbing

formatWithSeparator and parseWithSeparator helpers in src/util/numbers.js, plus DIGIT_GROUP_SEPARATOR_{SPACE,COMMA,NONE} constants in src/constants/settings.js.

keyAnalysisDigitGroupSeparator added to SYSTEM_SETTINGS so it's fetched by both the main app (useLayersLoader) and the plugin (LayerLoader). Both orchestrators thread it as a named parameter to every loader.

The separator is exposed as a Redux-free dependency via the existing useCachedData() provider, so the plugin (which doesn't have Redux) can read it the same way as the main app.

formatWithSeparator accepts an optional precision parameter for forward compatibility with DHIS2-3156, but no consumer wires it through yet.

Files: src/util/numbers.js, src/constants/settings.js, src/hooks/useLayersLoader.js, src/components/plugin/LayerLoader.jsx

Loaders

Each loader accepts keyAnalysisDigitGroupSeparator and attaches it to the loaded layer config. Two loaders also bake formatted strings into feature properties at load time:

  • thematicLoader: properties.value is set to the formatted display string (consumed by tooltip, label, popup); properties.rawValue preserves the numeric value for sort and computation. properties.range is formatted with the separator.
  • earthEngineLoader: createLegend constructs item names ("< min", "from - to", "> max") with the separator applied.
  • eventLoader, trackedEntityLoader, geoJsonUrlLoader: thread the separator on config; raw per-feature values are preserved unchanged. These layer types use dynamic column names for data items, making parallel "raw" fields impractical, so formatting happens at the consumption site.

The properties.value flip in thematicLoader is a breaking change for anyone reading feature.properties.value expecting a Number. All internal consumers are updated.

A side refactor extracts parseJsonConfig, fetchRelationshipData, and buildQueryVariables from trackedEntityLoader to keep the main loader function under SonarQube's complexity threshold. No behavior change.

Files: src/loaders/thematicLoader.js, src/loaders/earthEngineLoader.js, src/loaders/eventLoader.js, src/loaders/trackedEntityLoader.js, src/loaders/geoJsonUrlLoader.js

Display components

Components format at the render site, reading the separator either from layer config (popups, GeoJSON profile) or from cached system settings directly (legend, data table, org unit info, EE preview):

  • formatValueForDisplay in helpers.js learns to format numeric value types using formatWithSeparator with force: true. Popup data values arrive as strings from the API.
  • Data table reads rawValue as the value column's dataKey so sort and display both come from a single source. Cell rendering formats non-color cells with the separator.
  • Legend item ranges format startValue/endValue/count. Refactored into nameLabel/rangeLabel/countLabel for readability and to fix a leading-space artifact when name is empty.
  • Bubble legend: Bubbles.jsx formats bubble text values with the separator before passing them to computeLayout, so the layout offset correctly accounts for separator characters in text width. Bubble.jsx now renders the pre-formatted text prop directly.
  • EventPopup, TrackedEntityPopup, and Earth Engine popup data values, GeoJsonLayer feature profile, OrgUnitInfo attributes (note: the backend returns numeric attribute values as strings), OrgUnitData data items, LegendPreview (Earth Engine edit dialog) — all format their displayed numbers. The Earth Engine popup reads the separator from the layer config via EarthEngineLayer rather than useCachedData(), since its parent is a class component.

Files: src/components/legend/LegendItemRange.jsx, src/components/legend/Bubbles.jsx, src/components/map/layers/EventLayer.jsx, src/components/map/layers/EventPopup.jsx, src/components/map/layers/TrackedEntityLayer.jsx, src/components/map/layers/TrackedEntityPopup.jsx, src/components/map/layers/GeoJsonLayer.js, src/components/datatable/DataTable.jsx, src/components/datatable/useTableData.js, src/components/orgunits/OrgUnitInfo.jsx, src/components/orgunits/OrgUnitData.jsx, src/components/edit/earthEngine/LegendPreview.jsx, src/components/map/layers/earthEngine/EarthEnginePopup.jsx, src/components/map/layers/earthEngine/EarthEngineLayer.jsx, src/util/helpers.js

Tests update

  • src/util/__tests__/numbers.spec.js
  • src/util/__tests__/helpers.spec.js
  • src/util/__tests__/bubbles.spec.js
  • src/loaders/__tests__/earthEngineLoader.spec.js

Manual testing

Netlify: https://pr-3647.maps.netlify.dhis2.org/ + Instance: https://dev.im.dhis2.org/maps-app-42-3 (keyAnalysisDigitGroupSeparator === SPACE)

Quality checklist

Add N/A to items that are not applicable.

  • Jest tests added/updated
  • Docs added N/A
  • d2-ci dependencies replaced N/A
  • Include plugin in testing
  • Tester approved (@edoardo)

@dhis2-bot
Copy link
Copy Markdown
Contributor

dhis2-bot commented Apr 26, 2026

🚀 Deployed on https://pr-3647.maps.netlify.dhis2.org

@dhis2-bot dhis2-bot temporarily deployed to netlify April 26, 2026 09:46 Inactive
@BRaimbault BRaimbault changed the title feat: format numeric values with digit group separator [PR3] [DHIS2-18963] feat: format numeric values with digit group separator [PR3] [DHIS2-18242] Apr 26, 2026
@dhis2-bot dhis2-bot temporarily deployed to netlify April 26, 2026 10:30 Inactive
@dhis2-bot dhis2-bot temporarily deployed to netlify April 26, 2026 11:08 Inactive
@dhis2-bot dhis2-bot temporarily deployed to netlify April 26, 2026 11:32 Inactive
@BRaimbault BRaimbault force-pushed the feat/DHIS2-18242-PR3 branch from 4618336 to 78342d0 Compare April 26, 2026 11:40
Copy link
Copy Markdown
Collaborator Author

@BRaimbault BRaimbault left a comment

Choose a reason for hiding this comment

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

Ready for review.

@BRaimbault BRaimbault marked this pull request as ready for review April 26, 2026 11:40
@dhis2-bot dhis2-bot temporarily deployed to netlify April 26, 2026 11:42 Inactive
@BRaimbault BRaimbault force-pushed the feat/DHIS2-18242-PR3 branch from 78342d0 to 070dd74 Compare April 26, 2026 20:57
@dhis2-bot dhis2-bot temporarily deployed to netlify April 26, 2026 20:58 Inactive
@BRaimbault BRaimbault requested a review from a team April 27, 2026 09:12
@dhis2-bot dhis2-bot temporarily deployed to netlify April 27, 2026 12:52 Inactive
@BRaimbault BRaimbault force-pushed the feat/DHIS2-18242-PR2 branch from 9b7bc5b to 60caa87 Compare April 27, 2026 14:44
@dhis2-bot dhis2-bot temporarily deployed to netlify April 27, 2026 15:09 Inactive
Comment thread src/loaders/geoJsonUrlLoader.js Outdated
Copy link
Copy Markdown
Member

@edoardo edoardo left a comment

Choose a reason for hiding this comment

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

Some test examples don't have data, but I could verify on the netlify instance that changes in the DGS setting are reflected in the app.

@dhis2-bot dhis2-bot temporarily deployed to netlify May 14, 2026 11:41 Inactive
@sonarqubecloud
Copy link
Copy Markdown

@dhis2-bot dhis2-bot temporarily deployed to netlify May 14, 2026 11:49 Inactive
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.

3 participants