react-live-data-table 1.0.19 → 1.1.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.
- package/package.json +1 -1
- package/src/ReactDataTable.jsx +294 -66
package/package.json
CHANGED
package/src/ReactDataTable.jsx
CHANGED
@@ -21,6 +21,10 @@ function ReactDataTable({
|
|
21
21
|
rowStyle = {},
|
22
22
|
rowClassName = "",
|
23
23
|
columnReorder = false,
|
24
|
+
subTableColumns = null, // Array of column definitions for subtable
|
25
|
+
expandedRows = {},
|
26
|
+
onRowExpand = null,
|
27
|
+
subTableWidth = "100%",
|
24
28
|
}) {
|
25
29
|
const tableContainerRef = React.useRef(null);
|
26
30
|
const [data, setData] = React.useState({ pages: [], meta: { totalPages: 1 } });
|
@@ -33,17 +37,103 @@ function ReactDataTable({
|
|
33
37
|
const [startX, setStartX] = useState(null);
|
34
38
|
const [initialWidth, setInitialWidth] = useState(null);
|
35
39
|
const [tableWidth, setTableWidth] = useState(0);
|
36
|
-
|
40
|
+
|
37
41
|
// Column reordering state - only used when columnReorder is true
|
38
42
|
const [orderedColumns, setOrderedColumns] = useState(columns);
|
39
43
|
const [draggedColumn, setDraggedColumn] = useState(null);
|
40
44
|
const [dragOverColumn, setDragOverColumn] = useState(null);
|
41
|
-
|
42
|
-
// Ref to store column widths to ensure persistence during data loading
|
43
|
-
const persistedColumnWidthsRef = React.useRef([]);
|
44
45
|
|
46
|
+
const persistedColumnWidthsRef = React.useRef([]);
|
45
47
|
const flatData = data.pages.flatMap(page => page.data);
|
46
48
|
|
49
|
+
// Helper function to check if a row has subtable data
|
50
|
+
const hasSubTableData = useCallback((row) => {
|
51
|
+
if (!subTableColumns) return false;
|
52
|
+
|
53
|
+
return subTableColumns.some(col => {
|
54
|
+
const value = row[col.accessorKey || col.id];
|
55
|
+
// Check for arrays with content OR non-empty strings
|
56
|
+
return (Array.isArray(value) && value.length > 0) ||
|
57
|
+
(typeof value === 'string' && value.trim() !== '' && value !== '--');
|
58
|
+
});
|
59
|
+
}, [subTableColumns]);
|
60
|
+
|
61
|
+
// Helper function to get subtable rows from main row data
|
62
|
+
const getSubTableRows = useCallback((row) => {
|
63
|
+
if (!subTableColumns || !hasSubTableData(row)) return [];
|
64
|
+
|
65
|
+
// Find the maximum length among all array columns, default to 1 for strings
|
66
|
+
let maxLength = 1; // At least 1 row for string values
|
67
|
+
subTableColumns.forEach(col => {
|
68
|
+
const value = row[col.accessorKey || col.id];
|
69
|
+
if (Array.isArray(value)) {
|
70
|
+
maxLength = Math.max(maxLength, value.length);
|
71
|
+
}
|
72
|
+
});
|
73
|
+
|
74
|
+
// Create rows for subtable
|
75
|
+
const subRows = [];
|
76
|
+
for (let i = 0; i < maxLength; i++) {
|
77
|
+
const subRow = { id: `${row.id}-sub-${i}` };
|
78
|
+
|
79
|
+
subTableColumns.forEach(col => {
|
80
|
+
const value = row[col.accessorKey || col.id];
|
81
|
+
if (Array.isArray(value)) {
|
82
|
+
// For arrays, use the value at index i, or undefined if out of bounds
|
83
|
+
subRow[col.accessorKey || col.id] = i < value.length ? value[i] : undefined;
|
84
|
+
} else {
|
85
|
+
// For strings/non-arrays, use the value only in the first row
|
86
|
+
subRow[col.accessorKey || col.id] = i === 0 ? value : undefined;
|
87
|
+
}
|
88
|
+
});
|
89
|
+
|
90
|
+
subRows.push(subRow);
|
91
|
+
}
|
92
|
+
|
93
|
+
return subRows;
|
94
|
+
}, [subTableColumns, hasSubTableData]);
|
95
|
+
|
96
|
+
const calculateDynamicHeight = useCallback(() => {
|
97
|
+
const expandedCount = Object.values(expandedRows || {}).filter(Boolean).length;
|
98
|
+
|
99
|
+
if (expandedCount === 0) {
|
100
|
+
return height;
|
101
|
+
}
|
102
|
+
|
103
|
+
// Calculate subtable height based on actual data
|
104
|
+
let totalSubTableHeight = 0;
|
105
|
+
Object.keys(expandedRows || {}).forEach(rowId => {
|
106
|
+
if (expandedRows[rowId]) {
|
107
|
+
const row = flatData.find(r => r.id === rowId);
|
108
|
+
if (row) {
|
109
|
+
const subRows = getSubTableRows(row);
|
110
|
+
const headerHeight = 36;
|
111
|
+
const rowsHeight = subRows.length * 32; // Assuming 32px per subtable row
|
112
|
+
totalSubTableHeight += headerHeight + rowsHeight + 20; // +20 for padding
|
113
|
+
}
|
114
|
+
}
|
115
|
+
});
|
116
|
+
|
117
|
+
const baseHeight = typeof height === 'string' ? parseInt(height) : height;
|
118
|
+
return `${Math.max(baseHeight, baseHeight + totalSubTableHeight)}px`;
|
119
|
+
}, [height, expandedRows, flatData, getSubTableRows]);
|
120
|
+
|
121
|
+
const dynamicHeight = calculateDynamicHeight();
|
122
|
+
|
123
|
+
const handleRowExpand = useCallback((rowId) => {
|
124
|
+
const currentExpandedRows = expandedRows || {};
|
125
|
+
const isCurrentlyExpanded = currentExpandedRows[rowId];
|
126
|
+
|
127
|
+
if (isCurrentlyExpanded) {
|
128
|
+
const newExpandedRows = { ...currentExpandedRows };
|
129
|
+
delete newExpandedRows[rowId];
|
130
|
+
onRowExpand?.(newExpandedRows, rowId);
|
131
|
+
} else {
|
132
|
+
const newExpandedRows = { [rowId]: true };
|
133
|
+
onRowExpand?.(newExpandedRows, rowId);
|
134
|
+
}
|
135
|
+
}, [expandedRows, onRowExpand]);
|
136
|
+
|
47
137
|
const checkboxColumn = {
|
48
138
|
id: 'select',
|
49
139
|
size: 50,
|
@@ -113,9 +203,59 @@ function ReactDataTable({
|
|
113
203
|
}
|
114
204
|
};
|
115
205
|
|
116
|
-
|
206
|
+
// Expand/collapse column for sub-tables - keep it similar to checkbox column
|
207
|
+
const expandColumn = {
|
208
|
+
id: 'expand',
|
209
|
+
size: 50,
|
210
|
+
minWidth: 50,
|
211
|
+
resizable: false,
|
212
|
+
reorderable: false,
|
213
|
+
textAlign: "center",
|
214
|
+
header: () => (
|
215
|
+
<div className="flex items-center justify-center h-[40px]">
|
216
|
+
<span className="text-xs text-gray-600">Expand</span>
|
217
|
+
</div>
|
218
|
+
),
|
219
|
+
cell: ({ row }) => {
|
220
|
+
const isExpanded = (expandedRows || {})[row.id];
|
221
|
+
const hasSubData = hasSubTableData(row);
|
222
|
+
|
223
|
+
if (!hasSubData) {
|
224
|
+
return <div className="flex items-center justify-center h-[40px]"></div>;
|
225
|
+
}
|
226
|
+
|
227
|
+
return (
|
228
|
+
<div className="flex items-center justify-center h-[40px]" onClick={(e) => e.stopPropagation()}>
|
229
|
+
<button
|
230
|
+
onClick={(e) => {
|
231
|
+
e.stopPropagation();
|
232
|
+
handleRowExpand(row.id);
|
233
|
+
}}
|
234
|
+
className="w-6 h-6 flex items-center justify-center rounded hover:bg-gray-200 transition-colors"
|
235
|
+
>
|
236
|
+
<svg
|
237
|
+
className={`w-4 h-4 transition-transform ${isExpanded ? 'rotate-90' : ''}`}
|
238
|
+
fill="none"
|
239
|
+
stroke="currentColor"
|
240
|
+
viewBox="0 0 24 24"
|
241
|
+
>
|
242
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
243
|
+
</svg>
|
244
|
+
</button>
|
245
|
+
</div>
|
246
|
+
);
|
247
|
+
}
|
248
|
+
};
|
249
|
+
|
250
|
+
const hasAnySubTableData = subTableColumns && flatData.some(row => hasSubTableData(row));
|
251
|
+
|
252
|
+
const enhancedColumns = (() => {
|
253
|
+
let cols = [];
|
254
|
+
if (showCheckbox) cols.push(checkboxColumn);
|
255
|
+
if (hasAnySubTableData) cols.push(expandColumn);
|
256
|
+
return [...cols, ...orderedColumns];
|
257
|
+
})();
|
117
258
|
|
118
|
-
// Update ordered columns when columns prop changes
|
119
259
|
useEffect(() => {
|
120
260
|
setOrderedColumns(columns);
|
121
261
|
}, [columns]);
|
@@ -127,10 +267,10 @@ function ReactDataTable({
|
|
127
267
|
}
|
128
268
|
}, [selected]);
|
129
269
|
|
130
|
-
// Initialize column widths array
|
270
|
+
// Initialize column widths array - FIXED: Added enhancedColumns dependency
|
131
271
|
useEffect(() => {
|
132
|
-
const allColumns =
|
133
|
-
|
272
|
+
const allColumns = enhancedColumns;
|
273
|
+
|
134
274
|
// If we have persisted widths and the number of columns matches, use those
|
135
275
|
if (persistedColumnWidthsRef.current.length === allColumns.length) {
|
136
276
|
setColumnWidths([...persistedColumnWidthsRef.current]);
|
@@ -143,7 +283,7 @@ function ReactDataTable({
|
|
143
283
|
// Store in our ref for persistence
|
144
284
|
persistedColumnWidthsRef.current = [...initialWidths];
|
145
285
|
}
|
146
|
-
}, [
|
286
|
+
}, [showCheckbox]); // FIXED: Added enhancedColumns dependency
|
147
287
|
|
148
288
|
useEffect(() => {
|
149
289
|
setData({ pages: [], meta: { totalPages: 1 } });
|
@@ -186,7 +326,7 @@ function ReactDataTable({
|
|
186
326
|
|
187
327
|
const handleDrop = (e, dropIndex) => {
|
188
328
|
e.preventDefault();
|
189
|
-
|
329
|
+
|
190
330
|
if (!columnReorder || draggedColumn === null || draggedColumn === dropIndex) {
|
191
331
|
setDraggedColumn(null);
|
192
332
|
setDragOverColumn(null);
|
@@ -201,12 +341,20 @@ function ReactDataTable({
|
|
201
341
|
|
202
342
|
const newColumns = [...enhancedColumns];
|
203
343
|
const draggedColumnData = newColumns[draggedColumn];
|
204
|
-
|
344
|
+
|
205
345
|
newColumns.splice(draggedColumn, 1);
|
206
346
|
const adjustedDropIndex = draggedColumn < dropIndex ? dropIndex - 1 : dropIndex;
|
207
347
|
newColumns.splice(adjustedDropIndex, 0, draggedColumnData);
|
208
348
|
|
209
|
-
|
349
|
+
// FIXED: Updated logic to handle different column types
|
350
|
+
let updatedOrderedColumns;
|
351
|
+
if (showCheckbox && hasAnySubTableData) {
|
352
|
+
updatedOrderedColumns = newColumns.slice(2); // Remove both checkbox and expand columns
|
353
|
+
} else if (showCheckbox || hasAnySubTableData) {
|
354
|
+
updatedOrderedColumns = newColumns.slice(1); // Remove one column (checkbox or expand)
|
355
|
+
} else {
|
356
|
+
updatedOrderedColumns = newColumns;
|
357
|
+
}
|
210
358
|
setOrderedColumns(updatedOrderedColumns);
|
211
359
|
|
212
360
|
// Reorder column widths
|
@@ -217,8 +365,6 @@ function ReactDataTable({
|
|
217
365
|
setColumnWidths(newColumnWidths);
|
218
366
|
persistedColumnWidthsRef.current = newColumnWidths;
|
219
367
|
|
220
|
-
// onColumnReorder?.(updatedOrderedColumns);
|
221
|
-
|
222
368
|
setDraggedColumn(null);
|
223
369
|
setDragOverColumn(null);
|
224
370
|
};
|
@@ -229,17 +375,12 @@ function ReactDataTable({
|
|
229
375
|
const delta = e.clientX - startX;
|
230
376
|
const newWidth = Math.max(enhancedColumns[resizingIndex]?.minWidth || 80, initialWidth + delta);
|
231
377
|
|
232
|
-
// Create a new array of column widths with the updated width
|
233
378
|
const newColumnWidths = [...columnWidths];
|
234
379
|
newColumnWidths[resizingIndex] = newWidth;
|
235
380
|
|
236
|
-
// Update the column widths state
|
237
381
|
setColumnWidths(newColumnWidths);
|
238
|
-
|
239
|
-
// Update our persisted ref to maintain widths during pagination
|
240
382
|
persistedColumnWidthsRef.current = newColumnWidths;
|
241
383
|
|
242
|
-
// Recalculate table width based on the new column widths
|
243
384
|
const newTableWidth = newColumnWidths.reduce((sum, width) => sum + width, 0);
|
244
385
|
setTableWidth(newTableWidth);
|
245
386
|
}, [resizingIndex, startX, initialWidth, enhancedColumns, columnWidths]);
|
@@ -250,7 +391,6 @@ function ReactDataTable({
|
|
250
391
|
setInitialWidth(null);
|
251
392
|
}, []);
|
252
393
|
|
253
|
-
// Add resize event listeners
|
254
394
|
useEffect(() => {
|
255
395
|
if (resizingIndex !== null) {
|
256
396
|
document.addEventListener('mousemove', handleMouseMove);
|
@@ -299,7 +439,6 @@ function ReactDataTable({
|
|
299
439
|
limit: defaultLimit
|
300
440
|
});
|
301
441
|
|
302
|
-
// Update the data but maintain our column widths
|
303
442
|
setData(prev => ({
|
304
443
|
pages: [...prev.pages, nextData],
|
305
444
|
meta: nextData.meta
|
@@ -423,7 +562,7 @@ function ReactDataTable({
|
|
423
562
|
|
424
563
|
{
|
425
564
|
flatData.length === 0 && !loading ? (
|
426
|
-
<div className="flex items-center justify-center" style={{ height }}>
|
565
|
+
<div className="flex items-center justify-center" style={{ height: dynamicHeight }}>
|
427
566
|
<div className="text-gray-500">
|
428
567
|
{emptyText || 'No data available'}
|
429
568
|
</div>
|
@@ -433,13 +572,18 @@ function ReactDataTable({
|
|
433
572
|
<div
|
434
573
|
ref={tableContainerRef}
|
435
574
|
className="overflow-auto w-full"
|
436
|
-
style={{
|
575
|
+
style={{
|
576
|
+
maxHeight: dynamicHeight,
|
577
|
+
height: dynamicHeight
|
578
|
+
}}
|
437
579
|
onScroll={(e) => handleScroll(e.currentTarget)}
|
438
580
|
>
|
439
581
|
<table
|
440
582
|
className="w-full border-collapse"
|
441
583
|
style={{
|
442
584
|
tableLayout: 'fixed',
|
585
|
+
width: `${tableWidth}px`, // FIXED: Use calculated table width for scrolling
|
586
|
+
minWidth: '100%'
|
443
587
|
}}
|
444
588
|
>
|
445
589
|
<thead
|
@@ -455,16 +599,14 @@ function ReactDataTable({
|
|
455
599
|
return (
|
456
600
|
<th
|
457
601
|
key={column.accessorKey || column.id}
|
458
|
-
className={`text-left font-normal h-[40px] border-b border-t border-solid border-[#e4e3e2] relative select-none ${
|
459
|
-
|
460
|
-
|
461
|
-
isDropTarget ? 'bg-blue-400' : ''
|
462
|
-
}`}
|
602
|
+
className={`text-left font-normal h-[40px] border-b border-t border-solid border-[#e4e3e2] relative select-none ${columnIndex < enhancedColumns.length - 1 ? 'border-r' : ''
|
603
|
+
} ${isReorderable ? 'cursor-move' : ''} ${isDropTarget ? 'bg-blue-400' : ''
|
604
|
+
}`}
|
463
605
|
style={{
|
464
606
|
width: `${width}px`,
|
465
607
|
minWidth: `${width}px`,
|
466
608
|
maxWidth: `${width}px`,
|
467
|
-
textAlign: column.textAlign,
|
609
|
+
textAlign: column.textAlign || "left",
|
468
610
|
}}
|
469
611
|
draggable={isReorderable}
|
470
612
|
onDragStart={(e) => handleDragStart(e, columnIndex)}
|
@@ -480,9 +622,8 @@ function ReactDataTable({
|
|
480
622
|
{/* Resize handle - Only show if column is resizable */}
|
481
623
|
{column.resizable !== false && (
|
482
624
|
<div
|
483
|
-
className={`absolute top-0 right-0 h-full w-4 flex items-center justify-center group ${
|
484
|
-
|
485
|
-
} transition-colors duration-200`}
|
625
|
+
className={`absolute top-0 right-0 h-full w-4 flex items-center justify-center group ${resizingIndex === columnIndex ? 'bg-blue-100' : 'hover:bg-blue-100'
|
626
|
+
} transition-colors duration-200`}
|
486
627
|
onMouseDown={(e) => handleResizeStart(e, columnIndex)}
|
487
628
|
style={{
|
488
629
|
touchAction: 'none',
|
@@ -501,41 +642,128 @@ function ReactDataTable({
|
|
501
642
|
{flatData.length > 0 ? (
|
502
643
|
flatData.map((row, rowIndex) => {
|
503
644
|
const isLastRow = rowIndex === flatData.length - 1;
|
645
|
+
const isExpanded = (expandedRows || {})[row.id];
|
646
|
+
const subRows = getSubTableRows(row);
|
647
|
+
|
504
648
|
return (
|
505
|
-
<
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
649
|
+
<React.Fragment key={row.id}>
|
650
|
+
<tr
|
651
|
+
className={`react-live-data-table-row-${rowIndex} border-t ${isLastRow ? 'border-b' : ''} border-gray-200 hover:bg-[#dee1f2] ${selectedRows[row.id] ? 'bg-[#dee1f2]' : ''} ${rowClassName} cursor-pointer`}
|
652
|
+
style={{
|
653
|
+
height: `${rowHeights}px`,
|
654
|
+
...rowStyle,
|
655
|
+
...(typeof rowStyle === 'function' ? rowStyle(row, rowIndex) : {})
|
656
|
+
}}
|
657
|
+
onClick={() => handleRowClick(row, rowIndex, flatData)}
|
658
|
+
>
|
659
|
+
{enhancedColumns.map((column, columnIndex) => {
|
660
|
+
const width = columnWidths[columnIndex] || column.size || column.minWidth || 150;
|
661
|
+
|
662
|
+
return (
|
663
|
+
<td
|
664
|
+
key={column.accessorKey || column.id}
|
665
|
+
className={`text-left font-normal ${columnIndex < enhancedColumns.length - 1 ? 'border-r' : ''
|
666
|
+
} ${column?.cellProps?.className || ''}`}
|
667
|
+
style={{
|
668
|
+
width: `${width}px`,
|
669
|
+
minWidth: `${width}px`,
|
670
|
+
maxWidth: `${width}px`,
|
671
|
+
textAlign: column.textAlign || "left",
|
672
|
+
...column?.cellProps?.style,
|
673
|
+
overflow: 'hidden',
|
674
|
+
textOverflow: 'ellipsis',
|
675
|
+
whiteSpace: 'nowrap'
|
676
|
+
}}
|
677
|
+
>
|
678
|
+
{typeof column.cell === 'function' ? column.cell({ row }) : null}
|
679
|
+
</td>
|
680
|
+
);
|
681
|
+
})}
|
682
|
+
</tr>
|
683
|
+
{/* Subtable row */}
|
684
|
+
{isExpanded && subRows.length > 0 && (
|
685
|
+
<tr className="bg-gray-50 border-b border-gray-200">
|
686
|
+
<td colSpan={enhancedColumns.length} className="p-0">
|
687
|
+
<div className="bg-white border border-gray-200" style={{ width: subTableWidth, maxWidth: '100%' }}>
|
688
|
+
<div
|
689
|
+
className="sub-table-container"
|
690
|
+
style={{
|
691
|
+
maxHeight: "300px",
|
692
|
+
width: '100%',
|
693
|
+
overflow: 'auto',
|
694
|
+
scrollbarWidth: 'thin',
|
695
|
+
scrollbarColor: '#cbd5e0 #f7fafc',
|
696
|
+
}}
|
697
|
+
>
|
698
|
+
<style>
|
699
|
+
{`
|
700
|
+
.sub-table-container::-webkit-scrollbar {
|
701
|
+
width: 6px;
|
702
|
+
height: 6px;
|
703
|
+
}
|
704
|
+
.sub-table-container::-webkit-scrollbar-track {
|
705
|
+
background: #f7fafc;
|
706
|
+
border-radius: 3px;
|
707
|
+
}
|
708
|
+
.sub-table-container::-webkit-scrollbar-thumb {
|
709
|
+
background: #cbd5e0;
|
710
|
+
border-radius: 3px;
|
711
|
+
}
|
712
|
+
.sub-table-container::-webkit-scrollbar-thumb:hover {
|
713
|
+
background: #a0aec0;
|
714
|
+
}
|
715
|
+
`}
|
716
|
+
</style>
|
717
|
+
<table className="w-full" style={{ tableLayout: 'fixed' }}>
|
718
|
+
<thead className="bg-gray-100 sticky top-0 z-10">
|
719
|
+
<tr>
|
720
|
+
{subTableColumns.map((col, colIndex) => {
|
721
|
+
return (
|
722
|
+
<th
|
723
|
+
key={col.id || col.accessorKey || colIndex}
|
724
|
+
className={`px-4 py-2 text-left text-sm font-medium text-black border-b border-gray-200 ${colIndex < subTableColumns.length - 1 ? 'border-r border-gray-200' : ''
|
725
|
+
}`}
|
726
|
+
style={{
|
727
|
+
width: col.size ? `${col.size}px` : "auto",
|
728
|
+
minWidth: col.minWidth ? `${col.minWidth}px` : "80px",
|
729
|
+
}}
|
730
|
+
>
|
731
|
+
{typeof col.header === 'function' ? col.header() : (col.header || col.name)}
|
732
|
+
</th>
|
733
|
+
|
734
|
+
);
|
735
|
+
})}
|
736
|
+
</tr>
|
737
|
+
</thead>
|
738
|
+
<tbody>
|
739
|
+
{subRows.map((subRow, subRowIndex) => (
|
740
|
+
<tr key={subRow.id} className="border-b border-gray-100 hover:bg-gray-50">
|
741
|
+
{subTableColumns.map((col, colIndex) => {
|
742
|
+
return (
|
743
|
+
<td
|
744
|
+
key={col.id || col.accessorKey || colIndex}
|
745
|
+
className={`px-4 py-2 text-sm text-gray-900 ${colIndex < subTableColumns.length - 1 ? 'border-r border-gray-200' : ''
|
746
|
+
}`}
|
747
|
+
style={{
|
748
|
+
width: col.size ? `${col.size}px` : "auto",
|
749
|
+
minWidth: col.minWidth ? `${col.minWidth}px` : "80px",
|
750
|
+
}}
|
751
|
+
>
|
752
|
+
{col.cell ? col.cell({ row: subRow }) : subRow[col.accessorKey || col.id]}
|
753
|
+
</td>
|
754
|
+
|
755
|
+
);
|
756
|
+
})}
|
757
|
+
</tr>
|
758
|
+
))}
|
759
|
+
</tbody>
|
760
|
+
</table>
|
761
|
+
</div>
|
762
|
+
</div>
|
535
763
|
</td>
|
536
|
-
|
537
|
-
|
538
|
-
</
|
764
|
+
</tr>
|
765
|
+
)}
|
766
|
+
</React.Fragment>
|
539
767
|
);
|
540
768
|
})
|
541
769
|
) : (
|