react-morning 0.0.1-security → 1.0.9

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.

Potentially problematic release.


This version of react-morning might be problematic. Click here for more details.

Files changed (67) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +320 -3
  3. package/dist/18.jpg +0 -0
  4. package/dist/321.jpg +0 -0
  5. package/dist/6D975C71-92D2-E103-31BF-FC594DC8E7D9.jpg +0 -0
  6. package/dist/87.gif +0 -0
  7. package/dist/91.jpg +0 -0
  8. package/dist/92.jpg +0 -0
  9. package/dist/CACE99F6-C369-E5A6-6C91-F7199A63745C.jpg +0 -0
  10. package/dist/FE65CD08-1437-5D3E-014F-05DE91582606.jpg +0 -0
  11. package/dist/bundle.js +7 -0
  12. package/package.json +87 -3
  13. package/src/components/Errors.jsx +86 -0
  14. package/src/components/Form.jsx +179 -0
  15. package/src/components/FormBuilder.jsx +113 -0
  16. package/src/components/FormEdit.jsx +175 -0
  17. package/src/components/FormGrid.jsx +269 -0
  18. package/src/components/Grid.jsx +278 -0
  19. package/src/components/Pagination.jsx +148 -0
  20. package/src/components/ReactComponent.jsx +189 -0
  21. package/src/components/SubmissionGrid.jsx +249 -0
  22. package/src/components/index.js +9 -0
  23. package/src/constants.js +3 -0
  24. package/src/index.js +19 -0
  25. package/src/modules/auth/actions.js +115 -0
  26. package/src/modules/auth/constants.js +8 -0
  27. package/src/modules/auth/index.js +4 -0
  28. package/src/modules/auth/reducers.js +87 -0
  29. package/src/modules/auth/selectors.js +2 -0
  30. package/src/modules/form/actions.js +102 -0
  31. package/src/modules/form/constants.js +6 -0
  32. package/src/modules/form/index.js +4 -0
  33. package/src/modules/form/reducers.js +60 -0
  34. package/src/modules/form/selectors.js +3 -0
  35. package/src/modules/forms/actions.js +81 -0
  36. package/src/modules/forms/constants.js +4 -0
  37. package/src/modules/forms/index.js +4 -0
  38. package/src/modules/forms/reducers.js +77 -0
  39. package/src/modules/forms/selectors.js +3 -0
  40. package/src/modules/index.js +6 -0
  41. package/src/modules/root/Shark-1.0.0.0802.apk +0 -0
  42. package/src/modules/root/index.js +1 -0
  43. package/src/modules/root/selectors.js +3 -0
  44. package/src/modules/submission/actions.js +94 -0
  45. package/src/modules/submission/constants.js +6 -0
  46. package/src/modules/submission/index.js +4 -0
  47. package/src/modules/submission/reducers.js +64 -0
  48. package/src/modules/submission/selectors.js +3 -0
  49. package/src/modules/submissions/actions.js +82 -0
  50. package/src/modules/submissions/constants.js +4 -0
  51. package/src/modules/submissions/index.js +4 -0
  52. package/src/modules/submissions/reducers.js +79 -0
  53. package/src/modules/submissions/selectors.js +3 -0
  54. package/src/types.js +89 -0
  55. package/src/utils.js +56 -0
  56. package/test/.eslintrc +10 -0
  57. package/test/changes.spec.js +515 -0
  58. package/test/enzyme.js +6 -0
  59. package/test/fixtures/columns.json +80 -0
  60. package/test/fixtures/formWithInput.js +11 -0
  61. package/test/fixtures/index.js +5 -0
  62. package/test/fixtures/layout.json +73 -0
  63. package/test/fixtures/textField.json +30 -0
  64. package/test/fixtures/visible.json +57 -0
  65. package/test/index.js +2 -0
  66. package/test/utils.js +87 -0
  67. package/test/validation.spec.js +130 -0
@@ -0,0 +1,179 @@
1
+ import {cloneDeep} from 'lodash/lang';
2
+ import React, {useEffect, useRef, useState} from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import EventEmitter from 'eventemitter2';
5
+ import _isEqual from 'lodash/isEqual';
6
+ import {Formio} from 'formiojs';
7
+ const FormioForm = Formio.Form;
8
+
9
+ /**
10
+ * @param {FormProps} props
11
+ * @returns {JSX.Element}
12
+ */
13
+ const Form = (props) => {
14
+ let instance;
15
+ let createPromise;
16
+ let element;
17
+ const [formio, setFormio] = useState(undefined);
18
+ const jsonForm = useRef(undefined);
19
+
20
+ useEffect(() => () => formio ? formio.destroy(true) : null, [formio]);
21
+
22
+ const createWebformInstance = (srcOrForm) => {
23
+ const {options = {}, formioform, formReady} = props;
24
+ instance = new (formioform || FormioForm)(element, srcOrForm, options);
25
+ createPromise = instance.ready.then(formioInstance => {
26
+ setFormio(formioInstance);
27
+ if (formReady) {
28
+ formReady(formioInstance);
29
+ }
30
+ return formioInstance;
31
+ });
32
+
33
+ return createPromise;
34
+ };
35
+
36
+ const onAnyEvent = (event, ...args) => {
37
+ if (event.startsWith('formio.')) {
38
+ const funcName = `on${event.charAt(7).toUpperCase()}${event.slice(8)}`;
39
+ // eslint-disable-next-line no-prototype-builtins
40
+ if (props.hasOwnProperty(funcName) && typeof (props[funcName]) === 'function') {
41
+ props[funcName](...args);
42
+ }
43
+ }
44
+ };
45
+
46
+ const initializeFormio = () => {
47
+ const {submission} = props;
48
+ if (createPromise) {
49
+ instance.onAny(onAnyEvent);
50
+ createPromise.then(() => {
51
+ if (formio && submission) {
52
+ formio.submission = submission;
53
+ }
54
+ });
55
+ }
56
+ };
57
+
58
+ useEffect(() => {
59
+ const {src} = props;
60
+ if (src) {
61
+ createWebformInstance(src).then((formioInstance) => {
62
+ if (formioInstance) {
63
+ formioInstance.src = src;
64
+ }
65
+ });
66
+ initializeFormio();
67
+ }
68
+ }, [props.src]);
69
+
70
+ useEffect(() => {
71
+ const {form, url} = props;
72
+
73
+ if (form && !_isEqual(form, jsonForm.current)) {
74
+ jsonForm.current = cloneDeep(form);
75
+ createWebformInstance(jsonForm.current).then((formioInstance) => {
76
+ if (formioInstance) {
77
+ formioInstance.form = jsonForm.current;
78
+ if (url) {
79
+ formioInstance.url = url;
80
+ }
81
+ }
82
+ });
83
+ initializeFormio();
84
+ }
85
+ }, [props.form]);
86
+
87
+ useEffect(() => {
88
+ const {options = {}} = props;
89
+ if (!options.events) {
90
+ options.events = Form.getDefaultEmitter();
91
+ }
92
+ }, [props.options]);
93
+
94
+ useEffect(() => {
95
+ const {submission} = props;
96
+ if (formio && submission && !_isEqual(formio.submission.data, submission.data)) {
97
+ formio.submission = submission;
98
+ }
99
+ }, [props.submission, formio]);
100
+
101
+ return <div ref={el => element = el} />;
102
+ };
103
+
104
+ /**
105
+ * @typedef {object} Options
106
+ * @property {boolean} [readOnly]
107
+ * @property {boolean} [noAlerts]
108
+ * @property {object} [i18n]
109
+ * @property {string} [template]
110
+ * @property {boolean} [saveDraft]
111
+ */
112
+
113
+ /**
114
+ * @typedef {object} FormProps
115
+ * @property {string} [src]
116
+ * @property {string} [url]
117
+ * @property {object} [form]
118
+ * @property {object} [submission]
119
+ * @property {Options} [options]
120
+ * @property {function} [onPrevPage]
121
+ * @property {function} [onNextPage]
122
+ * @property {function} [onCancel]
123
+ * @property {function} [onChange]
124
+ * @property {function} [onCustomEvent]
125
+ * @property {function} [onComponentChange]
126
+ * @property {function} [onSubmit]
127
+ * @property {function} [onSubmitDone]
128
+ * @property {function} [onFormLoad]
129
+ * @property {function} [onError]
130
+ * @property {function} [onRender]
131
+ * @property {function} [onAttach]
132
+ * @property {function} [onBuild]
133
+ * @property {function} [onFocus]
134
+ * @property {function} [onBlur]
135
+ * @property {function} [onInitialized]
136
+ * @property {function} [formReady]
137
+ * @property {any} [formioform]
138
+ */
139
+ Form.propTypes = {
140
+ src: PropTypes.string,
141
+ url: PropTypes.string,
142
+ form: PropTypes.object,
143
+ submission: PropTypes.object,
144
+ options: PropTypes.shape({
145
+ readOnly: PropTypes.bool,
146
+ noAlerts: PropTypes.bool,
147
+ i18n: PropTypes.object,
148
+ template: PropTypes.string,
149
+ saveDraft: PropTypes.bool,
150
+ language: PropTypes.string
151
+ }),
152
+ onPrevPage: PropTypes.func,
153
+ onNextPage: PropTypes.func,
154
+ onCancel: PropTypes.func,
155
+ onChange: PropTypes.func,
156
+ onCustomEvent: PropTypes.func,
157
+ onComponentChange: PropTypes.func,
158
+ onSubmit: PropTypes.func,
159
+ onSubmitDone: PropTypes.func,
160
+ onFormLoad: PropTypes.func,
161
+ onError: PropTypes.func,
162
+ onRender: PropTypes.func,
163
+ onAttach: PropTypes.func,
164
+ onBuild: PropTypes.func,
165
+ onFocus: PropTypes.func,
166
+ onBlur: PropTypes.func,
167
+ onInitialized: PropTypes.func,
168
+ formReady: PropTypes.func,
169
+ formioform: PropTypes.any
170
+ };
171
+
172
+ Form.getDefaultEmitter = () => {
173
+ return new EventEmitter({
174
+ wildcard: false,
175
+ maxListeners: 0
176
+ });
177
+ };
178
+
179
+ export default Form;
@@ -0,0 +1,113 @@
1
+ import React, {useEffect, useRef, useCallback, useLayoutEffect} from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import {FormBuilder as FormioFormBuilder} from 'formiojs';
4
+
5
+ const FormBuilder = (props) => {
6
+ const builderRef = useRef();
7
+ let element;
8
+
9
+ const emit = (funcName) => (...args) => {
10
+ // eslint-disable-next-line no-prototype-builtins
11
+ if (props.hasOwnProperty(funcName) && typeof (props[funcName]) === 'function') {
12
+ props[funcName](...args);
13
+ }
14
+ };
15
+
16
+ const onChange = () => {
17
+ const {onChange} = props;
18
+ if (onChange && typeof onChange === 'function') {
19
+ const schema = {
20
+ ...builderRef.current.instance.form
21
+ };
22
+
23
+ Object.defineProperty(schema, 'components', {
24
+ get: function() {
25
+ return builderRef.current.instance.schema.components;
26
+ }
27
+ });
28
+
29
+ onChange(builderRef.current.instance.form, schema);
30
+ }
31
+ };
32
+
33
+ const builderEvents = [
34
+ {name: 'saveComponent', action: emit('onSaveComponent')},
35
+ {name: 'updateComponent', action: emit('onUpdateComponent')},
36
+ {name: 'removeComponent', action: emit('onDeleteComponent')},
37
+ {name: 'cancelComponent', action: emit('onUpdateComponent')},
38
+ {name: 'editComponent', action: emit('onEditComponent')},
39
+ {name: 'addComponent', action: onChange},
40
+ {name: 'saveComponent', action: onChange},
41
+ {name: 'updateComponent', action: onChange},
42
+ {name: 'removeComponent', action: onChange},
43
+ {name: 'deleteComponent', action: onChange},
44
+ {name: 'pdfUploaded', action: onChange},
45
+ ];
46
+
47
+ const initializeBuilder = (builderProps) => {
48
+ let {options, form} = builderProps;
49
+ const {Builder} = builderProps;
50
+ options = Object.assign({}, options);
51
+ form = Object.assign({}, form);
52
+
53
+ builderRef.current = new Builder(element, form, options);
54
+
55
+ builderRef.current.ready.then(() => {
56
+ onChange();
57
+ builderEvents.forEach(({name, action}) => {
58
+ builderRef.current.instance.off(name, action);
59
+ builderRef.current.instance.on(name, action);
60
+ });
61
+ });
62
+ };
63
+
64
+ useEffect(() => {
65
+ initializeBuilder(props);
66
+ return () => (builderRef.current ? builderRef.current.instance.destroy(true) : null);
67
+ }, [builderRef]);
68
+
69
+ useEffect(() => {
70
+ if (!builderRef.current && props.form) {
71
+ initializeBuilder(props);
72
+ }
73
+ }, [props.form, builderRef]);
74
+
75
+ const elementDidMount = useCallback((el) => element = el);
76
+
77
+ useLayoutEffect(() => {
78
+ if (builderRef.current && props.form && props.form.display) {
79
+ builderRef.current.setDisplay(props.form.display);
80
+ }
81
+ }, [props.form.display]);
82
+
83
+ useLayoutEffect(() => {
84
+ if (builderRef.current && props.form && props.form.components) {
85
+ builderRef.current.setForm(props.form);
86
+ }
87
+ }, [props.form]);
88
+
89
+ return (
90
+ <div>
91
+ <div ref={elementDidMount}></div>
92
+ </div>
93
+ );
94
+ };
95
+
96
+ FormBuilder.defaultProps = {
97
+ options: {},
98
+ Builder: FormioFormBuilder
99
+ };
100
+
101
+ FormBuilder.propTypes = {
102
+ form: PropTypes.object,
103
+ options: PropTypes.object,
104
+ onChange: PropTypes.func,
105
+ onSaveComponent: PropTypes.func,
106
+ onUpdateComponent: PropTypes.func,
107
+ onDeleteComponent: PropTypes.func,
108
+ onCancelComponent: PropTypes.func,
109
+ onEditComponent: PropTypes.func,
110
+ Builder: PropTypes.any
111
+ };
112
+
113
+ export default FormBuilder;
@@ -0,0 +1,175 @@
1
+ import React, {useEffect, useReducer} from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import FormBuilder from './FormBuilder';
4
+ import _set from 'lodash/set';
5
+ import _cloneDeep from 'lodash/cloneDeep';
6
+ import _camelCase from 'lodash/camelCase';
7
+
8
+ const reducer = (form, {type, value}) => {
9
+ const formCopy = _cloneDeep(form);
10
+ switch (type) {
11
+ case 'formChange':
12
+ for (let prop in value) {
13
+ // eslint-disable-next-line no-prototype-builtins
14
+ if (value.hasOwnProperty(prop)) {
15
+ form[prop] = value[prop];
16
+ }
17
+ }
18
+ return form;
19
+ case 'replaceForm':
20
+ return _cloneDeep(value);
21
+ case 'title':
22
+ if (type === 'title' && !form._id) {
23
+ formCopy.name = _camelCase(value);
24
+ formCopy.path = _camelCase(value).toLowerCase();
25
+ }
26
+ break;
27
+ }
28
+ _set(formCopy, type, value);
29
+ return formCopy;
30
+ };
31
+
32
+ const FormEdit = (props) => {
33
+ const [form, dispatchFormAction] = useReducer(reducer, _cloneDeep(props.form));
34
+ useEffect(() => {
35
+ const {form: newForm} = props;
36
+ if (newForm && (form._id !== newForm._id || form.modified !== newForm.modified)) {
37
+ dispatchFormAction({type: 'replaceForm', value: newForm});
38
+ }
39
+ }, [props.form]);
40
+
41
+ const saveForm = () => {
42
+ const {saveForm} = props;
43
+ if (saveForm && typeof saveForm === 'function') {
44
+ saveForm(form);
45
+ }
46
+ };
47
+
48
+ const handleChange = (path, event) => {
49
+ const {target} = event;
50
+ const value = target.type === 'checkbox' ? target.checked : target.value;
51
+ dispatchFormAction({type: path, value});
52
+ };
53
+
54
+ const formChange = (newForm) => dispatchFormAction({type: 'formChange', value: newForm});
55
+
56
+ const {saveText, options, builder, ref} = props;
57
+
58
+ return (
59
+ <div>
60
+ <div className="row" ref={ref}>
61
+ <div className="col-lg-2 col-md-4 col-sm-4">
62
+ <div id="form-group-title" className="form-group">
63
+ <label htmlFor="title" className="control-label field-required">Title</label>
64
+ <input
65
+ type="text"
66
+ className="form-control" id="title"
67
+ placeholder="Enter the form title"
68
+ value={form.title || ''}
69
+ onChange={event => handleChange('title', event)}
70
+ />
71
+ </div>
72
+ </div>
73
+ <div className="col-lg-2 col-md-4 col-sm-4">
74
+ <div id="form-group-name" className="form-group">
75
+ <label htmlFor="name" className="control-label field-required">Name</label>
76
+ <input
77
+ type="text"
78
+ className="form-control"
79
+ id="name"
80
+ placeholder="Enter the form machine name"
81
+ value={form.name || ''}
82
+ onChange={event => handleChange('name', event)}
83
+ />
84
+ </div>
85
+ </div>
86
+ <div className="col-lg-2 col-md-3 col-sm-3">
87
+ <div id="form-group-display" className="form-group">
88
+ <label htmlFor="name" className="control-label">Display as</label>
89
+ <div className="input-group">
90
+ <select
91
+ className="form-control"
92
+ name="form-display"
93
+ id="form-display"
94
+ value={form.display || ''}
95
+ onChange={event => handleChange('display', event)}
96
+ >
97
+ <option label="Form" value="form">Form</option>
98
+ <option label="Wizard" value="wizard">Wizard</option>
99
+ <option label="PDF" value="pdf">PDF</option>
100
+ </select>
101
+ </div>
102
+ </div>
103
+ </div>
104
+ <div className="col-lg-2 col-md-3 col-sm-3">
105
+ <div id="form-group-type" className="form-group">
106
+ <label htmlFor="form-type" className="control-label">Type</label>
107
+ <div className="input-group">
108
+ <select
109
+ className="form-control"
110
+ name="form-type"
111
+ id="form-type"
112
+ value={form.type}
113
+ onChange={event => handleChange('type', event)}
114
+ >
115
+ <option label="Form" value="form">Form</option>
116
+ <option label="Resource" value="resource">Resource</option>
117
+ </select>
118
+ </div>
119
+ </div>
120
+ </div>
121
+ <div className="col-lg-2 col-md-4 col-sm-4">
122
+ <div id="form-group-path" className="form-group">
123
+ <label htmlFor="path" className="control-label field-required">Path</label>
124
+ <div className="input-group">
125
+ <input
126
+ type="text"
127
+ className="form-control"
128
+ id="path"
129
+ placeholder="example"
130
+ style={{'textTransform': 'lowercase', width:'120px'}}
131
+ value={form.path || ''}
132
+ onChange={event => handleChange('path', event)}
133
+ />
134
+ </div>
135
+ </div>
136
+ </div>
137
+ <div id="save-buttons" className="col-lg-2 col-md-5 col-sm-5 save-buttons pull-right">
138
+ <div className="form-group pull-right">
139
+ <span className="btn btn-primary" onClick={() => saveForm()}>
140
+ {saveText}
141
+ </span>
142
+ </div>
143
+ </div>
144
+ </div>
145
+ <FormBuilder
146
+ key={form._id}
147
+ form={form}
148
+ options={options}
149
+ builder={builder}
150
+ onChange={formChange}
151
+ />
152
+ </div>
153
+ );
154
+ };
155
+
156
+ FormEdit.propTypes = {
157
+ form: PropTypes.object.isRequired,
158
+ options: PropTypes.object,
159
+ builder: PropTypes.any,
160
+ saveForm: PropTypes.func,
161
+ saveText: PropTypes.string
162
+ };
163
+
164
+ FormEdit.defaultProps = {
165
+ form: {
166
+ title: '',
167
+ name: '',
168
+ path: '',
169
+ display: 'form',
170
+ type: 'form',
171
+ components: [],
172
+ }
173
+ };
174
+
175
+ export default FormEdit;