diff --git a/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEnrollmentDashboard.feature b/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEnrollmentDashboard.feature index 89af2a7ea9..a9158e090a 100644 --- a/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEnrollmentDashboard.feature +++ b/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEnrollmentDashboard.feature @@ -31,7 +31,7 @@ Feature: The user interacts with the widgets on the enrollment dashboard And the user sets the birthday date to the current date Then the user see the following text: The womans age is outside the normal range. With the birthdate entered, the age would be: 0 - Scenario: The user updates the TEI attributes. The changes are reflected in the whole page. + Scenario: The user updates the TEI attributes. The changes are reflected in the whole page. Given you land on the enrollment dashboard page by having typed #/enrollment?enrollmentId=TjP3J9cf0z1&orgUnitId=CgunjDKbM45&programId=WSGAb5XwJ3Y&teiId=jzIwoNXIZsK When the user clicks the element containing the text: Edit And the user sees the edit profile modal @@ -132,4 +132,4 @@ Feature: The user interacts with the widgets on the enrollment dashboard Scenario: The program rules are triggered and the effects are displayed in the sidebar widgets Given you land on the enrollment dashboard page by having typed #/enrollment?enrollmentId=wBU0RAsYjKE - Then the user can see the program rules effect in the indicator widget \ No newline at end of file + Then the user can see the program rules effect in the indicator widget diff --git a/i18n/en.pot b/i18n/en.pot index 33b593d52c..4f16b090e4 100644 --- a/i18n/en.pot +++ b/i18n/en.pot @@ -5,8 +5,8 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -"POT-Creation-Date: 2024-02-14T10:01:26.732Z\n" -"PO-Revision-Date: 2024-02-14T10:01:26.732Z\n" +"POT-Creation-Date: 2024-02-16T12:15:15.668Z\n" +"PO-Revision-Date: 2024-02-16T12:15:15.668Z\n" msgid "Choose one or more dates..." msgstr "Choose one or more dates..." @@ -1404,6 +1404,22 @@ msgstr "Something went wrong while loading relationships. Please try again later msgid "{{trackedEntityTypeName}} relationships" msgstr "{{trackedEntityTypeName}} relationships" +msgid "Delete relationship" +msgstr "Delete relationship" + +msgid "" +"Deleting the relationship is permanent and cannot be undone. Are you sure " +"you want to delete this relationship?" +msgstr "" +"Deleting the relationship is permanent and cannot be undone. Are you sure " +"you want to delete this relationship?" + +msgid "Yes, delete relationship" +msgstr "Yes, delete relationship" + +msgid "An error occurred while deleting the relationship." +msgstr "An error occurred while deleting the relationship." + msgid "To open this relationship, please wait until saving is complete" msgstr "To open this relationship, please wait until saving is complete" diff --git a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/DeleteRelationship/DeleteRelationship.js b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/DeleteRelationship/DeleteRelationship.js new file mode 100644 index 0000000000..1e84e9c881 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/DeleteRelationship/DeleteRelationship.js @@ -0,0 +1,85 @@ +// @flow + +import React, { useState } from 'react'; +import i18n from '@dhis2/d2-i18n'; +import { + DataTableCell, + IconDelete16, + Modal, + ModalContent, + ModalTitle, + ModalActions, + ButtonStrip, + Button, + colors, +} from '@dhis2/ui'; +import { IconButton } from 'capture-ui'; +import { withStyles } from '@material-ui/core/styles'; + +type Props = { + handleDeleteRelationship: () => void, + disabled?: boolean, + classes: { + tableCell: string, + }, +} + +const styles = { + tableCell: { + display: 'flex', + justifyContent: 'center', + }, +}; + +export const DeleteRelationshipPlain = ({ handleDeleteRelationship, disabled, classes }: Props) => { + const [isModalOpen, setIsModalOpen] = useState(false); + return ( + <> + + { + if (disabled) return; + setIsModalOpen(true); + }} + dataTest={'delete-relationship-button'} + > + + + + + {isModalOpen && ( + setIsModalOpen(false)} + dataTest={'delete-relationship-modal'} + > + {i18n.t('Delete relationship')} + + {i18n.t('Deleting the relationship is permanent and cannot be undone. Are you sure you want to delete this relationship?')} + + + + + + + + + + + )} + + ); +}; + +export const DeleteRelationship = withStyles(styles)(DeleteRelationshipPlain); diff --git a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/DeleteRelationship/index.js b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/DeleteRelationship/index.js new file mode 100644 index 0000000000..619b3d8839 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/DeleteRelationship/index.js @@ -0,0 +1,3 @@ +// @flow + +export { DeleteRelationship } from './DeleteRelationship'; diff --git a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/DeleteRelationship/useDeleteRelationship.js b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/DeleteRelationship/useDeleteRelationship.js new file mode 100644 index 0000000000..a50498a888 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/DeleteRelationship/useDeleteRelationship.js @@ -0,0 +1,69 @@ +// @flow +import i18n from '@dhis2/d2-i18n'; +import log from 'loglevel'; +import { errorCreator, FEATURES, useFeature } from 'capture-core-utils'; +import { handleAPIResponse, REQUESTED_ENTITIES } from 'capture-core/utils/api'; +import { useMutation, useQueryClient } from 'react-query'; +import { useAlert, useDataEngine } from '@dhis2/app-runtime'; +import { ReactQueryAppNamespace } from '../../../../../utils/reactQueryHelpers'; + +type Props = { + sourceId: string, +}; + +export type OnDeleteRelationship = ({ relationshipId: string }) => void; + +const deleteRelationshipMutation = { + resource: 'tracker?importStrategy=DELETE&async=false', + type: 'create', + data: ({ relationshipId }) => ({ + relationships: [ + { + relationship: relationshipId, + }, + ], + }), +}; +export const useDeleteRelationship = ({ sourceId }: Props): { onDeleteRelationship: OnDeleteRelationship } => { + const dataEngine = useDataEngine(); + const queryKey: string = useFeature(FEATURES.exportablePayload) ? 'relationships' : 'instances'; + const queryClient = useQueryClient(); + const { show: showError } = useAlert( + i18n.t('An error occurred while deleting the relationship.'), + { + critical: true, + }, + ); + const { mutate: onDeleteRelationship } = useMutation( + ({ relationshipId }) => dataEngine.mutate(deleteRelationshipMutation, { variables: { relationshipId } }), + { + onMutate: ({ relationshipId }) => { + const prevRelationships = queryClient + .getQueryData([ReactQueryAppNamespace, 'relationships', sourceId]); + + const apiRelationships = handleAPIResponse(REQUESTED_ENTITIES.relationships, prevRelationships); + + const newRelationships = apiRelationships + ?.filter(({ relationship }) => relationship !== relationshipId); + + queryClient.setQueryData( + [ReactQueryAppNamespace, 'relationships', sourceId], + { [queryKey]: newRelationships }); + + return { prevRelationships }; + }, + onError: (error, { relationshipId }, context) => { + log.error(errorCreator('An error occurred while deleting the relationship')({ error, relationshipId })); + showError(); + + if (!context?.prevRelationships) return; + queryClient.setQueryData( + [ReactQueryAppNamespace, 'relationships', sourceId], + context.prevRelationships, + ); + }, + }, + ); + + return { onDeleteRelationship }; +}; diff --git a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/LinkedEntitiesViewer.component.js b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/LinkedEntitiesViewer.component.js index 072177e943..02739e36f4 100644 --- a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/LinkedEntitiesViewer.component.js +++ b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/LinkedEntitiesViewer.component.js @@ -21,7 +21,12 @@ const styles = { }; -const LinkedEntitiesViewerPlain = ({ groupedLinkedEntities, onLinkedRecordClick, classes }: StyledProps) => ( +const LinkedEntitiesViewerPlain = ({ + groupedLinkedEntities, + onLinkedRecordClick, + onDeleteRelationship, + classes, +}: StyledProps) => (
diff --git a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/LinkedEntityTable.component.js b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/LinkedEntityTable.component.js index a286b51ff4..12187d1e46 100644 --- a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/LinkedEntityTable.component.js +++ b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/LinkedEntityTable.component.js @@ -23,7 +23,14 @@ const styles = { }, }; -const LinkedEntityTablePlain = ({ linkedEntities, columns, onLinkedRecordClick, context, classes }: StyledProps) => { +const LinkedEntityTablePlain = ({ + linkedEntities, + columns, + onLinkedRecordClick, + onDeleteRelationship, + context, + classes, +}: StyledProps) => { const [visibleRowsCount, setVisibleRowsCount] = useState(DEFAULT_VISIBLE_ROWS_COUNT); const visibleLinkedEntities = useMemo(() => @@ -39,12 +46,14 @@ const LinkedEntityTablePlain = ({ linkedEntities, columns, onLinkedRecordClick, {showMoreButtonVisible && ( diff --git a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/LinkedEntityTableBody.component.js b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/LinkedEntityTableBody.component.js index 898e2fec0a..19b356d9dd 100644 --- a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/LinkedEntityTableBody.component.js +++ b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/LinkedEntityTableBody.component.js @@ -10,6 +10,7 @@ import { import i18n from '@dhis2/d2-i18n'; import { convertServerToClient, convertClientToList } from '../../../../converters'; import type { Props, StyledProps } from './linkedEntityTableBody.types'; +import { DeleteRelationship } from './DeleteRelationship'; const styles = { row: { @@ -26,16 +27,18 @@ const LinkedEntityTableBodyPlain = ({ columns, onLinkedRecordClick, context, + onDeleteRelationship, classes, }: StyledProps) => ( - + { linkedEntities .map(({ id: entityId, values, baseValues, navigation }) => { - const { pendingApiResponse } = baseValues || {}; + const { pendingApiResponse, relationshipId } = baseValues || {}; return ( { @@ -76,6 +79,12 @@ const LinkedEntityTableBodyPlain = ({ ); })} + {context.display.showDeleteButton && ( + onDeleteRelationship({ relationshipId })} + disabled={pendingApiResponse} + /> + )} ); }) diff --git a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/LinkedEntityTableHeader.component.js b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/LinkedEntityTableHeader.component.js index e7681a6867..86050fae1f 100644 --- a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/LinkedEntityTableHeader.component.js +++ b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/LinkedEntityTableHeader.component.js @@ -7,7 +7,7 @@ import { } from '@dhis2/ui'; import type { Props } from './linkedEntityTableHeader.types'; -export const LinkedEntityTableHeader = ({ columns }: Props) => ( +export const LinkedEntityTableHeader = ({ columns, context }: Props) => ( { @@ -20,6 +20,9 @@ export const LinkedEntityTableHeader = ({ columns }: Props) => ( )) } + {context.display.showDeleteButton && ( + + )} ); diff --git a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/RelationshipsWidget.component.js b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/RelationshipsWidget.component.js index 0eb6b9a6d2..569440cb76 100644 --- a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/RelationshipsWidget.component.js +++ b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/RelationshipsWidget.component.js @@ -7,6 +7,7 @@ import { useGroupedLinkedEntities } from './useGroupedLinkedEntities'; import { LinkedEntitiesViewer } from './LinkedEntitiesViewer.component'; import type { Props, StyledProps } from './relationshipsWidget.types'; import { LoadingMaskElementCenter } from '../../../LoadingMasks'; +import { useDeleteRelationship } from './DeleteRelationship/useDeleteRelationship'; const styles = { header: { @@ -30,6 +31,7 @@ const RelationshipsWidgetPlain = ({ }: StyledProps) => { const [open, setOpenStatus] = useState(true); const groupedLinkedEntities = useGroupedLinkedEntities(sourceId, relationshipTypes, relationships); + const { onDeleteRelationship } = useDeleteRelationship({ sourceId }); if (isLoading) { return ( @@ -54,7 +56,7 @@ const RelationshipsWidgetPlain = ({ return (
) } diff --git a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/linkedEntitiesViewer.types.js b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/linkedEntitiesViewer.types.js index 93160917f9..297d9e2294 100644 --- a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/linkedEntitiesViewer.types.js +++ b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/linkedEntitiesViewer.types.js @@ -1,9 +1,11 @@ // @flow import type { GroupedLinkedEntities, LinkedRecordClick } from './types'; +import type { OnDeleteRelationship } from './DeleteRelationship/useDeleteRelationship'; export type Props = $ReadOnly<{| groupedLinkedEntities: GroupedLinkedEntities, onLinkedRecordClick: LinkedRecordClick, + onDeleteRelationship: OnDeleteRelationship, |}>; export type StyledProps = $ReadOnly<{| diff --git a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/linkedEntityTable.types.js b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/linkedEntityTable.types.js index 8d3fb8b72a..de06ad218d 100644 --- a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/linkedEntityTable.types.js +++ b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/linkedEntityTable.types.js @@ -1,10 +1,12 @@ // @flow import type { LinkedEntityData, TableColumn, LinkedRecordClick, Context } from './types'; +import type { OnDeleteRelationship } from './DeleteRelationship/useDeleteRelationship'; export type Props = $ReadOnly<{| linkedEntities: $ReadOnlyArray, columns: $ReadOnlyArray, onLinkedRecordClick: LinkedRecordClick, + onDeleteRelationship: OnDeleteRelationship, context: Context, |}>; diff --git a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/linkedEntityTableBody.types.js b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/linkedEntityTableBody.types.js index 1efc3202a5..e81cd21718 100644 --- a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/linkedEntityTableBody.types.js +++ b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/linkedEntityTableBody.types.js @@ -1,11 +1,13 @@ // @flow import type { LinkedEntityData, TableColumn, Context, LinkedRecordClick } from './types'; +import type { OnDeleteRelationship } from './DeleteRelationship/useDeleteRelationship'; export type Props = $ReadOnly<{| linkedEntities: $ReadOnlyArray, columns: $ReadOnlyArray, onLinkedRecordClick: LinkedRecordClick, context: Context, + onDeleteRelationship: OnDeleteRelationship, |}>; export type StyledProps = $ReadOnly<{| diff --git a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/linkedEntityTableHeader.types.js b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/linkedEntityTableHeader.types.js index 17def5ae63..a7a0a2aa2b 100644 --- a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/linkedEntityTableHeader.types.js +++ b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/linkedEntityTableHeader.types.js @@ -1,6 +1,7 @@ // @flow -import type { TableColumn } from './types'; +import type { Context, TableColumn } from './types'; export type Props = $ReadOnly<{| columns: $ReadOnlyArray, + context: Context, |}>; diff --git a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/types/GroupedLinkedEntities.types.js b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/types/GroupedLinkedEntities.types.js index 3f18f492c9..d65d774648 100644 --- a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/types/GroupedLinkedEntities.types.js +++ b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/types/GroupedLinkedEntities.types.js @@ -26,6 +26,7 @@ export type LinkedEntityData = $ReadOnly<{| values: $ReadOnly<{| [id: string]: ?string |}>, baseValues?: { relationshipCreatedAt?: string, + relationshipId: string, pendingApiResponse?: boolean, }, navigation?: { diff --git a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/useGroupedLinkedEntities.js b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/useGroupedLinkedEntities.js index 095f8e5c8a..a040648f0d 100644 --- a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/useGroupedLinkedEntities.js +++ b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/useGroupedLinkedEntities.js @@ -61,6 +61,7 @@ const getContext = ({ relationshipEntity, program, programStage, trackedEntityTy }, display: { trackedEntityTypeName: trackedEntityType.name, + showDeleteButton: true, }, }; } @@ -70,6 +71,7 @@ const getContext = ({ relationshipEntity, program, programStage, trackedEntityTy navigation: {}, display: { programStageName: programStage.name, + showDeleteButton: false, }, }; } @@ -80,7 +82,7 @@ const getContext = ({ relationshipEntity, program, programStage, trackedEntityTy }; }; -const getEventData = ({ dataValues, event, program: programId }, relationshipCreatedAt, pendingApiResponse): LinkedEntityData => { +const getEventData = ({ dataValues, event, program: programId }, { relationshipCreatedAt, relationshipId }, pendingApiResponse): LinkedEntityData => { const values = dataValues.reduce((acc, dataValue) => { acc[dataValue.dataElement] = dataValue.value; return acc; @@ -91,6 +93,7 @@ const getEventData = ({ dataValues, event, program: programId }, relationshipCre values, baseValues: { relationshipCreatedAt, + relationshipId, pendingApiResponse, }, navigation: { @@ -100,7 +103,7 @@ const getEventData = ({ dataValues, event, program: programId }, relationshipCre }; }; -const getTrackedEntityData = ({ attributes, trackedEntity }, relationshipCreatedAt, pendingApiResponse?: boolean): LinkedEntityData => { +const getTrackedEntityData = ({ attributes, trackedEntity }, { relationshipCreatedAt, relationshipId }, pendingApiResponse?: boolean): LinkedEntityData => { const values = attributes.reduce((acc, attribute) => { acc[attribute.attribute] = attribute.value; return acc; @@ -112,6 +115,7 @@ const getTrackedEntityData = ({ attributes, trackedEntity }, relationshipCreated baseValues: { pendingApiResponse, relationshipCreatedAt, + relationshipId, }, navigation: { trackedEntityId: trackedEntity, @@ -119,13 +123,13 @@ const getTrackedEntityData = ({ attributes, trackedEntity }, relationshipCreated }; }; -const getLinkedEntityData = (apiLinkedEntity, relationshipCreatedAt, pendingApiResponse) => { +const getLinkedEntityData = (apiLinkedEntity, relationshipMeta, pendingApiResponse) => { if (apiLinkedEntity.trackedEntity) { - return getTrackedEntityData(apiLinkedEntity.trackedEntity, relationshipCreatedAt, pendingApiResponse); + return getTrackedEntityData(apiLinkedEntity.trackedEntity, relationshipMeta, pendingApiResponse); } if (apiLinkedEntity.event) { - return getEventData(apiLinkedEntity.event, relationshipCreatedAt, pendingApiResponse); + return getEventData(apiLinkedEntity.event, relationshipMeta, pendingApiResponse); } if (apiLinkedEntity.enrollment) { @@ -165,6 +169,7 @@ export const useGroupedLinkedEntities = ( .diff(moment(a.createdAt))) .reduce((accGroupedLinkedEntities, relationship) => { const { + relationship: relationshipId, relationshipType: relationshipTypeId, from: fromEntity, to: toEntity, @@ -189,7 +194,10 @@ export const useGroupedLinkedEntities = ( return accGroupedLinkedEntities; } - const linkedEntityData = getLinkedEntityData(apiLinkedEntity, relationshipCreatedAt, pendingApiResponse); + const linkedEntityData = getLinkedEntityData( + apiLinkedEntity, + { relationshipCreatedAt, relationshipId }, + pendingApiResponse); if (!linkedEntityData) { return accGroupedLinkedEntities; } diff --git a/src/core_modules/capture-core/components/WidgetsRelationship/common/useRelationships/useRelationships.js b/src/core_modules/capture-core/components/WidgetsRelationship/common/useRelationships/useRelationships.js index fdd63ffa2c..84f3db620e 100644 --- a/src/core_modules/capture-core/components/WidgetsRelationship/common/useRelationships/useRelationships.js +++ b/src/core_modules/capture-core/components/WidgetsRelationship/common/useRelationships/useRelationships.js @@ -25,7 +25,7 @@ export const useRelationships = ({ entityId, searchMode, relationshipTypes }: Pr params: { // $FlowFixMe - searchMode should be a valid key of RelationshipSearchEntities [searchMode]: entityId, - fields: 'relationshipType,createdAt,from[trackedEntity[trackedEntity,attributes,program,orgUnit,trackedEntityType],event[event,dataValues,program,orgUnit,orgUnitName,status,createdAt]],to[trackedEntity[trackedEntity,attributes,program,orgUnit,trackedEntityType],event[event,dataValues,program,orgUnit,orgUnitName,status,createdAt]]', + fields: 'relationship,relationshipType,createdAt,from[trackedEntity[trackedEntity,attributes,program,orgUnit,trackedEntityType],event[event,dataValues,program,orgUnit,orgUnitName,status,createdAt]],to[trackedEntity[trackedEntity,attributes,program,orgUnit,trackedEntityType],event[event,dataValues,program,orgUnit,orgUnitName,status,createdAt]]', }, }), [entityId, searchMode]);