@openmrs/esm-fast-data-entry-app 1.0.1-pre.17 → 1.0.1-pre.171
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -2
- package/dist/101.js +1 -0
- package/dist/101.js.map +1 -0
- package/dist/132.js +1 -1
- package/dist/143.js +1 -0
- package/dist/143.js.map +1 -0
- package/dist/188.js +1 -0
- package/dist/188.js.map +1 -0
- package/dist/197.js +1 -0
- package/dist/219.js +1 -0
- package/dist/219.js.map +1 -0
- package/dist/221.js +1 -0
- package/dist/221.js.map +1 -0
- package/dist/259.js +1 -0
- package/dist/259.js.map +1 -0
- package/dist/29.js +2 -0
- package/dist/29.js.LICENSE.txt +3 -0
- package/dist/29.js.map +1 -0
- package/dist/300.js +1 -0
- package/dist/31.js +2 -0
- package/dist/{569.js.LICENSE.txt → 31.js.LICENSE.txt} +9 -6
- package/dist/31.js.map +1 -0
- package/dist/326.js +1 -0
- package/dist/326.js.map +1 -0
- package/dist/335.js +1 -0
- package/dist/367.js +1 -0
- package/dist/367.js.map +1 -0
- package/dist/480.js +1 -0
- package/dist/491.js +1 -0
- package/dist/491.js.map +1 -0
- package/dist/540.js +2 -0
- package/dist/540.js.map +1 -0
- package/dist/55.js +1 -0
- package/dist/564.js +1 -0
- package/dist/564.js.map +1 -0
- package/dist/602.js +1 -0
- package/dist/602.js.map +1 -0
- package/dist/626.js +2 -0
- package/dist/626.js.LICENSE.txt +9 -0
- package/dist/626.js.map +1 -0
- package/dist/652.js +1 -0
- package/dist/685.js +1 -0
- package/dist/685.js.map +1 -0
- package/dist/773.js +2 -0
- package/dist/{68.js.LICENSE.txt → 773.js.LICENSE.txt} +13 -2
- package/dist/773.js.map +1 -0
- package/dist/91.js +1 -0
- package/dist/91.js.map +1 -0
- package/dist/961.js +2 -0
- package/dist/961.js.map +1 -0
- package/dist/99.js +1 -0
- package/dist/99.js.map +1 -0
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -0
- package/dist/openmrs-esm-fast-data-entry-app.js +1 -1
- package/dist/openmrs-esm-fast-data-entry-app.js.buildmanifest.json +403 -136
- package/dist/openmrs-esm-fast-data-entry-app.js.map +1 -0
- package/dist/routes.json +1 -0
- package/jest.config.json +2 -1
- package/package.json +42 -37
- package/src/CancelModal.tsx +48 -0
- package/src/CompleteModal.tsx +46 -0
- package/src/FormBootstrap.tsx +32 -4
- package/src/add-group-modal/AddGroupModal.tsx +110 -60
- package/src/add-group-modal/styles.scss +7 -3
- package/src/config-schema.ts +62 -0
- package/src/context/FormWorkflowContext.tsx +13 -1
- package/src/context/FormWorkflowReducer.ts +13 -3
- package/src/context/GroupFormWorkflowContext.tsx +43 -6
- package/src/context/GroupFormWorkflowReducer.ts +160 -15
- package/src/declarations.d.ts +4 -0
- package/src/empty-state/styles.scss +14 -14
- package/src/form-entry-workflow/FormEntryWorkflow.tsx +74 -102
- package/src/form-entry-workflow/form-review-card/styles.scss +9 -11
- package/src/form-entry-workflow/patient-banner/styles.scss +11 -12
- package/src/form-entry-workflow/patient-search-header/PatientSearchHeader.tsx +2 -2
- package/src/form-entry-workflow/patient-search-header/styles.scss +13 -10
- package/src/form-entry-workflow/styles.scss +13 -14
- package/src/form-entry-workflow/workflow-review/WorkflowReview.tsx +5 -3
- package/src/form-entry-workflow/workflow-review/styles.scss +0 -4
- package/src/forms-page/FormsPage.tsx +10 -5
- package/src/forms-page/forms-table/FormsTable.tsx +11 -5
- package/src/forms-page/forms-table/styles.scss +4 -5
- package/src/forms-page/styles.scss +3 -5
- package/src/group-form-entry-workflow/GroupFormEntryWorkflow.tsx +12 -399
- package/src/group-form-entry-workflow/GroupSessionWorkspace.tsx +238 -0
- package/src/group-form-entry-workflow/SessionDetailsForm.tsx +177 -0
- package/src/group-form-entry-workflow/SessionMetaWorkspace.tsx +107 -0
- package/src/group-form-entry-workflow/attendance-table/AttendanceTable.tsx +144 -0
- package/src/group-form-entry-workflow/attendance-table/index.ts +1 -0
- package/src/group-form-entry-workflow/configurable-questions/ConfigurableQuestionsSection.tsx +47 -0
- package/src/group-form-entry-workflow/group-display-header/GroupDisplayHeader.tsx +1 -9
- package/src/group-form-entry-workflow/group-display-header/styles.scss +20 -20
- package/src/group-form-entry-workflow/group-search/CompactGroupSearch.tsx +1 -1
- package/src/group-form-entry-workflow/group-search/GroupSearch.tsx +1 -1
- package/src/group-form-entry-workflow/group-search/compact-group-result.scss +16 -17
- package/src/group-form-entry-workflow/group-search/compact-group-search.scss +7 -8
- package/src/group-form-entry-workflow/group-search/group-search.scss +20 -23
- package/src/group-form-entry-workflow/group-search-header/GroupSearchHeader.tsx +36 -6
- package/src/group-form-entry-workflow/group-search-header/styles.scss +8 -8
- package/src/group-form-entry-workflow/styles.scss +15 -17
- package/src/hooks/index.ts +8 -1
- package/src/hooks/useForm.ts +73 -0
- package/src/hooks/useGetAllForms.ts +3 -2
- package/src/hooks/useGetEncounter.ts +2 -2
- package/src/hooks/useGetPatient.ts +1 -1
- package/src/hooks/useGetPatients.ts +34 -0
- package/src/hooks/useGetSystemSetting.ts +38 -0
- package/src/hooks/usePostEndpoint.ts +10 -4
- package/src/hooks/useSearchEndpoint.ts +14 -8
- package/src/hooks/useStartVisit.ts +93 -0
- package/src/index.ts +13 -65
- package/src/patient-card/styles.scss +3 -4
- package/src/routes.json +24 -0
- package/src/types.ts +20 -0
- package/tools/i18next-parser.config.js +93 -0
- package/translations/am.json +75 -0
- package/translations/ar.json +75 -0
- package/translations/en.json +32 -11
- package/translations/es.json +75 -0
- package/translations/fr.json +75 -0
- package/translations/he.json +75 -0
- package/translations/km.json +75 -0
- package/turbo.json +18 -0
- package/dist/247.js +0 -1
- package/dist/255.js +0 -1
- package/dist/294.js +0 -2
- package/dist/32.js +0 -1
- package/dist/327.js +0 -1
- package/dist/403.js +0 -2
- package/dist/403.js.LICENSE.txt +0 -14
- package/dist/553.js +0 -2
- package/dist/553.js.LICENSE.txt +0 -14
- package/dist/569.js +0 -2
- package/dist/574.js +0 -1
- package/dist/595.js +0 -2
- package/dist/595.js.LICENSE.txt +0 -1
- package/dist/617.js +0 -1
- package/dist/68.js +0 -2
- package/dist/776.js +0 -1
- package/dist/804.js +0 -1
- package/dist/820.js +0 -1
- package/dist/906.js +0 -1
- package/dist/935.js +0 -2
- package/dist/openmrs-esm-fast-data-entry-app.old +0 -1
- package/src/declarations.d.tsx +0 -2
- /package/dist/{294.js.LICENSE.txt → 540.js.LICENSE.txt} +0 -0
- /package/dist/{935.js.LICENSE.txt → 961.js.LICENSE.txt} +0 -0
package/src/config-schema.ts
CHANGED
|
@@ -60,6 +60,68 @@ export const configSchema = {
|
|
|
60
60
|
},
|
|
61
61
|
_default: ["ICRC Forms", "Distress Scales"],
|
|
62
62
|
},
|
|
63
|
+
groupSessionConcepts: {
|
|
64
|
+
sessionName: {
|
|
65
|
+
_type: Type.UUID,
|
|
66
|
+
_description: "UUID of concept for Session Name",
|
|
67
|
+
_default: "e2559620-900b-4f66-ae41-0b9c4adfb654",
|
|
68
|
+
},
|
|
69
|
+
sessionDate: {
|
|
70
|
+
_type: Type.UUID,
|
|
71
|
+
_description: "UUID of concept for Session Date",
|
|
72
|
+
_default: "ceaca505-6dff-4940-8a43-8c060a0924d7",
|
|
73
|
+
},
|
|
74
|
+
practitionerName: {
|
|
75
|
+
_type: Type.UUID,
|
|
76
|
+
_description: "UUID of concept for Practitioner Name",
|
|
77
|
+
_default: "f1a2d58c-1a0e-4148-931a-aac224649fdc",
|
|
78
|
+
},
|
|
79
|
+
sessionNotes: {
|
|
80
|
+
_type: Type.UUID,
|
|
81
|
+
_description: "UUID of concept for Session Notes",
|
|
82
|
+
_default: "fa8fedc0-c066-4da3-8dc1-2ad8621fc480",
|
|
83
|
+
},
|
|
84
|
+
cohortTypeId: {
|
|
85
|
+
_type: Type.UUID,
|
|
86
|
+
_description: "UUID of cohort type",
|
|
87
|
+
_default: "eee9970e-7ca0-4e8c-a280-c33e9d5f6a04",
|
|
88
|
+
},
|
|
89
|
+
cohortId: {
|
|
90
|
+
_type: Type.UUID,
|
|
91
|
+
_description: "UUID of concept for cohort identifier",
|
|
92
|
+
_default: "5461f231-7e59-4be8-93a4-6d49fd13c00a",
|
|
93
|
+
},
|
|
94
|
+
cohortName: {
|
|
95
|
+
_type: Type.UUID,
|
|
96
|
+
_description: "UUID of concept for cohort name",
|
|
97
|
+
_default: "6029f289-92a6-4a68-80f1-3078d0152449",
|
|
98
|
+
},
|
|
99
|
+
sessionUuid: {
|
|
100
|
+
_type: Type.UUID,
|
|
101
|
+
_description: "UUID of concept for session identifier",
|
|
102
|
+
_default: "6a803908-8a5b-4598-adea-19358c83529a",
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
specificQuestions: {
|
|
106
|
+
_type: Type.Array,
|
|
107
|
+
_description: "List of specific questions to populate forms.",
|
|
108
|
+
_elements: {
|
|
109
|
+
forms: {
|
|
110
|
+
_type: Type.Array,
|
|
111
|
+
_description: "List of form UUIDs for which the question applies.",
|
|
112
|
+
_elements: {
|
|
113
|
+
_type: Type.UUID,
|
|
114
|
+
},
|
|
115
|
+
_default: [],
|
|
116
|
+
},
|
|
117
|
+
questionId: {
|
|
118
|
+
_type: Type.String,
|
|
119
|
+
_description: "ID of the question.",
|
|
120
|
+
_default: "",
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
_default: [],
|
|
124
|
+
},
|
|
63
125
|
};
|
|
64
126
|
|
|
65
127
|
export type Form = {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React, { useEffect, useMemo, useReducer } from "react";
|
|
2
2
|
import reducer from "./FormWorkflowReducer";
|
|
3
3
|
import { useParams, useLocation } from "react-router-dom";
|
|
4
|
+
import useGetSystemSetting from "../hooks/useGetSystemSetting";
|
|
5
|
+
import { useSession } from "@openmrs/esm-framework";
|
|
4
6
|
interface ParamTypes {
|
|
5
7
|
formUuid?: string;
|
|
6
8
|
}
|
|
@@ -30,6 +32,8 @@ export const initialWorkflowState = {
|
|
|
30
32
|
activeEncounterUuid: null, // pseudo field from state[activeFormUuid].encounterUuid
|
|
31
33
|
patientUuids: [], // pseudo field from state[activeFormUuid].patientUuids
|
|
32
34
|
encounters: {}, // pseudo field from state[activeFormUuid].encounters
|
|
35
|
+
singleSessionVisitTypeUuid: null,
|
|
36
|
+
userUuid: null, // UUID of the user to which this workflow state belongs to
|
|
33
37
|
};
|
|
34
38
|
|
|
35
39
|
const FormWorkflowContext = React.createContext({
|
|
@@ -38,6 +42,7 @@ const FormWorkflowContext = React.createContext({
|
|
|
38
42
|
});
|
|
39
43
|
|
|
40
44
|
const FormWorkflowProvider = ({ children }) => {
|
|
45
|
+
const { user } = useSession();
|
|
41
46
|
const { formUuid } = useParams() as ParamTypes;
|
|
42
47
|
const activeFormUuid = formUuid.split("&")[0];
|
|
43
48
|
const { search } = useLocation();
|
|
@@ -46,6 +51,11 @@ const FormWorkflowProvider = ({ children }) => {
|
|
|
46
51
|
...initialWorkflowState,
|
|
47
52
|
...initialActions,
|
|
48
53
|
});
|
|
54
|
+
const systemSetting = useGetSystemSetting(
|
|
55
|
+
"@openmrs/esm-fast-data-entry-app.groupSessionVisitTypeUuid"
|
|
56
|
+
);
|
|
57
|
+
const singleSessionVisitTypeUuid =
|
|
58
|
+
systemSetting?.result?.data?.results?.[0]?.value;
|
|
49
59
|
|
|
50
60
|
const actions = useMemo(
|
|
51
61
|
() => ({
|
|
@@ -54,6 +64,7 @@ const FormWorkflowProvider = ({ children }) => {
|
|
|
54
64
|
type: "INITIALIZE_WORKFLOW_STATE",
|
|
55
65
|
activeFormUuid,
|
|
56
66
|
newPatientUuid,
|
|
67
|
+
userUuid: user.uuid,
|
|
57
68
|
}),
|
|
58
69
|
addPatient: (patientUuid) =>
|
|
59
70
|
dispatch({ type: "ADD_PATIENT", patientUuid }),
|
|
@@ -72,7 +83,7 @@ const FormWorkflowProvider = ({ children }) => {
|
|
|
72
83
|
destroySession: () => dispatch({ type: "DESTROY_SESSION" }),
|
|
73
84
|
closeSession: () => dispatch({ type: "CLOSE_SESSION" }),
|
|
74
85
|
}),
|
|
75
|
-
[]
|
|
86
|
+
[user]
|
|
76
87
|
);
|
|
77
88
|
|
|
78
89
|
// if formUuid isn't a part of state yet, grab it from the url params
|
|
@@ -103,6 +114,7 @@ const FormWorkflowProvider = ({ children }) => {
|
|
|
103
114
|
encounters:
|
|
104
115
|
state.forms?.[state.activeFormUuid]?.encounters ??
|
|
105
116
|
initialWorkflowState.encounters,
|
|
117
|
+
singleSessionVisitTypeUuid,
|
|
106
118
|
}}
|
|
107
119
|
>
|
|
108
120
|
{children}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { navigate } from "@openmrs/esm-framework";
|
|
2
2
|
import { initialWorkflowState } from "./FormWorkflowContext";
|
|
3
3
|
|
|
4
|
-
export const fdeWorkflowStorageVersion = "1.0
|
|
4
|
+
export const fdeWorkflowStorageVersion = "1.1.0";
|
|
5
5
|
export const fdeWorkflowStorageName = "openmrs:fastDataEntryWorkflowState";
|
|
6
6
|
const persistData = (data) => {
|
|
7
|
-
localStorage.setItem(
|
|
7
|
+
localStorage.setItem(
|
|
8
|
+
fdeWorkflowStorageName + ":" + data.userUuid,
|
|
9
|
+
JSON.stringify(data)
|
|
10
|
+
);
|
|
8
11
|
};
|
|
9
12
|
|
|
10
13
|
const initialFormState = {
|
|
@@ -18,7 +21,9 @@ const initialFormState = {
|
|
|
18
21
|
const reducer = (state, action) => {
|
|
19
22
|
switch (action.type) {
|
|
20
23
|
case "INITIALIZE_WORKFLOW_STATE": {
|
|
21
|
-
const savedData = localStorage.getItem(
|
|
24
|
+
const savedData = localStorage.getItem(
|
|
25
|
+
fdeWorkflowStorageName + ":" + action.userUuid
|
|
26
|
+
);
|
|
22
27
|
const savedDataObject = savedData ? JSON.parse(savedData) : {};
|
|
23
28
|
let newState: { [key: string]: unknown } = {};
|
|
24
29
|
const newPatient = action.newPatientUuid
|
|
@@ -69,6 +74,7 @@ const reducer = (state, action) => {
|
|
|
69
74
|
[action.activeFormUuid]: initialFormState,
|
|
70
75
|
},
|
|
71
76
|
activeFormUuid: action.activeFormUuid,
|
|
77
|
+
userUuid: action.userUuid,
|
|
72
78
|
};
|
|
73
79
|
}
|
|
74
80
|
persistData(newState);
|
|
@@ -259,6 +265,8 @@ const reducer = (state, action) => {
|
|
|
259
265
|
activeFormUuid: null,
|
|
260
266
|
};
|
|
261
267
|
persistData(newState);
|
|
268
|
+
//eslint-disable-next-line
|
|
269
|
+
navigate({ to: "${openmrsSpaBase}/forms" });
|
|
262
270
|
return newState;
|
|
263
271
|
}
|
|
264
272
|
case "CLOSE_SESSION": {
|
|
@@ -267,6 +275,8 @@ const reducer = (state, action) => {
|
|
|
267
275
|
activeFormUuid: null,
|
|
268
276
|
};
|
|
269
277
|
persistData(newState);
|
|
278
|
+
//eslint-disable-next-line
|
|
279
|
+
navigate({ to: "${openmrsSpaBase}/forms" });
|
|
270
280
|
return newState;
|
|
271
281
|
}
|
|
272
282
|
default:
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React, { useEffect, useMemo, useReducer } from "react";
|
|
2
2
|
import reducer from "./GroupFormWorkflowReducer";
|
|
3
3
|
import { useParams } from "react-router-dom";
|
|
4
|
-
import { Type } from "@openmrs/esm-framework";
|
|
4
|
+
import { type Type, useSession } from "@openmrs/esm-framework";
|
|
5
|
+
import useGetSystemSetting from "../hooks/useGetSystemSetting";
|
|
5
6
|
interface ParamTypes {
|
|
6
7
|
formUuid?: string;
|
|
7
8
|
}
|
|
@@ -25,9 +26,14 @@ const initialActions = {
|
|
|
25
26
|
openPatientSearch: () => undefined,
|
|
26
27
|
saveEncounter: (encounterUuid: string | number) => undefined,
|
|
27
28
|
editEncounter: (patientUuid: string | number) => undefined,
|
|
28
|
-
|
|
29
|
+
validateForNext: () => undefined,
|
|
30
|
+
validateForComplete: () => undefined,
|
|
31
|
+
updateVisitUuid: (visitUuid: string) => undefined,
|
|
32
|
+
submitForNext: (nextPatientUuid: string = null) => undefined,
|
|
29
33
|
submitForReview: () => undefined,
|
|
30
34
|
submitForComplete: () => undefined,
|
|
35
|
+
addPatientUuid: (patientUuid: string) => undefined,
|
|
36
|
+
removePatientUuid: (patientUuid: string) => undefined,
|
|
31
37
|
goToReview: () => undefined,
|
|
32
38
|
destroySession: () => undefined,
|
|
33
39
|
closeSession: () => undefined,
|
|
@@ -42,17 +48,23 @@ export const initialWorkflowState = {
|
|
|
42
48
|
// aciveFormUuid
|
|
43
49
|
workflowState: null, // pseudo field from state[activeFormUuid].workflowState
|
|
44
50
|
activePatientUuid: null, // pseudo field from state[activeFormUuid].activePatientUuid
|
|
45
|
-
activeEncounterUuid: null, // pseudo field from state[activeFormUuid].
|
|
51
|
+
activeEncounterUuid: null, // pseudo field from state[activeFormUuid].activeEncounterUuid
|
|
52
|
+
activeSessionUuid: null, // pseudo field from state[activeFormUuid].activeSessionUuid
|
|
53
|
+
activeVisitUuid: null, // pseudo field from state[activeFormUuid].activeVisitUuid
|
|
46
54
|
patientUuids: [], // pseudo field from state[activeFormUuid].patientUuids
|
|
47
55
|
encounters: {}, // pseudo field from state[activeFormUuid].encounters
|
|
56
|
+
visits: {}, // pseudo field from state[activeFormUuid].visits
|
|
48
57
|
activeGroupUuid: null, // pseudo field from state[activeFormUuid].groupUuid
|
|
49
|
-
activeGroupName: null, // pseudo field from state[activeFormUuid].
|
|
58
|
+
activeGroupName: null, // pseudo field from state[activeFormUuid].groupName
|
|
59
|
+
activeGroupMembers: [], // pseudo field from state[activeFormUuid].groupMembers
|
|
50
60
|
activeSessionMeta: {
|
|
51
61
|
sessionName: null,
|
|
52
62
|
practitionerName: null,
|
|
53
63
|
sessionDate: null,
|
|
54
64
|
sessionNotes: null,
|
|
55
65
|
},
|
|
66
|
+
groupVisitTypeUuid: null,
|
|
67
|
+
userUuid: null, // UUID of the user to which this workflow state belongs to
|
|
56
68
|
};
|
|
57
69
|
|
|
58
70
|
const GroupFormWorkflowContext = React.createContext({
|
|
@@ -61,8 +73,13 @@ const GroupFormWorkflowContext = React.createContext({
|
|
|
61
73
|
});
|
|
62
74
|
|
|
63
75
|
const GroupFormWorkflowProvider = ({ children }) => {
|
|
76
|
+
const { user } = useSession();
|
|
64
77
|
const { formUuid } = useParams() as ParamTypes;
|
|
65
78
|
const activeFormUuid = formUuid.split("&")[0];
|
|
79
|
+
const systemSetting = useGetSystemSetting(
|
|
80
|
+
"@openmrs/esm-fast-data-entry-app.groupSessionVisitTypeUuid"
|
|
81
|
+
);
|
|
82
|
+
const groupVisitTypeUuid = systemSetting?.result?.data?.results?.[0]?.value;
|
|
66
83
|
const [state, dispatch] = useReducer(reducer, {
|
|
67
84
|
...initialWorkflowState,
|
|
68
85
|
...initialActions,
|
|
@@ -74,17 +91,27 @@ const GroupFormWorkflowProvider = ({ children }) => {
|
|
|
74
91
|
dispatch({
|
|
75
92
|
type: "INITIALIZE_WORKFLOW_STATE",
|
|
76
93
|
activeFormUuid,
|
|
94
|
+
userUuid: user.uuid,
|
|
77
95
|
}),
|
|
78
96
|
setGroup: (group) => dispatch({ type: "SET_GROUP", group }),
|
|
79
97
|
unsetGroup: () => dispatch({ type: "UNSET_GROUP" }),
|
|
80
98
|
setSessionMeta: (meta) => dispatch({ type: "SET_SESSION_META", meta }),
|
|
99
|
+
addPatientUuid: (patientUuid) =>
|
|
100
|
+
dispatch({ type: "ADD_PATIENT_UUID", patientUuid }),
|
|
101
|
+
removePatientUuid: (patientUuid) =>
|
|
102
|
+
dispatch({ type: "REMOVE_PATIENT_UUID", patientUuid }),
|
|
81
103
|
openPatientSearch: () => dispatch({ type: "OPEN_PATIENT_SEARCH" }),
|
|
82
104
|
saveEncounter: (encounterUuid) =>
|
|
83
105
|
dispatch({
|
|
84
106
|
type: "SAVE_ENCOUNTER",
|
|
85
107
|
encounterUuid,
|
|
86
108
|
}),
|
|
87
|
-
|
|
109
|
+
validateForNext: () => dispatch({ type: "VALIDATE_FOR_NEXT" }),
|
|
110
|
+
validateForComplete: () => dispatch({ type: "VALIDATE_FOR_COMPLETE" }),
|
|
111
|
+
updateVisitUuid: (visitUuid) =>
|
|
112
|
+
dispatch({ type: "UPDATE_VISIT_UUID", visitUuid }),
|
|
113
|
+
submitForNext: (nextPatientUuid) =>
|
|
114
|
+
dispatch({ type: "SUBMIT_FOR_NEXT", nextPatientUuid }),
|
|
88
115
|
submitForComplete: () => dispatch({ type: "SUBMIT_FOR_COMPLETE" }),
|
|
89
116
|
editEncounter: (patientUuid) =>
|
|
90
117
|
dispatch({ type: "EDIT_ENCOUNTER", patientUuid }),
|
|
@@ -92,7 +119,7 @@ const GroupFormWorkflowProvider = ({ children }) => {
|
|
|
92
119
|
destroySession: () => dispatch({ type: "DESTROY_SESSION" }),
|
|
93
120
|
closeSession: () => dispatch({ type: "CLOSE_SESSION" }),
|
|
94
121
|
}),
|
|
95
|
-
[]
|
|
122
|
+
[user]
|
|
96
123
|
);
|
|
97
124
|
|
|
98
125
|
// if formUuid isn't a part of state yet, grab it from the url params
|
|
@@ -106,17 +133,24 @@ const GroupFormWorkflowProvider = ({ children }) => {
|
|
|
106
133
|
return (
|
|
107
134
|
<GroupFormWorkflowContext.Provider
|
|
108
135
|
value={{
|
|
136
|
+
groupVisitTypeUuid,
|
|
109
137
|
...state,
|
|
110
138
|
...actions,
|
|
111
139
|
workflowState:
|
|
112
140
|
state.forms?.[state.activeFormUuid]?.workflowState ??
|
|
113
141
|
initialWorkflowState.workflowState,
|
|
142
|
+
activeSessionUuid:
|
|
143
|
+
state.forms?.[state.activeFormUuid]?.activeSessionUuid ??
|
|
144
|
+
initialWorkflowState.activeSessionUuid,
|
|
114
145
|
activePatientUuid:
|
|
115
146
|
state.forms?.[state.activeFormUuid]?.activePatientUuid ??
|
|
116
147
|
initialWorkflowState.activePatientUuid,
|
|
117
148
|
activeEncounterUuid:
|
|
118
149
|
state.forms?.[state.activeFormUuid]?.activeEncounterUuid ??
|
|
119
150
|
initialWorkflowState.activeEncounterUuid,
|
|
151
|
+
activeVisitUuid:
|
|
152
|
+
state.forms?.[state.activeFormUuid]?.activeVisitUuid ??
|
|
153
|
+
initialWorkflowState.activeVisitUuid,
|
|
120
154
|
patientUuids:
|
|
121
155
|
state.forms?.[state.activeFormUuid]?.patientUuids ??
|
|
122
156
|
initialWorkflowState.patientUuids,
|
|
@@ -129,6 +163,9 @@ const GroupFormWorkflowProvider = ({ children }) => {
|
|
|
129
163
|
activeGroupName:
|
|
130
164
|
state.forms?.[state.activeFormUuid]?.groupName ??
|
|
131
165
|
initialWorkflowState.activeGroupName,
|
|
166
|
+
activeGroupMembers:
|
|
167
|
+
state.forms?.[state.activeFormUuid]?.groupMembers ??
|
|
168
|
+
initialWorkflowState.activeGroupMembers,
|
|
132
169
|
activeSessionMeta:
|
|
133
170
|
state.forms?.[state.activeFormUuid]?.sessionMeta ??
|
|
134
171
|
initialWorkflowState.activeSessionMeta,
|
|
@@ -1,27 +1,37 @@
|
|
|
1
1
|
import { navigate } from "@openmrs/esm-framework";
|
|
2
2
|
import { initialWorkflowState } from "./FormWorkflowContext";
|
|
3
|
+
import { v4 as uuid } from "uuid";
|
|
3
4
|
|
|
4
5
|
export const fdeGroupWorkflowStorageVersion = "1.0.5";
|
|
5
6
|
export const fdeGroupWorkflowStorageName =
|
|
6
7
|
"openmrs:fastDataEntryGroupWorkflowState";
|
|
7
8
|
const persistData = (data) => {
|
|
8
|
-
localStorage.setItem(
|
|
9
|
+
localStorage.setItem(
|
|
10
|
+
fdeGroupWorkflowStorageName + ":" + data.userUuid,
|
|
11
|
+
JSON.stringify(data)
|
|
12
|
+
);
|
|
9
13
|
};
|
|
10
14
|
|
|
11
15
|
const initialFormState = {
|
|
12
16
|
workflowState: "NEW_GROUP_SESSION",
|
|
13
17
|
groupUuid: null,
|
|
14
18
|
groupName: null,
|
|
19
|
+
groupMembers: [],
|
|
15
20
|
activePatientUuid: null,
|
|
16
21
|
activeEncounterUuid: null,
|
|
22
|
+
activeVisitUuid: null,
|
|
23
|
+
activeSessionUuid: null,
|
|
17
24
|
patientUuids: [],
|
|
18
25
|
encounters: {},
|
|
26
|
+
visits: {},
|
|
19
27
|
};
|
|
20
28
|
|
|
21
29
|
const reducer = (state, action) => {
|
|
22
30
|
switch (action.type) {
|
|
23
31
|
case "INITIALIZE_WORKFLOW_STATE": {
|
|
24
|
-
const savedData = localStorage.getItem(
|
|
32
|
+
const savedData = localStorage.getItem(
|
|
33
|
+
fdeGroupWorkflowStorageName + ":" + action.userUuid
|
|
34
|
+
);
|
|
25
35
|
const savedDataObject = savedData ? JSON.parse(savedData) : {};
|
|
26
36
|
let newState: { [key: string]: unknown } = {};
|
|
27
37
|
if (
|
|
@@ -37,6 +47,7 @@ const reducer = (state, action) => {
|
|
|
37
47
|
thisSavedForm?.patientUuids?.[0] ||
|
|
38
48
|
// something probably went wrong...
|
|
39
49
|
null;
|
|
50
|
+
const activeSessionUuid = thisSavedForm?.activeSessionUuid || uuid();
|
|
40
51
|
newState = {
|
|
41
52
|
...savedDataObject,
|
|
42
53
|
// set current form to this one
|
|
@@ -50,6 +61,9 @@ const reducer = (state, action) => {
|
|
|
50
61
|
activePatientUuid: activePatientUuid,
|
|
51
62
|
activeEncounterUuid:
|
|
52
63
|
thisSavedForm?.encounters?.[activePatientUuid] || null,
|
|
64
|
+
activeVisitUuid:
|
|
65
|
+
thisSavedForm?.visits?.[activePatientUuid] || null,
|
|
66
|
+
activeSessionUuid: activeSessionUuid,
|
|
53
67
|
},
|
|
54
68
|
},
|
|
55
69
|
};
|
|
@@ -62,6 +76,7 @@ const reducer = (state, action) => {
|
|
|
62
76
|
[action.activeFormUuid]: initialFormState,
|
|
63
77
|
},
|
|
64
78
|
activeFormUuid: action.activeFormUuid,
|
|
79
|
+
userUuid: action.userUuid,
|
|
65
80
|
};
|
|
66
81
|
}
|
|
67
82
|
persistData(newState);
|
|
@@ -84,8 +99,14 @@ const reducer = (state, action) => {
|
|
|
84
99
|
action.group.cohortMembers?.map(
|
|
85
100
|
(member) => member?.patient?.uuid
|
|
86
101
|
) ?? [],
|
|
102
|
+
groupMembers:
|
|
103
|
+
action.group.cohortMembers?.map(
|
|
104
|
+
(member) => member?.patient?.uuid
|
|
105
|
+
) ?? [],
|
|
87
106
|
activePatientUuid: null,
|
|
88
107
|
activeEncounterUuid: null,
|
|
108
|
+
activeVisitUuid: null,
|
|
109
|
+
activeSessionUuid: null,
|
|
89
110
|
},
|
|
90
111
|
},
|
|
91
112
|
};
|
|
@@ -102,8 +123,11 @@ const reducer = (state, action) => {
|
|
|
102
123
|
groupUuid: null,
|
|
103
124
|
groupName: null,
|
|
104
125
|
patientUuids: [],
|
|
126
|
+
groupMembers: [],
|
|
105
127
|
activePatientUuid: null,
|
|
106
128
|
activeEncounterUuid: null,
|
|
129
|
+
activeVisitUuid: null,
|
|
130
|
+
activeSessionUuid: null,
|
|
107
131
|
},
|
|
108
132
|
},
|
|
109
133
|
};
|
|
@@ -125,6 +149,11 @@ const reducer = (state, action) => {
|
|
|
125
149
|
state.forms[state.activeFormUuid].encounters[
|
|
126
150
|
state.forms[state.activeFormUuid].patientUuids?.[0]
|
|
127
151
|
] || null,
|
|
152
|
+
activeVisitUuid:
|
|
153
|
+
state.forms[state.activeFormUuid].visits[
|
|
154
|
+
state.forms[state.activeFormUuid].patientUuids?.[0]
|
|
155
|
+
] || null,
|
|
156
|
+
activeSessionUuid: uuid(),
|
|
128
157
|
workflowState: "EDIT_FORM",
|
|
129
158
|
},
|
|
130
159
|
},
|
|
@@ -132,7 +161,47 @@ const reducer = (state, action) => {
|
|
|
132
161
|
persistData(newState);
|
|
133
162
|
return newState;
|
|
134
163
|
}
|
|
164
|
+
case "ADD_PATIENT_UUID": {
|
|
165
|
+
if (
|
|
166
|
+
state.forms[state.activeFormUuid].patientUuids.includes(
|
|
167
|
+
action.patientUuid
|
|
168
|
+
)
|
|
169
|
+
) {
|
|
170
|
+
return state;
|
|
171
|
+
}
|
|
135
172
|
|
|
173
|
+
const newState = {
|
|
174
|
+
...state,
|
|
175
|
+
forms: {
|
|
176
|
+
...state.forms,
|
|
177
|
+
[state.activeFormUuid]: {
|
|
178
|
+
...state.forms[state.activeFormUuid],
|
|
179
|
+
patientUuids: [
|
|
180
|
+
...state.forms[state.activeFormUuid].patientUuids,
|
|
181
|
+
action.patientUuid,
|
|
182
|
+
],
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
persistData(newState);
|
|
187
|
+
return newState;
|
|
188
|
+
}
|
|
189
|
+
case "REMOVE_PATIENT_UUID": {
|
|
190
|
+
const newState = {
|
|
191
|
+
...state,
|
|
192
|
+
forms: {
|
|
193
|
+
...state.forms,
|
|
194
|
+
[state.activeFormUuid]: {
|
|
195
|
+
...state.forms[state.activeFormUuid],
|
|
196
|
+
patientUuids: state.forms[
|
|
197
|
+
state.activeFormUuid
|
|
198
|
+
].patientUuids?.filter((uuid) => action.patientUuid !== uuid),
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
persistData(newState);
|
|
203
|
+
return newState;
|
|
204
|
+
}
|
|
136
205
|
case "SAVE_ENCOUNTER": {
|
|
137
206
|
const thisForm = state.forms[state.activeFormUuid];
|
|
138
207
|
if (thisForm.workflowState === "SUBMIT_FOR_COMPLETE") {
|
|
@@ -147,25 +216,29 @@ const reducer = (state, action) => {
|
|
|
147
216
|
navigate({ to: "${openmrsSpaBase}/forms" });
|
|
148
217
|
return newState;
|
|
149
218
|
} else if (thisForm.workflowState === "SUBMIT_FOR_NEXT") {
|
|
150
|
-
const nextPatientUuid =
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
219
|
+
const nextPatientUuid = state.nextPatientUuid
|
|
220
|
+
? state.nextPatientUuid
|
|
221
|
+
: thisForm.patientUuids[
|
|
222
|
+
Math.min(
|
|
223
|
+
thisForm.patientUuids.indexOf(thisForm.activePatientUuid) + 1,
|
|
224
|
+
thisForm.patientUuids.length - 1
|
|
225
|
+
)
|
|
226
|
+
];
|
|
227
|
+
const encounters = {
|
|
228
|
+
...thisForm.encounters,
|
|
229
|
+
[thisForm.activePatientUuid]: action.encounterUuid,
|
|
230
|
+
};
|
|
157
231
|
const newState = {
|
|
158
232
|
...state,
|
|
159
233
|
forms: {
|
|
160
234
|
...state.forms,
|
|
161
235
|
[state.activeFormUuid]: {
|
|
162
236
|
...thisForm,
|
|
163
|
-
encounters
|
|
164
|
-
...thisForm.encounters,
|
|
165
|
-
[thisForm.activePatientUuid]: action.encounterUuid,
|
|
166
|
-
},
|
|
237
|
+
encounters,
|
|
167
238
|
activePatientUuid: nextPatientUuid,
|
|
168
|
-
activeEncounterUuid:
|
|
239
|
+
activeEncounterUuid: encounters[nextPatientUuid] || null,
|
|
240
|
+
activeVisitUuid: thisForm.visits[nextPatientUuid] || null,
|
|
241
|
+
activeSessionUuid: thisForm.activeSessionUuid,
|
|
169
242
|
workflowState: "EDIT_FORM",
|
|
170
243
|
},
|
|
171
244
|
},
|
|
@@ -183,7 +256,10 @@ const reducer = (state, action) => {
|
|
|
183
256
|
...state.forms[state.activeFormUuid],
|
|
184
257
|
activeEncounterUuid:
|
|
185
258
|
state.forms[state.activeFormUuid].encounters[action.patientUuid],
|
|
259
|
+
activeVisitUuid:
|
|
260
|
+
state.forms[state.activeFormUuid].visits[action.patientUuid],
|
|
186
261
|
activePatientUuid: action.patientUuid,
|
|
262
|
+
activeSessionUuid: action.activeSessionUuid,
|
|
187
263
|
workflowState: "EDIT_FORM",
|
|
188
264
|
},
|
|
189
265
|
},
|
|
@@ -191,6 +267,46 @@ const reducer = (state, action) => {
|
|
|
191
267
|
persistData(newState);
|
|
192
268
|
return newState;
|
|
193
269
|
}
|
|
270
|
+
case "VALIDATE_FOR_NEXT":
|
|
271
|
+
// this state should not be persisted
|
|
272
|
+
window.dispatchEvent(
|
|
273
|
+
new CustomEvent("ampath-form-action", {
|
|
274
|
+
detail: {
|
|
275
|
+
formUuid: state.activeFormUuid,
|
|
276
|
+
patientUuid: state.forms[state.activeFormUuid].activePatientUuid,
|
|
277
|
+
action: "validateForm",
|
|
278
|
+
},
|
|
279
|
+
})
|
|
280
|
+
);
|
|
281
|
+
return {
|
|
282
|
+
...state,
|
|
283
|
+
forms: {
|
|
284
|
+
...state.forms,
|
|
285
|
+
[state.activeFormUuid]: {
|
|
286
|
+
...state.forms[state.activeFormUuid],
|
|
287
|
+
workflowState: "VALIDATE_FOR_NEXT",
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
};
|
|
291
|
+
case "UPDATE_VISIT_UUID":
|
|
292
|
+
// this state should not be persisted
|
|
293
|
+
// we don't pers
|
|
294
|
+
return {
|
|
295
|
+
...state,
|
|
296
|
+
forms: {
|
|
297
|
+
...state.forms,
|
|
298
|
+
[state.activeFormUuid]: {
|
|
299
|
+
...state.forms[state.activeFormUuid],
|
|
300
|
+
visits: {
|
|
301
|
+
...state.forms[state.activeFormUuid].visits,
|
|
302
|
+
[state.forms[state.activeFormUuid].activePatientUuid]:
|
|
303
|
+
action.visitUuid,
|
|
304
|
+
},
|
|
305
|
+
activeVisitUuid: action.visitUuid,
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
};
|
|
309
|
+
|
|
194
310
|
case "SUBMIT_FOR_NEXT":
|
|
195
311
|
// this state should not be persisted
|
|
196
312
|
window.dispatchEvent(
|
|
@@ -211,6 +327,7 @@ const reducer = (state, action) => {
|
|
|
211
327
|
workflowState: "SUBMIT_FOR_NEXT",
|
|
212
328
|
},
|
|
213
329
|
},
|
|
330
|
+
nextPatientUuid: action.nextPatientUuid,
|
|
214
331
|
};
|
|
215
332
|
case "SUBMIT_FOR_REVIEW":
|
|
216
333
|
// this state should not be persisted
|
|
@@ -233,6 +350,28 @@ const reducer = (state, action) => {
|
|
|
233
350
|
},
|
|
234
351
|
},
|
|
235
352
|
};
|
|
353
|
+
|
|
354
|
+
case "VALIDATE_FOR_COMPLETE":
|
|
355
|
+
// this state should not be persisted
|
|
356
|
+
window.dispatchEvent(
|
|
357
|
+
new CustomEvent("ampath-form-action", {
|
|
358
|
+
detail: {
|
|
359
|
+
formUuid: state.activeFormUuid,
|
|
360
|
+
patientUuid: state.forms[state.activeFormUuid].activePatientUuid,
|
|
361
|
+
action: "validateForm",
|
|
362
|
+
},
|
|
363
|
+
})
|
|
364
|
+
);
|
|
365
|
+
return {
|
|
366
|
+
...state,
|
|
367
|
+
forms: {
|
|
368
|
+
...state.forms,
|
|
369
|
+
[state.activeFormUuid]: {
|
|
370
|
+
...state.forms[state.activeFormUuid],
|
|
371
|
+
workflowState: "VALIDATE_FOR_COMPLETE",
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
};
|
|
236
375
|
case "SUBMIT_FOR_COMPLETE":
|
|
237
376
|
// this state should not be persisted
|
|
238
377
|
window.dispatchEvent(
|
|
@@ -262,7 +401,9 @@ const reducer = (state, action) => {
|
|
|
262
401
|
[state.activeFormUuid]: {
|
|
263
402
|
...state.forms[state.activeFormUuid],
|
|
264
403
|
activeEncounterUuid: null,
|
|
404
|
+
activVisitUuid: null,
|
|
265
405
|
activePatientUuid: null,
|
|
406
|
+
activeSessionUuid: null,
|
|
266
407
|
workflowState: "REVIEW",
|
|
267
408
|
},
|
|
268
409
|
},
|
|
@@ -278,7 +419,9 @@ const reducer = (state, action) => {
|
|
|
278
419
|
activeFormUuid: null,
|
|
279
420
|
};
|
|
280
421
|
persistData(newState);
|
|
281
|
-
|
|
422
|
+
//eslint-disable-next-line
|
|
423
|
+
navigate({ to: "${openmrsSpaBase}/forms" });
|
|
424
|
+
return { ...newState, formDestroyed: true };
|
|
282
425
|
}
|
|
283
426
|
case "CLOSE_SESSION": {
|
|
284
427
|
const newState = {
|
|
@@ -286,6 +429,8 @@ const reducer = (state, action) => {
|
|
|
286
429
|
activeFormUuid: null,
|
|
287
430
|
};
|
|
288
431
|
persistData(newState);
|
|
432
|
+
//eslint-disable-next-line
|
|
433
|
+
navigate({ to: "${openmrsSpaBase}/forms" });
|
|
289
434
|
return newState;
|
|
290
435
|
}
|
|
291
436
|
default:
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
@
|
|
2
|
-
@
|
|
3
|
-
@
|
|
1
|
+
@use '@carbon/colors';
|
|
2
|
+
@use '@carbon/layout';
|
|
3
|
+
@use '@carbon/type';
|
|
4
4
|
|
|
5
5
|
.action {
|
|
6
|
-
margin-bottom:
|
|
6
|
+
margin-bottom: layout.$spacing-03;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
.content {
|
|
10
|
-
@include
|
|
11
|
-
color:
|
|
12
|
-
margin-top:
|
|
13
|
-
margin-bottom:
|
|
10
|
+
@include type.type-style("heading-compact-01");
|
|
11
|
+
color: colors.$gray-70;
|
|
12
|
+
margin-top: layout.$spacing-05;
|
|
13
|
+
margin-bottom: layout.$spacing-03;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
.desktopHeading {
|
|
17
17
|
h4 {
|
|
18
|
-
@include
|
|
19
|
-
color:
|
|
18
|
+
@include type.type-style('heading-compact-02');
|
|
19
|
+
color: colors.$gray-70;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
.tabletHeading {
|
|
24
24
|
h4 {
|
|
25
|
-
@include
|
|
26
|
-
color:
|
|
25
|
+
@include type.type-style('heading-03');
|
|
26
|
+
color: colors.$gray-70;
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
.desktopHeading, .tabletHeading {
|
|
31
31
|
text-align: left;
|
|
32
32
|
text-transform: capitalize;
|
|
33
|
-
margin-bottom:
|
|
33
|
+
margin-bottom: layout.$spacing-05;
|
|
34
34
|
|
|
35
35
|
h4:after {
|
|
36
36
|
content: "";
|
|
@@ -51,5 +51,5 @@
|
|
|
51
51
|
|
|
52
52
|
.tile {
|
|
53
53
|
text-align: center;
|
|
54
|
-
border: 1px solid
|
|
54
|
+
border: 1px solid colors.$gray-20;
|
|
55
55
|
}
|