@visns-studio/visns-components 5.3.6 → 5.3.7

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
@@ -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.7",
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, () => ({
@@ -448,9 +455,42 @@ const DataGrid = forwardRef(
448
455
  return 0;
449
456
  };
450
457
 
451
- confirmAlert({
452
- title: 'Delete Item',
453
- message:
458
+ const getDeletedNestedValue = (obj, path) => {
459
+ const value = path
460
+ .split('.')
461
+ .reduce(
462
+ (acc, part) =>
463
+ acc && acc[part] !== undefined
464
+ ? acc[part]
465
+ : undefined,
466
+ obj
467
+ );
468
+
469
+ // Format date if the path contains 'date'
470
+ if (value && path.toLowerCase().includes('date')) {
471
+ const momentDate = moment(value);
472
+ if (
473
+ momentDate.isValid() &&
474
+ momentDate.format('YYYY-MM-DD') !== '1970-01-01'
475
+ ) {
476
+ return momentDate.format('DD-MM-YYYY');
477
+ }
478
+ }
479
+ return value;
480
+ };
481
+
482
+ let confirmMessage = '';
483
+ if (s.labelKey && Array.isArray(s.labelKey)) {
484
+ const values = s.labelKey
485
+ .map((key) => {
486
+ const value = getDeletedNestedValue(d, key);
487
+ return value;
488
+ })
489
+ .filter((val) => val)
490
+ .join(' - ');
491
+ confirmMessage = `Are you sure you want to delete "${values}"?`;
492
+ } else {
493
+ confirmMessage =
454
494
  s.description && s.description !== ''
455
495
  ? s.description
456
496
  : `Are you sure you want to delete ${
@@ -459,7 +499,12 @@ const DataGrid = forwardRef(
459
499
  : d.label
460
500
  ? d.label
461
501
  : 'this item'
462
- }?`,
502
+ }?`;
503
+ }
504
+
505
+ confirmAlert({
506
+ title: 'Delete Item',
507
+ message: confirmMessage,
463
508
  buttons: [
464
509
  {
465
510
  label: 'Yes',
@@ -671,7 +716,10 @@ const DataGrid = forwardRef(
671
716
  } else {
672
717
  const column = rowProps.columns[columnIndex];
673
718
 
674
- if (column.type !== 'dropdown') {
719
+ if (
720
+ column.type !== 'dropdown' &&
721
+ column.type !== 'input_text'
722
+ ) {
675
723
  if (column.id !== '__checkbox-column') {
676
724
  if (column.link && column.link.hasOwnProperty('url')) {
677
725
  if (column.link.url) {
@@ -1223,6 +1271,27 @@ const DataGrid = forwardRef(
1223
1271
  }
1224
1272
  };
1225
1273
 
1274
+ const handleInputUpdate = debounce(
1275
+ (key, url, method, value, inputKey) => {
1276
+ CustomFetch(url, method, { [key]: value }, (res) => {
1277
+ if (res.error === '') {
1278
+ localInputValuesRef.current = {
1279
+ ...localInputValuesRef.current,
1280
+ [inputKey]: value,
1281
+ };
1282
+
1283
+ setLocalInputValues((prev) => ({
1284
+ ...prev,
1285
+ [inputKey]: value,
1286
+ }));
1287
+ } else {
1288
+ toast.error(res.error);
1289
+ }
1290
+ });
1291
+ },
1292
+ 500
1293
+ );
1294
+
1226
1295
  const getDropdownData = async (ids, url, fields) => {
1227
1296
  // Concatenate id array into a single string if it's an array
1228
1297
  const uniqueId = Array.isArray(ids) ? ids.join('') : ids;
@@ -2409,6 +2478,80 @@ const DataGrid = forwardRef(
2409
2478
  }
2410
2479
  },
2411
2480
  };
2481
+ case 'input_text':
2482
+ return {
2483
+ ...commonProps,
2484
+ name: column.id,
2485
+ render: ({ data }) => {
2486
+ const inputKey = `${data.id}-${column.id}`;
2487
+
2488
+ // Use the ref value first, then fall back to data value
2489
+ const currentValue =
2490
+ localInputValuesRef.current[
2491
+ inputKey
2492
+ ] !== undefined
2493
+ ? localInputValuesRef.current[
2494
+ inputKey
2495
+ ]
2496
+ : data[column.id] || '';
2497
+
2498
+ return (
2499
+ <input
2500
+ type="text"
2501
+ name={column.id}
2502
+ value={currentValue}
2503
+ style={{
2504
+ padding: '7px',
2505
+ width: '100%',
2506
+ }}
2507
+ onChange={(e) => {
2508
+ const newValue =
2509
+ e.target.value;
2510
+
2511
+ // Update both state and ref
2512
+ localInputValuesRef.current =
2513
+ {
2514
+ ...localInputValuesRef.current,
2515
+ [inputKey]:
2516
+ newValue,
2517
+ };
2518
+
2519
+ setLocalInputValues(
2520
+ (prev) => ({
2521
+ ...prev,
2522
+ [inputKey]:
2523
+ newValue,
2524
+ })
2525
+ );
2526
+
2527
+ if (
2528
+ column.update?.key &&
2529
+ column.update?.url &&
2530
+ column.update?.method
2531
+ ) {
2532
+ handleInputUpdate(
2533
+ column.update.key,
2534
+ `${column.update.url}/${data.id}`,
2535
+ column.update
2536
+ .method,
2537
+ newValue,
2538
+ inputKey
2539
+ );
2540
+ }
2541
+ }}
2542
+ onBlur={() => {
2543
+ if (
2544
+ column.update?.key &&
2545
+ column.update?.url &&
2546
+ column.update?.method
2547
+ ) {
2548
+ handleInputUpdate.flush();
2549
+ }
2550
+ }}
2551
+ />
2552
+ );
2553
+ },
2554
+ };
2412
2555
  default:
2413
2556
  columnId = Array.isArray(column.id)
2414
2557
  ? column.id.join('-')