From ba81d9c95dedcc39e039b181a0fea1b5551f8565 Mon Sep 17 00:00:00 2001 From: Simona Domnisoru Date: Thu, 14 Nov 2024 12:47:40 +0100 Subject: [PATCH 01/12] feat: show related stages Widget on registration page --- .../EnrollmentDataEntry.component.js | 2 + ...llmentWithFirstStageDataEntry.container.js | 21 ++++-- ...EnrollmentWithFirstStageDataEntry.types.js | 3 + .../EnrollmentRegistrationEntry.container.js | 10 ++- .../EnrollmentRegistrationEntry.types.js | 17 +++++ .../hooks/useBuildEnrollmentPayload.js | 49 +++++++++---- .../types/duplicateCheckOnSave.types.js | 1 + .../withAskToCompleteEnrollment.js | 12 ++- .../getConvertedRelatedStageEvent.js | 10 +-- .../getConvertedRelatedStageEvent.types.js | 40 ++++++++++ .../getConvertedRelatedStageEvent/index.js | 4 + .../DataEntries/converters/index.js | 3 + .../components/DataEntries/index.js | 4 +- .../EnrollmentAddEventPage.epics.js | 4 +- ...EnrollmentAddEventPageDefault.container.js | 2 +- .../RegistrationDataEntry.actions.js | 13 +++- .../RegistrationDataEntry.container.js | 10 ++- .../RegistrationDataEntry.epics.js | 23 +++--- .../helpers/deriveAutoGenerateEvents.js | 14 ++-- ...deriveFirstStageDuringRegistrationEvent.js | 2 + .../helpers/deriveRelatedStageEvent.js | 73 +++++++++++++++++++ ...erEnrollment.js => getPageToRedirectTo.js} | 25 +++++-- .../RegistrationDataEntry/helpers/index.js | 3 +- .../Validated/Validated.container.js | 3 +- .../getConvertedRelatedStageEvent.types.js | 29 -------- .../getConvertedRelatedStageEvent/index.js | 2 - .../Validated/useBuildNewEventPayload.js | 9 ++- .../Validated/validated.actions.js | 4 +- .../Validated/validated.types.js | 31 -------- .../WidgetRelatedStages.types.js | 30 +++++++- .../hooks/useRelatedStageEvents.js | 4 +- .../components/WidgetRelatedStages/index.js | 7 +- .../relatedStageEventIsValid.types.js | 4 +- 33 files changed, 324 insertions(+), 144 deletions(-) rename src/core_modules/capture-core/components/{WidgetEnrollmentEventNew/Validated => DataEntries/converters}/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js (89%) create mode 100644 src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.types.js create mode 100644 src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/index.js create mode 100644 src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveRelatedStageEvent.js rename src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/{getStageWithOpenAfterEnrollment.js => getPageToRedirectTo.js} (62%) delete mode 100644 src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.types.js delete mode 100644 src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/index.js diff --git a/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentDataEntry.component.js b/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentDataEntry.component.js index 9a902bab07..f2773e6fbb 100644 --- a/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentDataEntry.component.js +++ b/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentDataEntry.component.js @@ -42,6 +42,7 @@ import { withAOCFieldBuilder, withDataEntryFields, } from '../../DataEntryDhis2Helpers'; +import type { RelatedStageRefPayload } from '../../WidgetRelatedStages'; const overrideMessagePropNames = { errorMessage: 'validationError', @@ -335,6 +336,7 @@ type FinalTeiDataEntryProps = { onUpdateFormFieldAsync: Function, onUpdateFormField: Function, firstStageMetaData?: ?{ stage: ProgramStage }, + relatedStageRef?: { current: ?RelatedStageRefPayload }, formFoundation: RenderFoundation, }; // final step before the generic dataEntry is inserted diff --git a/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.container.js b/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.container.js index b831b9f197..d2edc31e0d 100644 --- a/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.container.js +++ b/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.container.js @@ -4,12 +4,13 @@ import type { Props } from './EnrollmentWithFirstStageDataEntry.types'; import { FirstStageDataEntry } from './EnrollmentWithFirstStageDataEntry.component'; import { useDataEntrySections } from './hooks'; import { Section } from '../../../../metaData'; +import { WidgetRelatedStages } from '../../../WidgetRelatedStages'; const getSectionId = sectionId => (sectionId === Section.MAIN_SECTION_ID ? `${Section.MAIN_SECTION_ID}-stage` : sectionId); export const EnrollmentWithFirstStageDataEntry = (props: Props) => { - const { firstStageMetaData, ...passOnProps } = props; + const { firstStageMetaData, relatedStageRef, ...passOnProps } = props; const { stage: { stageForm: firstStageFormFoundation, name: stageName }, } = firstStageMetaData; @@ -19,10 +20,18 @@ export const EnrollmentWithFirstStageDataEntry = (props: Props) => { const dataEntrySections = useDataEntrySections(stageName, beforeSectionId); return ( - + <> + + + ); }; diff --git a/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.types.js b/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.types.js index 6c2a054867..bccf388600 100644 --- a/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.types.js +++ b/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.types.js @@ -1,9 +1,12 @@ // @flow import type { ProgramStage, RenderFoundation } from '../../../../metaData'; +import type { RelatedStageRefPayload } from '../../../WidgetRelatedStages'; export type Props = { firstStageMetaData: { stage: ProgramStage, }, formFoundation: RenderFoundation, + programId: string, + relatedStageRef?: { current: ?RelatedStageRefPayload }, }; diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.container.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.container.js index 92ff9612b7..acaff25f1b 100644 --- a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.container.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.container.js @@ -1,5 +1,5 @@ // @flow -import React from 'react'; +import React, { useRef } from 'react'; import type { ComponentType } from 'react'; import { useSelector } from 'react-redux'; import { EnrollmentRegistrationEntryComponent } from './EnrollmentRegistrationEntry.component'; @@ -10,6 +10,7 @@ import { dataEntryHasChanges } from '../../DataEntry/common/dataEntryHasChanges' import { useBuildEnrollmentPayload, } from './hooks/useBuildEnrollmentPayload'; +import type { RelatedStageRefPayload } from '../../WidgetRelatedStages'; export const EnrollmentRegistrationEntry: ComponentType = ({ selectedScopeId, @@ -22,6 +23,7 @@ export const EnrollmentRegistrationEntry: ComponentType = ({ onCancel, ...passOnProps }) => { + const relatedStageRef = useRef(null); const { orgUnit, error } = useCoreOrgUnit(orgUnitId); const { ready, @@ -57,13 +59,15 @@ export const EnrollmentRegistrationEntry: ComponentType = ({ } const onSaveWithEnrollment = () => { - const teiWithEnrollment = buildTeiWithEnrollment(); - onSave(teiWithEnrollment); + const { teiWithEnrollment, formHasError, programStageIdLinkedEventToRedirectTo } = + buildTeiWithEnrollment(relatedStageRef); + !formHasError && onSave(teiWithEnrollment, programStageIdLinkedEventToRedirectTo); }; return ( , saveButtonText: (trackedEntityName: string) => string, firstStageMetaData?: ?{ stage: ?ProgramStage }, + relatedStageRef?: { current: ?RelatedStageRefPayload }, |}>; type ContainerProps = {| diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js index 65be698174..808161d25e 100644 --- a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js @@ -24,9 +24,12 @@ import { import { deriveAutoGenerateEvents, deriveFirstStageDuringRegistrationEvent, + deriveRelatedStageEvent, } from '../../../Pages/New/RegistrationDataEntry/helpers'; import type { EnrollmentPayload } from '../EnrollmentRegistrationEntry.types'; import { geometryType, getPossibleTetFeatureTypeKey, buildGeometryProp } from '../../common/TEIAndEnrollment/geometry'; +import { RelatedStageModes } from '../../../WidgetRelatedStages'; +import type { RelatedStageRefPayload } from '../../../WidgetRelatedStages'; type DataEntryReduxConverterProps = { programId: string; @@ -88,7 +91,11 @@ export const useBuildEnrollmentPayload = ({ const { firstStageMetaData } = useBuildFirstStageRegistration(programId); const { formFoundation } = useMergeFormFoundationsIfApplicable(scopeFormFoundation, firstStageMetaData); - const buildTeiWithEnrollment = (): EnrollmentPayload => { + const buildTeiWithEnrollment = (relatedStageRef?: {current: ?RelatedStageRefPayload}): { + teiWithEnrollment: EnrollmentPayload, + formHasError: boolean, + programStageIdLinkedEventToRedirectTo?: string, + } => { if (!formFoundation) throw Error('form foundation object not found'); const firstStage = firstStageMetaData && firstStageMetaData.stage; const clientValues = getClientValuesForFormData(formValues, formFoundation); @@ -126,8 +133,17 @@ export const useBuildEnrollmentPayload = ({ serverMinorVersion: minor, }); + const { formHasError, linkedEvent: relatedStageLinkedEvent, relationship, linkMode } = deriveRelatedStageEvent({ + clientRequestEvent: firstStageDuringRegistrationEvent, + relatedStageRef, + firstStageMetaData, + programId, + teiId, + }); + const autoGenerateEvents = deriveAutoGenerateEvents({ - firstStageMetadata: firstStage, + firstStageDuringRegistrationEvent, + relatedStageLinkedEvent, stages, enrolledAt, occurredAt, @@ -137,9 +153,8 @@ export const useBuildEnrollmentPayload = ({ serverMinorVersion: minor, }); - const allEventsToBeCreated = firstStageDuringRegistrationEvent - ? [firstStageDuringRegistrationEvent, ...autoGenerateEvents] - : autoGenerateEvents; + const allEventsToBeCreated = [firstStageDuringRegistrationEvent, relatedStageLinkedEvent, ...autoGenerateEvents] + .filter(Boolean); const attributes = deriveAttributesFromFormValues(formServerValues); @@ -155,17 +170,23 @@ export const useBuildEnrollmentPayload = ({ }; const tetFeatureTypeKey = getPossibleTetFeatureTypeKey(formServerValues); - const tetGeometry = tetFeatureTypeKey ? - buildGeometryProp(tetFeatureTypeKey, formValues) - : undefined; + const tetGeometry = tetFeatureTypeKey ? buildGeometryProp(tetFeatureTypeKey, formValues) : undefined; return { - trackedEntity: teiId || generateUID(), - orgUnit: orgUnitId, - trackedEntityType: trackedEntityTypeId, - attributes, - geometry: tetGeometry, - enrollments: [enrollment], + teiWithEnrollment: { + trackedEntity: teiId || generateUID(), + orgUnit: orgUnitId, + trackedEntityType: trackedEntityTypeId, + attributes, + geometry: tetGeometry, + enrollments: [enrollment], + relationships: relationship ? [relationship] : undefined, + }, + formHasError, + programStageIdLinkedEventToRedirectTo: + relatedStageLinkedEvent && linkMode === RelatedStageModes.ENTER_DATA + ? relatedStageLinkedEvent.programStage + : undefined, }; }; diff --git a/src/core_modules/capture-core/components/DataEntries/common/TEIAndEnrollment/DuplicateCheckOnSave/types/duplicateCheckOnSave.types.js b/src/core_modules/capture-core/components/DataEntries/common/TEIAndEnrollment/DuplicateCheckOnSave/types/duplicateCheckOnSave.types.js index f55dc39c0e..43e78f4ec8 100644 --- a/src/core_modules/capture-core/components/DataEntries/common/TEIAndEnrollment/DuplicateCheckOnSave/types/duplicateCheckOnSave.types.js +++ b/src/core_modules/capture-core/components/DataEntries/common/TEIAndEnrollment/DuplicateCheckOnSave/types/duplicateCheckOnSave.types.js @@ -4,4 +4,5 @@ import type { TeiPayload } from '../../../../../Pages/common/TEIRelationshipsWid export type SaveForDuplicateCheck = ( teiWithEnrollment: EnrollmentPayload | TeiPayload, + programStageIdLinkedEventToRedirectTo?: string, ) => void; diff --git a/src/core_modules/capture-core/components/DataEntries/common/trackerEvent/withAskToCompleteEnrollment/withAskToCompleteEnrollment.js b/src/core_modules/capture-core/components/DataEntries/common/trackerEvent/withAskToCompleteEnrollment/withAskToCompleteEnrollment.js index b1d2cee393..f41e682ea4 100644 --- a/src/core_modules/capture-core/components/DataEntries/common/trackerEvent/withAskToCompleteEnrollment/withAskToCompleteEnrollment.js +++ b/src/core_modules/capture-core/components/DataEntries/common/trackerEvent/withAskToCompleteEnrollment/withAskToCompleteEnrollment.js @@ -6,8 +6,8 @@ import { CompleteModal } from './CompleteModal'; import { statusTypes as eventStatuses } from '../../../../../events/statusTypes'; import { type RenderFoundation } from '../../../../../metaData'; import { addEventSaveTypes } from '../../../../WidgetEnrollmentEventNew/DataEntry/addEventSaveTypes'; -import { actions as LinkModes } from '../../../../WidgetRelatedStages/constants'; -import type { RelatedStageRefPayload } from '../../../../WidgetEnrollmentEventNew/Validated/validated.types'; +import { RelatedStageModes } from '../../../../WidgetRelatedStages'; +import type { RelatedStageRefPayload } from '../../../../WidgetRelatedStages'; type Props = { onSave: (eventId: string, dataEntryId: string, formFoundation: RenderFoundation, saveType?: ?string) => void, @@ -15,7 +15,7 @@ type Props = { isCompleted?: boolean, eventId?: ?string, formFoundation: RenderFoundation, - relatedStageRef: { current?: ?RelatedStageRefPayload }, + relatedStageRef?: { current: ?RelatedStageRefPayload }, onSaveAndCompleteEnrollment: ( eventId: string, dataEntryId: string, @@ -60,7 +60,11 @@ const getAskToCompleteEnrollment = (InnerComponent: ComponentType) => (prop ) => { const { linkMode } = relatedStageRef?.current?.getLinkedStageValues() ?? {}; eventDataToSave.current = { itemId, dataEntryId, formFoundation, saveType }; - if (askCompleteEnrollmentOnEventComplete && (isCompleted || saveType === addEventSaveTypes.COMPLETE) && linkMode !== LinkModes.ENTER_DATA) { + if ( + askCompleteEnrollmentOnEventComplete && + (isCompleted || saveType === addEventSaveTypes.COMPLETE) && + linkMode !== RelatedStageModes.ENTER_DATA + ) { setOpenCompleteModal(true); } else { onSave(itemId, dataEntryId, formFoundation, saveType); diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js b/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js similarity index 89% rename from src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js rename to src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js index 07832fe83f..5653e4179c 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js +++ b/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js @@ -1,10 +1,9 @@ // @flow import log from 'loglevel'; import { generateUID } from '../../../../utils/uid/generateUID'; -import { actions as RelatedStageModes } from '../../../WidgetRelatedStages/constants'; -import type { ConvertedRelatedStageEventProps } from './getConvertedRelatedStageEvent.types'; +import { RelatedStageModes } from '../../../WidgetRelatedStages'; +import type { LinkedRequestEvent, ConvertedRelatedStageEventProps } from './getConvertedRelatedStageEvent.types'; import { errorCreator, pipe } from '../../../../../capture-core-utils'; -import { type LinkedRequestEvent } from '../validated.types'; import { convertClientToServer, convertFormToClient } from '../../../../converters'; import { dataElementTypes } from '../../../../metaData'; @@ -69,7 +68,7 @@ const getEventDetailsByLinkMode = ({ return ({ linkedEvent: { ...baseEventDetails, - scheduledAt: convertFn(clientRequestEvent.scheduledAt, dataElementTypes.DATE), + scheduledAt: clientRequestEvent.scheduledAt, orgUnit: convertFn(linkedEventOrgUnit, dataElementTypes.ORGANISATION_UNIT), }, linkedEventId: baseEventDetails.event, @@ -100,7 +99,8 @@ export const getConvertedRelatedStageEvent = ({ enrollmentId, relatedStageType, }: ConvertedRelatedStageEventProps) => { - const requestEventIsFromConstraint = relatedStageType.fromConstraint.programStage.id === currentProgramStageId; + const requestEventIsFromConstraint = + relatedStageType.fromConstraint.programStage.id === currentProgramStageId; const { linkedEvent, linkedEventId } = getEventDetailsByLinkMode({ relatedStageDataValues, diff --git a/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.types.js b/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.types.js new file mode 100644 index 0000000000..4c0e720f7c --- /dev/null +++ b/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.types.js @@ -0,0 +1,40 @@ +// @flow +import type { RelatedStageDataValueStates, RelatedStageRelationshipType } from '../../../WidgetRelatedStages'; +import { RelatedStageModes } from '../../../WidgetRelatedStages'; + +type CommonEventDetails = { + event: string, + program: string, + programStage: string, + orgUnit: string, + trackedEntity?: ?string, + enrollment?: string, + scheduledAt: string, + dataValues: Array<{ dataElement: string, value: any }>, + status?: string, +} + +export type RequestEvent = { + ...CommonEventDetails, + occurredAt: string, + notes?: Array<{ value: string }>, + completedAt?: string, +} + +export type LinkedRequestEvent = { + ...CommonEventDetails, + occurredAt?: string, + completedAt?: string, +} + +export type ConvertedRelatedStageEventProps = {| + linkMode: $Keys, + relatedStageDataValues: RelatedStageDataValueStates, + programId: string, + teiId?: ?string, + currentProgramStageId: string, + enrollmentId?: string, + relatedStageType: RelatedStageRelationshipType, + clientRequestEvent: RequestEvent, +|} + diff --git a/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/index.js b/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/index.js new file mode 100644 index 0000000000..b6ecc885ea --- /dev/null +++ b/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/index.js @@ -0,0 +1,4 @@ +// @flow + +export { getConvertedRelatedStageEvent } from './getConvertedRelatedStageEvent'; +export type { RequestEvent, LinkedRequestEvent } from './getConvertedRelatedStageEvent.types'; diff --git a/src/core_modules/capture-core/components/DataEntries/converters/index.js b/src/core_modules/capture-core/components/DataEntries/converters/index.js index 29835b7f31..5bef2944fb 100644 --- a/src/core_modules/capture-core/components/DataEntries/converters/index.js +++ b/src/core_modules/capture-core/components/DataEntries/converters/index.js @@ -7,3 +7,6 @@ export { convertStatusOut, getConvertGeometryIn, } from './converters'; + +export { getConvertedRelatedStageEvent } from './getConvertedRelatedStageEvent'; +export type { RequestEvent, LinkedRequestEvent } from './getConvertedRelatedStageEvent'; diff --git a/src/core_modules/capture-core/components/DataEntries/index.js b/src/core_modules/capture-core/components/DataEntries/index.js index 6d73c67fbd..ff85f696cc 100644 --- a/src/core_modules/capture-core/components/DataEntries/index.js +++ b/src/core_modules/capture-core/components/DataEntries/index.js @@ -19,10 +19,12 @@ export { convertStatusIn, convertStatusOut, getConvertGeometryIn, -} from './converters/converters'; + getConvertedRelatedStageEvent, +} from './converters'; export { EnrollmentRegistrationEntry } from './EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.container'; export { TeiRegistrationEntry } from './TeiRegistrationEntry/TeiRegistrationEntry.container'; export { SingleEventRegistrationEntry } from './SingleEventRegistrationEntry/SingleEventRegistrationEntry.container'; export type { SaveForDuplicateCheck as SaveForEnrollmentAndTeiRegistration } from './common/TEIAndEnrollment/DuplicateCheckOnSave'; export type { ExistingUniqueValueDialogActionsComponent } from './withErrorMessagePostProcessor'; export { withAskToCompleteEnrollment } from './common/trackerEvent'; +export type { RequestEvent, LinkedRequestEvent } from './converters'; diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPage.epics.js b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPage.epics.js index ea90f8b0fc..6b18a26e4c 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPage.epics.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPage.epics.js @@ -11,7 +11,7 @@ import { rollbackEnrollmentEvents, saveFailed, } from '../common/EnrollmentOverviewDomain/enrollment.actions'; -import { actions as RelatedStageActions } from '../../WidgetRelatedStages/constants'; +import { RelatedStageModes } from '../../WidgetRelatedStages'; import { buildUrlQueryString } from '../../../utils/routing'; const shouldNavigateWithRelatedStage = ({ @@ -21,7 +21,7 @@ const shouldNavigateWithRelatedStage = ({ history, }) => { if (linkMode && linkedEventId) { - if (linkMode === RelatedStageActions.ENTER_DATA) { + if (linkMode === RelatedStageModes.ENTER_DATA) { const navigate = () => history.push(`/enrollmentEventEdit?${buildUrlQueryString({ eventId: linkedEventId, orgUnitId: linkedOrgUnitId, diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.container.js b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.container.js index 88b39abb5d..a3ef25c3e6 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.container.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.container.js @@ -11,7 +11,7 @@ import { buildUrlQueryString, useLocationQuery } from '../../../../utils/routing import { useProgramInfo } from '../../../../hooks/useProgramInfo'; import { useEnrollmentAddEventTopBar, EnrollmentAddEventTopBar } from '../TopBar'; import { deleteEnrollment, fetchEnrollments } from '../../Enrollment/EnrollmentPage.actions'; -import { actions as RelatedStageModes } from '../../../WidgetRelatedStages/constants'; +import { RelatedStageModes } from '../../../WidgetRelatedStages'; import { useWidgetDataFromStore } from '../hooks'; import { diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.actions.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.actions.js index 6beb555bc6..b8000eacf9 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.actions.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.actions.js @@ -46,21 +46,26 @@ export const saveNewTrackedEntityInstance = (candidateForRegistration: any) => ); // with enrollment -export const startSavingNewTrackedEntityInstanceWithEnrollment = (enrollmentPayload: EnrollmentPayload, uid: string) => +export const startSavingNewTrackedEntityInstanceWithEnrollment = ( + enrollmentPayload: EnrollmentPayload, + uid: string, + programStageIdLinkedEventToRedirectTo?: string, +) => actionCreator(registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_WITH_ENROLLMENT_SAVE_START)({ enrollmentPayload, uid, + programStageIdLinkedEventToRedirectTo, }); export const saveNewTrackedEntityInstanceWithEnrollment = ({ candidateForRegistration, - redirectTo, + pageToRedirectTo, uid, stageId, eventIndex, }: { candidateForRegistration: any, - redirectTo: string, + pageToRedirectTo: string, uid: string, stageId?: string, eventIndex: number, @@ -76,7 +81,7 @@ export const saveNewTrackedEntityInstanceWithEnrollment = ({ }, commit: { type: registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_WITH_ENROLLMENT_SAVE_COMPLETED, - meta: { redirectTo, stageId, uid, eventIndex }, + meta: { pageToRedirectTo, stageId, uid, eventIndex }, }, rollback: { type: registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_WITH_ENROLLMENT_SAVE_FAILED, diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.container.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.container.js index 8aeda04f1f..83398364d6 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.container.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.container.js @@ -30,9 +30,15 @@ export const RegistrationDataEntry: ComponentType = ({ [dispatch]); const dispatchOnSaveWithEnrollment = useCallback( - (enrollmentPayload) => { + (enrollmentPayload, programStageIdLinkedEventToRedirectTo) => { const uid = uuid(); - dispatch(startSavingNewTrackedEntityInstanceWithEnrollment(enrollmentPayload, uid)); + dispatch( + startSavingNewTrackedEntityInstanceWithEnrollment( + enrollmentPayload, + uid, + programStageIdLinkedEventToRedirectTo, + ), + ); }, [dispatch]); diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.epics.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.epics.js index 4ee21bd46c..787922f840 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.epics.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.epics.js @@ -14,7 +14,7 @@ import { } from '../../../../actions/navigateToEnrollmentOverview/navigateToEnrollmentOverview.actions'; import { buildUrlQueryString } from '../../../../utils/routing'; import { - getStageWithOpenAfterEnrollment, + getPageToRedirectTo, PAGES, } from './helpers'; import { cleanUpUid } from '../NewPage.actions'; @@ -54,15 +54,16 @@ export const startSavingNewTrackedEntityInstanceWithEnrollmentEpic: Epic = ( ofType(registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_WITH_ENROLLMENT_SAVE_START), map((action) => { const { currentSelections: { programId } } = store.value; - const { enrollmentPayload, uid } = action.payload; + const { enrollmentPayload, uid, programStageIdLinkedEventToRedirectTo } = action.payload; const { stages, useFirstStageDuringRegistration } = getTrackerProgramThrowIfNotFound(programId); - const { stageWithOpenAfterEnrollment, redirectTo } = getStageWithOpenAfterEnrollment( + const { programStageIdToRedirectTo, pageToRedirectTo } = getPageToRedirectTo( stages, useFirstStageDuringRegistration, + programStageIdLinkedEventToRedirectTo, ); const eventIndex = enrollmentPayload.enrollments[0]?.events.findIndex( - eventsToBeCreated => eventsToBeCreated.programStage === stageWithOpenAfterEnrollment?.id, + eventsToBeCreated => eventsToBeCreated.programStage === programStageIdToRedirectTo, ); return saveNewTrackedEntityInstanceWithEnrollment({ @@ -71,9 +72,9 @@ export const startSavingNewTrackedEntityInstanceWithEnrollmentEpic: Epic = ( enrollmentPayload, ], }, - redirectTo, + pageToRedirectTo, eventIndex, - stageId: stageWithOpenAfterEnrollment?.id, + stageId: programStageIdToRedirectTo, uid, }); }), @@ -91,7 +92,7 @@ export const completeSavingNewTrackedEntityInstanceWithEnrollmentEpic = ( payload: { bundleReport: { typeReportMap }, }, - meta: { uid, redirectTo, stageId, eventIndex }, + meta: { uid, pageToRedirectTo, stageId, eventIndex }, } = action; const { currentSelections: { orgUnitId, programId }, @@ -106,9 +107,9 @@ export const completeSavingNewTrackedEntityInstanceWithEnrollmentEpic = ( return EMPTY; } - if (redirectTo === PAGES.enrollmentEventNew) { + if (pageToRedirectTo === PAGES.enrollmentEventNew) { history.push( - `/${redirectTo}?${buildUrlQueryString({ + `/${pageToRedirectTo}?${buildUrlQueryString({ programId, orgUnitId, teiId, @@ -119,9 +120,9 @@ export const completeSavingNewTrackedEntityInstanceWithEnrollmentEpic = ( return EMPTY; } - if (redirectTo === PAGES.enrollmentEventEdit) { + if (pageToRedirectTo === PAGES.enrollmentEventEdit) { history.push( - `/${redirectTo}?${buildUrlQueryString({ + `/${pageToRedirectTo}?${buildUrlQueryString({ eventId, orgUnitId, initMode: dataEntryKeys.EDIT, diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveAutoGenerateEvents.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveAutoGenerateEvents.js index 215b32f57b..e4e67bad96 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveAutoGenerateEvents.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveAutoGenerateEvents.js @@ -3,9 +3,10 @@ import moment from 'moment'; import { dataElementTypes, ProgramStage } from '../../../../../metaData'; import { convertClientToServer } from '../../../../../converters'; import { convertCategoryOptionsToServer } from '../../../../../converters/clientToServer'; +import type { RequestEvent, LinkedRequestEvent } from '../../../../DataEntries'; -const ignoreAutoGenerateIfApplicable = (stage, firstStageDuringRegistrationEvent) => - !firstStageDuringRegistrationEvent || firstStageDuringRegistrationEvent.id !== stage.id; +const ignoreAutoGenerateIfApplicable = (stage, stageToSkip) => + !stageToSkip || stageToSkip.programStage !== stage.id; export const deriveAutoGenerateEvents = ({ stages, @@ -13,7 +14,8 @@ export const deriveAutoGenerateEvents = ({ occurredAt, programId, orgUnitId, - firstStageMetadata, + firstStageDuringRegistrationEvent, + relatedStageLinkedEvent, attributeCategoryOptions, serverMinorVersion, }: { @@ -22,7 +24,8 @@ export const deriveAutoGenerateEvents = ({ occurredAt: string, programId: string, orgUnitId: string, - firstStageMetadata: ?ProgramStage, + firstStageDuringRegistrationEvent: ?RequestEvent, + relatedStageLinkedEvent: ?LinkedRequestEvent, attributeCategoryOptions: { [categoryId: string]: string } | string, serverMinorVersion: number, }) => { @@ -33,7 +36,8 @@ export const deriveAutoGenerateEvents = ({ // $FlowFixMe[missing-annot] return [...stages.values()] .filter(({ autoGenerateEvent }) => autoGenerateEvent) - .filter(stage => ignoreAutoGenerateIfApplicable(stage, firstStageMetadata)) + .filter(stage => ignoreAutoGenerateIfApplicable(stage, firstStageDuringRegistrationEvent)) + .filter(stage => ignoreAutoGenerateIfApplicable(stage, relatedStageLinkedEvent)) .map( ({ id: programStage, diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveFirstStageDuringRegistrationEvent.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveFirstStageDuringRegistrationEvent.js index c0eac9af7b..2e59a8e195 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveFirstStageDuringRegistrationEvent.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveFirstStageDuringRegistrationEvent.js @@ -1,5 +1,6 @@ // @flow import { pipe } from 'capture-core-utils'; +import { generateUID } from '../../../../../utils/uid/generateUID'; import { dataElementTypes, ProgramStage } from '../../../../../metaData'; import { convertFormToClient, convertClientToServer } from '../../../../../converters'; import { convertCategoryOptionsToServer } from '../../../../../converters/clientToServer'; @@ -37,6 +38,7 @@ export const deriveFirstStageDuringRegistrationEvent = ({ : {}; const event: any = { + event: generateUID(), status: convertStatusOut(stageComplete), geometry: standardGeoJson(stageGeometry), occurredAt: convertFn(stageOccurredAt, dataElementTypes.DATE), diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveRelatedStageEvent.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveRelatedStageEvent.js new file mode 100644 index 0000000000..d5210a555b --- /dev/null +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveRelatedStageEvent.js @@ -0,0 +1,73 @@ +// @flow +import { ProgramStage } from '../../../../../metaData'; +import { getConvertedRelatedStageEvent } from '../../../../DataEntries'; +import type { RequestEvent } from '../../../../DataEntries'; +import type { RelatedStageRefPayload } from '../../../../WidgetRelatedStages'; + +export const deriveRelatedStageEvent = ({ + clientRequestEvent, + relatedStageRef, + firstStageMetaData, + programId, + teiId, +}: { + clientRequestEvent: ?RequestEvent, + relatedStageRef?: { current: ?RelatedStageRefPayload}, + firstStageMetaData: ?{ stage: ?ProgramStage}, + programId: string, + teiId?: ?string; +}) => { + if (relatedStageRef?.current && relatedStageRef.current.eventHasLinkableStageRelationship()) { + const isValid = relatedStageRef.current.formIsValidOnSave(); + const currentProgramStageId = firstStageMetaData?.stage?.id; + if ( + !isValid || + !relatedStageRef.current?.getLinkedStageValues || + !currentProgramStageId || + !clientRequestEvent + ) { + return { + formHasError: true, + linkedEvent: null, + relationship: null, + linkMode: null, + }; + } + + const { selectedRelationshipType, relatedStageDataValues, linkMode } = + relatedStageRef.current.getLinkedStageValues(); + + if (!linkMode) { + return { + formHasError: false, + linkedEvent: null, + relationship: null, + linkMode: null, + }; + } + + const { linkedEvent, relationship } = getConvertedRelatedStageEvent({ + linkMode, + relatedStageDataValues, + clientRequestEvent, + + relatedStageType: selectedRelationshipType, + programId, + currentProgramStageId, + teiId, + }); + + return { + formHasError: false, + linkedEvent, + relationship, + linkMode, + }; + } + return { + formHasError: false, + linkedEvent: null, + relationship: null, + linkMode: null, + }; +}; diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/getStageWithOpenAfterEnrollment.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/getPageToRedirectTo.js similarity index 62% rename from src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/getStageWithOpenAfterEnrollment.js rename to src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/getPageToRedirectTo.js index 3688d29b4c..baee7b2d40 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/getStageWithOpenAfterEnrollment.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/getPageToRedirectTo.js @@ -6,18 +6,27 @@ export const PAGES = { enrollmentEventEdit: 'enrollmentEventEdit', enrollmentDashboard: 'enrollmentDashboard', }; - -// an event can be created either during first stage registration or autogenerated -// when the event will be created redirect to enrollmentEventEdit -// when the event will not be created redirect to enrollmentEventNew -export const getStageWithOpenAfterEnrollment = ( +/** + * An event can be + * - created during first stage registration + * - created and linked during first stage registration + * - autogenerated + * When the event will be created redirect to enrollmentEventEdit + * When the event will not be created redirect to enrollmentEventNew + */ +export const getPageToRedirectTo = ( stages: Map, useFirstStageDuringRegistration: boolean, + programStageIdLinkedEventToRedirectTo?: string, ) => { const stagesArray = [...stages.values()]; const [firstStageWithOpenAfterEnrollment] = stagesArray.filter(({ openAfterEnrollment }) => openAfterEnrollment); - const redirectTo = (() => { + const pageToRedirectTo = (() => { + // event will be created and linked during first stage registration + if (programStageIdLinkedEventToRedirectTo) { + return PAGES.enrollmentEventEdit; + } if (firstStageWithOpenAfterEnrollment) { // event will be created during first stage registration if ( @@ -38,7 +47,7 @@ export const getStageWithOpenAfterEnrollment = ( })(); return { - stageWithOpenAfterEnrollment: firstStageWithOpenAfterEnrollment, - redirectTo, + programStageIdToRedirectTo: programStageIdLinkedEventToRedirectTo || firstStageWithOpenAfterEnrollment?.id, + pageToRedirectTo, }; }; diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/index.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/index.js index fe7c884a9e..8dddd26bf7 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/index.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/index.js @@ -1,5 +1,6 @@ // @flow export { deriveFirstStageDuringRegistrationEvent } from './deriveFirstStageDuringRegistrationEvent'; +export { deriveRelatedStageEvent } from './deriveRelatedStageEvent'; export { deriveAutoGenerateEvents } from './deriveAutoGenerateEvents'; -export { getStageWithOpenAfterEnrollment, PAGES } from './getStageWithOpenAfterEnrollment'; +export { getPageToRedirectTo, PAGES } from './getPageToRedirectTo'; export { standardGeoJson } from './standardGeoJson'; diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.container.js b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.container.js index 61c961a257..5f29998ba1 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.container.js +++ b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.container.js @@ -14,11 +14,12 @@ import { setSaveEnrollmentEventInProgress, startCreateNewAfterCompleting, } from './validated.actions'; -import type { ContainerProps, RelatedStageRefPayload } from './validated.types'; +import type { ContainerProps } from './validated.types'; import type { RenderFoundation } from '../../../metaData'; import { addEventSaveTypes } from '../DataEntry/addEventSaveTypes'; import { useAvailableProgramStages } from '../../../hooks'; import { createServerData, useBuildNewEventPayload } from './useBuildNewEventPayload'; +import type { RelatedStageRefPayload } from '../../WidgetRelatedStages'; const SaveHandlerHOC = withSaveHandler()(ValidatedComponent); const AskToCreateNewHandlerHOC = withAskToCreateNew()(SaveHandlerHOC); diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.types.js b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.types.js deleted file mode 100644 index ef2ae727a7..0000000000 --- a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.types.js +++ /dev/null @@ -1,29 +0,0 @@ -// @flow -import type { RelatedStageDataValueStates } from '../../../WidgetRelatedStages'; -import { actions as LinkModes } from '../../../WidgetRelatedStages/constants'; -import type { RequestEvent } from '../validated.types'; - -type RelatedStageType = {| - id: string, - fromConstraint: {| - programStage: { - id: string, - }, - |}, - toConstraint: { - programStage: { - id: string, - }, - } -|} - -export type ConvertedRelatedStageEventProps = {| - linkMode: $Keys, - relatedStageDataValues: RelatedStageDataValueStates, - programId: string, - teiId: string, - currentProgramStageId: string, - enrollmentId: string, - relatedStageType: RelatedStageType, - clientRequestEvent: RequestEvent, -|} diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/index.js b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/index.js deleted file mode 100644 index 1771ccf5b3..0000000000 --- a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/index.js +++ /dev/null @@ -1,2 +0,0 @@ -// @flow -export { getConvertedRelatedStageEvent } from './getConvertedRelatedStageEvent'; diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/useBuildNewEventPayload.js b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/useBuildNewEventPayload.js index e4269a87e1..791737876c 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/useBuildNewEventPayload.js +++ b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/useBuildNewEventPayload.js @@ -6,8 +6,9 @@ import { getAddEventEnrollmentServerData } from './getConvertedAddEvent'; import { convertDataEntryToClientValues } from '../../DataEntry/common/convertDataEntryToClientValues'; import { generateUID } from '../../../utils/uid/generateUID'; import { addEventSaveTypes } from '../DataEntry/addEventSaveTypes'; -import { getConvertedRelatedStageEvent } from './getConvertedRelatedStageEvent'; -import type { LinkedRequestEvent, RelatedStageRefPayload, RequestEvent } from './validated.types'; +import { getConvertedRelatedStageEvent } from '../../DataEntries'; +import type { LinkedRequestEvent, RequestEvent } from '../../DataEntries'; +import type { RelatedStageRefPayload } from '../../WidgetRelatedStages'; type Props = { dataEntryId: string, @@ -68,7 +69,7 @@ export const useBuildNewEventPayload = ({ const buildRelatedStageEventPayload = (clientRequestEvent, saveType: ?$Values, relatedStageRef) => { if ( - relatedStageRef.current + relatedStageRef?.current && relatedStageRef.current.eventHasLinkableStageRelationship() ) { const isValid = relatedStageRef.current.formIsValidOnSave(); @@ -121,7 +122,7 @@ export const useBuildNewEventPayload = ({ const buildNewEventPayload = ( saveType: ?$Values, - relatedStageRef: {| current: (?RelatedStageRefPayload) |}, + relatedStageRef?: {| current: (?RelatedStageRefPayload) |}, ) => { const requestEventId = generateUID(); diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/validated.actions.js b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/validated.actions.js index 0aa4c1292b..ddd8c75878 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/validated.actions.js +++ b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/validated.actions.js @@ -1,8 +1,8 @@ // @flow import { actionCreator } from '../../../actions/actions.utils'; import { effectMethods } from '../../../trackerOffline'; -import { actions as RelatedStageModes } from '../../WidgetRelatedStages/constants'; -import type { RequestEvent, LinkedRequestEvent } from './validated.types'; +import { RelatedStageModes } from '../../WidgetRelatedStages'; +import type { RequestEvent, LinkedRequestEvent } from '../../DataEntries'; import type { ExternalSaveHandler } from '../common.types'; export const newEventBatchActionTypes = { diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/validated.types.js b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/validated.types.js index e0af3da0ff..8d8e58fa74 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/validated.types.js +++ b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/validated.types.js @@ -7,37 +7,6 @@ import type { RulesExecutionDependenciesClientFormatted, } from '../common.types'; -type CommonEventDetails = { - event: string, - program: string, - programStage: string, - orgUnit: string, - trackedEntity: string, - enrollment: string, - scheduledAt: string, - dataValues: Array<{ dataElement: string, value: any }>, - status?: string, -} - -export type RequestEvent = { - ...CommonEventDetails, - occurredAt: string, - notes?: Array<{ value: string }>, - completedAt?: string, -} - -export type LinkedRequestEvent = { - ...CommonEventDetails, - occurredAt?: string, - completedAt?: string, -} - -export type RelatedStageRefPayload = {| - getLinkedStageValues: () => any, - eventHasLinkableStageRelationship: () => boolean, - formIsValidOnSave: () => boolean, -|} - export type ContainerProps = {| ...CommonValidatedProps, orgUnit: OrgUnit, diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js b/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js index 6f9288bb30..25284949c7 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js @@ -1,5 +1,5 @@ // @flow -import { actions as LinkModes } from './constants'; +import { RelatedStageModes } from './index'; import type { Constraint } from './RelatedStagesActions/RelatedStagesActions.types'; export type RelationshipType = {| @@ -17,12 +17,12 @@ export type RelationshipType = {| export type Props = {| programId: string, - enrollmentId: string, + enrollmentId?: string, programStageId: string, currentStageLabel: string, |} export type RelatedStageDataValueStates = {| - linkMode: ?$Keys, + linkMode: ?$Keys, scheduledAt: string, orgUnit: ?{ path: string, @@ -31,3 +31,27 @@ export type RelatedStageDataValueStates = {| }, linkedEventId: ?string, |} + +export type RelatedStageRelationshipType = {| + id: string, + fromConstraint: {| + programStage: { + id: string, + }, + |}, + toConstraint: { + programStage: { + id: string, + }, + } +|} + +export type RelatedStageRefPayload = { + getLinkedStageValues: () => { + selectedRelationshipType: RelatedStageRelationshipType, + relatedStageDataValues: RelatedStageDataValueStates, + linkMode: ?$Keys, + }, + eventHasLinkableStageRelationship: () => boolean, + formIsValidOnSave: () => boolean, +}; diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/hooks/useRelatedStageEvents.js b/src/core_modules/capture-core/components/WidgetRelatedStages/hooks/useRelatedStageEvents.js index 8a5e8a7c17..bc9d59d53d 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/hooks/useRelatedStageEvents.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/hooks/useRelatedStageEvents.js @@ -7,7 +7,7 @@ import { handleAPIResponse, REQUESTED_ENTITIES } from '../../../utils/api'; type Props = { stageId: ?string, - enrollmentId: string, + enrollmentId?: string, scheduledLabel: string, occurredLabel: string, relationshipTypeId: ?string, @@ -41,7 +41,7 @@ export const useRelatedStageEvents = ({ ['availableRelatedStageEvents', stageId, enrollmentId, relationshipTypeId], query, { - enabled: !!stageId && enabled, + enabled: !!stageId && !!enrollmentId && enabled, cacheTime: 0, staleTime: 0, select: (response: any) => { diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/index.js b/src/core_modules/capture-core/components/WidgetRelatedStages/index.js index 1cba4d9943..082bdd7c93 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/index.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/index.js @@ -1,4 +1,9 @@ // @flow export { WidgetRelatedStages } from './WidgetRelatedStages.component'; -export type { RelatedStageDataValueStates } from './WidgetRelatedStages.types'; +export type { + RelatedStageDataValueStates, + RelatedStageRefPayload, + RelatedStageRelationshipType, +} from './WidgetRelatedStages.types'; +export { actions as RelatedStageModes } from './constants'; export { relatedStageWidgetIsValid } from './relatedStageEventIsValid/relatedStageEventIsValid'; diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/relatedStageEventIsValid.types.js b/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/relatedStageEventIsValid.types.js index c97648e958..f3521b8cc5 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/relatedStageEventIsValid.types.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/relatedStageEventIsValid.types.js @@ -1,9 +1,9 @@ // @flow import type { ErrorMessagesForRelatedStages } from '../RelatedStagesActions'; -import { actions as LinkModes } from '../constants'; +import { RelatedStageModes } from '../index'; export type RelatedStageIsValidProps = {| - linkMode: ?$Keys, + linkMode: ?$Keys, scheduledAt: ?string, orgUnit: ?{ id: string, From 293c35908d08e979e46262e776b91e4b7b9bd719 Mon Sep 17 00:00:00 2001 From: Simona Domnisoru Date: Mon, 18 Nov 2024 08:33:29 +0100 Subject: [PATCH 02/12] feat: add enableLinkExistingEvent prop --- i18n/en.pot | 7 +++- .../getConvertedRelatedStageEvent.js | 3 +- .../Validated/Validated.component.js | 1 + .../RelatedStagesActions.component.js | 41 ++++++++++--------- .../RelatedStagesActions.types.js | 1 + .../WidgetRelatedStages.types.js | 1 + 6 files changed, 31 insertions(+), 23 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index 370523a4b2..5e5420d6b5 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-10-25T18:18:11.518Z\n" -"PO-Revision-Date: 2024-10-25T18:18:11.518Z\n" +"POT-Creation-Date: 2024-11-18T07:23:16.381Z\n" +"PO-Revision-Date: 2024-11-18T07:23:16.381Z\n" msgid "Choose one or more dates..." msgstr "Choose one or more dates..." @@ -1415,6 +1415,9 @@ msgstr "Link to an existing {{linkableStageLabel}}" msgid "Choose a {{linkableStageLabel}}" msgstr "Choose a {{linkableStageLabel}}" +msgid "Actions - {{relationshipName}}" +msgstr "Actions - {{relationshipName}}" + msgid "{{ linkableStageLabel }} is not repeatable" msgstr "{{ linkableStageLabel }} is not repeatable" diff --git a/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js b/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js index 5653e4179c..e2299cf418 100644 --- a/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js +++ b/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js @@ -99,8 +99,7 @@ export const getConvertedRelatedStageEvent = ({ enrollmentId, relatedStageType, }: ConvertedRelatedStageEventProps) => { - const requestEventIsFromConstraint = - relatedStageType.fromConstraint.programStage.id === currentProgramStageId; + const requestEventIsFromConstraint = relatedStageType.fromConstraint.programStage.id === currentProgramStageId; const { linkedEvent, linkedEventId } = getEventDetailsByLinkMode({ relatedStageDataValues, diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.component.js b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.component.js index b3ba7c2d14..3af5f487f6 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.component.js +++ b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.component.js @@ -53,6 +53,7 @@ const ValidatedPlain = ({ programId={programId} programStageId={stage?.id} currentStageLabel={stage.name} + enableLinkExistingEvent /> { const { programStage } = useProgramStageInfo(constraint?.programStage?.id); @@ -73,7 +74,7 @@ export const RelatedStagesActionsPlain = ({ return (
{type === relatedStageStatus.LINKABLE && ( @@ -114,24 +115,26 @@ export const RelatedStagesActionsPlain = ({ value={RelatedStagesActionTypes.ENTER_DATA} /> - - updateSelectedAction(e.value)} - value={RelatedStagesActionTypes.LINK_EXISTING_RESPONSE} - /> - + {enableLinkExistingEvent && ( + + updateSelectedAction(e.value)} + value={RelatedStagesActionTypes.LINK_EXISTING_RESPONSE} + /> + + )} )} diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.types.js b/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.types.js index a99f2d0758..0e2084b0d9 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.types.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.types.js @@ -37,5 +37,6 @@ export type Props = {| addErrorMessage: (ErrorMessagesForRelatedStages) => void, setRelatedStagesDataValues: (() => Object) => void, currentStageLabel: string, + enableLinkExistingEvent?: boolean, ...CssClasses |} diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js b/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js index 25284949c7..b0b2a87978 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js @@ -20,6 +20,7 @@ export type Props = {| enrollmentId?: string, programStageId: string, currentStageLabel: string, + enableLinkExistingEvent?: boolean, |} export type RelatedStageDataValueStates = {| linkMode: ?$Keys, From ddb3f0efd33abda13a58560884261e2914f613b0 Mon Sep 17 00:00:00 2001 From: Simona Domnisoru Date: Wed, 27 Nov 2024 15:55:34 +0100 Subject: [PATCH 03/12] chore: improve wording --- i18n/en.pot | 21 ++++++------------- ...llmentWithFirstStageDataEntry.container.js | 1 - .../Validated/Validated.component.js | 1 - .../EnterDataInOrgUnit/EnterData.component.js | 7 ++----- .../LinkToExisting.component.js | 2 +- .../RelatedStagesActions.component.js | 2 -- .../RelatedStagesActions.types.js | 1 - .../WidgetRelatedStages.component.js | 2 -- .../WidgetRelatedStages.types.js | 1 - .../WidgetRelatedStages/constants.js | 2 +- 10 files changed, 10 insertions(+), 30 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index 9de1bab609..95b582c37a 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-11-07T11:57:59.094Z\n" -"PO-Revision-Date: 2024-11-07T11:57:59.094Z\n" +"POT-Creation-Date: 2024-11-26T11:09:35.292Z\n" +"PO-Revision-Date: 2024-11-26T11:09:35.292Z\n" msgid "Choose one or more dates..." msgstr "Choose one or more dates..." @@ -1424,8 +1424,8 @@ msgstr "{{trackedEntityTypeName}} profile" msgid "tracked entity instance" msgstr "tracked entity instance" -msgid "Link to an existing {{linkableStageLabel}}" -msgstr "Link to an existing {{linkableStageLabel}}" +msgid "Choose a {{linkableStageLabel}} event" +msgstr "Choose a {{linkableStageLabel}} event" msgid "Choose a {{linkableStageLabel}}" msgstr "Choose a {{linkableStageLabel}}" @@ -1445,8 +1445,8 @@ msgstr "Ambiguous relationships, contact system administrator" msgid "Enter details now" msgstr "Enter details now" -msgid "Link to an existing" -msgstr "Link to an existing" +msgid "Link to an existing event" +msgstr "Link to an existing event" msgid "Scheduled date" msgstr "Scheduled date" @@ -1681,15 +1681,6 @@ msgstr "Follow up" msgid "Choose a program stage to filter by {{label}}" msgstr "Choose a program stage to filter by {{label}}" -msgid "Active enrollments" -msgstr "Active enrollments" - -msgid "Completed enrollments" -msgstr "Completed enrollments" - -msgid "Cancelled enrollments" -msgstr "Cancelled enrollments" - msgid "" "Some enrollments were completed successfully, but there was an error while " "completing the rest. Please see the details below." diff --git a/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.container.js b/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.container.js index d2edc31e0d..69050725e9 100644 --- a/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.container.js +++ b/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.container.js @@ -30,7 +30,6 @@ export const EnrollmentWithFirstStageDataEntry = (props: Props) => { ref={relatedStageRef} programId={passOnProps.programId} programStageId={firstStageMetaData.stage?.id} - currentStageLabel={firstStageMetaData.stage?.name} /> ); diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.component.js b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.component.js index 3af5f487f6..104cbcf420 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.component.js +++ b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.component.js @@ -52,7 +52,6 @@ const ValidatedPlain = ({ enrollmentId={enrollmentId} programId={programId} programStageId={stage?.id} - currentStageLabel={stage.name} enableLinkExistingEvent /> Object) => void, - currentStageLabel: string, saveAttempted: boolean, errorMessages: ErrorMessagesForRelatedStages, ...CssClasses @@ -60,7 +59,6 @@ export const EnterDataInOrgUnitPlain = ({ setRelatedStagesDataValues, saveAttempted, errorMessages, - currentStageLabel, classes, }: Props) => { const onSelectOrgUnit = (e: { id: string, displayName: string, path: string }) => { @@ -98,11 +96,10 @@ export const EnterDataInOrgUnitPlain = ({ {i18n.t( relatedStagesDataValues?.orgUnit?.name - ? 'Enter {{linkableStageLabel}} details for {{orgUnitLabel}} in the next step after completing this {{currentStageLabel}}.' - : 'Select organisation unit and enter {{linkableStageLabel}} details in the next step after completing this {{currentStageLabel}}.', + ? 'Enter {{linkableStageLabel}} details for {{orgUnitLabel}} in the next step' + : 'Select organisation unit and enter {{linkableStageLabel}} details in the next step', { linkableStageLabel, - currentStageLabel, orgUnitLabel: relatedStagesDataValues?.orgUnit?.name, }, )} diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/LinkToExisting/LinkToExisting.component.js b/src/core_modules/capture-core/components/WidgetRelatedStages/LinkToExisting/LinkToExisting.component.js index a53c05eb3f..dbc8d442d5 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/LinkToExisting/LinkToExisting.component.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/LinkToExisting/LinkToExisting.component.js @@ -40,7 +40,7 @@ export const LinkToExistingPlain = ({ return (

- {i18n.t('Link to an existing {{linkableStageLabel}}', { + {i18n.t('Choose a {{linkableStageLabel}} event', { linkableStageLabel, })}

diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js b/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js index defb1f55cd..8be0e97898 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js @@ -50,7 +50,6 @@ export const RelatedStagesActionsPlain = ({ relatedStagesDataValues, setRelatedStagesDataValues, constraint, - currentStageLabel, errorMessages, saveAttempted, enableLinkExistingEvent, @@ -170,7 +169,6 @@ export const RelatedStagesActionsPlain = ({ linkableStageLabel={programStage.stageForm.name} relatedStagesDataValues={relatedStagesDataValues} setRelatedStagesDataValues={setRelatedStagesDataValues} - currentStageLabel={currentStageLabel} saveAttempted={saveAttempted} errorMessages={errorMessages} /> diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.types.js b/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.types.js index 0e2084b0d9..dee2a54806 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.types.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.types.js @@ -36,7 +36,6 @@ export type Props = {| constraint: ?Constraint, addErrorMessage: (ErrorMessagesForRelatedStages) => void, setRelatedStagesDataValues: (() => Object) => void, - currentStageLabel: string, enableLinkExistingEvent?: boolean, ...CssClasses |} diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.component.js b/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.component.js index 722515d992..31460917ac 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.component.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.component.js @@ -14,7 +14,6 @@ const WidgetRelatedStagesPlain = ({ programId, enrollmentId, programStageId, - currentStageLabel, ...passOnProps }: Props, ref) => { const { currentRelatedStagesStatus, selectedRelationshipType, constraint } = useRelatedStages({ @@ -108,7 +107,6 @@ const WidgetRelatedStagesPlain = ({ saveAttempted={saveAttempted} errorMessages={errorMessages} constraint={constraint} - currentStageLabel={currentStageLabel} {...passOnProps} /> ); diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js b/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js index b0b2a87978..8995ddaf82 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js @@ -19,7 +19,6 @@ export type Props = {| programId: string, enrollmentId?: string, programStageId: string, - currentStageLabel: string, enableLinkExistingEvent?: boolean, |} export type RelatedStageDataValueStates = {| diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/constants.js b/src/core_modules/capture-core/components/WidgetRelatedStages/constants.js index bb46ba298d..d8e57bb9a4 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/constants.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/constants.js @@ -15,5 +15,5 @@ export const actions = Object.freeze({ export const mainOptionTranslatedTexts = { [actions.SCHEDULE_IN_ORG]: i18n.t('Schedule'), [actions.ENTER_DATA]: i18n.t('Enter details now'), - [actions.LINK_EXISTING_RESPONSE]: i18n.t('Link to an existing'), + [actions.LINK_EXISTING_RESPONSE]: i18n.t('Link to an existing event'), }; From 3eb3c93af34a75a48007bcd975af3ae65f833e64 Mon Sep 17 00:00:00 2001 From: Simona Domnisoru Date: Mon, 2 Dec 2024 13:10:24 +0100 Subject: [PATCH 04/12] feat: show related stages widget when adding a new relationship --- i18n/en.pot | 13 +- ...llmentWithFirstStageDataEntry.container.js | 3 +- ...EnrollmentWithFirstStageDataEntry.types.js | 8 + .../EnrollmentRegistrationEntry.types.js | 8 + .../addRelationshipForNewSingleEvent.epics.js | 12 +- ...lmentRegistrationEntryWrapper.component.js | 7 +- .../DataEntryEnrollment.component.js | 9 + .../RegisterTei/RegisterTei.component.js | 8 +- .../RegisterTei/RegisterTei.types.js | 7 +- .../exposedHelpers/getRelationshipNewTei.js | 97 +------- .../NewRelationship/RegisterTei/index.js | 2 +- .../TeiRelationship.component.js | 13 +- .../ViewEventRelationships.epics.js | 7 +- .../DataEntryEnrollment.component.js | 9 + .../exposedHelpers/getRelationshipNewTei.js | 100 +-------- .../RegisterTei/index.js | 2 +- .../Validated/Validated.component.js | 1 - .../RelatedStagesActions.component.js | 212 +++++++++++++----- .../RelatedStagesActions.types.js | 9 +- .../WidgetRelatedStages.types.js | 8 +- .../hooks/useAddRelationship.js | 11 +- 21 files changed, 270 insertions(+), 276 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index 95b582c37a..66fbc5b05b 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-11-26T11:09:35.292Z\n" -"PO-Revision-Date: 2024-11-26T11:09:35.292Z\n" +"POT-Creation-Date: 2024-12-02T11:16:49.543Z\n" +"PO-Revision-Date: 2024-12-02T11:16:49.543Z\n" msgid "Choose one or more dates..." msgstr "Choose one or more dates..." @@ -828,6 +828,9 @@ msgstr "Save {{trackedEntityTypeName}}" msgid "Save {{trackedEntityName}}" msgstr "Save {{trackedEntityName}}" +msgid "Enter details now is not available when creating a relationship" +msgstr "Enter details now is not available when creating a relationship" + msgid "Save new {{trackedEntityTypeName}} and link" msgstr "Save new {{trackedEntityTypeName}} and link" @@ -1430,15 +1433,15 @@ msgstr "Choose a {{linkableStageLabel}} event" msgid "Choose a {{linkableStageLabel}}" msgstr "Choose a {{linkableStageLabel}}" -msgid "Actions - {{relationshipName}}" -msgstr "Actions - {{relationshipName}}" - msgid "{{ linkableStageLabel }} is not repeatable" msgstr "{{ linkableStageLabel }} is not repeatable" msgid "{{ linkableStageLabel }} has no linkable events" msgstr "{{ linkableStageLabel }} has no linkable events" +msgid "Actions - {{relationshipName}}" +msgstr "Actions - {{relationshipName}}" + msgid "Ambiguous relationships, contact system administrator" msgstr "Ambiguous relationships, contact system administrator" diff --git a/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.container.js b/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.container.js index 69050725e9..bcb91759f0 100644 --- a/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.container.js +++ b/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.container.js @@ -10,7 +10,7 @@ const getSectionId = sectionId => (sectionId === Section.MAIN_SECTION_ID ? `${Section.MAIN_SECTION_ID}-stage` : sectionId); export const EnrollmentWithFirstStageDataEntry = (props: Props) => { - const { firstStageMetaData, relatedStageRef, ...passOnProps } = props; + const { firstStageMetaData, relatedStageRef, relatedStageModesOptions, ...passOnProps } = props; const { stage: { stageForm: firstStageFormFoundation, name: stageName }, } = firstStageMetaData; @@ -30,6 +30,7 @@ export const EnrollmentWithFirstStageDataEntry = (props: Props) => { ref={relatedStageRef} programId={passOnProps.programId} programStageId={firstStageMetaData.stage?.id} + actionTypesOptions={relatedStageModesOptions} /> ); diff --git a/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.types.js b/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.types.js index bccf388600..cbfbef6ea7 100644 --- a/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.types.js +++ b/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.types.js @@ -1,6 +1,7 @@ // @flow import type { ProgramStage, RenderFoundation } from '../../../../metaData'; import type { RelatedStageRefPayload } from '../../../WidgetRelatedStages'; +import { RelatedStageModes } from '../../../WidgetRelatedStages'; export type Props = { firstStageMetaData: { @@ -9,4 +10,11 @@ export type Props = { formFoundation: RenderFoundation, programId: string, relatedStageRef?: { current: ?RelatedStageRefPayload }, + relatedStageModesOptions?: { + [key: $Keys]: { + hidden?: boolean, + disabled?: boolean, + disabledMessage?: string + }, + }, }; diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.types.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.types.js index 11e594cd34..edbe849b06 100644 --- a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.types.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.types.js @@ -8,6 +8,7 @@ import type { ExistingUniqueValueDialogActionsComponent } from '../withErrorMess import type { InputAttribute } from './hooks/useFormValues'; import { RenderFoundation, ProgramStage } from '../../../metaData'; import type { RelatedStageRefPayload } from '../../WidgetRelatedStages'; +import { RelatedStageModes } from '../../WidgetRelatedStages'; type TrackedEntityAttributes = Array<{ attribute: string, @@ -68,6 +69,13 @@ export type OwnProps = $ReadOnly<{| saveButtonText: (trackedEntityName: string) => string, firstStageMetaData?: ?{ stage: ?ProgramStage }, relatedStageRef?: { current: ?RelatedStageRefPayload }, + relatedStageModesOptions?: { + [key: $Keys]: { + hidden?: boolean, + disabled?: boolean, + disabledMessage?: string + }, + }, |}>; type ContainerProps = {| diff --git a/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/epics/addRelationshipForNewSingleEvent.epics.js b/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/epics/addRelationshipForNewSingleEvent.epics.js index 73107c5710..65fd3ae6ac 100644 --- a/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/epics/addRelationshipForNewSingleEvent.epics.js +++ b/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/epics/addRelationshipForNewSingleEvent.epics.js @@ -29,7 +29,7 @@ import { } from '../../../../../DataEntry/actions/dataEntry.actions'; import { getDataEntryKey } from '../../../../../DataEntry/common/getDataEntryKey'; import { convertClientRelationshipToServer } from '../../../../../../relationships/convertClientToServer'; -import { getRelationshipNewTei } from '../../../../../Pages/NewRelationship/RegisterTei'; +import { getRelationshipNewTeiName } from '../../../../../Pages/NewRelationship/RegisterTei'; const dataEntryId = 'singleEvent'; const itemId = 'newEvent'; @@ -47,13 +47,8 @@ export const addRelationshipForNewSingleEventEpic = (action$: InputObservable, s const state = store.value; const existingRelationships = state.dataEntriesRelationships[dataEntryKey] || []; const payload = action.payload; - const entity = payload.entity; + const toEntity = payload.entity; - const toEntity = entity.id ? entity : getRelationshipNewTei(entity.dataEntryId, entity.itemId, state); - const toEntityIsNew = !entity.id; - const newToEntity = toEntityIsNew ? { - dataEntryId: entity.dataEntryId, - } : null; const newRelationship = { clientId: uuid(), @@ -64,6 +59,7 @@ export const addRelationshipForNewSingleEventEpic = (action$: InputObservable, s }, to: { ...toEntity, + name: toEntity.name || getRelationshipNewTeiName(toEntity.dataEntryId, toEntity.itemId, state), type: payload.entityType, }, relationshipType: { ...payload.relationshipType }, @@ -87,7 +83,7 @@ export const addRelationshipForNewSingleEventEpic = (action$: InputObservable, s return batchActions([ recentlyAddedRelationship(newRelationship.clientId), - addRelationship(dataEntryId, itemId, newRelationship, newToEntity), + addRelationship(dataEntryId, itemId, newRelationship, toEntity), ], newEventNewRelationshipBatchActionTypes.ADD_RELATIONSHIP_BATCH); })); diff --git a/src/core_modules/capture-core/components/Pages/New/EnrollmentRegistrationEntryWrapper.component.js b/src/core_modules/capture-core/components/Pages/New/EnrollmentRegistrationEntryWrapper.component.js index e701d15e88..ac0b51288b 100644 --- a/src/core_modules/capture-core/components/Pages/New/EnrollmentRegistrationEntryWrapper.component.js +++ b/src/core_modules/capture-core/components/Pages/New/EnrollmentRegistrationEntryWrapper.component.js @@ -4,6 +4,7 @@ import { useDispatch } from 'react-redux'; import { cleanUpUid } from './NewPage.actions'; import { EnrollmentRegistrationEntry } from '../../DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.container'; import type { OwnProps } from '../../DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.types'; +import { RelatedStageModes } from '../../WidgetRelatedStages'; export const EnrollmentRegistrationEntryWrapper: ComponentType = (props) => { const dispatch = useDispatch(); @@ -11,5 +12,9 @@ export const EnrollmentRegistrationEntryWrapper: ComponentType = (prop dispatch(cleanUpUid()); }, [dispatch]); - return ; + const relatedStageModesOptions = { + [RelatedStageModes.LINK_EXISTING_RESPONSE]: { hidden: true }, + }; + + return ; }; diff --git a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js index 252a34e61a..fb4dbb4837 100644 --- a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js +++ b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js @@ -6,6 +6,7 @@ import { DATA_ENTRY_ID } from '../../registerTei.const'; import enrollmentClasses from './enrollment.module.css'; import { EnrollmentRegistrationEntry } from '../../../../../DataEntries'; import type { Props } from './dataEntryEnrollment.types'; +import { RelatedStageModes } from '../../../../../WidgetRelatedStages'; const NewEnrollmentRelationshipPlain = ({ @@ -20,6 +21,13 @@ const NewEnrollmentRelationshipPlain = ExistingUniqueValueDialogActions, }: Props) => { const fieldOptions = { theme, fieldLabelMediaBasedClass: enrollmentClasses.fieldLabelMediaBased }; + const relatedStageModesOptions = { + [RelatedStageModes.ENTER_DATA]: { + disabled: true, + disabledMessage: i18n.t('Enter details now is not available when creating a relationship'), + }, + [RelatedStageModes.LINK_EXISTING_RESPONSE]: { hidden: true }, + }; return ( ); }; diff --git a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegisterTei.component.js b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegisterTei.component.js index 2c159e7aba..49df1bf07a 100644 --- a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegisterTei.component.js +++ b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegisterTei.component.js @@ -10,6 +10,10 @@ import { DataEntryWidgetOutput } from '../../../DataEntryWidgetOutput/DataEntryW import { ResultsPageSizeContext } from '../../shared-contexts'; import type { Props } from './RegisterTei.types'; import { withErrorMessageHandler } from '../../../../HOC'; +import type { EnrollmentPayload } from + '../../../DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.types'; +import type { TeiPayload } from + '../../common/TEIRelationshipsWidget/RegisterTei/DataEntry/TrackedEntityInstance/dataEntryTrackedEntityInstance.types'; const getStyles = () => ({ container: { @@ -95,8 +99,8 @@ const RegisterTeiPlain = ({ ), [onLink]); - const handleSave = useCallback(() => { - onSave(itemId, dataEntryId); + const handleSave = useCallback((payload: EnrollmentPayload | TeiPayload) => { + onSave(itemId, dataEntryId, payload); }, [onSave, itemId, dataEntryId]); return ( diff --git a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegisterTei.types.js b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegisterTei.types.js index 759abe2e6f..2cce109427 100644 --- a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegisterTei.types.js +++ b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegisterTei.types.js @@ -1,4 +1,9 @@ // @flow +import type { EnrollmentPayload } from + '../../../DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.types'; +import type { TeiPayload } from + '../../common/TEIRelationshipsWidget/RegisterTei/DataEntry/TrackedEntityInstance/dataEntryTrackedEntityInstance.types'; + type PropsFromRedux = {| dataEntryId: string, itemId: string, @@ -12,7 +17,7 @@ export type OwnProps = {| onLink: (teiId: string, values: Object) => void, onCancel: () => void, onGetUnsavedAttributeValues?: ?Function, - onSave: (itemId: string, dataEntryId: string) => void, + onSave: (itemId: string, dataEntryId: string, payload: EnrollmentPayload | TeiPayload) => void, |}; export type Props = {|...PropsFromRedux, ...OwnProps, ...CssClasses |} diff --git a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/exposedHelpers/getRelationshipNewTei.js b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/exposedHelpers/getRelationshipNewTei.js index 7eeef73978..e3e29b02f4 100644 --- a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/exposedHelpers/getRelationshipNewTei.js +++ b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/exposedHelpers/getRelationshipNewTei.js @@ -1,16 +1,11 @@ // @flow -import uuid from 'd2-utilizr/src/uuid'; -import moment from 'moment'; -import { getFormattedStringFromMomentUsingEuropeanGlyphs } from 'capture-core-utils/date'; -import { capitalizeFirstLetter } from 'capture-core-utils/string/capitalizeFirstLetter'; import { getTrackerProgramThrowIfNotFound, getTrackedEntityTypeThrowIfNotFound, type RenderFoundation, } from '../../../../../metaData'; -import { convertFormToClient, convertClientToServer } from '../../../../../converters'; +import { convertFormToClient } from '../../../../../converters'; import { getDisplayName } from '../../../../../trackedEntityInstances/getDisplayName'; -import { convertDataEntryValuesToClientValues } from '../../../../DataEntry/common/convertDataEntryValuesToClientValues'; import { getDataEntryKey } from '../../../../DataEntry/common/getDataEntryKey'; function getTrackerProgramMetadata(programId: string) { @@ -41,99 +36,15 @@ function getClientValuesForFormData(formValues: Object, formFoundation: RenderFo return clientValues; } -function getServerValuesForMainValues( - values: Object, - meta: Object, - formFoundation: RenderFoundation, -) { - const clientValues = convertDataEntryValuesToClientValues( - values, - meta, - formFoundation, - ) || {}; - - // potientally run this through a server to client converter for enrollment, the same way as for event - const serverValues = Object - .keys(clientValues) - .reduce((acc, key) => { - const value = clientValues[key]; - const type = meta[key].type; - acc[key] = convertClientToServer(value, type); - return acc; - }, {}); - - return serverValues; -} - -function getPossibleTetFeatureTypeKey(serverValues: Object) { - return Object - .keys(serverValues) - .find(key => key.startsWith('FEATURETYPE_')); -} - -function buildGeometryProp(key: string, serverValues: Object) { - if (!serverValues[key]) { - return undefined; - } - const type = capitalizeFirstLetter(key.replace('FEATURETYPE_', '').toLocaleLowerCase()); - return { - type, - coordinates: serverValues[key], - }; -} - -export function getRelationshipNewTei(dataEntryId: string, itemId: string, state: ReduxState) { +export function getRelationshipNewTeiName(dataEntryId: string, itemId: string, state: ReduxState) { const dataEntryKey = getDataEntryKey(dataEntryId, itemId); const formValues = state.formsValues[dataEntryKey]; - const { programId, orgUnit } = state.newRelationshipRegisterTei; + const { programId } = state.newRelationshipRegisterTei; const tetId = state.newRelationship.selectedRelationshipType.to.trackedEntityTypeId; const { attributes: metaDataAttributes, form: formFoundation, tetName } = getMetadata(programId, tetId); const clientValuesForFormData = getClientValuesForFormData(formValues, formFoundation); const displayName = getDisplayName(clientValuesForFormData, metaDataAttributes, tetName); - const serverValuesForFormValues = formFoundation.convertValues(clientValuesForFormData, convertClientToServer); - const serverValuesForMainValues = getServerValuesForMainValues( - state.dataEntriesFieldsValue[dataEntryKey], - state.dataEntriesFieldsMeta[dataEntryKey], - formFoundation, - ); - - // $FlowFixMe - const attributes = Object.keys(serverValuesForFormValues) - .map(key => ({ - attribute: key, - value: serverValuesForFormValues[key], - })); - - const enrollment = programId ? { - program: programId, - status: 'ACTIVE', - orgUnit: orgUnit.id, - occurredAt: getFormattedStringFromMomentUsingEuropeanGlyphs(moment()), - attributes, - ...serverValuesForMainValues, - } : null; - - const tetFeatureTypeKey = getPossibleTetFeatureTypeKey(serverValuesForFormValues); - let geometry; - if (tetFeatureTypeKey) { - geometry = buildGeometryProp(tetFeatureTypeKey, serverValuesForFormValues); - delete serverValuesForFormValues[tetFeatureTypeKey]; - } - - const teiPayload = { - // $FlowFixMe - attributes: !enrollment ? attributes : undefined, - orgUnit: orgUnit.id, - trackedEntityType: tetId, - geometry, - enrollments: enrollment ? [enrollment] : [], - }; - - return { - data: teiPayload, - name: displayName, - id: uuid(), - }; + return displayName; } diff --git a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/index.js b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/index.js index 7a77e9ec0d..b615fc1939 100644 --- a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/index.js +++ b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/index.js @@ -10,4 +10,4 @@ export { export { loadSearchGroupDuplicatesForReviewEpic, } from '../../../PossibleDuplicatesDialog/possibleDuplicatesDialog.epics'; -export { getRelationshipNewTei } from './exposedHelpers/getRelationshipNewTei'; +export { getRelationshipNewTeiName } from './exposedHelpers/getRelationshipNewTei'; diff --git a/src/core_modules/capture-core/components/Pages/NewRelationship/TeiRelationship/TeiRelationship.component.js b/src/core_modules/capture-core/components/Pages/NewRelationship/TeiRelationship/TeiRelationship.component.js index 863327b37f..87869ce23a 100644 --- a/src/core_modules/capture-core/components/Pages/NewRelationship/TeiRelationship/TeiRelationship.component.js +++ b/src/core_modules/capture-core/components/Pages/NewRelationship/TeiRelationship/TeiRelationship.component.js @@ -13,7 +13,10 @@ import type { TrackedEntityType } from '../../../../metaData'; import { findModes } from '../findModes'; import { getDisplayName } from '../../../../trackedEntityInstances/getDisplayName'; import { ResultsPageSizeContext } from '../../shared-contexts'; - +import type { EnrollmentPayload } from + '../../../DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.types'; +import type { TeiPayload } from + '../../common/TEIRelationshipsWidget/RegisterTei/DataEntry/TrackedEntityInstance/dataEntryTrackedEntityInstance.types'; type Props = { findMode?: ?$Values, @@ -74,10 +77,16 @@ class TeiRelationshipPlain extends React.Component { }); } - handleAddRelationshipWithNewTei = (itemId: string, dataEntryId: string) => { + handleAddRelationshipWithNewTei = ( + itemId: string, + dataEntryId: string, + payload: EnrollmentPayload | TeiPayload, + ) => { this.props.onAddRelationship({ itemId, dataEntryId, + data: payload, + id: payload?.trackedEntity, }); } diff --git a/src/core_modules/capture-core/components/Pages/ViewEvent/Relationship/ViewEventRelationships.epics.js b/src/core_modules/capture-core/components/Pages/ViewEvent/Relationship/ViewEventRelationships.epics.js index d1d27a8cc1..c662eae579 100644 --- a/src/core_modules/capture-core/components/Pages/ViewEvent/Relationship/ViewEventRelationships.epics.js +++ b/src/core_modules/capture-core/components/Pages/ViewEvent/Relationship/ViewEventRelationships.epics.js @@ -27,7 +27,7 @@ import { convertClientRelationshipToServer, getRelationshipsForEvent, } from '../../../../relationships'; -import { getRelationshipNewTei } from '../../NewRelationship/RegisterTei'; +import { getRelationshipNewTeiName } from '../../NewRelationship/RegisterTei'; const relationshipKey = 'viewEvent'; @@ -78,9 +78,7 @@ export const addRelationshipForViewEventEpic = (action$: InputObservable, store: const eventId = state.viewEventPage.eventId; const existingRelationships = state.dataEntriesRelationships[relationshipKey] || []; const payload = action.payload; - const entity = payload.entity; - - const toEntity = entity.id ? entity : getRelationshipNewTei(entity.dataEntryId, entity.itemId, state); + const toEntity = payload.entity; const relationshipClientId = uuid(); const clientRelationship = { @@ -92,6 +90,7 @@ export const addRelationshipForViewEventEpic = (action$: InputObservable, store: }, to: { ...toEntity, + name: toEntity.name || getRelationshipNewTeiName(toEntity.dataEntryId, toEntity.itemId, state), type: payload.entityType, }, relationshipType: { ...payload.relationshipType }, diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js index cea2f79f8f..406eacdc5f 100644 --- a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js +++ b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js @@ -6,6 +6,7 @@ import { DATA_ENTRY_ID } from '../../registerTei.const'; import enrollmentClasses from './enrollment.module.css'; import { EnrollmentRegistrationEntry } from '../../../../../../DataEntries'; import type { Props } from './dataEntryEnrollment.types'; +import { RelatedStageModes } from '../../../../../../WidgetRelatedStages'; const NewEnrollmentRelationshipPlain = ({ @@ -21,6 +22,13 @@ const NewEnrollmentRelationshipPlain = ExistingUniqueValueDialogActions, }: Props) => { const fieldOptions = { theme, fieldLabelMediaBasedClass: enrollmentClasses.fieldLabelMediaBased }; + const relatedStageModesOptions = { + [RelatedStageModes.ENTER_DATA]: { + disabled: true, + disabledMessage: i18n.t('Enter details now is not available when creating a relationship'), + }, + [RelatedStageModes.LINK_EXISTING_RESPONSE]: { hidden: true }, + }; return ( ); }; diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/exposedHelpers/getRelationshipNewTei.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/exposedHelpers/getRelationshipNewTei.js index d5c862fcd6..9a264ea2a5 100644 --- a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/exposedHelpers/getRelationshipNewTei.js +++ b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/exposedHelpers/getRelationshipNewTei.js @@ -1,18 +1,11 @@ // @flow -import uuid from 'd2-utilizr/src/uuid'; -import moment from 'moment'; -import { getFormattedStringFromMomentUsingEuropeanGlyphs } from 'capture-core-utils/date'; -import { capitalizeFirstLetter } from 'capture-core-utils/string/capitalizeFirstLetter'; import { getTrackerProgramThrowIfNotFound, getTrackedEntityTypeThrowIfNotFound, type RenderFoundation, } from '../../../../../../metaData'; -import { convertFormToClient, convertClientToServer } from '../../../../../../converters'; +import { convertFormToClient } from '../../../../../../converters'; import { getDisplayName } from '../../../../../../trackedEntityInstances/getDisplayName'; -import { - convertDataEntryValuesToClientValues, -} from '../../../../../DataEntry/common/convertDataEntryValuesToClientValues'; import { getDataEntryKey } from '../../../../../DataEntry/common/getDataEntryKey'; function getTrackerProgramMetadata(programId: string) { @@ -43,99 +36,16 @@ function getClientValuesForFormData(formValues: Object, formFoundation: RenderFo return clientValues; } -function getServerValuesForMainValues( - values: Object, - meta: Object, - formFoundation: RenderFoundation, -) { - const clientValues = convertDataEntryValuesToClientValues( - values, - meta, - formFoundation, - ) || {}; - - // potientally run this through a server to client converter for enrollment, the same way as for event - const serverValues = Object - .keys(clientValues) - .reduce((acc, key) => { - const value = clientValues[key]; - const type = meta[key].type; - acc[key] = convertClientToServer(value, type); - return acc; - }, {}); - - return serverValues; -} - -function getPossibleTetFeatureTypeKey(serverValues: Object) { - return Object - .keys(serverValues) - .find(key => key.startsWith('FEATURETYPE_')); -} - -function buildGeometryProp(key: string, serverValues: Object) { - if (!serverValues[key]) { - return undefined; - } - const type = capitalizeFirstLetter(key.replace('FEATURETYPE_', '').toLocaleLowerCase()); - return { - type, - coordinates: serverValues[key], - }; -} - -export function getRelationshipNewTei(dataEntryId: string, itemId: string, state: ReduxState) { +export function getRelationshipNewTeiName(dataEntryId: string, itemId: string, state: ReduxState) { const dataEntryKey = getDataEntryKey(dataEntryId, itemId); const formValues = state.formsValues[dataEntryKey]; - const { programId, orgUnit } = state.newRelationshipRegisterTei; + const { programId } = state.newRelationshipRegisterTei; const tetId = state.newRelationship.selectedRelationshipType.to.trackedEntityTypeId; const { attributes: metaDataAttributes, form: formFoundation, tetName } = getMetadata(programId, tetId); const clientValuesForFormData = getClientValuesForFormData(formValues, formFoundation); const displayName = getDisplayName(clientValuesForFormData, metaDataAttributes, tetName); - const serverValuesForFormValues = formFoundation.convertValues(clientValuesForFormData, convertClientToServer); - const serverValuesForMainValues = getServerValuesForMainValues( - state.dataEntriesFieldsValue[dataEntryKey], - state.dataEntriesFieldsMeta[dataEntryKey], - formFoundation, - ); - - // $FlowFixMe - const attributes = Object.keys(serverValuesForFormValues) - .map(key => ({ - attribute: key, - value: serverValuesForFormValues[key], - })); - - const enrollment = programId ? { - program: programId, - status: 'ACTIVE', - orgUnit: orgUnit.id, - occurredAt: getFormattedStringFromMomentUsingEuropeanGlyphs(moment()), - attributes, - ...serverValuesForMainValues, - } : null; - - const tetFeatureTypeKey = getPossibleTetFeatureTypeKey(serverValuesForFormValues); - let geometry; - if (tetFeatureTypeKey) { - geometry = buildGeometryProp(tetFeatureTypeKey, serverValuesForFormValues); - delete serverValuesForFormValues[tetFeatureTypeKey]; - } - - const teiPayload = { - // $FlowFixMe - attributes: !enrollment ? attributes : undefined, - orgUnit: orgUnit.id, - trackedEntityType: tetId, - geometry, - enrollments: enrollment ? [enrollment] : [], - }; - - return { - data: teiPayload, - name: displayName, - id: uuid(), - }; + // $FlowFixM + return displayName; } diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/index.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/index.js index dea1f66c95..b8aa107828 100644 --- a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/index.js +++ b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/index.js @@ -9,4 +9,4 @@ export { export { loadSearchGroupDuplicatesForReviewEpic, } from '../../../../PossibleDuplicatesDialog/possibleDuplicatesDialog.epics'; -export { getRelationshipNewTei } from './exposedHelpers/getRelationshipNewTei'; +export { getRelationshipNewTeiName } from './exposedHelpers/getRelationshipNewTei'; diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.component.js b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.component.js index 104cbcf420..663348da1b 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.component.js +++ b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.component.js @@ -52,7 +52,6 @@ const ValidatedPlain = ({ enrollmentId={enrollmentId} programId={programId} programStageId={stage?.id} - enableLinkExistingEvent /> ({ }, }); +const Schedule = ({ + actionTypesOptions, + linkableEvents, + selectedAction, + updateSelectedAction, + programStage, + canAddNewEventToStage, +}) => { + const { hidden, disabled, disabledMessage } = + (actionTypesOptions && actionTypesOptions[RelatedStagesActionTypes.SCHEDULE_IN_ORG]) || {}; + if (hidden) { + return null; + } + + const tooltipEnabled = disabled || !canAddNewEventToStage; + let tooltipContent = ''; + if (disabled) { + tooltipContent = disabledMessage; + } else if (!linkableEvents.length) { + tooltipContent = i18n.t('{{ linkableStageLabel }} is not repeatable', { + linkableStageLabel: programStage.stageForm.name, + interpolation: { escapeValue: false }, + }); + } + + return ( + + updateSelectedAction(e.value)} + value={RelatedStagesActionTypes.SCHEDULE_IN_ORG} + /> + + ); +}; + +const EnterData = ({ + actionTypesOptions, + linkableEvents, + selectedAction, + updateSelectedAction, + programStage, + canAddNewEventToStage, +}) => { + const { hidden, disabled, disabledMessage } = + (actionTypesOptions && actionTypesOptions[RelatedStagesActionTypes.ENTER_DATA]) || {}; + if (hidden) { + return null; + } + + const tooltipEnabled = disabled || !canAddNewEventToStage; + let tooltipContent = ''; + if (disabled) { + tooltipContent = disabledMessage; + } else if (!linkableEvents.length) { + tooltipContent = i18n.t('{{ linkableStageLabel }} is not repeatable', { + linkableStageLabel: programStage.stageForm.name, + interpolation: { escapeValue: false }, + }); + } + + return ( + + updateSelectedAction(e.value)} + value={RelatedStagesActionTypes.ENTER_DATA} + /> + + ); +}; + +const LinkExistingResponse = ({ + actionTypesOptions, + linkableEvents, + selectedAction, + updateSelectedAction, + programStage, +}) => { + const { hidden, disabled, disabledMessage } = + (actionTypesOptions && actionTypesOptions[RelatedStagesActionTypes.LINK_EXISTING_RESPONSE]) || {}; + if (hidden) { + return null; + } + + const tooltipEnabled = disabled || !linkableEvents.length; + let tooltipContent = ''; + if (disabled) { + tooltipContent = disabledMessage; + } else if (!linkableEvents.length) { + tooltipContent = i18n.t('{{ linkableStageLabel }} has no linkable events', { + linkableStageLabel: programStage.stageForm.name, + interpolation: { escapeValue: false }, + }); + } + + return ( + + updateSelectedAction(e.value)} + value={RelatedStagesActionTypes.LINK_EXISTING_RESPONSE} + /> + + ); +}; + export const RelatedStagesActionsPlain = ({ classes, type, @@ -52,7 +183,7 @@ export const RelatedStagesActionsPlain = ({ constraint, errorMessages, saveAttempted, - enableLinkExistingEvent, + actionTypesOptions, }: Props) => { const { programStage } = useProgramStageInfo(constraint?.programStage?.id); @@ -78,62 +209,29 @@ export const RelatedStagesActionsPlain = ({
{type === relatedStageStatus.LINKABLE && ( <> - - updateSelectedAction(e.value)} - value={RelatedStagesActionTypes.SCHEDULE_IN_ORG} - /> - - - updateSelectedAction(e.value)} - value={RelatedStagesActionTypes.ENTER_DATA} - /> - - {enableLinkExistingEvent && ( - - updateSelectedAction(e.value)} - value={RelatedStagesActionTypes.LINK_EXISTING_RESPONSE} - /> - - )} + + + )} diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.types.js b/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.types.js index dee2a54806..050c3350cb 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.types.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.types.js @@ -1,5 +1,6 @@ // @flow import type { RelatedStageDataValueStates } from '../WidgetRelatedStages.types'; +import { RelatedStageModes } from '../index'; export type Constraint = {| programStage: { @@ -36,6 +37,12 @@ export type Props = {| constraint: ?Constraint, addErrorMessage: (ErrorMessagesForRelatedStages) => void, setRelatedStagesDataValues: (() => Object) => void, - enableLinkExistingEvent?: boolean, + actionTypesOptions?: { + [key: $Keys]: { + hidden?: boolean, + disabled?: boolean, + disabledMessage?: string + }, + }, ...CssClasses |} diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js b/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js index 8995ddaf82..bb00b94c33 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js @@ -19,7 +19,13 @@ export type Props = {| programId: string, enrollmentId?: string, programStageId: string, - enableLinkExistingEvent?: boolean, + actionTypesOptions?: { + [key: $Keys]: { + hidden?: boolean, + disabled?: boolean, + disabledMessage?: string + }, + }, |} export type RelatedStageDataValueStates = {| linkMode: ?$Keys, diff --git a/src/core_modules/capture-core/components/WidgetsRelationship/WidgetTrackedEntityRelationship/NewTrackedEntityRelationship/hooks/useAddRelationship.js b/src/core_modules/capture-core/components/WidgetsRelationship/WidgetTrackedEntityRelationship/NewTrackedEntityRelationship/hooks/useAddRelationship.js index b57a46e4f0..e0e2055d29 100644 --- a/src/core_modules/capture-core/components/WidgetsRelationship/WidgetTrackedEntityRelationship/NewTrackedEntityRelationship/hooks/useAddRelationship.js +++ b/src/core_modules/capture-core/components/WidgetsRelationship/WidgetTrackedEntityRelationship/NewTrackedEntityRelationship/hooks/useAddRelationship.js @@ -69,13 +69,20 @@ export const useAddRelationship = ({ teiId, onMutate, onSuccess }: Props) => { }); }, onSuccess: async (apiResponse, requestData) => { - const apiRelationshipId = apiResponse.bundleReport.typeReportMap.RELATIONSHIP.objectReports[0].uid; + const apiRelationshipIds = apiResponse.bundleReport.typeReportMap.RELATIONSHIP.objectReports.reduce( + (acc, report) => [...acc, report.uid], + [], + ); const currentRelationships = queryClient.getQueryData([ReactQueryAppNamespace, 'relationships', teiId]); const apiRelationships = handleAPIResponse(REQUESTED_ENTITIES.relationships, currentRelationships); if (apiRelationships.length === 0) return; const newRelationships = apiRelationships.map((relationship) => { - if (relationship.relationship === apiRelationshipId) { + if ( + apiRelationshipIds.find( + apiRelationshipId => apiRelationshipId === relationship.relationship, + ) + ) { return { ...relationship, pendingApiResponse: false, From 2a27f5773cd7887edee66cbcb2b96154adcfb5fa Mon Sep 17 00:00:00 2001 From: Simona Domnisoru Date: Mon, 9 Dec 2024 16:49:10 +0100 Subject: [PATCH 05/12] chore: typo --- .../RegistrationDataEntry/helpers/deriveRelatedStageEvent.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveRelatedStageEvent.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveRelatedStageEvent.js index d5210a555b..972cfe0486 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveRelatedStageEvent.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveRelatedStageEvent.js @@ -15,7 +15,7 @@ export const deriveRelatedStageEvent = ({ relatedStageRef?: { current: ?RelatedStageRefPayload}, firstStageMetaData: ?{ stage: ?ProgramStage}, programId: string, - teiId?: ?string; + teiId?: ?string, }) => { if (relatedStageRef?.current && relatedStageRef.current.eventHasLinkableStageRelationship()) { const isValid = relatedStageRef.current.formIsValidOnSave(); @@ -50,7 +50,6 @@ export const deriveRelatedStageEvent = ({ linkMode, relatedStageDataValues, clientRequestEvent, - relatedStageType: selectedRelationshipType, programId, currentProgramStageId, From 9ecf999307c65b34ca6a7941b7bca3e31d621532 Mon Sep 17 00:00:00 2001 From: Simona Domnisoru Date: Wed, 11 Dec 2024 12:54:21 +0100 Subject: [PATCH 06/12] chore: fix PR comments --- .../Pages/NewRelationship/RegisterTei/RegisterTei.component.js | 3 +-- .../RegisterTei/DataEntry/TrackedEntityInstance/index.js | 1 + .../RelatedStagesActions/RelatedStagesActions.component.js | 2 +- .../WidgetRelatedStages/hooks/useRelatedStageEvents.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegisterTei.component.js b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegisterTei.component.js index 49df1bf07a..fcbdf474a4 100644 --- a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegisterTei.component.js +++ b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegisterTei.component.js @@ -12,8 +12,7 @@ import type { Props } from './RegisterTei.types'; import { withErrorMessageHandler } from '../../../../HOC'; import type { EnrollmentPayload } from '../../../DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.types'; -import type { TeiPayload } from - '../../common/TEIRelationshipsWidget/RegisterTei/DataEntry/TrackedEntityInstance/dataEntryTrackedEntityInstance.types'; +import type { TeiPayload } from '../../common/TEIRelationshipsWidget/RegisterTei/DataEntry/TrackedEntityInstance'; const getStyles = () => ({ container: { diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/TrackedEntityInstance/index.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/TrackedEntityInstance/index.js index 5bb8975389..d60b166b08 100644 --- a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/TrackedEntityInstance/index.js +++ b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/TrackedEntityInstance/index.js @@ -1,2 +1,3 @@ // @flow export { DataEntryTrackedEntityInstance } from './DataEntryTrackedEntityInstance'; +export type { TeiPayload } from './dataEntryTrackedEntityInstance.types'; diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js b/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js index 7e22c2407a..519cb05cea 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js @@ -171,7 +171,7 @@ const LinkExistingResponse = ({ ); }; -export const RelatedStagesActionsPlain = ({ +const RelatedStagesActionsPlain = ({ classes, type, relationshipName, diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/hooks/useRelatedStageEvents.js b/src/core_modules/capture-core/components/WidgetRelatedStages/hooks/useRelatedStageEvents.js index bc9d59d53d..058ab02f41 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/hooks/useRelatedStageEvents.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/hooks/useRelatedStageEvents.js @@ -7,7 +7,7 @@ import { handleAPIResponse, REQUESTED_ENTITIES } from '../../../utils/api'; type Props = { stageId: ?string, - enrollmentId?: string, + enrollmentId: ?string, scheduledLabel: string, occurredLabel: string, relationshipTypeId: ?string, From 28e26b876d90cae198387b5a775fc9d9ff2fda2c Mon Sep 17 00:00:00 2001 From: Simona Domnisoru Date: Tue, 17 Dec 2024 09:22:45 +0100 Subject: [PATCH 07/12] chore: correct the variable name to match its format --- .../hooks/useBuildEnrollmentPayload.js | 2 +- .../getConvertedRelatedStageEvent.js | 12 ++++++------ .../getConvertedRelatedStageEvent.types.js | 2 +- .../helpers/deriveRelatedStageEvent.js | 8 ++++---- .../Validated/Validated.container.js | 8 ++++---- .../Validated/useBuildNewEventPayload.js | 16 ++++++++-------- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js index 808161d25e..04d449f302 100644 --- a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js @@ -134,7 +134,7 @@ export const useBuildEnrollmentPayload = ({ }); const { formHasError, linkedEvent: relatedStageLinkedEvent, relationship, linkMode } = deriveRelatedStageEvent({ - clientRequestEvent: firstStageDuringRegistrationEvent, + serverRequestEvent: firstStageDuringRegistrationEvent, relatedStageRef, firstStageMetaData, programId, diff --git a/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js b/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js index e2299cf418..5603b4d6ff 100644 --- a/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js +++ b/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js @@ -17,7 +17,7 @@ const getEventDetailsByLinkMode = ({ programId, teiId, enrollmentId, - clientRequestEvent, + serverRequestEvent, }): { linkedEvent: ?LinkedRequestEvent, linkedEventId: ?string, @@ -68,7 +68,7 @@ const getEventDetailsByLinkMode = ({ return ({ linkedEvent: { ...baseEventDetails, - scheduledAt: clientRequestEvent.scheduledAt, + scheduledAt: serverRequestEvent.scheduledAt, orgUnit: convertFn(linkedEventOrgUnit, dataElementTypes.ORGANISATION_UNIT), }, linkedEventId: baseEventDetails.event, @@ -95,7 +95,7 @@ export const getConvertedRelatedStageEvent = ({ programId, teiId, currentProgramStageId, - clientRequestEvent, + serverRequestEvent, enrollmentId, relatedStageType, }: ConvertedRelatedStageEventProps) => { @@ -109,19 +109,19 @@ export const getConvertedRelatedStageEvent = ({ programId, teiId, enrollmentId, - clientRequestEvent, + serverRequestEvent, }); const relationship = linkedEventId && { relationshipType: relatedStageType.id, from: { event: { - event: requestEventIsFromConstraint ? clientRequestEvent.event : linkedEventId, + event: requestEventIsFromConstraint ? serverRequestEvent.event : linkedEventId, }, }, to: { event: { - event: requestEventIsFromConstraint ? linkedEventId : clientRequestEvent.event, + event: requestEventIsFromConstraint ? linkedEventId : serverRequestEvent.event, }, }, }; diff --git a/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.types.js b/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.types.js index 4c0e720f7c..7a40b70c2e 100644 --- a/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.types.js +++ b/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.types.js @@ -35,6 +35,6 @@ export type ConvertedRelatedStageEventProps = {| currentProgramStageId: string, enrollmentId?: string, relatedStageType: RelatedStageRelationshipType, - clientRequestEvent: RequestEvent, + serverRequestEvent: RequestEvent, |} diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveRelatedStageEvent.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveRelatedStageEvent.js index 972cfe0486..631e690645 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveRelatedStageEvent.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveRelatedStageEvent.js @@ -5,13 +5,13 @@ import type { RequestEvent } from '../../../../DataEntries'; import type { RelatedStageRefPayload } from '../../../../WidgetRelatedStages'; export const deriveRelatedStageEvent = ({ - clientRequestEvent, + serverRequestEvent, relatedStageRef, firstStageMetaData, programId, teiId, }: { - clientRequestEvent: ?RequestEvent, + serverRequestEvent: ?RequestEvent, relatedStageRef?: { current: ?RelatedStageRefPayload}, firstStageMetaData: ?{ stage: ?ProgramStage}, programId: string, @@ -24,7 +24,7 @@ export const deriveRelatedStageEvent = ({ !isValid || !relatedStageRef.current?.getLinkedStageValues || !currentProgramStageId || - !clientRequestEvent + !serverRequestEvent ) { return { formHasError: true, @@ -49,7 +49,7 @@ export const deriveRelatedStageEvent = ({ const { linkedEvent, relationship } = getConvertedRelatedStageEvent({ linkMode, relatedStageDataValues, - clientRequestEvent, + serverRequestEvent, relatedStageType: selectedRelationshipType, programId, currentProgramStageId, diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.container.js b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.container.js index 5f29998ba1..a376001e37 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.container.js +++ b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/Validated.container.js @@ -84,7 +84,7 @@ export const Validated = ({ // Creating a promise to be able to stop navigation if related stages has an error window.scrollTo(0, 0); const { - clientRequestEvent, + serverRequestEvent, linkedEvent, relationship, linkMode, @@ -100,7 +100,7 @@ export const Validated = ({ } const serverData = createServerData({ - clientRequestEvent, + serverRequestEvent, linkedEvent, relationship, enrollment, @@ -108,7 +108,7 @@ export const Validated = ({ dispatch(batchActions([ requestSaveEvent({ - requestEvent: clientRequestEvent, + requestEvent: serverRequestEvent, linkedEvent, relationship, serverData, @@ -120,7 +120,7 @@ export const Validated = ({ // stores meta in redux to be used when navigating after save setSaveEnrollmentEventInProgress({ - requestEventId: clientRequestEvent?.event, + requestEventId: serverRequestEvent?.event, linkedEventId: linkedEvent?.event, linkedOrgUnitId: linkedEvent?.orgUnit, linkMode, diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/useBuildNewEventPayload.js b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/useBuildNewEventPayload.js index 791737876c..ab8c0f3683 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/useBuildNewEventPayload.js +++ b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/useBuildNewEventPayload.js @@ -22,18 +22,18 @@ type Props = { }; export const createServerData = ({ - clientRequestEvent, + serverRequestEvent, linkedEvent, relationship, enrollment, }: { - clientRequestEvent: RequestEvent, + serverRequestEvent: RequestEvent, linkedEvent: ?LinkedRequestEvent, relationship: ?Object, enrollment: ?Object, }) => { const relationships = relationship ? [relationship] : undefined; - const newEvents = linkedEvent ? [clientRequestEvent, linkedEvent] : [clientRequestEvent]; + const newEvents = linkedEvent ? [serverRequestEvent, linkedEvent] : [serverRequestEvent]; if (enrollment) { const updatedEnrollment = { ...enrollment, events: [...(enrollment.events || []), ...newEvents] }; @@ -67,7 +67,7 @@ export const useBuildNewEventPayload = ({ const notes = useSelector(({ dataEntriesNotes }) => dataEntriesNotes[dataEntryKey]); const { fromClientDate } = useTimeZoneConversion(); - const buildRelatedStageEventPayload = (clientRequestEvent, saveType: ?$Values, relatedStageRef) => { + const buildRelatedStageEventPayload = (serverRequestEvent, saveType: ?$Values, relatedStageRef) => { if ( relatedStageRef?.current && relatedStageRef.current.eventHasLinkableStageRelationship() @@ -97,7 +97,7 @@ export const useBuildNewEventPayload = ({ const { linkedEvent, relationship } = getConvertedRelatedStageEvent({ linkMode, relatedStageDataValues, - clientRequestEvent, + serverRequestEvent, relatedStageType: selectedRelationshipType, programId, currentProgramStageId: formFoundation.id, @@ -134,7 +134,7 @@ export const useBuildNewEventPayload = ({ ); const notesValues = notes ? notes.map(note => ({ value: note.value })) : []; - const clientRequestEvent = getAddEventEnrollmentServerData({ + const serverRequestEvent = getAddEventEnrollmentServerData({ formFoundation, formClientValues, eventId: requestEventId, @@ -154,11 +154,11 @@ export const useBuildNewEventPayload = ({ linkedEvent, relationship, linkMode, - } = buildRelatedStageEventPayload(clientRequestEvent, saveType, relatedStageRef); + } = buildRelatedStageEventPayload(serverRequestEvent, saveType, relatedStageRef); return { formHasError, - clientRequestEvent, + serverRequestEvent, linkedEvent, relationship, linkMode, From d137e8e24e88c512dd0989a545548e2f463806a7 Mon Sep 17 00:00:00 2001 From: Simona Domnisoru Date: Tue, 17 Dec 2024 09:32:27 +0100 Subject: [PATCH 08/12] chore: move helpers files to DataEntries/EnrollmentRegistrationEntry --- .../helpers/deriveAutoGenerateEvents.js | 8 ++++---- .../helpers/deriveFirstStageDuringRegistrationEvent.js | 10 +++++----- .../helpers/deriveRelatedStageEvent.js | 8 ++++---- .../EnrollmentRegistrationEntry/helpers/index.js | 5 +++++ .../helpers/standardGeoJson.js | 0 .../hooks/useBuildEnrollmentPayload.js | 2 +- .../Pages/New/RegistrationDataEntry/helpers/index.js | 4 ---- 7 files changed, 19 insertions(+), 18 deletions(-) rename src/core_modules/capture-core/components/{Pages/New/RegistrationDataEntry => DataEntries/EnrollmentRegistrationEntry}/helpers/deriveAutoGenerateEvents.js (93%) rename src/core_modules/capture-core/components/{Pages/New/RegistrationDataEntry => DataEntries/EnrollmentRegistrationEntry}/helpers/deriveFirstStageDuringRegistrationEvent.js (86%) rename src/core_modules/capture-core/components/{Pages/New/RegistrationDataEntry => DataEntries/EnrollmentRegistrationEntry}/helpers/deriveRelatedStageEvent.js (87%) create mode 100644 src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/index.js rename src/core_modules/capture-core/components/{Pages/New/RegistrationDataEntry => DataEntries/EnrollmentRegistrationEntry}/helpers/standardGeoJson.js (100%) diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveAutoGenerateEvents.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/deriveAutoGenerateEvents.js similarity index 93% rename from src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveAutoGenerateEvents.js rename to src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/deriveAutoGenerateEvents.js index e4e67bad96..c4eb7ddc85 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveAutoGenerateEvents.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/deriveAutoGenerateEvents.js @@ -1,9 +1,9 @@ // @flow import moment from 'moment'; -import { dataElementTypes, ProgramStage } from '../../../../../metaData'; -import { convertClientToServer } from '../../../../../converters'; -import { convertCategoryOptionsToServer } from '../../../../../converters/clientToServer'; -import type { RequestEvent, LinkedRequestEvent } from '../../../../DataEntries'; +import { dataElementTypes, ProgramStage } from '../../../../metaData'; +import { convertClientToServer } from '../../../../converters'; +import { convertCategoryOptionsToServer } from '../../../../converters/clientToServer'; +import type { RequestEvent, LinkedRequestEvent } from '../../../DataEntries'; const ignoreAutoGenerateIfApplicable = (stage, stageToSkip) => !stageToSkip || stageToSkip.programStage !== stage.id; diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveFirstStageDuringRegistrationEvent.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/deriveFirstStageDuringRegistrationEvent.js similarity index 86% rename from src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveFirstStageDuringRegistrationEvent.js rename to src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/deriveFirstStageDuringRegistrationEvent.js index 2e59a8e195..38a5697e61 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveFirstStageDuringRegistrationEvent.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/deriveFirstStageDuringRegistrationEvent.js @@ -1,10 +1,10 @@ // @flow import { pipe } from 'capture-core-utils'; -import { generateUID } from '../../../../../utils/uid/generateUID'; -import { dataElementTypes, ProgramStage } from '../../../../../metaData'; -import { convertFormToClient, convertClientToServer } from '../../../../../converters'; -import { convertCategoryOptionsToServer } from '../../../../../converters/clientToServer'; -import { convertStatusOut } from '../../../../DataEntries'; +import { generateUID } from '../../../../utils/uid/generateUID'; +import { dataElementTypes, ProgramStage } from '../../../../metaData'; +import { convertFormToClient, convertClientToServer } from '../../../../converters'; +import { convertCategoryOptionsToServer } from '../../../../converters/clientToServer'; +import { convertStatusOut } from '../../../DataEntries'; import { standardGeoJson } from './standardGeoJson'; const convertFn = pipe(convertFormToClient, convertClientToServer); diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveRelatedStageEvent.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/deriveRelatedStageEvent.js similarity index 87% rename from src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveRelatedStageEvent.js rename to src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/deriveRelatedStageEvent.js index 631e690645..08d779bd3a 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/deriveRelatedStageEvent.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/deriveRelatedStageEvent.js @@ -1,8 +1,8 @@ // @flow -import { ProgramStage } from '../../../../../metaData'; -import { getConvertedRelatedStageEvent } from '../../../../DataEntries'; -import type { RequestEvent } from '../../../../DataEntries'; -import type { RelatedStageRefPayload } from '../../../../WidgetRelatedStages'; +import { ProgramStage } from '../../../../metaData'; +import { getConvertedRelatedStageEvent } from '../../../DataEntries'; +import type { RequestEvent } from '../../../DataEntries'; +import type { RelatedStageRefPayload } from '../../../WidgetRelatedStages'; export const deriveRelatedStageEvent = ({ serverRequestEvent, diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/index.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/index.js new file mode 100644 index 0000000000..b0c3744c1f --- /dev/null +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/index.js @@ -0,0 +1,5 @@ +// @flow +export { deriveFirstStageDuringRegistrationEvent } from './deriveFirstStageDuringRegistrationEvent'; +export { deriveRelatedStageEvent } from './deriveRelatedStageEvent'; +export { deriveAutoGenerateEvents } from './deriveAutoGenerateEvents'; +export { standardGeoJson } from './standardGeoJson'; diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/standardGeoJson.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/standardGeoJson.js similarity index 100% rename from src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/standardGeoJson.js rename to src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/standardGeoJson.js diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js index 04d449f302..20fc060c42 100644 --- a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js @@ -25,7 +25,7 @@ import { deriveAutoGenerateEvents, deriveFirstStageDuringRegistrationEvent, deriveRelatedStageEvent, -} from '../../../Pages/New/RegistrationDataEntry/helpers'; +} from '../helpers'; import type { EnrollmentPayload } from '../EnrollmentRegistrationEntry.types'; import { geometryType, getPossibleTetFeatureTypeKey, buildGeometryProp } from '../../common/TEIAndEnrollment/geometry'; import { RelatedStageModes } from '../../../WidgetRelatedStages'; diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/index.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/index.js index 8dddd26bf7..a82f1974d9 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/index.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/index.js @@ -1,6 +1,2 @@ // @flow -export { deriveFirstStageDuringRegistrationEvent } from './deriveFirstStageDuringRegistrationEvent'; -export { deriveRelatedStageEvent } from './deriveRelatedStageEvent'; -export { deriveAutoGenerateEvents } from './deriveAutoGenerateEvents'; export { getPageToRedirectTo, PAGES } from './getPageToRedirectTo'; -export { standardGeoJson } from './standardGeoJson'; From 0dc2f01bbfcd6db9a2245ab902819fd9bcf45b4c Mon Sep 17 00:00:00 2001 From: Simona Domnisoru Date: Tue, 17 Dec 2024 09:49:21 +0100 Subject: [PATCH 09/12] chore: use action naming throughout the code --- ...llmentWithFirstStageDataEntry.container.js | 4 +- ...EnrollmentWithFirstStageDataEntry.types.js | 6 +- .../EnrollmentRegistrationEntry.types.js | 6 +- .../hooks/useBuildEnrollmentPayload.js | 4 +- .../withAskToCompleteEnrollment.js | 4 +- .../getConvertedRelatedStageEvent.js | 8 +-- .../getConvertedRelatedStageEvent.types.js | 4 +- .../EnrollmentAddEventPage.epics.js | 4 +- ...EnrollmentAddEventPageDefault.container.js | 4 +- ...lmentRegistrationEntryWrapper.component.js | 8 +-- .../DataEntryEnrollment.component.js | 10 ++-- .../DataEntryEnrollment.component.js | 10 ++-- .../Validated/validated.actions.js | 6 +- .../RelatedStagesActions.component.js | 60 +++++++++---------- .../RelatedStagesActions.types.js | 6 +- .../WidgetRelatedStages.types.js | 10 ++-- .../WidgetRelatedStages/constants.js | 8 +-- .../components/WidgetRelatedStages/index.js | 2 +- .../ValidationFunctions.js | 8 +-- .../relatedStageEventIsValid.types.js | 4 +- 20 files changed, 88 insertions(+), 88 deletions(-) diff --git a/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.container.js b/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.container.js index bcb91759f0..420c663669 100644 --- a/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.container.js +++ b/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.container.js @@ -10,7 +10,7 @@ const getSectionId = sectionId => (sectionId === Section.MAIN_SECTION_ID ? `${Section.MAIN_SECTION_ID}-stage` : sectionId); export const EnrollmentWithFirstStageDataEntry = (props: Props) => { - const { firstStageMetaData, relatedStageRef, relatedStageModesOptions, ...passOnProps } = props; + const { firstStageMetaData, relatedStageRef, relatedStageActionsOptions, ...passOnProps } = props; const { stage: { stageForm: firstStageFormFoundation, name: stageName }, } = firstStageMetaData; @@ -30,7 +30,7 @@ export const EnrollmentWithFirstStageDataEntry = (props: Props) => { ref={relatedStageRef} programId={passOnProps.programId} programStageId={firstStageMetaData.stage?.id} - actionTypesOptions={relatedStageModesOptions} + actionsOptions={relatedStageActionsOptions} /> ); diff --git a/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.types.js b/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.types.js index cbfbef6ea7..135a01646b 100644 --- a/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.types.js +++ b/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentWithFirstStageDataEntry/EnrollmentWithFirstStageDataEntry.types.js @@ -1,7 +1,7 @@ // @flow import type { ProgramStage, RenderFoundation } from '../../../../metaData'; import type { RelatedStageRefPayload } from '../../../WidgetRelatedStages'; -import { RelatedStageModes } from '../../../WidgetRelatedStages'; +import { relatedStageActions } from '../../../WidgetRelatedStages'; export type Props = { firstStageMetaData: { @@ -10,8 +10,8 @@ export type Props = { formFoundation: RenderFoundation, programId: string, relatedStageRef?: { current: ?RelatedStageRefPayload }, - relatedStageModesOptions?: { - [key: $Keys]: { + relatedStageActionsOptions?: { + [key: $Keys]: { hidden?: boolean, disabled?: boolean, disabledMessage?: string diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.types.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.types.js index edbe849b06..6eff575ea5 100644 --- a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.types.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.types.js @@ -8,7 +8,7 @@ import type { ExistingUniqueValueDialogActionsComponent } from '../withErrorMess import type { InputAttribute } from './hooks/useFormValues'; import { RenderFoundation, ProgramStage } from '../../../metaData'; import type { RelatedStageRefPayload } from '../../WidgetRelatedStages'; -import { RelatedStageModes } from '../../WidgetRelatedStages'; +import { relatedStageActions } from '../../WidgetRelatedStages'; type TrackedEntityAttributes = Array<{ attribute: string, @@ -69,8 +69,8 @@ export type OwnProps = $ReadOnly<{| saveButtonText: (trackedEntityName: string) => string, firstStageMetaData?: ?{ stage: ?ProgramStage }, relatedStageRef?: { current: ?RelatedStageRefPayload }, - relatedStageModesOptions?: { - [key: $Keys]: { + relatedStageActionsOptions?: { + [key: $Keys]: { hidden?: boolean, disabled?: boolean, disabledMessage?: string diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js index 20fc060c42..6a5566696a 100644 --- a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js @@ -28,7 +28,7 @@ import { } from '../helpers'; import type { EnrollmentPayload } from '../EnrollmentRegistrationEntry.types'; import { geometryType, getPossibleTetFeatureTypeKey, buildGeometryProp } from '../../common/TEIAndEnrollment/geometry'; -import { RelatedStageModes } from '../../../WidgetRelatedStages'; +import { relatedStageActions } from '../../../WidgetRelatedStages'; import type { RelatedStageRefPayload } from '../../../WidgetRelatedStages'; type DataEntryReduxConverterProps = { @@ -184,7 +184,7 @@ export const useBuildEnrollmentPayload = ({ }, formHasError, programStageIdLinkedEventToRedirectTo: - relatedStageLinkedEvent && linkMode === RelatedStageModes.ENTER_DATA + relatedStageLinkedEvent && linkMode === relatedStageActions.ENTER_DATA ? relatedStageLinkedEvent.programStage : undefined, }; diff --git a/src/core_modules/capture-core/components/DataEntries/common/trackerEvent/withAskToCompleteEnrollment/withAskToCompleteEnrollment.js b/src/core_modules/capture-core/components/DataEntries/common/trackerEvent/withAskToCompleteEnrollment/withAskToCompleteEnrollment.js index f41e682ea4..c19649a0d7 100644 --- a/src/core_modules/capture-core/components/DataEntries/common/trackerEvent/withAskToCompleteEnrollment/withAskToCompleteEnrollment.js +++ b/src/core_modules/capture-core/components/DataEntries/common/trackerEvent/withAskToCompleteEnrollment/withAskToCompleteEnrollment.js @@ -6,7 +6,7 @@ import { CompleteModal } from './CompleteModal'; import { statusTypes as eventStatuses } from '../../../../../events/statusTypes'; import { type RenderFoundation } from '../../../../../metaData'; import { addEventSaveTypes } from '../../../../WidgetEnrollmentEventNew/DataEntry/addEventSaveTypes'; -import { RelatedStageModes } from '../../../../WidgetRelatedStages'; +import { relatedStageActions } from '../../../../WidgetRelatedStages'; import type { RelatedStageRefPayload } from '../../../../WidgetRelatedStages'; type Props = { @@ -63,7 +63,7 @@ const getAskToCompleteEnrollment = (InnerComponent: ComponentType) => (prop if ( askCompleteEnrollmentOnEventComplete && (isCompleted || saveType === addEventSaveTypes.COMPLETE) && - linkMode !== RelatedStageModes.ENTER_DATA + linkMode !== relatedStageActions.ENTER_DATA ) { setOpenCompleteModal(true); } else { diff --git a/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js b/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js index 5603b4d6ff..ad19d0ec9e 100644 --- a/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js +++ b/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js @@ -1,7 +1,7 @@ // @flow import log from 'loglevel'; import { generateUID } from '../../../../utils/uid/generateUID'; -import { RelatedStageModes } from '../../../WidgetRelatedStages'; +import { relatedStageActions } from '../../../WidgetRelatedStages'; import type { LinkedRequestEvent, ConvertedRelatedStageEventProps } from './getConvertedRelatedStageEvent.types'; import { errorCreator, pipe } from '../../../../../capture-core-utils'; import { convertClientToServer, convertFormToClient } from '../../../../converters'; @@ -35,7 +35,7 @@ const getEventDetailsByLinkMode = ({ status: 'SCHEDULE', }; - if (linkMode === RelatedStageModes.SCHEDULE_IN_ORG) { + if (linkMode === relatedStageActions.SCHEDULE_IN_ORG) { const { scheduledAt: linkedEventScheduledAt, orgUnit: linkedEventOrgUnit } = relatedStageDataValues; if (!linkedEventScheduledAt || !linkedEventOrgUnit) { // Business logic dictates that these values will not be null here @@ -56,7 +56,7 @@ const getEventDetailsByLinkMode = ({ }); } - if (linkMode === RelatedStageModes.ENTER_DATA) { + if (linkMode === relatedStageActions.ENTER_DATA) { const { orgUnit: linkedEventOrgUnit } = relatedStageDataValues; if (!linkedEventOrgUnit) { throw new Error( @@ -75,7 +75,7 @@ const getEventDetailsByLinkMode = ({ }); } - if (linkMode === RelatedStageModes.LINK_EXISTING_RESPONSE) { + if (linkMode === relatedStageActions.LINK_EXISTING_RESPONSE) { const { linkedEventId } = relatedStageDataValues; return { linkedEvent: null, diff --git a/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.types.js b/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.types.js index 7a40b70c2e..360a0ab676 100644 --- a/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.types.js +++ b/src/core_modules/capture-core/components/DataEntries/converters/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.types.js @@ -1,6 +1,6 @@ // @flow import type { RelatedStageDataValueStates, RelatedStageRelationshipType } from '../../../WidgetRelatedStages'; -import { RelatedStageModes } from '../../../WidgetRelatedStages'; +import { relatedStageActions } from '../../../WidgetRelatedStages'; type CommonEventDetails = { event: string, @@ -28,7 +28,7 @@ export type LinkedRequestEvent = { } export type ConvertedRelatedStageEventProps = {| - linkMode: $Keys, + linkMode: $Keys, relatedStageDataValues: RelatedStageDataValueStates, programId: string, teiId?: ?string, diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPage.epics.js b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPage.epics.js index 6b18a26e4c..7fd2050e30 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPage.epics.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPage.epics.js @@ -11,7 +11,7 @@ import { rollbackEnrollmentEvents, saveFailed, } from '../common/EnrollmentOverviewDomain/enrollment.actions'; -import { RelatedStageModes } from '../../WidgetRelatedStages'; +import { relatedStageActions } from '../../WidgetRelatedStages'; import { buildUrlQueryString } from '../../../utils/routing'; const shouldNavigateWithRelatedStage = ({ @@ -21,7 +21,7 @@ const shouldNavigateWithRelatedStage = ({ history, }) => { if (linkMode && linkedEventId) { - if (linkMode === RelatedStageModes.ENTER_DATA) { + if (linkMode === relatedStageActions.ENTER_DATA) { const navigate = () => history.push(`/enrollmentEventEdit?${buildUrlQueryString({ eventId: linkedEventId, orgUnitId: linkedOrgUnitId, diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.container.js b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.container.js index c7c32a4f76..a3500cd1f3 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.container.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.container.js @@ -11,7 +11,7 @@ import { buildUrlQueryString, useLocationQuery } from '../../../../utils/routing import { useProgramInfo } from '../../../../hooks/useProgramInfo'; import { EnrollmentAddEventTopBar, useEnrollmentAddEventTopBar } from '../TopBar'; import { deleteEnrollment, fetchEnrollments } from '../../Enrollment/EnrollmentPage.actions'; -import { RelatedStageModes } from '../../../WidgetRelatedStages'; +import { relatedStageActions } from '../../../WidgetRelatedStages'; import { useWidgetDataFromStore } from '../hooks'; import { useHideWidgetByRuleLocations } from '../../Enrollment/EnrollmentPageDefault/hooks'; @@ -70,7 +70,7 @@ export const EnrollmentAddEventPageDefault = ({ const handleSave = useCallback( ({ enrollments, events, linkMode }) => { - if (linkMode && linkMode === RelatedStageModes.ENTER_DATA) return; + if (linkMode && linkMode === relatedStageActions.ENTER_DATA) return; const nowClient = fromClientDate(new Date()); const nowServer = new Date(nowClient.getServerZonedISOString()); diff --git a/src/core_modules/capture-core/components/Pages/New/EnrollmentRegistrationEntryWrapper.component.js b/src/core_modules/capture-core/components/Pages/New/EnrollmentRegistrationEntryWrapper.component.js index ac0b51288b..8c65e761b5 100644 --- a/src/core_modules/capture-core/components/Pages/New/EnrollmentRegistrationEntryWrapper.component.js +++ b/src/core_modules/capture-core/components/Pages/New/EnrollmentRegistrationEntryWrapper.component.js @@ -4,7 +4,7 @@ import { useDispatch } from 'react-redux'; import { cleanUpUid } from './NewPage.actions'; import { EnrollmentRegistrationEntry } from '../../DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.container'; import type { OwnProps } from '../../DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.types'; -import { RelatedStageModes } from '../../WidgetRelatedStages'; +import { relatedStageActions } from '../../WidgetRelatedStages'; export const EnrollmentRegistrationEntryWrapper: ComponentType = (props) => { const dispatch = useDispatch(); @@ -12,9 +12,9 @@ export const EnrollmentRegistrationEntryWrapper: ComponentType = (prop dispatch(cleanUpUid()); }, [dispatch]); - const relatedStageModesOptions = { - [RelatedStageModes.LINK_EXISTING_RESPONSE]: { hidden: true }, + const relatedStageActionsOptions = { + [relatedStageActions.LINK_EXISTING_RESPONSE]: { hidden: true }, }; - return ; + return ; }; diff --git a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js index fb4dbb4837..710ff035c1 100644 --- a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js +++ b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js @@ -6,7 +6,7 @@ import { DATA_ENTRY_ID } from '../../registerTei.const'; import enrollmentClasses from './enrollment.module.css'; import { EnrollmentRegistrationEntry } from '../../../../../DataEntries'; import type { Props } from './dataEntryEnrollment.types'; -import { RelatedStageModes } from '../../../../../WidgetRelatedStages'; +import { relatedStageActions } from '../../../../../WidgetRelatedStages'; const NewEnrollmentRelationshipPlain = ({ @@ -21,12 +21,12 @@ const NewEnrollmentRelationshipPlain = ExistingUniqueValueDialogActions, }: Props) => { const fieldOptions = { theme, fieldLabelMediaBasedClass: enrollmentClasses.fieldLabelMediaBased }; - const relatedStageModesOptions = { - [RelatedStageModes.ENTER_DATA]: { + const relatedStageActionsOptions = { + [relatedStageActions.ENTER_DATA]: { disabled: true, disabledMessage: i18n.t('Enter details now is not available when creating a relationship'), }, - [RelatedStageModes.LINK_EXISTING_RESPONSE]: { hidden: true }, + [relatedStageActions.LINK_EXISTING_RESPONSE]: { hidden: true }, }; return ( @@ -45,7 +45,7 @@ const NewEnrollmentRelationshipPlain = renderDuplicatesDialogActions={renderDuplicatesDialogActions} renderDuplicatesCardActions={renderDuplicatesCardActions} ExistingUniqueValueDialogActions={ExistingUniqueValueDialogActions} - relatedStageModesOptions={relatedStageModesOptions} + relatedStageActionsOptions={relatedStageActionsOptions} /> ); }; diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js index 406eacdc5f..7d20b9f6ca 100644 --- a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js +++ b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js @@ -6,7 +6,7 @@ import { DATA_ENTRY_ID } from '../../registerTei.const'; import enrollmentClasses from './enrollment.module.css'; import { EnrollmentRegistrationEntry } from '../../../../../../DataEntries'; import type { Props } from './dataEntryEnrollment.types'; -import { RelatedStageModes } from '../../../../../../WidgetRelatedStages'; +import { relatedStageActions } from '../../../../../../WidgetRelatedStages'; const NewEnrollmentRelationshipPlain = ({ @@ -22,12 +22,12 @@ const NewEnrollmentRelationshipPlain = ExistingUniqueValueDialogActions, }: Props) => { const fieldOptions = { theme, fieldLabelMediaBasedClass: enrollmentClasses.fieldLabelMediaBased }; - const relatedStageModesOptions = { - [RelatedStageModes.ENTER_DATA]: { + const relatedStageActionsOptions = { + [relatedStageActions.ENTER_DATA]: { disabled: true, disabledMessage: i18n.t('Enter details now is not available when creating a relationship'), }, - [RelatedStageModes.LINK_EXISTING_RESPONSE]: { hidden: true }, + [relatedStageActions.LINK_EXISTING_RESPONSE]: { hidden: true }, }; return ( @@ -47,7 +47,7 @@ const NewEnrollmentRelationshipPlain = renderDuplicatesCardActions={renderDuplicatesCardActions} ExistingUniqueValueDialogActions={ExistingUniqueValueDialogActions} trackedEntityInstanceAttributes={inheritedAttributes} - relatedStageModesOptions={relatedStageModesOptions} + relatedStageActionsOptions={relatedStageActionsOptions} /> ); }; diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/validated.actions.js b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/validated.actions.js index ddd8c75878..f14942ced5 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/validated.actions.js +++ b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/validated.actions.js @@ -1,7 +1,7 @@ // @flow import { actionCreator } from '../../../actions/actions.utils'; import { effectMethods } from '../../../trackerOffline'; -import { RelatedStageModes } from '../../WidgetRelatedStages'; +import { relatedStageActions } from '../../WidgetRelatedStages'; import type { RequestEvent, LinkedRequestEvent } from '../../DataEntries'; import type { ExternalSaveHandler } from '../common.types'; @@ -37,7 +37,7 @@ export const requestSaveEvent = ({ linkedEvent: ?LinkedRequestEvent, relationship: ?Object, serverData: Object, - linkMode: ?$Keys, + linkMode: ?$Keys, onSaveExternal: ?ExternalSaveHandler, onSaveSuccessActionType?: string, onSaveErrorActionType?: string, @@ -62,7 +62,7 @@ export const setSaveEnrollmentEventInProgress = ({ requestEventId: string, linkedEventId: ?string, linkedOrgUnitId: ?string, - linkMode: ?$Keys, + linkMode: ?$Keys, }) => actionCreator(newEventWidgetActionTypes.SET_SAVE_ENROLLMENT_EVENT_IN_PROGRESS)({ requestEventId, linkedEventId, diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js b/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js index 519cb05cea..acf6c6e0a5 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js @@ -4,7 +4,7 @@ import i18n from '@dhis2/d2-i18n'; import { Button, colors, Radio, spacers, spacersNum } from '@dhis2/ui'; import { withStyles } from '@material-ui/core'; import { ConditionalTooltip } from 'capture-core/components/Tooltips/ConditionalTooltip'; -import { actions as RelatedStagesActionTypes, mainOptionTranslatedTexts, relatedStageStatus } from '../constants'; +import { relatedStageActions, mainOptionTranslatedTexts, relatedStageStatus } from '../constants'; import { useCanAddNewEventToStage } from '../hooks/useCanAddNewEventToStage'; import { DataSection } from '../../DataSection'; import { ScheduleInOrgUnit } from '../ScheduleInOrgUnit'; @@ -41,7 +41,7 @@ const styles = () => ({ }); const Schedule = ({ - actionTypesOptions, + actionsOptions, linkableEvents, selectedAction, updateSelectedAction, @@ -49,7 +49,7 @@ const Schedule = ({ canAddNewEventToStage, }) => { const { hidden, disabled, disabledMessage } = - (actionTypesOptions && actionTypesOptions[RelatedStagesActionTypes.SCHEDULE_IN_ORG]) || {}; + (actionsOptions && actionsOptions[relatedStageActions.SCHEDULE_IN_ORG]) || {}; if (hidden) { return null; } @@ -67,25 +67,25 @@ const Schedule = ({ return ( updateSelectedAction(e.value)} - value={RelatedStagesActionTypes.SCHEDULE_IN_ORG} + value={relatedStageActions.SCHEDULE_IN_ORG} /> ); }; const EnterData = ({ - actionTypesOptions, + actionsOptions, linkableEvents, selectedAction, updateSelectedAction, @@ -93,7 +93,7 @@ const EnterData = ({ canAddNewEventToStage, }) => { const { hidden, disabled, disabledMessage } = - (actionTypesOptions && actionTypesOptions[RelatedStagesActionTypes.ENTER_DATA]) || {}; + (actionsOptions && actionsOptions[relatedStageActions.ENTER_DATA]) || {}; if (hidden) { return null; } @@ -111,32 +111,32 @@ const EnterData = ({ return ( updateSelectedAction(e.value)} - value={RelatedStagesActionTypes.ENTER_DATA} + value={relatedStageActions.ENTER_DATA} /> ); }; const LinkExistingResponse = ({ - actionTypesOptions, + actionsOptions, linkableEvents, selectedAction, updateSelectedAction, programStage, }) => { const { hidden, disabled, disabledMessage } = - (actionTypesOptions && actionTypesOptions[RelatedStagesActionTypes.LINK_EXISTING_RESPONSE]) || {}; + (actionsOptions && actionsOptions[relatedStageActions.LINK_EXISTING_RESPONSE]) || {}; if (hidden) { return null; } @@ -154,18 +154,18 @@ const LinkExistingResponse = ({ return ( updateSelectedAction(e.value)} - value={RelatedStagesActionTypes.LINK_EXISTING_RESPONSE} + value={relatedStageActions.LINK_EXISTING_RESPONSE} /> ); @@ -183,13 +183,13 @@ const RelatedStagesActionsPlain = ({ constraint, errorMessages, saveAttempted, - actionTypesOptions, + actionsOptions, }: Props) => { const { programStage } = useProgramStageInfo(constraint?.programStage?.id); const selectedAction = useMemo(() => relatedStagesDataValues.linkMode, [relatedStagesDataValues.linkMode]); - const updateSelectedAction = (action: ?$Values) => { + const updateSelectedAction = (action: ?$Values) => { setRelatedStagesDataValues(prevState => ({ ...prevState, linkMode: action, @@ -210,7 +210,7 @@ const RelatedStagesActionsPlain = ({ {type === relatedStageStatus.LINKABLE && ( <> )} - {selectedAction === RelatedStagesActionTypes.SCHEDULE_IN_ORG && ( + {selectedAction === relatedStageActions.SCHEDULE_IN_ORG && ( )} - {selectedAction === RelatedStagesActionTypes.ENTER_DATA && ( + {selectedAction === relatedStageActions.ENTER_DATA && ( )} - {selectedAction === RelatedStagesActionTypes.LINK_EXISTING_RESPONSE && ( + {selectedAction === relatedStageActions.LINK_EXISTING_RESPONSE && ( void, setRelatedStagesDataValues: (() => Object) => void, - actionTypesOptions?: { - [key: $Keys]: { + actionsOptions?: { + [key: $Keys]: { hidden?: boolean, disabled?: boolean, disabledMessage?: string diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js b/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js index c433e40c89..7876e528c1 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.types.js @@ -1,5 +1,5 @@ // @flow -import { RelatedStageModes } from './index'; +import { relatedStageActions } from './index'; import type { Constraint } from './RelatedStagesActions/RelatedStagesActions.types'; export type RelationshipType = {| @@ -19,8 +19,8 @@ export type Props = {| programId: string, enrollmentId?: string, programStageId: string, - actionTypesOptions?: { - [key: $Keys]: { + actionsOptions?: { + [key: $Keys]: { hidden?: boolean, disabled?: boolean, disabledMessage?: string @@ -28,7 +28,7 @@ export type Props = {| }, |} export type RelatedStageDataValueStates = {| - linkMode: ?$Keys, + linkMode: ?$Keys, scheduledAt: string, scheduledAtFormatError: ?{error: ?string, errorCode: ?string}, orgUnit: ?{ @@ -57,7 +57,7 @@ export type RelatedStageRefPayload = { getLinkedStageValues: () => { selectedRelationshipType: RelatedStageRelationshipType, relatedStageDataValues: RelatedStageDataValueStates, - linkMode: ?$Keys, + linkMode: ?$Keys, }, eventHasLinkableStageRelationship: () => boolean, formIsValidOnSave: () => boolean, diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/constants.js b/src/core_modules/capture-core/components/WidgetRelatedStages/constants.js index d8e57bb9a4..7b021f5fc5 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/constants.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/constants.js @@ -6,14 +6,14 @@ export const relatedStageStatus = Object.freeze({ AMBIGUOUS_RELATIONSHIPS: 'AMBIGUOUS_RELATIONSHIPS', }); -export const actions = Object.freeze({ +export const relatedStageActions = Object.freeze({ SCHEDULE_IN_ORG: 'SCHEDULE_IN_ORG', LINK_EXISTING_RESPONSE: 'LINK_EXISTING_RESPONSE', ENTER_DATA: 'ENTER_DATA', }); export const mainOptionTranslatedTexts = { - [actions.SCHEDULE_IN_ORG]: i18n.t('Schedule'), - [actions.ENTER_DATA]: i18n.t('Enter details now'), - [actions.LINK_EXISTING_RESPONSE]: i18n.t('Link to an existing event'), + [relatedStageActions.SCHEDULE_IN_ORG]: i18n.t('Schedule'), + [relatedStageActions.ENTER_DATA]: i18n.t('Enter details now'), + [relatedStageActions.LINK_EXISTING_RESPONSE]: i18n.t('Link to an existing event'), }; diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/index.js b/src/core_modules/capture-core/components/WidgetRelatedStages/index.js index 082bdd7c93..e75b93c8cc 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/index.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/index.js @@ -5,5 +5,5 @@ export type { RelatedStageRefPayload, RelatedStageRelationshipType, } from './WidgetRelatedStages.types'; -export { actions as RelatedStageModes } from './constants'; +export { relatedStageActions } from './constants'; export { relatedStageWidgetIsValid } from './relatedStageEventIsValid/relatedStageEventIsValid'; diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/ValidationFunctions.js b/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/ValidationFunctions.js index 219e354ded..0092d76bab 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/ValidationFunctions.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/ValidationFunctions.js @@ -2,7 +2,7 @@ import i18n from '@dhis2/d2-i18n'; import { isValidOrgUnit } from '../../../../capture-core-utils/validators/form'; import { isValidDate } from '../../../utils/validation/validators/form'; -import { actions as RelatedStageModes } from '../constants'; +import { relatedStageActions } from '../index'; type Props = { scheduledAt: ?string, @@ -87,8 +87,8 @@ const linkToExistingResponse = (props) => { export const ValidationFunctionsByLinkMode: { [key: string]: (props: ?Props) => boolean } = { - [RelatedStageModes.SCHEDULE_IN_ORG]: props => scheduleInOrgUnit(props), - [RelatedStageModes.ENTER_DATA]: props => enterData(props), - [RelatedStageModes.LINK_EXISTING_RESPONSE]: props => linkToExistingResponse(props), + [relatedStageActions.SCHEDULE_IN_ORG]: props => scheduleInOrgUnit(props), + [relatedStageActions.ENTER_DATA]: props => enterData(props), + [relatedStageActions.LINK_EXISTING_RESPONSE]: props => linkToExistingResponse(props), }; diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/relatedStageEventIsValid.types.js b/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/relatedStageEventIsValid.types.js index a8211930b7..1f4fa5cb35 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/relatedStageEventIsValid.types.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/relatedStageEventIsValid.types.js @@ -1,9 +1,9 @@ // @flow import type { ErrorMessagesForRelatedStages } from '../RelatedStagesActions'; -import { RelatedStageModes } from '../index'; +import { relatedStageActions } from '../index'; export type RelatedStageIsValidProps = {| - linkMode: ?$Keys, + linkMode: ?$Keys, scheduledAt: ?string, scheduledAtFormatError: ?{error: ?string, errorCode: ?string}, orgUnit: ?{ From 6b97817d0a8410797789aaa9f09e8f20d15984f7 Mon Sep 17 00:00:00 2001 From: Simona Domnisoru Date: Tue, 17 Dec 2024 09:55:48 +0100 Subject: [PATCH 10/12] chore: rename helper file to getRelationshipNewTeiName --- .../{getRelationshipNewTei.js => getRelationshipNewTeiName.js} | 0 .../Pages/common/TEIRelationshipsWidget/RegisterTei/index.js | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/exposedHelpers/{getRelationshipNewTei.js => getRelationshipNewTeiName.js} (100%) diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/exposedHelpers/getRelationshipNewTei.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/exposedHelpers/getRelationshipNewTeiName.js similarity index 100% rename from src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/exposedHelpers/getRelationshipNewTei.js rename to src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/exposedHelpers/getRelationshipNewTeiName.js diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/index.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/index.js index b8aa107828..bdb73c3680 100644 --- a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/index.js +++ b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/index.js @@ -9,4 +9,4 @@ export { export { loadSearchGroupDuplicatesForReviewEpic, } from '../../../../PossibleDuplicatesDialog/possibleDuplicatesDialog.epics'; -export { getRelationshipNewTeiName } from './exposedHelpers/getRelationshipNewTei'; +export { getRelationshipNewTeiName } from './exposedHelpers/getRelationshipNewTeiName'; From 743bcbf471a906cdda89786d8d6d11d57183750c Mon Sep 17 00:00:00 2001 From: Simona Domnisoru Date: Wed, 18 Dec 2024 12:30:52 +0100 Subject: [PATCH 11/12] feat: simplify how we determine what event to redirect to --- .../EnrollmentRegistrationEntry.container.js | 4 +- .../helpers/deriveAutoGenerateEvents.js | 2 + .../hooks/useBuildEnrollmentPayload.js | 16 ++-- .../types/duplicateCheckOnSave.types.js | 5 +- .../RegistrationDataEntry.actions.js | 13 ++-- .../RegistrationDataEntry.container.js | 4 +- .../RegistrationDataEntry.epics.js | 20 ++--- .../helpers/getPageToRedirectTo.js | 77 ++++++++++++------- .../ValidationFunctions.js | 2 +- 9 files changed, 87 insertions(+), 56 deletions(-) diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.container.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.container.js index acaff25f1b..e4f014b325 100644 --- a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.container.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.container.js @@ -59,9 +59,9 @@ export const EnrollmentRegistrationEntry: ComponentType = ({ } const onSaveWithEnrollment = () => { - const { teiWithEnrollment, formHasError, programStageIdLinkedEventToRedirectTo } = + const { teiWithEnrollment, formHasError, relatedStageLinkedEvent } = buildTeiWithEnrollment(relatedStageRef); - !formHasError && onSave(teiWithEnrollment, programStageIdLinkedEventToRedirectTo); + !formHasError && onSave(teiWithEnrollment, relatedStageLinkedEvent); }; return ( diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/deriveAutoGenerateEvents.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/deriveAutoGenerateEvents.js index c4eb7ddc85..6af15e19be 100644 --- a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/deriveAutoGenerateEvents.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/helpers/deriveAutoGenerateEvents.js @@ -4,6 +4,7 @@ import { dataElementTypes, ProgramStage } from '../../../../metaData'; import { convertClientToServer } from '../../../../converters'; import { convertCategoryOptionsToServer } from '../../../../converters/clientToServer'; import type { RequestEvent, LinkedRequestEvent } from '../../../DataEntries'; +import { generateUID } from '../../../../utils/uid/generateUID'; const ignoreAutoGenerateIfApplicable = (stage, stageToSkip) => !stageToSkip || stageToSkip.programStage !== stage.id; @@ -75,6 +76,7 @@ export const deriveAutoGenerateEvents = ({ return { ...eventInfo, ...eventAttributeCategoryOptions, + event: generateUID(), programStage, program: programId, orgUnit: orgUnitId, diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js index 6a5566696a..8d0a1c4b01 100644 --- a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js @@ -94,7 +94,10 @@ export const useBuildEnrollmentPayload = ({ const buildTeiWithEnrollment = (relatedStageRef?: {current: ?RelatedStageRefPayload}): { teiWithEnrollment: EnrollmentPayload, formHasError: boolean, - programStageIdLinkedEventToRedirectTo?: string, + relatedStageLinkedEvent?: { + programStageId: string, + eventId: string, + }, } => { if (!formFoundation) throw Error('form foundation object not found'); const firstStage = firstStageMetaData && firstStageMetaData.stage; @@ -183,10 +186,13 @@ export const useBuildEnrollmentPayload = ({ relationships: relationship ? [relationship] : undefined, }, formHasError, - programStageIdLinkedEventToRedirectTo: - relatedStageLinkedEvent && linkMode === relatedStageActions.ENTER_DATA - ? relatedStageLinkedEvent.programStage - : undefined, + relatedStageLinkedEvent: + relatedStageLinkedEvent && linkMode === relatedStageActions.ENTER_DATA + ? { + programStageId: relatedStageLinkedEvent.programStage, + eventId: relatedStageLinkedEvent.event, + } + : undefined, }; }; diff --git a/src/core_modules/capture-core/components/DataEntries/common/TEIAndEnrollment/DuplicateCheckOnSave/types/duplicateCheckOnSave.types.js b/src/core_modules/capture-core/components/DataEntries/common/TEIAndEnrollment/DuplicateCheckOnSave/types/duplicateCheckOnSave.types.js index 43e78f4ec8..da1e6bcc39 100644 --- a/src/core_modules/capture-core/components/DataEntries/common/TEIAndEnrollment/DuplicateCheckOnSave/types/duplicateCheckOnSave.types.js +++ b/src/core_modules/capture-core/components/DataEntries/common/TEIAndEnrollment/DuplicateCheckOnSave/types/duplicateCheckOnSave.types.js @@ -4,5 +4,8 @@ import type { TeiPayload } from '../../../../../Pages/common/TEIRelationshipsWid export type SaveForDuplicateCheck = ( teiWithEnrollment: EnrollmentPayload | TeiPayload, - programStageIdLinkedEventToRedirectTo?: string, + relatedStageLinkedEvent?: { + programStageId: string, + eventId: string, + }, ) => void; diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.actions.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.actions.js index b8000eacf9..55731792cd 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.actions.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.actions.js @@ -49,12 +49,15 @@ export const saveNewTrackedEntityInstance = (candidateForRegistration: any) => export const startSavingNewTrackedEntityInstanceWithEnrollment = ( enrollmentPayload: EnrollmentPayload, uid: string, - programStageIdLinkedEventToRedirectTo?: string, + relatedStageLinkedEvent?: { + programStageId: string, + eventId: string, + }, ) => actionCreator(registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_WITH_ENROLLMENT_SAVE_START)({ enrollmentPayload, uid, - programStageIdLinkedEventToRedirectTo, + relatedStageLinkedEvent, }); export const saveNewTrackedEntityInstanceWithEnrollment = ({ @@ -62,13 +65,13 @@ export const saveNewTrackedEntityInstanceWithEnrollment = ({ pageToRedirectTo, uid, stageId, - eventIndex, + eventId, }: { candidateForRegistration: any, pageToRedirectTo: string, uid: string, stageId?: string, - eventIndex: number, + eventId?: string, }) => actionCreator(registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_WITH_ENROLLMENT_SAVE)( { ...candidateForRegistration }, @@ -81,7 +84,7 @@ export const saveNewTrackedEntityInstanceWithEnrollment = ({ }, commit: { type: registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_WITH_ENROLLMENT_SAVE_COMPLETED, - meta: { pageToRedirectTo, stageId, uid, eventIndex }, + meta: { pageToRedirectTo, stageId, uid, eventId }, }, rollback: { type: registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_WITH_ENROLLMENT_SAVE_FAILED, diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.container.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.container.js index 83398364d6..2527f67c65 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.container.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.container.js @@ -30,13 +30,13 @@ export const RegistrationDataEntry: ComponentType = ({ [dispatch]); const dispatchOnSaveWithEnrollment = useCallback( - (enrollmentPayload, programStageIdLinkedEventToRedirectTo) => { + (enrollmentPayload, relatedStageLinkedEvent) => { const uid = uuid(); dispatch( startSavingNewTrackedEntityInstanceWithEnrollment( enrollmentPayload, uid, - programStageIdLinkedEventToRedirectTo, + relatedStageLinkedEvent, ), ); }, diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.epics.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.epics.js index 787922f840..390e95aabc 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.epics.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.epics.js @@ -54,17 +54,14 @@ export const startSavingNewTrackedEntityInstanceWithEnrollmentEpic: Epic = ( ofType(registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_WITH_ENROLLMENT_SAVE_START), map((action) => { const { currentSelections: { programId } } = store.value; - const { enrollmentPayload, uid, programStageIdLinkedEventToRedirectTo } = action.payload; + const { enrollmentPayload, uid, relatedStageLinkedEvent } = action.payload; const { stages, useFirstStageDuringRegistration } = getTrackerProgramThrowIfNotFound(programId); - const { programStageIdToRedirectTo, pageToRedirectTo } = getPageToRedirectTo( + const { stageId, eventId, pageToRedirectTo } = getPageToRedirectTo({ stages, + events: enrollmentPayload.enrollments[0]?.events, useFirstStageDuringRegistration, - programStageIdLinkedEventToRedirectTo, - ); - - const eventIndex = enrollmentPayload.enrollments[0]?.events.findIndex( - eventsToBeCreated => eventsToBeCreated.programStage === programStageIdToRedirectTo, - ); + relatedStageLinkedEvent, + }); return saveNewTrackedEntityInstanceWithEnrollment({ candidateForRegistration: { @@ -73,8 +70,8 @@ export const startSavingNewTrackedEntityInstanceWithEnrollmentEpic: Epic = ( ], }, pageToRedirectTo, - eventIndex, - stageId: programStageIdToRedirectTo, + eventId, + stageId, uid, }); }), @@ -92,7 +89,7 @@ export const completeSavingNewTrackedEntityInstanceWithEnrollmentEpic = ( payload: { bundleReport: { typeReportMap }, }, - meta: { uid, pageToRedirectTo, stageId, eventIndex }, + meta: { uid, pageToRedirectTo, stageId, eventId }, } = action; const { currentSelections: { orgUnitId, programId }, @@ -101,7 +98,6 @@ export const completeSavingNewTrackedEntityInstanceWithEnrollmentEpic = ( const { uid: stateUid } = newPage || {}; const teiId = typeReportMap.TRACKED_ENTITY.objectReports[0].uid; const enrollmentId = typeReportMap.ENROLLMENT.objectReports[0].uid; - const eventId = typeReportMap.EVENT.objectReports?.[eventIndex]?.uid; if (stateUid !== uid) { return EMPTY; diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/getPageToRedirectTo.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/getPageToRedirectTo.js index baee7b2d40..1b99b1c8fa 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/getPageToRedirectTo.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/getPageToRedirectTo.js @@ -14,40 +14,61 @@ export const PAGES = { * When the event will be created redirect to enrollmentEventEdit * When the event will not be created redirect to enrollmentEventNew */ -export const getPageToRedirectTo = ( +export const getPageToRedirectTo = ({ + stages, + events, + useFirstStageDuringRegistration, + relatedStageLinkedEvent, +}: { stages: Map, + events: any, useFirstStageDuringRegistration: boolean, - programStageIdLinkedEventToRedirectTo?: string, -) => { + relatedStageLinkedEvent?: { + programStageId: string, + eventId: string, + }, +}): { stageId?: string, eventId?: string, pageToRedirectTo: string } => { const stagesArray = [...stages.values()]; const [firstStageWithOpenAfterEnrollment] = stagesArray.filter(({ openAfterEnrollment }) => openAfterEnrollment); - const pageToRedirectTo = (() => { - // event will be created and linked during first stage registration - if (programStageIdLinkedEventToRedirectTo) { - return PAGES.enrollmentEventEdit; + // event will be created and linked during first stage registration + if (relatedStageLinkedEvent?.eventId) { + const { programStageId, eventId } = relatedStageLinkedEvent; + return { + stageId: programStageId, + eventId, + pageToRedirectTo: PAGES.enrollmentEventEdit, + }; + } + + if (firstStageWithOpenAfterEnrollment) { + // event will be created during first stage registration + if (useFirstStageDuringRegistration && stagesArray[0].id === firstStageWithOpenAfterEnrollment.id) { + const eventId = events.find(e => e.programStage === firstStageWithOpenAfterEnrollment.id).event; + + return { + programStageIdToRedirectTo: firstStageWithOpenAfterEnrollment.id, + eventId, + pageToRedirectTo: PAGES.enrollmentEventEdit, + }; } - if (firstStageWithOpenAfterEnrollment) { - // event will be created during first stage registration - if ( - useFirstStageDuringRegistration - && stagesArray[0].id === firstStageWithOpenAfterEnrollment.id - ) { - return PAGES.enrollmentEventEdit; - } - // event will be autogenerated - if ( - stagesArray.find(stage => stage.autoGenerateEvent && stage.id === firstStageWithOpenAfterEnrollment.id) - ) { - return PAGES.enrollmentEventEdit; - } - return PAGES.enrollmentEventNew; + + // event will be autogenerated + if (stagesArray.find(stage => stage.autoGenerateEvent && stage.id === firstStageWithOpenAfterEnrollment.id)) { + const eventId = events.find(e => e.programStage === firstStageWithOpenAfterEnrollment.id).event; + + return { + programStageIdToRedirectTo: firstStageWithOpenAfterEnrollment.id, + eventId, + pageToRedirectTo: PAGES.enrollmentEventEdit, + }; } - return PAGES.enrollmentDashboard; - })(); - return { - programStageIdToRedirectTo: programStageIdLinkedEventToRedirectTo || firstStageWithOpenAfterEnrollment?.id, - pageToRedirectTo, - }; + return { + programStageIdToRedirectTo: firstStageWithOpenAfterEnrollment.id, + pageToRedirectTo: PAGES.enrollmentEventNew, + }; + } + + return { pageToRedirectTo: PAGES.enrollmentDashboard }; }; diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/ValidationFunctions.js b/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/ValidationFunctions.js index 0092d76bab..187f20b625 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/ValidationFunctions.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/ValidationFunctions.js @@ -2,7 +2,7 @@ import i18n from '@dhis2/d2-i18n'; import { isValidOrgUnit } from '../../../../capture-core-utils/validators/form'; import { isValidDate } from '../../../utils/validation/validators/form'; -import { relatedStageActions } from '../index'; +import { relatedStageActions } from '../constants'; type Props = { scheduledAt: ?string, From e4a16cae5be2795e15701398bc2e5247dec1f122 Mon Sep 17 00:00:00 2001 From: Simona Domnisoru Date: Mon, 13 Jan 2025 10:05:50 +0100 Subject: [PATCH 12/12] fix: simplify how we determine what event to redirect to --- .../EnrollmentRegistrationEntry.container.js | 4 +- .../hooks/getRedirectIds.js | 63 ++++++++++++++++ .../hooks/useBuildEnrollmentPayload.js | 24 +++--- .../types/duplicateCheckOnSave.types.js | 6 +- .../RegistrationDataEntry.actions.js | 21 +++--- .../RegistrationDataEntry.container.js | 4 +- .../RegistrationDataEntry.epics.js | 34 +++------ .../helpers/getPageToRedirectTo.js | 74 ------------------- .../RegistrationDataEntry/helpers/index.js | 2 - 9 files changed, 102 insertions(+), 130 deletions(-) create mode 100644 src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/getRedirectIds.js delete mode 100644 src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/getPageToRedirectTo.js delete mode 100644 src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/index.js diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.container.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.container.js index e4f014b325..44db04adf5 100644 --- a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.container.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.container.js @@ -59,9 +59,9 @@ export const EnrollmentRegistrationEntry: ComponentType = ({ } const onSaveWithEnrollment = () => { - const { teiWithEnrollment, formHasError, relatedStageLinkedEvent } = + const { teiWithEnrollment, formHasError, redirect } = buildTeiWithEnrollment(relatedStageRef); - !formHasError && onSave(teiWithEnrollment, relatedStageLinkedEvent); + !formHasError && onSave(teiWithEnrollment, redirect); }; return ( diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/getRedirectIds.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/getRedirectIds.js new file mode 100644 index 0000000000..dfae1d70aa --- /dev/null +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/getRedirectIds.js @@ -0,0 +1,63 @@ +// @flow +import { ProgramStage } from '../../../../metaData'; +import { relatedStageActions } from '../../../WidgetRelatedStages'; + +/** + * An event can be + * - created during first stage registration + * - created and linked during first stage registration + * - autogenerated + * When the event will be created redirect to enrollmentEventEdit + * When the event will not be created redirect to enrollmentEventNew + */ +export const getRedirectIds = ({ + stages, + relatedStageLinkedEvent, + linkMode, + firstStageDuringRegistrationEvent, + autoGenerateEvents, +}: { + stages: Map, + linkMode: ?string, + relatedStageLinkedEvent: ?{ + programStage: string, + event: string, + }, + firstStageDuringRegistrationEvent: ?{ + programStage: string, + event: string, + }, + autoGenerateEvents: Array<{ + programStage: string, + event: string, + orgUnit: string, + }>, +}): { programStageId?: string, eventId?: string } => { + if (relatedStageLinkedEvent && linkMode === relatedStageActions.ENTER_DATA) { + return { eventId: relatedStageLinkedEvent.event }; + } + + const [firstStageWithOpenAfterEnrollment] = [...stages.values()].filter( + ({ openAfterEnrollment }) => openAfterEnrollment, + ); + + if (firstStageWithOpenAfterEnrollment) { + // event will be created during first stage registration + if ( + firstStageDuringRegistrationEvent && + firstStageDuringRegistrationEvent.programStage === firstStageWithOpenAfterEnrollment.id + ) { + return { eventId: firstStageDuringRegistrationEvent.event }; + } + + // event will be autogenerated + const autoGenerateEvent = autoGenerateEvents.find(e => e.programStage === firstStageWithOpenAfterEnrollment.id); + if (autoGenerateEvent) { + return { eventId: autoGenerateEvent.event }; + } + + return { programStageId: firstStageWithOpenAfterEnrollment.id }; + } + + return {}; +}; diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js index 8d0a1c4b01..f996eeb263 100644 --- a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js @@ -28,8 +28,8 @@ import { } from '../helpers'; import type { EnrollmentPayload } from '../EnrollmentRegistrationEntry.types'; import { geometryType, getPossibleTetFeatureTypeKey, buildGeometryProp } from '../../common/TEIAndEnrollment/geometry'; -import { relatedStageActions } from '../../../WidgetRelatedStages'; import type { RelatedStageRefPayload } from '../../../WidgetRelatedStages'; +import { getRedirectIds } from './getRedirectIds'; type DataEntryReduxConverterProps = { programId: string; @@ -94,9 +94,9 @@ export const useBuildEnrollmentPayload = ({ const buildTeiWithEnrollment = (relatedStageRef?: {current: ?RelatedStageRefPayload}): { teiWithEnrollment: EnrollmentPayload, formHasError: boolean, - relatedStageLinkedEvent?: { - programStageId: string, - eventId: string, + redirect: { + programStageId?: string, + eventId?: string, }, } => { if (!formFoundation) throw Error('form foundation object not found'); @@ -156,6 +156,14 @@ export const useBuildEnrollmentPayload = ({ serverMinorVersion: minor, }); + const redirect = getRedirectIds({ + stages, + relatedStageLinkedEvent, + linkMode, + firstStageDuringRegistrationEvent, + autoGenerateEvents, + }); + const allEventsToBeCreated = [firstStageDuringRegistrationEvent, relatedStageLinkedEvent, ...autoGenerateEvents] .filter(Boolean); @@ -186,13 +194,7 @@ export const useBuildEnrollmentPayload = ({ relationships: relationship ? [relationship] : undefined, }, formHasError, - relatedStageLinkedEvent: - relatedStageLinkedEvent && linkMode === relatedStageActions.ENTER_DATA - ? { - programStageId: relatedStageLinkedEvent.programStage, - eventId: relatedStageLinkedEvent.event, - } - : undefined, + redirect, }; }; diff --git a/src/core_modules/capture-core/components/DataEntries/common/TEIAndEnrollment/DuplicateCheckOnSave/types/duplicateCheckOnSave.types.js b/src/core_modules/capture-core/components/DataEntries/common/TEIAndEnrollment/DuplicateCheckOnSave/types/duplicateCheckOnSave.types.js index da1e6bcc39..ee773e5d33 100644 --- a/src/core_modules/capture-core/components/DataEntries/common/TEIAndEnrollment/DuplicateCheckOnSave/types/duplicateCheckOnSave.types.js +++ b/src/core_modules/capture-core/components/DataEntries/common/TEIAndEnrollment/DuplicateCheckOnSave/types/duplicateCheckOnSave.types.js @@ -4,8 +4,8 @@ import type { TeiPayload } from '../../../../../Pages/common/TEIRelationshipsWid export type SaveForDuplicateCheck = ( teiWithEnrollment: EnrollmentPayload | TeiPayload, - relatedStageLinkedEvent?: { - programStageId: string, - eventId: string, + redirect: { + programStageId?: string, + eventId?: string, }, ) => void; diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.actions.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.actions.js index 55731792cd..6cd66b0309 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.actions.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.actions.js @@ -49,29 +49,28 @@ export const saveNewTrackedEntityInstance = (candidateForRegistration: any) => export const startSavingNewTrackedEntityInstanceWithEnrollment = ( enrollmentPayload: EnrollmentPayload, uid: string, - relatedStageLinkedEvent?: { - programStageId: string, - eventId: string, + redirect: { + programStageId?: string, + eventId?: string, }, ) => actionCreator(registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_WITH_ENROLLMENT_SAVE_START)({ enrollmentPayload, uid, - relatedStageLinkedEvent, + redirect, }); export const saveNewTrackedEntityInstanceWithEnrollment = ({ candidateForRegistration, - pageToRedirectTo, uid, - stageId, - eventId, + redirect, }: { candidateForRegistration: any, - pageToRedirectTo: string, uid: string, - stageId?: string, - eventId?: string, + redirect: { + programStageId?: string, + eventId?: string, + } }) => actionCreator(registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_WITH_ENROLLMENT_SAVE)( { ...candidateForRegistration }, @@ -84,7 +83,7 @@ export const saveNewTrackedEntityInstanceWithEnrollment = ({ }, commit: { type: registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_WITH_ENROLLMENT_SAVE_COMPLETED, - meta: { pageToRedirectTo, stageId, uid, eventId }, + meta: { redirect, uid }, }, rollback: { type: registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_WITH_ENROLLMENT_SAVE_FAILED, diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.container.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.container.js index 2527f67c65..04032e012f 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.container.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.container.js @@ -30,13 +30,13 @@ export const RegistrationDataEntry: ComponentType = ({ [dispatch]); const dispatchOnSaveWithEnrollment = useCallback( - (enrollmentPayload, relatedStageLinkedEvent) => { + (enrollmentPayload, redirect) => { const uid = uuid(); dispatch( startSavingNewTrackedEntityInstanceWithEnrollment( enrollmentPayload, uid, - relatedStageLinkedEvent, + redirect, ), ); }, diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.epics.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.epics.js index 390e95aabc..9c78d3e97f 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.epics.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.epics.js @@ -8,15 +8,10 @@ import { saveNewTrackedEntityInstance, saveNewTrackedEntityInstanceWithEnrollment, } from './RegistrationDataEntry.actions'; -import { getTrackerProgramThrowIfNotFound } from '../../../../metaData'; import { navigateToEnrollmentOverview, } from '../../../../actions/navigateToEnrollmentOverview/navigateToEnrollmentOverview.actions'; import { buildUrlQueryString } from '../../../../utils/routing'; -import { - getPageToRedirectTo, - PAGES, -} from './helpers'; import { cleanUpUid } from '../NewPage.actions'; export const startSavingNewTrackedEntityInstanceEpic: Epic = (action$: InputObservable) => @@ -48,20 +43,11 @@ export const completeSavingNewTrackedEntityInstanceEpic: Epic = (action$: InputO export const startSavingNewTrackedEntityInstanceWithEnrollmentEpic: Epic = ( action$: InputObservable, - store: ReduxStore, ) => action$.pipe( ofType(registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_WITH_ENROLLMENT_SAVE_START), map((action) => { - const { currentSelections: { programId } } = store.value; - const { enrollmentPayload, uid, relatedStageLinkedEvent } = action.payload; - const { stages, useFirstStageDuringRegistration } = getTrackerProgramThrowIfNotFound(programId); - const { stageId, eventId, pageToRedirectTo } = getPageToRedirectTo({ - stages, - events: enrollmentPayload.enrollments[0]?.events, - useFirstStageDuringRegistration, - relatedStageLinkedEvent, - }); + const { enrollmentPayload, uid, redirect } = action.payload; return saveNewTrackedEntityInstanceWithEnrollment({ candidateForRegistration: { @@ -69,9 +55,7 @@ export const startSavingNewTrackedEntityInstanceWithEnrollmentEpic: Epic = ( enrollmentPayload, ], }, - pageToRedirectTo, - eventId, - stageId, + redirect, uid, }); }), @@ -89,7 +73,7 @@ export const completeSavingNewTrackedEntityInstanceWithEnrollmentEpic = ( payload: { bundleReport: { typeReportMap }, }, - meta: { uid, pageToRedirectTo, stageId, eventId }, + meta: { uid, redirect }, } = action; const { currentSelections: { orgUnitId, programId }, @@ -103,23 +87,23 @@ export const completeSavingNewTrackedEntityInstanceWithEnrollmentEpic = ( return EMPTY; } - if (pageToRedirectTo === PAGES.enrollmentEventNew) { + if (redirect.programStageId) { history.push( - `/${pageToRedirectTo}?${buildUrlQueryString({ + `/enrollmentEventNew?${buildUrlQueryString({ programId, orgUnitId, teiId, enrollmentId, - stageId, + stageId: redirect.programStageId, })}`, ); return EMPTY; } - if (pageToRedirectTo === PAGES.enrollmentEventEdit) { + if (redirect.eventId) { history.push( - `/${pageToRedirectTo}?${buildUrlQueryString({ - eventId, + `/enrollmentEventEdit?${buildUrlQueryString({ + eventId: redirect.eventId, orgUnitId, initMode: dataEntryKeys.EDIT, })}`, diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/getPageToRedirectTo.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/getPageToRedirectTo.js deleted file mode 100644 index 1b99b1c8fa..0000000000 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/getPageToRedirectTo.js +++ /dev/null @@ -1,74 +0,0 @@ -// @flow -import { ProgramStage } from '../../../../../metaData'; - -export const PAGES = { - enrollmentEventNew: 'enrollmentEventNew', - enrollmentEventEdit: 'enrollmentEventEdit', - enrollmentDashboard: 'enrollmentDashboard', -}; -/** - * An event can be - * - created during first stage registration - * - created and linked during first stage registration - * - autogenerated - * When the event will be created redirect to enrollmentEventEdit - * When the event will not be created redirect to enrollmentEventNew - */ -export const getPageToRedirectTo = ({ - stages, - events, - useFirstStageDuringRegistration, - relatedStageLinkedEvent, -}: { - stages: Map, - events: any, - useFirstStageDuringRegistration: boolean, - relatedStageLinkedEvent?: { - programStageId: string, - eventId: string, - }, -}): { stageId?: string, eventId?: string, pageToRedirectTo: string } => { - const stagesArray = [...stages.values()]; - const [firstStageWithOpenAfterEnrollment] = stagesArray.filter(({ openAfterEnrollment }) => openAfterEnrollment); - - // event will be created and linked during first stage registration - if (relatedStageLinkedEvent?.eventId) { - const { programStageId, eventId } = relatedStageLinkedEvent; - return { - stageId: programStageId, - eventId, - pageToRedirectTo: PAGES.enrollmentEventEdit, - }; - } - - if (firstStageWithOpenAfterEnrollment) { - // event will be created during first stage registration - if (useFirstStageDuringRegistration && stagesArray[0].id === firstStageWithOpenAfterEnrollment.id) { - const eventId = events.find(e => e.programStage === firstStageWithOpenAfterEnrollment.id).event; - - return { - programStageIdToRedirectTo: firstStageWithOpenAfterEnrollment.id, - eventId, - pageToRedirectTo: PAGES.enrollmentEventEdit, - }; - } - - // event will be autogenerated - if (stagesArray.find(stage => stage.autoGenerateEvent && stage.id === firstStageWithOpenAfterEnrollment.id)) { - const eventId = events.find(e => e.programStage === firstStageWithOpenAfterEnrollment.id).event; - - return { - programStageIdToRedirectTo: firstStageWithOpenAfterEnrollment.id, - eventId, - pageToRedirectTo: PAGES.enrollmentEventEdit, - }; - } - - return { - programStageIdToRedirectTo: firstStageWithOpenAfterEnrollment.id, - pageToRedirectTo: PAGES.enrollmentEventNew, - }; - } - - return { pageToRedirectTo: PAGES.enrollmentDashboard }; -}; diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/index.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/index.js deleted file mode 100644 index a82f1974d9..0000000000 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/index.js +++ /dev/null @@ -1,2 +0,0 @@ -// @flow -export { getPageToRedirectTo, PAGES } from './getPageToRedirectTo';