@evoke-platform/ui-components 1.10.0-dev.2 → 1.10.0-dev.4

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.
@@ -87,7 +87,7 @@ export const ActionDialog = (props) => {
87
87
  borderBottom: action.type === 'delete' ? undefined : '1px solid #e9ecef',
88
88
  } },
89
89
  action && hasAccess && !loading ? action?.name : '',
90
- React.createElement(IconButton, { sx: styles.closeIcon, onClick: onClose },
90
+ React.createElement(IconButton, { sx: styles.closeIcon, onClick: onClose, "aria-label": "Close" },
91
91
  React.createElement(Close, { fontSize: "small" })),
92
92
  formHeaderProps.hasAccordions && React.createElement(AccordionActions, { ...formHeaderProps })));
93
93
  }, renderBody: (bodyProps) => (React.createElement(DialogContent, { sx: {
@@ -6,9 +6,6 @@ export type ObjectPropertyInputProps = {
6
6
  criteria?: object;
7
7
  viewLayout?: ViewLayoutEntityReference;
8
8
  entry: InputField | InputParameterReference | ReadonlyField;
9
- createActionId?: string;
10
- updateActionId?: string;
11
- deleteActionId?: string;
12
9
  };
13
10
  declare const RepeatableField: (props: ObjectPropertyInputProps) => React.JSX.Element;
14
11
  export default RepeatableField;
@@ -34,7 +34,7 @@ const styles = {
34
34
  },
35
35
  };
36
36
  const RepeatableField = (props) => {
37
- const { fieldDefinition, canUpdateProperty, criteria, viewLayout, entry, createActionId, updateActionId, deleteActionId, } = props;
37
+ const { fieldDefinition, canUpdateProperty, criteria, viewLayout, entry } = props;
38
38
  const { fetchedOptions, setFetchedOptions, instance, width } = useFormContext();
39
39
  const { isBelow } = useWidgetSize({
40
40
  scroll: false,
@@ -62,9 +62,9 @@ const RepeatableField = (props) => {
62
62
  showAlert: false,
63
63
  isError: false,
64
64
  });
65
- const createAction = relatedObject?.actions?.find((item) => item.id === createActionId);
66
- const updateAction = relatedObject?.actions?.find((item) => item.id === updateActionId);
67
- const deleteAction = relatedObject?.actions?.find((item) => item.id === deleteActionId);
65
+ const createAction = relatedObject?.actions?.find((item) => item.id === entry.display?.createActionId);
66
+ const updateAction = relatedObject?.actions?.find((item) => item.id === entry.display?.updateActionId);
67
+ const deleteAction = relatedObject?.actions?.find((item) => item.id === entry.display?.deleteActionId);
68
68
  function getForm(setForm, action, formId) {
69
69
  if (formId || action?.defaultFormId) {
70
70
  apiServices
@@ -209,11 +209,11 @@ const RepeatableField = (props) => {
209
209
  }, [fetchCriteriaObjects, relatedObject]);
210
210
  useEffect(() => {
211
211
  if (createAction && !createForm)
212
- getForm(setCreateForm, createAction); // TODO: pass entry.display?.createForm as a third argument
212
+ getForm(setCreateForm, createAction, entry.display?.createFormId);
213
213
  if (updateAction && !updateForm)
214
- getForm(setUpdateForm, updateAction); // TODO: pass entry.display?.updateForm as a third argument
214
+ getForm(setUpdateForm, updateAction, entry.display?.updateFormId);
215
215
  if (deleteAction && !deleteForm)
216
- getForm(setDeleteForm, deleteAction); // TODO: pass entry.display?.deleteForm as a third argument
216
+ getForm(setDeleteForm, deleteAction, entry.display?.deleteFormId);
217
217
  }, [entry.display, createAction, updateAction, deleteAction]);
218
218
  useEffect(() => {
219
219
  if (relatedObject?.rootObjectId) {
@@ -269,10 +269,10 @@ const RepeatableField = (props) => {
269
269
  if (fieldDefinition.objectId && canUpdateProperty && !fetchedOptions[`${fieldDefinition.id}HasCreateAction`]) {
270
270
  apiServices
271
271
  .get(getPrefixedUrl(`/objects/${fieldDefinition.objectId}/instances/checkAccess`), {
272
- params: { action: 'execute', field: '_create', scope: 'data' },
272
+ params: { action: 'execute', field: entry.display?.createActionId, scope: 'data' },
273
273
  })
274
274
  .then((checkAccess) => {
275
- const action = relatedObject.actions?.find((item) => item.id === '_create');
275
+ const action = relatedObject.actions?.find((item) => item.id === entry.display?.createActionId);
276
276
  if (action && fieldDefinition.relatedPropertyId) {
277
277
  const { relatedObjectProperty, criteria } = retrieveCriteria(fieldDefinition.relatedPropertyId, action, relatedObject);
278
278
  if (!criteria || JSON.stringify(criteria).includes('{{{input.') || !relatedObjectProperty) {
@@ -346,17 +346,21 @@ const RepeatableField = (props) => {
346
346
  }, variant: "text", onClick: () => setReloadOnErrorTrigger((prevState) => !prevState) }, "Retry")));
347
347
  const save = async (input) => {
348
348
  const action = relatedObject?.actions?.find((a) => a.id ===
349
- (dialogType === 'create' ? createActionId : dialogType === 'update' ? updateActionId : deleteActionId));
349
+ (dialogType === 'create'
350
+ ? entry.display?.createActionId
351
+ : dialogType === 'update'
352
+ ? entry.display?.updateActionId
353
+ : entry.display?.deleteActionId));
350
354
  // when save is called we know that fieldDefinition is a parameter and fieldDefinition.objectId is defined
351
355
  input = await formatSubmission(input, apiServices, fieldDefinition.objectId, selectedInstanceId, action?.type === 'update' ? updateForm : undefined);
352
- if (action?.type === 'create' && createActionId) {
356
+ if (action?.type === 'create' && entry.display?.createActionId) {
353
357
  const updatedInput = {
354
358
  ...input,
355
359
  [fieldDefinition?.relatedPropertyId]: { id: instance?.id },
356
360
  };
357
361
  try {
358
362
  const instance = await apiServices.post(getPrefixedUrl(`/objects/${fieldDefinition.objectId}/instances/actions`), {
359
- actionId: createActionId,
363
+ actionId: entry.display?.createActionId,
360
364
  input: updatedInput,
361
365
  });
362
366
  const hasAccess = fieldDefinition?.relatedPropertyId && fieldDefinition.relatedPropertyId in instance;
@@ -519,12 +523,12 @@ const RepeatableField = (props) => {
519
523
  users?.find((user) => get(relatedInstance, `${prop.id.split('.')[0]}.id`) === user.id)?.status === 'Inactive' &&
520
524
  ' (Inactive)')))))),
521
525
  canUpdateProperty && (React.createElement(Box, { sx: { mt: 2, display: 'flex', gap: 1 } },
522
- React.createElement(IconButton, { onClick: () => editRow(relatedInstance.id) },
526
+ entry.display?.updateActionId && (React.createElement(IconButton, { onClick: () => editRow(relatedInstance.id) },
523
527
  React.createElement(Tooltip, { title: "Edit" },
524
- React.createElement(Edit, null))),
525
- React.createElement(IconButton, { onClick: () => deleteRow(relatedInstance.id) },
528
+ React.createElement(Edit, null)))),
529
+ entry.display?.deleteActionId && (React.createElement(IconButton, { onClick: () => deleteRow(relatedInstance.id) },
526
530
  React.createElement(Tooltip, { title: "Delete" },
527
- React.createElement(TrashCan, { sx: { ':hover': { color: '#A12723' } } }))))))))))) : (React.createElement(TableContainer, { sx: {
531
+ React.createElement(TrashCan, { sx: { ':hover': { color: '#A12723' } } })))))))))))) : (React.createElement(TableContainer, { sx: {
528
532
  borderRadius: '6px',
529
533
  border: '1px solid #919EAB3D',
530
534
  boxShadow: 'none',
@@ -544,7 +548,7 @@ const RepeatableField = (props) => {
544
548
  cursor: 'pointer',
545
549
  },
546
550
  }
547
- : {}, onClick: updateActionId &&
551
+ : {}, onClick: entry.display?.updateActionId &&
548
552
  canUpdateProperty &&
549
553
  prop.id === 'name'
550
554
  ? () => editRow(relatedInstance.id)
@@ -554,19 +558,19 @@ const RepeatableField = (props) => {
554
558
  users?.find((user) => get(relatedInstance, `${prop.id.split('.')[0]}.id`) === user.id)?.status === 'Inactive' && (React.createElement("span", null, ' (Inactive)'))))));
555
559
  }),
556
560
  canUpdateProperty && (React.createElement(TableCell, { sx: { width: '80px' } },
557
- updateActionId && (React.createElement(IconButton, { "aria-label": `edit-collection-instance-${index}`, onClick: () => editRow(relatedInstance.id) },
561
+ entry.display?.updateActionId && (React.createElement(IconButton, { "aria-label": `edit-collection-instance-${index}`, onClick: () => editRow(relatedInstance.id) },
558
562
  React.createElement(Tooltip, { title: "Edit" },
559
563
  React.createElement(Edit, null)))),
560
- React.createElement(IconButton, { "aria-label": `delete-collection-instance-${index}`, onClick: () => deleteRow(relatedInstance.id) },
564
+ entry.display?.deleteActionId && (React.createElement(IconButton, { "aria-label": `delete-collection-instance-${index}`, onClick: () => deleteRow(relatedInstance.id) },
561
565
  React.createElement(Tooltip, { title: "Delete" },
562
- React.createElement(TrashCan, { sx: { ':hover': { color: '#A12723' } } })))))))))))),
563
- hasCreateAction && createActionId && (React.createElement(Button, { variant: "contained", sx: styles.addButton, onClick: addRow, "aria-label": 'Add' }, "Add"))),
566
+ React.createElement(TrashCan, { sx: { ':hover': { color: '#A12723' } } }))))))))))))),
567
+ hasCreateAction && entry.display?.createActionId && (React.createElement(Button, { variant: "contained", sx: styles.addButton, onClick: addRow, "aria-label": 'Add' }, "Add"))),
564
568
  relatedObject && openDialog && (React.createElement(ActionDialog, { object: relatedObject, open: openDialog, onClose: () => setOpenDialog(false), onSubmit: save, action: relatedObject?.actions?.find((a) => a.id ===
565
569
  (dialogType === 'create'
566
- ? createActionId
570
+ ? entry.display?.createActionId
567
571
  : dialogType === 'update'
568
- ? updateActionId
569
- : deleteActionId)), relatedFormId: dialogType === 'create'
572
+ ? entry.display?.updateActionId
573
+ : entry.display?.deleteActionId)), relatedFormId: dialogType === 'create'
570
574
  ? createForm?.id
571
575
  : dialogType === 'update'
572
576
  ? updateForm?.id
@@ -90,9 +90,7 @@ export function RecursiveEntryRenderer(props) {
90
90
  ? display?.defaultValue.orderBy
91
91
  : undefined, defaultValueCriteria: typeof display?.defaultValue === 'object' && 'criteria' in display.defaultValue
92
92
  ? display?.defaultValue?.criteria
93
- : undefined, viewLayout: display?.viewLayout, hasDescription: !!display?.description,
94
- // formId={display?.createFormId} // TODO: this should be added as part of the builder update
95
- createActionId: '_create' })));
93
+ : undefined, viewLayout: display?.viewLayout, hasDescription: !!display?.description, formId: display?.createFormId, createActionId: display?.createActionId })));
96
94
  }
97
95
  else if (fieldDefinition.type === 'user') {
98
96
  return (React.createElement(FieldWrapper, { ...getFieldWrapperProps(fieldDefinition, entry, entryId, fieldValue, display, errors) },
@@ -101,7 +99,7 @@ export function RecursiveEntryRenderer(props) {
101
99
  else if (fieldDefinition.type === 'collection') {
102
100
  return fieldDefinition?.manyToManyPropertyId ? (middleObject && initialMiddleObjectInstances && (React.createElement(FieldWrapper, { ...getFieldWrapperProps(fieldDefinition, entry, entryId, fieldValue, display, errors) },
103
101
  React.createElement(DropdownRepeatableField, { initialMiddleObjectInstances: fetchedOptions[`${entryId}MiddleObjectInstances`] || initialMiddleObjectInstances, fieldDefinition: fieldDefinition, id: entryId, middleObject: middleObject, readOnly: entry.type === 'readonlyField', criteria: validation?.criteria, hasDescription: !!display?.description })))) : (React.createElement(FieldWrapper, { ...getFieldWrapperProps(fieldDefinition, entry, entryId, fieldValue, display, errors) },
104
- React.createElement(RepeatableField, { fieldDefinition: fieldDefinition, canUpdateProperty: entry.type !== 'readonlyField', criteria: validation?.criteria, viewLayout: display?.viewLayout, entry: entry, createActionId: '_create', updateActionId: '_update', deleteActionId: '_delete' })));
102
+ React.createElement(RepeatableField, { fieldDefinition: fieldDefinition, canUpdateProperty: entry.type !== 'readonlyField', criteria: validation?.criteria, viewLayout: display?.viewLayout, entry: entry })));
105
103
  }
106
104
  else if (fieldDefinition.type === 'richText') {
107
105
  return (React.createElement(FieldWrapper, { ...getFieldWrapperProps(fieldDefinition, entry, entryId, fieldValue, display, errors) }, richTextEditor ? (React.createElement(richTextEditor, {
@@ -156,18 +154,9 @@ export function RecursiveEntryRenderer(props) {
156
154
  : `${entryId}-reset-false`, ...getFieldWrapperProps(fieldDefinition, entry, entryId, fieldValue, display, errors), errorMessage: undefined },
157
155
  React.createElement(FormField, { id: entryId,
158
156
  // TODO: Ideally the FormField prop should be called parameter but can't change the name for backwards compatibility reasons
159
- property: fieldDefinition, defaultValue: fieldValue || getValues(entryId), onChange: handleChange, readOnly: entry.type === 'readonlyField', placeholder: display?.placeholder, mask: validation?.mask, isOptionEqualToValue: isOptionEqualToValue, error: !!errors?.[entryId], errorMessage: errors?.[entryId]?.message, isMultiLineText: !!display?.rowCount, rows: display?.rowCount, required: entry.display?.required || false, getOptionLabel: (option) => {
160
- if (typeof option === 'string') {
161
- return (entry?.enumWithLabels?.find((e) => e.value === option)
162
- ?.label ?? option);
163
- }
164
- else {
165
- return (entry?.enumWithLabels?.find((e) => e.value === option.value)?.label ?? String(option.value));
166
- }
167
- }, size: fieldHeight, sortBy: display?.choicesDisplay?.sortBy && display.choicesDisplay.sortBy, displayOption: fieldDefinition.type === 'boolean'
157
+ property: fieldDefinition, defaultValue: fieldValue || getValues(entryId), onChange: handleChange, readOnly: entry.type === 'readonlyField', placeholder: display?.placeholder, mask: validation?.mask, isOptionEqualToValue: isOptionEqualToValue, error: !!errors?.[entryId], errorMessage: errors?.[entryId]?.message, isMultiLineText: !!display?.rowCount, rows: display?.rowCount, required: entry.display?.required || false, size: fieldHeight, sortBy: display?.choicesDisplay?.sortBy && display.choicesDisplay.sortBy, displayOption: fieldDefinition.type === 'boolean'
168
158
  ? display?.booleanDisplay
169
- : display?.choicesDisplay?.type && display.choicesDisplay.type, label: display?.label, description: display?.description, tooltip: display?.tooltip, selectOptions: entry?.enumWithLabels &&
170
- entry.enumWithLabels, additionalProps: additionalProps, isCombobox: fieldDefinition.nonStrictEnum, strictlyTrue: fieldDefinition.strictlyTrue })));
159
+ : display?.choicesDisplay?.type && display.choicesDisplay.type, label: display?.label, description: display?.description, tooltip: display?.tooltip, selectOptions: fieldDefinition?.enum, additionalProps: additionalProps, isCombobox: fieldDefinition.nonStrictEnum, strictlyTrue: fieldDefinition.strictlyTrue })));
171
160
  }
172
161
  }
173
162
  else if (entry.type === 'columns') {
@@ -482,11 +482,6 @@ export function convertDocToEntries(document) {
482
482
  sortBy: 'ASC',
483
483
  },
484
484
  },
485
- enumWithLabels: [
486
- { label: 'Public', value: 'Public' },
487
- { label: 'Private', value: 'Private' },
488
- { label: 'Portal', value: 'Portal' },
489
- ],
490
485
  });
491
486
  }
492
487
  entries.push({
@@ -507,8 +502,8 @@ export function formatDataToDoc(data) {
507
502
  uploadedDate: data.uploadedDate,
508
503
  versionId: data.versionId,
509
504
  metadata: {
510
- type: data.type,
511
- view_permission: data.view_permission,
505
+ type: data.type ?? '',
506
+ view_permission: data.view_permission ?? '',
512
507
  },
513
508
  };
514
509
  }
@@ -650,6 +650,7 @@ describe('Form component', () => {
650
650
  parameterId: 'specialtyType',
651
651
  display: {
652
652
  label: 'Speciality Type',
653
+ createActionId: '_create',
653
654
  },
654
655
  },
655
656
  ],
@@ -922,6 +923,7 @@ describe('Form component', () => {
922
923
  display: {
923
924
  label: 'Speciality Type',
924
925
  relatedObjectDisplay: 'dropdown',
926
+ createActionId: '_create',
925
927
  },
926
928
  },
927
929
  ],
@@ -1021,4 +1023,210 @@ describe('Form component', () => {
1021
1023
  });
1022
1024
  });
1023
1025
  });
1026
+ describe('when passed a one-to-many collection entry', () => {
1027
+ const setupTestMocks = (object, form, instances) => {
1028
+ server.use(http.get(`/api/data/objects/${object.id}/effective`, () => HttpResponse.json(object)), http.get(`/api/data/forms/${form.id}`, () => HttpResponse.json(form)), http.get(`/api/data/forms?filter={"where":{"actionId":"${form.actionId}","objectId":"${object.id}"}}`, () => HttpResponse.json([form])), http.get(`/api/data/objects/${object.id}/instances`, () => HttpResponse.json(instances || [])), http.get(`/api/data/objects/${object.id}/instances/checkAccess`, () => HttpResponse.json({
1029
+ result: true,
1030
+ })));
1031
+ };
1032
+ const form = {
1033
+ id: 'collectionTestForm',
1034
+ name: 'Collection Test Form',
1035
+ entries: [
1036
+ {
1037
+ type: 'inputField',
1038
+ input: {
1039
+ id: 'collection',
1040
+ type: 'collection',
1041
+ objectId: 'collectionObject',
1042
+ relatedPropertyId: 'relatedObject',
1043
+ },
1044
+ display: {
1045
+ label: 'Collection',
1046
+ },
1047
+ },
1048
+ ],
1049
+ actionId: '_update',
1050
+ objectId: 'testObjectForCollections',
1051
+ };
1052
+ beforeEach(() => {
1053
+ const collectionFormObject = {
1054
+ id: 'testObjectForCollections',
1055
+ name: 'Object for one-to-many collections tests',
1056
+ actions: [
1057
+ {
1058
+ id: '_update',
1059
+ name: 'Update',
1060
+ type: 'update',
1061
+ outputEvent: 'updated',
1062
+ },
1063
+ ],
1064
+ properties: [
1065
+ {
1066
+ id: 'collection',
1067
+ name: 'Collection',
1068
+ type: 'collection',
1069
+ objectId: 'collectionObject',
1070
+ relatedPropertyId: 'relatedObject',
1071
+ },
1072
+ ],
1073
+ };
1074
+ setupTestMocks(collectionFormObject, form);
1075
+ const collectionObject = {
1076
+ id: 'collectionObject',
1077
+ name: 'Collection Object',
1078
+ properties: [
1079
+ {
1080
+ name: 'Name',
1081
+ id: 'name',
1082
+ type: 'string',
1083
+ },
1084
+ {
1085
+ name: 'Related Object',
1086
+ id: 'relatedObject',
1087
+ type: 'object',
1088
+ objectId: 'testObjectForCollections',
1089
+ },
1090
+ ],
1091
+ actions: [
1092
+ {
1093
+ id: '_create',
1094
+ name: 'Create',
1095
+ type: 'create',
1096
+ outputEvent: 'created',
1097
+ parameters: [
1098
+ {
1099
+ id: 'name',
1100
+ name: 'Name',
1101
+ type: 'string',
1102
+ },
1103
+ {
1104
+ id: 'relatedObject',
1105
+ name: 'Related Object',
1106
+ type: 'object',
1107
+ objectId: 'testObjectForCollections',
1108
+ },
1109
+ ],
1110
+ },
1111
+ ],
1112
+ };
1113
+ const collectionObjectForm = {
1114
+ id: 'collectionObjectForm',
1115
+ name: 'Collection Object Form',
1116
+ entries: [
1117
+ {
1118
+ type: 'input',
1119
+ parameterId: 'name',
1120
+ display: {
1121
+ label: 'Name',
1122
+ },
1123
+ },
1124
+ {
1125
+ type: 'input',
1126
+ parameterId: 'relatedObject',
1127
+ display: {
1128
+ label: 'Related Object',
1129
+ relatedObjectDisplay: 'dropdown',
1130
+ },
1131
+ },
1132
+ ],
1133
+ actionId: '_create',
1134
+ objectId: 'collectionObject',
1135
+ };
1136
+ setupTestMocks(collectionObject, collectionObjectForm);
1137
+ });
1138
+ it('should render collection field', async () => {
1139
+ render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
1140
+ await screen.findByText('Collection');
1141
+ });
1142
+ it('should not render an add button if user does not have permission to create collection items', async () => {
1143
+ server.use(http.get('/api/data/objects/collectionObject/instances/checkAccess', () => HttpResponse.json({
1144
+ result: false,
1145
+ })));
1146
+ render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
1147
+ const addButton = screen.queryByRole('button', { name: /add/i });
1148
+ expect(addButton).not.toBeInTheDocument();
1149
+ });
1150
+ it('should render an add button for the collection when user has permission to create collection items', async () => {
1151
+ render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
1152
+ await screen.findByRole('button', { name: /add/i });
1153
+ });
1154
+ it('should open a dialog when clicking the add button', async () => {
1155
+ const user = userEvent.setup();
1156
+ render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
1157
+ const addButton = await screen.findByRole('button', { name: /add/i });
1158
+ await user.click(addButton);
1159
+ await screen.findByRole('dialog');
1160
+ });
1161
+ it('should render a close button in the collection dialog', async () => {
1162
+ const user = userEvent.setup();
1163
+ render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
1164
+ const addButton = await screen.findByRole('button', { name: /add/i });
1165
+ await user.click(addButton);
1166
+ await screen.findByRole('button', { name: 'Close' });
1167
+ });
1168
+ it('should allow closing the collection dialog using the close button', async () => {
1169
+ const user = userEvent.setup();
1170
+ render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
1171
+ const addButton = await screen.findByRole('button', { name: /add/i });
1172
+ await user.click(addButton);
1173
+ const dialog = await screen.findByRole('dialog');
1174
+ const closeButton = await screen.findByRole('button', { name: 'Close' });
1175
+ await user.click(closeButton);
1176
+ await waitFor(() => expect(dialog).not.toBeInTheDocument());
1177
+ });
1178
+ it('shows a cancel button in the collection dialog', async () => {
1179
+ const user = userEvent.setup();
1180
+ render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
1181
+ await user.click(await screen.findByRole('button', { name: 'Add' }));
1182
+ await screen.findByRole('button', { name: 'Cancel' });
1183
+ });
1184
+ it('closes dialog in the collection dialog clicking cancel', async () => {
1185
+ const user = userEvent.setup();
1186
+ render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
1187
+ await user.click(await screen.findByRole('button', { name: 'Add' }));
1188
+ const dialog = await screen.findByRole('dialog');
1189
+ await user.click(await screen.findByRole('button', { name: 'Cancel' }));
1190
+ await waitFor(() => expect(dialog).not.toBeInTheDocument());
1191
+ });
1192
+ it('displays a submit button in the collection dialog', async () => {
1193
+ const user = userEvent.setup();
1194
+ render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
1195
+ await user.click(await screen.findByRole('button', { name: 'Add' }));
1196
+ await screen.findByRole('button', { name: 'Submit' });
1197
+ });
1198
+ it('should hide related object field in collection item form', async () => {
1199
+ const user = userEvent.setup();
1200
+ render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
1201
+ const addButton = await screen.findByRole('button', { name: /add/i });
1202
+ await user.click(addButton);
1203
+ await screen.findByRole('dialog');
1204
+ // Make sure other form entry is present
1205
+ await screen.findByRole('textbox', { name: 'Name' });
1206
+ const relatedObjectField = screen.queryByRole('textbox', { name: 'Related Object' });
1207
+ expect(relatedObjectField).not.toBeInTheDocument();
1208
+ });
1209
+ it('should add newly created collection item to the collection list upon submission', async () => {
1210
+ const user = userEvent.setup();
1211
+ server.use(http.post('/api/data/objects/collectionObject/instances/actions', () => HttpResponse.json({
1212
+ id: 'newCollectionItemId',
1213
+ name: 'New Collection Item',
1214
+ objectId: 'collectionObject',
1215
+ relatedObject: {
1216
+ id: 'testInstanceId',
1217
+ name: 'Test Instance',
1218
+ },
1219
+ })));
1220
+ render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
1221
+ const addButton = await screen.findByRole('button', { name: /add/i });
1222
+ await user.click(addButton);
1223
+ await screen.findByRole('dialog');
1224
+ const nameField = screen.getByRole('textbox', { name: 'Name' });
1225
+ await user.type(nameField, 'New Collection Item');
1226
+ const submitButton = screen.getByRole('button', { name: 'Submit' });
1227
+ await user.click(submitButton);
1228
+ await screen.findByRole('columnheader', { name: 'Name' });
1229
+ screen.getByRole('cell', { name: 'New Collection Item' });
1230
+ });
1231
+ });
1024
1232
  });
@@ -116,6 +116,8 @@ export const UpdateAccessibilityFormOne = {
116
116
  display: {
117
117
  label: 'License',
118
118
  relatedObjectDisplay: 'dropdown',
119
+ createActionId: '_create',
120
+ createFormId: 'specialtyForm',
119
121
  },
120
122
  },
121
123
  ],
@@ -196,7 +196,7 @@ export const mockMovieObject = {
196
196
  id: 'customers',
197
197
  name: 'Customers',
198
198
  type: 'collection',
199
- objectId: 'costomerMovie',
199
+ objectId: 'customerMovie',
200
200
  relatedPropertyId: 'movie',
201
201
  manyToManyPropertyId: 'customer',
202
202
  },
@@ -533,20 +533,6 @@ export const mockEvokeForm = {
533
533
  display: {
534
534
  label: 'Multi-Select',
535
535
  },
536
- enumWithLabels: [
537
- {
538
- label: '1',
539
- value: '1',
540
- },
541
- {
542
- label: '2',
543
- value: '2',
544
- },
545
- {
546
- label: '3',
547
- value: '3',
548
- },
549
- ],
550
536
  },
551
537
  {
552
538
  type: 'input',
@@ -571,6 +557,8 @@ export const mockEvokeForm = {
571
557
  parameterId: 'collection',
572
558
  display: {
573
559
  label: 'Collection',
560
+ createActionId: '_create',
561
+ createFormId: 'customerCreateForm',
574
562
  },
575
563
  },
576
564
  {
@@ -815,20 +803,6 @@ export const mockDocEvokeForm = {
815
803
  sortBy: 'ASC',
816
804
  },
817
805
  },
818
- enumWithLabels: [
819
- {
820
- label: 'Public',
821
- value: 'Public',
822
- },
823
- {
824
- label: 'Private',
825
- value: 'Private',
826
- },
827
- {
828
- label: 'Portal',
829
- value: 'Portal',
830
- },
831
- ],
832
806
  },
833
807
  {
834
808
  type: 'readonlyField',
@@ -887,20 +861,6 @@ export const mockEvokeFormWithSections = {
887
861
  display: {
888
862
  label: 'Multi-Select',
889
863
  },
890
- enumWithLabels: [
891
- {
892
- label: '1',
893
- value: '1',
894
- },
895
- {
896
- label: '2',
897
- value: '2',
898
- },
899
- {
900
- label: '3',
901
- value: '3',
902
- },
903
- ],
904
864
  },
905
865
  {
906
866
  type: 'input',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evoke-platform/ui-components",
3
- "version": "1.10.0-dev.2",
3
+ "version": "1.10.0-dev.4",
4
4
  "description": "",
5
5
  "main": "dist/published/index.js",
6
6
  "module": "dist/published/index.js",