@pareto-engineering/design-system 4.9.3 → 4.10.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/cjs/b/Button/styles.scss +1 -0
- package/dist/cjs/g/FormBuilder/FormBuilder.js +3 -3
- package/dist/cjs/g/FormBuilder/common/Renderer/Renderer.js +38 -38
- package/dist/cjs/g/FormBuilder/common/Renderer/common/Section/Section.js +34 -8
- package/dist/es/b/Button/styles.scss +1 -0
- package/dist/es/g/FormBuilder/FormBuilder.js +3 -3
- package/dist/es/g/FormBuilder/common/Renderer/Renderer.js +39 -39
- package/dist/es/g/FormBuilder/common/Renderer/common/Section/Section.js +35 -9
- package/package.json +2 -2
- package/src/ui/b/Button/styles.scss +1 -0
- package/src/ui/g/FormBuilder/FormBuilder.jsx +2 -2
- package/src/ui/g/FormBuilder/common/Renderer/Renderer.jsx +40 -39
- package/src/ui/g/FormBuilder/common/Renderer/common/Section/Section.jsx +41 -10
- package/tests/__snapshots__/Storyshots.test.js.snap +1 -1
|
@@ -34,8 +34,8 @@ const FormBuilder = _ref => {
|
|
|
34
34
|
formBuilderId,
|
|
35
35
|
onBuilderFormSave,
|
|
36
36
|
onBuilderError,
|
|
37
|
-
onRendererError,
|
|
38
37
|
onRendererFormSave,
|
|
38
|
+
onFileUpload,
|
|
39
39
|
onBuilderValidate,
|
|
40
40
|
initialBuilderValues,
|
|
41
41
|
fileUploadStatus,
|
|
@@ -62,9 +62,9 @@ const FormBuilder = _ref => {
|
|
|
62
62
|
onSave: onRendererFormSave,
|
|
63
63
|
readOnly: readOnly,
|
|
64
64
|
shouldSubmit: shouldSubmit,
|
|
65
|
-
onError: onRendererError,
|
|
66
65
|
fileUploadStatus: fileUploadStatus,
|
|
67
|
-
handleFileDelete: handleFileDelete
|
|
66
|
+
handleFileDelete: handleFileDelete,
|
|
67
|
+
onFileUpload: onFileUpload
|
|
68
68
|
}));
|
|
69
69
|
};
|
|
70
70
|
FormBuilder.propTypes = {
|
|
@@ -18,28 +18,6 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
|
|
|
18
18
|
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } /* @pareto-engineering/generator-front 1.1.1-alpha.2 */ // Local Definitions
|
|
19
19
|
const baseClassName = _exports.default.base;
|
|
20
20
|
const componentClassName = 'renderer';
|
|
21
|
-
const reconstructFormDataWithValues = (formData, values) => {
|
|
22
|
-
const valuesMap = {};
|
|
23
|
-
Object.keys(values).forEach(async key => {
|
|
24
|
-
if (key.includes('files')) {
|
|
25
|
-
const files = values[key].map(file => file instanceof File ? URL.createObjectURL(file) : file);
|
|
26
|
-
valuesMap[key] = files;
|
|
27
|
-
} else {
|
|
28
|
-
valuesMap[key] = values[key];
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
const newData = {
|
|
32
|
-
...formData,
|
|
33
|
-
sections: formData.sections.map(section => ({
|
|
34
|
-
...section,
|
|
35
|
-
inputs: section.inputs.map(input => ({
|
|
36
|
-
...input,
|
|
37
|
-
value: valuesMap[input.name] !== undefined ? valuesMap[input.name] : input.value
|
|
38
|
-
}))
|
|
39
|
-
}))
|
|
40
|
-
};
|
|
41
|
-
return newData;
|
|
42
|
-
};
|
|
43
21
|
const validate = (currentSectionIndex, formData, values) => {
|
|
44
22
|
const errors = {};
|
|
45
23
|
const hasAtLeastOneValue = Object.keys(values).some(valueKey => {
|
|
@@ -58,6 +36,25 @@ const validate = (currentSectionIndex, formData, values) => {
|
|
|
58
36
|
});
|
|
59
37
|
return errors;
|
|
60
38
|
};
|
|
39
|
+
const reconstructFormDataWithValues = (formData, values) => {
|
|
40
|
+
const valuesMap = {};
|
|
41
|
+
Object.keys(values).forEach(async key => {
|
|
42
|
+
if (!key.includes('files')) {
|
|
43
|
+
valuesMap[key] = values[key];
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
const newData = {
|
|
47
|
+
...formData,
|
|
48
|
+
sections: formData.sections.map(section => ({
|
|
49
|
+
...section,
|
|
50
|
+
inputs: section.inputs.map(input => ({
|
|
51
|
+
...input,
|
|
52
|
+
value: valuesMap[input.name] !== undefined ? valuesMap[input.name] : input.value
|
|
53
|
+
}))
|
|
54
|
+
}))
|
|
55
|
+
};
|
|
56
|
+
return newData;
|
|
57
|
+
};
|
|
61
58
|
|
|
62
59
|
/**
|
|
63
60
|
* This is the component description.
|
|
@@ -70,15 +67,18 @@ const Renderer = _ref => {
|
|
|
70
67
|
formData,
|
|
71
68
|
readOnly,
|
|
72
69
|
onSave,
|
|
73
|
-
onError,
|
|
74
70
|
shouldSubmit,
|
|
75
71
|
fileUploadStatus,
|
|
76
|
-
handleFileDelete
|
|
72
|
+
handleFileDelete,
|
|
73
|
+
onFileUpload,
|
|
74
|
+
shouldUpdateInputStateInRealTime = true
|
|
77
75
|
// ...otherProps
|
|
78
76
|
} = _ref;
|
|
79
77
|
const [currentSectionIndex, setCurrentSectionIndex] = (0, _react.useState)(0);
|
|
80
78
|
const [sectionHistory, setSectionHistory] = (0, _react.useState)([]);
|
|
81
|
-
const [updatedFormData, setUpdatedFormData] = (0, _react.useState)(
|
|
79
|
+
const [updatedFormData, setUpdatedFormData] = (0, _react.useState)({
|
|
80
|
+
...formData
|
|
81
|
+
});
|
|
82
82
|
(0, _react.useEffect)(() => {
|
|
83
83
|
setUpdatedFormData(formData);
|
|
84
84
|
}, [formData]);
|
|
@@ -118,6 +118,9 @@ const Renderer = _ref => {
|
|
|
118
118
|
}
|
|
119
119
|
};
|
|
120
120
|
const isSubmit = currentSectionIndex === updatedFormData.sections.length - 1 || updatedFormData.sections[currentSectionIndex].navigation.nextSection === 'submit';
|
|
121
|
+
const ref = (0, _react.useRef)(null);
|
|
122
|
+
const currentSectionInputs = updatedFormData.sections[currentSectionIndex].inputs;
|
|
123
|
+
const hasErrorsOnInitialRender = currentSectionInputs.some(input => input.required && !ref.current?.values[input.name] || ref.current?.errors[input.name]);
|
|
121
124
|
return /*#__PURE__*/React.createElement("div", {
|
|
122
125
|
id: id,
|
|
123
126
|
className: [baseClassName, componentClassName, userClassName].filter(e => e).join(' '),
|
|
@@ -125,31 +128,28 @@ const Renderer = _ref => {
|
|
|
125
128
|
}, /*#__PURE__*/React.createElement(_formik.Formik, {
|
|
126
129
|
initialValues: initialValues,
|
|
127
130
|
onSubmit: handleSubmit,
|
|
128
|
-
validate: values => validate(currentSectionIndex,
|
|
131
|
+
validate: values => validate(currentSectionIndex, updatedFormData, values),
|
|
132
|
+
innerRef: ref
|
|
129
133
|
}, _ref2 => {
|
|
130
134
|
let {
|
|
131
135
|
values,
|
|
132
136
|
errors
|
|
133
137
|
} = _ref2;
|
|
134
138
|
(0, _react.useEffect)(() => {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
139
|
+
if (shouldUpdateInputStateInRealTime) {
|
|
140
|
+
const formDataWithValues = reconstructFormDataWithValues(updatedFormData, values);
|
|
141
|
+
onSave?.(formDataWithValues);
|
|
142
|
+
}
|
|
138
143
|
}, [values]);
|
|
139
|
-
(0, _react.useEffect)(() => {
|
|
140
|
-
onError?.({
|
|
141
|
-
errors,
|
|
142
|
-
values
|
|
143
|
-
});
|
|
144
|
-
}, [errors, values]);
|
|
145
144
|
const hasErrors = Object.keys(errors).length > 0;
|
|
146
145
|
return /*#__PURE__*/React.createElement(_formik.Form, null, updatedFormData.sections.map((section, sectionIndex) => sectionIndex === currentSectionIndex && /*#__PURE__*/React.createElement(_common.Section, _extends({
|
|
147
146
|
key: `${section.title}`
|
|
148
147
|
}, section, {
|
|
149
148
|
readOnly: readOnly,
|
|
150
|
-
setUpdatedFormData: setUpdatedFormData,
|
|
151
149
|
fileUploadStatus: fileUploadStatus,
|
|
152
|
-
handleFileDelete: handleFileDelete
|
|
150
|
+
handleFileDelete: handleFileDelete,
|
|
151
|
+
onFileUpload: onFileUpload,
|
|
152
|
+
sectionIndex: sectionIndex
|
|
153
153
|
}))), /*#__PURE__*/React.createElement("div", {
|
|
154
154
|
className: "navigator-container"
|
|
155
155
|
}, updatedFormData.sections.length > 1 && /*#__PURE__*/React.createElement(_b.Button, {
|
|
@@ -164,7 +164,7 @@ const Renderer = _ref => {
|
|
|
164
164
|
color: "interactive",
|
|
165
165
|
isGradient: true,
|
|
166
166
|
type: "submit",
|
|
167
|
-
disabled: hasErrors
|
|
167
|
+
disabled: hasErrors || hasErrorsOnInitialRender
|
|
168
168
|
}, isSubmit ? 'Submit' : 'Next')));
|
|
169
169
|
}));
|
|
170
170
|
};
|
|
@@ -15,6 +15,14 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
|
|
|
15
15
|
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } /* eslint-disable no-alert */ /* @pareto-engineering/generator-front 1.1.1-alpha.2 */ // Local Definitions
|
|
16
16
|
const baseClassName = _exports.default.base;
|
|
17
17
|
const componentClassName = 'section';
|
|
18
|
+
const fileTypeMapper = {
|
|
19
|
+
VID: 'Video',
|
|
20
|
+
TXT: 'Text',
|
|
21
|
+
IMG: 'Image',
|
|
22
|
+
PDF: 'PDF',
|
|
23
|
+
AUD: 'Audio',
|
|
24
|
+
FILE: 'Generic'
|
|
25
|
+
};
|
|
18
26
|
|
|
19
27
|
/**
|
|
20
28
|
* This is the component description.
|
|
@@ -29,7 +37,9 @@ const Section = _ref => {
|
|
|
29
37
|
inputs,
|
|
30
38
|
readOnly,
|
|
31
39
|
fileUploadStatus,
|
|
32
|
-
handleFileDelete
|
|
40
|
+
handleFileDelete,
|
|
41
|
+
onFileUpload,
|
|
42
|
+
sectionIndex
|
|
33
43
|
// ...otherProps
|
|
34
44
|
} = _ref;
|
|
35
45
|
return /*#__PURE__*/React.createElement("div", {
|
|
@@ -41,13 +51,29 @@ const Section = _ref => {
|
|
|
41
51
|
}, title), /*#__PURE__*/React.createElement(_.ExpandableLexicalPreview, {
|
|
42
52
|
nodes: description,
|
|
43
53
|
name: "instructions"
|
|
44
|
-
}), inputs?.map(input =>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
54
|
+
}), inputs?.map((input, inputIndex) => {
|
|
55
|
+
const isFileInput = input.type === 'file';
|
|
56
|
+
return /*#__PURE__*/React.createElement(_f.FormInput, _extends({
|
|
57
|
+
key: input.name
|
|
58
|
+
}, input, {
|
|
59
|
+
disabled: readOnly
|
|
60
|
+
}, isFileInput && {
|
|
61
|
+
uploadStatus: fileUploadStatus,
|
|
62
|
+
handleFileDelete,
|
|
63
|
+
onChange: files => {
|
|
64
|
+
const filesToUpload = files?.filter(file => file instanceof File).map(file => ({
|
|
65
|
+
file,
|
|
66
|
+
name: file.name,
|
|
67
|
+
mimeType: file.type,
|
|
68
|
+
type: fileTypeMapper[(0, _f.getFileType)(file)] || 'Generic',
|
|
69
|
+
title: file.name,
|
|
70
|
+
sectionIndex,
|
|
71
|
+
inputIndex
|
|
72
|
+
}));
|
|
73
|
+
onFileUpload(filesToUpload);
|
|
74
|
+
}
|
|
75
|
+
}));
|
|
76
|
+
}));
|
|
51
77
|
};
|
|
52
78
|
Section.propTypes = {
|
|
53
79
|
/**
|
|
@@ -24,8 +24,8 @@ const FormBuilder = ({
|
|
|
24
24
|
formBuilderId,
|
|
25
25
|
onBuilderFormSave,
|
|
26
26
|
onBuilderError,
|
|
27
|
-
onRendererError,
|
|
28
27
|
onRendererFormSave,
|
|
28
|
+
onFileUpload,
|
|
29
29
|
onBuilderValidate,
|
|
30
30
|
initialBuilderValues,
|
|
31
31
|
fileUploadStatus,
|
|
@@ -52,9 +52,9 @@ const FormBuilder = ({
|
|
|
52
52
|
onSave: onRendererFormSave,
|
|
53
53
|
readOnly: readOnly,
|
|
54
54
|
shouldSubmit: shouldSubmit,
|
|
55
|
-
onError: onRendererError,
|
|
56
55
|
fileUploadStatus: fileUploadStatus,
|
|
57
|
-
handleFileDelete: handleFileDelete
|
|
56
|
+
handleFileDelete: handleFileDelete,
|
|
57
|
+
onFileUpload: onFileUpload
|
|
58
58
|
}));
|
|
59
59
|
};
|
|
60
60
|
FormBuilder.propTypes = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
2
2
|
/* @pareto-engineering/generator-front 1.1.1-alpha.2 */
|
|
3
3
|
import * as React from 'react';
|
|
4
|
-
import { useState, useEffect } from 'react';
|
|
4
|
+
import { useState, useEffect, useRef } from 'react';
|
|
5
5
|
import { Formik, Form } from 'formik';
|
|
6
6
|
import PropTypes from 'prop-types';
|
|
7
7
|
import styleNames from '@pareto-engineering/bem/exports';
|
|
@@ -13,28 +13,6 @@ import "./styles.scss";
|
|
|
13
13
|
import { Section } from "./common";
|
|
14
14
|
const baseClassName = styleNames.base;
|
|
15
15
|
const componentClassName = 'renderer';
|
|
16
|
-
const reconstructFormDataWithValues = (formData, values) => {
|
|
17
|
-
const valuesMap = {};
|
|
18
|
-
Object.keys(values).forEach(async key => {
|
|
19
|
-
if (key.includes('files')) {
|
|
20
|
-
const files = values[key].map(file => file instanceof File ? URL.createObjectURL(file) : file);
|
|
21
|
-
valuesMap[key] = files;
|
|
22
|
-
} else {
|
|
23
|
-
valuesMap[key] = values[key];
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
const newData = {
|
|
27
|
-
...formData,
|
|
28
|
-
sections: formData.sections.map(section => ({
|
|
29
|
-
...section,
|
|
30
|
-
inputs: section.inputs.map(input => ({
|
|
31
|
-
...input,
|
|
32
|
-
value: valuesMap[input.name] !== undefined ? valuesMap[input.name] : input.value
|
|
33
|
-
}))
|
|
34
|
-
}))
|
|
35
|
-
};
|
|
36
|
-
return newData;
|
|
37
|
-
};
|
|
38
16
|
const validate = (currentSectionIndex, formData, values) => {
|
|
39
17
|
const errors = {};
|
|
40
18
|
const hasAtLeastOneValue = Object.keys(values).some(valueKey => {
|
|
@@ -53,6 +31,25 @@ const validate = (currentSectionIndex, formData, values) => {
|
|
|
53
31
|
});
|
|
54
32
|
return errors;
|
|
55
33
|
};
|
|
34
|
+
const reconstructFormDataWithValues = (formData, values) => {
|
|
35
|
+
const valuesMap = {};
|
|
36
|
+
Object.keys(values).forEach(async key => {
|
|
37
|
+
if (!key.includes('files')) {
|
|
38
|
+
valuesMap[key] = values[key];
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
const newData = {
|
|
42
|
+
...formData,
|
|
43
|
+
sections: formData.sections.map(section => ({
|
|
44
|
+
...section,
|
|
45
|
+
inputs: section.inputs.map(input => ({
|
|
46
|
+
...input,
|
|
47
|
+
value: valuesMap[input.name] !== undefined ? valuesMap[input.name] : input.value
|
|
48
|
+
}))
|
|
49
|
+
}))
|
|
50
|
+
};
|
|
51
|
+
return newData;
|
|
52
|
+
};
|
|
56
53
|
|
|
57
54
|
/**
|
|
58
55
|
* This is the component description.
|
|
@@ -64,15 +61,18 @@ const Renderer = ({
|
|
|
64
61
|
formData,
|
|
65
62
|
readOnly,
|
|
66
63
|
onSave,
|
|
67
|
-
onError,
|
|
68
64
|
shouldSubmit,
|
|
69
65
|
fileUploadStatus,
|
|
70
|
-
handleFileDelete
|
|
66
|
+
handleFileDelete,
|
|
67
|
+
onFileUpload,
|
|
68
|
+
shouldUpdateInputStateInRealTime = true
|
|
71
69
|
// ...otherProps
|
|
72
70
|
}) => {
|
|
73
71
|
const [currentSectionIndex, setCurrentSectionIndex] = useState(0);
|
|
74
72
|
const [sectionHistory, setSectionHistory] = useState([]);
|
|
75
|
-
const [updatedFormData, setUpdatedFormData] = useState(
|
|
73
|
+
const [updatedFormData, setUpdatedFormData] = useState({
|
|
74
|
+
...formData
|
|
75
|
+
});
|
|
76
76
|
useEffect(() => {
|
|
77
77
|
setUpdatedFormData(formData);
|
|
78
78
|
}, [formData]);
|
|
@@ -112,6 +112,9 @@ const Renderer = ({
|
|
|
112
112
|
}
|
|
113
113
|
};
|
|
114
114
|
const isSubmit = currentSectionIndex === updatedFormData.sections.length - 1 || updatedFormData.sections[currentSectionIndex].navigation.nextSection === 'submit';
|
|
115
|
+
const ref = useRef(null);
|
|
116
|
+
const currentSectionInputs = updatedFormData.sections[currentSectionIndex].inputs;
|
|
117
|
+
const hasErrorsOnInitialRender = currentSectionInputs.some(input => input.required && !ref.current?.values[input.name] || ref.current?.errors[input.name]);
|
|
115
118
|
return /*#__PURE__*/React.createElement("div", {
|
|
116
119
|
id: id,
|
|
117
120
|
className: [baseClassName, componentClassName, userClassName].filter(e => e).join(' '),
|
|
@@ -119,30 +122,27 @@ const Renderer = ({
|
|
|
119
122
|
}, /*#__PURE__*/React.createElement(Formik, {
|
|
120
123
|
initialValues: initialValues,
|
|
121
124
|
onSubmit: handleSubmit,
|
|
122
|
-
validate: values => validate(currentSectionIndex,
|
|
125
|
+
validate: values => validate(currentSectionIndex, updatedFormData, values),
|
|
126
|
+
innerRef: ref
|
|
123
127
|
}, ({
|
|
124
128
|
values,
|
|
125
129
|
errors
|
|
126
130
|
}) => {
|
|
127
131
|
useEffect(() => {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
132
|
+
if (shouldUpdateInputStateInRealTime) {
|
|
133
|
+
const formDataWithValues = reconstructFormDataWithValues(updatedFormData, values);
|
|
134
|
+
onSave?.(formDataWithValues);
|
|
135
|
+
}
|
|
131
136
|
}, [values]);
|
|
132
|
-
useEffect(() => {
|
|
133
|
-
onError?.({
|
|
134
|
-
errors,
|
|
135
|
-
values
|
|
136
|
-
});
|
|
137
|
-
}, [errors, values]);
|
|
138
137
|
const hasErrors = Object.keys(errors).length > 0;
|
|
139
138
|
return /*#__PURE__*/React.createElement(Form, null, updatedFormData.sections.map((section, sectionIndex) => sectionIndex === currentSectionIndex && /*#__PURE__*/React.createElement(Section, _extends({
|
|
140
139
|
key: `${section.title}`
|
|
141
140
|
}, section, {
|
|
142
141
|
readOnly: readOnly,
|
|
143
|
-
setUpdatedFormData: setUpdatedFormData,
|
|
144
142
|
fileUploadStatus: fileUploadStatus,
|
|
145
|
-
handleFileDelete: handleFileDelete
|
|
143
|
+
handleFileDelete: handleFileDelete,
|
|
144
|
+
onFileUpload: onFileUpload,
|
|
145
|
+
sectionIndex: sectionIndex
|
|
146
146
|
}))), /*#__PURE__*/React.createElement("div", {
|
|
147
147
|
className: "navigator-container"
|
|
148
148
|
}, updatedFormData.sections.length > 1 && /*#__PURE__*/React.createElement(Button, {
|
|
@@ -157,7 +157,7 @@ const Renderer = ({
|
|
|
157
157
|
color: "interactive",
|
|
158
158
|
isGradient: true,
|
|
159
159
|
type: "submit",
|
|
160
|
-
disabled: hasErrors
|
|
160
|
+
disabled: hasErrors || hasErrorsOnInitialRender
|
|
161
161
|
}, isSubmit ? 'Submit' : 'Next')));
|
|
162
162
|
}));
|
|
163
163
|
};
|
|
@@ -6,11 +6,19 @@ import PropTypes from 'prop-types';
|
|
|
6
6
|
|
|
7
7
|
// Local Definitions
|
|
8
8
|
|
|
9
|
-
import { FormInput } from "../../../../../../f";
|
|
9
|
+
import { FormInput, getFileType } from "../../../../../../f";
|
|
10
10
|
import { ExpandableLexicalPreview } from "../../../../..";
|
|
11
11
|
import styleNames from '@pareto-engineering/bem/exports';
|
|
12
12
|
const baseClassName = styleNames.base;
|
|
13
13
|
const componentClassName = 'section';
|
|
14
|
+
const fileTypeMapper = {
|
|
15
|
+
VID: 'Video',
|
|
16
|
+
TXT: 'Text',
|
|
17
|
+
IMG: 'Image',
|
|
18
|
+
PDF: 'PDF',
|
|
19
|
+
AUD: 'Audio',
|
|
20
|
+
FILE: 'Generic'
|
|
21
|
+
};
|
|
14
22
|
|
|
15
23
|
/**
|
|
16
24
|
* This is the component description.
|
|
@@ -24,7 +32,9 @@ const Section = ({
|
|
|
24
32
|
inputs,
|
|
25
33
|
readOnly,
|
|
26
34
|
fileUploadStatus,
|
|
27
|
-
handleFileDelete
|
|
35
|
+
handleFileDelete,
|
|
36
|
+
onFileUpload,
|
|
37
|
+
sectionIndex
|
|
28
38
|
// ...otherProps
|
|
29
39
|
}) => /*#__PURE__*/React.createElement("div", {
|
|
30
40
|
id: id,
|
|
@@ -35,13 +45,29 @@ const Section = ({
|
|
|
35
45
|
}, title), /*#__PURE__*/React.createElement(ExpandableLexicalPreview, {
|
|
36
46
|
nodes: description,
|
|
37
47
|
name: "instructions"
|
|
38
|
-
}), inputs?.map(input =>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
48
|
+
}), inputs?.map((input, inputIndex) => {
|
|
49
|
+
const isFileInput = input.type === 'file';
|
|
50
|
+
return /*#__PURE__*/React.createElement(FormInput, _extends({
|
|
51
|
+
key: input.name
|
|
52
|
+
}, input, {
|
|
53
|
+
disabled: readOnly
|
|
54
|
+
}, isFileInput && {
|
|
55
|
+
uploadStatus: fileUploadStatus,
|
|
56
|
+
handleFileDelete,
|
|
57
|
+
onChange: files => {
|
|
58
|
+
const filesToUpload = files?.filter(file => file instanceof File).map(file => ({
|
|
59
|
+
file,
|
|
60
|
+
name: file.name,
|
|
61
|
+
mimeType: file.type,
|
|
62
|
+
type: fileTypeMapper[getFileType(file)] || 'Generic',
|
|
63
|
+
title: file.name,
|
|
64
|
+
sectionIndex,
|
|
65
|
+
inputIndex
|
|
66
|
+
}));
|
|
67
|
+
onFileUpload(filesToUpload);
|
|
68
|
+
}
|
|
69
|
+
}));
|
|
70
|
+
}));
|
|
45
71
|
Section.propTypes = {
|
|
46
72
|
/**
|
|
47
73
|
* The HTML id for this element
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pareto-engineering/design-system",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.10.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/es/index.js",
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"relay-test-utils": "^15.0.0"
|
|
84
84
|
},
|
|
85
85
|
"browserslist": "> 2%",
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "a7230fcb13b180d33c831ed413f8fc039e95fc89"
|
|
87
87
|
}
|
|
@@ -29,8 +29,8 @@ const FormBuilder = ({
|
|
|
29
29
|
formBuilderId,
|
|
30
30
|
onBuilderFormSave,
|
|
31
31
|
onBuilderError,
|
|
32
|
-
onRendererError,
|
|
33
32
|
onRendererFormSave,
|
|
33
|
+
onFileUpload,
|
|
34
34
|
onBuilderValidate,
|
|
35
35
|
initialBuilderValues,
|
|
36
36
|
fileUploadStatus,
|
|
@@ -75,9 +75,9 @@ const FormBuilder = ({
|
|
|
75
75
|
onSave={onRendererFormSave}
|
|
76
76
|
readOnly={readOnly}
|
|
77
77
|
shouldSubmit={shouldSubmit}
|
|
78
|
-
onError={onRendererError}
|
|
79
78
|
fileUploadStatus={fileUploadStatus}
|
|
80
79
|
handleFileDelete={handleFileDelete}
|
|
80
|
+
onFileUpload={onFileUpload}
|
|
81
81
|
/>
|
|
82
82
|
)}
|
|
83
83
|
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* @pareto-engineering/generator-front 1.1.1-alpha.2 */
|
|
2
2
|
import * as React from 'react'
|
|
3
3
|
|
|
4
|
-
import { useState, useEffect } from 'react'
|
|
4
|
+
import { useState, useEffect, useRef } from 'react'
|
|
5
5
|
|
|
6
6
|
import { Formik, Form } from 'formik'
|
|
7
7
|
|
|
@@ -21,31 +21,6 @@ const baseClassName = styleNames.base
|
|
|
21
21
|
|
|
22
22
|
const componentClassName = 'renderer'
|
|
23
23
|
|
|
24
|
-
const reconstructFormDataWithValues = (formData, values) => {
|
|
25
|
-
const valuesMap = {}
|
|
26
|
-
Object.keys(values).forEach(async (key) => {
|
|
27
|
-
if (key.includes('files')) {
|
|
28
|
-
const files = values[key].map((file) => (
|
|
29
|
-
file instanceof File ? URL.createObjectURL(file) : file
|
|
30
|
-
))
|
|
31
|
-
valuesMap[key] = files
|
|
32
|
-
} else {
|
|
33
|
-
valuesMap[key] = values[key]
|
|
34
|
-
}
|
|
35
|
-
})
|
|
36
|
-
const newData = {
|
|
37
|
-
...formData,
|
|
38
|
-
sections:formData.sections.map((section) => ({
|
|
39
|
-
...section,
|
|
40
|
-
inputs:section.inputs.map((input) => ({
|
|
41
|
-
...input,
|
|
42
|
-
value:valuesMap[input.name] !== undefined ? valuesMap[input.name] : input.value,
|
|
43
|
-
})),
|
|
44
|
-
})),
|
|
45
|
-
}
|
|
46
|
-
return newData
|
|
47
|
-
}
|
|
48
|
-
|
|
49
24
|
const validate = (currentSectionIndex, formData, values) => {
|
|
50
25
|
const errors = {}
|
|
51
26
|
|
|
@@ -68,6 +43,26 @@ const validate = (currentSectionIndex, formData, values) => {
|
|
|
68
43
|
return errors
|
|
69
44
|
}
|
|
70
45
|
|
|
46
|
+
const reconstructFormDataWithValues = (formData, values) => {
|
|
47
|
+
const valuesMap = {}
|
|
48
|
+
Object.keys(values).forEach(async (key) => {
|
|
49
|
+
if (!key.includes('files')) {
|
|
50
|
+
valuesMap[key] = values[key]
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
const newData = {
|
|
54
|
+
...formData,
|
|
55
|
+
sections:formData.sections.map((section) => ({
|
|
56
|
+
...section,
|
|
57
|
+
inputs:section.inputs.map((input) => ({
|
|
58
|
+
...input,
|
|
59
|
+
value:valuesMap[input.name] !== undefined ? valuesMap[input.name] : input.value,
|
|
60
|
+
})),
|
|
61
|
+
})),
|
|
62
|
+
}
|
|
63
|
+
return newData
|
|
64
|
+
}
|
|
65
|
+
|
|
71
66
|
/**
|
|
72
67
|
* This is the component description.
|
|
73
68
|
*/
|
|
@@ -78,15 +73,16 @@ const Renderer = ({
|
|
|
78
73
|
formData,
|
|
79
74
|
readOnly,
|
|
80
75
|
onSave,
|
|
81
|
-
onError,
|
|
82
76
|
shouldSubmit,
|
|
83
77
|
fileUploadStatus,
|
|
84
78
|
handleFileDelete,
|
|
79
|
+
onFileUpload,
|
|
80
|
+
shouldUpdateInputStateInRealTime = true,
|
|
85
81
|
// ...otherProps
|
|
86
82
|
}) => {
|
|
87
83
|
const [currentSectionIndex, setCurrentSectionIndex] = useState(0)
|
|
88
84
|
const [sectionHistory, setSectionHistory] = useState([])
|
|
89
|
-
const [updatedFormData, setUpdatedFormData] = useState(formData)
|
|
85
|
+
const [updatedFormData, setUpdatedFormData] = useState({ ...formData })
|
|
90
86
|
|
|
91
87
|
useEffect(() => {
|
|
92
88
|
setUpdatedFormData(formData)
|
|
@@ -135,6 +131,13 @@ const Renderer = ({
|
|
|
135
131
|
const isSubmit = currentSectionIndex === updatedFormData.sections.length - 1
|
|
136
132
|
|| updatedFormData.sections[currentSectionIndex].navigation.nextSection === 'submit'
|
|
137
133
|
|
|
134
|
+
const ref = useRef(null)
|
|
135
|
+
|
|
136
|
+
const currentSectionInputs = updatedFormData.sections[currentSectionIndex].inputs
|
|
137
|
+
const hasErrorsOnInitialRender = currentSectionInputs
|
|
138
|
+
.some((input) => (input.required && !ref.current?.values[input.name])
|
|
139
|
+
|| ref.current?.errors[input.name])
|
|
140
|
+
|
|
138
141
|
return (
|
|
139
142
|
<div
|
|
140
143
|
id={id}
|
|
@@ -151,21 +154,18 @@ const Renderer = ({
|
|
|
151
154
|
<Formik
|
|
152
155
|
initialValues={initialValues}
|
|
153
156
|
onSubmit={handleSubmit}
|
|
154
|
-
validate={(values) => validate(currentSectionIndex,
|
|
157
|
+
validate={(values) => validate(currentSectionIndex, updatedFormData, values)}
|
|
158
|
+
innerRef={ref}
|
|
155
159
|
>
|
|
156
160
|
{({ values, errors }) => {
|
|
157
161
|
useEffect(() => {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
162
|
+
if (shouldUpdateInputStateInRealTime) {
|
|
163
|
+
const formDataWithValues = reconstructFormDataWithValues(updatedFormData, values)
|
|
164
|
+
onSave?.(formDataWithValues)
|
|
165
|
+
}
|
|
161
166
|
}, [values])
|
|
162
167
|
|
|
163
|
-
useEffect(() => {
|
|
164
|
-
onError?.({ errors, values })
|
|
165
|
-
}, [errors, values])
|
|
166
|
-
|
|
167
168
|
const hasErrors = Object.keys(errors).length > 0
|
|
168
|
-
|
|
169
169
|
return (
|
|
170
170
|
<Form>
|
|
171
171
|
{updatedFormData.sections.map((section, sectionIndex) => (
|
|
@@ -174,9 +174,10 @@ const Renderer = ({
|
|
|
174
174
|
key={`${section.title}`}
|
|
175
175
|
{...section}
|
|
176
176
|
readOnly={readOnly}
|
|
177
|
-
setUpdatedFormData={setUpdatedFormData}
|
|
178
177
|
fileUploadStatus={fileUploadStatus}
|
|
179
178
|
handleFileDelete={handleFileDelete}
|
|
179
|
+
onFileUpload={onFileUpload}
|
|
180
|
+
sectionIndex={sectionIndex}
|
|
180
181
|
/>
|
|
181
182
|
)
|
|
182
183
|
))}
|
|
@@ -197,7 +198,7 @@ const Renderer = ({
|
|
|
197
198
|
)
|
|
198
199
|
}
|
|
199
200
|
{(!isSubmit || shouldSubmit) && (
|
|
200
|
-
<Button color="interactive" isGradient type="submit" disabled={hasErrors}>
|
|
201
|
+
<Button color="interactive" isGradient type="submit" disabled={hasErrors || hasErrorsOnInitialRender}>
|
|
201
202
|
{isSubmit ? 'Submit' : 'Next'}
|
|
202
203
|
</Button>
|
|
203
204
|
)}
|
|
@@ -6,7 +6,7 @@ import PropTypes from 'prop-types'
|
|
|
6
6
|
|
|
7
7
|
// Local Definitions
|
|
8
8
|
|
|
9
|
-
import { FormInput } from 'ui/f'
|
|
9
|
+
import { FormInput, getFileType } from 'ui/f'
|
|
10
10
|
|
|
11
11
|
import { ExpandableLexicalPreview } from 'ui/g'
|
|
12
12
|
|
|
@@ -16,6 +16,15 @@ const baseClassName = styleNames.base
|
|
|
16
16
|
|
|
17
17
|
const componentClassName = 'section'
|
|
18
18
|
|
|
19
|
+
const fileTypeMapper = {
|
|
20
|
+
VID :'Video',
|
|
21
|
+
TXT :'Text',
|
|
22
|
+
IMG :'Image',
|
|
23
|
+
PDF :'PDF',
|
|
24
|
+
AUD :'Audio',
|
|
25
|
+
FILE:'Generic',
|
|
26
|
+
}
|
|
27
|
+
|
|
19
28
|
/**
|
|
20
29
|
* This is the component description.
|
|
21
30
|
*/
|
|
@@ -29,6 +38,8 @@ const Section = ({
|
|
|
29
38
|
readOnly,
|
|
30
39
|
fileUploadStatus,
|
|
31
40
|
handleFileDelete,
|
|
41
|
+
onFileUpload,
|
|
42
|
+
sectionIndex,
|
|
32
43
|
// ...otherProps
|
|
33
44
|
}) => (
|
|
34
45
|
<div
|
|
@@ -49,15 +60,35 @@ const Section = ({
|
|
|
49
60
|
nodes={description}
|
|
50
61
|
name="instructions"
|
|
51
62
|
/>
|
|
52
|
-
{inputs?.map((input) =>
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
{inputs?.map((input, inputIndex) => {
|
|
64
|
+
const isFileInput = input.type === 'file'
|
|
65
|
+
return (
|
|
66
|
+
<FormInput
|
|
67
|
+
key={input.name}
|
|
68
|
+
{...input}
|
|
69
|
+
disabled={readOnly}
|
|
70
|
+
{...(isFileInput && {
|
|
71
|
+
uploadStatus:fileUploadStatus,
|
|
72
|
+
handleFileDelete,
|
|
73
|
+
onChange :(files) => {
|
|
74
|
+
const filesToUpload = files
|
|
75
|
+
?.filter((file) => file instanceof File)
|
|
76
|
+
.map((file) => ({
|
|
77
|
+
file,
|
|
78
|
+
name :file.name,
|
|
79
|
+
mimeType:file.type,
|
|
80
|
+
type :fileTypeMapper[getFileType(file)] || 'Generic',
|
|
81
|
+
title :file.name,
|
|
82
|
+
sectionIndex,
|
|
83
|
+
inputIndex,
|
|
84
|
+
}))
|
|
85
|
+
|
|
86
|
+
onFileUpload(filesToUpload)
|
|
87
|
+
},
|
|
88
|
+
})}
|
|
89
|
+
/>
|
|
90
|
+
)
|
|
91
|
+
})}
|
|
61
92
|
</div>
|
|
62
93
|
)
|
|
63
94
|
|
|
@@ -12416,7 +12416,7 @@ exports[`Storyshots a/Timestamp Distance Format 1`] = `
|
|
|
12416
12416
|
className="base timestamp"
|
|
12417
12417
|
onClick={[Function]}
|
|
12418
12418
|
>
|
|
12419
|
-
|
|
12419
|
+
over 2 years ago
|
|
12420
12420
|
</p>
|
|
12421
12421
|
`;
|
|
12422
12422
|
|