@openmrs/esm-fast-data-entry-app 1.0.1-pre.15 → 1.0.1-pre.21

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.
Files changed (57) hide show
  1. package/dist/132.js +1 -0
  2. package/dist/229.js +1 -0
  3. package/dist/247.js +1 -0
  4. package/dist/255.js +1 -0
  5. package/dist/294.js +2 -0
  6. package/dist/294.js.LICENSE.txt +9 -0
  7. package/dist/32.js +1 -0
  8. package/dist/327.js +1 -0
  9. package/dist/403.js +2 -0
  10. package/dist/403.js.LICENSE.txt +14 -0
  11. package/dist/553.js +2 -0
  12. package/dist/553.js.LICENSE.txt +14 -0
  13. package/dist/569.js +2 -0
  14. package/dist/569.js.LICENSE.txt +27 -0
  15. package/dist/574.js +1 -0
  16. package/dist/595.js +2 -0
  17. package/dist/595.js.LICENSE.txt +1 -0
  18. package/dist/617.js +1 -0
  19. package/dist/640.js +1 -0
  20. package/dist/68.js +2 -0
  21. package/dist/68.js.LICENSE.txt +21 -0
  22. package/dist/776.js +1 -0
  23. package/dist/804.js +1 -0
  24. package/dist/820.js +1 -0
  25. package/dist/935.js +2 -0
  26. package/dist/935.js.LICENSE.txt +19 -0
  27. package/dist/main.js +1 -0
  28. package/dist/openmrs-esm-fast-data-entry-app.js +1 -1
  29. package/dist/openmrs-esm-fast-data-entry-app.js.buildmanifest.json +567 -0
  30. package/dist/openmrs-esm-fast-data-entry-app.old +1 -0
  31. package/package.json +3 -3
  32. package/src/CancelModal.tsx +48 -0
  33. package/src/CompleteModal.tsx +46 -0
  34. package/src/FormBootstrap.tsx +3 -0
  35. package/src/context/FormWorkflowReducer.ts +4 -0
  36. package/src/context/GroupFormWorkflowContext.tsx +31 -2
  37. package/src/context/GroupFormWorkflowReducer.ts +127 -1
  38. package/src/form-entry-workflow/FormEntryWorkflow.tsx +15 -82
  39. package/src/group-form-entry-workflow/GroupFormEntryWorkflow.tsx +11 -398
  40. package/src/group-form-entry-workflow/GroupSessionWorkspace.tsx +227 -0
  41. package/src/group-form-entry-workflow/SessionDetailsForm.tsx +122 -0
  42. package/src/group-form-entry-workflow/SessionMetaWorkspace.tsx +107 -0
  43. package/src/group-form-entry-workflow/attendance-table/AttendanceTable.tsx +105 -0
  44. package/src/group-form-entry-workflow/attendance-table/index.ts +1 -0
  45. package/src/group-form-entry-workflow/group-display-header/GroupDisplayHeader.tsx +1 -9
  46. package/src/group-form-entry-workflow/group-search-header/GroupSearchHeader.tsx +0 -3
  47. package/src/hooks/useGetSystemSetting.ts +38 -0
  48. package/src/hooks/useStartVisit.ts +83 -0
  49. package/translations/en.json +7 -1
  50. package/.editorconfig +0 -12
  51. package/.eslintignore +0 -2
  52. package/.eslintrc.js +0 -10
  53. package/.husky/pre-push +0 -1
  54. package/.prettierignore +0 -14
  55. package/.tx/config +0 -9
  56. package/.yarn/plugins/@yarnpkg/plugin-version.cjs +0 -550
  57. package/.yarn/versions/c1451405.yml +0 -0
@@ -107,6 +107,7 @@ interface FormParams {
107
107
  showDiscardSubmitButtons?: boolean;
108
108
  handlePostResponse?: (Encounter) => void;
109
109
  handleEncounterCreate?: (Object) => void;
110
+ handleOnValidate?: (boolean) => void;
110
111
  }
111
112
 
112
113
  const FormBootstrap = ({
@@ -117,6 +118,7 @@ const FormBootstrap = ({
117
118
  encounterUuid,
118
119
  handlePostResponse,
119
120
  handleEncounterCreate,
121
+ handleOnValidate,
120
122
  }: FormParams) => {
121
123
  const patient = useGetPatient(patientUuid);
122
124
 
@@ -140,6 +142,7 @@ const FormBootstrap = ({
140
142
  closeWorkspace: () => undefined,
141
143
  handlePostResponse,
142
144
  handleEncounterCreate,
145
+ handleOnValidate,
143
146
  showDiscardSubmitButtons: false,
144
147
  }}
145
148
  />
@@ -259,6 +259,8 @@ const reducer = (state, action) => {
259
259
  activeFormUuid: null,
260
260
  };
261
261
  persistData(newState);
262
+ //eslint-disable-next-line
263
+ navigate({ to: "${openmrsSpaBase}/forms" });
262
264
  return newState;
263
265
  }
264
266
  case "CLOSE_SESSION": {
@@ -267,6 +269,8 @@ const reducer = (state, action) => {
267
269
  activeFormUuid: null,
268
270
  };
269
271
  persistData(newState);
272
+ //eslint-disable-next-line
273
+ navigate({ to: "${openmrsSpaBase}/forms" });
270
274
  return newState;
271
275
  }
272
276
  default:
@@ -2,6 +2,7 @@ import React, { useEffect, useMemo, useReducer } from "react";
2
2
  import reducer from "./GroupFormWorkflowReducer";
3
3
  import { useParams } from "react-router-dom";
4
4
  import { Type } 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,
29
+ validateForNext: () => undefined,
30
+ validateForComplete: () => undefined,
31
+ updateVisitUuid: (visitUuid: string) => undefined,
28
32
  submitForNext: () => 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,21 @@ 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].encounterUuid
51
+ activeEncounterUuid: null, // pseudo field from state[activeFormUuid].activeEncounterUuid
52
+ activeVisitUuid: null, // pseudo field from state[activeFormUuid].activeVisitUuid
46
53
  patientUuids: [], // pseudo field from state[activeFormUuid].patientUuids
47
54
  encounters: {}, // pseudo field from state[activeFormUuid].encounters
55
+ visits: {}, // pseudo field from state[activeFormUuid].visits
48
56
  activeGroupUuid: null, // pseudo field from state[activeFormUuid].groupUuid
49
- activeGroupName: null, // pseudo field from state[activeFormUuid].groupname
57
+ activeGroupName: null, // pseudo field from state[activeFormUuid].groupName
58
+ activeGroupMembers: [], // pseudo field from state[activeFormUuid].groupMembers
50
59
  activeSessionMeta: {
51
60
  sessionName: null,
52
61
  practitionerName: null,
53
62
  sessionDate: null,
54
63
  sessionNotes: null,
55
64
  },
65
+ groupVisitTypeUuid: null,
56
66
  };
57
67
 
58
68
  const GroupFormWorkflowContext = React.createContext({
@@ -63,6 +73,10 @@ const GroupFormWorkflowContext = React.createContext({
63
73
  const GroupFormWorkflowProvider = ({ children }) => {
64
74
  const { formUuid } = useParams() as ParamTypes;
65
75
  const activeFormUuid = formUuid.split("&")[0];
76
+ const systemSetting = useGetSystemSetting(
77
+ "@openmrs/esm-fast-data-entry-app.groupSessionVisitTypeUuid"
78
+ );
79
+ const groupVisitTypeUuid = systemSetting?.result?.data?.results?.[0]?.value;
66
80
  const [state, dispatch] = useReducer(reducer, {
67
81
  ...initialWorkflowState,
68
82
  ...initialActions,
@@ -78,12 +92,20 @@ const GroupFormWorkflowProvider = ({ children }) => {
78
92
  setGroup: (group) => dispatch({ type: "SET_GROUP", group }),
79
93
  unsetGroup: () => dispatch({ type: "UNSET_GROUP" }),
80
94
  setSessionMeta: (meta) => dispatch({ type: "SET_SESSION_META", meta }),
95
+ addPatientUuid: (patientUuid) =>
96
+ dispatch({ type: "ADD_PATIENT_UUID", patientUuid }),
97
+ removePatientUuid: (patientUuid) =>
98
+ dispatch({ type: "REMOVE_PATIENT_UUID", patientUuid }),
81
99
  openPatientSearch: () => dispatch({ type: "OPEN_PATIENT_SEARCH" }),
82
100
  saveEncounter: (encounterUuid) =>
83
101
  dispatch({
84
102
  type: "SAVE_ENCOUNTER",
85
103
  encounterUuid,
86
104
  }),
105
+ validateForNext: () => dispatch({ type: "VALIDATE_FOR_NEXT" }),
106
+ validateForComplete: () => dispatch({ type: "VALIDATE_FOR_COMPLETE" }),
107
+ updateVisitUuid: (visitUuid) =>
108
+ dispatch({ type: "UPDATE_VISIT_UUID", visitUuid }),
87
109
  submitForNext: () => dispatch({ type: "SUBMIT_FOR_NEXT" }),
88
110
  submitForComplete: () => dispatch({ type: "SUBMIT_FOR_COMPLETE" }),
89
111
  editEncounter: (patientUuid) =>
@@ -106,6 +128,7 @@ const GroupFormWorkflowProvider = ({ children }) => {
106
128
  return (
107
129
  <GroupFormWorkflowContext.Provider
108
130
  value={{
131
+ groupVisitTypeUuid,
109
132
  ...state,
110
133
  ...actions,
111
134
  workflowState:
@@ -117,6 +140,9 @@ const GroupFormWorkflowProvider = ({ children }) => {
117
140
  activeEncounterUuid:
118
141
  state.forms?.[state.activeFormUuid]?.activeEncounterUuid ??
119
142
  initialWorkflowState.activeEncounterUuid,
143
+ activeVisitUuid:
144
+ state.forms?.[state.activeFormUuid]?.activeVisitUuid ??
145
+ initialWorkflowState.activeVisitUuid,
120
146
  patientUuids:
121
147
  state.forms?.[state.activeFormUuid]?.patientUuids ??
122
148
  initialWorkflowState.patientUuids,
@@ -129,6 +155,9 @@ const GroupFormWorkflowProvider = ({ children }) => {
129
155
  activeGroupName:
130
156
  state.forms?.[state.activeFormUuid]?.groupName ??
131
157
  initialWorkflowState.activeGroupName,
158
+ activeGroupMembers:
159
+ state.forms?.[state.activeFormUuid]?.groupMembers ??
160
+ initialWorkflowState.activeGroupMembers,
132
161
  activeSessionMeta:
133
162
  state.forms?.[state.activeFormUuid]?.sessionMeta ??
134
163
  initialWorkflowState.activeSessionMeta,
@@ -12,10 +12,13 @@ const initialFormState = {
12
12
  workflowState: "NEW_GROUP_SESSION",
13
13
  groupUuid: null,
14
14
  groupName: null,
15
+ groupMembers: [],
15
16
  activePatientUuid: null,
16
17
  activeEncounterUuid: null,
18
+ activeVisitUuid: null,
17
19
  patientUuids: [],
18
20
  encounters: {},
21
+ visits: {},
19
22
  };
20
23
 
21
24
  const reducer = (state, action) => {
@@ -50,6 +53,8 @@ const reducer = (state, action) => {
50
53
  activePatientUuid: activePatientUuid,
51
54
  activeEncounterUuid:
52
55
  thisSavedForm?.encounters?.[activePatientUuid] || null,
56
+ activeVisitUuid:
57
+ thisSavedForm?.visits?.[activePatientUuid] || null,
53
58
  },
54
59
  },
55
60
  };
@@ -84,8 +89,13 @@ const reducer = (state, action) => {
84
89
  action.group.cohortMembers?.map(
85
90
  (member) => member?.patient?.uuid
86
91
  ) ?? [],
92
+ groupMembers:
93
+ action.group.cohortMembers?.map(
94
+ (member) => member?.patient?.uuid
95
+ ) ?? [],
87
96
  activePatientUuid: null,
88
97
  activeEncounterUuid: null,
98
+ activeVisitUuid: null,
89
99
  },
90
100
  },
91
101
  };
@@ -102,8 +112,10 @@ const reducer = (state, action) => {
102
112
  groupUuid: null,
103
113
  groupName: null,
104
114
  patientUuids: [],
115
+ groupMembers: [],
105
116
  activePatientUuid: null,
106
117
  activeEncounterUuid: null,
118
+ activeVisitUuid: null,
107
119
  },
108
120
  },
109
121
  };
@@ -125,6 +137,10 @@ const reducer = (state, action) => {
125
137
  state.forms[state.activeFormUuid].encounters[
126
138
  state.forms[state.activeFormUuid].patientUuids?.[0]
127
139
  ] || null,
140
+ activeVisitUuid:
141
+ state.forms[state.activeFormUuid].visits[
142
+ state.forms[state.activeFormUuid].patientUuids?.[0]
143
+ ] || null,
128
144
  workflowState: "EDIT_FORM",
129
145
  },
130
146
  },
@@ -132,7 +148,47 @@ const reducer = (state, action) => {
132
148
  persistData(newState);
133
149
  return newState;
134
150
  }
151
+ case "ADD_PATIENT_UUID": {
152
+ if (
153
+ state.forms[state.activeFormUuid].patientUuids.includes(
154
+ action.patientUuid
155
+ )
156
+ ) {
157
+ return state;
158
+ }
135
159
 
160
+ const newState = {
161
+ ...state,
162
+ forms: {
163
+ ...state.forms,
164
+ [state.activeFormUuid]: {
165
+ ...state.forms[state.activeFormUuid],
166
+ patientUuids: [
167
+ ...state.forms[state.activeFormUuid].patientUuids,
168
+ action.patientUuid,
169
+ ],
170
+ },
171
+ },
172
+ };
173
+ persistData(newState);
174
+ return newState;
175
+ }
176
+ case "REMOVE_PATIENT_UUID": {
177
+ const newState = {
178
+ ...state,
179
+ forms: {
180
+ ...state.forms,
181
+ [state.activeFormUuid]: {
182
+ ...state.forms[state.activeFormUuid],
183
+ patientUuids: state.forms[
184
+ state.activeFormUuid
185
+ ].patientUuids?.filter((uuid) => action.patientUuid !== uuid),
186
+ },
187
+ },
188
+ };
189
+ persistData(newState);
190
+ return newState;
191
+ }
136
192
  case "SAVE_ENCOUNTER": {
137
193
  const thisForm = state.forms[state.activeFormUuid];
138
194
  if (thisForm.workflowState === "SUBMIT_FOR_COMPLETE") {
@@ -166,6 +222,7 @@ const reducer = (state, action) => {
166
222
  },
167
223
  activePatientUuid: nextPatientUuid,
168
224
  activeEncounterUuid: thisForm.encounters[nextPatientUuid] || null,
225
+ activeVisitUuid: thisForm.visits[nextPatientUuid] || null,
169
226
  workflowState: "EDIT_FORM",
170
227
  },
171
228
  },
@@ -183,6 +240,8 @@ const reducer = (state, action) => {
183
240
  ...state.forms[state.activeFormUuid],
184
241
  activeEncounterUuid:
185
242
  state.forms[state.activeFormUuid].encounters[action.patientUuid],
243
+ activeVisitUuid:
244
+ state.forms[state.activeFormUuid].visits[action.patientUuid],
186
245
  activePatientUuid: action.patientUuid,
187
246
  workflowState: "EDIT_FORM",
188
247
  },
@@ -191,6 +250,46 @@ const reducer = (state, action) => {
191
250
  persistData(newState);
192
251
  return newState;
193
252
  }
253
+ case "VALIDATE_FOR_NEXT":
254
+ // this state should not be persisted
255
+ window.dispatchEvent(
256
+ new CustomEvent("ampath-form-action", {
257
+ detail: {
258
+ formUuid: state.activeFormUuid,
259
+ patientUuid: state.forms[state.activeFormUuid].activePatientUuid,
260
+ action: "validateForm",
261
+ },
262
+ })
263
+ );
264
+ return {
265
+ ...state,
266
+ forms: {
267
+ ...state.forms,
268
+ [state.activeFormUuid]: {
269
+ ...state.forms[state.activeFormUuid],
270
+ workflowState: "VALIDATE_FOR_NEXT",
271
+ },
272
+ },
273
+ };
274
+ case "UPDATE_VISIT_UUID":
275
+ // this state should not be persisted
276
+ // we don't pers
277
+ return {
278
+ ...state,
279
+ forms: {
280
+ ...state.forms,
281
+ [state.activeFormUuid]: {
282
+ ...state.forms[state.activeFormUuid],
283
+ visits: {
284
+ ...state.forms[state.activeFormUuid].visits,
285
+ [state.forms[state.activeFormUuid].activePatientUuid]:
286
+ action.visitUuid,
287
+ },
288
+ activeVisitUuid: action.visitUuid,
289
+ },
290
+ },
291
+ };
292
+
194
293
  case "SUBMIT_FOR_NEXT":
195
294
  // this state should not be persisted
196
295
  window.dispatchEvent(
@@ -233,6 +332,28 @@ const reducer = (state, action) => {
233
332
  },
234
333
  },
235
334
  };
335
+
336
+ case "VALIDATE_FOR_COMPLETE":
337
+ // this state should not be persisted
338
+ window.dispatchEvent(
339
+ new CustomEvent("ampath-form-action", {
340
+ detail: {
341
+ formUuid: state.activeFormUuid,
342
+ patientUuid: state.forms[state.activeFormUuid].activePatientUuid,
343
+ action: "validateForm",
344
+ },
345
+ })
346
+ );
347
+ return {
348
+ ...state,
349
+ forms: {
350
+ ...state.forms,
351
+ [state.activeFormUuid]: {
352
+ ...state.forms[state.activeFormUuid],
353
+ workflowState: "VALIDATE_FOR_COMPLETE",
354
+ },
355
+ },
356
+ };
236
357
  case "SUBMIT_FOR_COMPLETE":
237
358
  // this state should not be persisted
238
359
  window.dispatchEvent(
@@ -262,6 +383,7 @@ const reducer = (state, action) => {
262
383
  [state.activeFormUuid]: {
263
384
  ...state.forms[state.activeFormUuid],
264
385
  activeEncounterUuid: null,
386
+ activVisitUuid: null,
265
387
  activePatientUuid: null,
266
388
  workflowState: "REVIEW",
267
389
  },
@@ -278,7 +400,9 @@ const reducer = (state, action) => {
278
400
  activeFormUuid: null,
279
401
  };
280
402
  persistData(newState);
281
- return newState;
403
+ //eslint-disable-next-line
404
+ navigate({ to: "${openmrsSpaBase}/forms" });
405
+ return { ...newState, formDestroyed: true };
282
406
  }
283
407
  case "CLOSE_SESSION": {
284
408
  const newState = {
@@ -286,6 +410,8 @@ const reducer = (state, action) => {
286
410
  activeFormUuid: null,
287
411
  };
288
412
  persistData(newState);
413
+ //eslint-disable-next-line
414
+ navigate({ to: "${openmrsSpaBase}/forms" });
289
415
  return newState;
290
416
  }
291
417
  default:
@@ -3,15 +3,8 @@ import {
3
3
  getGlobalStore,
4
4
  useStore,
5
5
  } from "@openmrs/esm-framework";
6
- import {
7
- Button,
8
- ComposedModal,
9
- ModalBody,
10
- ModalFooter,
11
- ModalHeader,
12
- } from "@carbon/react";
6
+ import { Button } from "@carbon/react";
13
7
  import React, { useContext, useState } from "react";
14
- import { useNavigate } from "react-router-dom";
15
8
  import FormBootstrap from "../FormBootstrap";
16
9
  import PatientCard from "../patient-card/PatientCard";
17
10
  import styles from "./styles.scss";
@@ -22,83 +15,15 @@ import FormWorkflowContext, {
22
15
  } from "../context/FormWorkflowContext";
23
16
  import WorkflowReview from "./workflow-review";
24
17
  import PatientBanner from "./patient-banner";
18
+ import CompleteModal from "../CompleteModal";
19
+ import CancelModal from "../CancelModal";
25
20
 
26
21
  const formStore = getGlobalStore("ampath-form-state");
27
22
 
28
- const CancelModal = ({ open, setOpen }) => {
29
- const { destroySession, closeSession } = useContext(FormWorkflowContext);
30
- const { t } = useTranslation();
31
- const navigate = useNavigate();
32
-
33
- const discard = async () => {
34
- await destroySession();
35
- setOpen(false);
36
- navigate("../");
37
- };
38
-
39
- const saveAndClose = async () => {
40
- await closeSession();
41
- setOpen(false);
42
- navigate("../");
43
- };
44
-
45
- return (
46
- <ComposedModal open={open}>
47
- <ModalHeader>{t("areYouSure", "Are you sure?")}</ModalHeader>
48
- <ModalBody>
49
- {t(
50
- "cancelExplanation",
51
- "You will lose any unsaved changes on the current form. Do you want to discard the current session?"
52
- )}
53
- </ModalBody>
54
- <ModalFooter>
55
- <Button kind="secondary" onClick={() => setOpen(false)}>
56
- {t("cancel", "Cancel")}
57
- </Button>
58
- <Button kind="danger" onClick={discard}>
59
- {t("discard", "Discard")}
60
- </Button>
61
- <Button kind="primary" onClick={saveAndClose}>
62
- {t("saveSession", "Save Session")}
63
- </Button>
64
- </ModalFooter>
65
- </ComposedModal>
66
- );
67
- };
68
-
69
- const CompleteModal = ({ open, setOpen }) => {
70
- const { submitForComplete } = useContext(FormWorkflowContext);
71
- const { t } = useTranslation();
72
-
73
- const completeSession = () => {
74
- submitForComplete();
75
- setOpen(false);
76
- };
77
-
78
- return (
79
- <ComposedModal open={open}>
80
- <ModalHeader>{t("areYouSure", "Are you sure?")}</ModalHeader>
81
- <ModalBody>
82
- {t(
83
- "saveExplanation",
84
- "Do you want to save the current form and exit the workflow?"
85
- )}
86
- </ModalBody>
87
- <ModalFooter>
88
- <Button kind="secondary" onClick={() => setOpen(false)}>
89
- {t("cancel", "Cancel")}
90
- </Button>
91
- <Button kind="primary" onClick={completeSession}>
92
- {t("complete", "Complete")}
93
- </Button>
94
- </ModalFooter>
95
- </ComposedModal>
96
- );
97
- };
98
-
99
23
  const WorkflowNavigationButtons = () => {
24
+ const context = useContext(FormWorkflowContext);
100
25
  const { activeFormUuid, submitForNext, workflowState, destroySession } =
101
- useContext(FormWorkflowContext);
26
+ context;
102
27
  const store = useStore(formStore);
103
28
  const formState = store[activeFormUuid];
104
29
  const navigationDisabled = formState !== "ready";
@@ -132,8 +57,16 @@ const WorkflowNavigationButtons = () => {
132
57
  {t("cancel", "Cancel")}
133
58
  </Button>
134
59
  </div>
135
- <CancelModal open={cancelModalOpen} setOpen={setCancelModalOpen} />
136
- <CompleteModal open={completeModalOpen} setOpen={setCompleteModalOpen} />
60
+ <CancelModal
61
+ open={cancelModalOpen}
62
+ setOpen={setCancelModalOpen}
63
+ context={context}
64
+ />
65
+ <CompleteModal
66
+ open={completeModalOpen}
67
+ setOpen={setCompleteModalOpen}
68
+ context={context}
69
+ />
137
70
  </>
138
71
  );
139
72
  };