@visns-studio/visns-components 4.7.0 → 4.7.2

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 (110) hide show
  1. package/dist/104e5636d8ddb791614c.woff2 +0 -0
  2. package/dist/11fe6a83d647de5daf95.woff +0 -0
  3. package/dist/141e2a8c7836495afe2a.woff +0 -0
  4. package/dist/2ba5877f7079830b5383.woff +0 -0
  5. package/dist/2d6836f45b2037be41f3.woff +0 -0
  6. package/dist/399.0a0f3e0d21be1057d599.css +8 -0
  7. package/dist/399.b8f57fa3f8c0c10119e4.js +1 -0
  8. package/dist/47d566c3b1293dfd9d77.woff +0 -0
  9. package/dist/6282a13cbba671a71913.woff2 +0 -0
  10. package/dist/78266f551031aa9db127.woff +0 -0
  11. package/dist/7b7da89f1e3fdcbfe36c.woff2 +0 -0
  12. package/dist/7e78e8338af7efeda712.woff2 +0 -0
  13. package/dist/7fa387951673abf164b1.woff2 +0 -0
  14. package/dist/819d59862c2d0640aad8.woff +0 -0
  15. package/dist/b615e1a6c838ea059a56.woff +0 -0
  16. package/dist/b9b1aa739c660c4ce67c.woff2 +0 -0
  17. package/dist/c5f3640b11df9414facb.woff +0 -0
  18. package/dist/da26d162ff5af71d6590.woff2 +0 -0
  19. package/dist/dd5b2912dbf896310865.woff2 +0 -0
  20. package/dist/f282b331272463c1aa6c.woff2 +0 -0
  21. package/dist/index.css +2902 -0
  22. package/dist/index.js +2 -0
  23. package/dist/index.js.LICENSE.txt +150 -0
  24. package/dist/main.83b033670d64419bb497.css +1 -0
  25. package/dist/main.b1723d17cd2d3513ab62.js +1 -0
  26. package/dist/report.html +39 -0
  27. package/dist/runtime.33c276593b23f8035b8d.js +1 -0
  28. package/package.json +26 -6
  29. package/.idea/codeStyles/Project.xml +0 -50
  30. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  31. package/.idea/deployment.xml +0 -4
  32. package/.idea/modules.xml +0 -8
  33. package/.idea/php.xml +0 -19
  34. package/.idea/vcs.xml +0 -6
  35. package/.idea/visns-components.iml +0 -8
  36. package/.prettierrc.json +0 -7
  37. package/.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs +0 -541
  38. package/.yarn/releases/yarn-3.6.1.cjs +0 -874
  39. package/.yarnrc.yml +0 -7
  40. package/components/cms/DataGrid.jsx +0 -1461
  41. package/components/cms/DropZone.jsx +0 -349
  42. package/components/cms/Field.jsx +0 -802
  43. package/components/cms/Form.jsx +0 -476
  44. package/components/cms/generic/CmsDetail.jsx +0 -36
  45. package/components/cms/generic/CmsIndex.jsx +0 -73
  46. package/components/cms/generic/CmsSort.jsx +0 -125
  47. package/components/cms/sorting/Item.jsx +0 -115
  48. package/components/cms/sorting/List.jsx +0 -30
  49. package/components/crm/AsyncSelect.jsx +0 -125
  50. package/components/crm/Autocomplete.jsx +0 -174
  51. package/components/crm/Breadcrumb.jsx +0 -52
  52. package/components/crm/Call.jsx +0 -220
  53. package/components/crm/DataGrid.jsx +0 -2701
  54. package/components/crm/Download.jsx +0 -101
  55. package/components/crm/Fetch.jsx +0 -119
  56. package/components/crm/Field.jsx +0 -1557
  57. package/components/crm/Form.jsx +0 -1409
  58. package/components/crm/Loader.jsx +0 -29
  59. package/components/crm/MultiSelect.jsx +0 -78
  60. package/components/crm/Navigation.jsx +0 -619
  61. package/components/crm/Notification.jsx +0 -197
  62. package/components/crm/QrCode.jsx +0 -83
  63. package/components/crm/Select.jsx +0 -58
  64. package/components/crm/SelectList.jsx +0 -21
  65. package/components/crm/TableFilter.jsx +0 -198
  66. package/components/crm/auth/Login.jsx +0 -223
  67. package/components/crm/auth/Profile.jsx +0 -280
  68. package/components/crm/auth/Reset.jsx +0 -111
  69. package/components/crm/auth/Verify.jsx +0 -174
  70. package/components/crm/auth/styles/Login.module.css +0 -243
  71. package/components/crm/auth/styles/Profile.module.css +0 -222
  72. package/components/crm/auth/styles/Reset.module.css +0 -216
  73. package/components/crm/auth/styles/Verify.module.css +0 -216
  74. package/components/crm/generic/AuditLog.jsx +0 -108
  75. package/components/crm/generic/AuditLogs.jsx +0 -115
  76. package/components/crm/generic/GenericAuth.jsx +0 -166
  77. package/components/crm/generic/GenericDashboard.jsx +0 -42
  78. package/components/crm/generic/GenericDetail.jsx +0 -1499
  79. package/components/crm/generic/GenericDynamic.jsx +0 -915
  80. package/components/crm/generic/GenericFormBuilder.jsx +0 -1765
  81. package/components/crm/generic/GenericIndex.jsx +0 -376
  82. package/components/crm/generic/GenericMain.jsx +0 -129
  83. package/components/crm/generic/GenericSort.jsx +0 -188
  84. package/components/crm/generic/NotificationList.jsx +0 -64
  85. package/components/crm/generic/styles/AuditLog.module.css +0 -147
  86. package/components/crm/generic/styles/AuditLogs.module.css +0 -92
  87. package/components/crm/generic/styles/GenericDetail.module.css +0 -634
  88. package/components/crm/generic/styles/GenericDynamic.module.css +0 -932
  89. package/components/crm/generic/styles/GenericFormBuilder.module.css +0 -944
  90. package/components/crm/generic/styles/GenericIndex.module.css +0 -247
  91. package/components/crm/generic/styles/GenericMain.module.css +0 -91
  92. package/components/crm/generic/styles/GenericSort.module.css +0 -123
  93. package/components/crm/generic/styles/NotificationList.module.css +0 -67
  94. package/components/crm/sorting/Item.jsx +0 -117
  95. package/components/crm/sorting/List.jsx +0 -32
  96. package/components/crm/sorting/styles/Item.module.css +0 -68
  97. package/components/crm/sorting/styles/List.module.css +0 -68
  98. package/components/crm/styles/AsyncSelect.module.css +0 -8
  99. package/components/crm/styles/Autocomplete.module.css +0 -44
  100. package/components/crm/styles/DataGrid.module.css +0 -210
  101. package/components/crm/styles/Field.module.css +0 -311
  102. package/components/crm/styles/Form.module.css +0 -499
  103. package/components/crm/styles/Loader.module.css +0 -94
  104. package/components/crm/styles/MultiSelect.module.css +0 -8
  105. package/components/crm/styles/Navigation.module.css +0 -978
  106. package/components/crm/styles/Notification.module.css +0 -147
  107. package/components/crm/styles/QrCode.module.css +0 -87
  108. package/components/crm/styles/TableFilter.module.css +0 -52
  109. package/components/styles/global.css +0 -73
  110. package/index.js +0 -86
@@ -1,2701 +0,0 @@
1
- import '../styles/global.css';
2
-
3
- import React, {
4
- forwardRef,
5
- useCallback,
6
- useEffect,
7
- useImperativeHandle,
8
- useRef,
9
- useState,
10
- } from 'react';
11
- import { useNavigate } from 'react-router-dom';
12
- import axios from 'axios';
13
- import debounce from 'lodash.debounce';
14
- import moment from 'moment';
15
- import numeral from 'numeral';
16
- import Popup from 'reactjs-popup';
17
- import parse from 'html-react-parser';
18
- import { saveAs } from 'file-saver';
19
- import NumberFilter from '@inovua/reactdatagrid-community/NumberFilter';
20
- import SelectFilter from '@inovua/reactdatagrid-community/SelectFilter';
21
- import DateFilter from '@inovua/reactdatagrid-community/DateFilter';
22
- import ReactDataGrid from '@inovua/reactdatagrid-community';
23
- // import NumberFilter from '@visns-studio/visns-datagrid-enterprise/NumberFilter';
24
- // import SelectFilter from '@visns-studio/visns-datagrid-enterprise/SelectFilter';
25
- // import DateFilter from '@visns-studio/visns-datagrid-enterprise/DateFilter';
26
- // import ReactDataGrid from '@visns-studio/visns-datagrid-enterprise';
27
- import { Gallery } from 'react-grid-gallery';
28
- import { confirmAlert } from 'react-confirm-alert';
29
- import { toast } from 'react-toastify';
30
- import {
31
- Alarm,
32
- ArrowCounterClockwise,
33
- Backspace,
34
- Check,
35
- CircleCheck,
36
- CircleX,
37
- Clock,
38
- CloudDownload,
39
- Copy,
40
- Edit,
41
- Envelope,
42
- Folder,
43
- Image,
44
- Inbox,
45
- LinkOut,
46
- LockOn,
47
- Network,
48
- Ribbon,
49
- Search,
50
- ShippingBoxV1,
51
- SoundOn,
52
- TriangleAlert,
53
- } from 'akar-icons';
54
- import styles from './styles/DataGrid.module.css';
55
-
56
- import '@inovua/reactdatagrid-community/index.css';
57
- import 'react-confirm-alert/src/react-confirm-alert.css';
58
-
59
- import CustomFetch from './Fetch';
60
- import Download from './Download';
61
- import Form from './Form';
62
- import _ from 'lodash';
63
-
64
- const loadData = async (
65
- { skip, limit, sortInfo, filterValue },
66
- search,
67
- ajaxSetting
68
- ) => {
69
- const url = ajaxSetting.url;
70
- const page = Math.floor(skip / limit) + 1;
71
- const params = { page, sortInfo, take: limit, search: search, where: [] };
72
-
73
- if (sortInfo) {
74
- params.sortBy = sortInfo.name;
75
- params.sort = sortInfo.dir === 1 ? 'asc' : 'desc';
76
- }
77
-
78
- if (ajaxSetting && ajaxSetting.where) {
79
- params.where = ajaxSetting.where;
80
- }
81
-
82
- if (filterValue) {
83
- filterValue.forEach((fv) => {
84
- const identifier = fv.key ? fv.key : fv.name;
85
- const existingIndex = params.where.findIndex(
86
- (w) => w.id === identifier
87
- );
88
-
89
- if (fv.value !== null && fv.value !== '') {
90
- if (existingIndex !== -1) {
91
- params.where[existingIndex].value = fv.value;
92
- } else {
93
- params.where.push({
94
- id: identifier,
95
- value: fv.value,
96
- operator: fv.operator,
97
- });
98
- }
99
- } else {
100
- if (existingIndex !== -1) {
101
- params.where.splice(existingIndex, 1);
102
- }
103
- }
104
- });
105
- }
106
-
107
- try {
108
- const response = await axios.post(url, params);
109
- const { data, total } = response.data;
110
- return { data, count: total };
111
- } catch (error) {
112
- console.error('Error fetching data:', error);
113
- return { data: [], count: 0 };
114
- }
115
- };
116
-
117
- const DataGrid = forwardRef(
118
- (
119
- {
120
- ajaxSetting,
121
- api,
122
- columns,
123
- form,
124
- gridHeight,
125
- mapbox,
126
- pageData,
127
- pageSetting,
128
- paramValue,
129
- settings,
130
- setConfig,
131
- setFilterData,
132
- setTotal,
133
- setRowsSelected,
134
- style,
135
- tableSetting,
136
- userProfile = null,
137
- },
138
- ref
139
- ) => {
140
- const navigate = useNavigate();
141
-
142
- /** Audio */
143
- const audioRef = useRef(null);
144
- const [audioSource, setAudioSource] = useState('');
145
-
146
- useEffect(() => {
147
- if (audioSource) {
148
- audioRef.current.play();
149
- }
150
- }, [audioSource]);
151
-
152
- /** Gallery Modal States */
153
- const [modalGalleryShow, setModalGalleryShow] = useState(false);
154
- const [galleryData, setGalleryData] = useState([]);
155
-
156
- /** Gallery Modal Functions */
157
- const modalGalleryOpen = () => {
158
- setModalGalleryShow(true);
159
- };
160
-
161
- const modalGalleryClose = () => {
162
- setModalGalleryShow(false);
163
- };
164
-
165
- /** Modal States */
166
- const [formData, setFormData] = useState({});
167
- const [formType, setFormType] = useState('');
168
- const [formId, setFormId] = useState(0);
169
- const [modalShow, setModalShow] = useState(false);
170
-
171
- /** Modal Functions */
172
- const modalOpen = (formType, formId) => {
173
- setModalShow(true);
174
- setFormType(formType);
175
- setFormId(formId);
176
- };
177
-
178
- const modalClose = () => {
179
- setModalShow(false);
180
- };
181
-
182
- useEffect(() => {
183
- setFormData(form);
184
- }, [form]);
185
-
186
- /** Table States */
187
- const dataRef = useRef(null);
188
- const [dSearch, setDSearch] = useState('');
189
- const dataSource = useCallback(
190
- (params) => {
191
- const sqlResult = loadData(params, dSearch, ajaxSetting);
192
- if (setFilterData && params.filterValue) {
193
- setFilterData(params.filterValue);
194
- }
195
-
196
- sqlResult.then((res) => {
197
- if (setTotal) {
198
- setTotal(res.count);
199
- }
200
- setDataCount(res.count);
201
-
202
- dataRef.current = res.data;
203
- });
204
-
205
- return sqlResult;
206
- },
207
- [ajaxSetting, dSearch]
208
- );
209
- const [filterDataSource, setFilterDataSource] = useState([]);
210
- const [filterValue, setFilterValue] = useState([]);
211
- const [gridColumns, setGridColumns] = useState([]);
212
- const gridRef = useRef(null);
213
- const [limit, setLimit] = useState(0);
214
- const [search, setSearch] = useState('');
215
- const [selected, setSelected] = useState({});
216
-
217
- /** Table Functions */
218
- useImperativeHandle(ref, () => ({
219
- reload: () => {
220
- handleReload();
221
- },
222
- reset: (filter) => {
223
- handleReset(filter);
224
- },
225
- }));
226
-
227
- const handleDownload = async (d) => {
228
- const toastId = toast.loading('Starting download please wait...');
229
-
230
- try {
231
- const res = await Download(
232
- `/ajax/files/download/${d.id}/null`,
233
- 'GET',
234
- {}
235
- );
236
-
237
- if (res.data.error) {
238
- toast.error(res.data.error);
239
- } else {
240
- // Assuming the response contains a Blob or similar data
241
- if (res.data && res.data instanceof Blob) {
242
- const fileName = `${d.file_name}`;
243
- saveAs(res.data, fileName);
244
- } else {
245
- // Handle the case where the response is not a Blob
246
- toast.error('Invalid file format received.');
247
- }
248
- }
249
- } catch (error) {
250
- console.info(error);
251
- } finally {
252
- // Dismiss the loading toast in the finally block to ensure it's always dismissed
253
- toast.dismiss(toastId);
254
- }
255
- };
256
-
257
- const handleTimer = async (id, key) => {
258
- try {
259
- const res = await CustomFetch(`${form.url}/${id}`, 'PUT', {
260
- [key]: moment().toDate(),
261
- });
262
-
263
- if (res.data.error === '') {
264
- toast.success('Timer has been updated.');
265
-
266
- handleReload();
267
- } else {
268
- toast.error(res.data.error);
269
- }
270
- } catch (error) {
271
- console.info(error);
272
- }
273
- };
274
-
275
- const handleSelectionChange = useCallback(
276
- (param) => {
277
- if (param.selected === true) {
278
- const s = {};
279
-
280
- param.data.forEach((obj) => {
281
- s[obj.id] = obj;
282
- });
283
-
284
- setSelected(s);
285
- } else if (typeof param.selected === 'object') {
286
- // Assuming param.selected is an object where keys are the ids of the selections
287
- const selectedKey = Object.keys(param.selected)[0]; // Get the key of the selected object
288
- const isSelectedAlready =
289
- selected.hasOwnProperty(selectedKey); // Check if this key is already in selected
290
-
291
- if (isSelectedAlready) {
292
- // If the key already exists, reset selected
293
- setSelected({});
294
- } else {
295
- // If it does not exist, update selected with the new object
296
- setSelected((prevSelected) => ({
297
- ...prevSelected,
298
- [selectedKey]: param.selected[selectedKey],
299
- }));
300
- }
301
- } else {
302
- // Handle other cases as needed
303
- setSelected(param.selected);
304
- }
305
- },
306
- [selected]
307
- ); // Including selected in the dependency array
308
-
309
- const findUpdatedFilter = (filters, currentValues) => {
310
- for (const filter of filters) {
311
- const matchingCurrentValue = currentValues.find(
312
- (currentValue) => currentValue.name === filter.name
313
- );
314
-
315
- if (
316
- matchingCurrentValue &&
317
- filter.value !== matchingCurrentValue.value
318
- ) {
319
- return {
320
- key: filter.key || '',
321
- name: filter.name,
322
- oldValue: matchingCurrentValue.value,
323
- newValue: filter.value,
324
- };
325
- }
326
- }
327
-
328
- return null; // No changes found
329
- };
330
-
331
- const handleFilterChange = useCallback((filters, currentValues) => {
332
- const updatedFilter = findUpdatedFilter(filters, currentValues);
333
- let updatedFilters = filters;
334
- let resetMappings = [];
335
-
336
- filters.forEach((filter) => {
337
- if (filter.reset?.length > 0) {
338
- filter.reset.forEach((childId) => {
339
- resetMappings.push({ childId, parentId: filter.name });
340
- });
341
- }
342
- });
343
-
344
- filters.forEach((filter, index) => {
345
- if (
346
- filter.key &&
347
- resetMappings.some(
348
- (mapping) => mapping.childId === filter.key
349
- )
350
- ) {
351
- resetMappings.forEach((mapping) => {
352
- if (
353
- updatedFilter &&
354
- mapping.childId === filter.key &&
355
- mapping.parentId === updatedFilter.name
356
- ) {
357
- updatedFilters[index].value = '';
358
- gridRef.current.setColumnFilterValue(
359
- updatedFilters[index].name,
360
- null
361
- );
362
- }
363
- });
364
- }
365
- });
366
-
367
- setFilterValue(filters);
368
- }, []);
369
-
370
- const handleChangeSearch = (e) => {
371
- const { value } = e.target;
372
- setSearch(value);
373
- };
374
-
375
- const handleSettingClick = (s, d) => {
376
- switch (s.id) {
377
- case 'activate':
378
- CustomFetch(s.url, 'POST', { id: d[s.key] }, (result) => {
379
- toast.success(result.message);
380
- });
381
- break;
382
- case 'oauth2':
383
- let oauth2Payload = d;
384
-
385
- if (s.key?.detailKey?.length > 0) {
386
- for (const k of s.key.detailKey) {
387
- if (oauth2Payload?.[k]) {
388
- oauth2Payload = oauth2Payload[k];
389
- } else {
390
- oauth2Payload = undefined;
391
- break;
392
- }
393
- }
394
- }
395
- CustomFetch(
396
- s.key.redirect,
397
- 'POST',
398
- { ...oauth2Payload, id: d.id },
399
- (result) => {
400
- if (result.url !== '') {
401
- window.location.href = result.url;
402
- } else {
403
- toast.error(
404
- 'An error occurred while processing the request.'
405
- );
406
- }
407
- }
408
- );
409
- break;
410
- case 'delete':
411
- const getDataId = () => {
412
- for (const item of ajaxSetting.where) {
413
- if (
414
- item.hasOwnProperty('urlParam') &&
415
- item.urlParam === 'dataId'
416
- ) {
417
- return item.value;
418
- }
419
- }
420
- return 0;
421
- };
422
-
423
- confirmAlert({
424
- title: 'Delete Item',
425
- message:
426
- s.description && s.description !== ''
427
- ? s.description
428
- : `Are you sure you want to delete ${
429
- d.name
430
- ? d.name
431
- : d.label
432
- ? d.label
433
- : 'this item'
434
- }?`,
435
- buttons: [
436
- {
437
- label: 'Yes',
438
- onClick: () => {
439
- let deleteForm = {
440
- url: '',
441
- method: 'DELETE',
442
- payload: {},
443
- };
444
-
445
- if (
446
- form.hasOwnProperty('json') &&
447
- form.json === true
448
- ) {
449
- deleteForm.url = `${form.url}/jsonDelete`;
450
- deleteForm.method = 'POST';
451
- deleteForm.payload = {
452
- id: d[form.primaryKey],
453
- dataId: getDataId(),
454
- };
455
- } else {
456
- deleteForm.url = `${form.url}/${
457
- d[form.primaryKey]
458
- }`;
459
- }
460
-
461
- CustomFetch(
462
- deleteForm.url,
463
- deleteForm.method,
464
- deleteForm.payload,
465
- (result) => {
466
- if (result.error === '') {
467
- handleReload();
468
-
469
- toast.success(
470
- `The selected item has been deleted.`
471
- );
472
- } else {
473
- toast.error(
474
- <div>
475
- {parse(result.error)}
476
- </div>
477
- );
478
- }
479
- }
480
- );
481
- },
482
- },
483
- {
484
- label: 'No',
485
- onClick: () => close(),
486
- },
487
- ],
488
- });
489
- break;
490
- case 'envelope':
491
- CustomFetch(s.url, 'POST', { id: d[s.key] }, (result) => {
492
- toast.success(result.message);
493
- });
494
- break;
495
- case 'gallery':
496
- // Function to access nested property using a series of keys
497
- const getNestedValue = (data, keys) =>
498
- keys.reduce(
499
- (currentValue, key) =>
500
- currentValue && currentValue[key] !== undefined
501
- ? currentValue[key]
502
- : undefined,
503
- data
504
- );
505
-
506
- // Extracting nested value using predefined keys from 's.relation'
507
- const nestedValue = getNestedValue(d, s.relation);
508
-
509
- // Mapping nested values to create gallery array with source and captions
510
- const galleryArray = nestedValue.map((item) => ({
511
- src: item[s.key],
512
- caption: item.file_name,
513
- }));
514
-
515
- setGalleryData(galleryArray);
516
-
517
- modalGalleryOpen();
518
- break;
519
- case 'link':
520
- const url = `${s.baseUrl}/${d[s.key]}`;
521
- navigator.clipboard.writeText(url).then(
522
- () => {
523
- toast.success(
524
- 'URL has been copied to your clipboard.'
525
- );
526
- },
527
- () => {
528
- toast.warning('Failed to copy URL to clipboard.');
529
- }
530
- );
531
- break;
532
- case 'sound':
533
- const soundRelation = s.relation.reduce((acc, id) => {
534
- if (acc === '') {
535
- return d[id];
536
- } else {
537
- if (acc && acc[id]) {
538
- return acc[id];
539
- } else {
540
- return '';
541
- }
542
- }
543
- }, '');
544
-
545
- if (soundRelation && soundRelation[s.key] && s.url) {
546
- CustomFetch(
547
- `${s.url}/${soundRelation[s.key]}`,
548
- 'POST',
549
- {},
550
- (res) => {
551
- if (res && res !== '') {
552
- setAudioSource(res);
553
- }
554
- }
555
- );
556
- }
557
- break;
558
- case 'update':
559
- modalOpen('update', d.id);
560
- break;
561
- default:
562
- confirmAlert({
563
- title: s.title,
564
- message: '',
565
- buttons: [
566
- {
567
- label: 'Yes',
568
- onClick: () =>
569
- CustomFetch(
570
- s.url + '/' + d[form.primaryKey],
571
- s.method,
572
- {},
573
- function (result) {
574
- if (result.error === '') {
575
- handleReload();
576
-
577
- toast.success(String(s.title));
578
- } else {
579
- toast.error(
580
- <div>
581
- {parse(result.error)}
582
- </div>
583
- );
584
- }
585
- }
586
- ),
587
- },
588
- {
589
- label: 'No',
590
- onClick: () => close(),
591
- },
592
- ],
593
- });
594
- break;
595
- }
596
- };
597
-
598
- const handleReset = (filter) => {
599
- if (filter && filter.length > 0) {
600
- filter.forEach((f) => {
601
- gridRef.current.setColumnFilterValue(f.name, f.value);
602
- });
603
-
604
- setFilterData(filter);
605
- }
606
- };
607
-
608
- const handleReload = () => {
609
- gridRef.current.paginationProps.reload();
610
- };
611
-
612
- const handleSort = (value) => {
613
- if (setConfig) {
614
- setConfig((prevState) => {
615
- const { id, dir } = value || {}; // Destructure id and dir from value (if provided)
616
- const sortBy = id || null;
617
- const sort = dir === 1 ? 'asc' : dir === -1 ? 'desc' : null;
618
-
619
- return {
620
- ...prevState,
621
- ajaxSetting: {
622
- ...prevState.ajaxSetting,
623
- sortBy,
624
- sort,
625
- },
626
- };
627
- });
628
- }
629
- };
630
-
631
- const onRowClick = useCallback((rowProps, event) => {
632
- const cellElement = event.target.closest(
633
- '.InovuaReactDataGrid__cell'
634
- );
635
- const columnIndex = Array.from(
636
- cellElement.parentNode.children
637
- ).indexOf(cellElement);
638
-
639
- if (
640
- rowProps.columns.length > 1 &&
641
- columnIndex === rowProps.columns.length - 1
642
- ) {
643
- // Handle last column click
644
- } else {
645
- const column = rowProps.columns[columnIndex];
646
-
647
- if (column.type !== 'dropdown') {
648
- if (column.id !== '__checkbox-column') {
649
- if (column.link && column.link.url) {
650
- const fileRelationArray = column.id.split('.');
651
- const linkUrl = column.link.url;
652
- const linkKey =
653
- rowProps.columns[columnIndex].link.key;
654
- const rowData = rowProps.data[linkKey];
655
-
656
- if (column.link.hasOwnProperty('folder')) {
657
- const linkFolder =
658
- rowProps.columns[columnIndex].link.folder;
659
-
660
- if (rowProps.data[fileRelationArray[0]]) {
661
- if (linkFolder !== '') {
662
- window.open(
663
- `${linkUrl}${rowData}/${linkFolder}`
664
- );
665
- } else {
666
- window.open(`${linkUrl}${rowData}`);
667
- }
668
- }
669
- } else {
670
- navigate(`${linkUrl}${rowData}`);
671
- }
672
- } else if (column.link && column.link.popup) {
673
- const linkPopup = column.link.popup;
674
- const linkKey =
675
- rowProps.columns[columnIndex].link.key;
676
- const rowData = rowProps.data[linkKey];
677
-
678
- window.open(
679
- `${linkPopup}/${rowData}`,
680
- '',
681
- 'width=1440,height=1024,menubar=1,resizable=1,status=1,titlebar=1,toolbar=1'
682
- );
683
- } else {
684
- const updateSetting = settings.find(
685
- (setting) => setting.id === 'update'
686
- );
687
-
688
- if (updateSetting) {
689
- modalOpen(
690
- 'update',
691
- rowProps.data[form.primaryKey]
692
- );
693
- }
694
- }
695
- }
696
- }
697
- }
698
- }, []);
699
-
700
- const onRenderRow = useCallback((rowProps) => {
701
- // save the original handlers to be called later
702
- const { onClick } = rowProps;
703
-
704
- rowProps.onClick = (event) => {
705
- onRowClick(rowProps, event);
706
-
707
- const cellElement = event.target.closest(
708
- '.InovuaReactDataGrid__cell'
709
- );
710
- const columnIndex = Array.from(
711
- cellElement.parentNode.children
712
- ).indexOf(cellElement);
713
-
714
- const column = rowProps.columns[columnIndex];
715
-
716
- if (column.id === '__checkbox-column') {
717
- if (onClick) {
718
- onClick(event);
719
- }
720
- }
721
- };
722
- }, []);
723
-
724
- const exportTrigger = async () => {
725
- try {
726
- toast.success('Starting export please wait...');
727
-
728
- let payload;
729
-
730
- if (form.export.useData) {
731
- payload = { data: dataRef.current };
732
- } else {
733
- payload = {
734
- filter: filterValue,
735
- paramId: paramValue || '',
736
- };
737
- }
738
-
739
- const res = await Download(form.export.url, 'POST', payload);
740
-
741
- if (res.data.error) {
742
- toast.error(res.data.error);
743
- } else {
744
- // Assuming the response contains a Blob or similar data
745
- if (res.data && res.data instanceof Blob) {
746
- const fileName = `${form.export.filename}`;
747
- saveAs(res.data, fileName);
748
- } else {
749
- // Handle the case where the response is not a Blob
750
- toast.error('Invalid file format received.');
751
- }
752
- }
753
- } catch (error) {
754
- console.info(error);
755
- }
756
- };
757
-
758
- const sortTrigger = () => {
759
- let baseUrl = form.url.replace('/ajax', '');
760
- let sortUrl = paramValue
761
- ? `${baseUrl}/${paramValue}/sort`
762
- : `${baseUrl}/sort`;
763
-
764
- if (form.sort?.url) {
765
- sortUrl = form.sort.url;
766
- }
767
-
768
- const newState = {
769
- form,
770
- page: {
771
- data: pageData,
772
- setting: pageSetting,
773
- },
774
- paramValue,
775
- };
776
-
777
- navigate(sortUrl, { state: newState });
778
- };
779
-
780
- const renderCreateButton = () => {
781
- if (form.createDisable && form.createDisable === true) {
782
- return null;
783
- }
784
-
785
- return (
786
- <div className={styles['filterAction--alt']}>
787
- {form.export && form.export.url && (
788
- <button className={styles.btn} onClick={exportTrigger}>
789
- Export
790
- </button>
791
- )}
792
- {form.sort && form.sort.title && (
793
- <button className={styles.btn} onClick={sortTrigger}>
794
- <div className="icon-plus"></div> Sort Order
795
- </button>
796
- )}
797
-
798
- {(form.create &&
799
- form.create.title &&
800
- form.create.title !== '') ||
801
- (form.url && form.create?.title !== '') ? (
802
- <button
803
- className={styles.btn}
804
- onClick={(e) => {
805
- e.preventDefault();
806
-
807
- if (form.create) {
808
- if (form.create.url) {
809
- navigate(form.create.url);
810
- } else {
811
- modalOpen('create', 0);
812
- }
813
- } else {
814
- if (form.url) {
815
- window.open(
816
- form.url,
817
- '',
818
- 'width=1440,height=1024,menubar=1,resizable=1,status=1,titlebar=1,toolbar=1'
819
- );
820
- }
821
- }
822
- }}
823
- >
824
- <div className="icon-plus"></div> Create
825
- </button>
826
- ) : form.url && form.modal === false ? (
827
- <button
828
- className={styles.btn}
829
- onClick={(e) => {
830
- e.preventDefault();
831
-
832
- window.open(
833
- form.url,
834
- '',
835
- 'width=1440,height=1024,menubar=1,resizable=1,status=1,titlebar=1,toolbar=1'
836
- );
837
- }}
838
- >
839
- <div className="icon-plus"></div> Create
840
- </button>
841
- ) : null}
842
- </div>
843
- );
844
- };
845
-
846
- const renderSearch = () => {
847
- const isSearchEnabled = !(form.searchDisable === true);
848
- const isCreateDisabled = form.createDisable === true;
849
-
850
- if (isSearchEnabled) {
851
- return (
852
- <div className={styles['filterInput--alt']}>
853
- <div className={styles['icon-search']}>
854
- <Search strokeWidth={2} size={18} />
855
- </div>
856
- <input
857
- type="text"
858
- placeholder="Search"
859
- value={search}
860
- onChange={handleChangeSearch}
861
- />
862
- </div>
863
- );
864
- } else if (!isCreateDisabled) {
865
- return (
866
- <div
867
- className={styles['filterInput--alt']}
868
- style={{
869
- height: style.data_grid_search_height
870
- ? style.data_grid_search_height
871
- : '58px',
872
- }}
873
- ></div>
874
- );
875
- }
876
-
877
- return null; // Return null if neither search is enabled nor create is disabled
878
- };
879
-
880
- const renderRowContextMenu = useCallback(
881
- (menuProps, { rowProps }) => {
882
- if (form && form.newTabUrl && form.newTabUrl !== '') {
883
- menuProps.autoDismiss = true;
884
- menuProps.items = [
885
- {
886
- label: 'Open Link in a New Tab',
887
- onClick: () => {
888
- window.open(
889
- `${form.newTabUrl}${
890
- rowProps.data[form.primaryKey]
891
- }`
892
- );
893
- },
894
- },
895
- ];
896
- }
897
- },
898
- [form]
899
- );
900
-
901
- const handleCoding = (c, data) => {
902
- const icons = [];
903
- const assetPath =
904
- import.meta.env.REACT_APP_ASSET_PATH !== undefined
905
- ? import.meta.env.REACT_APP_ASSET_PATH
906
- : '';
907
-
908
- const addIcon = (src, icon, alt, tooltipContent, key) => {
909
- if (src && src !== '') {
910
- icons.push(
911
- <img
912
- src={`${assetPath}${src}`}
913
- alt={alt}
914
- data-tooltip-id="system-tooltip"
915
- data-tooltip-content={tooltipContent}
916
- key={key}
917
- />
918
- );
919
- } else {
920
- let IconComponent = null;
921
-
922
- if (icon === 'archive') {
923
- IconComponent = ShippingBoxV1;
924
- } else if (icon === 'folder') {
925
- IconComponent = Folder;
926
- } else if (icon === 'inbox') {
927
- IconComponent = Inbox;
928
- } else if (icon === 'network') {
929
- IconComponent = Network;
930
- } else if (icon === 'urgent') {
931
- IconComponent = TriangleAlert;
932
- }
933
-
934
- if (IconComponent) {
935
- icons.push(
936
- <IconComponent
937
- data-tooltip-id="system-tooltip"
938
- data-tooltip-content={tooltipContent}
939
- strokeWidth={2}
940
- size={18}
941
- className={styles.tdaction}
942
- key={key}
943
- />
944
- );
945
- }
946
- }
947
- };
948
-
949
- c.config.forEach((config, configKey) => {
950
- const fieldValue = config.id.reduce((acc, id) => {
951
- if (acc === '') {
952
- return data[id];
953
- } else {
954
- return acc ? acc[id] : '';
955
- }
956
- }, '');
957
-
958
- const iconData = config.icons.find(
959
- (icon) => icon.value === fieldValue
960
- );
961
-
962
- if (
963
- iconData &&
964
- (iconData.src || iconData.icon) &&
965
- iconData.alt &&
966
- iconData.tooltipContent
967
- ) {
968
- addIcon(
969
- iconData.src ? iconData.src : null,
970
- iconData.icon ? iconData.icon : null,
971
- iconData.alt,
972
- iconData.tooltipContent,
973
- `coding-${config.id[0]}-${configKey}`
974
- );
975
- }
976
- });
977
-
978
- return icons;
979
- };
980
-
981
- /** Table Hooks */
982
- useEffect(() => {
983
- if (setRowsSelected) {
984
- setRowsSelected(selected);
985
- }
986
- }, [selected]);
987
-
988
- useEffect(() => {
989
- const delayedSetDSearch = debounce(() => {
990
- setDSearch(search);
991
- }, 300); // Adjust the delay (in milliseconds) according to your needs
992
-
993
- delayedSetDSearch();
994
-
995
- return delayedSetDSearch.cancel; // Cleanup the debounce timer on unmount
996
- }, [search, setDSearch]);
997
-
998
- const renderSetting = (s, d) => {
999
- let iconStyle = {};
1000
- let allow = true;
1001
-
1002
- if (s.active) {
1003
- if (
1004
- d.hasOwnProperty(s.active.id) &&
1005
- d[s.active.id] === s.active.value &&
1006
- s.active.type !== 'greater' &&
1007
- s.active.type !== 'not null'
1008
- ) {
1009
- iconStyle = {
1010
- color: s.active.colour,
1011
- };
1012
- } else if (
1013
- s.active.type === 'greater' &&
1014
- d[s.active.id] > s.active.value
1015
- ) {
1016
- iconStyle = {
1017
- color: s.active.colour,
1018
- };
1019
- } else if (
1020
- s.active.type === 'not null' &&
1021
- d[s.active.id] !== null
1022
- ) {
1023
- iconStyle = {
1024
- color: s.active.colour,
1025
- };
1026
- } else {
1027
- iconStyle = {
1028
- color: '',
1029
- };
1030
- }
1031
- }
1032
-
1033
- const handleIconClick = (e) => {
1034
- e.preventDefault();
1035
- e.stopPropagation();
1036
- handleSettingClick(s, d);
1037
- };
1038
-
1039
- const tooltipContent =
1040
- iconStyle && iconStyle.color ? s.active.title : s.title;
1041
-
1042
- if (s.hide && s.hide.id && s.hide.value >= 0) {
1043
- if (
1044
- d.hasOwnProperty(s.hide.id) &&
1045
- parseInt(d[s.hide.id]) === parseInt(s.hide.value)
1046
- ) {
1047
- allow = false;
1048
- }
1049
- }
1050
-
1051
- if (s.id === 'oauth2') {
1052
- let tmpCheckValue = d;
1053
-
1054
- if (s.key?.check?.length > 0) {
1055
- for (const k of s.key.check) {
1056
- if (tmpCheckValue?.[k]) {
1057
- tmpCheckValue = tmpCheckValue[k];
1058
- } else {
1059
- tmpCheckValue = undefined;
1060
- break;
1061
- }
1062
- }
1063
- }
1064
-
1065
- if (!tmpCheckValue) {
1066
- allow = false;
1067
- }
1068
- }
1069
-
1070
- if (allow) {
1071
- switch (s.id) {
1072
- case 'activate':
1073
- return getIconComponent(CircleCheck);
1074
- case 'archive':
1075
- return getIconComponent(ShippingBoxV1);
1076
- case 'oauth2':
1077
- return getIconComponent(LockOn);
1078
- case 'complete':
1079
- return getIconComponent(Check);
1080
- case 'copy':
1081
- return getIconComponent(Copy);
1082
- case 'delete':
1083
- return getIconComponent(Backspace);
1084
- case 'envelope':
1085
- return getIconComponent(Envelope);
1086
- case 'family':
1087
- return getIconComponent(Network);
1088
- case 'gallery':
1089
- return getIconComponent(Image);
1090
- case 'link':
1091
- return getIconComponent(LinkOut);
1092
- case 'primary':
1093
- return getIconComponent(Ribbon);
1094
- case 'restore':
1095
- return getIconComponent(ArrowCounterClockwise);
1096
- case 'sound':
1097
- return getIconComponent(SoundOn);
1098
- case 'ssa':
1099
- return getIconComponent(Clock);
1100
- case 'update':
1101
- return getIconComponent(Edit);
1102
- default:
1103
- return null;
1104
- }
1105
- } else {
1106
- return null;
1107
- }
1108
-
1109
- function getIconComponent(IconComponent) {
1110
- return (
1111
- <span key={`setting-${s.id}`} onClick={handleIconClick}>
1112
- <IconComponent
1113
- data-tooltip-id="system-tooltip"
1114
- data-tooltip-content={tooltipContent}
1115
- strokeWidth={2}
1116
- size={18}
1117
- className={styles.tdaction}
1118
- style={iconStyle}
1119
- />
1120
- </span>
1121
- );
1122
- }
1123
- };
1124
-
1125
- const renderColumnContextMenu = useCallback(
1126
- (menuProps, { cellProps }) => {
1127
- const filteredItems = menuProps.items
1128
- .map((item, key) => {
1129
- if (key >= 6 && key <= 9) {
1130
- return null; // Skip items with keys 6-9 [lock columns setting]
1131
- }
1132
- return item;
1133
- })
1134
- .filter(Boolean); // Filter out any null items
1135
-
1136
- menuProps.items = filteredItems;
1137
- },
1138
- []
1139
- );
1140
-
1141
- const handleDropdownUpdate = async (id, url, method, value) => {
1142
- try {
1143
- const res = await CustomFetch(url, method, {
1144
- [id]: value,
1145
- });
1146
-
1147
- if (res.data.error === '') {
1148
- handleReload();
1149
- } else {
1150
- toast.error(res.data.error);
1151
- }
1152
- } catch (err) {
1153
- console.error(err);
1154
- }
1155
- };
1156
-
1157
- const getDropdownData = async (ids, url, fields) => {
1158
- // Concatenate id array into a single string if it's an array
1159
- const uniqueId = Array.isArray(ids) ? ids.join('') : ids;
1160
-
1161
- // Return a promise that includes the concatenated uniqueId in the resolution
1162
- return new Promise(async (resolve, reject) => {
1163
- try {
1164
- const res = await CustomFetch(url, 'POST', { fields });
1165
- resolve({ [uniqueId]: res.data.data }); // Correctly use uniqueId as the key
1166
- } catch (err) {
1167
- console.error(err);
1168
- reject(err); // Reject the promise if there's an error
1169
- }
1170
- });
1171
- };
1172
-
1173
- useEffect(() => {
1174
- const dropdownFetches = columns
1175
- .filter((column) => column.type === 'dropdown')
1176
- .map((column) =>
1177
- getDropdownData(column.id, column.url, column.fields)
1178
- );
1179
-
1180
- Promise.all(dropdownFetches)
1181
- .then((results) => {
1182
- // Merge all resolved objects into a single object
1183
- const dropdownData = results.reduce((acc, result) => {
1184
- return { ...acc, ...result };
1185
- }, {});
1186
-
1187
- const renderColumn = (column) => {
1188
- let childValue;
1189
- let columnId;
1190
- let date;
1191
- let filterEditor = null;
1192
- let filterEditorProps = null;
1193
- let fileUrl = null;
1194
- let icons = [];
1195
- let relationName;
1196
- let selectedDataSource = null;
1197
- let stage;
1198
- let columnStyle;
1199
- let value;
1200
-
1201
- const commonProps = {
1202
- header: column.label,
1203
- defaultFlex: 1,
1204
- link: column.link ?? {},
1205
- minWidth: column.minWidth ?? undefined,
1206
- maxWidth: column.maxWidth ?? undefined,
1207
- textAlign: column.textAlign ?? undefined,
1208
- textVerticalAlign:
1209
- style && style.text_vertical_align
1210
- ? style.text_vertical_align
1211
- : 'center',
1212
- style: (cellProps) => {
1213
- const { id, value } = cellProps;
1214
- let columnStyle = {};
1215
-
1216
- if (
1217
- column.styleCondition &&
1218
- column.styleCondition.key
1219
- ) {
1220
- if (value) {
1221
- columnStyle = {
1222
- ...(column.style ?? {}),
1223
- margin: '0px',
1224
- };
1225
- }
1226
- } else {
1227
- columnStyle = {
1228
- ...(column.style ?? {}),
1229
- margin: '0px',
1230
- };
1231
- }
1232
-
1233
- return columnStyle;
1234
- },
1235
- type: column.type,
1236
- };
1237
-
1238
- switch (column.type) {
1239
- case 'relation':
1240
- case 'relationArray':
1241
- relationName = column.id.reduce(
1242
- (acc, id) => acc + `${id}.`,
1243
- ''
1244
- );
1245
- relationName += column.nameFrom;
1246
-
1247
- selectedDataSource = filterDataSource.reduce(
1248
- (acc, fds) => {
1249
- if (fds.id === relationName) {
1250
- return fds.dataset;
1251
- }
1252
- return acc;
1253
- },
1254
- null
1255
- );
1256
- break;
1257
- default:
1258
- selectedDataSource = filterDataSource.reduce(
1259
- (acc, fds) => {
1260
- if (fds.id === column.id) {
1261
- return fds.dataset;
1262
- }
1263
- return acc;
1264
- },
1265
- null
1266
- );
1267
- break;
1268
- }
1269
-
1270
- if (column.filter && column.filter.type) {
1271
- switch (column.filter.type) {
1272
- case 'date':
1273
- filterEditor = DateFilter;
1274
- filterEditorProps = (props, { index }) => {
1275
- return {
1276
- dateFormat: 'DD-MM-YYYY',
1277
- placeholder: column.filter
1278
- .placeholder
1279
- ? column.filter.placeholder
1280
- : 'Select Date',
1281
- };
1282
- };
1283
- break;
1284
- case 'number':
1285
- filterEditor = NumberFilter;
1286
- break;
1287
- case 'select':
1288
- filterEditor = SelectFilter;
1289
- filterEditorProps = {
1290
- multiple:
1291
- column.filter.operator === 'inlist',
1292
- wrapMultiple:
1293
- column.filter.operator !== 'inlist',
1294
- placeholder: column.filter.placeholder
1295
- ? column.filter.placeholder
1296
- : 'All Options',
1297
- dataSource: selectedDataSource,
1298
- };
1299
- break;
1300
- default:
1301
- filterEditor = null;
1302
- filterEditorProps = null;
1303
- break;
1304
- }
1305
- } else {
1306
- filterEditor = null;
1307
- filterEditorProps = null;
1308
- }
1309
-
1310
- switch (column.type) {
1311
- case 'address':
1312
- return {
1313
- ...commonProps,
1314
- name: `${column.type}.${column.id}`,
1315
- filterEditor: filterEditor,
1316
- filterEditorProps: filterEditorProps,
1317
- render: ({ data }) => {
1318
- const addressFields = [
1319
- 'address1',
1320
- 'address2',
1321
- 'suburb',
1322
- 'postcode',
1323
- ];
1324
-
1325
- const addressValue = addressFields
1326
- .filter((field) => data[field])
1327
- .map((field) => data[field])
1328
- .join(' ');
1329
-
1330
- const stateValue =
1331
- data.state?.name ||
1332
- data.state ||
1333
- '';
1334
-
1335
- const value = `${addressValue} ${stateValue}`;
1336
-
1337
- return <span>{value}</span>;
1338
- },
1339
- };
1340
- case 'age':
1341
- return {
1342
- ...commonProps,
1343
- type: 'number',
1344
- filterEditor: filterEditor,
1345
- name: `${column.type}.${column.id}`,
1346
- render: ({ data }) => {
1347
- value = column.id.reduce((acc, id) => {
1348
- if (acc === '') {
1349
- return data[id];
1350
- } else {
1351
- return acc ? acc[id] : '';
1352
- }
1353
- }, '');
1354
-
1355
- if (value !== '' && value !== null) {
1356
- date = moment(value);
1357
-
1358
- return (
1359
- <span>
1360
- {moment().diff(
1361
- date,
1362
- column.duration
1363
- ? column.duration
1364
- : 'years'
1365
- )}
1366
- </span>
1367
- );
1368
- } else {
1369
- return null;
1370
- }
1371
- },
1372
- };
1373
- case 'arrayCount':
1374
- return {
1375
- ...commonProps,
1376
- name: `${column.type}.${column.id}`,
1377
- sortable: false,
1378
- render: ({ data }) => {
1379
- if (data && data[column.id]) {
1380
- return data[column.id].length;
1381
- } else {
1382
- return null;
1383
- }
1384
- },
1385
- };
1386
- case 'boolean':
1387
- return {
1388
- ...commonProps,
1389
- name: `${column.type}.${column.id}`,
1390
- sortable: false,
1391
- render: ({ data }) => {
1392
- if (data[column.id]) {
1393
- return 'Yes';
1394
- } else {
1395
- return 'No';
1396
- }
1397
- },
1398
- };
1399
- case 'coding':
1400
- return {
1401
- ...commonProps,
1402
- name: `${column.type}.${column.id}`,
1403
- sortable: false,
1404
- render: ({ data }) => {
1405
- if (data) {
1406
- return handleCoding(column, data);
1407
- } else {
1408
- return null;
1409
- }
1410
- },
1411
- };
1412
- case 'colour':
1413
- return {
1414
- ...commonProps,
1415
- name: `${column.type}.${column.id}`,
1416
- sortable: false,
1417
- render: ({ data }) => {
1418
- if (data && data[column.id]) {
1419
- return (
1420
- <div
1421
- style={{
1422
- width: '25px',
1423
- height: '25px',
1424
- borderRadius: '10px',
1425
- overflow: 'hidden',
1426
- }}
1427
- >
1428
- <div
1429
- style={{
1430
- background:
1431
- data[
1432
- column.id
1433
- ] +
1434
- ' none repeat scroll 0% 0%',
1435
- height: '100%',
1436
- width: '100%',
1437
- cursor: 'pointer',
1438
- position:
1439
- 'relative',
1440
- outline:
1441
- 'currentcolor none medium',
1442
- }}
1443
- ></div>
1444
- </div>
1445
- );
1446
- } else {
1447
- return null;
1448
- }
1449
- },
1450
- };
1451
- case 'created_by':
1452
- return {
1453
- ...commonProps,
1454
- name: `${column.type}.${column.id}`,
1455
- sortable: false,
1456
- render: ({ data }) => {
1457
- if (
1458
- data.audits[0] &&
1459
- data.audits[0].user &&
1460
- data.audits[0].user.name
1461
- ) {
1462
- value = data.audits[0].user.name;
1463
-
1464
- return <span>{value}</span>;
1465
- } else {
1466
- return null;
1467
- }
1468
- },
1469
- };
1470
- case 'currency':
1471
- return {
1472
- ...commonProps,
1473
- name: column.id,
1474
- render: ({ data }) => {
1475
- if (data) {
1476
- data = numeral(
1477
- data[column.id]
1478
- ).format('$0,0.00');
1479
-
1480
- return <span>{data}</span>;
1481
- } else {
1482
- return null;
1483
- }
1484
- },
1485
- };
1486
- case 'date':
1487
- return {
1488
- ...commonProps,
1489
- name: column.id,
1490
- filterEditor: filterEditor,
1491
- filterEditorProps: filterEditorProps,
1492
- render: ({ data }) => {
1493
- if (
1494
- data &&
1495
- data[column.id] &&
1496
- moment(data[column.id]).isValid() &&
1497
- moment(data[column.id]).format(
1498
- 'YYYY-MM-DD'
1499
- ) !== '1970-01-01'
1500
- ) {
1501
- const value = moment(
1502
- data[column.id]
1503
- ).format(
1504
- column.format || 'DD-MM-YYYY'
1505
- );
1506
- columnStyle = {};
1507
-
1508
- if (
1509
- column.active &&
1510
- column.active.id &&
1511
- column.active.value ===
1512
- 'expired'
1513
- ) {
1514
- if (
1515
- data[column.active.id] &&
1516
- moment(
1517
- data[column.active.id]
1518
- ).isBefore(moment())
1519
- ) {
1520
- columnStyle = {
1521
- color: column.active
1522
- .colour,
1523
- };
1524
- }
1525
- }
1526
-
1527
- return (
1528
- <span style={columnStyle}>
1529
- {value}
1530
- </span>
1531
- );
1532
- } else {
1533
- return null;
1534
- }
1535
- },
1536
- };
1537
- case 'daterange':
1538
- return {
1539
- ...commonProps,
1540
- name: `${column.id[0]}.${column.id[1]}.`,
1541
- filterEditor: filterEditor,
1542
- filterEditorProps: filterEditorProps,
1543
- render: ({ data }) => {
1544
- if (
1545
- data &&
1546
- data[column.id[0]] &&
1547
- moment(
1548
- data[column.id[0]]
1549
- ).isValid() &&
1550
- moment(data[column.id[0]]).format(
1551
- 'YYYY-MM-DD'
1552
- ) !== '1970-01-01'
1553
- ) {
1554
- value = moment(
1555
- data[column.id[0]]
1556
- ).format(
1557
- column.format || 'DD-MM-YYYY'
1558
- );
1559
- }
1560
-
1561
- if (
1562
- data &&
1563
- data[column.id[1]] &&
1564
- moment(
1565
- data[column.id[1]]
1566
- ).isValid() &&
1567
- moment(data[column.id[1]]).format(
1568
- 'YYYY-MM-DD'
1569
- ) !== '1970-01-01'
1570
- ) {
1571
- value += ` - ${moment(
1572
- data[column.id[1]]
1573
- ).format(
1574
- column.format || 'DD-MM-YYYY'
1575
- )}`;
1576
- }
1577
-
1578
- return <span>{value}</span>;
1579
- },
1580
- };
1581
- case 'datetime':
1582
- return {
1583
- ...commonProps,
1584
- name: column.id,
1585
- filterEditor: filterEditor,
1586
- filterEditorProps: filterEditorProps,
1587
- render: ({ data }) => {
1588
- if (
1589
- data &&
1590
- data[column.id] &&
1591
- moment(data[column.id]).isValid() &&
1592
- moment(data[column.id]).format(
1593
- 'YYYY-MM-DD'
1594
- ) !== '1970-01-01'
1595
- ) {
1596
- data = moment(
1597
- data[column.id]
1598
- ).format(
1599
- column.format
1600
- ? column.format
1601
- : 'DD-MM-YYYY hh:mm A'
1602
- );
1603
-
1604
- return <span>{data}</span>;
1605
- } else {
1606
- return null;
1607
- }
1608
- },
1609
- };
1610
- case 'dropdown':
1611
- columnId = Array.isArray(column.id)
1612
- ? column.id.join('-')
1613
- : column.id;
1614
-
1615
- return {
1616
- ...commonProps,
1617
- name: columnId,
1618
- render: ({ data }) => {
1619
- return (
1620
- <select
1621
- name={column.id}
1622
- value={
1623
- data[column.id]?.id || ''
1624
- }
1625
- style={{ padding: '7px' }}
1626
- onChange={(e) => {
1627
- e.preventDefault();
1628
-
1629
- if (
1630
- (column.update?.key,
1631
- column.update?.url,
1632
- column.update?.method)
1633
- ) {
1634
- handleDropdownUpdate(
1635
- column.update.key,
1636
- `${column.update.url}/${data.id}`,
1637
- column.update
1638
- .method,
1639
- e.target.value
1640
- );
1641
- }
1642
- }}
1643
- >
1644
- <option value="">
1645
- Select an Option
1646
- </option>
1647
- {dropdownData[column.id] &&
1648
- dropdownData[column.id].length >
1649
- 0
1650
- ? dropdownData[
1651
- column.id
1652
- ].map((option, index) => (
1653
- <option
1654
- value={option.id}
1655
- key={index}
1656
- >
1657
- {option.label}
1658
- </option>
1659
- ))
1660
- : null}
1661
- </select>
1662
- );
1663
- },
1664
- };
1665
- case 'file':
1666
- return {
1667
- ...commonProps,
1668
- name: column.id,
1669
- sortable: false,
1670
- render: ({ data }) => {
1671
- if (data && data[column.id]) {
1672
- // Check if the data is an array of files
1673
- if (
1674
- Array.isArray(data[column.id])
1675
- ) {
1676
- // Return a span for each file in the array with added margin
1677
- return data[column.id].map(
1678
- (file, index) => (
1679
- <span
1680
- key={index} // Use index as a key; consider using unique ids if available
1681
- onClick={(e) => {
1682
- e.stopPropagation();
1683
- e.preventDefault();
1684
- handleDownload(
1685
- file
1686
- );
1687
- }}
1688
- style={{
1689
- marginRight:
1690
- '10px',
1691
- display:
1692
- 'inline-block',
1693
- }} // Added margin right and display style
1694
- >
1695
- <CloudDownload
1696
- data-tooltip-id={`system-tooltip`}
1697
- data-tooltip-content={`Download File ${file.file_name}`}
1698
- strokeWidth={2}
1699
- size={18}
1700
- className={
1701
- styles.tdaction
1702
- }
1703
- />
1704
- </span>
1705
- )
1706
- );
1707
- } else {
1708
- // Return a single span for a single file with added margin
1709
- return (
1710
- <span
1711
- onClick={(e) => {
1712
- e.stopPropagation();
1713
- e.preventDefault();
1714
- handleDownload(
1715
- data[column.id]
1716
- );
1717
- }}
1718
- style={{
1719
- marginRight: '10px',
1720
- display:
1721
- 'inline-block',
1722
- }} // Added margin right and display style for consistency
1723
- >
1724
- <CloudDownload
1725
- data-tooltip-id="system-tooltip"
1726
- data-tooltip-content={`Download File ${
1727
- data[column.id]
1728
- .file_name
1729
- }`}
1730
- strokeWidth={2}
1731
- size={18}
1732
- className={
1733
- styles.tdaction
1734
- }
1735
- />
1736
- </span>
1737
- );
1738
- }
1739
- } else {
1740
- return null;
1741
- }
1742
- },
1743
- };
1744
- case 'icons':
1745
- return {
1746
- ...commonProps,
1747
- name: column.id,
1748
- sortable: false,
1749
- render: ({ data }) => {
1750
- icons = [];
1751
-
1752
- if (
1753
- column.icons &&
1754
- column.icons.length > 0
1755
- ) {
1756
- column.icons.forEach((icon) => {
1757
- icons.push(
1758
- <img
1759
- src={icon.url}
1760
- alt={icon.name}
1761
- data-tooltip-id="system-tooltip"
1762
- data-tooltip-content={
1763
- icon.name
1764
- }
1765
- />
1766
- );
1767
- });
1768
- }
1769
-
1770
- if (data) {
1771
- return <span>{icons}</span>;
1772
- } else {
1773
- return null;
1774
- }
1775
- },
1776
- };
1777
- case 'image':
1778
- return {
1779
- ...commonProps,
1780
- name: column.id,
1781
- render: ({ data }) => {
1782
- if (data && data[column.id]) {
1783
- fileUrl =
1784
- data[column.id][0]?.file_url ||
1785
- data[column.id]?.file_url;
1786
-
1787
- if (fileUrl) {
1788
- return (
1789
- <span>
1790
- {parse(
1791
- `<img width="150" src="${fileUrl}" />`
1792
- )}
1793
- </span>
1794
- );
1795
- }
1796
- }
1797
-
1798
- return null;
1799
- },
1800
- };
1801
- case 'json':
1802
- return {
1803
- ...commonProps,
1804
- name: `${column.id}.${column.jsonData}`,
1805
- render: ({ data }) => {
1806
- if (
1807
- data &&
1808
- data[column.id] &&
1809
- data[column.id][column.jsonData]
1810
- ) {
1811
- data =
1812
- data[column.id][
1813
- column.jsonData
1814
- ];
1815
-
1816
- return <span>{data}</span>;
1817
- } else {
1818
- return null;
1819
- }
1820
- },
1821
- };
1822
- case 'number':
1823
- return {
1824
- ...commonProps,
1825
- name: column.id,
1826
- type: 'number',
1827
- };
1828
- case 'option':
1829
- return {
1830
- ...commonProps,
1831
- name: column.id,
1832
- filterEditor: filterEditor,
1833
- filterEditorProps: filterEditorProps,
1834
- render: ({ data }) => {
1835
- let newData;
1836
-
1837
- if (
1838
- data &&
1839
- column.options &&
1840
- column.options[data[column.id]]
1841
- ) {
1842
- if (
1843
- column.key &&
1844
- data[column.key] > 0 &&
1845
- column.options[
1846
- data[column.id]
1847
- ].includes('#')
1848
- ) {
1849
- newData = column.options[
1850
- data[column.id]
1851
- ].replace(
1852
- /#/g,
1853
- data[column.key]
1854
- );
1855
- } else {
1856
- newData =
1857
- column.options[
1858
- data[column.id]
1859
- ];
1860
- }
1861
-
1862
- return <span>{newData}</span>;
1863
- } else {
1864
- return null;
1865
- }
1866
- },
1867
- };
1868
- case 'placeholder':
1869
- return {
1870
- ...commonProps,
1871
- name: column.id,
1872
- sortable: false,
1873
- render: ({ data }) => {
1874
- if (data) {
1875
- return (
1876
- <span>
1877
- {column.placeholder}
1878
- </span>
1879
- );
1880
- } else {
1881
- return null;
1882
- }
1883
- },
1884
- };
1885
- case 'relation':
1886
- return {
1887
- ...commonProps,
1888
- name: relationName,
1889
- sortable: false,
1890
- filterEditor: filterEditor,
1891
- filterEditorProps: filterEditorProps,
1892
- render: ({ data }) => {
1893
- value = column.id.reduce((acc, id) => {
1894
- if (acc === '') {
1895
- if (data[id]) {
1896
- return data[id];
1897
- } else {
1898
- return '';
1899
- }
1900
- } else {
1901
- if (acc && acc[id]) {
1902
- return acc[id];
1903
- } else {
1904
- return '';
1905
- }
1906
- }
1907
- }, '');
1908
-
1909
- if (value) {
1910
- if (Array.isArray(value)) {
1911
- if (value[0]) {
1912
- value = value[0];
1913
- }
1914
- }
1915
-
1916
- if (
1917
- Array.isArray(column.nameFrom)
1918
- ) {
1919
- value = column.nameFrom
1920
- .map(
1921
- (nf) =>
1922
- value?.[nf] ?? ''
1923
- )
1924
- .join(' ');
1925
- } else {
1926
- if (
1927
- value &&
1928
- value.hasOwnProperty(
1929
- column.nameFrom
1930
- )
1931
- ) {
1932
- value =
1933
- value[column.nameFrom];
1934
- }
1935
- }
1936
-
1937
- if (
1938
- column.placeholder &&
1939
- column.placeholder !== ''
1940
- ) {
1941
- return (
1942
- <span>
1943
- {column.placeholder}
1944
- </span>
1945
- );
1946
- } else {
1947
- if (
1948
- column.hasOwnProperty(
1949
- 'format'
1950
- )
1951
- ) {
1952
- if (column.format) {
1953
- value =
1954
- moment(
1955
- value
1956
- ).format(
1957
- 'DD-MM-YYYY'
1958
- );
1959
- }
1960
- }
1961
-
1962
- if (typeof value === 'string') {
1963
- return <span>{value}</span>;
1964
- } else {
1965
- return null;
1966
- }
1967
- }
1968
- } else {
1969
- return null;
1970
- }
1971
- },
1972
- };
1973
- case 'relationArray':
1974
- return {
1975
- ...commonProps,
1976
- name: relationName,
1977
- sortable: false,
1978
- filterEditor: filterEditor,
1979
- filterEditorProps: filterEditorProps,
1980
- render: ({ data }) => {
1981
- const relationValue = column.id.reduce(
1982
- (acc, id) =>
1983
- acc === ''
1984
- ? data[id]
1985
- : acc && acc[id]
1986
- ? acc[id]
1987
- : '',
1988
- ''
1989
- );
1990
-
1991
- if (
1992
- relationValue &&
1993
- Array.isArray(relationValue) &&
1994
- relationValue.length > 0
1995
- ) {
1996
- const nameProperties =
1997
- Array.isArray(column.nameFrom)
1998
- ? column.nameFrom
1999
- : [column.nameFrom];
2000
-
2001
- const values = relationValue
2002
- .map((rv) => {
2003
- if (
2004
- column.childId &&
2005
- Array.isArray(
2006
- column.childId
2007
- )
2008
- ) {
2009
- childValue = rv;
2010
-
2011
- column.childId.forEach(
2012
- (a) => {
2013
- if (
2014
- childValue[
2015
- a
2016
- ]
2017
- ) {
2018
- childValue =
2019
- childValue[
2020
- a
2021
- ];
2022
- }
2023
- }
2024
- );
2025
-
2026
- if (childValue) {
2027
- const propertyValues =
2028
- nameProperties
2029
- .map(
2030
- (
2031
- prop
2032
- ) =>
2033
- childValue[
2034
- prop
2035
- ]
2036
- )
2037
- .filter(
2038
- (
2039
- value
2040
- ) =>
2041
- value !==
2042
- undefined &&
2043
- value !==
2044
- null
2045
- );
2046
- return propertyValues.join(
2047
- ' '
2048
- );
2049
- }
2050
- } else {
2051
- const propertyValues =
2052
- nameProperties
2053
- .map(
2054
- (prop) =>
2055
- rv[prop]
2056
- )
2057
- .filter(
2058
- (value) =>
2059
- value !==
2060
- undefined &&
2061
- value !==
2062
- null
2063
- );
2064
- return propertyValues.join(
2065
- ' '
2066
- );
2067
- }
2068
- })
2069
- .filter(
2070
- (value) => value !== ''
2071
- );
2072
-
2073
- // if (values.length > 0) {
2074
- let result = '';
2075
-
2076
- if (
2077
- column.relation?.id &&
2078
- column.relation?.key
2079
- ) {
2080
- const relationValue =
2081
- column.relation.key.reduce(
2082
- (acc, id) =>
2083
- acc === ''
2084
- ? data[id]
2085
- : acc && acc[id]
2086
- ? acc[id]
2087
- : '',
2088
- ''
2089
- );
2090
-
2091
- result = `${
2092
- relationValue[
2093
- column.relation.id
2094
- ]
2095
- }<br />`;
2096
- }
2097
-
2098
- if (
2099
- column.where &&
2100
- column.where.id &&
2101
- column.where.value
2102
- ) {
2103
- if (
2104
- data[column.where.id] ===
2105
- column.where.value
2106
- ) {
2107
- result +=
2108
- values.join('<br />');
2109
- }
2110
- } else {
2111
- result += values.join('<br />');
2112
- }
2113
-
2114
- return <span>{parse(result)}</span>;
2115
- // }
2116
- } else {
2117
- let result = '';
2118
-
2119
- if (
2120
- column.relation?.id &&
2121
- column.relation?.key
2122
- ) {
2123
- const relationValue =
2124
- column.relation.key.reduce(
2125
- (acc, id) =>
2126
- acc === ''
2127
- ? data[id]
2128
- : acc && acc[id]
2129
- ? acc[id]
2130
- : '',
2131
- ''
2132
- );
2133
-
2134
- result =
2135
- relationValue &&
2136
- relationValue[
2137
- column.relation.id
2138
- ]
2139
- ? relationValue[
2140
- column.relation.id
2141
- ]
2142
- : '';
2143
- }
2144
-
2145
- return <span>{parse(result)}</span>;
2146
- }
2147
-
2148
- return null;
2149
- },
2150
- };
2151
- case 'richtext':
2152
- return {
2153
- ...commonProps,
2154
- name: column.id,
2155
- render: ({ data }) => {
2156
- if (data && data[column.id]) {
2157
- return (
2158
- <span>
2159
- {parse(data[column.id])}
2160
- </span>
2161
- );
2162
- } else {
2163
- return null;
2164
- }
2165
- },
2166
- };
2167
- case 'stage':
2168
- return {
2169
- ...commonProps,
2170
- name: column.id,
2171
- sortable: false,
2172
- render: ({ data }) => {
2173
- stage = '';
2174
-
2175
- column.keyIds.forEach((a, b) => {
2176
- if (data[a] === 1) {
2177
- stage = column.valueIds[b];
2178
- }
2179
- });
2180
-
2181
- return <span>{stage}</span>;
2182
- },
2183
- };
2184
- case 'time':
2185
- return {
2186
- ...commonProps,
2187
- name: column.id,
2188
- render: ({ data }) => {
2189
- if (
2190
- data &&
2191
- data[column.id] &&
2192
- moment(data[column.id]).isValid() &&
2193
- moment(data[column.id]).format(
2194
- 'YYYY-MM-DD'
2195
- ) !== '1970-01-01'
2196
- ) {
2197
- data = moment(
2198
- data[column.id]
2199
- ).format(
2200
- column.format
2201
- ? column.format
2202
- : 'hh:mm A'
2203
- );
2204
-
2205
- return <span>{data}</span>;
2206
- } else {
2207
- return null;
2208
- }
2209
- },
2210
- };
2211
- case 'timer':
2212
- return {
2213
- ...commonProps,
2214
- name: column.id,
2215
- render: ({ data }) => {
2216
- if (
2217
- data &&
2218
- data[column.id] &&
2219
- moment(data[column.id]).isValid() &&
2220
- moment(data[column.id]).format(
2221
- 'YYYY-MM-DD'
2222
- ) !== '1970-01-01'
2223
- ) {
2224
- data = moment(
2225
- data[column.id]
2226
- ).format(
2227
- column.format
2228
- ? column.format
2229
- : 'DD-MM-YYYY hh:mm A'
2230
- );
2231
-
2232
- return <span>{data}</span>;
2233
- } else {
2234
- let shouldRenderButton = false;
2235
-
2236
- if (
2237
- !column.hasOwnProperty(
2238
- 'require'
2239
- ) ||
2240
- column.require.length === 0
2241
- ) {
2242
- shouldRenderButton = true;
2243
- } else {
2244
- for (const req of column.require) {
2245
- if (
2246
- req.hasOwnProperty('id')
2247
- ) {
2248
- const hasValue =
2249
- req.hasOwnProperty(
2250
- 'value'
2251
- );
2252
- if (
2253
- (hasValue &&
2254
- data[req.id] ===
2255
- req.value) ||
2256
- (!hasValue &&
2257
- data[req.id])
2258
- ) {
2259
- shouldRenderButton = true;
2260
- } else {
2261
- shouldRenderButton = false;
2262
- break;
2263
- }
2264
- }
2265
- }
2266
- }
2267
-
2268
- if (shouldRenderButton) {
2269
- return (
2270
- <button
2271
- className={styles.btn}
2272
- style={{
2273
- padding:
2274
- '0.2em 1em 0.05em 1em',
2275
- }}
2276
- onClick={(e) => {
2277
- e.stopPropagation();
2278
- e.preventDefault();
2279
-
2280
- // Check if every required field in column.validate exists and is truthy in data
2281
- const isValid =
2282
- column.validate?.every(
2283
- (v) =>
2284
- data[v]
2285
- ) ?? true;
2286
-
2287
- if (isValid) {
2288
- handleTimer(
2289
- data[
2290
- form
2291
- .primaryKey
2292
- ],
2293
- column.id
2294
- );
2295
- } else {
2296
- toast.error(
2297
- 'Please complete the required fields before starting the timer.'
2298
- );
2299
- }
2300
- }}
2301
- >
2302
- <Alarm
2303
- data-tooltip-id="system-tooltip"
2304
- data-tooltip-content={`${column.label} Timer`}
2305
- strokeWidth={2}
2306
- size={18}
2307
- className={
2308
- styles.tdaction
2309
- }
2310
- />
2311
- </button>
2312
- );
2313
- }
2314
-
2315
- return null;
2316
- }
2317
- },
2318
- };
2319
- case 'url':
2320
- return {
2321
- ...commonProps,
2322
- name: column.id,
2323
- render: ({ data }) => {
2324
- if (data && data[column.id]) {
2325
- return (
2326
- <span>
2327
- <a
2328
- href={data[column.id]}
2329
- target="_blank"
2330
- >
2331
- Link
2332
- </a>
2333
- </span>
2334
- );
2335
- } else {
2336
- return null;
2337
- }
2338
- },
2339
- };
2340
- default:
2341
- columnId = Array.isArray(column.id)
2342
- ? column.id.join('-')
2343
- : column.id;
2344
-
2345
- return {
2346
- ...commonProps,
2347
- name: columnId,
2348
- filterEditor: filterEditor,
2349
- filterEditorProps: filterEditorProps,
2350
- render: ({ data }) => {
2351
- if (
2352
- data &&
2353
- data[column.id] &&
2354
- data[column.id] !== ''
2355
- ) {
2356
- return (
2357
- <span>
2358
- {parse(
2359
- String(data[column.id])
2360
- )}
2361
- </span>
2362
- );
2363
- } else {
2364
- return null;
2365
- }
2366
- },
2367
- };
2368
- }
2369
- };
2370
-
2371
- const newColumns = columns.map(renderColumn);
2372
-
2373
- if (settings.length > 0) {
2374
- newColumns.push({
2375
- name: 'setting',
2376
- header: 'Action',
2377
- defaultWidth: 100,
2378
- textAlign: 'center',
2379
- textVerticalAlign:
2380
- style && style.text_vertical_align
2381
- ? style.text_vertical_align
2382
- : 'center',
2383
- render: ({ data }) => {
2384
- return (
2385
- <div className={styles.tdactions}>
2386
- {settings.map((setting) =>
2387
- renderSetting(setting, data)
2388
- )}
2389
- </div>
2390
- );
2391
- },
2392
- });
2393
- }
2394
-
2395
- setGridColumns(newColumns);
2396
-
2397
- const newFilterValue = columns
2398
- .filter((column) => column.filter && column.filter.type) // Only consider columns with a filter type
2399
- .map((column) => {
2400
- // Map these filtered columns to a new object array
2401
- let filterName = '';
2402
- if (Array.isArray(column.id)) {
2403
- filterName = column.id.reduce(
2404
- (acc, id) => acc + `${id}.`,
2405
- ''
2406
- );
2407
- } else {
2408
- if (column.type === 'address') {
2409
- filterName = `address.${column.id}`;
2410
- } else {
2411
- filterName = column.id;
2412
- }
2413
- }
2414
-
2415
- if (column.nameFrom) {
2416
- filterName += column.nameFrom;
2417
- }
2418
-
2419
- let filterValue = '';
2420
-
2421
- if (column.filter.hasOwnProperty('value')) {
2422
- if (
2423
- column.filter.value === '' &&
2424
- column.filter.param === 'profileId' &&
2425
- userProfile?.id
2426
- ) {
2427
- filterValue = userProfile.id;
2428
- } else {
2429
- filterValue = column.filter.value;
2430
- }
2431
- }
2432
-
2433
- return {
2434
- key: column.filter.key
2435
- ? column.filter.key
2436
- : null,
2437
- name: filterName,
2438
- operator: column.filter.operator,
2439
- type: column.filter.type,
2440
- value: filterValue,
2441
- reset: column.filter.reset
2442
- ? column.filter.reset
2443
- : [],
2444
- };
2445
- });
2446
-
2447
- setFilterValue(newFilterValue);
2448
- setSelected([]);
2449
- })
2450
- .catch((error) => {
2451
- console.error('Error in fetching dropdown data: ', error);
2452
- });
2453
- }, [columns, filterDataSource]);
2454
-
2455
- useEffect(() => {
2456
- if (setFilterData) {
2457
- setFilterData(filterValue);
2458
- }
2459
- }, [filterValue]);
2460
-
2461
- const createFilterName = (column) => {
2462
- let filterName = Array.isArray(column.id)
2463
- ? column.id.join('.') + '.'
2464
- : column.id;
2465
-
2466
- if (column.nameFrom) {
2467
- filterName += column.nameFrom;
2468
- }
2469
-
2470
- if (column.jsonData) {
2471
- filterName += column.jsonData;
2472
- }
2473
-
2474
- return filterName;
2475
- };
2476
-
2477
- const updateFilterDataSource = (filterName, data) => {
2478
- const filterIndex = filterDataSource.findIndex(
2479
- (filter) => filter.id === filterName
2480
- );
2481
-
2482
- if (filterIndex >= 0) {
2483
- const updatedFilter = {
2484
- ...filterDataSource[filterIndex],
2485
- dataset: data,
2486
- };
2487
- setFilterDataSource([
2488
- ...filterDataSource.slice(0, filterIndex),
2489
- updatedFilter,
2490
- ...filterDataSource.slice(filterIndex + 1),
2491
- ]);
2492
- } else {
2493
- const newFilter = {
2494
- id: filterName,
2495
- dataset: data,
2496
- };
2497
- setFilterDataSource((prevState) => [...prevState, newFilter]);
2498
- }
2499
- };
2500
-
2501
- useEffect(() => {
2502
- columns.forEach((column) => {
2503
- if (column.filter && column.filter.url) {
2504
- const filterWhere = {
2505
- ...(column.filter.where && {
2506
- where: column.filter.where,
2507
- }),
2508
- ...(column.filter.fields && {
2509
- fields: column.filter.fields,
2510
- }),
2511
- ...(column.filter.order && {
2512
- order: column.filter.order,
2513
- }),
2514
- ...(column.filter.orderBy && {
2515
- orderBy: column.filter.orderBy,
2516
- }),
2517
- };
2518
-
2519
- CustomFetch(
2520
- column.filter.url,
2521
- 'POST',
2522
- filterWhere,
2523
- (res) => {
2524
- const filterName = createFilterName(column);
2525
- updateFilterDataSource(filterName, res.data);
2526
- }
2527
- );
2528
- } else if (column.filter && column.filter.options) {
2529
- const filterName = createFilterName(column);
2530
- updateFilterDataSource(filterName, column.filter.options);
2531
- }
2532
- });
2533
-
2534
- setSelected([]);
2535
- }, [columns]);
2536
-
2537
- // Data Grid Styling
2538
- const [windowHeight, setWindowHeight] = useState(window.innerHeight);
2539
- const [dataCount, setDataCount] = useState(0);
2540
- const [gridStyle, setGridStyle] = useState({
2541
- minHeight:
2542
- gridHeight && gridHeight > 0
2543
- ? gridHeight
2544
- : dataCount > 5
2545
- ? dataCount > 8
2546
- ? windowHeight * 0.7 > 550
2547
- ? windowHeight * 0.7
2548
- : 550
2549
- : 450
2550
- : 400,
2551
- boxShadow: 'none',
2552
- });
2553
- const headerProps = {
2554
- style: style ? style : {},
2555
- };
2556
-
2557
- useEffect(() => {
2558
- const getMinimumHeight = () => {
2559
- if (gridHeight > 0) return gridHeight;
2560
- if (dataCount > 0) {
2561
- if (dataCount <= 5) return 400;
2562
- if (dataCount <= 8) return 450;
2563
- }
2564
- return Math.max(window.innerHeight * 0.7, 550);
2565
- };
2566
-
2567
- const minHeight = getMinimumHeight();
2568
- setGridStyle((prevState) => ({ ...prevState, minHeight }));
2569
-
2570
- if (ajaxSetting?.take >= 35) {
2571
- setLimit(ajaxSetting.take);
2572
- } else {
2573
- const calculateRows = (height) =>
2574
- Math.floor((height - 100) / 40);
2575
-
2576
- const rowCount = calculateRows(minHeight);
2577
- setLimit(rowCount);
2578
- }
2579
- }, [dataCount, gridHeight, window.innerHeight]);
2580
-
2581
- useEffect(() => {
2582
- const handleResize = () => {
2583
- setWindowHeight(window.innerHeight);
2584
- };
2585
-
2586
- window.addEventListener('resize', handleResize);
2587
-
2588
- // Clean up the event listener
2589
- return () => {
2590
- window.removeEventListener('resize', handleResize);
2591
- };
2592
- }, []);
2593
-
2594
- return (
2595
- <>
2596
- {renderSearch()}
2597
- {renderCreateButton()}
2598
- {limit && limit > 0 ? (
2599
- <>
2600
- <ReactDataGrid
2601
- {...tableSetting}
2602
- columns={gridColumns}
2603
- dataSource={dataSource}
2604
- filterValue={filterValue}
2605
- limit={limit}
2606
- enableColumnAutosize={false}
2607
- enableColumnFilterContextMenu={false}
2608
- handle={(ref) =>
2609
- (gridRef.current = ref ? ref.current : null)
2610
- }
2611
- headerProps={headerProps}
2612
- idProperty="id"
2613
- minRowHeight={40}
2614
- onFilterValueChange={(fv) => {
2615
- handleFilterChange(fv, filterValue);
2616
- }}
2617
- onLimitChange={setLimit}
2618
- onSelectionChange={handleSelectionChange}
2619
- onSortInfoChange={handleSort}
2620
- onRenderRow={onRenderRow}
2621
- pagination
2622
- renderRowContextMenu={renderRowContextMenu}
2623
- renderColumnContextMenu={renderColumnContextMenu}
2624
- rowClassName="vs-datagrid--row"
2625
- rowHeight={null}
2626
- selected={selected}
2627
- showZebraRows={true}
2628
- showActiveRowIndicator={false}
2629
- sortInfo={
2630
- ajaxSetting.sortBy && ajaxSetting.sort
2631
- ? {
2632
- name: ajaxSetting.sortBy,
2633
- dir:
2634
- ajaxSetting.sort === 'asc'
2635
- ? 1
2636
- : -1,
2637
- }
2638
- : null
2639
- }
2640
- style={gridStyle}
2641
- />
2642
- </>
2643
- ) : null}
2644
- {audioSource && <audio src={audioSource} ref={audioRef} />}
2645
- <Popup
2646
- open={modalShow}
2647
- onClose={modalClose}
2648
- closeOnDocumentClick={false}
2649
- nested
2650
- >
2651
- <Form
2652
- ajaxSetting={ajaxSetting}
2653
- api={api}
2654
- closeModal={modalClose}
2655
- columnId={formId}
2656
- fetchTable={handleReload}
2657
- formSettings={formData}
2658
- formType={formType}
2659
- gridRef={gridRef}
2660
- mapbox={mapbox}
2661
- modalOpen={modalOpen}
2662
- paramValue={paramValue}
2663
- style={style}
2664
- updateForm={setFormData}
2665
- />
2666
- </Popup>
2667
- <Popup
2668
- open={modalGalleryShow}
2669
- onClose={modalGalleryClose}
2670
- closeOnDocumentClick={false}
2671
- >
2672
- <div
2673
- className={`${styles.modalwrap} ${styles['top--modal']}`}
2674
- >
2675
- <div className={styles.modal}>
2676
- <div className={styles.modal__header}>
2677
- <h1>Gallery</h1>
2678
- <button
2679
- className={styles.modal__close}
2680
- onClick={modalGalleryClose}
2681
- >
2682
- <CircleX strokeWidth={1} size={24} />
2683
- </button>
2684
- </div>
2685
- <div className={styles.modal__content}>
2686
- <div className={styles.formcontainer}>
2687
- <Gallery
2688
- images={galleryData}
2689
- enableImageSelection={false}
2690
- />
2691
- </div>
2692
- </div>
2693
- </div>
2694
- </div>
2695
- </Popup>
2696
- </>
2697
- );
2698
- }
2699
- );
2700
-
2701
- export default DataGrid;