@visns-studio/visns-components 1.2.9 → 1.3.1

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