diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/TrackedEntityRelationshipsWrapper/TrackedEntityRelationshipsWrapper.component.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/TrackedEntityRelationshipsWrapper/TrackedEntityRelationshipsWrapper.component.js index b246f5a485..7be6a4a07b 100644 --- a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/TrackedEntityRelationshipsWrapper/TrackedEntityRelationshipsWrapper.component.js +++ b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/TrackedEntityRelationshipsWrapper/TrackedEntityRelationshipsWrapper.component.js @@ -47,7 +47,7 @@ export const TrackedEntityRelationshipsWrapper = ({ ); } - if (!relationshipTypes || !addRelationshipRenderElement) { + if (!relationshipTypes?.length || !addRelationshipRenderElement) { return null; } diff --git a/src/core_modules/capture-core/components/WidgetsRelationship/WidgetTrackedEntityRelationship/WidgetTrackedEntityRelationship.component.js b/src/core_modules/capture-core/components/WidgetsRelationship/WidgetTrackedEntityRelationship/WidgetTrackedEntityRelationship.component.js index 6037269107..8af24e2195 100644 --- a/src/core_modules/capture-core/components/WidgetsRelationship/WidgetTrackedEntityRelationship/WidgetTrackedEntityRelationship.component.js +++ b/src/core_modules/capture-core/components/WidgetsRelationship/WidgetTrackedEntityRelationship/WidgetTrackedEntityRelationship.component.js @@ -6,6 +6,7 @@ import { RelationshipsWidget } from '../common/RelationshipsWidget'; import { RelationshipSearchEntities, useRelationships } from '../common/useRelationships'; import { NewTrackedEntityRelationship } from './NewTrackedEntityRelationship'; import { useTrackedEntityTypeName } from './hooks/useTrackedEntityTypeName'; +import { useRelationshipTypes } from '../common/RelationshipsWidget/useRelationshipTypes'; export const WidgetTrackedEntityRelationship = ({ relationshipTypes: cachedRelationshipTypes, @@ -21,8 +22,17 @@ export const WidgetTrackedEntityRelationship = ({ renderTrackedEntitySearch, renderTrackedEntityRegistration, }: WidgetTrackedEntityRelationshipProps) => { - const { data: relationships, isError, isLoading: isLoadingRelationships } = useRelationships(teiId, RelationshipSearchEntities.TRACKED_ENTITY); + const { data: relationshipTypes } = useRelationshipTypes(cachedRelationshipTypes); const { data: trackedEntityTypeName, isLoading: isLoadingTEType } = useTrackedEntityTypeName(trackedEntityTypeId); + const { + data: relationships, + isError, + isLoading: isLoadingRelationships, + } = useRelationships({ + entityId: teiId, + searchMode: RelationshipSearchEntities.TRACKED_ENTITY, + relationshipTypes, + }); const isLoading = useMemo(() => isLoadingRelationships || isLoadingTEType, [isLoadingRelationships, isLoadingTEType], @@ -36,6 +46,10 @@ export const WidgetTrackedEntityRelationship = ({ ); } + if (!relationshipTypes?.length) { + return null; + } + return ( - { - relationshipTypes => ( - - ) - } + ); }; 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 c0ee94c29d..0eb6b9a6d2 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 @@ -4,7 +4,6 @@ import { Chip, IconLink24, spacers } from '@dhis2/ui'; import { withStyles } from '@material-ui/core'; import { Widget } from '../../../Widget'; import { useGroupedLinkedEntities } from './useGroupedLinkedEntities'; -import { useRelationshipTypes } from './useRelationshipTypes'; import { LinkedEntitiesViewer } from './LinkedEntitiesViewer.component'; import type { Props, StyledProps } from './relationshipsWidget.types'; import { LoadingMaskElementCenter } from '../../../LoadingMasks'; @@ -23,14 +22,13 @@ const RelationshipsWidgetPlain = ({ title, relationships, isLoading, - cachedRelationshipTypes, sourceId, + relationshipTypes, onLinkedRecordClick, children, classes, }: StyledProps) => { const [open, setOpenStatus] = useState(true); - const { data: relationshipTypes } = useRelationshipTypes(cachedRelationshipTypes); const groupedLinkedEntities = useGroupedLinkedEntities(sourceId, relationshipTypes, relationships); if (isLoading) { @@ -83,9 +81,8 @@ const RelationshipsWidgetPlain = ({ onLinkedRecordClick={onLinkedRecordClick} /> ) - }{ - relationshipTypes && children(relationshipTypes) } + {children} ); diff --git a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/relationshipsWidget.types.js b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/relationshipsWidget.types.js index e7e8d306c3..7dce149334 100644 --- a/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/relationshipsWidget.types.js +++ b/src/core_modules/capture-core/components/WidgetsRelationship/common/RelationshipsWidget/relationshipsWidget.types.js @@ -6,11 +6,11 @@ import type { LinkedRecordClick } from './types'; export type Props = $ReadOnly<{| title: string, relationships?: Array, - cachedRelationshipTypes?: RelationshipTypes, + relationshipTypes: RelationshipTypes, isLoading: boolean, sourceId: string, onLinkedRecordClick: LinkedRecordClick, - children: (relationshipTypes: RelationshipTypes) => Node, + children: Node, |}>; export type StyledProps = $ReadOnly<{| 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 d339202c7b..095f8e5c8a 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 @@ -8,7 +8,7 @@ import { dataElementTypes } from '../../../../metaData'; import { RELATIONSHIP_ENTITIES } from '../constants'; import { convertClientToList, convertServerToClient } from '../../../../converters'; import type { GroupedLinkedEntities, LinkedEntityData } from './types'; -import type { InputRelationshipData, RelationshipTypes } from '../Types'; +import type { ApiLinkedEntity, InputRelationshipData, RelationshipTypes } from '../Types'; const getFallbackFieldsByRelationshipEntity = { @@ -137,18 +137,19 @@ const getLinkedEntityData = (apiLinkedEntity, relationshipCreatedAt, pendingApiR return null; }; -const determineLinkedEntity = (fromEntity, toEntity, sourceId) => { - if (fromEntity.trackedEntity?.trackedEntity === sourceId || fromEntity.event?.event === sourceId) { - return toEntity; - } +export const determineLinkedEntity = + (fromEntity: ApiLinkedEntity, toEntity: ApiLinkedEntity, sourceId: string): ApiLinkedEntity | null => { + if (fromEntity.trackedEntity?.trackedEntity === sourceId || fromEntity.event?.event === sourceId) { + return toEntity; + } - if (toEntity.trackedEntity?.trackedEntity === sourceId || toEntity.event?.event === sourceId) { - return fromEntity; - } + if (toEntity.trackedEntity?.trackedEntity === sourceId || toEntity.event?.event === sourceId) { + return fromEntity; + } - log.error(errorCreator('Could not determine linked entity')({ fromEntity, toEntity, sourceId })); - return null; -}; + log.error(errorCreator('Could not determine linked entity')({ fromEntity, toEntity, sourceId })); + return null; + }; export const useGroupedLinkedEntities = ( sourceId: string, @@ -184,6 +185,10 @@ export const useGroupedLinkedEntities = ( return accGroupedLinkedEntities; } + if (!relationshipType.bidirectional && apiLinkedEntity === fromEntity) { + return accGroupedLinkedEntities; + } + const linkedEntityData = getLinkedEntityData(apiLinkedEntity, relationshipCreatedAt, 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 9c5b323232..7f626a84c1 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 @@ -1,7 +1,8 @@ // @flow import { useMemo } from 'react'; import { useApiDataQuery } from '../../../../utils/reactQueryHelpers'; -import type { InputRelationshipData } from '../Types'; +import type { InputRelationshipData, RelationshipTypes } from '../Types'; +import { determineLinkedEntity } from '../RelationshipsWidget/useGroupedLinkedEntities'; export const RelationshipSearchEntities = Object.freeze({ TRACKED_ENTITY: 'trackedEntity', @@ -9,12 +10,19 @@ export const RelationshipSearchEntities = Object.freeze({ EVENT: 'event', }); +type Props = {| + entityId: string, + searchMode: $Values, + relationshipTypes: ?RelationshipTypes, +|} + type ReturnData = Array; -export const useRelationships = (entityId: string, searchMode: string) => { +export const useRelationships = ({ entityId, searchMode, relationshipTypes }: Props) => { const query = useMemo(() => ({ resource: 'tracker/relationships', 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]]', }, @@ -25,7 +33,32 @@ export const useRelationships = (entityId: string, searchMode: string) => { query, { enabled: !!entityId, - select: ({ instances }: any) => instances, + select: ({ instances }: any) => { + if (!relationshipTypes?.length || !instances?.length) { + return []; + } + + return instances.reduce((acc, relationship) => { + const relationshipType = relationshipTypes + .find(relType => relType.id === relationship.relationshipType); + if (!relationshipType) { + return acc; + } + const { from, to } = relationship; + const apiLinkedEntity = determineLinkedEntity(from, to, entityId); + + if (!apiLinkedEntity) { + return acc; + } + + if (!relationshipType.bidirectional && apiLinkedEntity === from) { + return acc; + } + + acc.push(relationship); + return acc; + }, []); + }, }, ); };