-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: [DHIS2-17192] show related stages widget on registration page #3880
base: master
Are you sure you want to change the base?
Changes from 11 commits
ba81d9c
293c359
0bd5fa9
d88b9c2
ddb3f0e
3eb3c93
c1a1edb
32c824f
9b2d205
2a27f57
9ecf999
28e26b8
d137e8e
0dc2f01
6b97817
d643dd6
743bcbf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,20 @@ | ||
// @flow | ||
import type { ProgramStage, RenderFoundation } from '../../../../metaData'; | ||
import type { RelatedStageRefPayload } from '../../../WidgetRelatedStages'; | ||
import { RelatedStageModes } from '../../../WidgetRelatedStages'; | ||
|
||
export type Props = { | ||
firstStageMetaData: { | ||
stage: ProgramStage, | ||
}, | ||
formFoundation: RenderFoundation, | ||
programId: string, | ||
relatedStageRef?: { current: ?RelatedStageRefPayload }, | ||
relatedStageModesOptions?: { | ||
[key: $Keys<typeof RelatedStageModes>]: { | ||
hidden?: boolean, | ||
disabled?: boolean, | ||
disabledMessage?: string | ||
}, | ||
}, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,9 +24,12 @@ import { | |
import { | ||
deriveAutoGenerateEvents, | ||
deriveFirstStageDuringRegistrationEvent, | ||
deriveRelatedStageEvent, | ||
} from '../../../Pages/New/RegistrationDataEntry/helpers'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we use the opportunity to move these files to |
||
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, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is a good time to simplify how we determine what event to redirect to. My suggestion would be that we in this function (buildTeiWithEnrollment) get the eventId for the event. For related stages we are generating the eventId on the client, we will have to do this for auto generated events too. Then we should be able to write the logic to determine the eventId (that we will redirect to). Having the related stage take precedence makes sense to me (like you already did). This way we can simplify the epics in the chain quite a bit and the code would be easier to reason about. Might be missing something of course. Happy to talk about it. |
||
}; | ||
}; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
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); | ||
})); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be better to stick with either "action" or "mode" throughout? For this particular one, if we stick with actions:
actionsOptions={relatedStageActionsOptions}
(I see that both mode and action are being used in code not introduced by this PR, would be great to fix those as well)
I do like the generic approach you have chosen here though 👍 Nice!