@openmrs/esm-form-engine-lib 2.1.0-pre.1404 → 2.1.0-pre.1412
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/package.json +1 -1
- package/src/adapters/obs-adapter.ts +7 -2
- package/src/components/renderer/field/form-field-renderer.component.tsx +1 -2
- package/src/registry/registry.ts +28 -1
- package/src/types/index.ts +13 -0
- package/src/types/schema.ts +0 -14
- package/src/utils/common-utils.test.ts +37 -1
- package/src/utils/common-utils.ts +12 -0
- package/src/utils/form-helper.test.ts +0 -30
- package/src/utils/form-helper.ts +0 -38
- package/12ea0b64ac1d74d9/12ea0b64ac1d74d9.gz +0 -0
- package/b39f834950646b97/b39f834950646b97.gz +0 -0
- package/f7899165a77a3934/f7899165a77a3934.gz +0 -0
- package/ff6bbdac1639f6d1/ff6bbdac1639f6d1.gz +0 -0
package/package.json
CHANGED
@@ -8,8 +8,13 @@ import {
|
|
8
8
|
type Attachment,
|
9
9
|
type ValueAndDisplay,
|
10
10
|
} from '../types';
|
11
|
-
import {
|
12
|
-
|
11
|
+
import {
|
12
|
+
hasRendering,
|
13
|
+
gracefullySetSubmission,
|
14
|
+
clearSubmission,
|
15
|
+
flattenObsList,
|
16
|
+
parseToLocalDateTime,
|
17
|
+
} from '../utils/common-utils';
|
13
18
|
import { type FormContextProps } from '../provider/form-provider';
|
14
19
|
import { type FormFieldValueAdapter } from '../types';
|
15
20
|
import { isEmpty } from '../validators/form-validator';
|
@@ -16,11 +16,10 @@ import { hasRendering } from '../../../utils/common-utils';
|
|
16
16
|
import { useFormProviderContext } from '../../../provider/form-provider';
|
17
17
|
import { isEmpty } from '../../../validators/form-validator';
|
18
18
|
import PreviousValueReview from '../../previous-value-review/previous-value-review.component';
|
19
|
-
import { getRegisteredControl } from '../../../registry/registry';
|
19
|
+
import { getFieldControlWithFallback, getRegisteredControl } from '../../../registry/registry';
|
20
20
|
import styles from './form-field-renderer.scss';
|
21
21
|
import { isTrue } from '../../../utils/boolean-utils';
|
22
22
|
import UnspecifiedField from '../../inputs/unspecified/unspecified.component';
|
23
|
-
import { getFieldControlWithFallback } from '../../../utils/form-helper';
|
24
23
|
import { handleFieldLogic } from './fieldLogic';
|
25
24
|
|
26
25
|
export interface FormFieldRendererProps {
|
package/src/registry/registry.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import {
|
2
|
+
type FormField,
|
2
3
|
type DataSource,
|
3
4
|
type FormFieldValidator,
|
4
5
|
type FormSchemaTransformer,
|
@@ -121,7 +122,7 @@ export async function getRegisteredControl(renderType: string) {
|
|
121
122
|
let component = inbuiltControls.find(
|
122
123
|
(control) => control.name === renderType || control?.alias === renderType,
|
123
124
|
)?.component;
|
124
|
-
// if undefined, try
|
125
|
+
// if undefined, try searching through the registered custom controls
|
125
126
|
if (!component) {
|
126
127
|
const importedControl = await getFormsStore()
|
127
128
|
.controls.find((control) => control.name === renderType || control?.alias === renderType)
|
@@ -132,6 +133,26 @@ export async function getRegisteredControl(renderType: string) {
|
|
132
133
|
return component;
|
133
134
|
}
|
134
135
|
|
136
|
+
/**
|
137
|
+
* Retrieves the appropriate field control for a question, considering missing concepts.
|
138
|
+
* If the question is of type 'obs' and has a missing concept, it falls back to a disabled text input.
|
139
|
+
* Otherwise, it retrieves the registered control based on the rendering specified in the question.
|
140
|
+
* @param question - The FormField representing the question.
|
141
|
+
* @returns The field control to be used for rendering the question.
|
142
|
+
*/
|
143
|
+
export function getFieldControlWithFallback(question: FormField) {
|
144
|
+
// Check if the question has a missing concept
|
145
|
+
if (hasMissingConcept(question)) {
|
146
|
+
// If so, render a disabled text input
|
147
|
+
question.disabled = true;
|
148
|
+
question.isDisabled = true;
|
149
|
+
return getRegisteredControl('text');
|
150
|
+
}
|
151
|
+
|
152
|
+
// Retrieve the registered control based on the specified rendering
|
153
|
+
return getRegisteredControl(question.questionOptions.rendering);
|
154
|
+
}
|
155
|
+
|
135
156
|
export async function getRegisteredFieldValueAdapter(type: string): Promise<FormFieldValueAdapter> {
|
136
157
|
if (registryCache.fieldValueAdapters[type]) {
|
137
158
|
return registryCache.fieldValueAdapters[type];
|
@@ -259,3 +280,9 @@ function getFormsStore(): FormsRegistryStoreState {
|
|
259
280
|
formSchemaTransformers: [],
|
260
281
|
}).getState();
|
261
282
|
}
|
283
|
+
|
284
|
+
function hasMissingConcept(question: FormField) {
|
285
|
+
return (
|
286
|
+
question.type == 'obs' && !question.questionOptions.concept && question.questionOptions.rendering !== 'fixed-value'
|
287
|
+
);
|
288
|
+
}
|
package/src/types/index.ts
CHANGED
@@ -110,6 +110,19 @@ export interface PostSubmissionAction {
|
|
110
110
|
): void;
|
111
111
|
}
|
112
112
|
|
113
|
+
export interface FormFieldInputProps {
|
114
|
+
value: any;
|
115
|
+
field: FormField;
|
116
|
+
errors: ValidationResult[];
|
117
|
+
warnings: ValidationResult[];
|
118
|
+
/**
|
119
|
+
* Callback function to handle changes to the field value in the React Hook Form context.
|
120
|
+
*
|
121
|
+
* @param value - The new value of the field.
|
122
|
+
*/
|
123
|
+
setFieldValue: (value: any) => void;
|
124
|
+
}
|
125
|
+
|
113
126
|
/**
|
114
127
|
* Field validator
|
115
128
|
*/
|
package/src/types/schema.ts
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
import { type OpenmrsResource } from '@openmrs/esm-framework';
|
2
2
|
import { type OpenmrsEncounter } from './domain';
|
3
|
-
import { type ValidationResult } from '..';
|
4
3
|
|
5
4
|
export interface FormSchema {
|
6
5
|
name: string;
|
@@ -88,19 +87,6 @@ export interface FormField {
|
|
88
87
|
meta?: QuestionMetaProps;
|
89
88
|
}
|
90
89
|
|
91
|
-
export interface FormFieldInputProps {
|
92
|
-
value: any;
|
93
|
-
field: FormField;
|
94
|
-
errors: ValidationResult[];
|
95
|
-
warnings: ValidationResult[];
|
96
|
-
/**
|
97
|
-
* Callback function to handle changes to the field value in the React Hook Form context.
|
98
|
-
*
|
99
|
-
* @param value - The new value of the field.
|
100
|
-
*/
|
101
|
-
setFieldValue: (value: any) => void;
|
102
|
-
}
|
103
|
-
|
104
90
|
export interface HideProps {
|
105
91
|
hideWhenExpression: string;
|
106
92
|
}
|
@@ -1,4 +1,11 @@
|
|
1
|
-
import {
|
1
|
+
import {
|
2
|
+
flattenObsList,
|
3
|
+
hasRendering,
|
4
|
+
clearSubmission,
|
5
|
+
gracefullySetSubmission,
|
6
|
+
hasSubmission,
|
7
|
+
parseToLocalDateTime,
|
8
|
+
} from './common-utils';
|
2
9
|
import { isEmpty } from '../validators/form-validator';
|
3
10
|
import { type FormField, type OpenmrsObs } from '../types';
|
4
11
|
import { obsList } from '__mocks__/forms/rfe-forms/obs-list-data';
|
@@ -134,3 +141,32 @@ describe('utils functions', () => {
|
|
134
141
|
});
|
135
142
|
});
|
136
143
|
});
|
144
|
+
|
145
|
+
describe('parseToLocalDateTime', () => {
|
146
|
+
it('should parse valid date string with time correctly', () => {
|
147
|
+
const dateString = '2023-06-27T14:30:00';
|
148
|
+
const expectedDate = new Date(2023, 5, 27, 14, 30, 0);
|
149
|
+
const parsedDate = parseToLocalDateTime(dateString);
|
150
|
+
|
151
|
+
expect(parsedDate).toEqual(expectedDate);
|
152
|
+
});
|
153
|
+
|
154
|
+
it('should parse valid date string without time correctly', () => {
|
155
|
+
const dateString = '2023-06-27';
|
156
|
+
const expectedDate = new Date(2023, 5, 27);
|
157
|
+
const parsedDate = parseToLocalDateTime(dateString);
|
158
|
+
|
159
|
+
// Set hours, minutes, and seconds to 0 since the input doesn't contain time
|
160
|
+
expectedDate.setHours(0, 0, 0, 0);
|
161
|
+
|
162
|
+
expect(parsedDate).toEqual(expectedDate);
|
163
|
+
});
|
164
|
+
|
165
|
+
it('should handle invalid date string format gracefully', () => {
|
166
|
+
const dateString = 'invalid-date-string';
|
167
|
+
const parsedDate = parseToLocalDateTime(dateString);
|
168
|
+
|
169
|
+
// Check if the parsedDate is an Invalid Date
|
170
|
+
expect(isNaN(parsedDate.getTime())).toBe(true);
|
171
|
+
});
|
172
|
+
});
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import dayjs from 'dayjs';
|
1
2
|
import { type FormField, type OpenmrsObs, type RenderType } from '../types';
|
2
3
|
import { isEmpty } from '../validators/form-validator';
|
3
4
|
|
@@ -53,3 +54,14 @@ export function hasSubmission(field: FormField) {
|
|
53
54
|
export function isViewMode(sessionMode: string) {
|
54
55
|
return sessionMode === 'view' || sessionMode === 'embedded-view';
|
55
56
|
}
|
57
|
+
|
58
|
+
export function parseToLocalDateTime(dateString: string): Date {
|
59
|
+
const dateObj = dayjs(dateString).toDate();
|
60
|
+
try {
|
61
|
+
const localTimeTokens = dateString.split('T')[1].split(':');
|
62
|
+
dateObj.setHours(parseInt(localTimeTokens[0]), parseInt(localTimeTokens[1]), 0);
|
63
|
+
} catch (e) {
|
64
|
+
console.error(e);
|
65
|
+
}
|
66
|
+
return dateObj;
|
67
|
+
}
|
@@ -2,7 +2,6 @@ import {
|
|
2
2
|
findConceptByReference,
|
3
3
|
evaluateConditionalAnswered,
|
4
4
|
evaluateFieldReadonlyProp,
|
5
|
-
parseToLocalDateTime,
|
6
5
|
evaluateDisabled,
|
7
6
|
} from './form-helper';
|
8
7
|
import { DefaultValueValidator } from '../validators/default-value-validator';
|
@@ -384,35 +383,6 @@ describe('Form Engine Helper', () => {
|
|
384
383
|
});
|
385
384
|
});
|
386
385
|
|
387
|
-
describe('parseToLocalDateTime', () => {
|
388
|
-
it('should parse valid date string with time correctly', () => {
|
389
|
-
const dateString = '2023-06-27T14:30:00';
|
390
|
-
const expectedDate = new Date(2023, 5, 27, 14, 30, 0);
|
391
|
-
const parsedDate = parseToLocalDateTime(dateString);
|
392
|
-
|
393
|
-
expect(parsedDate).toEqual(expectedDate);
|
394
|
-
});
|
395
|
-
|
396
|
-
it('should parse valid date string without time correctly', () => {
|
397
|
-
const dateString = '2023-06-27';
|
398
|
-
const expectedDate = new Date(2023, 5, 27);
|
399
|
-
const parsedDate = parseToLocalDateTime(dateString);
|
400
|
-
|
401
|
-
// Set hours, minutes, and seconds to 0 since the input doesn't contain time
|
402
|
-
expectedDate.setHours(0, 0, 0, 0);
|
403
|
-
|
404
|
-
expect(parsedDate).toEqual(expectedDate);
|
405
|
-
});
|
406
|
-
|
407
|
-
it('should handle invalid date string format gracefully', () => {
|
408
|
-
const dateString = 'invalid-date-string';
|
409
|
-
const parsedDate = parseToLocalDateTime(dateString);
|
410
|
-
|
411
|
-
// Check if the parsedDate is an Invalid Date
|
412
|
-
expect(isNaN(parsedDate.getTime())).toBe(true);
|
413
|
-
});
|
414
|
-
});
|
415
|
-
|
416
386
|
describe('evaluateDisabled', () => {
|
417
387
|
let mockExpressionRunnerFn;
|
418
388
|
let node;
|
package/src/utils/form-helper.ts
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
import dayjs from 'dayjs';
|
2
1
|
import { type LayoutType } from '@openmrs/esm-framework';
|
3
2
|
import { type FormField, type FormPage, type FormSection, type SessionMode } from '../types';
|
4
3
|
import { isEmpty } from '../validators/form-validator';
|
@@ -58,17 +57,6 @@ export function findPagesWithErrors(pages: Set<FormPage>, errorFields: FormField
|
|
58
57
|
return pagesWithErrors;
|
59
58
|
}
|
60
59
|
|
61
|
-
export function parseToLocalDateTime(dateString: string): Date {
|
62
|
-
const dateObj = dayjs(dateString).toDate();
|
63
|
-
try {
|
64
|
-
const localTimeTokens = dateString.split('T')[1].split(':');
|
65
|
-
dateObj.setHours(parseInt(localTimeTokens[0]), parseInt(localTimeTokens[1]), 0);
|
66
|
-
} catch (e) {
|
67
|
-
console.error(e);
|
68
|
-
}
|
69
|
-
return dateObj;
|
70
|
-
}
|
71
|
-
|
72
60
|
export function evalConditionalRequired(field: FormField, allFields: FormField[], formValues: Record<string, any>) {
|
73
61
|
if (typeof field.required !== 'object') {
|
74
62
|
return false;
|
@@ -170,32 +158,6 @@ export function findConceptByReference(reference: string, concepts) {
|
|
170
158
|
}
|
171
159
|
}
|
172
160
|
|
173
|
-
/**
|
174
|
-
* Retrieves the appropriate field control for a question, considering missing concepts.
|
175
|
-
* If the question is of type 'obs' and has a missing concept, it falls back to a disabled text input.
|
176
|
-
* Otherwise, it retrieves the registered control based on the rendering specified in the question.
|
177
|
-
* @param question - The FormField representing the question.
|
178
|
-
* @returns The field control to be used for rendering the question.
|
179
|
-
*/
|
180
|
-
export function getFieldControlWithFallback(question: FormField) {
|
181
|
-
// Check if the question has a missing concept
|
182
|
-
if (hasMissingConcept(question)) {
|
183
|
-
// If so, render a disabled text input
|
184
|
-
question.disabled = true;
|
185
|
-
question.isDisabled = true;
|
186
|
-
return getRegisteredControl('text');
|
187
|
-
}
|
188
|
-
|
189
|
-
// Retrieve the registered control based on the specified rendering
|
190
|
-
return getRegisteredControl(question.questionOptions.rendering);
|
191
|
-
}
|
192
|
-
|
193
|
-
export function hasMissingConcept(question: FormField) {
|
194
|
-
return (
|
195
|
-
question.type == 'obs' && !question.questionOptions.concept && question.questionOptions.rendering !== 'fixed-value'
|
196
|
-
);
|
197
|
-
}
|
198
|
-
|
199
161
|
export function scrollIntoView(viewId: string, shouldFocus: boolean = false) {
|
200
162
|
const currentElement = document.getElementById(viewId);
|
201
163
|
currentElement?.scrollIntoView({
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|