@evoke-platform/ui-components 1.13.0-dev.0 → 1.13.0-dev.2
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/published/components/custom/FormV2/components/RecursiveEntryRenderer.js +8 -4
- package/dist/published/components/custom/FormV2/components/utils.d.ts +1 -1
- package/dist/published/components/custom/FormV2/components/utils.js +3 -2
- package/dist/published/components/custom/FormV2/tests/FormRenderer.test.js +38 -1
- package/dist/published/components/custom/FormV2/tests/test-data.js +29 -0
- package/package.json +2 -1
|
@@ -85,8 +85,8 @@ export function RecursiveEntryRenderer(props) {
|
|
|
85
85
|
}
|
|
86
86
|
else if (fieldDefinition.type === 'object') {
|
|
87
87
|
return (React.createElement(FieldWrapper, { ...getFieldWrapperProps(fieldDefinition, entry, entryId, fieldValue, display, errors) },
|
|
88
|
-
React.createElement(ObjectPropertyInput, { relatedObjectId: !fieldDefinition.objectId ? display?.relatedObjectId : fieldDefinition.objectId, fieldDefinition: fieldDefinition, id: entryId, mode: display?.mode || 'default', error: !!errors?.[entryId], displayOption: display?.relatedObjectDisplay || 'dialogBox', initialValue: fieldValue, readOnly: entry.type === 'readonlyField', filter: validation
|
|
89
|
-
? updateCriteriaInputs(validation.criteria, getValues(), userAccount)
|
|
88
|
+
React.createElement(ObjectPropertyInput, { relatedObjectId: !fieldDefinition.objectId ? display?.relatedObjectId : fieldDefinition.objectId, fieldDefinition: fieldDefinition, id: entryId, mode: display?.mode || 'default', error: !!errors?.[entryId], displayOption: display?.relatedObjectDisplay || 'dialogBox', initialValue: fieldValue, readOnly: entry.type === 'readonlyField', filter: 'criteria' in validation && validation.criteria
|
|
89
|
+
? updateCriteriaInputs(validation.criteria, getValues(), userAccount, instance)
|
|
90
90
|
: undefined, sortBy: typeof display?.defaultValue === 'object' && 'sortBy' in display.defaultValue
|
|
91
91
|
? display?.defaultValue.sortBy
|
|
92
92
|
: undefined, orderBy: typeof display?.defaultValue === 'object' && 'orderBy' in display.defaultValue
|
|
@@ -104,7 +104,9 @@ export function RecursiveEntryRenderer(props) {
|
|
|
104
104
|
if (middleObject && !isEmpty(middleObject)) {
|
|
105
105
|
return (initialMiddleObjectInstances && (React.createElement(FieldWrapper, { ...getFieldWrapperProps(fieldDefinition, entry, entryId, fieldValue, display, errors) },
|
|
106
106
|
React.createElement(DropdownRepeatableField, { initialMiddleObjectInstances: fetchedOptions[`${entryId}MiddleObjectInstances`] ||
|
|
107
|
-
initialMiddleObjectInstances, fieldDefinition: fieldDefinition, id: entryId, middleObject: middleObject, readOnly: entry.type === 'readonlyField', criteria:
|
|
107
|
+
initialMiddleObjectInstances, fieldDefinition: fieldDefinition, id: entryId, middleObject: middleObject, readOnly: entry.type === 'readonlyField', criteria: 'criteria' in validation && validation.criteria
|
|
108
|
+
? updateCriteriaInputs(validation.criteria, getValues(), userAccount, instance)
|
|
109
|
+
: undefined, hasDescription: !!display?.description }))));
|
|
108
110
|
}
|
|
109
111
|
else {
|
|
110
112
|
// when in the builder preview, the middle object won't be fetched so instead show an empty field
|
|
@@ -116,7 +118,9 @@ export function RecursiveEntryRenderer(props) {
|
|
|
116
118
|
}
|
|
117
119
|
else {
|
|
118
120
|
return (React.createElement(FieldWrapper, { ...getFieldWrapperProps(fieldDefinition, entry, entryId, fieldValue, display, errors) },
|
|
119
|
-
React.createElement(RepeatableField, { fieldDefinition: fieldDefinition, canUpdateProperty: entry.type !== 'readonlyField', criteria:
|
|
121
|
+
React.createElement(RepeatableField, { fieldDefinition: fieldDefinition, canUpdateProperty: entry.type !== 'readonlyField', criteria: 'criteria' in validation && validation.criteria
|
|
122
|
+
? updateCriteriaInputs(validation.criteria, getValues(), userAccount, instance)
|
|
123
|
+
: undefined, viewLayout: display?.viewLayout, entry: entry })));
|
|
120
124
|
}
|
|
121
125
|
}
|
|
122
126
|
else if (fieldDefinition.type === 'richText') {
|
|
@@ -40,7 +40,7 @@ export declare const encodePageSlug: (slug: string) => string;
|
|
|
40
40
|
export declare function getDefaultPages(parameters: InputParameter[], defaultPages: Record<string, string> | undefined, findDefaultPageSlugFor: (objectId: string) => Promise<string | undefined>): Promise<{
|
|
41
41
|
[x: string]: string;
|
|
42
42
|
}>;
|
|
43
|
-
export declare function updateCriteriaInputs(criteria: Record<string, unknown>, data: Record<string, unknown>, user?: UserAccount): Record<string, unknown>;
|
|
43
|
+
export declare function updateCriteriaInputs(criteria: Record<string, unknown>, data: Record<string, unknown>, user?: UserAccount, instance?: Record<string, unknown>): Record<string, unknown>;
|
|
44
44
|
export declare function fetchCollectionData(apiServices: ApiServices, fieldDefinition: InputParameter | Property, setFetchedOptions: (newData: FieldValues) => void, instanceId?: string, fetchedOptions?: Record<string, unknown>, initialMiddleObjectInstances?: ObjectInstance[]): Promise<void>;
|
|
45
45
|
export declare const getErrorCountForSection: (section: Section | Column, errors?: FieldErrors) => number;
|
|
46
46
|
export declare const propertyToParameter: (property: Property) => InputParameter;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LocalDateTime } from '@js-joda/core';
|
|
2
|
-
import jsonLogic from 'json-logic-js';
|
|
2
|
+
import { jsonLogic } from 'json-logic-js-graphql';
|
|
3
3
|
import { get, isArray, isEmpty, isObject, omit, pick, startCase, transform } from 'lodash';
|
|
4
4
|
import { DateTime } from 'luxon';
|
|
5
5
|
import { nanoid } from 'nanoid';
|
|
@@ -307,12 +307,13 @@ function compileQueryValues(query, data) {
|
|
|
307
307
|
return query;
|
|
308
308
|
}
|
|
309
309
|
}
|
|
310
|
-
export function updateCriteriaInputs(criteria, data, user) {
|
|
310
|
+
export function updateCriteriaInputs(criteria, data, user, instance) {
|
|
311
311
|
const dataSet = {
|
|
312
312
|
input: {
|
|
313
313
|
...data,
|
|
314
314
|
},
|
|
315
315
|
user: user,
|
|
316
|
+
instance,
|
|
316
317
|
};
|
|
317
318
|
const compiledQuery = compileQueryValues(parseMongoDB(criteria), dataSet);
|
|
318
319
|
// The "compiledQueryValues" function filters out rules that have a value of "undefined".
|
|
@@ -135,6 +135,44 @@ describe('FormRenderer', () => {
|
|
|
135
135
|
// Validate that specialty type dropdown renders
|
|
136
136
|
await screen.findByRole('combobox', { name: 'Specialty Type' });
|
|
137
137
|
});
|
|
138
|
+
it('shows fields based on form data using JsonLogic with a Lodash function', async () => {
|
|
139
|
+
server.use(http.get('/data/objects/license/instances/rnLicense', () => HttpResponse.json(rnLicense)));
|
|
140
|
+
const user = userEvent.setup();
|
|
141
|
+
const FormWithState = () => {
|
|
142
|
+
const [formData, setFormData] = React.useState({
|
|
143
|
+
specialtyType: { id: 'rnSpecialtyType1', name: 'RN Specialty Type #1' },
|
|
144
|
+
});
|
|
145
|
+
const handleChange = (id, value) => {
|
|
146
|
+
setFormData((prev) => {
|
|
147
|
+
const newData = { ...prev };
|
|
148
|
+
set(newData, id, value);
|
|
149
|
+
return newData;
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
try {
|
|
153
|
+
return (React.createElement(FormRenderer, { form: jsonLogicDisplayTestSpecialtyForm, value: formData, onChange: handleChange, instance: {
|
|
154
|
+
id: '123',
|
|
155
|
+
objectId: 'specialty',
|
|
156
|
+
name: 'Test Specialty Object Instance',
|
|
157
|
+
} }));
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
console.error('Render error:', err);
|
|
161
|
+
return React.createElement("div", null, "Render error");
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
render(React.createElement(FormWithState, null));
|
|
165
|
+
// Validate that Additional Training renders because specialtyType.name isn't empty
|
|
166
|
+
await screen.findByRole('textbox', { name: 'Additional Training' });
|
|
167
|
+
await screen.findByRole('combobox', { name: 'Specialty Type' });
|
|
168
|
+
// Clear the specialtyType field
|
|
169
|
+
const clearButton = screen.getByRole('button', { name: 'Clear selection' });
|
|
170
|
+
await user.click(clearButton);
|
|
171
|
+
// Validate that Additional Training is no longer visible because specialtyType.name is now empty
|
|
172
|
+
await waitFor(() => {
|
|
173
|
+
expect(screen.queryByRole('textbox', { name: 'Additional Training' })).not.toBeInTheDocument();
|
|
174
|
+
});
|
|
175
|
+
});
|
|
138
176
|
it('hides fields based on instance data using JsonLogic', async () => {
|
|
139
177
|
server.use(http.get('/data/objects/license/instances/rnLicense', () => HttpResponse.json(rnLicense)));
|
|
140
178
|
render(React.createElement(FormRenderer, { form: jsonLogicDisplayTestSpecialtyForm, onChange: () => { }, instance: {
|
|
@@ -170,7 +208,6 @@ describe('FormRenderer', () => {
|
|
|
170
208
|
expect(screen.queryByRole('combobox', { name: 'Specialty Type' })).not.toBeInTheDocument();
|
|
171
209
|
});
|
|
172
210
|
});
|
|
173
|
-
// accessibility508Form2
|
|
174
211
|
describe('508 accessibility compliance', () => {
|
|
175
212
|
it('supports keyboard navigation back and forth through Related Object dropdowns', async () => {
|
|
176
213
|
const user = userEvent.setup();
|
|
@@ -87,6 +87,25 @@ export const jsonLogicDisplayTestSpecialtyForm = {
|
|
|
87
87
|
},
|
|
88
88
|
},
|
|
89
89
|
},
|
|
90
|
+
{
|
|
91
|
+
parameterId: 'additionalTraining',
|
|
92
|
+
type: 'input',
|
|
93
|
+
display: {
|
|
94
|
+
label: 'Additional Training',
|
|
95
|
+
visibility: {
|
|
96
|
+
and: [
|
|
97
|
+
{
|
|
98
|
+
'!': {
|
|
99
|
+
_isEmpty: { var: 'data.specialtyType.name' },
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
in: [{ var: 'data.specialtyType.name' }, ['RN Specialty Type #1', 'RN Specialty Type #2']],
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
90
109
|
{
|
|
91
110
|
parameterId: 'license',
|
|
92
111
|
type: 'input',
|
|
@@ -360,6 +379,11 @@ export const specialtyObject = {
|
|
|
360
379
|
type: 'object',
|
|
361
380
|
objectId: 'license',
|
|
362
381
|
},
|
|
382
|
+
{
|
|
383
|
+
id: 'additionalTraining',
|
|
384
|
+
name: 'Additional Training',
|
|
385
|
+
type: 'string',
|
|
386
|
+
},
|
|
363
387
|
],
|
|
364
388
|
actions: [
|
|
365
389
|
{
|
|
@@ -422,6 +446,11 @@ export const specialtyObject = {
|
|
|
422
446
|
type: 'object',
|
|
423
447
|
objectId: 'license',
|
|
424
448
|
},
|
|
449
|
+
{
|
|
450
|
+
id: 'additionalTraining',
|
|
451
|
+
name: 'Additional Training',
|
|
452
|
+
type: 'string',
|
|
453
|
+
},
|
|
425
454
|
],
|
|
426
455
|
},
|
|
427
456
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evoke-platform/ui-components",
|
|
3
|
-
"version": "1.13.0-dev.
|
|
3
|
+
"version": "1.13.0-dev.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/published/index.js",
|
|
6
6
|
"module": "dist/published/index.js",
|
|
@@ -128,6 +128,7 @@
|
|
|
128
128
|
"flat": "^6.0.1",
|
|
129
129
|
"formiojs": "^4.21.7",
|
|
130
130
|
"html-react-parser": "^5.1.18",
|
|
131
|
+
"json-logic-js-graphql": "^1.2.4",
|
|
131
132
|
"luxon": "^2.5.2",
|
|
132
133
|
"nanoid": "^5.0.8",
|
|
133
134
|
"nanoid-dictionary": "^4.3.0",
|