-
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-9652 with save buttons #1260
Changes from 41 commits
684098e
d57dda9
7445483
1816123
4d8001c
5286ddc
1b119d4
73293c0
2cda0b2
7e1a12c
8e1f067
cdea6ec
6d55a6f
d2f3937
8c1caf9
e60d3b6
d3f343c
5b59256
776622a
8c91c49
584c058
f12add8
f428586
6048d42
9d89f52
39558c4
e9faaaa
56517a1
83dcbcd
9022a68
774a28a
e9b0b3f
a9bb19c
33d15b1
3d81661
05dbd79
a7ac966
89c15b9
89b776b
33c730d
ac340f4
34e96a2
5f9e41f
0dcb1f2
331529b
42f41c8
a01b33a
3d6107f
f471b34
1301c33
a43961a
3575dbf
a3dd10a
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 |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// @flow | ||
import { actionCreator } from '../../../actions/actions.utils'; | ||
|
||
export const enrollmentRegistrationEntryActionTypes = { | ||
TRACKER_PROGRAM_REGISTRATION_ENTRY_INITIALISATION_START: 'StartInitForEnrollmentRegistrationForm', | ||
}; | ||
|
||
export const startNewEnrollmentDataEntryInitialisation = ({ selectedOrgUnitId, selectedScopeId, dataEntryId, formFoundation }: Object) => | ||
actionCreator(enrollmentRegistrationEntryActionTypes.TRACKER_PROGRAM_REGISTRATION_ENTRY_INITIALISATION_START)({ selectedOrgUnitId, selectedScopeId, dataEntryId, formFoundation }); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// @flow | ||
import React, { type ComponentType } from 'react'; | ||
import { Button } from '@dhis2/ui'; | ||
import { withStyles } from '@material-ui/core'; | ||
import { compose } from 'redux'; | ||
import { useScopeInfo } from '../../../hooks/useScopeInfo'; | ||
import { scopeTypes } from '../../../metaData'; | ||
import { EnrollmentDataEntry } from '../Enrollment'; | ||
import { useCurrentOrgUnitInfo } from '../../../hooks/useCurrentOrgUnitInfo'; | ||
import { useRegistrationFormInfoForSelectedScope } from '../common/useRegistrationFormInfoForSelectedScope'; | ||
import type { OwnProps } from './EnrollmentRegistrationEntry.types'; | ||
import { withSaveHandler } from '../../DataEntry'; | ||
|
||
const styles = ({ typography }) => ({ | ||
marginTop: { | ||
marginTop: typography.pxToRem(2), | ||
}, | ||
}); | ||
|
||
const EnrollmentRegistrationEntryPlain = | ||
({ | ||
id, | ||
selectedScopeId, | ||
enrollmentMetadata, | ||
saveButtonText, | ||
classes, | ||
onSave, | ||
...rest | ||
}: {...OwnProps, ...CssClasses}) => { | ||
const { scopeType } = useScopeInfo(selectedScopeId); | ||
const { formId, formFoundation } = useRegistrationFormInfoForSelectedScope(selectedScopeId); | ||
const orgUnit = useCurrentOrgUnitInfo(); | ||
|
||
return ( | ||
<> | ||
{ | ||
scopeType === scopeTypes.TRACKER_PROGRAM && formId && | ||
<> | ||
<EnrollmentDataEntry | ||
orgUnit={orgUnit} | ||
programId={selectedScopeId} | ||
formFoundation={formFoundation} | ||
enrollmentMetadata={enrollmentMetadata} | ||
id={id} | ||
{...rest} | ||
/> | ||
{ | ||
onSave && | ||
<Button | ||
dataTest="dhis2-capture-create-and-link-button" | ||
primary | ||
onClick={onSave} | ||
className={classes.marginTop} | ||
> | ||
{saveButtonText} | ||
</Button> | ||
Comment on lines
+49
to
+57
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. Displaying the buttons only when there is an onSave function. I dont know what is your preference on this one. To my eyes using HOC component to display the buttons in this case seems kind of an overkill. Dont get me wrong HOC are great but I would use them in cases we want to share something between multiple components like you do on the 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. Yep, this is fine 👍 |
||
} | ||
|
||
</> | ||
} | ||
</> | ||
); | ||
}; | ||
|
||
export const EnrollmentRegistrationEntryComponent: ComponentType<OwnProps> = | ||
compose( | ||
withSaveHandler({ onGetFormFoundation: ({ enrollmentMetadata }) => enrollmentMetadata && enrollmentMetadata.enrollmentForm }), | ||
withStyles(styles), | ||
)(EnrollmentRegistrationEntryPlain); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// @flow | ||
import { useDispatch } from 'react-redux'; | ||
import React, { useEffect } from 'react'; | ||
import type { ComponentType } from 'react'; | ||
import { EnrollmentRegistrationEntryComponent } from './EnrollmentRegistrationEntry.component'; | ||
import { startNewEnrollmentDataEntryInitialisation } from './EnrollmentRegistrationEntry.actions'; | ||
import type { OwnProps } from './EnrollmentRegistrationEntry.types'; | ||
import { useScopeInfo } from '../../../hooks/useScopeInfo'; | ||
import { useRegistrationFormInfoForSelectedScope } from '../common/useRegistrationFormInfoForSelectedScope'; | ||
import { useCurrentOrgUnitInfo } from '../../../hooks/useCurrentOrgUnitInfo'; | ||
import { scopeTypes } from '../../../metaData'; | ||
|
||
const useInitialiseEnrollmentRegistration = (selectedScopeId, dataEntryId) => { | ||
const dispatch = useDispatch(); | ||
const { scopeType } = useScopeInfo(selectedScopeId); | ||
const { id: selectedOrgUnitId } = useCurrentOrgUnitInfo(); | ||
const { formId, formFoundation } = useRegistrationFormInfoForSelectedScope(selectedScopeId); | ||
const registrationFormReady = !!formId; | ||
useEffect(() => { | ||
if (registrationFormReady && scopeType === scopeTypes.TRACKER_PROGRAM) { | ||
dispatch( | ||
startNewEnrollmentDataEntryInitialisation( | ||
{ selectedOrgUnitId, selectedScopeId, dataEntryId, formFoundation }, | ||
), | ||
); | ||
} | ||
}, [ | ||
scopeType, | ||
dataEntryId, | ||
selectedScopeId, | ||
selectedOrgUnitId, | ||
registrationFormReady, | ||
formFoundation, | ||
dispatch, | ||
]); | ||
}; | ||
|
||
|
||
export const EnrollmentRegistrationEntry: ComponentType<OwnProps> = ({ selectedScopeId, id, ...rest }) => { | ||
useInitialiseEnrollmentRegistration(selectedScopeId, id); | ||
|
||
return ( | ||
<EnrollmentRegistrationEntryComponent | ||
selectedScopeId={selectedScopeId} | ||
id={id} | ||
{...rest} | ||
/>); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// @flow | ||
import { ofType } from 'redux-observable'; | ||
import { pluck, switchMap } from 'rxjs/operators'; | ||
import { empty, from } from 'rxjs'; | ||
import { errorCreator } from 'capture-core-utils'; | ||
import log from 'loglevel'; | ||
import i18n from '@dhis2/d2-i18n'; | ||
import { enrollmentRegistrationEntryActionTypes } from './EnrollmentRegistrationEntry.actions'; | ||
import { openDataEntryForNewEnrollmentBatchAsync } from '../Enrollment'; | ||
import { getTrackerProgramThrowIfNotFound } from '../../../metaData/helpers'; | ||
import { openDataEntryFailed } from '../../Pages/NewRelationship/RegisterTei/DataEntry/RegisterTeiDataEntry.actions'; | ||
import { type TrackerProgram } from '../../../metaData/Program'; | ||
|
||
export const startNewEnrollmentDataEntrySelfInitialisationEpic = (action$: InputObservable) => | ||
action$.pipe( | ||
ofType(enrollmentRegistrationEntryActionTypes.TRACKER_PROGRAM_REGISTRATION_ENTRY_INITIALISATION_START), | ||
pluck('payload'), | ||
switchMap(({ selectedOrgUnitId, selectedScopeId: programId, dataEntryId, formFoundation }) => { | ||
if (selectedOrgUnitId) { | ||
let trackerProgram: ?TrackerProgram; | ||
try { | ||
trackerProgram = getTrackerProgramThrowIfNotFound(programId); | ||
} catch (error) { | ||
log.error( | ||
errorCreator('tracker program for id not found')({ programId, error }), | ||
); | ||
return Promise.resolve(openDataEntryFailed(i18n.t('Metadata error. see log for details'))); | ||
} | ||
|
||
const openEnrollmentPromise = openDataEntryForNewEnrollmentBatchAsync( | ||
trackerProgram, | ||
formFoundation, | ||
{ id: selectedOrgUnitId }, | ||
dataEntryId, | ||
); | ||
|
||
return from(openEnrollmentPromise); | ||
} | ||
|
||
return empty(); | ||
}), | ||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// @flow | ||
import type { RenderFoundation } from '../../../metaData/RenderFoundation'; | ||
import type { RegistrationFormMetadata } from '../common/types'; | ||
|
||
export type OwnProps = $ReadOnly<{| | ||
id: string, | ||
enrollmentMetadata: RegistrationFormMetadata, | ||
selectedScopeId: string, | ||
saveButtonText: string, | ||
fieldOptions?: Object, | ||
onSave: (dataEntryId: string, itemId: string, formFoundation: RenderFoundation) => void, | ||
onPostProcessErrorMessage: Function, | ||
onGetUnsavedAttributeValues: Function, | ||
onUpdateField: Function, | ||
onStartAsyncUpdateField: Function, | ||
|}> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// @flow | ||
import { actionCreator } from '../../../actions/actions.utils'; | ||
|
||
export const teiRegistrationEntryActionTypes = { | ||
TEI_REGISTRATION_ENTRY_INITIALISATION_START: 'StartInitForTrackedEntityTypeRegistrationForm', | ||
}; | ||
|
||
export const startNewTeiDataEntryInitialisation = ({ selectedOrgUnitId, selectedScopeId, dataEntryId, formFoundation }: Object) => | ||
actionCreator(teiRegistrationEntryActionTypes.TEI_REGISTRATION_ENTRY_INITIALISATION_START)({ selectedOrgUnitId, selectedScopeId, dataEntryId, formFoundation }); |
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.
suggestion: passOnProps
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.
Right. I will make a PR in the end renaming all the
rest
toonProps
.