@openmrs/esm-form-engine-lib 4.2.1-pre.2435 → 4.2.1-pre.2438
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/dist/form-engine.component.js +9 -2
- package/dist/processors/encounter/encounter-processor-helper.js +6 -2
- package/dist/src/form-engine.component.d.ts.map +1 -1
- package/dist/src/processors/encounter/encounter-processor-helper.d.ts.map +1 -1
- package/dist/src/utils/common-utils.d.ts +8 -0
- package/dist/src/utils/common-utils.d.ts.map +1 -1
- package/dist/utils/common-utils.js +16 -0
- package/package.json +1 -1
- package/src/form-engine.component.tsx +6 -2
- package/src/processors/encounter/encounter-processor-helper.ts +15 -2
- package/src/utils/common-utils.ts +19 -1
|
@@ -8,6 +8,7 @@ import { init, teardown } from "./lifecycle.js";
|
|
|
8
8
|
import { isEmpty, useFormJson } from "./index.js";
|
|
9
9
|
import { formEngineAppName } from "./globals.js";
|
|
10
10
|
import { reportError } from "./utils/error-utils.js";
|
|
11
|
+
import { getDateWithinVisitWindow } from "./utils/common-utils.js";
|
|
11
12
|
import { useFormCollapse } from "./hooks/useFormCollapse.js";
|
|
12
13
|
import { useFormWorkspaceSize } from "./hooks/useFormWorkspaceSize.js";
|
|
13
14
|
import { usePageObserver } from "./components/sidebar/usePageObserver.js";
|
|
@@ -22,9 +23,15 @@ const FormEngine = ({ formJson, patientUUID, formUUID, encounterUUID, visit, for
|
|
|
22
23
|
const { t } = useTranslation();
|
|
23
24
|
const session = useSession();
|
|
24
25
|
const ref = useRef(null);
|
|
26
|
+
const rawSessionDate = useRef(new Date());
|
|
27
|
+
// Recompute when the visit bounds arrive or change; the visit prop may not be
|
|
28
|
+
// fully loaded when the form mounts.
|
|
25
29
|
const sessionDate = useMemo(()=>{
|
|
26
|
-
return
|
|
27
|
-
}, [
|
|
30
|
+
return getDateWithinVisitWindow(rawSessionDate.current, visit);
|
|
31
|
+
}, [
|
|
32
|
+
visit?.startDatetime,
|
|
33
|
+
visit?.stopDatetime
|
|
34
|
+
]);
|
|
28
35
|
const workspaceSize = useFormWorkspaceSize(ref);
|
|
29
36
|
const { patient, isLoadingPatient } = usePatientData(patientUUID);
|
|
30
37
|
const [isLoadingDependencies, setIsLoadingDependencies] = useState(false);
|
|
@@ -134,11 +134,15 @@ export function saveAttachments(fields, encounter, abortController) {
|
|
|
134
134
|
return Promise.all(allPromises);
|
|
135
135
|
}
|
|
136
136
|
export function getMutableSessionProps(context) {
|
|
137
|
-
const { formFields, location, currentProvider, customDependencies, domainObjectValue: encounter } = context;
|
|
137
|
+
const { formFields, location, currentProvider, customDependencies, sessionDate, domainObjectValue: encounter } = context;
|
|
138
138
|
const { defaultEncounterRole } = customDependencies;
|
|
139
139
|
const encounterRole = formFields.find((field)=>field.type === 'encounterRole')?.meta.submission?.newValue || defaultEncounterRole?.uuid;
|
|
140
140
|
const encounterProvider = formFields.find((field)=>field.type === 'encounterProvider')?.meta.submission?.newValue || currentProvider.uuid;
|
|
141
|
-
const
|
|
141
|
+
const explicitEncounterDate = formFields.find((field)=>field.type === 'encounterDatetime')?.meta.submission?.newValue;
|
|
142
|
+
// Always submit an explicit datetime for new encounters; if it is omitted, the backend
|
|
143
|
+
// defaults it to "now", which fails validation when saving into a past (stopped) visit.
|
|
144
|
+
// `sessionDate` is already constrained to the visit window.
|
|
145
|
+
const encounterDate = explicitEncounterDate ?? (encounter?.encounterDatetime ? new Date(encounter.encounterDatetime) : sessionDate);
|
|
142
146
|
const encounterLocation = formFields.find((field)=>field.type === 'encounterLocation')?.meta.submission?.newValue || encounter?.location?.uuid || location.uuid;
|
|
143
147
|
return {
|
|
144
148
|
encounterRole: encounterRole,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-engine.component.d.ts","sourceRoot":"","sources":["../../src/form-engine.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAIjF,OAAO,EAAc,KAAK,KAAK,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"form-engine.component.d.ts","sourceRoot":"","sources":["../../src/form-engine.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAIjF,OAAO,EAAc,KAAK,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAWhE,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAQtF,UAAU,eAAe;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,6BAA6B,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjF,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC;AAkLD,iBAAS,aAAa,CAAC,KAAK,EAAE,eAAe,qBAM5C;AAED,eAAe,aAAa,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encounter-processor-helper.d.ts","sourceRoot":"","sources":["../../../../src/processors/encounter/encounter-processor-helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,yBAAyB,EAC9B,KAAK,gBAAgB,EAErB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACrB,MAAM,aAAa,CAAC;AAKrB,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAQrE,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,gBAAgB,EACzB,aAAa,EAAE,IAAI,EACnB,aAAa,EAAE,MAAM,EACrB,iBAAiB,EAAE,MAAM,EACzB,QAAQ,EAAE,MAAM,oBA6DjB;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,iBAAiB,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAI7G;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,4DAI7F;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,eAAe,EAAE,CAI9E;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,4DAIxF;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,SAAS,EAAE,EACnB,OAAO,EAAE,IAAI,CAAC,OAAO,EACrB,sBAAsB,EAAE,KAAK,CAAC,cAAc,CAAC,GAC5C,KAAK,CAAC,qBAAqB,CAAC,CA+B9B;AAED,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,qBAAqB,EAAE,4DAG3E;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,oEAcjH;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,gBAAgB;
|
|
1
|
+
{"version":3,"file":"encounter-processor-helper.d.ts","sourceRoot":"","sources":["../../../../src/processors/encounter/encounter-processor-helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,yBAAyB,EAC9B,KAAK,gBAAgB,EAErB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACrB,MAAM,aAAa,CAAC;AAKrB,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAQrE,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,gBAAgB,EACzB,aAAa,EAAE,IAAI,EACnB,aAAa,EAAE,MAAM,EACrB,iBAAiB,EAAE,MAAM,EACzB,QAAQ,EAAE,MAAM,oBA6DjB;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,iBAAiB,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAI7G;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,4DAI7F;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,eAAe,EAAE,CAI9E;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,4DAIxF;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,SAAS,EAAE,EACnB,OAAO,EAAE,IAAI,CAAC,OAAO,EACrB,sBAAsB,EAAE,KAAK,CAAC,cAAc,CAAC,GAC5C,KAAK,CAAC,qBAAqB,CAAC,CA+B9B;AAED,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,qBAAqB,EAAE,4DAG3E;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,oEAcjH;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,gBAAgB;mBA0B5B,MAAM;uBACE,MAAM;mBACd,IAAI;uBACI,MAAM;EAEjD;AA4FD,wBAAgB,sCAAsC,CAAC,KAAK,EAAE,SAAS,OAetE;AAED,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,SAAS,EAChB,SAAS,EAAE,gBAAgB,EAC3B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAClC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,SAAS,EAAE,CAAC,CAwEtB"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type FormSchema, type FormField, type OpenmrsObs, type RenderType } from '../types';
|
|
2
|
+
import { type Visit } from '@openmrs/esm-framework';
|
|
2
3
|
export declare function flattenObsList(obsList: OpenmrsObs[]): OpenmrsObs[];
|
|
3
4
|
export declare function hasRendering(field: FormField, rendering: RenderType): boolean;
|
|
4
5
|
export declare function clearSubmission(field: FormField): void;
|
|
@@ -6,6 +7,13 @@ export declare function gracefullySetSubmission(field: FormField, newValue: any,
|
|
|
6
7
|
export declare function hasSubmission(field: FormField): boolean;
|
|
7
8
|
export declare function isViewMode(sessionMode: string): sessionMode is "view" | "embedded-view";
|
|
8
9
|
export declare function parseToLocalDateTime(dateString: string): Date;
|
|
10
|
+
/**
|
|
11
|
+
* Returns `date` if it falls within the visit's start/stop window, otherwise the
|
|
12
|
+
* visit's start datetime. This keeps default encounter datetimes valid when filling
|
|
13
|
+
* forms against a past (stopped) visit via retrospective data entry; the backend
|
|
14
|
+
* rejects encounters dated outside the visit window.
|
|
15
|
+
*/
|
|
16
|
+
export declare function getDateWithinVisitWindow(date: Date, visit?: Visit): Date;
|
|
9
17
|
export declare function formatDateAsDisplayString(field: FormField, date: Date): string;
|
|
10
18
|
/**
|
|
11
19
|
* Creates a new copy of `formJson` with updated references at the page and section levels.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common-utils.d.ts","sourceRoot":"","sources":["../../../src/utils/common-utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"common-utils.d.ts","sourceRoot":"","sources":["../../../src/utils/common-utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAE7F,OAAO,EAAsC,KAAK,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAExF,wBAAgB,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAgBlE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,WAEnE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,QAS/C;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,OAWxF;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,WAE7C;AAED,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,2CAE7C;AAED,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAgB7D;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAUxE;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,UAQrE;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,UAAU;;;;;;;;;;;;;;;eAjG5C,CAAC;cACd,CAAC;;;;;;;;gBAWD,CAAC;4BAA0B,CAAC;;;;EA2FlC;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAW,UAExD"}
|
|
@@ -69,6 +69,22 @@ export function parseToLocalDateTime(dateString) {
|
|
|
69
69
|
}
|
|
70
70
|
return dateObj;
|
|
71
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Returns `date` if it falls within the visit's start/stop window, otherwise the
|
|
74
|
+
* visit's start datetime. This keeps default encounter datetimes valid when filling
|
|
75
|
+
* forms against a past (stopped) visit via retrospective data entry; the backend
|
|
76
|
+
* rejects encounters dated outside the visit window.
|
|
77
|
+
*/ export function getDateWithinVisitWindow(date, visit) {
|
|
78
|
+
if (!visit) {
|
|
79
|
+
return date;
|
|
80
|
+
}
|
|
81
|
+
const visitStart = visit.startDatetime ? new Date(visit.startDatetime) : null;
|
|
82
|
+
const visitStop = visit.stopDatetime ? new Date(visit.stopDatetime) : null;
|
|
83
|
+
if (visitStart && date < visitStart || visitStop && date > visitStop) {
|
|
84
|
+
return visitStart ?? visitStop;
|
|
85
|
+
}
|
|
86
|
+
return date;
|
|
87
|
+
}
|
|
72
88
|
export function formatDateAsDisplayString(field, date) {
|
|
73
89
|
const options = {
|
|
74
90
|
noToday: true
|
package/package.json
CHANGED
|
@@ -8,6 +8,7 @@ import { init, teardown } from './lifecycle';
|
|
|
8
8
|
import { isEmpty, useFormJson } from '.';
|
|
9
9
|
import { formEngineAppName } from './globals';
|
|
10
10
|
import { reportError } from './utils/error-utils';
|
|
11
|
+
import { getDateWithinVisitWindow } from './utils/common-utils';
|
|
11
12
|
import { useFormCollapse } from './hooks/useFormCollapse';
|
|
12
13
|
import { useFormWorkspaceSize } from './hooks/useFormWorkspaceSize';
|
|
13
14
|
import { usePageObserver } from './components/sidebar/usePageObserver';
|
|
@@ -58,9 +59,12 @@ const FormEngine = ({
|
|
|
58
59
|
const { t } = useTranslation();
|
|
59
60
|
const session = useSession();
|
|
60
61
|
const ref = useRef(null);
|
|
62
|
+
const rawSessionDate = useRef(new Date());
|
|
63
|
+
// Recompute when the visit bounds arrive or change; the visit prop may not be
|
|
64
|
+
// fully loaded when the form mounts.
|
|
61
65
|
const sessionDate = useMemo(() => {
|
|
62
|
-
return
|
|
63
|
-
}, []);
|
|
66
|
+
return getDateWithinVisitWindow(rawSessionDate.current, visit);
|
|
67
|
+
}, [visit?.startDatetime, visit?.stopDatetime]);
|
|
64
68
|
const workspaceSize = useFormWorkspaceSize(ref);
|
|
65
69
|
const { patient, isLoadingPatient } = usePatientData(patientUUID);
|
|
66
70
|
const [isLoadingDependencies, setIsLoadingDependencies] = useState(false);
|
|
@@ -172,13 +172,26 @@ export function saveAttachments(fields: FormField[], encounter: OpenmrsEncounter
|
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
export function getMutableSessionProps(context: FormContextProps) {
|
|
175
|
-
const {
|
|
175
|
+
const {
|
|
176
|
+
formFields,
|
|
177
|
+
location,
|
|
178
|
+
currentProvider,
|
|
179
|
+
customDependencies,
|
|
180
|
+
sessionDate,
|
|
181
|
+
domainObjectValue: encounter,
|
|
182
|
+
} = context;
|
|
176
183
|
const { defaultEncounterRole } = customDependencies;
|
|
177
184
|
const encounterRole =
|
|
178
185
|
formFields.find((field) => field.type === 'encounterRole')?.meta.submission?.newValue || defaultEncounterRole?.uuid;
|
|
179
186
|
const encounterProvider =
|
|
180
187
|
formFields.find((field) => field.type === 'encounterProvider')?.meta.submission?.newValue || currentProvider.uuid;
|
|
181
|
-
const
|
|
188
|
+
const explicitEncounterDate = formFields.find((field) => field.type === 'encounterDatetime')?.meta.submission
|
|
189
|
+
?.newValue;
|
|
190
|
+
// Always submit an explicit datetime for new encounters; if it is omitted, the backend
|
|
191
|
+
// defaults it to "now", which fails validation when saving into a past (stopped) visit.
|
|
192
|
+
// `sessionDate` is already constrained to the visit window.
|
|
193
|
+
const encounterDate =
|
|
194
|
+
explicitEncounterDate ?? (encounter?.encounterDatetime ? new Date(encounter.encounterDatetime) : sessionDate);
|
|
182
195
|
const encounterLocation =
|
|
183
196
|
formFields.find((field) => field.type === 'encounterLocation')?.meta.submission?.newValue ||
|
|
184
197
|
encounter?.location?.uuid ||
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import dayjs from 'dayjs';
|
|
2
2
|
import { type FormSchema, type FormField, type OpenmrsObs, type RenderType } from '../types';
|
|
3
3
|
import { isEmpty } from '../validators/form-validator';
|
|
4
|
-
import { formatDate, type FormatDateOptions } from '@openmrs/esm-framework';
|
|
4
|
+
import { formatDate, type FormatDateOptions, type Visit } from '@openmrs/esm-framework';
|
|
5
5
|
|
|
6
6
|
export function flattenObsList(obsList: OpenmrsObs[]): OpenmrsObs[] {
|
|
7
7
|
const flattenedList: OpenmrsObs[] = [];
|
|
@@ -75,6 +75,24 @@ export function parseToLocalDateTime(dateString: string): Date {
|
|
|
75
75
|
return dateObj;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Returns `date` if it falls within the visit's start/stop window, otherwise the
|
|
80
|
+
* visit's start datetime. This keeps default encounter datetimes valid when filling
|
|
81
|
+
* forms against a past (stopped) visit via retrospective data entry; the backend
|
|
82
|
+
* rejects encounters dated outside the visit window.
|
|
83
|
+
*/
|
|
84
|
+
export function getDateWithinVisitWindow(date: Date, visit?: Visit): Date {
|
|
85
|
+
if (!visit) {
|
|
86
|
+
return date;
|
|
87
|
+
}
|
|
88
|
+
const visitStart = visit.startDatetime ? new Date(visit.startDatetime) : null;
|
|
89
|
+
const visitStop = visit.stopDatetime ? new Date(visit.stopDatetime) : null;
|
|
90
|
+
if ((visitStart && date < visitStart) || (visitStop && date > visitStop)) {
|
|
91
|
+
return visitStart ?? visitStop;
|
|
92
|
+
}
|
|
93
|
+
return date;
|
|
94
|
+
}
|
|
95
|
+
|
|
78
96
|
export function formatDateAsDisplayString(field: FormField, date: Date) {
|
|
79
97
|
const options: Partial<FormatDateOptions> = { noToday: true };
|
|
80
98
|
if (field.datePickerFormat === 'calendar') {
|