From e79324029194f23c945b26cdd1f09f06bd27c213 Mon Sep 17 00:00:00 2001 From: henrikmv <110386561+henrikmv@users.noreply.github.com> Date: Fri, 31 Jan 2025 10:48:51 +0100 Subject: [PATCH] fix: [DHIS2-18582] Data element with number option set are not displayed in Stages and Events widget (#3928) * fix: remove type check when comparing values * fix: convert options to client values * fix: type * fix: code cleanup --- .../StageDetail/StageDetail.component.js | 6 ++-- .../Stages/Stage/StageDetail/hooks/helpers.js | 4 +-- .../hooks/useClientDataElements.js | 32 +++++++++++++++++++ .../Stage/StageDetail/hooks/useEventList.js | 26 +++++++-------- .../types/common.types.js | 10 ++++++ 5 files changed, 59 insertions(+), 19 deletions(-) create mode 100644 src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/hooks/useClientDataElements.js diff --git a/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/StageDetail.component.js b/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/StageDetail.component.js index 4a02ddcd75..4ab54db15f 100644 --- a/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/StageDetail.component.js +++ b/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/StageDetail.component.js @@ -27,6 +27,7 @@ import { getProgramAndStageForProgram } from '../../../../../metaData/helpers'; import type { Props } from './stageDetail.types'; import { EventRow } from './EventRow'; import { errorCreator } from '../../../../../../capture-core-utils'; +import { useClientDataElements } from './hooks/useClientDataElements'; const styles = { @@ -113,7 +114,8 @@ const StageDetailPlain = (props: Props) => { }; const { stage } = getProgramAndStageForProgram(programId, stageId); const headerColumns = useComputeHeaderColumn(dataElements, hideDueDate, enableUserAssignment, stage?.stageForm); - const { loading, value: dataSource, error } = useComputeDataFromEvent(dataElements, events); + const dataElementsClient = useClientDataElements(dataElements); + const { loading, value: dataSource, error } = useComputeDataFromEvent(dataElementsClient, events); const [{ columnName, sortDirection }, setSortInstructions] = useState(defaultSortState); const [displayedRowNumber, setDisplayedRowNumber] = useState(DEFAULT_NUMBER_OF_ROW); @@ -177,7 +179,7 @@ const StageDetailPlain = (props: Props) => { return sortDataFromEvent({ dataA, dataB, type, columnName, direction: sortDirection }); }) .slice(0, displayedRowNumber) - .map(row => formatRowForView(row, dataElements)) + .map(row => formatRowForView(row, dataElementsClient)) .map((row: Object) => { const cells = headerColumns.map(({ id }) => ( , - dataElements: Array, + dataElements: Array, querySingleResource: QuerySingleResource, absoluteApiPath: string, ) => { diff --git a/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/hooks/useClientDataElements.js b/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/hooks/useClientDataElements.js new file mode 100644 index 0000000000..a375bdd296 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/hooks/useClientDataElements.js @@ -0,0 +1,32 @@ +// @flow +import { useMemo } from 'react'; +import { convertValue } from 'capture-core/converters/serverToClient'; +import type { StageDataElement, StageDataElementClient } from '../../../../types/common.types'; + +export const useClientDataElements = (dataElements: Array) => + useMemo(() => { + if (!dataElements || !Array.isArray(dataElements)) { + return []; + } + + return dataElements.map ( + (dataElement: StageDataElement) => { + const { + options, + type, + ...rest + } = dataElement; + + const convertedOptions = options + ? Object.entries(options).map(([key, value]) => ({ + value: convertValue(key, type), + text: value, + })) : undefined; + + return { + ...rest, + type, + options: convertedOptions, + }; + }); + }, [dataElements]); diff --git a/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/hooks/useEventList.js b/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/hooks/useEventList.js index d6fcf10be0..3a545be6ec 100644 --- a/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/hooks/useEventList.js +++ b/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/hooks/useEventList.js @@ -6,7 +6,7 @@ import { useDataEngine, useConfig } from '@dhis2/app-runtime'; import { makeQuerySingleResource } from 'capture-core/utils/api'; import { errorCreator, buildUrl } from 'capture-core-utils'; import { dataElementTypes, DataElement, OptionSet, Option } from '../../../../../../metaData'; -import type { StageDataElement } from '../../../../types/common.types'; +import type { StageDataElement, StageDataElementClient } from '../../../../types/common.types'; import { convertValue as convertClientToList } from '../../../../../../converters/clientToList'; import { convertValue as convertServerToClient } from '../../../../../../converters/serverToClient'; import { @@ -45,7 +45,7 @@ const getBaseColumns = props => baseFields.map((key, index) => ({ ...key, ...get const getAllFieldsWithValue = ( eventId: string, - dataElements: Array, + dataElements: Array, dataElementsByType: Array<{type: string, eventId: string, ids: Object}>, ) => dataElements .reduce((acc, { id, type }) => { @@ -59,7 +59,7 @@ const getAllFieldsWithValue = ( return acc; }, {}); -const useComputeDataFromEvent = (dataElements: Array, events: Array) => { +const useComputeDataFromEvent = (dataElements: Array, events: Array) => { const [value, setValue] = useState(null); const [error, setError] = useState(null); const [loading, setLoading] = useState(true); @@ -132,32 +132,28 @@ const useComputeHeaderColumn = (dataElements: Array, hideDueDa return headerColumns; }; -const getDataElement = (stageDataElement, type) => { +function getDataElement(stageDataElement, type) { if (!stageDataElement) { return null; } - const dataElement = new DataElement((o) => { o.id = stageDataElement.id; o.type = type; }); if (stageDataElement.options) { - const options = Object.keys(stageDataElement.options).map( - (code: string) => - new Option((o) => { - // $FlowFixMe - o.text = stageDataElement.options[code]; - o.value = code; - }), - ); + const options = stageDataElement.options.map(({ value, text }) => + new Option((o) => { + o.text = text; + o.value = value; + })); const optionSet = new OptionSet(stageDataElement.id, options); dataElement.optionSet = optionSet; } return dataElement; -}; +} -const formatRowForView = (row: Object, dataElements: Array) => Object.keys(row).reduce((acc, id) => { +const formatRowForView = (row: Object, dataElements: Array) => Object.keys(row).reduce((acc, id) => { const { type: predefinedType } = baseFields.find(f => f.id === id) || {}; const stageDataElement = dataElements.find(el => el.id === id); const { type } = stageDataElement || {}; diff --git a/src/core_modules/capture-core/components/WidgetStagesAndEvents/types/common.types.js b/src/core_modules/capture-core/components/WidgetStagesAndEvents/types/common.types.js index cff6ac9938..24873d1721 100644 --- a/src/core_modules/capture-core/components/WidgetStagesAndEvents/types/common.types.js +++ b/src/core_modules/capture-core/components/WidgetStagesAndEvents/types/common.types.js @@ -6,6 +6,7 @@ import { dataElementTypes, Option } from '../../../metaData'; type StageOptions = { [code: string]: string; } + export type StageDataElement = { id: string, name: string, @@ -15,6 +16,15 @@ export type StageDataElement = { optionSet?: { options: Array