Skip to content

Commit

Permalink
feat: [DHIS2-12361] Tracked Entity Relationships widget
Browse files Browse the repository at this point in the history
Co-authored-by: jasminenguyennn <[email protected]>
Co-authored-by: JasmineNg <[email protected]>
Co-authored-by: Joakim Storløkken Melseth <[email protected]>
  • Loading branch information
4 people authored Oct 24, 2023
1 parent 79ecede commit cafed8d
Show file tree
Hide file tree
Showing 185 changed files with 6,064 additions and 369 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ Then('the list should display data ordered descendingly by report date', () => {
cy.get('input[placeholder="To"]').click();

cy.contains('Update')
.click();
.click({ force: true });

const rows = combineDataAndYear(lastYear, {
'01-01': ['14 Female'],
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 34 additions & 1 deletion docs/user/using-the-capture-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,39 @@ The enrollment comment widget displays comments and allows addition of comments,

By clicking in the text field, you will be able to enter new text and see action buttons **Save comment** and **Cancel**. Note that Enrollment comments are attributed to a user and cannot be deleted.

### Relationship widget

The Relationships widget on the enrollment dashboard is used for viewing the record’s linked relationships to other records.
The number next to the title signifies the total number of relationships

![](resources/images/enrollment-dash-relationship-widget.png)

For tracked entity instance relationships, the key attributes shown in the widget are the attributes that have been selected to be displayed on the relationship type page in Maintenance.

If no attributes are selected, it will just show a row per record with tracked entity type name and relationship creation date.

When clicking a tracked entity instance you should be taken to the Enrollment Dashboard. If the relationship type includes a program, you should be taken to the latest enrollment for that program. If no program is specified, you should still be sent to the enrollment dashboard, but without a program.

Click the **Add new** button to add a new relationship. Adding a new relationship opens a dialog where you can select the applicable relationship type.

![](resources/images/enrollment-dash-relationship-widget-add.png)

Choose between linking to an existing tracked entity instance or creating a new one.

![](resources/images/enrollment-dash-relationship-widget-add-choose.png)

#### Existing tracked entity instance

Use the search form to find any existing record to link to.

![](resources/images/enrollment-dash-relationship-widget-add-existing.png)

#### New tracked entity instance

Use the form to create a new record and link.

![](resources/images/enrollment-dash-relationship-widget-add-new.png)

### Tracked entity instance profile widget

On the enrollment dashboard, you can view the tracked entity instance profile widget. Inside the profile widget you can view the key attributes values.
Expand Down Expand Up @@ -1226,4 +1259,4 @@ The attribute option combo selector will be displayed when you are adding or cha

Example from new Tracker event:

![](resources/images/attribute-option-combo-tracker.png)
![](resources/images/attribute-option-combo-tracker.png)
61 changes: 50 additions & 11 deletions i18n/en.pot
Original file line number Diff line number Diff line change
Expand Up @@ -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: 2023-09-29T14:14:34.330Z\n"
"PO-Revision-Date: 2023-09-29T14:14:34.330Z\n"
"POT-Creation-Date: 2023-09-12T06:24:49.265Z\n"
"PO-Revision-Date: 2023-09-12T06:24:49.265Z\n"

msgid "Choose one or more dates..."
msgstr "Choose one or more dates..."
Expand Down Expand Up @@ -947,6 +947,18 @@ msgstr "Event could not be loaded"
msgid "Organisation unit could not be loaded"
msgstr "Organisation unit could not be loaded"

msgid "Selected program"
msgstr "Selected program"

msgid "Search {{uniqueAttrName}}"
msgstr "Search {{uniqueAttrName}}"

msgid "Search by attributes"
msgstr "Search by attributes"

msgid "Could not retrieve metadata. Please try again later."
msgstr "Could not retrieve metadata. Please try again later."

msgid "Possible duplicates found"
msgstr "Possible duplicates found"

Expand Down Expand Up @@ -1010,9 +1022,6 @@ msgstr "Search {{name}}"
msgid "Search by {{name}}"
msgstr "Search by {{name}}"

msgid "Search by attributes"
msgstr "Search by attributes"

msgid "all programs"
msgstr "all programs"

Expand Down Expand Up @@ -1070,12 +1079,6 @@ msgstr "Missing search criteria"
msgid "Results found"
msgstr "Results found"

msgid "Selected program"
msgstr "Selected program"

msgid "Search {{uniqueAttrName}}"
msgstr "Search {{uniqueAttrName}}"

msgid "Saved lists in this program"
msgstr "Saved lists in this program"

Expand Down Expand Up @@ -1359,6 +1362,42 @@ msgstr "{{ scheduledEvents }} scheduled"
msgid "Stages and Events"
msgstr "Stages and Events"

msgid "New TEI Relationship"
msgstr "New TEI Relationship"

msgid "Missing implementation step"
msgstr "Missing implementation step"

msgid "Go back without saving relationship"
msgstr "Go back without saving relationship"

msgid "New Relationship"
msgstr "New Relationship"

msgid "Link to an existing {{tetName}}"
msgstr "Link to an existing {{tetName}}"

msgid "An error occurred while adding the relationship"
msgstr "An error occurred while adding the relationship"

msgid "Something went wrong while loading relationships. Please try again later."
msgstr "Something went wrong while loading relationships. Please try again later."

msgid "{{trackedEntityTypeName}} relationships"
msgstr "{{trackedEntityTypeName}} relationships"

msgid "To open this relationship, please wait until saving is complete"
msgstr "To open this relationship, please wait until saving is complete"

msgid "Type"
msgstr "Type"

msgid "Created date"
msgstr "Created date"

msgid "Program stage name"
msgstr "Program stage name"

msgid "Working list could not be loaded"
msgstr "Working list could not be loaded"

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "capture-app",
"homepage": ".",
"version": "100.41.4",
"cacheVersion": "6",
"cacheVersion": "7",
"serverVersion": "38",
"license": "BSD-3-Clause",
"private": true,
Expand Down
26 changes: 15 additions & 11 deletions src/components/App/AppPages.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,21 @@ import { EnrollmentPage } from 'capture-core/components/Pages/Enrollment';
import { StageEventListPage } from 'capture-core/components/Pages/StageEvent';
import { EnrollmentEditEventPage } from 'capture-core/components/Pages/EnrollmentEditEvent';
import { EnrollmentAddEventPage } from 'capture-core/components/Pages/EnrollmentAddEvent';
import { ReactQueryDevtools } from 'react-query/devtools';

export const AppPages = () => (
<Switch>
<Route path="/viewEvent" component={ViewEventPage} />
<Route path="/search" component={SearchPage} />
<Route path="/new" component={NewPage} />
<Route path="/enrollment/stageEvents" component={StageEventListPage} />
<Route path="/enrollmentEventEdit" component={EnrollmentEditEventPage} />
<Route path="/enrollmentEventNew" component={EnrollmentAddEventPage} />
<Route path="/enrollment" component={EnrollmentPage} />
<Route path="/:keys" component={MainPage} />
<Route path="/" component={MainPage} />
</Switch>
<>
<ReactQueryDevtools />
<Switch>
<Route path="/viewEvent" component={ViewEventPage} />
<Route path="/search" component={SearchPage} />
<Route path="/new" component={NewPage} />
<Route path="/enrollment/stageEvents" component={StageEventListPage} />
<Route path="/enrollmentEventEdit" component={EnrollmentEditEventPage} />
<Route path="/enrollmentEventNew" component={EnrollmentAddEventPage} />
<Route path="/enrollment" component={EnrollmentPage} />
<Route path="/:keys" component={MainPage} />
<Route path="/" component={MainPage} />
</Switch>
</>
);
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,38 @@ import { useSelector } from 'react-redux';
import { EnrollmentRegistrationEntryComponent } from './EnrollmentRegistrationEntry.component';
import type { OwnProps } from './EnrollmentRegistrationEntry.types';
import { useLifecycle } from './hooks';
import { useCurrentOrgUnitInfo } from '../../../hooks/useCurrentOrgUnitInfo';
import { useRulesEngineOrgUnit } from '../../../hooks';
import { dataEntryHasChanges } from '../../DataEntry/common/dataEntryHasChanges';
import {
useBuildEnrollmentPayload,
} from './hooks/useBuildEnrollmentPayload';

export const EnrollmentRegistrationEntry: ComponentType<OwnProps> = ({
selectedScopeId,
id,
saveButtonText,
trackedEntityInstanceAttributes,
orgUnitId,
teiId,
onSave,
...passOnProps
}) => {
const orgUnitId = useCurrentOrgUnitInfo().id;
const { orgUnit, error } = useRulesEngineOrgUnit(orgUnitId);
const {
teiId,
ready,
skipDuplicateCheck,
firstStageMetaData,
formId,
enrollmentMetadata,
formFoundation,
} = useLifecycle(selectedScopeId, id, trackedEntityInstanceAttributes, orgUnit);
} = useLifecycle(selectedScopeId, id, trackedEntityInstanceAttributes, orgUnit, teiId, selectedScopeId);
const { buildTeiWithEnrollment } = useBuildEnrollmentPayload({
programId: selectedScopeId,
dataEntryId: id,
orgUnitId,
teiId,
trackedEntityTypeId: enrollmentMetadata?.trackedEntityType?.id,
});

const isUserInteractionInProgress: boolean = useSelector(
state =>
Expand All @@ -41,10 +50,16 @@ export const EnrollmentRegistrationEntry: ComponentType<OwnProps> = ({
const isSavingInProgress = useSelector(({ possibleDuplicates, newPage }) =>
possibleDuplicates.isLoading || possibleDuplicates.isUpdating || !!newPage.uid);


if (error) {
return error.errorComponent;
}

const onSaveWithEnrollment = () => {
const teiWithEnrollment = buildTeiWithEnrollment();
onSave(teiWithEnrollment);
};

return (
<EnrollmentRegistrationEntryComponent
{...passOnProps}
Expand All @@ -62,7 +77,7 @@ export const EnrollmentRegistrationEntry: ComponentType<OwnProps> = ({
orgUnit={orgUnit}
isUserInteractionInProgress={isUserInteractionInProgress}
isSavingInProgress={isSavingInProgress}
onSave={() => onSave(formFoundation, firstStageMetaData)}
onSave={onSaveWithEnrollment}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,32 @@ import type { ExistingUniqueValueDialogActionsComponent } from '../withErrorMess
import type { InputAttribute } from './hooks/useFormValues';
import { RenderFoundation, ProgramStage } from '../../../metaData';

export type EnrollmentPayload = {|
trackedEntity: string,
trackedEntityType: string,
orgUnit: string,
geometry: any,
enrollments: [
{|
occurredAt: string,
orgUnit: string,
program: string,
status: string,
enrolledAt: string,
events: Array<{
orgUnit: string,
}>,
attributes: Array<{
attribute: string,
value: any,
}>,
|}
]
|}

export type OwnProps = $ReadOnly<{|
id: string,
orgUnitId: string,
selectedScopeId: string,
fieldOptions?: Object,
onSave: SaveForDuplicateCheck,
Expand Down
Loading

0 comments on commit cafed8d

Please sign in to comment.