@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.
- package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.js +3 -0
- package/dist/published/components/custom/Form/utils.d.ts +2 -2
- package/dist/published/components/custom/FormField/AddressFieldComponent/addressFieldComponent.js +1 -1
- package/dist/published/components/custom/FormField/BooleanSelect/BooleanSelect.js +15 -7
- package/dist/published/components/custom/FormField/InputFieldComponent/InputFieldComponent.js +1 -1
- package/dist/published/components/custom/FormField/Select/Select.js +1 -1
- package/dist/published/components/custom/FormV2/FormRenderer.d.ts +1 -0
- package/dist/published/components/custom/FormV2/FormRenderer.js +12 -7
- package/dist/published/components/custom/FormV2/FormRendererContainer.d.ts +1 -0
- package/dist/published/components/custom/FormV2/FormRendererContainer.js +52 -31
- package/dist/published/components/custom/FormV2/components/Body.d.ts +1 -0
- package/dist/published/components/custom/FormV2/components/Body.js +4 -2
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableFieldInput.js +3 -0
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/RepeatableField.js +8 -6
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/Document.js +1 -0
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/Image.js +1 -0
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/UserProperty.js +2 -0
- package/dist/published/components/custom/FormV2/components/FormletRenderer.d.ts +7 -0
- package/dist/published/components/custom/FormV2/components/FormletRenderer.js +22 -0
- package/dist/published/components/custom/FormV2/components/HtmlView.js +16 -9
- package/dist/published/components/custom/FormV2/components/MisconfiguredErrorMessage.d.ts +2 -0
- package/dist/published/components/custom/FormV2/components/MisconfiguredErrorMessage.js +15 -0
- package/dist/published/components/custom/FormV2/components/RecursiveEntryRenderer.js +17 -24
- package/dist/published/components/custom/FormV2/components/types.d.ts +2 -1
- package/dist/published/components/custom/FormV2/components/utils.d.ts +7 -2
- package/dist/published/components/custom/FormV2/components/utils.js +84 -4
- package/dist/published/components/custom/FormV2/tests/FormRenderer.test.js +228 -7
- package/dist/published/components/custom/FormV2/tests/FormRendererContainer.test.js +491 -35
- package/dist/published/components/custom/ViewDetailsV2/InstanceEntryRenderer.js +20 -9
- package/dist/published/components/custom/ViewDetailsV2/ViewDetailsV2Container.js +1 -0
- package/dist/published/stories/FormRenderer.stories.d.ts +3 -0
- package/dist/published/stories/FormRenderer.stories.js +1 -0
- package/dist/published/stories/FormRendererContainer.stories.d.ts +5 -0
- package/dist/published/stories/FormRendererData.d.ts +15 -0
- package/dist/published/stories/FormRendererData.js +63 -0
- package/dist/published/stories/sharedMswHandlers.js +4 -2
- 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 ??
|
|
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
|
|
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
|
|
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
|
-
:
|
|
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()
|
|
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
|
-
|
|
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
|
}>;
|
|
@@ -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
|
|
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':
|