@openmrs/esm-form-engine-lib 4.2.2-pre.2543 → 4.2.2-pre.2550
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/components/processor-factory/form-processor-factory.component.js +111 -39
- package/dist/components/renderer/custom-hooks-renderer.component.js +2 -2
- package/dist/form-engine.component.js +5 -3
- package/dist/hooks/useFormFieldValidators.js +22 -12
- package/dist/hooks/useFormFieldValueAdapters.js +22 -15
- package/dist/hooks/useFormFields.js +35 -42
- package/dist/hooks/useInitialValues.js +12 -5
- package/dist/hooks/useProcessorDependencies.js +2 -2
- package/dist/processors/encounter/encounter-form-processor.js +10 -20
- package/dist/processors/form-processor.js +4 -1
- package/dist/src/components/processor-factory/form-processor-factory.component.d.ts.map +1 -1
- package/dist/src/components/renderer/custom-hooks-renderer.component.d.ts +5 -8
- package/dist/src/components/renderer/custom-hooks-renderer.component.d.ts.map +1 -1
- package/dist/src/form-engine.component.d.ts.map +1 -1
- package/dist/src/hooks/useFormFieldValidators.d.ts.map +1 -1
- package/dist/src/hooks/useFormFieldValueAdapters.d.ts.map +1 -1
- package/dist/src/hooks/useFormFields.d.ts.map +1 -1
- package/dist/src/hooks/useInitialValues.d.ts.map +1 -1
- package/dist/src/hooks/useProcessorDependencies.d.ts +2 -2
- package/dist/src/hooks/useProcessorDependencies.d.ts.map +1 -1
- package/dist/src/processors/encounter/encounter-form-processor.d.ts +6 -3
- package/dist/src/processors/encounter/encounter-form-processor.d.ts.map +1 -1
- package/dist/src/processors/form-processor.d.ts +21 -2
- package/dist/src/processors/form-processor.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/processor-factory/form-processor-factory.component.tsx +151 -35
- package/src/components/renderer/custom-hooks-renderer.component.tsx +6 -8
- package/src/form-engine.component.tsx +6 -4
- package/src/hooks/useFormFieldValidators.ts +23 -13
- package/src/hooks/useFormFieldValueAdapters.ts +23 -16
- package/src/hooks/useFormFields.ts +28 -41
- package/src/hooks/useInitialValues.ts +15 -6
- package/src/hooks/useProcessorDependencies.ts +4 -3
- package/src/processors/encounter/encounter-form-processor.ts +12 -21
- package/src/processors/form-processor.ts +27 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useMemo, useState } from "react";
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
2
2
|
import useProcessorDependencies from "../../hooks/useProcessorDependencies.js";
|
|
3
3
|
import useInitialValues from "../../hooks/useInitialValues.js";
|
|
4
4
|
import { FormRenderer } from "../renderer/form/form-renderer.component.js";
|
|
@@ -14,8 +14,29 @@ import { reportError } from "../../utils/error-utils.js";
|
|
|
14
14
|
import { useTranslation } from "react-i18next";
|
|
15
15
|
import Loader from "../loaders/loader.component.js";
|
|
16
16
|
import { registerFormFieldAdaptersForCleanUp } from "../../lifecycle.js";
|
|
17
|
+
/** Context properties this component derives; a processor that sets one of these is ignored. */ const factoryOwnedContextKeys = [
|
|
18
|
+
'patient',
|
|
19
|
+
'formJson',
|
|
20
|
+
'visit',
|
|
21
|
+
'sessionMode',
|
|
22
|
+
'sessionDate',
|
|
23
|
+
'location',
|
|
24
|
+
'currentProvider',
|
|
25
|
+
'layoutType',
|
|
26
|
+
'processor',
|
|
27
|
+
'formFields',
|
|
28
|
+
'formFieldAdapters',
|
|
29
|
+
'formFieldValidators'
|
|
30
|
+
];
|
|
31
|
+
function warnAboutIgnoredContextKeys(previous, next) {
|
|
32
|
+
const ignored = factoryOwnedContextKeys.filter((key)=>key in next && next[key] !== previous[key]);
|
|
33
|
+
if (ignored.length) {
|
|
34
|
+
console.warn(`A form processor tried to set the context propert${ignored.length === 1 ? 'y' : 'ies'} ` + `${ignored.join(', ')}, which the form engine derives itself. ${ignored.length === 1 ? 'It was' : 'They were'} ignored. Use the setters passed alongside setContext to update the domain object or custom dependencies.`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
17
37
|
const FormProcessorFactory = ({ formJson, isSubForm = false, setIsLoadingFormDependencies })=>{
|
|
18
38
|
const { patient, sessionMode, formProcessors, layoutType, location, provider, sessionDate, visit } = useFormFactory();
|
|
39
|
+
const { t } = useTranslation();
|
|
19
40
|
const processor = useMemo(()=>{
|
|
20
41
|
const ProcessorClass = formProcessors[formJson.processor];
|
|
21
42
|
let processorInstance;
|
|
@@ -31,66 +52,116 @@ const FormProcessorFactory = ({ formJson, isSubForm = false, setIsLoadingFormDep
|
|
|
31
52
|
formProcessors,
|
|
32
53
|
formJson.processor
|
|
33
54
|
]);
|
|
34
|
-
|
|
55
|
+
// Derive form fields and related data
|
|
56
|
+
const { formFields: rawFormFields, conceptReferences } = useFormFields(formJson);
|
|
57
|
+
const { concepts: formFieldsConcepts, isLoading: isLoadingConcepts } = useConcepts(Array.from(conceptReferences));
|
|
58
|
+
const formFieldsWithMeta = useFormFieldsMeta(rawFormFields, formFieldsConcepts);
|
|
59
|
+
const formFieldAdapters = useFormFieldValueAdapters(rawFormFields);
|
|
60
|
+
const formFieldValidators = useFormFieldValidators(rawFormFields);
|
|
61
|
+
const formFields = useMemo(()=>formFieldsWithMeta?.length ? formFieldsWithMeta : rawFormFields ?? [], [
|
|
62
|
+
formFieldsWithMeta,
|
|
63
|
+
rawFormFields
|
|
64
|
+
]);
|
|
65
|
+
// We divide the context into the "mutable" parts, which can be changed by custom hooks
|
|
66
|
+
// and the "static" parts
|
|
67
|
+
const [mutableContext, setMutableContext] = useState({});
|
|
68
|
+
// Create the "static" part of the context
|
|
69
|
+
const baseContext = useMemo(()=>({
|
|
70
|
+
patient,
|
|
71
|
+
formJson,
|
|
72
|
+
sessionMode,
|
|
73
|
+
layoutType,
|
|
74
|
+
location,
|
|
75
|
+
currentProvider: provider,
|
|
76
|
+
processor,
|
|
77
|
+
sessionDate,
|
|
78
|
+
visit,
|
|
79
|
+
formFields,
|
|
80
|
+
formFieldAdapters: formFieldAdapters ?? {},
|
|
81
|
+
formFieldValidators: formFieldValidators ?? {}
|
|
82
|
+
}), [
|
|
35
83
|
patient,
|
|
36
84
|
formJson,
|
|
37
85
|
sessionMode,
|
|
38
86
|
layoutType,
|
|
39
87
|
location,
|
|
40
|
-
|
|
88
|
+
provider,
|
|
41
89
|
processor,
|
|
42
90
|
sessionDate,
|
|
43
91
|
visit,
|
|
44
|
-
formFields
|
|
45
|
-
formFieldAdapters
|
|
46
|
-
formFieldValidators
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
92
|
+
formFields,
|
|
93
|
+
formFieldAdapters,
|
|
94
|
+
formFieldValidators
|
|
95
|
+
]);
|
|
96
|
+
// re-create the full processor context
|
|
97
|
+
const processorContext = useMemo(()=>({
|
|
98
|
+
...baseContext,
|
|
99
|
+
...mutableContext
|
|
100
|
+
}), [
|
|
101
|
+
baseContext,
|
|
102
|
+
mutableContext
|
|
103
|
+
]);
|
|
104
|
+
// callback to update the mutable part of the context
|
|
105
|
+
const setProcessorContext = useCallback((updater)=>{
|
|
106
|
+
setMutableContext((prevMutable)=>{
|
|
107
|
+
// Build the "previous" full context to pass to the updater
|
|
108
|
+
const prevFull = {
|
|
109
|
+
...baseContext,
|
|
110
|
+
...prevMutable
|
|
111
|
+
};
|
|
112
|
+
const newFull = typeof updater === 'function' ? updater(prevFull) : updater;
|
|
113
|
+
// Only the updater form sees prevFull; a bare object may be a stale context, whose
|
|
114
|
+
// differences aren't attempted writes.
|
|
115
|
+
if (typeof updater === 'function') {
|
|
116
|
+
warnAboutIgnoredContextKeys(prevFull, newFull);
|
|
117
|
+
}
|
|
118
|
+
// Extract only the mutable parts from the result
|
|
119
|
+
return {
|
|
120
|
+
domainObjectValue: newFull.domainObjectValue,
|
|
121
|
+
previousDomainObjectValue: newFull.previousDomainObjectValue,
|
|
122
|
+
customDependencies: newFull.customDependencies
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
}, [
|
|
126
|
+
baseContext
|
|
127
|
+
]);
|
|
128
|
+
const processorSetters = useMemo(()=>({
|
|
129
|
+
setDomainObjectValue: (value)=>setMutableContext((prev)=>({
|
|
130
|
+
...prev,
|
|
131
|
+
domainObjectValue: value
|
|
132
|
+
})),
|
|
133
|
+
setPreviousDomainObjectValue: (value)=>setMutableContext((prev)=>({
|
|
134
|
+
...prev,
|
|
135
|
+
previousDomainObjectValue: value
|
|
136
|
+
})),
|
|
137
|
+
setCustomDependencies: (dependencies)=>setMutableContext((prev)=>({
|
|
138
|
+
...prev,
|
|
139
|
+
customDependencies: typeof dependencies === 'function' ? dependencies(prev.customDependencies ?? {}) : dependencies
|
|
140
|
+
}))
|
|
141
|
+
}), []);
|
|
142
|
+
const { isLoading: isLoadingCustomDeps } = useProcessorDependencies(processor, processorContext, setProcessorContext, processorSetters);
|
|
55
143
|
const useCustomHooks = processor.getCustomHooks().useCustomHooks;
|
|
56
144
|
const [isLoadingCustomHooks, setIsLoadingCustomHooks] = useState(!!useCustomHooks);
|
|
57
|
-
const [isLoadingProcessorDependencies, setIsLoadingProcessorDependencies] = useState(true);
|
|
58
145
|
const { isLoadingInitialValues, initialValues, error: initialValuesError } = useInitialValues(processor, isLoadingCustomDeps || isLoadingCustomHooks || isLoadingConcepts, processorContext);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
setIsLoadingFormDependencies(isLoading);
|
|
62
|
-
setIsLoadingProcessorDependencies(isLoading);
|
|
63
|
-
}, [
|
|
146
|
+
// Derive loading state with useMemo to avoid effect-based state updates
|
|
147
|
+
const isLoadingProcessorDependencies = useMemo(()=>isLoadingCustomDeps || isLoadingCustomHooks || isLoadingConcepts || isLoadingInitialValues, [
|
|
64
148
|
isLoadingCustomDeps,
|
|
65
149
|
isLoadingCustomHooks,
|
|
66
150
|
isLoadingConcepts,
|
|
67
151
|
isLoadingInitialValues
|
|
68
152
|
]);
|
|
153
|
+
// Notify parent of loading state changes
|
|
69
154
|
useEffect(()=>{
|
|
70
|
-
|
|
71
|
-
...prev,
|
|
72
|
-
...formFieldAdapters && {
|
|
73
|
-
formFieldAdapters
|
|
74
|
-
},
|
|
75
|
-
...formFieldValidators && {
|
|
76
|
-
formFieldValidators
|
|
77
|
-
},
|
|
78
|
-
...formFieldsWithMeta?.length ? {
|
|
79
|
-
formFields: formFieldsWithMeta
|
|
80
|
-
} : rawFormFields?.length ? {
|
|
81
|
-
formFields: rawFormFields
|
|
82
|
-
} : {}
|
|
83
|
-
}));
|
|
155
|
+
setIsLoadingFormDependencies(isLoadingProcessorDependencies);
|
|
84
156
|
}, [
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
rawFormFields,
|
|
88
|
-
formFieldsWithMeta
|
|
157
|
+
isLoadingProcessorDependencies,
|
|
158
|
+
setIsLoadingFormDependencies
|
|
89
159
|
]);
|
|
90
160
|
useEffect(()=>{
|
|
91
161
|
reportError(initialValuesError, t('errorLoadingInitialValues', 'Error loading initial values'));
|
|
92
162
|
}, [
|
|
93
|
-
initialValuesError
|
|
163
|
+
initialValuesError,
|
|
164
|
+
t
|
|
94
165
|
]);
|
|
95
166
|
useEffect(()=>{
|
|
96
167
|
if (formFieldAdapters) {
|
|
@@ -102,6 +173,7 @@ const FormProcessorFactory = ({ formJson, isSubForm = false, setIsLoadingFormDep
|
|
|
102
173
|
return /*#__PURE__*/ React.createElement(React.Fragment, null, useCustomHooks && /*#__PURE__*/ React.createElement(CustomHooksRenderer, {
|
|
103
174
|
context: processorContext,
|
|
104
175
|
setContext: setProcessorContext,
|
|
176
|
+
setters: processorSetters,
|
|
105
177
|
useCustomHooks: useCustomHooks,
|
|
106
178
|
setIsLoadingCustomHooks: setIsLoadingCustomHooks
|
|
107
179
|
}), isLoadingProcessorDependencies && !isSubForm ? /*#__PURE__*/ React.createElement(Loader, null) : /*#__PURE__*/ React.createElement(FormRenderer, {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { useEffect } from "react";
|
|
2
|
-
export const CustomHooksRenderer = ({ context, setContext, useCustomHooks, setIsLoadingCustomHooks })=>{
|
|
2
|
+
export const CustomHooksRenderer = ({ context, setContext, setters, useCustomHooks, setIsLoadingCustomHooks })=>{
|
|
3
3
|
const { isLoading = false, error = null, data, updateContext } = useCustomHooks(context);
|
|
4
4
|
useEffect(()=>{
|
|
5
5
|
if (!isLoading && updateContext) {
|
|
6
|
-
updateContext(setContext);
|
|
6
|
+
updateContext(setContext, setters);
|
|
7
7
|
setIsLoadingCustomHooks(false);
|
|
8
8
|
}
|
|
9
9
|
}, [
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
1
|
+
import React, { Suspense, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
2
2
|
import classNames from "classnames";
|
|
3
3
|
import { Button, ButtonSet, InlineLoading } from "@carbon/react";
|
|
4
4
|
import { I18nextProvider, useTranslation } from "react-i18next";
|
|
@@ -173,9 +173,11 @@ const FormEngine = ({ formJson, patientUUID, formUUID, encounterUUID, visit, for
|
|
|
173
173
|
}) : /*#__PURE__*/ React.createElement("span", null, `${t('save', 'Save')}`))))))));
|
|
174
174
|
};
|
|
175
175
|
function I18FormEngine(props) {
|
|
176
|
-
return /*#__PURE__*/ React.createElement(
|
|
176
|
+
return /*#__PURE__*/ React.createElement(Suspense, {
|
|
177
|
+
fallback: /*#__PURE__*/ React.createElement(Loader, null)
|
|
178
|
+
}, /*#__PURE__*/ React.createElement(I18nextProvider, {
|
|
177
179
|
i18n: window.i18next,
|
|
178
180
|
defaultNS: formEngineAppName
|
|
179
|
-
}, /*#__PURE__*/ React.createElement(FormEngine, props));
|
|
181
|
+
}, /*#__PURE__*/ React.createElement(FormEngine, props)));
|
|
180
182
|
}
|
|
181
183
|
export default I18FormEngine;
|
|
@@ -1,20 +1,30 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import useSWRImmutable from "swr/immutable";
|
|
2
3
|
import { getRegisteredValidator } from "../registry/registry.js";
|
|
4
|
+
const EMPTY_VALIDATORS = {};
|
|
3
5
|
export function useFormFieldValidators(fields) {
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
const supportedTypes = new Set();
|
|
6
|
+
const validatorTypesKey = useMemo(()=>{
|
|
7
|
+
const uniqueTypes = new Set();
|
|
7
8
|
fields.forEach((field)=>{
|
|
8
|
-
field.validators?.forEach((validator)=>
|
|
9
|
-
});
|
|
10
|
-
const supportedTypesArray = Array.from(supportedTypes);
|
|
11
|
-
Promise.all(supportedTypesArray.map((type)=>getRegisteredValidator(type))).then((validators)=>{
|
|
12
|
-
setValidators(Object.assign({}, ...validators.map((validator, index)=>({
|
|
13
|
-
[supportedTypesArray[index]]: validator
|
|
14
|
-
}))));
|
|
9
|
+
field.validators?.forEach((validator)=>uniqueTypes.add(validator.type));
|
|
15
10
|
});
|
|
11
|
+
return Array.from(uniqueTypes).sort().join(',');
|
|
16
12
|
}, [
|
|
17
13
|
fields
|
|
18
14
|
]);
|
|
19
|
-
|
|
15
|
+
const { data: validators } = useSWRImmutable(validatorTypesKey ? [
|
|
16
|
+
'formFieldValidators',
|
|
17
|
+
validatorTypesKey
|
|
18
|
+
] : null, async ([, key])=>{
|
|
19
|
+
const types = key.split(',');
|
|
20
|
+
const loadedValidators = await Promise.all(types.map((type)=>getRegisteredValidator(type)));
|
|
21
|
+
const validatorsByType = {};
|
|
22
|
+
types.forEach((type, index)=>{
|
|
23
|
+
validatorsByType[type] = loadedValidators[index];
|
|
24
|
+
});
|
|
25
|
+
return validatorsByType;
|
|
26
|
+
}, {
|
|
27
|
+
keepPreviousData: true
|
|
28
|
+
});
|
|
29
|
+
return validators ?? EMPTY_VALIDATORS;
|
|
20
30
|
}
|
|
@@ -1,21 +1,28 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import useSWRImmutable from "swr/immutable";
|
|
2
3
|
import { getRegisteredFieldValueAdapter } from "../registry/registry.js";
|
|
4
|
+
const EMPTY_ADAPTERS = {};
|
|
3
5
|
export const useFormFieldValueAdapters = (fields)=>{
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
supportedTypes.add(field.type);
|
|
9
|
-
});
|
|
10
|
-
const supportedTypesArray = Array.from(supportedTypes);
|
|
11
|
-
Promise.all(supportedTypesArray.map((type)=>getRegisteredFieldValueAdapter(type))).then((adapters)=>{
|
|
12
|
-
const adaptersByType = supportedTypesArray.map((type, index)=>({
|
|
13
|
-
[type]: adapters[index]
|
|
14
|
-
}));
|
|
15
|
-
setAdapters(Object.assign({}, ...adaptersByType));
|
|
16
|
-
});
|
|
6
|
+
const typesKey = useMemo(()=>{
|
|
7
|
+
const uniqueTypes = new Set();
|
|
8
|
+
fields.forEach((field)=>uniqueTypes.add(field.type));
|
|
9
|
+
return Array.from(uniqueTypes).sort().join(',');
|
|
17
10
|
}, [
|
|
18
11
|
fields
|
|
19
12
|
]);
|
|
20
|
-
|
|
13
|
+
const { data: adapters } = useSWRImmutable(typesKey ? [
|
|
14
|
+
'formFieldValueAdapters',
|
|
15
|
+
typesKey
|
|
16
|
+
] : null, async ([, key])=>{
|
|
17
|
+
const types = key.split(',');
|
|
18
|
+
const loadedAdapters = await Promise.all(types.map((type)=>getRegisteredFieldValueAdapter(type)));
|
|
19
|
+
const adaptersByType = {};
|
|
20
|
+
types.forEach((type, index)=>{
|
|
21
|
+
adaptersByType[type] = loadedAdapters[index];
|
|
22
|
+
});
|
|
23
|
+
return adaptersByType;
|
|
24
|
+
}, {
|
|
25
|
+
keepPreviousData: true
|
|
26
|
+
});
|
|
27
|
+
return adapters ?? EMPTY_ADAPTERS;
|
|
21
28
|
};
|
|
@@ -1,60 +1,53 @@
|
|
|
1
1
|
import { useMemo } from "react";
|
|
2
2
|
export function useFormFields(form) {
|
|
3
|
-
const [flattenedFields,
|
|
3
|
+
const [flattenedFields, conceptReferencesKey] = useMemo(()=>{
|
|
4
4
|
const flattenedFieldsTemp = [];
|
|
5
5
|
const conceptReferencesTemp = new Set();
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
meta: {
|
|
14
|
-
...field.meta,
|
|
15
|
-
groupId: parentGroupId
|
|
16
|
-
}
|
|
17
|
-
} : field;
|
|
18
|
-
// Add field to flattened list
|
|
19
|
-
flattenedFields.push(processedField);
|
|
20
|
-
// Collect concept references
|
|
21
|
-
if (processedField.questionOptions?.concept) {
|
|
22
|
-
conceptReferences.add(processedField.questionOptions.concept);
|
|
6
|
+
const processField = (field, parentGroupId)=>{
|
|
7
|
+
// Add group ID to nested fields if applicable
|
|
8
|
+
const processedField = parentGroupId ? {
|
|
9
|
+
...field,
|
|
10
|
+
meta: {
|
|
11
|
+
...field.meta,
|
|
12
|
+
groupId: parentGroupId
|
|
23
13
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
14
|
+
} : field;
|
|
15
|
+
// Add field to flattened list
|
|
16
|
+
flattenedFieldsTemp.push(processedField);
|
|
17
|
+
// Collect concept references
|
|
18
|
+
if (processedField.questionOptions?.concept) {
|
|
19
|
+
conceptReferencesTemp.add(processedField.questionOptions.concept);
|
|
20
|
+
}
|
|
21
|
+
// Collect concept references from answers
|
|
22
|
+
processedField.questionOptions?.answers?.forEach((answer)=>{
|
|
23
|
+
if (answer.concept) {
|
|
24
|
+
conceptReferencesTemp.add(answer.concept);
|
|
35
25
|
}
|
|
36
|
-
};
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
26
|
+
});
|
|
27
|
+
// Recursively process nested questions for obsGroup
|
|
28
|
+
if (processedField.type === 'obsGroup' && processedField.questions) {
|
|
29
|
+
processedField.questions.forEach((nestedField)=>{
|
|
30
|
+
processField(nestedField, processedField.id);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
43
33
|
};
|
|
34
|
+
// Process all input fields
|
|
44
35
|
form.pages?.forEach((page)=>page.sections?.forEach((section)=>{
|
|
45
|
-
|
|
46
|
-
const { flattenedFields, conceptReferences } = processFlattenedFields(section.questions);
|
|
47
|
-
flattenedFieldsTemp.push(...flattenedFields);
|
|
48
|
-
conceptReferences.forEach((conceptReference)=>conceptReferencesTemp.add(conceptReference));
|
|
49
|
-
}
|
|
36
|
+
section.questions?.forEach((field)=>processField(field));
|
|
50
37
|
}));
|
|
38
|
+
// Serialised so the set below is rebuilt only when the references change. JSON rather than a
|
|
39
|
+
// delimiter because mapping codes may contain any character, commas included.
|
|
40
|
+
const sortedRefs = Array.from(conceptReferencesTemp).sort();
|
|
51
41
|
return [
|
|
52
42
|
flattenedFieldsTemp,
|
|
53
|
-
|
|
43
|
+
JSON.stringify(sortedRefs)
|
|
54
44
|
];
|
|
55
45
|
}, [
|
|
56
46
|
form
|
|
57
47
|
]);
|
|
48
|
+
const conceptReferences = useMemo(()=>new Set(JSON.parse(conceptReferencesKey)), [
|
|
49
|
+
conceptReferencesKey
|
|
50
|
+
]);
|
|
58
51
|
return {
|
|
59
52
|
formFields: flattenedFields,
|
|
60
53
|
conceptReferences
|
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
import { useEffect, useState } from "react";
|
|
1
|
+
import { useEffect, useRef, useState } from "react";
|
|
2
2
|
const useInitialValues = (formProcessor, isLoadingContextDependencies, context)=>{
|
|
3
3
|
const [isLoadingInitialValues, setIsLoadingInitialValues] = useState(true);
|
|
4
4
|
const [initialValues, setInitialValues] = useState({});
|
|
5
5
|
const [error, setError] = useState(null);
|
|
6
|
+
const contextRef = useRef(context);
|
|
7
|
+
contextRef.current = context;
|
|
8
|
+
const hasStartedLoading = useRef(false);
|
|
9
|
+
const hasFormFields = context.formFields?.length > 0;
|
|
10
|
+
const hasFormFieldAdapters = Object.keys(context.formFieldAdapters ?? {}).length > 0;
|
|
6
11
|
useEffect(()=>{
|
|
7
|
-
if (formProcessor && !isLoadingContextDependencies &&
|
|
8
|
-
|
|
12
|
+
if (formProcessor && !isLoadingContextDependencies && hasFormFields && hasFormFieldAdapters && !hasStartedLoading.current) {
|
|
13
|
+
hasStartedLoading.current = true;
|
|
14
|
+
const currentContext = contextRef.current;
|
|
15
|
+
formProcessor.getInitialValues(currentContext).then((values)=>{
|
|
9
16
|
setInitialValues(values);
|
|
10
17
|
setIsLoadingInitialValues(false);
|
|
11
18
|
}).catch((error)=>{
|
|
@@ -17,8 +24,8 @@ const useInitialValues = (formProcessor, isLoadingContextDependencies, context)=
|
|
|
17
24
|
}, [
|
|
18
25
|
formProcessor,
|
|
19
26
|
isLoadingContextDependencies,
|
|
20
|
-
|
|
21
|
-
|
|
27
|
+
hasFormFields,
|
|
28
|
+
hasFormFieldAdapters
|
|
22
29
|
]);
|
|
23
30
|
return {
|
|
24
31
|
isLoadingInitialValues,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useEffect, useState } from "react";
|
|
2
2
|
import { reportError } from "../utils/error-utils.js";
|
|
3
|
-
const useProcessorDependencies = (formProcessor, context, setContext)=>{
|
|
3
|
+
const useProcessorDependencies = (formProcessor, context, setContext, setters)=>{
|
|
4
4
|
const [isLoading, setIsLoading] = useState(false);
|
|
5
5
|
const [error, setError] = useState('');
|
|
6
6
|
const { loadDependencies } = formProcessor;
|
|
@@ -8,7 +8,7 @@ const useProcessorDependencies = (formProcessor, context, setContext)=>{
|
|
|
8
8
|
let ignore = false;
|
|
9
9
|
if (loadDependencies) {
|
|
10
10
|
setIsLoading(true);
|
|
11
|
-
loadDependencies(context, setContext).then(()=>{
|
|
11
|
+
loadDependencies(context, setContext, setters).then(()=>{
|
|
12
12
|
if (!ignore) {
|
|
13
13
|
setIsLoading(false);
|
|
14
14
|
}
|
|
@@ -32,19 +32,14 @@ function useCustomHooks(context) {
|
|
|
32
32
|
},
|
|
33
33
|
isLoading,
|
|
34
34
|
error: null,
|
|
35
|
-
updateContext: (
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
...
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
patientPrograms: patientPrograms,
|
|
44
|
-
defaultEncounterRole: encounterRole
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
});
|
|
35
|
+
updateContext: (_setContext, { setDomainObjectValue, setCustomDependencies })=>{
|
|
36
|
+
context.processor.domainObjectValue = encounter;
|
|
37
|
+
setDomainObjectValue(encounter);
|
|
38
|
+
setCustomDependencies((previous)=>({
|
|
39
|
+
...previous,
|
|
40
|
+
patientPrograms: patientPrograms,
|
|
41
|
+
defaultEncounterRole: encounterRole
|
|
42
|
+
}));
|
|
48
43
|
}
|
|
49
44
|
};
|
|
50
45
|
}
|
|
@@ -293,15 +288,10 @@ export class EncounterFormProcessor extends FormProcessor {
|
|
|
293
288
|
}
|
|
294
289
|
return initialValues;
|
|
295
290
|
}
|
|
296
|
-
async loadDependencies(context,
|
|
291
|
+
async loadDependencies(context, _setContext, { setPreviousDomainObjectValue }) {
|
|
297
292
|
const { patient, formJson } = context;
|
|
298
293
|
const encounter = await getPreviousEncounter(patient?.id, formJson.encounterType);
|
|
299
|
-
|
|
300
|
-
return {
|
|
301
|
-
...context,
|
|
302
|
-
previousDomainObjectValue: encounter
|
|
303
|
-
};
|
|
304
|
-
});
|
|
294
|
+
setPreviousDomainObjectValue(encounter);
|
|
305
295
|
return context;
|
|
306
296
|
}
|
|
307
297
|
async getHistoricalValue(field, context) {
|
|
@@ -15,7 +15,10 @@ export class FormProcessor {
|
|
|
15
15
|
getDomainObject() {
|
|
16
16
|
return this.domainObjectValue;
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Loads whatever the processor needs before the form can render, merging the results into the
|
|
20
|
+
* processor context. `setContext` is deprecated; use `setters`.
|
|
21
|
+
*/ async loadDependencies(context, setContext, setters) {
|
|
19
22
|
return Promise.resolve({});
|
|
20
23
|
}
|
|
21
24
|
constructor(formJson){
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-processor-factory.component.d.ts","sourceRoot":"","sources":["../../../../src/components/processor-factory/form-processor-factory.component.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"form-processor-factory.component.d.ts","sourceRoot":"","sources":["../../../../src/components/processor-factory/form-processor-factory.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoD,MAAM,OAAO,CAAC;AAKzE,OAAO,EAAkC,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAe9E,UAAU,yBAAyB;IACjC,QAAQ,EAAE,UAAU,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4BAA4B,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5D;AAqCD,QAAA,MAAM,oBAAoB,GAAI,wDAI3B,yBAAyB,sBAgL3B,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import { type FormProcessorContextProps } from '../../types';
|
|
2
|
-
|
|
2
|
+
import { type FormProcessorContextSetters, type GetCustomHooksResponse } from '../../processors/form-processor';
|
|
3
|
+
export declare const CustomHooksRenderer: ({ context, setContext, setters, useCustomHooks, setIsLoadingCustomHooks, }: {
|
|
3
4
|
context: FormProcessorContextProps;
|
|
4
|
-
setContext:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
isLoading: boolean;
|
|
8
|
-
error: any;
|
|
9
|
-
updateContext: (setContext: React.Dispatch<React.SetStateAction<FormProcessorContextProps>>) => void;
|
|
10
|
-
};
|
|
5
|
+
setContext: React.Dispatch<React.SetStateAction<FormProcessorContextProps>>;
|
|
6
|
+
setters: FormProcessorContextSetters;
|
|
7
|
+
useCustomHooks: GetCustomHooksResponse["useCustomHooks"];
|
|
11
8
|
setIsLoadingCustomHooks: (isLoading: boolean) => void;
|
|
12
9
|
}) => any;
|
|
13
10
|
//# sourceMappingURL=custom-hooks-renderer.component.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-hooks-renderer.component.d.ts","sourceRoot":"","sources":["../../../../src/components/renderer/custom-hooks-renderer.component.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"custom-hooks-renderer.component.d.ts","sourceRoot":"","sources":["../../../../src/components/renderer/custom-hooks-renderer.component.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,KAAK,2BAA2B,EAAE,KAAK,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAEhH,eAAO,MAAM,mBAAmB,GAAI,4EAMjC;IACD,OAAO,EAAE,yBAAyB,CAAC;IACnC,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,yBAAyB,CAAC,CAAC,CAAC;IAC5E,OAAO,EAAE,2BAA2B,CAAC;IACrC,cAAc,EAAE,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;IACzD,uBAAuB,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CACvD,QAWA,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-engine.component.d.ts","sourceRoot":"","sources":["../../src/form-engine.component.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"form-engine.component.d.ts","sourceRoot":"","sources":["../../src/form-engine.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsE,MAAM,OAAO,CAAC;AAI3F,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,qBAQ5C;AAED,eAAe,aAAa,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormFieldValidators.d.ts","sourceRoot":"","sources":["../../../src/hooks/useFormFieldValidators.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useFormFieldValidators.d.ts","sourceRoot":"","sources":["../../../src/hooks/useFormFieldValidators.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAInE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,sCAwBzD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormFieldValueAdapters.d.ts","sourceRoot":"","sources":["../../../src/hooks/useFormFieldValueAdapters.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useFormFieldValueAdapters.d.ts","sourceRoot":"","sources":["../../../src/hooks/useFormFieldValueAdapters.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAKtE,eAAO,MAAM,yBAAyB,GAAI,QAAQ,SAAS,EAAE,0CAsB5D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormFields.d.ts","sourceRoot":"","sources":["../../../src/hooks/useFormFields.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3D,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG;IAAE,UAAU,EAAE,SAAS,EAAE,CAAC;IAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"useFormFields.d.ts","sourceRoot":"","sources":["../../../src/hooks/useFormFields.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3D,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG;IAAE,UAAU,EAAE,SAAS,EAAE,CAAC;IAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAAE,CAgD3G"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useInitialValues.d.ts","sourceRoot":"","sources":["../../../src/hooks/useInitialValues.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE,QAAA,MAAM,gBAAgB,GACpB,eAAe,aAAa,EAC5B,8BAA8B,OAAO,EACrC,SAAS,yBAAyB;;;;
|
|
1
|
+
{"version":3,"file":"useInitialValues.d.ts","sourceRoot":"","sources":["../../../src/hooks/useInitialValues.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE,QAAA,MAAM,gBAAgB,GACpB,eAAe,aAAa,EAC5B,8BAA8B,OAAO,EACrC,SAAS,yBAAyB;;;;CAsCnC,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type FormProcessorContextProps } from '../types';
|
|
2
|
-
import { type FormProcessor } from '../processors/form-processor';
|
|
3
|
-
declare const useProcessorDependencies: (formProcessor: FormProcessor, context: Partial<FormProcessorContextProps>, setContext:
|
|
2
|
+
import { type FormProcessor, type FormProcessorContextSetters } from '../processors/form-processor';
|
|
3
|
+
declare const useProcessorDependencies: (formProcessor: FormProcessor, context: Partial<FormProcessorContextProps>, setContext: React.Dispatch<React.SetStateAction<FormProcessorContextProps>>, setters: FormProcessorContextSetters) => {
|
|
4
4
|
isLoading: boolean;
|
|
5
5
|
error: string;
|
|
6
6
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useProcessorDependencies.d.ts","sourceRoot":"","sources":["../../../src/hooks/useProcessorDependencies.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"useProcessorDependencies.d.ts","sourceRoot":"","sources":["../../../src/hooks/useProcessorDependencies.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAGpG,QAAA,MAAM,wBAAwB,GAC5B,eAAe,aAAa,EAC5B,SAAS,OAAO,CAAC,yBAAyB,CAAC,EAC3C,YAAY,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,yBAAyB,CAAC,CAAC,EAC3E,SAAS,2BAA2B;;;CA+BrC,CAAC;AAEF,eAAe,wBAAwB,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type OpenmrsResource } from '@openmrs/esm-framework';
|
|
2
2
|
import { type FormField, type FormProcessorContextProps, type FormSchema, type ValueAndDisplay } from '../../types';
|
|
3
|
-
import { FormProcessor } from '../form-processor';
|
|
3
|
+
import { FormProcessor, type FormProcessorContextSetters } from '../form-processor';
|
|
4
4
|
import { type FormContextProps } from '../../provider/form-provider';
|
|
5
5
|
declare function useCustomHooks(context: Partial<FormProcessorContextProps>): {
|
|
6
6
|
data: {
|
|
@@ -10,7 +10,10 @@ declare function useCustomHooks(context: Partial<FormProcessorContextProps>): {
|
|
|
10
10
|
};
|
|
11
11
|
isLoading: boolean;
|
|
12
12
|
error: any;
|
|
13
|
-
updateContext: (
|
|
13
|
+
updateContext: (_setContext: any, { setDomainObjectValue, setCustomDependencies }: {
|
|
14
|
+
setDomainObjectValue: any;
|
|
15
|
+
setCustomDependencies: any;
|
|
16
|
+
}) => void;
|
|
14
17
|
};
|
|
15
18
|
export declare class EncounterFormProcessor extends FormProcessor {
|
|
16
19
|
prepareFormSchema(schema: FormSchema): FormSchema;
|
|
@@ -19,7 +22,7 @@ export declare class EncounterFormProcessor extends FormProcessor {
|
|
|
19
22
|
useCustomHooks: typeof useCustomHooks;
|
|
20
23
|
};
|
|
21
24
|
getInitialValues(context: FormProcessorContextProps): Promise<{}>;
|
|
22
|
-
loadDependencies(context: FormContextProps,
|
|
25
|
+
loadDependencies(context: FormContextProps, _setContext: React.Dispatch<React.SetStateAction<FormProcessorContextProps>>, { setPreviousDomainObjectValue }: FormProcessorContextSetters): Promise<FormContextProps>;
|
|
23
26
|
getHistoricalValue(field: FormField, context: FormContextProps): Promise<ValueAndDisplay>;
|
|
24
27
|
}
|
|
25
28
|
export {};
|