ui-soxo-bootstrap-core 2.4.25-dev.36 → 2.4.25-dev.40
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.
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
*
|
|
3
3
|
* @author Ashique Mohammed
|
|
4
4
|
* @description Generic Form create accepts an array of fields to update any resource
|
|
5
5
|
* @version
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
// let forms = [{
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
// tabs: [{}]
|
|
14
14
|
// }]
|
|
15
15
|
|
|
16
|
-
import React, { useState } from
|
|
16
|
+
import React, { useState } from 'react';
|
|
17
17
|
|
|
18
18
|
import moment from 'moment';
|
|
19
19
|
|
|
20
|
-
import Button from
|
|
20
|
+
import Button from '../../../../../lib/elements/basic/button/button';
|
|
21
21
|
|
|
22
|
-
import {
|
|
22
|
+
import { Form, Input, Radio, InputNumber, DatePicker, TimePicker, Checkbox, Select, Row, Col, Tabs } from 'antd';
|
|
23
23
|
|
|
24
24
|
// import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';
|
|
25
25
|
|
|
@@ -29,9 +29,9 @@ import Camera from './../../../../components/camera/camera';
|
|
|
29
29
|
|
|
30
30
|
// import { ColumnHeightOutlined } from '@ant-design/icons';
|
|
31
31
|
|
|
32
|
-
import { DateUtils } from
|
|
32
|
+
import { DateUtils } from '../../../../utils';
|
|
33
33
|
|
|
34
|
-
import { FieldCustomizer, TabCustomizer } from
|
|
34
|
+
import { FieldCustomizer, TabCustomizer, ReferenceSelect } from './../../../../';
|
|
35
35
|
|
|
36
36
|
import { prepareAndExecuteScript } from './../../../../utils/script.utils';
|
|
37
37
|
|
|
@@ -43,163 +43,148 @@ const { TabPane } = Tabs;
|
|
|
43
43
|
|
|
44
44
|
// const grid = 4;
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
import './form-creator.scss'
|
|
46
|
+
import './form-creator.scss';
|
|
48
47
|
|
|
49
48
|
/**
|
|
50
49
|
* Component accepts fields to render the necessary components and returns the values on submission
|
|
51
|
-
*
|
|
52
|
-
* @param {*} param0
|
|
53
|
-
* @returns
|
|
50
|
+
*
|
|
51
|
+
* @param {*} param0
|
|
52
|
+
* @returns
|
|
54
53
|
*/
|
|
55
54
|
function FormCreator({
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
55
|
+
/**If we want to change the existing information first we need the current information ie, selectedInformation*/
|
|
56
|
+
selectedInformation,
|
|
57
|
+
model,
|
|
58
|
+
formContent = {},
|
|
59
|
+
onSubmit,
|
|
60
|
+
fields = [],
|
|
61
|
+
callback,
|
|
62
|
+
layout,
|
|
63
|
+
// Below are arguments for use in form display
|
|
64
|
+
onFieldUpdate,
|
|
65
|
+
// onListUpdate,
|
|
66
|
+
onFieldRemove,
|
|
68
67
|
}) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (['date'].indexOf(entry.type) !== -1 && formContent[entry.field]) {
|
|
100
|
-
|
|
101
|
-
body[entry.field] = DateUtils.getMomentObject(formContent[entry.field]);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
return body;
|
|
107
|
-
|
|
68
|
+
const [form] = Form.useForm();
|
|
69
|
+
|
|
70
|
+
let layoutValue;
|
|
71
|
+
|
|
72
|
+
if (layout) {
|
|
73
|
+
layoutValue = layout;
|
|
74
|
+
} else {
|
|
75
|
+
layoutValue = {
|
|
76
|
+
labelCol: { span: 12 },
|
|
77
|
+
wrapperCol: { span: 12 },
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Variable used for loading state
|
|
82
|
+
const [loading, setLoading] = useState(false);
|
|
83
|
+
|
|
84
|
+
// Variable stores the form body values
|
|
85
|
+
const [content, setContent] = useState(() => {
|
|
86
|
+
// Body for the files
|
|
87
|
+
let body = formContent || { [model.name]: {} };
|
|
88
|
+
|
|
89
|
+
fields.forEach((entry) => {
|
|
90
|
+
if (entry.transform) {
|
|
91
|
+
body[entry.field] = entry.transform(body[entry.field]);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// If its a date
|
|
95
|
+
if (['date'].indexOf(entry.type) !== -1 && formContent[entry.field]) {
|
|
96
|
+
body[entry.field] = DateUtils.getMomentObject(formContent[entry.field]);
|
|
97
|
+
}
|
|
108
98
|
});
|
|
109
99
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// const onDragEnd = (result) => {
|
|
144
|
-
|
|
145
|
-
// onListUpdate(result.source, result.destination);
|
|
146
|
-
// }
|
|
147
|
-
|
|
148
|
-
// const getListStyle = (isDraggingOver) => ({
|
|
149
|
-
// // background: isDraggingOver ? 'lightblue' : '',
|
|
150
|
-
// boxShadow: isDraggingOver ? '0px 0px 5px 5px #eeeeee' : '',
|
|
151
|
-
|
|
152
|
-
// // padding: grid,
|
|
153
|
-
// // width: 250
|
|
154
|
-
// });
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Function triggered for any onChange of input
|
|
158
|
-
*
|
|
159
|
-
* @param {*} formFields
|
|
160
|
-
*/
|
|
161
|
-
const onFieldsChange = (formFields) => {
|
|
162
|
-
|
|
163
|
-
formFields.forEach((field) => {
|
|
164
|
-
if (field.name[0].includes('date')) {
|
|
165
|
-
|
|
166
|
-
// values[field.field] = new Timestamp(moment(field.value).valueOf());
|
|
167
|
-
|
|
168
|
-
// content[field.name[0]] = moment(field.value).format('DD/MM/YYYY');
|
|
169
|
-
} else {
|
|
170
|
-
// content[field.name[0]] = field.value;
|
|
171
|
-
}
|
|
172
|
-
})
|
|
173
|
-
// setContent({ ...content })
|
|
100
|
+
return body;
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Function handles trigger of onupload
|
|
105
|
+
*
|
|
106
|
+
* @param {*} element
|
|
107
|
+
* @param {*} attachments
|
|
108
|
+
*/
|
|
109
|
+
function onUpload(element, attachments) {
|
|
110
|
+
form.setFieldsValue({ [element.field]: attachments });
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Custom Listener for onchange of input
|
|
115
|
+
*
|
|
116
|
+
* @param {*} element
|
|
117
|
+
* @param {*} attachments
|
|
118
|
+
*/
|
|
119
|
+
function onChange(element, value) {
|
|
120
|
+
// Though we initially gave less respect to this method
|
|
121
|
+
// This is the game changer - 29/01/23
|
|
122
|
+
|
|
123
|
+
// Being able to listen to script , Bind onChange listeners to each input
|
|
124
|
+
// can avoid the need for building custom forms again
|
|
125
|
+
|
|
126
|
+
// console.log(element);
|
|
127
|
+
|
|
128
|
+
/** */
|
|
129
|
+
if (element.field) {
|
|
130
|
+
form.setFieldsValue({ [element.field]: value });
|
|
174
131
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// const onDragEnd = (result) => {
|
|
135
|
+
|
|
136
|
+
// onListUpdate(result.source, result.destination);
|
|
137
|
+
// }
|
|
138
|
+
|
|
139
|
+
// const getListStyle = (isDraggingOver) => ({
|
|
140
|
+
// // background: isDraggingOver ? 'lightblue' : '',
|
|
141
|
+
// boxShadow: isDraggingOver ? '0px 0px 5px 5px #eeeeee' : '',
|
|
142
|
+
|
|
143
|
+
// // padding: grid,
|
|
144
|
+
// // width: 250
|
|
145
|
+
// });
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Function triggered for any onChange of input
|
|
149
|
+
*
|
|
150
|
+
* @param {*} formFields
|
|
151
|
+
*/
|
|
152
|
+
const onFieldsChange = (formFields) => {
|
|
153
|
+
formFields.forEach((field) => {
|
|
154
|
+
if (field.name[0].includes('date')) {
|
|
155
|
+
// values[field.field] = new Timestamp(moment(field.value).valueOf());
|
|
156
|
+
// content[field.name[0]] = moment(field.value).format('DD/MM/YYYY');
|
|
157
|
+
} else {
|
|
158
|
+
// content[field.name[0]] = field.value;
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
// setContent({ ...content })
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Values Change
|
|
166
|
+
*
|
|
167
|
+
* @param {*} field
|
|
168
|
+
* @param {*} values
|
|
169
|
+
*/
|
|
170
|
+
const onValuesChange = async (field, values) => {
|
|
171
|
+
// Find the input that is changed
|
|
172
|
+
let key = Object.keys(field)[0];
|
|
173
|
+
|
|
174
|
+
// Configuration
|
|
175
|
+
let fieldConfiguration = fields.filter((config) => config.field === key)[0];
|
|
176
|
+
|
|
177
|
+
// We have to check if there is an onChange script for the field
|
|
178
|
+
if (fieldConfiguration.on_change) {
|
|
179
|
+
// Before Submit of form , execute the script
|
|
180
|
+
values = await prepareAndExecuteScript(values, null, fieldConfiguration.on_change);
|
|
197
181
|
}
|
|
182
|
+
};
|
|
198
183
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
184
|
+
return (
|
|
185
|
+
<section className="form-creator">
|
|
186
|
+
<div>
|
|
187
|
+
{/* <DragDropContext onDragEnd={onDragEnd}>
|
|
203
188
|
<Droppable droppableId="droppable">
|
|
204
189
|
|
|
205
190
|
{(provided, snapshot) => (
|
|
@@ -209,362 +194,343 @@ function FormCreator({
|
|
|
209
194
|
{...provided.droppableProps}
|
|
210
195
|
> */}
|
|
211
196
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
onUpload={onUpload}
|
|
271
|
-
onFieldUpdate={onFieldUpdate}
|
|
272
|
-
onFieldRemove={onFieldRemove}
|
|
273
|
-
/>
|
|
274
|
-
|
|
275
|
-
{/* Mapper Ends */}
|
|
276
|
-
|
|
277
|
-
<Button loading={loading} type="primary" htmlType="submit" className="submit-button">
|
|
278
|
-
SUBMIT
|
|
279
|
-
</Button>
|
|
280
|
-
</Form>
|
|
281
|
-
</div>
|
|
282
|
-
{/* </div>)}
|
|
197
|
+
<Form
|
|
198
|
+
form={form}
|
|
199
|
+
// layout="inline"
|
|
200
|
+
{...layoutValue}
|
|
201
|
+
className="new-record"
|
|
202
|
+
name="new-record"
|
|
203
|
+
onFinish={(values) => {
|
|
204
|
+
setLoading(true);
|
|
205
|
+
|
|
206
|
+
// Do a screening to check if date fields are
|
|
207
|
+
fields.forEach((field) => {
|
|
208
|
+
if (field.field && field.field.includes('date')) {
|
|
209
|
+
// values[field.field] = new Timestamp(new Date());
|
|
210
|
+
|
|
211
|
+
values[field.field] = moment(values[field.field]).valueOf();
|
|
212
|
+
} else {
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (field.type === 'time') {
|
|
216
|
+
// values[field.field] = new Timestamp(new Date());
|
|
217
|
+
|
|
218
|
+
values[field.field] = moment(values[field.field]).format('HH:mm A');
|
|
219
|
+
} else {
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
onSubmit(values).then(() => {
|
|
224
|
+
setLoading(false);
|
|
225
|
+
});
|
|
226
|
+
}}
|
|
227
|
+
onFieldsChange={onFieldsChange}
|
|
228
|
+
onValuesChange={onValuesChange}
|
|
229
|
+
layout={layoutValue}
|
|
230
|
+
// validateMessages={validateMessages}
|
|
231
|
+
initialValues={{
|
|
232
|
+
...content,
|
|
233
|
+
remarks: '',
|
|
234
|
+
}}
|
|
235
|
+
>
|
|
236
|
+
{/* Mapper maps each fields to build the form */}
|
|
237
|
+
<FieldMapper
|
|
238
|
+
fields={fields}
|
|
239
|
+
onChange={onChange}
|
|
240
|
+
selectedInformation={selectedInformation}
|
|
241
|
+
onUpload={onUpload}
|
|
242
|
+
onFieldUpdate={onFieldUpdate}
|
|
243
|
+
onFieldRemove={onFieldRemove}
|
|
244
|
+
formContent={formContent}
|
|
245
|
+
/>
|
|
246
|
+
|
|
247
|
+
{/* Mapper Ends */}
|
|
248
|
+
|
|
249
|
+
<Button loading={loading} type="primary" htmlType="submit" className="submit-button">
|
|
250
|
+
SUBMIT
|
|
251
|
+
</Button>
|
|
252
|
+
</Form>
|
|
253
|
+
</div>
|
|
254
|
+
{/* </div>)}
|
|
283
255
|
|
|
284
256
|
</Droppable>
|
|
285
257
|
</DragDropContext> */}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
);
|
|
258
|
+
</section>
|
|
259
|
+
);
|
|
289
260
|
}
|
|
290
261
|
|
|
291
262
|
export default FormCreator;
|
|
292
263
|
|
|
293
|
-
|
|
294
264
|
/**
|
|
295
265
|
* Field Mapper accepts fields to build the form
|
|
296
|
-
*
|
|
297
|
-
* @param {*} param0
|
|
298
|
-
* @returns
|
|
266
|
+
*
|
|
267
|
+
* @param {*} param0
|
|
268
|
+
* @returns
|
|
299
269
|
*/
|
|
300
|
-
function FieldMapper({
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
270
|
+
function FieldMapper({ fields = [], onChange, selectedInformation, onUpload, onFieldUpdate, onFieldRemove, formContent }) {
|
|
271
|
+
return (
|
|
272
|
+
<>
|
|
273
|
+
{fields.map((field, index) => {
|
|
274
|
+
// For Tabs
|
|
275
|
+
if (field.type === 'Tabs') {
|
|
276
|
+
return (
|
|
277
|
+
<Tabs defaultActiveKey="0">
|
|
278
|
+
{field.tabs.map((tab, tabIndex) => {
|
|
279
|
+
return (
|
|
280
|
+
<TabPane tab={`${tab.caption}`} key={tabIndex}>
|
|
281
|
+
{/* Customizes the Tab */}
|
|
282
|
+
<TabCustomizer
|
|
283
|
+
tab={tab}
|
|
284
|
+
field={field}
|
|
285
|
+
onFieldUpdate={onFieldUpdate}
|
|
286
|
+
fieldIndex={tabIndex}
|
|
287
|
+
index={index}
|
|
288
|
+
onFieldRemove={onFieldRemove}
|
|
289
|
+
/>
|
|
290
|
+
{/* Customizes the Tab Ends */}
|
|
308
291
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
</Tabs>)
|
|
352
|
-
|
|
353
|
-
} else {
|
|
354
|
-
|
|
355
|
-
if (field.condition) {
|
|
356
|
-
|
|
357
|
-
return field.condition(content)
|
|
358
|
-
?
|
|
359
|
-
<UserInput
|
|
360
|
-
onChange={onChange}
|
|
361
|
-
index={index}
|
|
362
|
-
key={index}
|
|
363
|
-
onUpload={onUpload}
|
|
364
|
-
field={field}
|
|
365
|
-
onFieldUpdate={onFieldUpdate}
|
|
366
|
-
onFieldRemove={onFieldRemove}
|
|
367
|
-
/>
|
|
368
|
-
:
|
|
369
|
-
null
|
|
370
|
-
|
|
371
|
-
} else {
|
|
372
|
-
return <UserInput
|
|
373
|
-
onChange={onChange}
|
|
374
|
-
key={index}
|
|
375
|
-
selectedInformation={selectedInformation}
|
|
376
|
-
index={index}
|
|
377
|
-
field={field}
|
|
378
|
-
onUpload={onUpload}
|
|
379
|
-
onFieldUpdate={onFieldUpdate}
|
|
380
|
-
|
|
381
|
-
onFieldRemove={onFieldRemove}
|
|
382
|
-
|
|
383
|
-
/>;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
})
|
|
292
|
+
{/* Mapper maps each fields to build the form */}
|
|
293
|
+
<FieldMapper
|
|
294
|
+
fields={tab.fields}
|
|
295
|
+
onChange={onChange}
|
|
296
|
+
onUpload={onUpload}
|
|
297
|
+
onFieldUpdate={onFieldUpdate}
|
|
298
|
+
onFieldRemove={onFieldRemove}
|
|
299
|
+
/>
|
|
300
|
+
</TabPane>
|
|
301
|
+
);
|
|
302
|
+
})}
|
|
303
|
+
</Tabs>
|
|
304
|
+
);
|
|
305
|
+
} else {
|
|
306
|
+
if (field.condition) {
|
|
307
|
+
return field.condition(content) ? (
|
|
308
|
+
<UserInput
|
|
309
|
+
onChange={onChange}
|
|
310
|
+
index={index}
|
|
311
|
+
key={index}
|
|
312
|
+
onUpload={onUpload}
|
|
313
|
+
field={field}
|
|
314
|
+
onFieldUpdate={onFieldUpdate}
|
|
315
|
+
onFieldRemove={onFieldRemove}
|
|
316
|
+
formContent={formContent}
|
|
317
|
+
/>
|
|
318
|
+
) : null;
|
|
319
|
+
} else {
|
|
320
|
+
return (
|
|
321
|
+
<UserInput
|
|
322
|
+
onChange={onChange}
|
|
323
|
+
key={index}
|
|
324
|
+
selectedInformation={selectedInformation}
|
|
325
|
+
index={index}
|
|
326
|
+
field={field}
|
|
327
|
+
onUpload={onUpload}
|
|
328
|
+
onFieldUpdate={onFieldUpdate}
|
|
329
|
+
onFieldRemove={onFieldRemove}
|
|
330
|
+
formContent={formContent}
|
|
331
|
+
/>
|
|
332
|
+
);
|
|
333
|
+
}
|
|
387
334
|
}
|
|
388
|
-
|
|
389
|
-
</>
|
|
390
|
-
|
|
335
|
+
})}
|
|
336
|
+
</>
|
|
337
|
+
);
|
|
391
338
|
}
|
|
392
339
|
|
|
393
|
-
|
|
394
|
-
|
|
395
340
|
/**
|
|
396
341
|
* Component accepts user input according to type
|
|
397
|
-
*
|
|
398
|
-
* @param {*} param0
|
|
342
|
+
*
|
|
343
|
+
* @param {*} param0
|
|
399
344
|
*/
|
|
400
|
-
function UserInput({ field, onUpload, selectedInformation, onChange, onFieldUpdate, onFieldRemove, index }) {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
345
|
+
function UserInput({ field, onUpload, selectedInformation, onChange, onFieldUpdate, onFieldRemove, index, formContent }) {
|
|
346
|
+
let props = {};
|
|
347
|
+
|
|
348
|
+
// The extra text
|
|
349
|
+
if (field.extra) {
|
|
350
|
+
props.extra = field.extra;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const isVisible = field.visible !== undefined ? field.visible : true;
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* According to the type render each element
|
|
357
|
+
*
|
|
358
|
+
* @param {*} field
|
|
359
|
+
*/
|
|
360
|
+
const inputElement = (field, onChange) => {
|
|
361
|
+
if (field.visible) {
|
|
362
|
+
if (field.visible === false) return null;
|
|
407
363
|
}
|
|
408
364
|
|
|
409
|
-
|
|
365
|
+
switch (field.type) {
|
|
366
|
+
case 'number':
|
|
367
|
+
return <InputNumber required={field.required} />;
|
|
368
|
+
|
|
369
|
+
case 'input':
|
|
370
|
+
return <Input required={field.required} />;
|
|
371
|
+
|
|
372
|
+
case 'radio':
|
|
373
|
+
return (
|
|
374
|
+
<Radio.Group>
|
|
375
|
+
{field.options.map((option, key) => (
|
|
376
|
+
<Radio key={key} value={option}>
|
|
377
|
+
{option ? 'Yes' : 'No'}
|
|
378
|
+
</Radio>
|
|
379
|
+
))}
|
|
380
|
+
</Radio.Group>
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
case 'checkbox':
|
|
384
|
+
return (
|
|
385
|
+
<Checkbox.Group style={{ width: '100%' }}>
|
|
386
|
+
<Col>
|
|
387
|
+
{field.options.map((option, key) => {
|
|
388
|
+
let opt = typeof option === 'string' ? option : option.value;
|
|
410
389
|
|
|
411
|
-
/**
|
|
412
|
-
* According to the type render each element
|
|
413
|
-
*
|
|
414
|
-
* @param {*} field
|
|
415
|
-
*/
|
|
416
|
-
const inputElement = (field, onChange) => {
|
|
417
|
-
|
|
418
|
-
if (field.visible) {
|
|
419
|
-
|
|
420
|
-
if (field.visible === false) return null;
|
|
421
|
-
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
switch (field.type) {
|
|
425
|
-
|
|
426
|
-
case 'number':
|
|
427
|
-
return <InputNumber required={field.required} />
|
|
428
|
-
|
|
429
|
-
case 'input':
|
|
430
|
-
return <Input required={field.required} />
|
|
431
|
-
|
|
432
|
-
case 'radio':
|
|
433
390
|
return (
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
391
|
+
<Row>
|
|
392
|
+
<Checkbox key={key} value={opt}>
|
|
393
|
+
{opt}
|
|
394
|
+
</Checkbox>
|
|
395
|
+
</Row>
|
|
440
396
|
);
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
return (
|
|
496
|
-
<Select defaultValue={defaultValue}
|
|
497
|
-
required={field.required}
|
|
498
|
-
style={{ width: 120 }}
|
|
499
|
-
onChange={(value) => onChange(field, value)}
|
|
500
|
-
>
|
|
501
|
-
{field.options.map((option, key) => (
|
|
502
|
-
<Option key={key} value={option.valueMember}>
|
|
503
|
-
{option.displayMember}
|
|
504
|
-
</Option>
|
|
505
|
-
))}
|
|
506
|
-
</Select>
|
|
507
|
-
);
|
|
508
|
-
}
|
|
509
|
-
// case 'checkbox':
|
|
510
|
-
// return <Checkbox.Group options={field.options} />
|
|
511
|
-
|
|
512
|
-
case 'datetime':
|
|
513
|
-
return <DatePicker format={"DD/MM/YYYY"} onChange={(record) => {
|
|
514
|
-
|
|
515
|
-
onChange(field, record.format('DD/MM/YYYY'))
|
|
516
|
-
|
|
517
|
-
}} />
|
|
518
|
-
|
|
519
|
-
case 'date':
|
|
520
|
-
return <DatePicker format={"DD/MM/YYYY"} />
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
case 'time':
|
|
524
|
-
return <TimePicker format={"HH:mm A"} />
|
|
525
|
-
|
|
526
|
-
// onChange={(record) => {
|
|
527
|
-
|
|
528
|
-
// console.log(record);
|
|
529
|
-
|
|
530
|
-
// onChange(field, record.format('HH:mm A'))
|
|
531
|
-
|
|
532
|
-
// }}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
case 'upload':
|
|
536
|
-
return <FileUpload multiple={field.multiple} maxSize={field.maxSize || 3} callback={(attachment) => onUpload(field, attachment)} onProgress={() => { }} />
|
|
537
|
-
|
|
538
|
-
case 'camera':
|
|
539
|
-
return <Camera />
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
default:
|
|
543
|
-
return <Input />
|
|
397
|
+
})}
|
|
398
|
+
</Col>
|
|
399
|
+
</Checkbox.Group>
|
|
400
|
+
);
|
|
401
|
+
|
|
402
|
+
// case 'checkbox':
|
|
403
|
+
// return <Checkbox.Group options={field.options}/>
|
|
404
|
+
case 'textarea':
|
|
405
|
+
return <TextArea rows={4} required={field.required} />;
|
|
406
|
+
|
|
407
|
+
case 'boolean':
|
|
408
|
+
return (
|
|
409
|
+
<Select style={{ width: 120 }} required={field.required}>
|
|
410
|
+
{[true, false].map((option, key) => (
|
|
411
|
+
<Option key={key} value={option}>
|
|
412
|
+
{option ? 'Yes' : 'No'}
|
|
413
|
+
</Option>
|
|
414
|
+
))}
|
|
415
|
+
</Select>
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
case 'select':
|
|
419
|
+
// Handle static select options
|
|
420
|
+
if (Array.isArray(field.options)) {
|
|
421
|
+
let defaultValue = field.default ? field.default : '';
|
|
422
|
+
|
|
423
|
+
/**If there is selected Information ie, for change info if there is selected guest information
|
|
424
|
+
* then we will match and set a default value from the guest details
|
|
425
|
+
*/
|
|
426
|
+
if (selectedInformation) {
|
|
427
|
+
// Get the field value dynamically from selectedInformation[0] using field.field
|
|
428
|
+
const fieldValue = selectedInformation[0] && selectedInformation[0][field.caption];
|
|
429
|
+
|
|
430
|
+
// Find the default value based on field value and matching DisplayMember or description
|
|
431
|
+
const defaultOption = field.options.find((option) => option.displayMember?.toLowerCase() === fieldValue?.toLowerCase());
|
|
432
|
+
|
|
433
|
+
// If a matching option is found, set the default value; otherwise, do not set a default value (i.e., null or undefined)
|
|
434
|
+
defaultValue = defaultOption ? defaultOption.valueMember : null;
|
|
435
|
+
}
|
|
436
|
+
/**In case of default selection we need to call the onchange manually */
|
|
437
|
+
if (defaultValue) {
|
|
438
|
+
onChange(field, defaultValue);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
return (
|
|
442
|
+
<Select defaultValue={defaultValue} required={field.required} style={{ width: 120 }} onChange={(value) => onChange(field, value)}>
|
|
443
|
+
{field.options.map((option, key) => (
|
|
444
|
+
<Option key={key} value={option.valueMember}>
|
|
445
|
+
{option.displayMember}
|
|
446
|
+
</Option>
|
|
447
|
+
))}
|
|
448
|
+
</Select>
|
|
449
|
+
);
|
|
544
450
|
}
|
|
451
|
+
// case 'checkbox':
|
|
452
|
+
// return <Checkbox.Group options={field.options} />
|
|
453
|
+
case 'reference-select':
|
|
454
|
+
// If a default value is provided in the field configuration
|
|
455
|
+
if (field.default) {
|
|
456
|
+
onChange(field, field.default);
|
|
457
|
+
}
|
|
458
|
+
// Render the ReferenceSelect component
|
|
459
|
+
|
|
460
|
+
return (
|
|
461
|
+
<ReferenceSelect
|
|
462
|
+
style={{ width: 120 }}
|
|
463
|
+
field={field.code}
|
|
464
|
+
model={formContent[field.modelName]}
|
|
465
|
+
{...field}
|
|
466
|
+
onChange={(value) => onChange(field, value)}
|
|
467
|
+
defaultValue={field.default}
|
|
468
|
+
// defaultValue={'1'}
|
|
469
|
+
/>
|
|
470
|
+
);
|
|
471
|
+
|
|
472
|
+
case 'datetime':
|
|
473
|
+
return (
|
|
474
|
+
<DatePicker
|
|
475
|
+
format={'DD/MM/YYYY'}
|
|
476
|
+
onChange={(record) => {
|
|
477
|
+
onChange(field, record.format('DD/MM/YYYY'));
|
|
478
|
+
}}
|
|
479
|
+
/>
|
|
480
|
+
);
|
|
481
|
+
|
|
482
|
+
case 'date':
|
|
483
|
+
return <DatePicker format={'DD/MM/YYYY'} />;
|
|
484
|
+
|
|
485
|
+
case 'time':
|
|
486
|
+
return <TimePicker format={'HH:mm A'} />;
|
|
487
|
+
|
|
488
|
+
// onChange={(record) => {
|
|
489
|
+
|
|
490
|
+
// console.log(record);
|
|
491
|
+
|
|
492
|
+
// onChange(field, record.format('HH:mm A'))
|
|
493
|
+
|
|
494
|
+
// }}
|
|
495
|
+
|
|
496
|
+
case 'upload':
|
|
497
|
+
return (
|
|
498
|
+
<FileUpload
|
|
499
|
+
multiple={field.multiple}
|
|
500
|
+
maxSize={field.maxSize || 3}
|
|
501
|
+
callback={(attachment) => onUpload(field, attachment)}
|
|
502
|
+
onProgress={() => {}}
|
|
503
|
+
/>
|
|
504
|
+
);
|
|
505
|
+
|
|
506
|
+
case 'camera':
|
|
507
|
+
return <Camera />;
|
|
508
|
+
|
|
509
|
+
default:
|
|
510
|
+
return <Input />;
|
|
545
511
|
}
|
|
512
|
+
};
|
|
546
513
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
// // change background colour if dragging
|
|
556
|
-
// // background: isDragging ? 'lightgreen' : 'whitesmoke',
|
|
514
|
+
// const getItemStyle = (draggableStyle, isDragging) => ({
|
|
515
|
+
// // some basic styles to make the items look a bit nicer
|
|
516
|
+
// userSelect: 'none',
|
|
517
|
+
// // padding: grid,
|
|
518
|
+
// // margin: `0 0 ${grid}px 0`,
|
|
519
|
+
// // position: `absolute`,
|
|
520
|
+
// // right: '40px',
|
|
557
521
|
|
|
558
|
-
|
|
522
|
+
// // change background colour if dragging
|
|
523
|
+
// // background: isDragging ? 'lightgreen' : 'whitesmoke',
|
|
559
524
|
|
|
560
|
-
|
|
561
|
-
// ...draggableStyle
|
|
562
|
-
// });
|
|
525
|
+
// boxShadow: isDragging ? '0px 0px 5px 5px #eeeeee' : '',
|
|
563
526
|
|
|
527
|
+
// // styles we need to apply on draggables
|
|
528
|
+
// ...draggableStyle
|
|
529
|
+
// });
|
|
564
530
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
531
|
+
return (
|
|
532
|
+
<>
|
|
533
|
+
{/* <Draggable
|
|
568
534
|
key={`${field.caption}-${index}`}
|
|
569
535
|
draggableId={`${field.caption}-${index}`}
|
|
570
536
|
index={index}
|
|
@@ -582,10 +548,9 @@ function UserInput({ field, onUpload, selectedInformation, onChange, onFieldUpda
|
|
|
582
548
|
)}
|
|
583
549
|
|
|
584
550
|
> */}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
{/* <Button
|
|
551
|
+
{isVisible === true ? (
|
|
552
|
+
<div className="form-item-element">
|
|
553
|
+
{/* <Button
|
|
589
554
|
size="small"
|
|
590
555
|
ref={provided.innerRef}
|
|
591
556
|
{...provided.dragHandleProps}
|
|
@@ -600,25 +565,25 @@ function UserInput({ field, onUpload, selectedInformation, onChange, onFieldUpda
|
|
|
600
565
|
|
|
601
566
|
</Button> */}
|
|
602
567
|
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
568
|
+
{/* Customizes the form */}
|
|
569
|
+
<FieldCustomizer field={field} onFieldUpdate={onFieldUpdate} index={index} onFieldRemove={onFieldRemove} />
|
|
570
|
+
{/* Customizes the form Ends */}
|
|
571
|
+
|
|
572
|
+
<Form.Item
|
|
573
|
+
{...props}
|
|
574
|
+
name={field.field}
|
|
575
|
+
label={field.caption}
|
|
576
|
+
rules={[{ required: field.required, message: field.placeholder || 'Please enter ' + field.caption }]}
|
|
577
|
+
>
|
|
578
|
+
{inputElement(field, onChange)}
|
|
579
|
+
{/* <InputElement field={field} /> */}
|
|
580
|
+
</Form.Item>
|
|
581
|
+
</div>
|
|
582
|
+
) : null}
|
|
583
|
+
{/* </div>
|
|
618
584
|
</div>
|
|
619
585
|
)}
|
|
620
586
|
</Draggable> */}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
)
|
|
587
|
+
</>
|
|
588
|
+
);
|
|
624
589
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useState, useEffect, useContext, useRef } from 'react';
|
|
2
2
|
|
|
3
|
-
import { Table, Skeleton, Input, Tag, Modal, message, Pagination } from 'antd';
|
|
3
|
+
import { Table, Skeleton, Input, Tag, Modal, message, Pagination, Tooltip } from 'antd';
|
|
4
4
|
|
|
5
5
|
import { QrcodeOutlined } from '@ant-design/icons';
|
|
6
6
|
|
|
@@ -220,7 +220,7 @@ export default function ReportingDashboard({
|
|
|
220
220
|
if (['reference-select', 'reference-search', 'select'].indexOf(record.type) !== -1) {
|
|
221
221
|
// let model = "";
|
|
222
222
|
let model = CustomModels[record.modelName];
|
|
223
|
-
|
|
223
|
+
formContent[record.modelName] = model;
|
|
224
224
|
return {
|
|
225
225
|
...record,
|
|
226
226
|
model,
|
|
@@ -270,7 +270,19 @@ export default function ReportingDashboard({
|
|
|
270
270
|
try {
|
|
271
271
|
// Prepare payload for backend: format only here
|
|
272
272
|
const formattedValues = {};
|
|
273
|
+
const inputParams = JSON.parse(config.input_parameters);
|
|
274
|
+
// Extract only allowed field names from input parameters
|
|
275
|
+
|
|
276
|
+
const allowedFields = inputParams.map((p) => p.field);
|
|
277
|
+
// Iterate through all keys in the values object
|
|
278
|
+
|
|
273
279
|
Object.keys(values).forEach((key) => {
|
|
280
|
+
// Skip keys that are not in the allowed fields list
|
|
281
|
+
|
|
282
|
+
if (!allowedFields.includes(key)) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
|
|
274
286
|
const val = values[key];
|
|
275
287
|
formattedValues[key] = moment.isMoment(val) ? val.format('YYYY-MM-DD') : val;
|
|
276
288
|
});
|
|
@@ -290,6 +302,7 @@ export default function ReportingDashboard({
|
|
|
290
302
|
if (scope) {
|
|
291
303
|
formBody = { body: { ...scope, ...paginationData } };
|
|
292
304
|
}
|
|
305
|
+
|
|
293
306
|
// Fetch result
|
|
294
307
|
const result = await CoreScripts.getReportingLisitng(coreScriptId, formBody, dbPtr);
|
|
295
308
|
// Handle both result formats
|
|
@@ -410,7 +423,7 @@ export default function ReportingDashboard({
|
|
|
410
423
|
Object.entries(urlsToUpdate).filter(([_, value]) => value !== undefined && value !== null && value !== '')
|
|
411
424
|
);
|
|
412
425
|
|
|
413
|
-
setformContents(formContent);
|
|
426
|
+
setformContents((prev) => ({ ...prev, ...formContent }));
|
|
414
427
|
Location.search({ ...Location.search(), ...filteredParams });
|
|
415
428
|
}
|
|
416
429
|
|
|
@@ -798,9 +811,19 @@ function GuestList({
|
|
|
798
811
|
}
|
|
799
812
|
},
|
|
800
813
|
field: entry.field,
|
|
801
|
-
title: entry.title,
|
|
814
|
+
// title: entry.title,
|
|
815
|
+
// title: (
|
|
816
|
+
// <Tooltip title={entry.title}>
|
|
817
|
+
// {entry.title}
|
|
818
|
+
// </Tooltip>
|
|
819
|
+
// ),
|
|
820
|
+
title: (
|
|
821
|
+
<Tooltip title={entry.tooltip || entry.title}>
|
|
822
|
+
<span>{entry.title}</span>
|
|
823
|
+
</Tooltip>
|
|
824
|
+
),
|
|
802
825
|
key: entry.field,
|
|
803
|
-
width: entry.width ? parseInt(entry.width) :
|
|
826
|
+
width: entry.width ? parseInt(entry.width) : 160,
|
|
804
827
|
fixed: entry.isFixedColumn ? entry.isFixedColumn : null, // Conditionally setting the 'fixed' key to 'left' if 'isColumnStatic' is true; otherwise, setting it to null.
|
|
805
828
|
// Check if filtering is enabled and patients is an array
|
|
806
829
|
filters:
|
|
@@ -824,7 +847,6 @@ function GuestList({
|
|
|
824
847
|
// Return the value from record.props if it exists
|
|
825
848
|
return description && record[description] ? record[description] : null;
|
|
826
849
|
}
|
|
827
|
-
|
|
828
850
|
return record[entry.field];
|
|
829
851
|
},
|
|
830
852
|
// Add align property based on column type
|
|
@@ -908,13 +930,21 @@ function GuestList({
|
|
|
908
930
|
// setData(data);
|
|
909
931
|
|
|
910
932
|
// Define export data
|
|
911
|
-
|
|
933
|
+
// Sanitize cols for export to ensure titles are strings
|
|
934
|
+
const exportCols = cols.map((col) => {
|
|
935
|
+
if (col.title && typeof col.title === 'object' && col.title.props) {
|
|
936
|
+
return { ...col, title: col.title.props.title };
|
|
937
|
+
}
|
|
938
|
+
return col;
|
|
939
|
+
});
|
|
940
|
+
|
|
941
|
+
let exportDatas = getExportData(patients, exportCols);
|
|
912
942
|
|
|
913
943
|
if (exportDatas.exportDataColumns.length && exportDatas.exportDataHeaders.length) {
|
|
914
944
|
setExportData({ exportDatas });
|
|
915
945
|
}
|
|
916
946
|
}
|
|
917
|
-
}, [patients]);
|
|
947
|
+
}, [patients, columns]);
|
|
918
948
|
|
|
919
949
|
let filtered;
|
|
920
950
|
|