From 763e5a8e292f4e3d8d88686569664da008f862e8 Mon Sep 17 00:00:00 2001 From: Thomas Zemp Date: Mon, 8 Jun 2026 15:23:55 +0200 Subject: [PATCH 1/2] fix: replace standalone indicators custom forms [DHIS2-21607] --- .../custom-form-indicator-cell.jsx | 29 ++++++++++++ .../custom-form/custom-form-total-cell.jsx | 7 ++- .../custom-form/parse-html-to-react.test.js | 45 +++++++++++++++++++ .../custom-form/replace-input-node.jsx | 6 +++ .../custom-form/replace-td-node.jsx | 20 +-------- 5 files changed, 86 insertions(+), 21 deletions(-) create mode 100644 src/data-workspace/custom-form/custom-form-indicator-cell.jsx diff --git a/src/data-workspace/custom-form/custom-form-indicator-cell.jsx b/src/data-workspace/custom-form/custom-form-indicator-cell.jsx new file mode 100644 index 000000000..4d7f7e14f --- /dev/null +++ b/src/data-workspace/custom-form/custom-form-indicator-cell.jsx @@ -0,0 +1,29 @@ +import PropTypes from 'prop-types' +import React from 'react' +import { IndicatorTableCell } from '../indicators-table-body/indicator-table-cell.jsx' + +export const CustomFormIndicatorCell = ({ indicatorId, metadata }) => { + const { + denominator, + numerator, + indicatorType: { factor }, + decimals, + } = metadata.indicators[indicatorId] + + return ( + + ) +} +CustomFormIndicatorCell.propTypes = { + indicatorId: PropTypes.string.isRequired, + metadata: PropTypes.object.isRequired, +} + +export const replaceIndicatorCell = (indicatorId, metadata) => ( + +) diff --git a/src/data-workspace/custom-form/custom-form-total-cell.jsx b/src/data-workspace/custom-form/custom-form-total-cell.jsx index 2e0270da2..7b7d288dd 100644 --- a/src/data-workspace/custom-form/custom-form-total-cell.jsx +++ b/src/data-workspace/custom-form/custom-form-total-cell.jsx @@ -1,5 +1,5 @@ import PropTypes from 'prop-types' -import React, { useState, useEffect } from 'react' +import React, { useMemo, useState, useEffect } from 'react' import { useValueStore } from '../../shared/index.js' import { TotalCell } from '../category-combo-table-body/total-cells.jsx' @@ -18,7 +18,10 @@ const computeTotalValues = (dataElementValues) => { export const CustomFormTotalCell = ({ dataElementId }) => { const dataValues = useValueStore((state) => state.getDataValues()) - const dataElementValues = dataValues?.[dataElementId] || {} + const dataElementValues = useMemo( + () => dataValues?.[dataElementId] || {}, + [dataValues, dataElementId] + ) const [total, setTotal] = useState(() => computeTotalValues(dataElementValues) diff --git a/src/data-workspace/custom-form/parse-html-to-react.test.js b/src/data-workspace/custom-form/parse-html-to-react.test.js index bc08ff2f5..ba625c790 100644 --- a/src/data-workspace/custom-form/parse-html-to-react.test.js +++ b/src/data-workspace/custom-form/parse-html-to-react.test.js @@ -1,5 +1,6 @@ import React from 'react' import { DataEntryField } from '../data-entry-cell/index.js' +import { CustomFormIndicatorCell } from './custom-form-indicator-cell.jsx' import { CustomFormTotalCell } from './custom-form-total-cell.jsx' import { parseHtmlToReact } from './parse-html-to-react.jsx' @@ -24,6 +25,50 @@ describe('parseHtmlToReact', () => { ) }) + it('replaces indicator cells inside td elements', () => { + const htmlCode = + "" + const metadata = { + indicators: { + RANDOMuid01: { + indicatorType: { factor: 1 }, + numerator: 'numerator', + denominator: 'denominator', + decimals: 2, + }, + }, + } + const result = parseHtmlToReact(htmlCode, metadata) + expect(result).toEqual( + + ) + }) + it('replaces indicator cells outside of elements', () => { + const htmlCode = + "
" + const metadata = { + indicators: { + RANDOMuid01: { + indicatorType: { factor: 1 }, + numerator: 'numerator', + denominator: 'denominator', + decimals: 2, + }, + }, + } + const result = parseHtmlToReact(htmlCode, metadata) + expect(result).toEqual( +
+ +
+ ) + }) it('uses disabled entry field when input has disabled attribute', () => { const htmlCode = diff --git a/src/data-workspace/custom-form/replace-input-node.jsx b/src/data-workspace/custom-form/replace-input-node.jsx index 1010ebc53..94d466880 100644 --- a/src/data-workspace/custom-form/replace-input-node.jsx +++ b/src/data-workspace/custom-form/replace-input-node.jsx @@ -1,6 +1,7 @@ import React from 'react' import { selectors } from '../../shared/index.js' import { DataEntryField } from '../data-entry-cell/index.js' +import { replaceIndicatorCell } from './custom-form-indicator-cell.jsx' import { replaceTotalCell } from './custom-form-total-cell.jsx' const INPUT_TYPES = { @@ -27,6 +28,7 @@ const getInputType = (domNode) => { export const replaceInputNode = (domNode, metadata) => { const inputType = getInputType(domNode) + console.log('inputType', inputType) // TODO: This was already there when I started on this branch // Need to check with Kai what his intentions were with it. // const cellProps = getCellPropsByInputType(inputType) @@ -34,6 +36,10 @@ export const replaceInputNode = (domNode, metadata) => { return replaceTotalCell(domNode.attribs.dataelementid) } + if (inputType === INPUT_TYPES.INDICATOR) { + return replaceIndicatorCell(domNode.attribs.indicatorid, metadata) + } + if (inputType !== INPUT_TYPES.ENTRYFIELD) { return undefined } diff --git a/src/data-workspace/custom-form/replace-td-node.jsx b/src/data-workspace/custom-form/replace-td-node.jsx index 8a188a971..f361d19c0 100644 --- a/src/data-workspace/custom-form/replace-td-node.jsx +++ b/src/data-workspace/custom-form/replace-td-node.jsx @@ -1,26 +1,8 @@ import { attributesToProps } from 'html-react-parser' import React from 'react' -import { IndicatorTableCell } from '../indicators-table-body/indicator-table-cell.jsx' +import { replaceIndicatorCell } from './custom-form-indicator-cell.jsx' import { replaceTotalCell } from './custom-form-total-cell.jsx' -const replaceIndicatorCell = (indicatorId, metadata) => { - const { - denominator, - numerator, - indicatorType: { factor }, - decimals, - } = metadata.indicators[indicatorId] - - return ( - - ) -} - const replaceTextCell = (domNode) => { const cleanedText = domNode.children[0].nodeValue.trim() const props = attributesToProps(domNode.attribs) From 5392a09689eb40b53ac57c1e252cfe6625e3a94e Mon Sep 17 00:00:00 2001 From: Thomas Zemp Date: Mon, 8 Jun 2026 15:28:31 +0200 Subject: [PATCH 2/2] fix: remove console statement --- src/data-workspace/custom-form/replace-input-node.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/data-workspace/custom-form/replace-input-node.jsx b/src/data-workspace/custom-form/replace-input-node.jsx index 94d466880..f82771829 100644 --- a/src/data-workspace/custom-form/replace-input-node.jsx +++ b/src/data-workspace/custom-form/replace-input-node.jsx @@ -28,7 +28,6 @@ const getInputType = (domNode) => { export const replaceInputNode = (domNode, metadata) => { const inputType = getInputType(domNode) - console.log('inputType', inputType) // TODO: This was already there when I started on this branch // Need to check with Kai what his intentions were with it. // const cellProps = getCellPropsByInputType(inputType)