@visns-studio/visns-components 5.3.6 → 5.3.8

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.
package/package.json CHANGED
@@ -54,8 +54,8 @@
54
54
  "swapy": "^1.0.5",
55
55
  "truncate": "^3.0.0",
56
56
  "uuid": "^10.0.0",
57
- "validator": "^13.12.0",
58
- "vite": "^5.4.14",
57
+ "validator": "^13.15.0",
58
+ "vite": "^5.4.15",
59
59
  "yarn": "^1.22.22"
60
60
  },
61
61
  "devDependencies": {
@@ -78,7 +78,7 @@
78
78
  "react-dom": "^17.0.0 || ^18.0.0"
79
79
  },
80
80
  "name": "@visns-studio/visns-components",
81
- "version": "5.3.6",
81
+ "version": "5.3.8",
82
82
  "description": "Various packages to assist in the development of our Custom Applications.",
83
83
  "main": "src/index.js",
84
84
  "files": [
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { Link } from 'react-router-dom';
3
3
  import dayjs from 'dayjs';
4
4
  import { CircleChevronRight } from 'akar-icons';
5
+ import parse from 'html-react-parser';
5
6
 
6
7
  function Breadcrumb({ data, page }) {
7
8
  // Function to get nested data, handling array of keys
@@ -33,7 +34,7 @@ function Breadcrumb({ data, page }) {
33
34
  <h1>
34
35
  {page?.parentTitle && page?.parentUrl && (
35
36
  <>
36
- <Link to={page.parentUrl}>{page.parentTitle}</Link>
37
+ <Link to={page.parentUrl}>{parse(page.parentTitle)}</Link>
37
38
  <CircleChevronRight strokeWidth={2} size={18} />
38
39
  </>
39
40
  )}
@@ -46,7 +47,7 @@ function Breadcrumb({ data, page }) {
46
47
  page.parentUrlKey
47
48
  )}`}
48
49
  >
49
- {nestedData}
50
+ {parse(nestedData)}
50
51
  </Link>
51
52
  <CircleChevronRight strokeWidth={2} size={18} />
52
53
  </>
@@ -61,7 +62,7 @@ function Breadcrumb({ data, page }) {
61
62
  : ''
62
63
  }`}
63
64
  >
64
- {page.title}
65
+ {parse(page.title)}
65
66
  </Link>
66
67
  <CircleChevronRight strokeWidth={2} size={18} />
67
68
  </>
@@ -72,10 +73,12 @@ function Breadcrumb({ data, page }) {
72
73
  <>
73
74
  {Array.isArray(page.titleKey) ? (
74
75
  <>
75
- {page.titleText && <span>{page.titleText} </span>}
76
+ {page.titleText && (
77
+ <span>{parse(page.titleText)} </span>
78
+ )}
76
79
  {page.titleKey.map((key, index) => (
77
80
  <span key={index}>
78
- {data[key]}
81
+ {parse(String(data[key] || ''))}
79
82
  {index < page.titleKey.length - 1 && ' '}
80
83
  </span>
81
84
  ))}
@@ -89,7 +92,12 @@ function Breadcrumb({ data, page }) {
89
92
  ? page.titleFormat
90
93
  : 'DD/MM/YYYY'
91
94
  )
92
- : getTitleData(data, page.titleKey)}
95
+ : parse(
96
+ String(
97
+ getTitleData(data, page.titleKey) ||
98
+ ''
99
+ )
100
+ )}
93
101
  </>
94
102
  )}
95
103
  </>
@@ -224,6 +224,13 @@ const DataGrid = forwardRef(
224
224
  const [limit, setLimit] = useState(0);
225
225
  const [search, setSearch] = useState('');
226
226
  const [selected, setSelected] = useState({});
227
+ const [inputDebounceTimers] = useState({});
228
+ const [localInputValues, setLocalInputValues] = useState({});
229
+ const localInputValuesRef = useRef({}); // Add this ref to track values
230
+
231
+ useEffect(() => {
232
+ localInputValuesRef.current = localInputValues;
233
+ }, [localInputValues]);
227
234
 
228
235
  /** Table Functions */
229
236
  useImperativeHandle(ref, () => ({
@@ -235,6 +242,27 @@ const DataGrid = forwardRef(
235
242
  },
236
243
  }));
237
244
 
245
+ const getRowStyle = useCallback(
246
+ (rowProps) => {
247
+ const { data } = rowProps;
248
+
249
+ if (ajaxSetting?.rowColours?.length > 0) {
250
+ const colorConfig = ajaxSetting.rowColours.find(
251
+ (config) => data[config.id] === config.value
252
+ );
253
+
254
+ if (colorConfig) {
255
+ return {
256
+ backgroundColor: colorConfig.colour,
257
+ };
258
+ }
259
+ }
260
+
261
+ return null;
262
+ },
263
+ [ajaxSetting]
264
+ );
265
+
238
266
  const handleDownload = async (d) => {
239
267
  const toastId = toast.loading('Starting download please wait...');
240
268
 
@@ -448,9 +476,42 @@ const DataGrid = forwardRef(
448
476
  return 0;
449
477
  };
450
478
 
451
- confirmAlert({
452
- title: 'Delete Item',
453
- message:
479
+ const getDeletedNestedValue = (obj, path) => {
480
+ const value = path
481
+ .split('.')
482
+ .reduce(
483
+ (acc, part) =>
484
+ acc && acc[part] !== undefined
485
+ ? acc[part]
486
+ : undefined,
487
+ obj
488
+ );
489
+
490
+ // Format date if the path contains 'date'
491
+ if (value && path.toLowerCase().includes('date')) {
492
+ const momentDate = moment(value);
493
+ if (
494
+ momentDate.isValid() &&
495
+ momentDate.format('YYYY-MM-DD') !== '1970-01-01'
496
+ ) {
497
+ return momentDate.format('DD-MM-YYYY');
498
+ }
499
+ }
500
+ return value;
501
+ };
502
+
503
+ let confirmMessage = '';
504
+ if (s.labelKey && Array.isArray(s.labelKey)) {
505
+ const values = s.labelKey
506
+ .map((key) => {
507
+ const value = getDeletedNestedValue(d, key);
508
+ return value;
509
+ })
510
+ .filter((val) => val)
511
+ .join(' - ');
512
+ confirmMessage = `Are you sure you want to delete "${values}"?`;
513
+ } else {
514
+ confirmMessage =
454
515
  s.description && s.description !== ''
455
516
  ? s.description
456
517
  : `Are you sure you want to delete ${
@@ -459,7 +520,12 @@ const DataGrid = forwardRef(
459
520
  : d.label
460
521
  ? d.label
461
522
  : 'this item'
462
- }?`,
523
+ }?`;
524
+ }
525
+
526
+ confirmAlert({
527
+ title: 'Delete Item',
528
+ message: confirmMessage,
463
529
  buttons: [
464
530
  {
465
531
  label: 'Yes',
@@ -671,7 +737,10 @@ const DataGrid = forwardRef(
671
737
  } else {
672
738
  const column = rowProps.columns[columnIndex];
673
739
 
674
- if (column.type !== 'dropdown') {
740
+ if (
741
+ column.type !== 'dropdown' &&
742
+ column.type !== 'input_text'
743
+ ) {
675
744
  if (column.id !== '__checkbox-column') {
676
745
  if (column.link && column.link.hasOwnProperty('url')) {
677
746
  if (column.link.url) {
@@ -1223,6 +1292,27 @@ const DataGrid = forwardRef(
1223
1292
  }
1224
1293
  };
1225
1294
 
1295
+ const handleInputUpdate = debounce(
1296
+ (key, url, method, value, inputKey) => {
1297
+ CustomFetch(url, method, { [key]: value }, (res) => {
1298
+ if (res.error === '') {
1299
+ localInputValuesRef.current = {
1300
+ ...localInputValuesRef.current,
1301
+ [inputKey]: value,
1302
+ };
1303
+
1304
+ setLocalInputValues((prev) => ({
1305
+ ...prev,
1306
+ [inputKey]: value,
1307
+ }));
1308
+ } else {
1309
+ toast.error(res.error);
1310
+ }
1311
+ });
1312
+ },
1313
+ 500
1314
+ );
1315
+
1226
1316
  const getDropdownData = async (ids, url, fields) => {
1227
1317
  // Concatenate id array into a single string if it's an array
1228
1318
  const uniqueId = Array.isArray(ids) ? ids.join('') : ids;
@@ -2409,6 +2499,80 @@ const DataGrid = forwardRef(
2409
2499
  }
2410
2500
  },
2411
2501
  };
2502
+ case 'input_text':
2503
+ return {
2504
+ ...commonProps,
2505
+ name: column.id,
2506
+ render: ({ data }) => {
2507
+ const inputKey = `${data.id}-${column.id}`;
2508
+
2509
+ // Use the ref value first, then fall back to data value
2510
+ const currentValue =
2511
+ localInputValuesRef.current[
2512
+ inputKey
2513
+ ] !== undefined
2514
+ ? localInputValuesRef.current[
2515
+ inputKey
2516
+ ]
2517
+ : data[column.id] || '';
2518
+
2519
+ return (
2520
+ <input
2521
+ type="text"
2522
+ name={column.id}
2523
+ value={currentValue}
2524
+ style={{
2525
+ padding: '7px',
2526
+ width: '100%',
2527
+ }}
2528
+ onChange={(e) => {
2529
+ const newValue =
2530
+ e.target.value;
2531
+
2532
+ // Update both state and ref
2533
+ localInputValuesRef.current =
2534
+ {
2535
+ ...localInputValuesRef.current,
2536
+ [inputKey]:
2537
+ newValue,
2538
+ };
2539
+
2540
+ setLocalInputValues(
2541
+ (prev) => ({
2542
+ ...prev,
2543
+ [inputKey]:
2544
+ newValue,
2545
+ })
2546
+ );
2547
+
2548
+ if (
2549
+ column.update?.key &&
2550
+ column.update?.url &&
2551
+ column.update?.method
2552
+ ) {
2553
+ handleInputUpdate(
2554
+ column.update.key,
2555
+ `${column.update.url}/${data.id}`,
2556
+ column.update
2557
+ .method,
2558
+ newValue,
2559
+ inputKey
2560
+ );
2561
+ }
2562
+ }}
2563
+ onBlur={() => {
2564
+ if (
2565
+ column.update?.key &&
2566
+ column.update?.url &&
2567
+ column.update?.method
2568
+ ) {
2569
+ handleInputUpdate.flush();
2570
+ }
2571
+ }}
2572
+ />
2573
+ );
2574
+ },
2575
+ };
2412
2576
  default:
2413
2577
  columnId = Array.isArray(column.id)
2414
2578
  ? column.id.join('-')
@@ -2716,6 +2880,7 @@ const DataGrid = forwardRef(
2716
2880
  renderColumnContextMenu={renderColumnContextMenu}
2717
2881
  rowClassName="vs-datagrid--row"
2718
2882
  rowHeight={null}
2883
+ rowStyle={getRowStyle}
2719
2884
  selected={selected}
2720
2885
  showZebraRows={true}
2721
2886
  showActiveRowIndicator={false}