@visns-studio/visns-components 4.7.2 → 4.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/package.json +13 -9
  2. package/src/components/cms/DataGrid.jsx +1461 -0
  3. package/src/components/cms/DropZone.jsx +349 -0
  4. package/src/components/cms/Field.jsx +802 -0
  5. package/src/components/cms/Form.jsx +476 -0
  6. package/src/components/cms/generic/CmsDetail.jsx +36 -0
  7. package/src/components/cms/generic/CmsIndex.jsx +73 -0
  8. package/src/components/cms/generic/CmsSort.jsx +125 -0
  9. package/src/components/cms/sorting/Item.jsx +115 -0
  10. package/src/components/cms/sorting/List.jsx +30 -0
  11. package/src/components/crm/AsyncSelect.jsx +125 -0
  12. package/src/components/crm/Autocomplete.jsx +174 -0
  13. package/src/components/crm/Breadcrumb.jsx +52 -0
  14. package/src/components/crm/Call.jsx +220 -0
  15. package/src/components/crm/DataGrid.jsx +2701 -0
  16. package/src/components/crm/Download.jsx +101 -0
  17. package/src/components/crm/Fetch.jsx +119 -0
  18. package/src/components/crm/Field.jsx +1557 -0
  19. package/src/components/crm/Form.jsx +1409 -0
  20. package/src/components/crm/Loader.jsx +29 -0
  21. package/src/components/crm/MultiSelect.jsx +78 -0
  22. package/src/components/crm/Navigation.jsx +619 -0
  23. package/src/components/crm/Notification.jsx +197 -0
  24. package/src/components/crm/QrCode.jsx +83 -0
  25. package/src/components/crm/Select.jsx +58 -0
  26. package/src/components/crm/SelectList.jsx +21 -0
  27. package/src/components/crm/TableFilter.jsx +198 -0
  28. package/src/components/crm/auth/Login.jsx +223 -0
  29. package/src/components/crm/auth/Profile.jsx +280 -0
  30. package/src/components/crm/auth/Reset.jsx +111 -0
  31. package/src/components/crm/auth/Verify.jsx +174 -0
  32. package/src/components/crm/auth/styles/Login.module.scss +243 -0
  33. package/src/components/crm/auth/styles/Profile.module.scss +222 -0
  34. package/src/components/crm/auth/styles/Reset.module.scss +216 -0
  35. package/src/components/crm/auth/styles/Verify.module.scss +216 -0
  36. package/src/components/crm/generic/AuditLog.jsx +108 -0
  37. package/src/components/crm/generic/AuditLogs.jsx +115 -0
  38. package/src/components/crm/generic/GenericAuth.jsx +166 -0
  39. package/src/components/crm/generic/GenericDashboard.jsx +42 -0
  40. package/src/components/crm/generic/GenericDetail.jsx +1499 -0
  41. package/src/components/crm/generic/GenericDynamic.jsx +915 -0
  42. package/src/components/crm/generic/GenericFormBuilder.jsx +1765 -0
  43. package/src/components/crm/generic/GenericIndex.jsx +376 -0
  44. package/src/components/crm/generic/GenericMain.jsx +129 -0
  45. package/src/components/crm/generic/GenericSort.jsx +188 -0
  46. package/src/components/crm/generic/NotificationList.jsx +64 -0
  47. package/src/components/crm/generic/styles/AuditLog.module.scss +147 -0
  48. package/src/components/crm/generic/styles/AuditLogs.module.scss +92 -0
  49. package/src/components/crm/generic/styles/GenericDetail.module.scss +634 -0
  50. package/src/components/crm/generic/styles/GenericDynamic.module.scss +932 -0
  51. package/src/components/crm/generic/styles/GenericFormBuilder.module.scss +944 -0
  52. package/src/components/crm/generic/styles/GenericIndex.module.scss +247 -0
  53. package/src/components/crm/generic/styles/GenericMain.module.scss +91 -0
  54. package/src/components/crm/generic/styles/GenericSort.module.scss +123 -0
  55. package/src/components/crm/generic/styles/NotificationList.module.scss +67 -0
  56. package/src/components/crm/sorting/Item.jsx +117 -0
  57. package/src/components/crm/sorting/List.jsx +32 -0
  58. package/src/components/crm/sorting/styles/Item.module.scss +68 -0
  59. package/src/components/crm/sorting/styles/List.module.scss +68 -0
  60. package/src/components/crm/styles/AsyncSelect.module.scss +8 -0
  61. package/src/components/crm/styles/Autocomplete.module.scss +44 -0
  62. package/src/components/crm/styles/DataGrid.module.scss +210 -0
  63. package/src/components/crm/styles/Field.module.scss +311 -0
  64. package/src/components/crm/styles/Form.module.scss +499 -0
  65. package/src/components/crm/styles/Loader.module.scss +94 -0
  66. package/src/components/crm/styles/MultiSelect.module.scss +8 -0
  67. package/src/components/crm/styles/Navigation.module.scss +978 -0
  68. package/src/components/crm/styles/Notification.module.scss +147 -0
  69. package/src/components/crm/styles/QrCode.module.scss +87 -0
  70. package/src/components/crm/styles/TableFilter.module.scss +52 -0
  71. package/src/components/styles/global.css +73 -0
  72. package/src/index.js +86 -0
  73. package/dist/104e5636d8ddb791614c.woff2 +0 -0
  74. package/dist/11fe6a83d647de5daf95.woff +0 -0
  75. package/dist/141e2a8c7836495afe2a.woff +0 -0
  76. package/dist/2ba5877f7079830b5383.woff +0 -0
  77. package/dist/2d6836f45b2037be41f3.woff +0 -0
  78. package/dist/399.0a0f3e0d21be1057d599.css +0 -8
  79. package/dist/399.b8f57fa3f8c0c10119e4.js +0 -1
  80. package/dist/47d566c3b1293dfd9d77.woff +0 -0
  81. package/dist/6282a13cbba671a71913.woff2 +0 -0
  82. package/dist/78266f551031aa9db127.woff +0 -0
  83. package/dist/7b7da89f1e3fdcbfe36c.woff2 +0 -0
  84. package/dist/7e78e8338af7efeda712.woff2 +0 -0
  85. package/dist/7fa387951673abf164b1.woff2 +0 -0
  86. package/dist/819d59862c2d0640aad8.woff +0 -0
  87. package/dist/b615e1a6c838ea059a56.woff +0 -0
  88. package/dist/b9b1aa739c660c4ce67c.woff2 +0 -0
  89. package/dist/c5f3640b11df9414facb.woff +0 -0
  90. package/dist/da26d162ff5af71d6590.woff2 +0 -0
  91. package/dist/dd5b2912dbf896310865.woff2 +0 -0
  92. package/dist/f282b331272463c1aa6c.woff2 +0 -0
  93. package/dist/index.css +0 -2902
  94. package/dist/index.js +0 -2
  95. package/dist/index.js.LICENSE.txt +0 -150
  96. package/dist/main.83b033670d64419bb497.css +0 -1
  97. package/dist/main.b1723d17cd2d3513ab62.js +0 -1
  98. package/dist/report.html +0 -39
  99. package/dist/runtime.33c276593b23f8035b8d.js +0 -1
@@ -0,0 +1,1461 @@
1
+ import React, { useCallback, useEffect, useState } from 'react';
2
+ import { useNavigate } from 'react-router-dom';
3
+ import axios from 'axios';
4
+ import debounce from 'lodash.debounce';
5
+ import moment from 'moment';
6
+ import numeral from 'numeral';
7
+ import Popup from 'reactjs-popup';
8
+ import parse from 'html-react-parser';
9
+ import NumberFilter from '@inovua/reactdatagrid-community/NumberFilter';
10
+ import SelectFilter from '@inovua/reactdatagrid-community/SelectFilter';
11
+ import DateFilter from '@inovua/reactdatagrid-community/DateFilter';
12
+ import ReactDataGrid from '@inovua/reactdatagrid-community';
13
+ import { confirmAlert } from 'react-confirm-alert';
14
+ import { toast } from 'react-toastify';
15
+ import Toggle from 'react-toggle';
16
+ import {
17
+ Backspace,
18
+ Check,
19
+ Clock,
20
+ CloudDownload,
21
+ Copy,
22
+ Edit,
23
+ Folder,
24
+ Inbox,
25
+ Network,
26
+ Ribbon,
27
+ Search,
28
+ ShippingBoxV1,
29
+ ToggleOff,
30
+ ToggleOnFill,
31
+ TriangleAlert,
32
+ } from 'akar-icons';
33
+
34
+ import '@inovua/reactdatagrid-community/index.css';
35
+ import 'react-confirm-alert/src/react-confirm-alert.css';
36
+ import 'react-toggle/style.css';
37
+
38
+ import CustomFetch from '../crm/Fetch';
39
+ import Form from './Form';
40
+
41
+ const loadData = async (
42
+ { skip, limit, sortInfo, currentData, filterValue, groupBy },
43
+ search,
44
+ ajaxSetting
45
+ ) => {
46
+ const url = ajaxSetting.url;
47
+ const page = Math.floor(skip / limit) + 1;
48
+ const params = { page, sortInfo, take: limit, search: search, where: [] };
49
+
50
+ if (sortInfo) {
51
+ params.sortBy = sortInfo.name;
52
+ params.sort = sortInfo.dir === 1 ? 'asc' : 'desc';
53
+ }
54
+
55
+ if (ajaxSetting && ajaxSetting.where) {
56
+ params.where = ajaxSetting.where;
57
+ }
58
+
59
+ if (filterValue) {
60
+ filterValue.forEach((fv) => {
61
+ const identifier = fv.key ? fv.key : fv.name;
62
+ const existingIndex = params.where.findIndex(
63
+ (w) => w.id === identifier
64
+ );
65
+
66
+ if (fv.value !== null && fv.value !== '') {
67
+ if (existingIndex !== -1) {
68
+ params.where[existingIndex].value = fv.value;
69
+ } else {
70
+ params.where.push({
71
+ id: identifier,
72
+ value: fv.value,
73
+ operator: fv.operator,
74
+ });
75
+ }
76
+ } else {
77
+ if (existingIndex !== -1) {
78
+ params.where.splice(existingIndex, 1);
79
+ }
80
+ }
81
+ });
82
+ }
83
+
84
+ try {
85
+ const response = await axios.post(url, params);
86
+ const { data, total } = response.data;
87
+ return { data, count: total };
88
+ } catch (error) {
89
+ console.error('Error fetching data:', error);
90
+ return { data: [], count: 0 };
91
+ }
92
+ };
93
+
94
+ const DataGrid = ({
95
+ ajaxSetting,
96
+ columns,
97
+ form,
98
+ gridHeight,
99
+ settings,
100
+ setFilterData,
101
+ setConfig,
102
+ style,
103
+ }) => {
104
+ const navigate = useNavigate();
105
+
106
+ /** Modal States */
107
+ const [formData, setFormData] = useState(form);
108
+ const [formType, setFormType] = useState('');
109
+ const [formId, setFormId] = useState(0);
110
+ const [modalShow, setModalShow] = useState(false);
111
+
112
+ /** Modal Functions */
113
+ const childDropdownCallback = (data) => {
114
+ let _form = { ...formData };
115
+
116
+ if (formData.fields.length > 0) {
117
+ formData.fields.forEach((a, b) => {
118
+ if (a.id === data.id) {
119
+ _form.fields[b].options = data.data;
120
+ }
121
+ });
122
+ }
123
+
124
+ setFormData(_form);
125
+ };
126
+
127
+ const modalOpen = (formType, formId) => {
128
+ setModalShow(true);
129
+ setFormType(formType);
130
+ setFormId(formId);
131
+ };
132
+
133
+ const modalClose = () => {
134
+ setModalShow(false);
135
+ };
136
+
137
+ useEffect(() => {
138
+ setFormData(form);
139
+ }, [form]);
140
+
141
+ /** Table States */
142
+ const [dataReload, setDataReload] = useState(0);
143
+ const [dSearch, setDSearch] = useState('');
144
+ const data = useCallback(
145
+ (params) => {
146
+ const sqlResult = loadData(params, dSearch, ajaxSetting);
147
+
148
+ sqlResult.then((res) => {
149
+ setDataCount(res.count);
150
+ });
151
+
152
+ return sqlResult;
153
+ },
154
+ [ajaxSetting, dataReload, dSearch]
155
+ );
156
+ const [filterDataSource, setFilterDataSource] = useState([]);
157
+ const [filterValue, setFilterValue] = useState([]);
158
+ const [gridColumns, setGridColumns] = useState([]);
159
+ const [limit, setLimit] = useState(ajaxSetting.take || 10);
160
+ const [search, setSearch] = useState('');
161
+
162
+ /** Table Functions */
163
+ const handleChangeSearch = (e) => {
164
+ const { value } = e.target;
165
+ setSearch(value);
166
+ };
167
+
168
+ const handleSettingClick = (s, d) => {
169
+ switch (s.id) {
170
+ case 'update':
171
+ modalOpen('update', d.id);
172
+ break;
173
+ case 'delete':
174
+ confirmAlert({
175
+ title: 'Delete Item',
176
+ message: `Are you sure you want to delete ${
177
+ d.name ? d.name : d.label ? d.label : 'this item'
178
+ }?`,
179
+ buttons: [
180
+ {
181
+ label: 'Yes',
182
+ onClick: () =>
183
+ CustomFetch(
184
+ form.url + '/' + d[form.primaryKey],
185
+ 'DELETE',
186
+ {},
187
+ (result) => {
188
+ if (result.error === '') {
189
+ const min = 0;
190
+ const max = 999999999;
191
+ const randomNumber = Math.floor(
192
+ Math.random() *
193
+ (max - min + 1) +
194
+ min
195
+ );
196
+
197
+ setDataReload(randomNumber);
198
+
199
+ toast.success(
200
+ `The selected item has been deleted.`
201
+ );
202
+ } else {
203
+ toast.error(String(result.error));
204
+ }
205
+ }
206
+ ),
207
+ },
208
+ {
209
+ label: 'No',
210
+ onClick: () => close(),
211
+ },
212
+ ],
213
+ });
214
+ break;
215
+ default:
216
+ confirmAlert({
217
+ title: s.title,
218
+ message: '',
219
+ buttons: [
220
+ {
221
+ label: 'Yes',
222
+ onClick: () =>
223
+ CustomFetch(
224
+ s.url + '/' + d[form.primaryKey],
225
+ s.method,
226
+ {},
227
+ function (result) {
228
+ if (result.error === '') {
229
+ const min = 0;
230
+ const max = 999999999;
231
+ const randomNumber = Math.floor(
232
+ Math.random() *
233
+ (max - min + 1) +
234
+ min
235
+ );
236
+
237
+ setDataReload(randomNumber);
238
+
239
+ toast.success(String(s.title));
240
+ } else {
241
+ toast.error(String(result.error));
242
+ }
243
+ }
244
+ ),
245
+ },
246
+ {
247
+ label: 'No',
248
+ onClick: () => close(),
249
+ },
250
+ ],
251
+ });
252
+ break;
253
+ }
254
+ };
255
+
256
+ const handleReload = () => {
257
+ const min = 0;
258
+ const max = 999999999;
259
+ const randomNumber = Math.floor(Math.random() * (max - min + 1) + min);
260
+
261
+ setDataReload(randomNumber);
262
+ };
263
+
264
+ const handleSort = (value) => {
265
+ setConfig((prevState) => {
266
+ const { id, dir } = value || {}; // Destructure id and dir from value (if provided)
267
+ const sortBy = id || null;
268
+ const sort = dir === 1 ? 'asc' : dir === -1 ? 'desc' : null;
269
+
270
+ return {
271
+ ...prevState,
272
+ ajaxSetting: {
273
+ ...prevState.ajaxSetting,
274
+ sortBy,
275
+ sort,
276
+ },
277
+ };
278
+ });
279
+ };
280
+
281
+ const onRowClick = useCallback(
282
+ (rowProps, event) => {
283
+ const cellElement = event.target.closest(
284
+ '.InovuaReactDataGrid__cell'
285
+ );
286
+ const columnIndex = Array.from(
287
+ cellElement.parentNode.children
288
+ ).indexOf(cellElement);
289
+
290
+ let proceed = true;
291
+
292
+ columns.forEach((a, b) => {
293
+ if (
294
+ a.id === rowProps.columns[columnIndex].id &&
295
+ a.type === 'toggle'
296
+ ) {
297
+ proceed = false;
298
+ }
299
+ });
300
+
301
+ if (proceed) {
302
+ if (
303
+ rowProps.columns[columnIndex].link &&
304
+ rowProps.columns[columnIndex].link.url
305
+ ) {
306
+ if (rowProps.columns[columnIndex].link.folder) {
307
+ window.location.href =
308
+ rowProps.columns[columnIndex].link.url +
309
+ rowProps.data[
310
+ rowProps.columns[columnIndex].link.key
311
+ ] +
312
+ '/' +
313
+ rowProps.columns[columnIndex].link.folder;
314
+ } else {
315
+ navigate(
316
+ `${rowProps.columns[columnIndex].link.url}${
317
+ rowProps.data[
318
+ rowProps.columns[columnIndex].link.key
319
+ ]
320
+ }`,
321
+ {
322
+ state: {
323
+ form: form,
324
+ },
325
+ }
326
+ );
327
+ }
328
+ }
329
+ }
330
+ },
331
+ [form]
332
+ );
333
+
334
+ const onRenderRow = useCallback((rowProps) => {
335
+ // save the original handlers to be called later
336
+ const { onClick } = rowProps;
337
+
338
+ rowProps.onClick = (event) => {
339
+ onRowClick(rowProps, event);
340
+ if (onClick) {
341
+ onClick(event);
342
+ }
343
+ };
344
+ }, []);
345
+
346
+ const sortTrigger = () => {
347
+ const url = form.url.replace('/ajax', '');
348
+ const newState = {
349
+ form: form,
350
+ };
351
+
352
+ navigate(`${url}/sort`, {
353
+ state: newState,
354
+ });
355
+ };
356
+
357
+ /** Table Hooks */
358
+ useEffect(() => {
359
+ const delayedSetDSearch = debounce(() => {
360
+ setDSearch(search);
361
+ }, 300); // Adjust the delay (in milliseconds) according to your needs
362
+
363
+ delayedSetDSearch();
364
+
365
+ return delayedSetDSearch.cancel; // Cleanup the debounce timer on unmount
366
+ }, [search, setDSearch]);
367
+
368
+ const renderSetting = (s, d) => {
369
+ let iconStyle = {};
370
+
371
+ if (s.active) {
372
+ if (
373
+ d.hasOwnProperty(s.active.id) &&
374
+ !s.active.hasOwnProperty('type') &&
375
+ d[s.active.id] === s.active.value
376
+ ) {
377
+ iconStyle = {
378
+ color: s.active.colour,
379
+ };
380
+ } else if (s.active.hasOwnProperty('type')) {
381
+ switch (s.active.type) {
382
+ case 'greater':
383
+ if (d[s.active.id] > s.active.value) {
384
+ iconStyle = {
385
+ color: s.active.colour,
386
+ };
387
+ }
388
+ break;
389
+ case 'not null':
390
+ if (d[s.active.id] !== null) {
391
+ iconStyle = {
392
+ color: s.active.colour,
393
+ };
394
+ }
395
+ break;
396
+ default:
397
+ break;
398
+ }
399
+ }
400
+ }
401
+
402
+ const getIconComponent = (IconComponent) => (
403
+ <IconComponent
404
+ data-tooltip-id="system-tooltip"
405
+ data-tooltip-content={
406
+ iconStyle && iconStyle.color ? s.active.title : s.title
407
+ }
408
+ strokeWidth={2}
409
+ size={18}
410
+ className="tdaction"
411
+ style={iconStyle}
412
+ />
413
+ );
414
+
415
+ switch (s.id) {
416
+ case 'complete':
417
+ return getIconComponent(Check);
418
+ case 'delete':
419
+ return getIconComponent(Backspace);
420
+ case 'primary':
421
+ return getIconComponent(Ribbon);
422
+ case 'ssa':
423
+ return getIconComponent(Clock);
424
+ case 'update':
425
+ return getIconComponent(Edit);
426
+ default:
427
+ return null;
428
+ }
429
+ };
430
+
431
+ const renderColumnContextMenu = useCallback((menuProps, { cellProps }) => {
432
+ const filteredItems = menuProps.items
433
+ .map((item, key) => {
434
+ if (key >= 6 && key <= 9) {
435
+ return null; // Skip items with keys 6-9 [lock columns setting]
436
+ }
437
+ return item;
438
+ })
439
+ .filter(Boolean); // Filter out any null items
440
+
441
+ menuProps.items = filteredItems;
442
+ }, []);
443
+
444
+ useEffect(() => {
445
+ const renderColumn = (column) => {
446
+ let childValue;
447
+ let date;
448
+ let filterEditor = null;
449
+ let filterEditorProps = null;
450
+ let icons = [];
451
+ let relationName;
452
+ let selectedDataSource = null;
453
+ let stage;
454
+ let style;
455
+ let value;
456
+
457
+ const commonProps = {
458
+ header: column.label,
459
+ defaultFlex: 1,
460
+ link: column.link ? column.link : {},
461
+ minWidth:
462
+ column.minWidth && column.minWidth > 0
463
+ ? column.minWidth
464
+ : undefined,
465
+ maxWidth:
466
+ column.maxWidth && column.maxWidth > 0
467
+ ? column.maxWidth
468
+ : undefined,
469
+ };
470
+
471
+ switch (column.type) {
472
+ case 'address':
473
+ return {
474
+ ...commonProps,
475
+ name: `${column.type}.${column.id}`,
476
+ render: ({ data }) => {
477
+ if (data.address1) {
478
+ value += `${data.address1} `;
479
+ }
480
+
481
+ if (data.address2) {
482
+ value += `${data.address2} `;
483
+ }
484
+
485
+ if (data.suburb) {
486
+ value += `${data.suburb} `;
487
+ }
488
+
489
+ if (data.postcode) {
490
+ value += `${data.postcode} `;
491
+ }
492
+ },
493
+ };
494
+ case 'age':
495
+ return {
496
+ ...commonProps,
497
+ name: `${column.type}.${column.id}`,
498
+ render: ({ data }) => {
499
+ value = column.id.reduce((acc, id) => {
500
+ if (acc === '') {
501
+ return data[id];
502
+ } else {
503
+ return acc[id];
504
+ }
505
+ }, '');
506
+
507
+ if (value !== '' && value !== null) {
508
+ date = moment(value);
509
+
510
+ return (
511
+ <span>
512
+ {moment().diff(
513
+ date,
514
+ column.duration
515
+ ? column.duration
516
+ : 'years'
517
+ )}
518
+ </span>
519
+ );
520
+ } else {
521
+ return null;
522
+ }
523
+ },
524
+ };
525
+ case 'arrayCount':
526
+ return {
527
+ ...commonProps,
528
+ name: `${column.type}.${column.id}`,
529
+ sortable: false,
530
+ render: ({ data }) => {
531
+ if (data && data[column.id]) {
532
+ return data[column.id].length;
533
+ } else {
534
+ return null;
535
+ }
536
+ },
537
+ };
538
+ case 'coding':
539
+ return {
540
+ ...commonProps,
541
+ name: 'audits.name',
542
+ sortable: false,
543
+ render: ({ data }) => {
544
+ if (data) {
545
+ return handleCoding(column, data);
546
+ } else {
547
+ return null;
548
+ }
549
+ },
550
+ };
551
+ case 'created_by':
552
+ return {
553
+ ...commonProps,
554
+ name: 'audits.name',
555
+ sortable: false,
556
+ render: ({ data }) => {
557
+ if (
558
+ data.audits[0] &&
559
+ data.audits[0].user &&
560
+ data.audits[0].user.name
561
+ ) {
562
+ value = data.audits[0].user.name;
563
+
564
+ return <span>{value}</span>;
565
+ } else {
566
+ return null;
567
+ }
568
+ },
569
+ };
570
+ case 'currency':
571
+ return {
572
+ ...commonProps,
573
+ name: column.id,
574
+ render: ({ data }) => {
575
+ if (data) {
576
+ data = numeral(data[column.id]).format(
577
+ '$0,0.00'
578
+ );
579
+
580
+ return <span>{data}</span>;
581
+ } else {
582
+ return null;
583
+ }
584
+ },
585
+ };
586
+ case 'date':
587
+ if (column.filter && column.filter.type) {
588
+ filterEditor = DateFilter;
589
+ filterEditorProps = (props, { index }) => {
590
+ return {
591
+ dateFormat: 'DD-MM-YYYY',
592
+ placeholder: 'All Dates',
593
+ };
594
+ };
595
+ } else {
596
+ filterEditor = null;
597
+ filterEditorProps = null;
598
+ }
599
+
600
+ return {
601
+ ...commonProps,
602
+ name: column.id,
603
+ filterEditor: filterEditor,
604
+ filterEditorProps: filterEditorProps,
605
+ render: ({ data }) => {
606
+ if (
607
+ data &&
608
+ data[column.id] &&
609
+ moment(data[column.id]).isValid() &&
610
+ moment(data[column.id]).format('YYYY-MM-DD') !==
611
+ '1970-01-01'
612
+ ) {
613
+ const value = moment(data[column.id]).format(
614
+ column.format || 'DD-MM-YYYY'
615
+ );
616
+ style = {};
617
+
618
+ if (
619
+ column.active &&
620
+ column.active.id &&
621
+ column.active.value === 'expired'
622
+ ) {
623
+ if (
624
+ data[column.active.id] &&
625
+ moment(data[column.active.id]).isBefore(
626
+ moment()
627
+ )
628
+ ) {
629
+ style = {
630
+ color: column.active.colour,
631
+ };
632
+ }
633
+ }
634
+
635
+ return <span style={style}>{value}</span>;
636
+ } else {
637
+ return null;
638
+ }
639
+ },
640
+ };
641
+ case 'datetime':
642
+ if (column.filter && column.filter.type) {
643
+ filterEditor = DateFilter;
644
+ filterEditorProps = (props, { index }) => {
645
+ return {
646
+ dateFormat: 'DD-MM-YYYY',
647
+ placeholder: 'All Dates',
648
+ };
649
+ };
650
+ } else {
651
+ filterEditor = null;
652
+ filterEditorProps = null;
653
+ }
654
+
655
+ return {
656
+ ...commonProps,
657
+ name: column.id,
658
+ filterEditor: filterEditor,
659
+ filterEditorProps: filterEditorProps,
660
+ render: ({ data }) => {
661
+ if (
662
+ data &&
663
+ data[column.id] &&
664
+ moment(data[column.id]).isValid() &&
665
+ moment(data[column.id]).format('YYYY-MM-DD') !==
666
+ '1970-01-01'
667
+ ) {
668
+ data = moment(data[column.id]).format(
669
+ column.format
670
+ ? column.format
671
+ : 'DD-MM-YYYY hh:mm A'
672
+ );
673
+
674
+ return <span>{data}</span>;
675
+ } else {
676
+ return null;
677
+ }
678
+ },
679
+ };
680
+ case 'file':
681
+ return {
682
+ ...commonProps,
683
+ name: column.id,
684
+ sortable: false,
685
+ render: ({ data }) => {
686
+ if (data) {
687
+ return (
688
+ <span>
689
+ <CloudDownload
690
+ data-tooltip-id="system-tooltip"
691
+ data-tooltip-content="Download File"
692
+ strokeWidth={2}
693
+ size={18}
694
+ className="tdaction"
695
+ />
696
+ </span>
697
+ );
698
+ } else {
699
+ return null;
700
+ }
701
+ },
702
+ };
703
+ case 'icons':
704
+ return {
705
+ ...commonProps,
706
+ name: column.id,
707
+ sortable: false,
708
+ render: ({ data }) => {
709
+ icons = [];
710
+
711
+ if (column.icons && column.icons.length > 0) {
712
+ column.icons.forEach((icon) => {
713
+ icons.push(
714
+ <img
715
+ src={icon.url}
716
+ alt={icon.name}
717
+ data-tooltip-id="system-tooltip"
718
+ data-tooltip-content={icon.name}
719
+ />
720
+ );
721
+ });
722
+ }
723
+
724
+ if (data) {
725
+ return <span>{icons}</span>;
726
+ } else {
727
+ return null;
728
+ }
729
+ },
730
+ };
731
+ case 'image':
732
+ return {
733
+ ...commonProps,
734
+ name: column.id,
735
+ render: ({ data }) => {
736
+ if (data && data[column.id]) {
737
+ const fileUrl =
738
+ data[column.id][0]?.file_url ||
739
+ data[column.id]?.file_url;
740
+
741
+ if (fileUrl) {
742
+ return (
743
+ <span>
744
+ {parse(
745
+ `<img width="150" src="${fileUrl}" />`
746
+ )}
747
+ </span>
748
+ );
749
+ }
750
+ }
751
+
752
+ return null;
753
+ },
754
+ };
755
+ case 'json':
756
+ return {
757
+ ...commonProps,
758
+ name: `${column.id}-${column.jsonData}`,
759
+ render: ({ data }) => {
760
+ if (
761
+ data &&
762
+ data[column.id] &&
763
+ data[column.id][column.jsonData]
764
+ ) {
765
+ data = data[column.id][column.jsonData];
766
+
767
+ return <span>{data}</span>;
768
+ } else {
769
+ return null;
770
+ }
771
+ },
772
+ };
773
+ case 'number':
774
+ return {
775
+ ...commonProps,
776
+ name: column.id,
777
+ type: 'number',
778
+ };
779
+ case 'option':
780
+ selectedDataSource = filterDataSource.reduce((acc, fds) => {
781
+ if (fds.id === column.id) {
782
+ return fds.dataset;
783
+ }
784
+ return acc;
785
+ }, null);
786
+
787
+ if (
788
+ column.filter &&
789
+ column.filter.type &&
790
+ column.filter.type === 'select'
791
+ ) {
792
+ filterEditor = SelectFilter;
793
+ filterEditorProps = {
794
+ placeholder: column.filter.placeholder
795
+ ? column.filter.placeholder
796
+ : 'All Options',
797
+ dataSource: selectedDataSource,
798
+ };
799
+ } else {
800
+ filterEditor = null;
801
+ filterEditorProps = null;
802
+ }
803
+
804
+ return {
805
+ ...commonProps,
806
+ name: column.id,
807
+ filterEditor: filterEditor,
808
+ filterEditorProps: filterEditorProps,
809
+ render: ({ data }) => {
810
+ if (
811
+ data &&
812
+ column.options &&
813
+ column.options[data[column.id]]
814
+ ) {
815
+ data = column.options[data[column.id]];
816
+
817
+ return <span>{data}</span>;
818
+ } else {
819
+ return null;
820
+ }
821
+ },
822
+ };
823
+ case 'placeholder':
824
+ return {
825
+ ...commonProps,
826
+ name: column.id,
827
+ sortable: false,
828
+ render: ({ data }) => {
829
+ if (data) {
830
+ return <span>{column.placeholder}</span>;
831
+ } else {
832
+ return null;
833
+ }
834
+ },
835
+ };
836
+ case 'relation':
837
+ relationName = column.id.reduce(
838
+ (acc, id) => acc + `${id}.`,
839
+ ''
840
+ );
841
+ relationName += column.nameFrom;
842
+
843
+ selectedDataSource = filterDataSource.reduce((acc, fds) => {
844
+ if (fds.id === relationName) {
845
+ return fds.dataset;
846
+ }
847
+ return acc;
848
+ }, null);
849
+
850
+ if (
851
+ column.filter &&
852
+ column.filter.type &&
853
+ column.filter.type === 'select'
854
+ ) {
855
+ filterEditor = SelectFilter;
856
+ filterEditorProps = {
857
+ placeholder: column.filter.placeholder
858
+ ? column.filter.placeholder
859
+ : 'All Options',
860
+ dataSource: selectedDataSource,
861
+ };
862
+ } else {
863
+ filterEditor = null;
864
+ filterEditorProps = null;
865
+ }
866
+
867
+ return {
868
+ ...commonProps,
869
+ name: relationName,
870
+ sortable: false,
871
+ filterEditor: filterEditor,
872
+ filterEditorProps: filterEditorProps,
873
+ render: ({ data }) => {
874
+ value = column.id.reduce((acc, id) => {
875
+ if (acc === '') {
876
+ return data[id];
877
+ } else {
878
+ if (acc && acc[id]) {
879
+ return acc[id];
880
+ } else {
881
+ return '';
882
+ }
883
+ }
884
+ }, '');
885
+
886
+ if (value) {
887
+ if (Array.isArray(column.nameFrom)) {
888
+ value = column.nameFrom
889
+ .map((nf) => value[nf])
890
+ .join(' ');
891
+ } else {
892
+ value = value[column.nameFrom];
893
+ }
894
+
895
+ if (
896
+ column.placeholder &&
897
+ column.placeholder !== ''
898
+ ) {
899
+ return <span>{column.placeholder}</span>;
900
+ } else {
901
+ return <span>{value}</span>;
902
+ }
903
+ } else {
904
+ return null;
905
+ }
906
+ },
907
+ };
908
+ case 'relationArray':
909
+ relationName =
910
+ column.id.reduce((acc, id) => acc + `${id}.`, '') +
911
+ column.nameFrom;
912
+
913
+ selectedDataSource = filterDataSource.reduce((acc, fds) => {
914
+ if (fds.id === relationName) {
915
+ return fds.dataset;
916
+ }
917
+ return acc;
918
+ }, null);
919
+
920
+ if (
921
+ column.filter &&
922
+ column.filter.type &&
923
+ column.filter.type === 'select'
924
+ ) {
925
+ filterEditor = SelectFilter;
926
+ filterEditorProps = {
927
+ placeholder: column.filter.placeholder
928
+ ? column.filter.placeholder
929
+ : 'All Options',
930
+ dataSource: selectedDataSource,
931
+ };
932
+ } else {
933
+ filterEditor = null;
934
+ filterEditorProps = null;
935
+ }
936
+
937
+ return {
938
+ ...commonProps,
939
+ name: relationName,
940
+ sortable: false,
941
+ filterEditor: filterEditor,
942
+ filterEditorProps: filterEditorProps,
943
+ render: ({ data }) => {
944
+ const relationValue = column.id.reduce(
945
+ (acc, id) =>
946
+ acc === ''
947
+ ? data[id]
948
+ : acc && acc[id]
949
+ ? acc[id]
950
+ : '',
951
+ ''
952
+ );
953
+
954
+ if (relationValue && Array.isArray(relationValue)) {
955
+ const nameProperties = Array.isArray(
956
+ column.nameFrom
957
+ )
958
+ ? column.nameFrom
959
+ : [column.nameFrom];
960
+
961
+ const values = relationValue
962
+ .map((rv) => {
963
+ if (
964
+ column.childId &&
965
+ Array.isArray(column.childId)
966
+ ) {
967
+ childValue = rv;
968
+
969
+ column.childId.forEach((a) => {
970
+ if (childValue[a]) {
971
+ childValue = childValue[a];
972
+ }
973
+ });
974
+
975
+ if (childValue) {
976
+ const propertyValues =
977
+ nameProperties
978
+ .map(
979
+ (prop) =>
980
+ childValue[prop]
981
+ )
982
+ .filter(
983
+ (value) =>
984
+ value !==
985
+ undefined &&
986
+ value !== null
987
+ );
988
+ return propertyValues.join(' ');
989
+ }
990
+ } else {
991
+ const propertyValues =
992
+ nameProperties
993
+ .map((prop) => rv[prop])
994
+ .filter(
995
+ (value) =>
996
+ value !==
997
+ undefined &&
998
+ value !== null
999
+ );
1000
+ return propertyValues.join(' ');
1001
+ }
1002
+ })
1003
+ .filter((value) => value !== '');
1004
+
1005
+ if (values.length > 0) {
1006
+ let result = '';
1007
+
1008
+ if (
1009
+ column.relation?.id &&
1010
+ column.relation?.key
1011
+ ) {
1012
+ const relationValue =
1013
+ column.relation.key.reduce(
1014
+ (acc, id) =>
1015
+ acc === ''
1016
+ ? data[id]
1017
+ : acc && acc[id]
1018
+ ? acc[id]
1019
+ : '',
1020
+ ''
1021
+ );
1022
+
1023
+ result = `${
1024
+ relationValue[column.relation.id]
1025
+ }<br />`;
1026
+ }
1027
+
1028
+ if (
1029
+ column.where &&
1030
+ column.where.id &&
1031
+ column.where.value
1032
+ ) {
1033
+ if (
1034
+ data[column.where.id] ===
1035
+ column.where.value
1036
+ ) {
1037
+ result += values.join('<br />');
1038
+ }
1039
+ } else {
1040
+ result += values.join('<br />');
1041
+ }
1042
+
1043
+ return <span>{parse(result)}</span>;
1044
+ }
1045
+ }
1046
+
1047
+ return null;
1048
+ },
1049
+ };
1050
+ case 'richtext':
1051
+ return {
1052
+ ...commonProps,
1053
+ name: column.id,
1054
+ render: ({ data }) => {
1055
+ if (data && data[column.id]) {
1056
+ return <span>{parse(data[column.id])}</span>;
1057
+ } else {
1058
+ return null;
1059
+ }
1060
+ },
1061
+ };
1062
+ case 'stage':
1063
+ return {
1064
+ ...commonProps,
1065
+ name: column.id,
1066
+ sortable: false,
1067
+ render: ({ data }) => {
1068
+ stage = '';
1069
+
1070
+ column.keyIds.forEach((a, b) => {
1071
+ if (data[a] === 1) {
1072
+ stage = column.valueIds[b];
1073
+ }
1074
+ });
1075
+
1076
+ return <span>{stage}</span>;
1077
+ },
1078
+ };
1079
+ case 'time':
1080
+ return {
1081
+ ...commonProps,
1082
+ name: column.id,
1083
+ render: ({ data }) => {
1084
+ if (
1085
+ data &&
1086
+ data[column.id] &&
1087
+ moment(data[column.id]).isValid() &&
1088
+ moment(data[column.id]).format('YYYY-MM-DD') !==
1089
+ '1970-01-01'
1090
+ ) {
1091
+ data = moment(data[column.id]).format(
1092
+ column.format ? column.format : 'hh:mm A'
1093
+ );
1094
+
1095
+ return <span>{data}</span>;
1096
+ } else {
1097
+ return null;
1098
+ }
1099
+ },
1100
+ };
1101
+ case 'toggle':
1102
+ return {
1103
+ ...commonProps,
1104
+ name: column.id,
1105
+ render: ({ data }) => {
1106
+ return (
1107
+ <Toggle
1108
+ name={column.id}
1109
+ checked={
1110
+ data[column.id] === 1 ? true : false
1111
+ }
1112
+ onChange={() => {
1113
+ CustomFetch(
1114
+ `${column.url}/${data.id}`,
1115
+ 'POST',
1116
+ {
1117
+ [column.id]:
1118
+ data[column.id] === 1
1119
+ ? 0
1120
+ : 1,
1121
+ },
1122
+ (res) => {
1123
+ if (res.error === '') {
1124
+ handleReload();
1125
+ } else {
1126
+ toast.error(res.error);
1127
+ }
1128
+ }
1129
+ );
1130
+ }}
1131
+ />
1132
+ );
1133
+ },
1134
+ };
1135
+ case 'url':
1136
+ return {
1137
+ ...commonProps,
1138
+ name: column.id,
1139
+ render: ({ data }) => {
1140
+ if (data && data[column.id]) {
1141
+ return (
1142
+ <span>
1143
+ <a
1144
+ href={data[column.id]}
1145
+ target="_blank"
1146
+ >
1147
+ Link
1148
+ </a>
1149
+ </span>
1150
+ );
1151
+ } else {
1152
+ return null;
1153
+ }
1154
+ },
1155
+ };
1156
+ default:
1157
+ selectedDataSource = filterDataSource.reduce((acc, fds) => {
1158
+ if (fds.id === column.id) {
1159
+ return fds.dataset;
1160
+ }
1161
+ return acc;
1162
+ }, null);
1163
+
1164
+ if (column.filter && column.filter.type) {
1165
+ switch (column.filter.type) {
1166
+ case 'select':
1167
+ filterEditor = SelectFilter;
1168
+ filterEditorProps = {
1169
+ placeholder: column.filter.placeholder
1170
+ ? column.filter.placeholder
1171
+ : 'All Options',
1172
+ dataSource: selectedDataSource,
1173
+ };
1174
+ break;
1175
+ default:
1176
+ filterEditor = null;
1177
+ filterEditorProps = null;
1178
+ break;
1179
+ }
1180
+ } else {
1181
+ filterEditor = null;
1182
+ filterEditorProps = null;
1183
+ }
1184
+
1185
+ return {
1186
+ ...commonProps,
1187
+ name: column.id,
1188
+ filterEditor: filterEditor,
1189
+ filterEditorProps: filterEditorProps,
1190
+ };
1191
+ }
1192
+ };
1193
+
1194
+ const newColumns = columns.map(renderColumn);
1195
+
1196
+ if (settings.length > 0) {
1197
+ newColumns.push({
1198
+ name: 'setting',
1199
+ header: 'Action',
1200
+ defaultWidth: 100,
1201
+ textAlign: 'center',
1202
+ render: ({ data }) => {
1203
+ return (
1204
+ <div className="tdactions">
1205
+ {settings.map((setting) => (
1206
+ <span
1207
+ key={`setting-${setting.id}`}
1208
+ onClick={(e) => {
1209
+ e.preventDefault();
1210
+ e.stopPropagation();
1211
+ handleSettingClick(setting, data);
1212
+ }}
1213
+ >
1214
+ {renderSetting(setting, data)}
1215
+ </span>
1216
+ ))}
1217
+ </div>
1218
+ );
1219
+ },
1220
+ });
1221
+ }
1222
+
1223
+ setGridColumns(newColumns);
1224
+
1225
+ const newFilterValue = columns
1226
+ .filter((column) => column.filter && column.filter.type) // Only consider columns with a filter type
1227
+ .map((column) => {
1228
+ // Map these filtered columns to a new object array
1229
+ const filterName = Array.isArray(column.id)
1230
+ ? column.id.reduce((acc, id) => acc + `${id}.`, '') +
1231
+ column.nameFrom
1232
+ : column.id;
1233
+
1234
+ return {
1235
+ key: column.filter.key ? column.filter.key : null,
1236
+ name: filterName,
1237
+ operator: column.filter.operator,
1238
+ type: column.filter.type,
1239
+ value: column.filter.value ? column.filter.value : '',
1240
+ };
1241
+ });
1242
+
1243
+ setFilterValue(newFilterValue);
1244
+ }, [columns, filterDataSource]);
1245
+
1246
+ useEffect(() => {
1247
+ if (setFilterData) {
1248
+ setFilterData(filterValue);
1249
+ }
1250
+ }, [filterValue]);
1251
+
1252
+ useEffect(() => {
1253
+ columns.forEach((column) => {
1254
+ if (column.filter && column.filter.url) {
1255
+ CustomFetch(
1256
+ column.filter.url,
1257
+ 'POST',
1258
+ column.filter.where ? { where: column.filter.where } : {},
1259
+ (res) => {
1260
+ const filterName = Array.isArray(column.id)
1261
+ ? column.id.reduce(
1262
+ (acc, id) => acc + `${id}.`,
1263
+ ''
1264
+ ) + column.nameFrom
1265
+ : column.id;
1266
+
1267
+ const filterIndex = filterDataSource.findIndex(
1268
+ (filter) => filter.id === filterName
1269
+ );
1270
+
1271
+ if (filterIndex >= 0) {
1272
+ const updatedFilter = {
1273
+ ...filterDataSource[filterIndex],
1274
+ dataset: res.data,
1275
+ };
1276
+ const updatedDataSource = [
1277
+ ...filterDataSource.slice(0, filterIndex),
1278
+ updatedFilter,
1279
+ ...filterDataSource.slice(filterIndex + 1),
1280
+ ];
1281
+ setFilterDataSource(updatedDataSource);
1282
+ } else {
1283
+ const newFilter = {
1284
+ id: filterName,
1285
+ dataset: res.data,
1286
+ };
1287
+ setFilterDataSource((prevState) => [
1288
+ ...prevState,
1289
+ newFilter,
1290
+ ]);
1291
+ }
1292
+ }
1293
+ );
1294
+ } else if (column.filter && column.filter.options) {
1295
+ const filterName = Array.isArray(column.id)
1296
+ ? column.id.reduce((acc, id) => acc + `${id}.`, '') +
1297
+ column.nameFrom
1298
+ : column.id;
1299
+
1300
+ const newFilter = {
1301
+ id: filterName,
1302
+ dataset: column.filter.options,
1303
+ };
1304
+
1305
+ setFilterDataSource((prevState) => [...prevState, newFilter]);
1306
+ }
1307
+ });
1308
+ }, []);
1309
+
1310
+ // Data Grid Styling
1311
+ const [windowHeight, setWindowHeight] = useState(window.innerHeight);
1312
+ const [dataCount, setDataCount] = useState(0);
1313
+ const [gridStyle, setGridStyle] = useState({
1314
+ minHeight:
1315
+ gridHeight && gridHeight > 0
1316
+ ? gridHeight
1317
+ : dataCount > 5
1318
+ ? dataCount > 8
1319
+ ? windowHeight * 0.7 > 550
1320
+ ? windowHeight * 0.7
1321
+ : 550
1322
+ : 450
1323
+ : 400,
1324
+ boxShadow: 'none',
1325
+ });
1326
+ const headerProps = {
1327
+ style: style ? style : {},
1328
+ };
1329
+
1330
+ useEffect(() => {
1331
+ setGridStyle((prevState) => ({
1332
+ ...prevState,
1333
+ minHeight:
1334
+ gridHeight && gridHeight > 0
1335
+ ? gridHeight
1336
+ : dataCount > 5
1337
+ ? dataCount > 8
1338
+ ? windowHeight * 0.7 > 550
1339
+ ? windowHeight * 0.7
1340
+ : 550
1341
+ : 450
1342
+ : 400,
1343
+ }));
1344
+
1345
+ let dgHeight =
1346
+ gridHeight && gridHeight > 0
1347
+ ? gridHeight
1348
+ : dataCount > 5
1349
+ ? dataCount > 8
1350
+ ? windowHeight * 0.7 > 550
1351
+ ? windowHeight * 0.7
1352
+ : 550
1353
+ : 450
1354
+ : 400;
1355
+
1356
+ let rowCount = Math.floor((dgHeight - 100) / 40);
1357
+ setLimit(rowCount);
1358
+ }, [dataCount]);
1359
+
1360
+ useEffect(() => {
1361
+ const handleResize = () => {
1362
+ setWindowHeight(window.innerHeight);
1363
+ };
1364
+
1365
+ window.addEventListener('resize', handleResize);
1366
+
1367
+ // Clean up the event listener
1368
+ return () => {
1369
+ window.removeEventListener('resize', handleResize);
1370
+ };
1371
+ }, []);
1372
+
1373
+ return (
1374
+ <>
1375
+ <div className="filterInput--alt">
1376
+ <div className="icon-search">
1377
+ <Search strokeWidth={2} size={18} />
1378
+ </div>
1379
+ <input
1380
+ type="text"
1381
+ placeholder="Search"
1382
+ value={search}
1383
+ onChange={handleChangeSearch}
1384
+ />
1385
+ </div>
1386
+ <div className="filterAction--alt">
1387
+ {form.sort && form.sort.title && (
1388
+ <button className="btn" onClick={sortTrigger}>
1389
+ <div className="icon-plus"></div> Sort Order
1390
+ </button>
1391
+ )}
1392
+
1393
+ {form.create && form.create.title && (
1394
+ <button
1395
+ className="btn"
1396
+ onClick={() => {
1397
+ let _url = form.url.replace('/ajax', '');
1398
+
1399
+ navigate(_url + '/create', {
1400
+ state: {
1401
+ form: formData,
1402
+ },
1403
+ });
1404
+ }}
1405
+ >
1406
+ <div className="icon-plus"></div> Create
1407
+ </button>
1408
+ )}
1409
+ </div>
1410
+ <ReactDataGrid
1411
+ columns={gridColumns}
1412
+ dataSource={data}
1413
+ filterValue={filterValue}
1414
+ enableColumnAutosize={false}
1415
+ enableColumnFilterContextMenu={false}
1416
+ enableSelection={false}
1417
+ headerProps={headerProps}
1418
+ idProperty={`visns-datagrid-${ajaxSetting.url.replace(
1419
+ /\//g,
1420
+ '-'
1421
+ )}`}
1422
+ limit={limit}
1423
+ minRowHeight={40}
1424
+ onFilterValueChange={setFilterValue}
1425
+ onLimitChange={setLimit}
1426
+ onSortInfoChange={handleSort}
1427
+ onRenderRow={onRenderRow}
1428
+ pagination
1429
+ renderColumnContextMenu={renderColumnContextMenu}
1430
+ rowHeight={null}
1431
+ showZebraRows={true}
1432
+ sortInfo={
1433
+ ajaxSetting.sortBy && ajaxSetting.sort
1434
+ ? {
1435
+ name: ajaxSetting.sortBy,
1436
+ dir: ajaxSetting.sort === 'asc' ? 1 : -1,
1437
+ }
1438
+ : null
1439
+ }
1440
+ style={gridStyle}
1441
+ />
1442
+ <Popup
1443
+ open={modalShow}
1444
+ onClose={modalClose}
1445
+ closeOnDocumentClick={false}
1446
+ >
1447
+ <Form
1448
+ closeModal={modalClose}
1449
+ fetchTable={handleReload}
1450
+ formSettings={formData}
1451
+ formType={formType}
1452
+ updateForm={setFormData}
1453
+ columnId={formId}
1454
+ childDropdownCallback={childDropdownCallback}
1455
+ />
1456
+ </Popup>
1457
+ </>
1458
+ );
1459
+ };
1460
+
1461
+ export default DataGrid;