@evoke-platform/ui-components 1.16.0 → 1.18.0

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.
Files changed (37) hide show
  1. package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.js +3 -0
  2. package/dist/published/components/custom/Form/utils.d.ts +2 -2
  3. package/dist/published/components/custom/FormField/AddressFieldComponent/addressFieldComponent.js +1 -1
  4. package/dist/published/components/custom/FormField/BooleanSelect/BooleanSelect.js +15 -7
  5. package/dist/published/components/custom/FormField/InputFieldComponent/InputFieldComponent.js +1 -1
  6. package/dist/published/components/custom/FormField/Select/Select.js +1 -1
  7. package/dist/published/components/custom/FormV2/FormRenderer.d.ts +1 -0
  8. package/dist/published/components/custom/FormV2/FormRenderer.js +12 -7
  9. package/dist/published/components/custom/FormV2/FormRendererContainer.d.ts +1 -0
  10. package/dist/published/components/custom/FormV2/FormRendererContainer.js +52 -31
  11. package/dist/published/components/custom/FormV2/components/Body.d.ts +1 -0
  12. package/dist/published/components/custom/FormV2/components/Body.js +4 -2
  13. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableFieldInput.js +3 -0
  14. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/RepeatableField.js +8 -6
  15. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/Document.js +1 -0
  16. package/dist/published/components/custom/FormV2/components/FormFieldTypes/Image.js +1 -0
  17. package/dist/published/components/custom/FormV2/components/FormFieldTypes/UserProperty.js +2 -0
  18. package/dist/published/components/custom/FormV2/components/FormletRenderer.d.ts +7 -0
  19. package/dist/published/components/custom/FormV2/components/FormletRenderer.js +22 -0
  20. package/dist/published/components/custom/FormV2/components/HtmlView.js +16 -9
  21. package/dist/published/components/custom/FormV2/components/MisconfiguredErrorMessage.d.ts +2 -0
  22. package/dist/published/components/custom/FormV2/components/MisconfiguredErrorMessage.js +15 -0
  23. package/dist/published/components/custom/FormV2/components/RecursiveEntryRenderer.js +17 -24
  24. package/dist/published/components/custom/FormV2/components/types.d.ts +2 -1
  25. package/dist/published/components/custom/FormV2/components/utils.d.ts +7 -2
  26. package/dist/published/components/custom/FormV2/components/utils.js +84 -4
  27. package/dist/published/components/custom/FormV2/tests/FormRenderer.test.js +228 -7
  28. package/dist/published/components/custom/FormV2/tests/FormRendererContainer.test.js +491 -35
  29. package/dist/published/components/custom/ViewDetailsV2/InstanceEntryRenderer.js +20 -9
  30. package/dist/published/components/custom/ViewDetailsV2/ViewDetailsV2Container.js +1 -0
  31. package/dist/published/stories/FormRenderer.stories.d.ts +3 -0
  32. package/dist/published/stories/FormRenderer.stories.js +1 -0
  33. package/dist/published/stories/FormRendererContainer.stories.d.ts +5 -0
  34. package/dist/published/stories/FormRendererData.d.ts +15 -0
  35. package/dist/published/stories/FormRendererData.js +63 -0
  36. package/dist/published/stories/sharedMswHandlers.js +4 -2
  37. package/package.json +1 -1
@@ -19,6 +19,8 @@ import { Image } from '../FormV2/components/FormFieldTypes/Image';
19
19
  import PropertyProtection from '../FormV2/components/PropertyProtection';
20
20
  import { entryIsVisible, fetchInitialMiddleObjectInstances, fetchMiddleObject, filterEmptySections, getDefaultPages, isAddressProperty, } from '../FormV2/components/utils';
21
21
  import HtmlView from '../FormV2/components/HtmlView';
22
+ import FormletRenderer from '../FormV2/components/FormletRenderer';
23
+ import MisconfiguredErrorMessage from '../FormV2/components/MisconfiguredErrorMessage';
22
24
  function ViewOnlyEntryRenderer(props) {
23
25
  const { entry } = props;
24
26
  const { fetchedOptions, setFetchedOptions, object, instance, richTextEditor: RichTextEditor } = useFormContext();
@@ -29,6 +31,7 @@ function ViewOnlyEntryRenderer(props) {
29
31
  const [currentDisplayValue, setCurrentDisplayValue] = useState(instance?.[entryId]);
30
32
  const [protectionMode, setProtectionMode] = useState('mask');
31
33
  const display = 'display' in entry ? entry.display : undefined;
34
+ const isReference = (value) => !!value && typeof value === 'object' && 'id' in value && 'name' in value;
32
35
  const fieldDefinition = useMemo(() => {
33
36
  const def = entry.type === 'readonlyField'
34
37
  ? isAddressProperty(entry.propertyId)
@@ -111,14 +114,14 @@ function ViewOnlyEntryRenderer(props) {
111
114
  return (React.createElement(AddressFields, { entry: entry, viewOnly: true, entryId: entryId, fieldDefinition: fieldDefinition }));
112
115
  }
113
116
  else {
114
- let fieldValue = currentDisplayValue ?? (instance?.[entryId] || '');
117
+ let fieldValue = currentDisplayValue ?? instance?.[entryId];
115
118
  switch (fieldDefinition?.type) {
116
119
  case 'object':
117
- if (navigationSlug && fieldDefinition?.objectId) {
120
+ if (navigationSlug && fieldDefinition?.objectId && isReference(fieldValue)) {
118
121
  return (React.createElement(FieldWrapper, { inputId: entryId, inputType: "object", label: display?.label || fieldDefinition?.name || 'default', value: fieldValue, required: display?.required || false, viewOnly: true },
119
122
  React.createElement(Link, { sx: { cursor: 'pointer', fontFamily: 'sans-serif' }, href: `${'/app'}${navigationSlug.replace(':instanceId', fieldValue.id)}` }, fieldValue.name)));
120
123
  }
121
- fieldValue = fieldValue.name;
124
+ fieldValue = isReference(fieldValue) ? fieldValue.name : undefined;
122
125
  break;
123
126
  case 'array':
124
127
  if (!isEmpty(fieldValue)) {
@@ -129,24 +132,29 @@ function ViewOnlyEntryRenderer(props) {
129
132
  }
130
133
  break;
131
134
  case 'user':
132
- fieldValue = fieldValue && fieldValue.name;
135
+ fieldValue = isReference(fieldValue) ? fieldValue.name : undefined;
133
136
  break;
134
137
  case 'date':
135
138
  fieldValue =
136
139
  isProtectedProperty && protectionMode === 'mask'
137
140
  ? fieldValue
138
- : fieldValue && DateTime.fromISO(fieldValue).toFormat('MM/dd/yyyy');
141
+ : typeof fieldValue === 'string'
142
+ ? DateTime.fromISO(fieldValue).toFormat('MM/dd/yyyy')
143
+ : undefined;
139
144
  break;
140
145
  case 'date-time':
141
146
  fieldValue =
142
147
  fieldValue && fieldValue instanceof Date
143
148
  ? DateTime.fromJSDate(fieldValue).toFormat('MM/dd/yyyy hh:mm a')
144
- : fieldValue && DateTime.fromISO(fieldValue).toFormat('MM/dd/yyyy hh:mm a');
149
+ : typeof fieldValue === 'string'
150
+ ? DateTime.fromISO(fieldValue).toFormat('MM/dd/yyyy hh:mm a')
151
+ : undefined;
145
152
  break;
146
153
  case 'time':
147
154
  fieldValue =
148
- fieldValue &&
149
- DateTime.fromISO(DateTime.now().toISODate() + 'T' + fieldValue).toFormat('hh:mm a');
155
+ typeof fieldValue === 'string'
156
+ ? DateTime.fromISO(`${DateTime.now().toISODate()}T${fieldValue}`).toFormat('hh:mm a')
157
+ : undefined;
150
158
  break;
151
159
  default:
152
160
  break;
@@ -200,6 +208,9 @@ function ViewOnlyEntryRenderer(props) {
200
208
  const filteredEntry = filterEmptySections(entry, instance);
201
209
  return filteredEntry ? React.createElement(AccordionSections, { entry: filteredEntry, readOnly: true }) : null;
202
210
  }
203
- return null;
211
+ else if (entry.type === 'formlet') {
212
+ return React.createElement(FormletRenderer, { entry: entry, readOnly: true });
213
+ }
214
+ return React.createElement(MisconfiguredErrorMessage, null);
204
215
  }
205
216
  export default ViewOnlyEntryRenderer;
@@ -131,6 +131,7 @@ function ViewDetailsV2ContainerInner(props) {
131
131
  onCollapseAll: handleCollapseAll,
132
132
  expandedSections,
133
133
  hasAccordions: hasSections,
134
+ readOnly: true,
134
135
  })
135
136
  : updatedEntries.map((entry, index) => (React.createElement(ViewOnlyEntryRenderer, { entry: entry, key: index }))))))) : (React.createElement(Box, { sx: { padding: '20px' } },
136
137
  React.createElement(Box, { display: 'flex', width: '100%', justifyContent: 'space-between' },
@@ -19,6 +19,7 @@ declare const _default: import("@storybook/types").ComponentAnnotations<import("
19
19
  } | undefined;
20
20
  renderHeader?: ((props: import("../components/custom").HeaderProps) => React.ReactNode) | undefined;
21
21
  renderBody?: ((props: import("../components/custom").BodyProps) => React.ReactNode) | undefined;
22
+ readOnly?: boolean | undefined;
22
23
  renderFooter?: ((props: import("../components/custom").FooterProps) => React.ReactNode) | undefined;
23
24
  }>;
24
25
  export default _default;
@@ -42,6 +43,7 @@ export declare const Editable: import("@storybook/types").AnnotatedStoryFn<impor
42
43
  } | undefined;
43
44
  renderHeader?: ((props: import("../components/custom").HeaderProps) => React.ReactNode) | undefined;
44
45
  renderBody?: ((props: import("../components/custom").BodyProps) => React.ReactNode) | undefined;
46
+ readOnly?: boolean | undefined;
45
47
  renderFooter?: ((props: import("../components/custom").FooterProps) => React.ReactNode) | undefined;
46
48
  }>;
47
49
  export declare const NoButtons: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0fc72a6d").R, import("../components/custom/FormV2/components/types").BaseProps & {
@@ -64,5 +66,6 @@ export declare const NoButtons: import("@storybook/types").AnnotatedStoryFn<impo
64
66
  } | undefined;
65
67
  renderHeader?: ((props: import("../components/custom").HeaderProps) => React.ReactNode) | undefined;
66
68
  renderBody?: ((props: import("../components/custom").BodyProps) => React.ReactNode) | undefined;
69
+ readOnly?: boolean | undefined;
67
70
  renderFooter?: ((props: import("../components/custom").FooterProps) => React.ReactNode) | undefined;
68
71
  }>;
@@ -27,6 +27,7 @@ const mockProps = {
27
27
  fieldHeight: 'medium',
28
28
  form: mockEvokeForm,
29
29
  instance: instance,
30
+ readOnly: false,
30
31
  };
31
32
  const Template = (args) => {
32
33
  const [formDataState, setFormDataState] = React.useState(formData);
@@ -10,6 +10,7 @@ declare const _default: import("@storybook/types").ComponentAnnotations<import("
10
10
  } | undefined;
11
11
  display?: {
12
12
  fieldHeight?: "medium" | "small" | undefined;
13
+ readOnly?: boolean | undefined;
13
14
  } | undefined;
14
15
  actionId?: string | undefined;
15
16
  objectId: string;
@@ -43,6 +44,7 @@ export declare const Editable: import("@storybook/types").AnnotatedStoryFn<impor
43
44
  } | undefined;
44
45
  display?: {
45
46
  fieldHeight?: "medium" | "small" | undefined;
47
+ readOnly?: boolean | undefined;
46
48
  } | undefined;
47
49
  actionId?: string | undefined;
48
50
  objectId: string;
@@ -75,6 +77,7 @@ export declare const DefaultForm: import("@storybook/types").AnnotatedStoryFn<im
75
77
  } | undefined;
76
78
  display?: {
77
79
  fieldHeight?: "medium" | "small" | undefined;
80
+ readOnly?: boolean | undefined;
78
81
  } | undefined;
79
82
  actionId?: string | undefined;
80
83
  objectId: string;
@@ -107,6 +110,7 @@ export declare const NoButtons: import("@storybook/types").AnnotatedStoryFn<impo
107
110
  } | undefined;
108
111
  display?: {
109
112
  fieldHeight?: "medium" | "small" | undefined;
113
+ readOnly?: boolean | undefined;
110
114
  } | undefined;
111
115
  actionId?: string | undefined;
112
116
  objectId: string;
@@ -139,6 +143,7 @@ export declare const FormWithSections: import("@storybook/types").AnnotatedStory
139
143
  } | undefined;
140
144
  display?: {
141
145
  fieldHeight?: "medium" | "small" | undefined;
146
+ readOnly?: boolean | undefined;
142
147
  } | undefined;
143
148
  actionId?: string | undefined;
144
149
  objectId: string;
@@ -121,3 +121,18 @@ export declare const customerLayout: {
121
121
  };
122
122
  objectId: string;
123
123
  };
124
+ export declare const formlet: {
125
+ id: string;
126
+ name: string;
127
+ entries: {
128
+ type: string;
129
+ input: {
130
+ type: string;
131
+ id: string;
132
+ };
133
+ display: {
134
+ label: string;
135
+ required: boolean;
136
+ };
137
+ }[];
138
+ };
@@ -571,6 +571,29 @@ export const mockEvokeForm = {
571
571
  label: 'User',
572
572
  },
573
573
  },
574
+ {
575
+ display: {
576
+ booleanDisplay: 'checkbox',
577
+ label: 'Boolean',
578
+ required: false,
579
+ },
580
+ type: 'inputField',
581
+ input: {
582
+ type: 'boolean',
583
+ id: 'boolean',
584
+ },
585
+ },
586
+ {
587
+ type: 'inputField',
588
+ input: {
589
+ type: 'image',
590
+ id: 'image',
591
+ },
592
+ display: {
593
+ label: 'Image',
594
+ required: false,
595
+ },
596
+ },
574
597
  ],
575
598
  objectId: 'genericEvokeForm',
576
599
  actionId: '_update',
@@ -898,6 +921,28 @@ export const mockEvokeFormWithSections = {
898
921
  },
899
922
  ],
900
923
  },
924
+ {
925
+ label: 'Nested Section 3',
926
+ entries: [
927
+ // This is how effective forms will show formlets
928
+ {
929
+ type: 'inputField',
930
+ input: {
931
+ type: 'date',
932
+ id: 'dateId1',
933
+ },
934
+ display: {
935
+ label: 'Date 1',
936
+ required: false,
937
+ },
938
+ },
939
+ // This is how non effective forms will show formlets
940
+ {
941
+ type: 'formlet',
942
+ formletId: 'formletId',
943
+ },
944
+ ],
945
+ },
901
946
  ],
902
947
  },
903
948
  ],
@@ -1057,3 +1102,21 @@ export const customerLayout = {
1057
1102
  },
1058
1103
  objectId: 'customers',
1059
1104
  };
1105
+ // Formlets
1106
+ export const formlet = {
1107
+ id: 'formletId',
1108
+ name: 'Formlet with no objectId',
1109
+ entries: [
1110
+ {
1111
+ type: 'inputField',
1112
+ input: {
1113
+ type: 'date',
1114
+ id: 'dateId2',
1115
+ },
1116
+ display: {
1117
+ label: 'Date 2',
1118
+ required: false,
1119
+ },
1120
+ },
1121
+ ],
1122
+ };
@@ -1,5 +1,5 @@
1
1
  import { http, HttpResponse } from 'msw';
2
- import { customerLayout, instance, mockCustomerCreateForm, mockCustomerObject, mockCustomerUpdateForm, mockEvokeForm, mockEvokeFormWithSections, mockGenericEvokeFormObject, mockInstancesForCollection, mockInstancesForRelatedObject, mockMovieCreateForm, mockMovieObject, mockPeopleGenericObject, mockPeopleGenericObjectInstances, mockPeopleObject, mockPropertiesForCriteria, users, } from './FormRendererData';
2
+ import { customerLayout, formlet, instance, mockCustomerCreateForm, mockCustomerObject, mockCustomerUpdateForm, mockEvokeForm, mockEvokeFormWithSections, mockGenericEvokeFormObject, mockInstancesForCollection, mockInstancesForRelatedObject, mockMovieCreateForm, mockMovieObject, mockPeopleGenericObject, mockPeopleGenericObjectInstances, mockPeopleObject, mockPropertiesForCriteria, users, } from './FormRendererData';
3
3
  import { mockGenericEvokeView, mockGenericEvokeViewWithSections, viewInstance } from './ViewDetailsV2Data';
4
4
  export const sharedObjectHandlers = [
5
5
  // Object fetches
@@ -55,6 +55,8 @@ export const sharedObjectHandlers = [
55
55
  http.get(/\/checkAccess$/, () => HttpResponse.json({ result: true })),
56
56
  // Layout fetches
57
57
  http.get('/api/data/objects/customers/tableLayouts/layoutId', () => HttpResponse.json(customerLayout)),
58
+ // Formlet fetches
59
+ http.get('/api/data/formlets/formletId', () => HttpResponse.json(formlet)),
58
60
  // General instance fetches
59
61
  http.get('/api/data/objects/:objectId/instances/:instanceId?', ({ params }) => {
60
62
  const { objectId, instanceId } = params;
@@ -104,7 +106,7 @@ export const sharedObjectHandlers = [
104
106
  return HttpResponse.json(data);
105
107
  }),
106
108
  // Form fetches
107
- http.get('/api/data/forms/:formId?', ({ params, request }) => {
109
+ http.get('/api/data/forms/:formId/effective', ({ params, request }) => {
108
110
  const formId = Array.isArray(params.formId) ? params.formId[0] : params.formId;
109
111
  switch (formId) {
110
112
  case 'customerUpdateForm':
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evoke-platform/ui-components",
3
- "version": "1.16.0",
3
+ "version": "1.18.0",
4
4
  "description": "",
5
5
  "main": "dist/published/index.js",
6
6
  "module": "dist/published/index.js",