@visns-studio/visns-components 1.2.8 → 1.2.10

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