@openmrs/esm-fast-data-entry-app 1.0.1-pre.8 → 1.0.1-pre.85

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 (86) hide show
  1. package/README.md +21 -2
  2. package/dist/132.js +1 -0
  3. package/dist/168.js +1 -0
  4. package/dist/229.js +1 -0
  5. package/dist/247.js +1 -0
  6. package/dist/255.js +1 -0
  7. package/dist/294.js +2 -0
  8. package/dist/294.js.LICENSE.txt +9 -0
  9. package/dist/32.js +1 -0
  10. package/dist/327.js +1 -0
  11. package/dist/403.js +2 -0
  12. package/dist/403.js.LICENSE.txt +14 -0
  13. package/dist/553.js +2 -0
  14. package/dist/553.js.LICENSE.txt +14 -0
  15. package/dist/574.js +1 -0
  16. package/dist/595.js +2 -0
  17. package/dist/595.js.LICENSE.txt +3 -0
  18. package/dist/617.js +1 -0
  19. package/dist/658.js +2 -0
  20. package/dist/658.js.LICENSE.txt +27 -0
  21. package/dist/68.js +2 -0
  22. package/dist/68.js.LICENSE.txt +21 -0
  23. package/dist/74.js +1 -0
  24. package/dist/757.js +1 -0
  25. package/dist/776.js +1 -0
  26. package/dist/804.js +1 -0
  27. package/dist/820.js +1 -0
  28. package/dist/935.js +2 -0
  29. package/dist/935.js.LICENSE.txt +19 -0
  30. package/dist/main.js +1 -0
  31. package/dist/openmrs-esm-fast-data-entry-app.js +1 -1
  32. package/dist/openmrs-esm-fast-data-entry-app.js.buildmanifest.json +612 -0
  33. package/dist/openmrs-esm-fast-data-entry-app.old +1 -0
  34. package/jest.config.json +2 -1
  35. package/package.json +9 -9
  36. package/src/CancelModal.tsx +48 -0
  37. package/src/CompleteModal.tsx +46 -0
  38. package/src/FormBootstrap.tsx +18 -3
  39. package/src/add-group-modal/AddGroupModal.tsx +80 -27
  40. package/src/add-group-modal/styles.scss +14 -4
  41. package/src/config-schema.ts +22 -0
  42. package/src/context/FormWorkflowContext.tsx +13 -1
  43. package/src/context/FormWorkflowReducer.ts +13 -3
  44. package/src/context/GroupFormWorkflowContext.tsx +41 -6
  45. package/src/context/GroupFormWorkflowReducer.ts +170 -12
  46. package/src/form-entry-workflow/FormEntryWorkflow.tsx +67 -101
  47. package/src/form-entry-workflow/styles.scss +2 -1
  48. package/src/forms-page/FormsPage.tsx +8 -3
  49. package/src/forms-page/forms-table/FormsTable.tsx +11 -5
  50. package/src/group-form-entry-workflow/GroupFormEntryWorkflow.tsx +13 -400
  51. package/src/group-form-entry-workflow/GroupSessionWorkspace.tsx +247 -0
  52. package/src/group-form-entry-workflow/SessionDetailsForm.tsx +122 -0
  53. package/src/group-form-entry-workflow/SessionMetaWorkspace.tsx +107 -0
  54. package/src/group-form-entry-workflow/attendance-table/AttendanceTable.tsx +105 -0
  55. package/src/group-form-entry-workflow/attendance-table/index.ts +1 -0
  56. package/src/group-form-entry-workflow/{group-banner/GroupBanner.test.tsx → group-display-header/GroupDisplayHeader.test.tsx} +2 -2
  57. package/src/group-form-entry-workflow/{group-banner/GroupBanner.tsx → group-display-header/GroupDisplayHeader.tsx} +23 -5
  58. package/src/group-form-entry-workflow/group-display-header/index.ts +3 -0
  59. package/src/group-form-entry-workflow/group-search/CompactGroupResults.tsx +61 -28
  60. package/src/group-form-entry-workflow/group-search/CompactGroupSearch.tsx +5 -0
  61. package/src/group-form-entry-workflow/group-search/GroupSearch.tsx +65 -8
  62. package/src/group-form-entry-workflow/group-search/group-search.scss +8 -6
  63. package/src/group-form-entry-workflow/group-search-header/GroupSearchHeader.tsx +11 -7
  64. package/src/group-form-entry-workflow/styles.scss +12 -1
  65. package/src/hooks/index.ts +1 -0
  66. package/src/hooks/useGetPatient.ts +1 -1
  67. package/src/hooks/useGetSystemSetting.ts +38 -0
  68. package/src/hooks/usePostEndpoint.ts +70 -0
  69. package/src/hooks/useSearchEndpoint.ts +120 -0
  70. package/src/hooks/useStartVisit.ts +92 -0
  71. package/src/patient-card/styles.scss +1 -0
  72. package/tools/i18next-parser.config.js +93 -0
  73. package/translations/en.json +27 -9
  74. package/translations/fr.json +50 -0
  75. package/.editorconfig +0 -12
  76. package/.eslintignore +0 -2
  77. package/.eslintrc.js +0 -10
  78. package/.husky/pre-push +0 -1
  79. package/.prettierignore +0 -14
  80. package/.yarn/plugins/@yarnpkg/plugin-version.cjs +0 -550
  81. package/.yarn/versions/7ee3eceb.yml +0 -0
  82. package/src/group-form-entry-workflow/group-banner/index.ts +0 -3
  83. package/src/group-form-entry-workflow/group-search/mock-group-data.ts +0 -79
  84. package/src/group-form-entry-workflow/group-search/useGroupSearch.ts +0 -14
  85. package/src/hooks/usePostCohort.ts +0 -18
  86. /package/src/group-form-entry-workflow/{group-banner → group-display-header}/styles.scss +0 -0
package/jest.config.json CHANGED
@@ -8,7 +8,8 @@
8
8
  "\\.(s?css)$": "identity-obj-proxy",
9
9
  "@openmrs/esm-framework": "@openmrs/esm-framework/mock",
10
10
  "^lodash-es/(.*)$": "lodash/$1",
11
- "^uuid$": "<rootDir>/node_modules/uuid/dist/index.js"
11
+ "^uuid$": "<rootDir>/node_modules/uuid/dist/index.js",
12
+ "^dexie$": "<rootDir>/node_modules/dexie"
12
13
  },
13
14
  "setupFilesAfterEnv": [
14
15
  "<rootDir>/src/setup-tests.ts"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openmrs/esm-fast-data-entry-app",
3
- "version": "1.0.1-pre.8",
3
+ "version": "1.0.1-pre.85",
4
4
  "license": "MPL-2.0",
5
5
  "description": "An OpenMRS 3.x microfrontend",
6
6
  "browser": "dist/openmrs-esm-fast-data-entry-app.js",
@@ -17,12 +17,8 @@
17
17
  "test": "jest --config jest.config.json --passWithNoTests",
18
18
  "verify": "concurrently 'yarn:lint' 'yarn:test' 'yarn:typescript'",
19
19
  "coverage": "yarn test -- --coverage ",
20
- "prepare": "husky install"
21
- },
22
- "husky": {
23
- "hooks": {
24
- "pre-commit": "pretty-quick --staged && yarn verify"
25
- }
20
+ "postinstall": "husky install",
21
+ "extract-translations": "i18next 'src/**/*.tsx' --config ./tools/i18next-parser.config.js"
26
22
  },
27
23
  "browserslist": [
28
24
  "extends browserslist-config-openmrs"
@@ -45,6 +41,7 @@
45
41
  "peerDependencies": {
46
42
  "@carbon/react": "^1.9.0",
47
43
  "@openmrs/esm-framework": "*",
44
+ "lodash-es": "4.x",
48
45
  "react": "18.x",
49
46
  "react-dom": "18.x",
50
47
  "react-i18next": "11.x",
@@ -76,6 +73,7 @@
76
73
  "jest": "^28.1.3",
77
74
  "jest-cli": "^28.1.3",
78
75
  "jest-environment-jsdom": "^28.1.3",
76
+ "lodash-es": "^4.17.21",
79
77
  "openmrs": "next",
80
78
  "prettier": "^2.3.0",
81
79
  "pretty-quick": "^3.1.0",
@@ -85,13 +83,15 @@
85
83
  "react-router-dom": "^6.3.0",
86
84
  "semver": "^7.3.7",
87
85
  "swc-loader": "^0.2.3",
88
- "swr": "^1.3.0",
89
86
  "typescript": "^4.7.3",
90
87
  "webpack": "^5.73.0"
91
88
  },
92
89
  "packageManager": "yarn@3.2.2",
93
90
  "dependencies": {
94
- "react-hook-form": "^7.34.2"
91
+ "i18next": "^21.10.0",
92
+ "i18next-parser": "^6.6.0",
93
+ "react-hook-form": "^7.34.2",
94
+ "swr": "1.1.2"
95
95
  },
96
96
  "stableVersion": "1.0.0"
97
97
  }
@@ -0,0 +1,48 @@
1
+ import {
2
+ Button,
3
+ ComposedModal,
4
+ ModalBody,
5
+ ModalFooter,
6
+ ModalHeader,
7
+ } from "@carbon/react";
8
+ import React from "react";
9
+ import { useTranslation } from "react-i18next";
10
+
11
+ const CancelModal = ({ open, setOpen, context }) => {
12
+ const { t } = useTranslation();
13
+
14
+ const onCancel = () => setOpen(false);
15
+
16
+ const onDiscard = async () => {
17
+ await context.destroySession();
18
+ };
19
+
20
+ const onSaveAndClose = async () => {
21
+ await context.closeSession();
22
+ };
23
+
24
+ return (
25
+ <ComposedModal open={open}>
26
+ <ModalHeader>{t("areYouSure", "Are you sure?")}</ModalHeader>
27
+ <ModalBody>
28
+ {t(
29
+ "cancelExplanation",
30
+ "You will lose any unsaved changes on the current form. Do you want to discard the current session?"
31
+ )}
32
+ </ModalBody>
33
+ <ModalFooter>
34
+ <Button kind="secondary" onClick={onCancel}>
35
+ {t("cancel", "Cancel")}
36
+ </Button>
37
+ <Button kind="danger" onClick={onDiscard}>
38
+ {t("discard", "Discard")}
39
+ </Button>
40
+ <Button kind="primary" onClick={onSaveAndClose}>
41
+ {t("saveSession", "Save Session")}
42
+ </Button>
43
+ </ModalFooter>
44
+ </ComposedModal>
45
+ );
46
+ };
47
+
48
+ export default CancelModal;
@@ -0,0 +1,46 @@
1
+ import {
2
+ Button,
3
+ ComposedModal,
4
+ ModalBody,
5
+ ModalFooter,
6
+ ModalHeader,
7
+ } from "@carbon/react";
8
+ import React from "react";
9
+ import { useTranslation } from "react-i18next";
10
+
11
+ const CompleteModal = ({ open, setOpen, context, validateFirst = false }) => {
12
+ const { t } = useTranslation();
13
+
14
+ const onCancel = () => setOpen(false);
15
+
16
+ const onComplete = () => {
17
+ if (validateFirst) {
18
+ context.validateForComplete();
19
+ } else {
20
+ context.submitForComplete();
21
+ }
22
+ setOpen(false);
23
+ };
24
+
25
+ return (
26
+ <ComposedModal open={open}>
27
+ <ModalHeader>{t("areYouSure", "Are you sure?")}</ModalHeader>
28
+ <ModalBody>
29
+ {t(
30
+ "saveExplanation",
31
+ "Do you want to save the current form and exit the workflow?"
32
+ )}
33
+ </ModalBody>
34
+ <ModalFooter>
35
+ <Button kind="secondary" onClick={onCancel}>
36
+ {t("cancel", "Cancel")}
37
+ </Button>
38
+ <Button kind="primary" onClick={onComplete}>
39
+ {t("complete", "Complete")}
40
+ </Button>
41
+ </ModalFooter>
42
+ </ComposedModal>
43
+ );
44
+ };
45
+
46
+ export default CompleteModal;
@@ -1,4 +1,4 @@
1
- import React, { useEffect } from "react";
1
+ import React, { useEffect, useState } from "react";
2
2
  import { detach, ExtensionSlot } from "@openmrs/esm-framework";
3
3
  import useGetPatient from "./hooks/useGetPatient";
4
4
 
@@ -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
 
@@ -124,11 +126,23 @@ const FormBootstrap = ({
124
126
  return () => detach("form-widget-slot", "form-widget-slot");
125
127
  });
126
128
 
129
+ // FIXME This should not be necessary
130
+ const [showForm, setShowForm] = useState(true);
131
+
132
+ useEffect(() => {
133
+ if (patientUuid && formUuid && patient) {
134
+ setShowForm(false);
135
+ setTimeout(() => {
136
+ setShowForm(true);
137
+ });
138
+ }
139
+ }, [patientUuid, formUuid, patient]);
140
+
127
141
  return (
128
142
  <div>
129
- {formUuid && patientUuid && patient && (
143
+ {showForm && formUuid && patientUuid && patient && (
130
144
  <ExtensionSlot
131
- extensionSlotName="form-widget-slot"
145
+ name="form-widget-slot"
132
146
  state={{
133
147
  view: "form",
134
148
  formUuid,
@@ -140,6 +154,7 @@ const FormBootstrap = ({
140
154
  closeWorkspace: () => undefined,
141
155
  handlePostResponse,
142
156
  handleEncounterCreate,
157
+ handleOnValidate,
143
158
  showDiscardSubmitButtons: false,
144
159
  }}
145
160
  />
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useContext, useState } from "react";
1
+ import React, { useCallback, useContext, useEffect, useState } from "react";
2
2
  import {
3
3
  ComposedModal,
4
4
  Button,
@@ -7,12 +7,14 @@ import {
7
7
  ModalBody,
8
8
  TextInput,
9
9
  FormLabel,
10
+ Loading,
10
11
  } from "@carbon/react";
11
- import { Add, Close } from "@carbon/react/icons";
12
+ import { Add, TrashCan } from "@carbon/react/icons";
12
13
  import { useTranslation } from "react-i18next";
13
- import { ExtensionSlot } from "@openmrs/esm-framework";
14
+ import { ExtensionSlot, showToast } from "@openmrs/esm-framework";
14
15
  import styles from "./styles.scss";
15
16
  import GroupFormWorkflowContext from "../context/GroupFormWorkflowContext";
17
+ import { usePostCohort } from "../hooks";
16
18
 
17
19
  const MemExtension = React.memo(ExtensionSlot);
18
20
 
@@ -20,18 +22,19 @@ const PatientRow = ({ patient, removePatient }) => {
20
22
  const { t } = useTranslation();
21
23
  return (
22
24
  <li key={patient.uuid} className={styles.patientRow}>
23
- <span className={styles.patientName}>{patient?.display}</span>
24
25
  <span>
25
26
  <Button
26
27
  kind="tertiary"
27
28
  size="sm"
29
+ hasIconOnly
28
30
  onClick={() => removePatient(patient.uuid)}
29
- renderIcon={Close}
30
- tooltipPosition="right"
31
- >
32
- {t("remove", "Remove")}
33
- </Button>
31
+ renderIcon={TrashCan}
32
+ tooltipAlignment="start"
33
+ tooltipPosition="top"
34
+ iconDescription={t("remove", "Remove")}
35
+ />
34
36
  </span>
37
+ <span className={styles.patientName}>{patient?.display}</span>
35
38
  </li>
36
39
  );
37
40
  };
@@ -64,17 +67,21 @@ const NewGroupForm = (props) => {
64
67
  />
65
68
  {errors?.name && (
66
69
  <p className={styles.formError}>
67
- {t("groupNameError", "Please enter a group name.")}
70
+ {errors.name === "required"
71
+ ? t("groupNameError", "Please enter a group name.")
72
+ : errors.name}
68
73
  </p>
69
74
  )}
70
- <FormLabel>Patients in group</FormLabel>
75
+ <FormLabel>
76
+ {patientList.length} {t("patientsInGroup", "Patients in group")}
77
+ </FormLabel>
71
78
  {errors?.patientList && (
72
79
  <p className={styles.formError}>
73
80
  {t("noPatientError", "Please enter at least one patient.")}
74
81
  </p>
75
82
  )}
76
83
  {!errors?.patientList && (
77
- <ul>
84
+ <ul className={styles.patientList}>
78
85
  {patientList?.map((patient, index) => (
79
86
  <PatientRow
80
87
  patient={patient}
@@ -92,7 +99,7 @@ const NewGroupForm = (props) => {
92
99
  state={{
93
100
  selectPatientAction: updatePatientList,
94
101
  buttonProps: {
95
- kind: "primary",
102
+ kind: "secondary",
96
103
  },
97
104
  }}
98
105
  />
@@ -108,6 +115,7 @@ const AddGroupModal = () => {
108
115
  const [errors, setErrors] = useState({});
109
116
  const [name, setName] = useState("");
110
117
  const [patientList, setPatientList] = useState([]);
118
+ const { post, result, isPosting, error } = usePostCohort();
111
119
 
112
120
  const handleCancel = () => {
113
121
  setOpen(false);
@@ -165,10 +173,46 @@ const AddGroupModal = () => {
165
173
 
166
174
  const handleSubmit = () => {
167
175
  if (validate()) {
168
- setGroup({ id: "1234", name: name, members: patientList });
176
+ post({
177
+ name: name,
178
+ cohortMembers: patientList.map((p) => ({ patient: p.uuid })),
179
+ });
169
180
  }
170
181
  };
171
182
 
183
+ useEffect(() => {
184
+ if (result) {
185
+ setGroup({
186
+ ...result,
187
+ // the result doesn't come with cohortMembers.
188
+ // need to add it in based on our local state
189
+ cohortMembers: patientList.map((p) => ({ patient: { uuid: p.uuid } })),
190
+ });
191
+ }
192
+ }, [result, setGroup, patientList]);
193
+
194
+ useEffect(() => {
195
+ if (error) {
196
+ showToast({
197
+ kind: "error",
198
+ title: t("postError", "POST Error"),
199
+ description:
200
+ error.message ??
201
+ t("unknownPostError", "An unknown error occured while saving data"),
202
+ });
203
+ if (error.fieldErrors) {
204
+ setErrors(
205
+ Object.fromEntries(
206
+ Object.entries(error.fieldErrors).map(([key, value]) => [
207
+ key,
208
+ value?.[0]?.message,
209
+ ])
210
+ )
211
+ );
212
+ }
213
+ }
214
+ }, [error, t]);
215
+
172
216
  return (
173
217
  <div className={styles.modal}>
174
218
  <Button
@@ -181,23 +225,32 @@ const AddGroupModal = () => {
181
225
  <ComposedModal open={open} onClose={() => setOpen(false)}>
182
226
  <ModalHeader>{t("createNewGroup", "Create New Group")}</ModalHeader>
183
227
  <ModalBody>
184
- <NewGroupForm
185
- {...{
186
- name,
187
- setName,
188
- patientList,
189
- updatePatientList,
190
- errors,
191
- validate,
192
- removePatient,
193
- }}
194
- />
228
+ {result ? (
229
+ <p>Group saved succesfully</p>
230
+ ) : isPosting ? (
231
+ <div className={styles.loading}>
232
+ <Loading withOverlay={false} />
233
+ <span>Saving new group...</span>
234
+ </div>
235
+ ) : (
236
+ <NewGroupForm
237
+ {...{
238
+ name,
239
+ setName,
240
+ patientList,
241
+ updatePatientList,
242
+ errors,
243
+ validate,
244
+ removePatient,
245
+ }}
246
+ />
247
+ )}
195
248
  </ModalBody>
196
249
  <ModalFooter>
197
- <Button kind="secondary" onClick={handleCancel}>
250
+ <Button kind="secondary" onClick={handleCancel} disabled={isPosting}>
198
251
  {t("cancel", "Cancel")}
199
252
  </Button>
200
- <Button kind="primary" onClick={handleSubmit}>
253
+ <Button kind="primary" onClick={handleSubmit} disabled={isPosting}>
201
254
  {t("createGroup", "Create Group")}
202
255
  </Button>
203
256
  </ModalFooter>
@@ -23,13 +23,23 @@
23
23
 
24
24
  .patientRow {
25
25
  display: flex;
26
+ align-items: center;
26
27
  width: "100%";
28
+ &:nth-child(odd) {
29
+ background-color: colors.$gray-20;
30
+ }
27
31
  }
28
32
 
29
33
  .patientName {
30
34
  flex-grow: 1;
31
- padding: spacing.$spacing-02;
32
- &:hover {
33
- background-color: colors.$gray-20;
34
- }
35
+ padding-left: spacing.$spacing-05;
36
+ }
37
+
38
+ .loading {
39
+ display: flex;
40
+ height: 100%;
41
+ flex-direction: column;
42
+ justify-content: center;
43
+ align-items: center;
44
+ row-gap: spacing.$spacing-05;
35
45
  }
@@ -60,6 +60,28 @@ 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
+ },
63
85
  };
64
86
 
65
87
  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.13";
4
+ export const fdeWorkflowStorageVersion = "1.1.0";
5
5
  export const fdeWorkflowStorageName = "openmrs:fastDataEntryWorkflowState";
6
6
  const persistData = (data) => {
7
- localStorage.setItem(fdeWorkflowStorageName, JSON.stringify(data));
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(fdeWorkflowStorageName);
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: