@visns-studio/visns-components 5.11.20 → 5.11.21

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
@@ -87,7 +87,7 @@
87
87
  "react-dom": "^17.0.0 || ^18.0.0"
88
88
  },
89
89
  "name": "@visns-studio/visns-components",
90
- "version": "5.11.20",
90
+ "version": "5.11.21",
91
91
  "description": "Various packages to assist in the development of our Custom Applications.",
92
92
  "main": "src/index.js",
93
93
  "files": [
@@ -110,6 +110,7 @@ import {
110
110
  renderCreatedByColumn,
111
111
  renderDateRangeColumn,
112
112
  renderStageCounterColumn,
113
+ renderGalleryColumn,
113
114
  } from './columns/ColumnRenderers.jsx';
114
115
  import _ from 'lodash';
115
116
 
@@ -2549,6 +2550,14 @@ const DataGrid = forwardRef(
2549
2550
  column,
2550
2551
  commonProps,
2551
2552
  });
2553
+ case 'gallery':
2554
+ return renderGalleryColumn({
2555
+ column,
2556
+ commonProps,
2557
+ modalGalleryOpen,
2558
+ setGalleryData,
2559
+ setCurrentItem,
2560
+ });
2552
2561
  case 'image':
2553
2562
  return renderImageColumn({
2554
2563
  column,
@@ -1424,6 +1424,163 @@ export const renderDateRangeColumn = ({
1424
1424
  };
1425
1425
 
1426
1426
  // Stage Counter Column Renderer
1427
+ // Gallery Column Renderer
1428
+ export const renderGalleryColumn = ({
1429
+ column,
1430
+ commonProps,
1431
+ modalGalleryOpen,
1432
+ setGalleryData,
1433
+ setCurrentItem,
1434
+ }) => {
1435
+ return {
1436
+ ...commonProps,
1437
+ name: column.id,
1438
+ sortable: false,
1439
+ render: ({ data }) => {
1440
+ // Function to access nested property using a series of keys
1441
+ const getNestedValue = (data, keys) =>
1442
+ keys.reduce(
1443
+ (currentValue, key) =>
1444
+ currentValue && currentValue[key] !== undefined
1445
+ ? currentValue[key]
1446
+ : undefined,
1447
+ data
1448
+ );
1449
+
1450
+ // Get the images array from the nested structure
1451
+ const imagesArray = column.relation
1452
+ ? getNestedValue(data, column.relation)
1453
+ : data[column.id];
1454
+
1455
+ // Check if we have valid image data
1456
+ if (!imagesArray || !Array.isArray(imagesArray) || imagesArray.length === 0) {
1457
+ return (
1458
+ <div style={{
1459
+ display: 'flex',
1460
+ alignItems: 'center',
1461
+ justifyContent: 'center',
1462
+ height: '40px',
1463
+ color: '#999',
1464
+ fontSize: '12px'
1465
+ }}>
1466
+ No images
1467
+ </div>
1468
+ );
1469
+ }
1470
+
1471
+ const maxThumbnails = column.maxThumbnails || 3;
1472
+ const displayImages = imagesArray.slice(0, maxThumbnails);
1473
+ const remainingCount = imagesArray.length - maxThumbnails;
1474
+
1475
+ const handleGalleryClick = (e) => {
1476
+ e.stopPropagation();
1477
+ e.preventDefault();
1478
+
1479
+ // Prepare gallery data in the format expected by the modal
1480
+ const galleryData = imagesArray.map((item) => ({
1481
+ src: item[column.key],
1482
+ caption: item[column.captionKey || 'file_name'],
1483
+ width: 320,
1484
+ height: 240,
1485
+ }));
1486
+
1487
+ // Set gallery data and current item
1488
+ setGalleryData(galleryData);
1489
+ setCurrentItem({
1490
+ data: data,
1491
+ settings: {
1492
+ relation: column.relation,
1493
+ key: column.key,
1494
+ captionKey: column.captionKey || 'file_name'
1495
+ }
1496
+ });
1497
+
1498
+ // Open the gallery modal
1499
+ modalGalleryOpen();
1500
+ };
1501
+
1502
+ return (
1503
+ <div
1504
+ onClick={handleGalleryClick}
1505
+ style={{
1506
+ display: 'flex',
1507
+ flexDirection: 'column',
1508
+ alignItems: 'flex-start',
1509
+ gap: '6px',
1510
+ cursor: 'pointer',
1511
+ padding: '6px',
1512
+ borderRadius: '4px',
1513
+ transition: 'background-color 0.2s',
1514
+ width: '100%',
1515
+ height: '100%',
1516
+ minHeight: '60px',
1517
+ }}
1518
+ onMouseEnter={(e) => {
1519
+ e.target.style.backgroundColor = '#f0f0f0';
1520
+ }}
1521
+ onMouseLeave={(e) => {
1522
+ e.target.style.backgroundColor = 'transparent';
1523
+ }}
1524
+ >
1525
+ {/* Thumbnail images */}
1526
+ <div
1527
+ style={{
1528
+ display: 'flex',
1529
+ gap: '4px',
1530
+ flexWrap: 'wrap',
1531
+ }}
1532
+ >
1533
+ {displayImages.map((image, index) => {
1534
+ const imageUrl = image[column.key];
1535
+ if (!imageUrl) return null;
1536
+
1537
+ return (
1538
+ <div
1539
+ key={index}
1540
+ style={{
1541
+ width: '28px',
1542
+ height: '28px',
1543
+ borderRadius: '3px',
1544
+ overflow: 'hidden',
1545
+ border: '1px solid #ddd',
1546
+ flexShrink: 0,
1547
+ }}
1548
+ >
1549
+ <img
1550
+ src={imageUrl}
1551
+ alt={image[column.captionKey || 'file_name'] || `Image ${index + 1}`}
1552
+ style={{
1553
+ width: '100%',
1554
+ height: '100%',
1555
+ objectFit: 'cover',
1556
+ }}
1557
+ onError={(e) => {
1558
+ e.target.style.display = 'none';
1559
+ }}
1560
+ />
1561
+ </div>
1562
+ );
1563
+ })}
1564
+ </div>
1565
+
1566
+ {/* Count badge */}
1567
+ <div
1568
+ style={{
1569
+ fontSize: '11px',
1570
+ color: '#666',
1571
+ fontWeight: '500',
1572
+ lineHeight: '1.2',
1573
+ }}
1574
+ >
1575
+ {imagesArray.length} {imagesArray.length === 1 ? 'image' : 'images'}
1576
+ {remainingCount > 0 && ` (+${remainingCount})`}
1577
+ </div>
1578
+ </div>
1579
+ );
1580
+ },
1581
+ };
1582
+ };
1583
+
1427
1584
  export const renderStageCounterColumn = ({ column, commonProps, navigate }) => {
1428
1585
  return {
1429
1586
  ...commonProps,