Skip to content
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

Merged
merged 53 commits into from
Jan 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
684098e
feat: adds tetselector on the new page
paschalidi Nov 26, 2020
d57dda9
feat: trackedEntityTypeId on url for new and search page
paschalidi Nov 26, 2020
7445483
refactor: cleans up the older func
paschalidi Nov 26, 2020
1816123
chore: removes debugger
paschalidi Nov 26, 2020
4d8001c
chore: order
paschalidi Nov 26, 2020
5286ddc
fix: one trackedEntityTypeId
paschalidi Nov 26, 2020
1b119d4
chore: one line
paschalidi Nov 26, 2020
73293c0
feat: adds the enrollment and profile sections
paschalidi Nov 26, 2020
2cda0b2
chore: tetype once
paschalidi Nov 26, 2020
7e1a12c
chore: better id
paschalidi Nov 26, 2020
8e1f067
chore: reverts
paschalidi Nov 26, 2020
cdea6ec
chore: reverts
paschalidi Nov 26, 2020
6d55a6f
chore: reverts
paschalidi Nov 26, 2020
d2f3937
chore: linting
paschalidi Nov 26, 2020
8c1caf9
chore: styles the forms
paschalidi Nov 26, 2020
e60d3b6
chore: rebasing
paschalidi Nov 26, 2020
d3f343c
chore: reverts
paschalidi Nov 26, 2020
5b59256
chore: reverts ;)
paschalidi Nov 26, 2020
776622a
chore: styles the max width
paschalidi Nov 26, 2020
8c91c49
refactor: exports consts and moves the files around
paschalidi Nov 26, 2020
584c058
chore: remove line
paschalidi Nov 26, 2020
f12add8
refactor: the registration entries are self initialised and ready to use
paschalidi Nov 26, 2020
f428586
chore: rebasing
paschalidi Nov 26, 2020
6048d42
fix: infinite loading state
paschalidi Nov 30, 2020
9d89f52
Merge remote-tracking branch 'origin/master' into cp/registration/10-…
paschalidi Dec 3, 2020
39558c4
chore: rebasing
paschalidi Dec 3, 2020
e9faaaa
chore: styles
paschalidi Dec 3, 2020
56517a1
Merge branch 'cp/registration/09-styles' into cp/registration/10-enro…
paschalidi Dec 3, 2020
83dcbcd
chore: removes dispatch
paschalidi Dec 3, 2020
9022a68
Merge branch 'cp/registration/10-enrollment-data-entry' into cp/regis…
paschalidi Dec 3, 2020
774a28a
chore: lints
paschalidi Dec 3, 2020
e9b0b3f
chore: reverts
paschalidi Dec 3, 2020
a9bb19c
chore: no {}
paschalidi Dec 3, 2020
33d15b1
chore: creates containers
paschalidi Dec 3, 2020
3d81661
chore: fixes the paths
paschalidi Dec 3, 2020
05dbd79
chore: loading indicator
paschalidi Dec 3, 2020
a7ac966
chore: no need for startDataEntryInitialisationEpic
paschalidi Dec 3, 2020
89c15b9
feat: with buttons
paschalidi Dec 3, 2020
89b776b
chore: rebase
paschalidi Dec 3, 2020
33c730d
chore: org unit
paschalidi Dec 3, 2020
ac340f4
chore: "better" text
paschalidi Dec 3, 2020
34e96a2
chore: flow fixes me
paschalidi Dec 3, 2020
5f9e41f
Merge remote-tracking branch 'origin/master' into cp/registration/10-…
paschalidi Dec 3, 2020
0dcb1f2
Merge branch 'cp/registration/10-enrollment-data-entry' into cp/regis…
paschalidi Dec 3, 2020
331529b
Merge branch 'cp/registration/11-shows-enrollment-section' into cp/re…
paschalidi Dec 3, 2020
42f41c8
Merge remote-tracking branch 'origin/master' into cp/registration/12-…
paschalidi Dec 7, 2020
a01b33a
Merge remote-tracking branch 'origin/master' into cp/registration/12-…
paschalidi Dec 10, 2020
3d6107f
chore: InfoIconText refactoe
paschalidi Jan 5, 2021
f471b34
Merge remote-tracking branch 'origin/master' into cp/registration/12-…
paschalidi Jan 5, 2021
1301c33
chore: space
paschalidi Jan 5, 2021
a43961a
chore: no space
paschalidi Jan 5, 2021
3575dbf
Merge remote-tracking branch 'origin/master' into cp/registration/12-…
paschalidi Jan 5, 2021
a3dd10a
[part 02] feat: DHIS2-9653 submitting a new TEI (#1266)
paschalidi Jan 5, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 24 additions & 12 deletions i18n/en.pot
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,24 @@ msgstr ""
msgid "Choose a registering unit to start reporting"
msgstr ""

msgid "Saving a {{trackedEntityName}} in"
msgstr ""

msgid "in"
msgstr ""

msgid "Saving a {{trackedEntityName}}"
msgstr ""

msgid "without"
msgstr ""

msgid "enrollment"
msgstr ""

msgid "Enroll in a program by selecting a program from the top bar."
msgstr ""

msgid "Creating a new {{TET}} in {{program}} in {{orgUnit}}"
msgstr ""

Expand Down Expand Up @@ -565,9 +583,6 @@ msgstr ""
msgid "Saving to"
msgstr ""

msgid "in"
msgstr ""

msgid ""
"This is not an event program or the metadata is corrupt. See log for "
"details."
Expand Down Expand Up @@ -616,15 +631,6 @@ msgstr ""
msgid "You dont have access to create an event in the current selections"
msgstr ""

msgid "Review duplicates"
msgstr ""

msgid "Create {{trackedEntityTypeName}} and link"
msgstr ""

msgid "Review Duplicates"
msgstr ""

msgid "A duplicate exists (but there were some errors, see log for details"
msgstr ""

Expand All @@ -650,6 +656,12 @@ msgstr ""
msgid "Link"
msgstr ""

msgid "Review Duplicates"
msgstr ""

msgid "Save new {{trackedEntityTypeName}} and link"
msgstr ""

msgid "Possible duplicates found"
msgstr ""

Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,70 @@
// @flow
import React from 'react';
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';

export const EnrollmentRegistrationEntryComponent = ({ selectedScopeId, id, ...rest }: OwnProps) => {
const { scopeType } = useScopeInfo(selectedScopeId);
const { formId, registrationMetaData, formFoundation } = useRegistrationFormInfoForSelectedScope(selectedScopeId);
const orgUnit = useCurrentOrgUnitInfo();
const styles = ({ typography }) => ({
marginTop: {
marginTop: typography.pxToRem(2),
},
});

return (
<>
{
scopeType === scopeTypes.TRACKER_PROGRAM && formId &&
<EnrollmentDataEntry
orgUnit={orgUnit}
programId={selectedScopeId}
formFoundation={formFoundation}
enrollmentMetadata={registrationMetaData}
id={id}
{...rest}
/>
}
</>
);
};
const EnrollmentRegistrationEntryPlain =
({
id,
selectedScopeId,
enrollmentMetadata,
saveButtonText,
classes,
onSave,
...rest
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: passOnProps

Copy link
Contributor Author

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 to onProps.

}: {...OwnProps, ...CssClasses}) => {
const { scopeType } = useScopeInfo(selectedScopeId);
const { formId, formFoundation } = useRegistrationFormInfoForSelectedScope(selectedScopeId);
const orgUnit = useCurrentOrgUnitInfo();

return (
<>
{
scopeType === scopeTypes.TRACKER_PROGRAM && formId &&
<>
{/* $FlowFixMe */}
<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
Copy link
Contributor Author

@paschalidi paschalidi Dec 3, 2020

Choose a reason for hiding this comment

The 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 withLoadingIndicator

Copy link
Member

Choose a reason for hiding this comment

The 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
@@ -1,5 +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,
id: string
saveButtonText: string,
fieldOptions?: Object,
onSave: (dataEntryId: string, itemId: string, formFoundation: RenderFoundation) => void,
onPostProcessErrorMessage: Function,
onGetUnsavedAttributeValues: Function,
onUpdateField: Function,
onStartAsyncUpdateField: Function,
Comment on lines +6 to +15
Copy link
Contributor Author

@paschalidi paschalidi Dec 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am attempting to explicitly define the properties this components needs in order to be rendered.
In the future when someone will need to use it they can look in this signature

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, makes sense 👍 I did the same for the working lists. Let's settle on name though. I think I called it InterfaceProps. If you don't like it, what about ModuleProps or ConceptProps? I'm not sure I like OwnProps, but if you have some compelling arguments I might reconsider. Feel free to suggest alternatives.

Copy link
Contributor Author

@paschalidi paschalidi Jan 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point @JoakimSM. Yep for me the naming here is under discussion as well.
What I am trying to do with the OwnProps is to have a type for properties that the user passes directly on the component when they use it.

Eg.

<Button type='one' size='lg'>
Text
</Button>

On the example above OwnProps would be the type and the size. However sometimes you might have the ContainerProps which are props that are passed on the container level. My only point is that I would want to differentiate between what I call OwnProps and the rest of props a component might have. This is because then flow can tell you what props you are supposed to pass in the component when you try to use it.

Again I agree we would like to align on a name here. I stole my name from the redux world, look here.


Now if we agree on communicating the same thing we can be creative with a name. What do you think, would you find it useful to differentiate between the props that we pass on the component and the props that the component takes from redux?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining. Our use cases are a bit different. OwnProps is good for what you're trying to achieve here 👍

|}>
Original file line number Diff line number Diff line change
@@ -1,31 +1,78 @@
// @flow
import React from 'react';
import React, { type ComponentType } from 'react';
import { compose } from 'redux';
import { Button } from '@dhis2/ui';
import { withStyles } from '@material-ui/core';
import { useScopeInfo } from '../../../hooks/useScopeInfo';
import { scopeTypes } from '../../../metaData';
import { TrackedEntityInstanceDataEntry } from '../TrackedEntityInstance';
import { useCurrentOrgUnitInfo } from '../../../hooks/useCurrentOrgUnitInfo';
import type { OwnProps } from './TeiRegistrationEntry.types';
import { useRegistrationFormInfoForSelectedScope } from '../common/useRegistrationFormInfoForSelectedScope';
import { withSaveHandler } from '../../DataEntry';


export const TeiRegistrationEntryComponent = ({ selectedScopeId, id, ...rest }: OwnProps) => {
const { scopeType } = useScopeInfo(selectedScopeId);
const { formId, registrationMetaData, formFoundation } = useRegistrationFormInfoForSelectedScope(selectedScopeId);
const orgUnit = useCurrentOrgUnitInfo();
const styles = ({ typography }) => ({
marginTop: {
marginTop: typography.pxToRem(2),
},
});
const TeiRegistrationEntryPlain =
({
id,
selectedScopeId,
onSave,
saveButtonText,
teiRegistrationMetadata,
fieldOptions,
classes,
onPostProcessErrorMessage,
onGetUnsavedAttributeValues,
...rest
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: passOnProps

}: { ...OwnProps, ...CssClasses }) => {
const { scopeType } = useScopeInfo(selectedScopeId);
const { formId, formFoundation } = useRegistrationFormInfoForSelectedScope(selectedScopeId);
const orgUnit = useCurrentOrgUnitInfo();

return (
<>
{
scopeType === scopeTypes.TRACKED_ENTITY_TYPE && formId &&
<TrackedEntityInstanceDataEntry
orgUnit={orgUnit}
formFoundation={formFoundation}
programId={selectedScopeId}
teiRegistrationMetadata={registrationMetaData}
id={id}
{...rest}
/>
}
</>
);
};
return (
<>
{
scopeType === scopeTypes.TRACKED_ENTITY_TYPE && formId &&
<>
{/* $FlowFixMe */}
<TrackedEntityInstanceDataEntry
orgUnit={orgUnit}
formFoundation={formFoundation}
programId={selectedScopeId}
teiRegistrationMetadata={teiRegistrationMetadata}
id={id}
fieldOptions={fieldOptions}
onPostProcessErrorMessage={onPostProcessErrorMessage}
onGetUnsavedAttributeValues={onGetUnsavedAttributeValues}
{...rest}
/>
{
onSave &&
<Button
dataTest="dhis2-capture-create-and-link-button"
primary
onClick={onSave}
className={classes.marginTop}
>
{saveButtonText}
</Button>
}
</>
}
</>
);
};

export const TeiRegistrationEntryComponent: ComponentType<OwnProps> =
compose(
withSaveHandler({ onGetFormFoundation: ({ teiRegistrationMetadata }) => {
const form = teiRegistrationMetadata && teiRegistrationMetadata.form;
return form;
} }),
withStyles(styles),
)(TeiRegistrationEntryPlain);
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
// @flow
import type { RenderFoundation } from '../../../metaData/RenderFoundation';
import type { RegistrationFormMetadata } from '../common/types';

export type OwnProps = $ReadOnly<{|
id: string,
teiRegistrationMetadata: RegistrationFormMetadata,
selectedScopeId: string,
id: string
saveButtonText: string,
fieldOptions?: Object,
onSave: (dataEntryId: string, itemId: string, formFoundation: RenderFoundation) => void,
onGetUnsavedAttributeValues: Function,
onPostProcessErrorMessage: Function,
|}>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// @flow
import type { TeiRegistration } from '../../../metaData/TrackedEntityType/TeiRegistration';
import type { Enrollment } from '../../../metaData/Program/Enrollment';

export type RegistrationFormMetadata = ?(TeiRegistration | Enrollment)
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import { useMemo } from 'react';
import { useTrackedEntityTypesWithCorrelatedPrograms } from '../../../hooks/useTrackedEntityTypesWithCorrelatedPrograms';
import { useScopeInfo } from '../../../hooks/useScopeInfo';
import { scopeTypes } from '../../../metaData';
import type { RegistrationFormMetadata } from './types';

type RegistrationOptions = $ReadOnly<{|
[elementId: string]: {|
+name: string,
+registrationMetaData: string,
+registrationMetaData: RegistrationFormMetadata,
+formId: string,
+formFoundation: Object,
|}
Expand Down Expand Up @@ -48,5 +49,5 @@ export const useRegistrationFormInfoForSelectedScope = (selectedScopeId: string)
const { formFoundation, formId, registrationMetaData } = options[selectedScopeId];
return { formFoundation, formId, registrationMetaData };
}
return { formFoundation: [], formId: null, registrationMetaData: {} };
return { formFoundation: [], formId: null, registrationMetaData: null };
};
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ const styles = theme => ({
},
footerBar: {
display: 'flex',
paddingTop: theme.typography.pxToRem(10),
},
button: {
marginTop: theme.typography.pxToRem(10),
paddingRight: theme.spacing.unit * 2,
},
horizontalFormInnerContainer: {
Expand Down Expand Up @@ -308,9 +308,7 @@ class DataEntry extends React.Component<Props> {
</div>
}
</div>
<div
className={classes.footerBar}
>
<div className={classes.footerBar}>
{
(() => {
if (completeButton) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type Props = {

type IsCompletingFn = (props: Props) => boolean;
type FilterPropsFn = (props: Object) => Object;
type GetFormFoundationFn = (props: Object) => RenderFoundation;
type GetFormFoundationFn = (props: Object) => ?RenderFoundation;

type State = {
messagesDialogOpen: boolean,
Expand Down Expand Up @@ -218,10 +218,6 @@ const getSaveHandler = (
...passOnProps
} = this.props;

if (!itemId) {
return null;
}

const filteredProps = onFilterProps ? onFilterProps(passOnProps) : passOnProps;
this.isCompleting = !!(onIsCompleting && onIsCompleting(this.props));

Expand Down
Loading