@onehat/ui 0.4.77 → 0.4.78
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/Components/Editor/AttachmentDirectoriesEditor.js +51 -0
- package/src/Components/Editor/AttachmentsEditor.js +81 -0
- package/src/Components/Form/Field/Combo/AttachmentDirectoriesCombo.js +20 -0
- package/src/Components/Form/Field/Combo/AttachmentDirectoriesComboEditor.js +22 -0
- package/src/Components/Form/Field/Combo/AttachmentsCombo.js +20 -0
- package/src/Components/Form/Field/Combo/AttachmentsComboEditor.js +22 -0
- package/src/Components/Form/Field/Tag/AttachmentDirectoriesTag.js +22 -0
- package/src/Components/Form/Field/Tag/AttachmentDirectoriesTagEditor.js +22 -0
- package/src/Components/Form/Field/Tag/AttachmentsTag.js +22 -0
- package/src/Components/Form/Field/Tag/AttachmentsTagEditor.js +22 -0
- package/src/Components/Form/Form.js +17 -17
- package/src/Components/Grid/AttachmentDirectoriesFilteredGrid.js +17 -0
- package/src/Components/Grid/AttachmentDirectoriesFilteredGridEditor.js +17 -0
- package/src/Components/Grid/AttachmentDirectoriesFilteredInlineGridEditor.js +17 -0
- package/src/Components/Grid/AttachmentDirectoriesFilteredSideGridEditor.js +17 -0
- package/src/Components/Grid/AttachmentDirectoriesGrid.js +20 -0
- package/src/Components/Grid/AttachmentDirectoriesGridEditor.js +27 -0
- package/src/Components/Grid/AttachmentDirectoriesInlineGridEditor.js +25 -0
- package/src/Components/Grid/AttachmentDirectoriesSideGridEditor.js +24 -0
- package/src/Components/Grid/AttachmentsFilteredGrid.js +17 -0
- package/src/Components/Grid/AttachmentsFilteredGridEditor.js +17 -0
- package/src/Components/Grid/AttachmentsFilteredInlineGridEditor.js +17 -0
- package/src/Components/Grid/AttachmentsFilteredSideGridEditor.js +17 -0
- package/src/Components/Grid/AttachmentsGrid.js +20 -0
- package/src/Components/Grid/AttachmentsGridEditor.js +27 -0
- package/src/Components/Grid/AttachmentsInlineGridEditor.js +25 -0
- package/src/Components/Grid/AttachmentsSideGridEditor.js +24 -0
- package/src/Components/Grid/Columns/AttachmentDirectoriesGridColumns.js +32 -0
- package/src/Components/Grid/Columns/AttachmentsGridColumns.js +133 -0
- package/src/Components/Grid/Grid.js +193 -20
- package/src/Components/Grid/GridHeaderRow.js +10 -17
- package/src/Components/Grid/GridRow.js +49 -22
- package/src/Components/Grid/RowHandle.js +8 -6
- package/src/Components/Hoc/withEditor.js +1 -1
- package/src/Components/Hoc/withPdfButtons.js +1 -1
- package/src/Components/Hoc/withSelection.js +26 -4
- package/src/Components/Layout/AsyncOperation.js +299 -195
- package/src/Components/Messages/GlobalModals.js +1 -2
- package/src/Components/Panel/Panel.js +14 -2
- package/src/Components/Panel/TabPanel.js +1 -1
- package/src/Components/Panel/TreePanel.js +1 -1
- package/src/Components/Report/Report.js +106 -17
- package/src/Components/Toolbar/PaginationToolbar.js +4 -3
- package/src/Components/Toolbar/Toolbar.js +6 -3
- package/src/Components/Tree/Tree.js +218 -147
- package/src/Components/Tree/TreeNode.js +20 -13
- package/src/Components/Window/AttachmentDirectoriesEditorWindow.js +34 -0
- package/src/Components/Window/AttachmentsEditorWindow.js +34 -0
- package/src/Components/index.js +92 -1
- package/src/Constants/Attachments.js +2 -0
- package/src/Constants/Dates.js +2 -2
- package/src/Constants/Progress.js +5 -1
- package/src/Models/Schemas/AttachmentDirectories.js +66 -0
- package/src/Models/Schemas/Attachments.js +88 -0
- package/src/Models/Slices/SystemSlice.js +220 -0
- package/src/PlatformImports/Web/Attachments.js +783 -145
- package/src/Styles/Global.css +7 -2
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COPYRIGHT NOTICE
|
|
3
|
+
* This file is categorized as "Custom Source Code"
|
|
4
|
+
* and is subject to the terms and conditions defined in the
|
|
5
|
+
* "LICENSE.txt" file, which is part of this source code package.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
SELECTION_MODE_SINGLE,
|
|
10
|
+
} from '../../Constants/Selection.js';
|
|
11
|
+
import { InlineGridEditor } from './Grid.js';
|
|
12
|
+
import AttachmentsGridColumns from './Columns/AttachmentsGridColumns.js';
|
|
13
|
+
|
|
14
|
+
export default function AttachmentsInlineGridEditor(props) {
|
|
15
|
+
return <InlineGridEditor
|
|
16
|
+
reference="AttachmentsInlineGridEditor"
|
|
17
|
+
model="Attachments"
|
|
18
|
+
usePermissions={true}
|
|
19
|
+
selectionMode={SELECTION_MODE_SINGLE}
|
|
20
|
+
columnsConfig={AttachmentsGridColumns}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
{...props}
|
|
24
|
+
/>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COPYRIGHT NOTICE
|
|
3
|
+
* This file is categorized as "Custom Source Code"
|
|
4
|
+
* and is subject to the terms and conditions defined in the
|
|
5
|
+
* "LICENSE.txt" file, which is part of this source code package.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { SideGridEditor } from './Grid.js';
|
|
9
|
+
import AttachmentsEditor from '../Editor/AttachmentsEditor.js';
|
|
10
|
+
import AttachmentsGridColumns from './Columns/AttachmentsGridColumns.js';
|
|
11
|
+
|
|
12
|
+
export default function AttachmentsSideGridEditor(props) {
|
|
13
|
+
return <SideGridEditor
|
|
14
|
+
reference="AttachmentsSideGridEditor"
|
|
15
|
+
model="Attachments"
|
|
16
|
+
usePermissions={true}
|
|
17
|
+
isCollapsible={false}
|
|
18
|
+
Editor={AttachmentsEditor}
|
|
19
|
+
columnsConfig={AttachmentsGridColumns}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
{...props}
|
|
23
|
+
/>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export default [
|
|
2
|
+
{
|
|
3
|
+
"id": "attachment_directories__name",
|
|
4
|
+
"header": "Name",
|
|
5
|
+
"fieldName": "attachment_directories__name",
|
|
6
|
+
"isSortable": true,
|
|
7
|
+
"isEditable": true,
|
|
8
|
+
"isReorderable": true,
|
|
9
|
+
"isResizable": true,
|
|
10
|
+
"w": 150
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"id": "attachment_directories__model",
|
|
14
|
+
"header": "Model",
|
|
15
|
+
"fieldName": "attachment_directories__model",
|
|
16
|
+
"isSortable": true,
|
|
17
|
+
"isEditable": true,
|
|
18
|
+
"isReorderable": true,
|
|
19
|
+
"isResizable": true,
|
|
20
|
+
"w": 150
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": "attachment_directories__modelid",
|
|
24
|
+
"header": "Modelid",
|
|
25
|
+
"fieldName": "attachment_directories__modelid",
|
|
26
|
+
"isSortable": true,
|
|
27
|
+
"isEditable": true,
|
|
28
|
+
"isReorderable": true,
|
|
29
|
+
"isResizable": true,
|
|
30
|
+
"w": 100
|
|
31
|
+
}
|
|
32
|
+
];
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
export default [
|
|
2
|
+
{
|
|
3
|
+
"id": "attachments__model_display",
|
|
4
|
+
"header": "Model Display",
|
|
5
|
+
"fieldName": "attachments__model_display",
|
|
6
|
+
"isSortable": false,
|
|
7
|
+
"isEditable": false,
|
|
8
|
+
"isReorderable": true,
|
|
9
|
+
"isResizable": true,
|
|
10
|
+
"w": 200
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"id": "attachments__size_formatted",
|
|
14
|
+
"header": "Size Formatted",
|
|
15
|
+
"fieldName": "attachments__size_formatted",
|
|
16
|
+
"isSortable": false,
|
|
17
|
+
"isEditable": false,
|
|
18
|
+
"isReorderable": true,
|
|
19
|
+
"isResizable": true,
|
|
20
|
+
"w": 200
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": "attachments__info",
|
|
24
|
+
"header": "Info",
|
|
25
|
+
"fieldName": "attachments__info",
|
|
26
|
+
"isSortable": false,
|
|
27
|
+
"isEditable": false,
|
|
28
|
+
"isReorderable": true,
|
|
29
|
+
"isResizable": true,
|
|
30
|
+
"w": 200
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": "attachments__uri",
|
|
34
|
+
"header": "Uri",
|
|
35
|
+
"fieldName": "attachments__uri",
|
|
36
|
+
"isSortable": false,
|
|
37
|
+
"isEditable": false,
|
|
38
|
+
"isReorderable": true,
|
|
39
|
+
"isResizable": true,
|
|
40
|
+
"w": 200
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"id": "attachments__attachment_directory_id",
|
|
44
|
+
"header": "Attachment Directory",
|
|
45
|
+
"fieldName": "attachment_directories__name",
|
|
46
|
+
"isSortable": true,
|
|
47
|
+
"isEditable": true,
|
|
48
|
+
"isReorderable": true,
|
|
49
|
+
"isResizable": true,
|
|
50
|
+
"w": 100,
|
|
51
|
+
"editField": "attachments__attachment_directory_id"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"id": "attachments__abs_path",
|
|
55
|
+
"header": "Abs Path",
|
|
56
|
+
"fieldName": "attachments__abs_path",
|
|
57
|
+
"isSortable": false,
|
|
58
|
+
"isEditable": false,
|
|
59
|
+
"isReorderable": true,
|
|
60
|
+
"isResizable": true,
|
|
61
|
+
"w": 200
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"id": "attachments__model",
|
|
65
|
+
"header": "Model",
|
|
66
|
+
"fieldName": "attachments__model",
|
|
67
|
+
"isSortable": true,
|
|
68
|
+
"isEditable": true,
|
|
69
|
+
"isReorderable": true,
|
|
70
|
+
"isResizable": true,
|
|
71
|
+
"w": 200
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"id": "attachments__modelid",
|
|
75
|
+
"header": "Modelid",
|
|
76
|
+
"fieldName": "attachments__modelid",
|
|
77
|
+
"isSortable": true,
|
|
78
|
+
"isEditable": true,
|
|
79
|
+
"isReorderable": true,
|
|
80
|
+
"isResizable": true,
|
|
81
|
+
"w": 100
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"id": "attachments__uuid",
|
|
85
|
+
"header": "Uuid",
|
|
86
|
+
"fieldName": "attachments__uuid",
|
|
87
|
+
"isSortable": true,
|
|
88
|
+
"isEditable": true,
|
|
89
|
+
"isReorderable": true,
|
|
90
|
+
"isResizable": true,
|
|
91
|
+
"w": 150
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"id": "attachments__path",
|
|
95
|
+
"header": "Path",
|
|
96
|
+
"fieldName": "attachments__path",
|
|
97
|
+
"isSortable": true,
|
|
98
|
+
"isEditable": true,
|
|
99
|
+
"isReorderable": true,
|
|
100
|
+
"isResizable": true,
|
|
101
|
+
"w": 200
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"id": "attachments__filename",
|
|
105
|
+
"header": "Filename",
|
|
106
|
+
"fieldName": "attachments__filename",
|
|
107
|
+
"isSortable": true,
|
|
108
|
+
"isEditable": true,
|
|
109
|
+
"isReorderable": true,
|
|
110
|
+
"isResizable": true,
|
|
111
|
+
"w": 150
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"id": "attachments__mimetype",
|
|
115
|
+
"header": "Mimetype",
|
|
116
|
+
"fieldName": "attachments__mimetype",
|
|
117
|
+
"isSortable": true,
|
|
118
|
+
"isEditable": true,
|
|
119
|
+
"isReorderable": true,
|
|
120
|
+
"isResizable": true,
|
|
121
|
+
"w": 150
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"id": "attachments__size",
|
|
125
|
+
"header": "Size",
|
|
126
|
+
"fieldName": "attachments__size",
|
|
127
|
+
"isSortable": true,
|
|
128
|
+
"isEditable": true,
|
|
129
|
+
"isReorderable": true,
|
|
130
|
+
"isResizable": true,
|
|
131
|
+
"w": 100
|
|
132
|
+
}
|
|
133
|
+
];
|
|
@@ -103,7 +103,10 @@ import _ from 'lodash';
|
|
|
103
103
|
const
|
|
104
104
|
SINGLE_CLICK = 1,
|
|
105
105
|
DOUBLE_CLICK = 2,
|
|
106
|
-
TRIPLE_CLICK = 3
|
|
106
|
+
TRIPLE_CLICK = 3,
|
|
107
|
+
PHASES_INITIAL = 'initial',
|
|
108
|
+
PHASES_MEASURING = 'measuring',
|
|
109
|
+
PHASES_OPTIMIZED = 'optimized';
|
|
107
110
|
|
|
108
111
|
function GridComponent(props) {
|
|
109
112
|
const {
|
|
@@ -184,6 +187,8 @@ function GridComponent(props) {
|
|
|
184
187
|
areRowsDropTarget = false,
|
|
185
188
|
dropTargetAccept,
|
|
186
189
|
onRowDrop,
|
|
190
|
+
onDragStart,
|
|
191
|
+
onDragEnd,
|
|
187
192
|
|
|
188
193
|
// withComponent
|
|
189
194
|
self,
|
|
@@ -263,6 +268,7 @@ function GridComponent(props) {
|
|
|
263
268
|
[isLoading, setIsLoading] = useState(false),
|
|
264
269
|
[localColumnsConfig, setLocalColumnsConfigRaw] = useState([]),
|
|
265
270
|
[isReorderMode, setIsReorderMode] = useState(false),
|
|
271
|
+
showRowHandle = showSelectHandle || areRowsDragSource || (canRowsReorder && isReorderMode),
|
|
266
272
|
getIsExpanded = (index) => {
|
|
267
273
|
return !!expandedRowsRef.current[index];
|
|
268
274
|
},
|
|
@@ -491,6 +497,7 @@ function GridComponent(props) {
|
|
|
491
497
|
'Row',
|
|
492
498
|
'flex-row',
|
|
493
499
|
'grow',
|
|
500
|
+
'max-h-[80px]',
|
|
494
501
|
)}
|
|
495
502
|
>
|
|
496
503
|
{({
|
|
@@ -500,6 +507,7 @@ function GridComponent(props) {
|
|
|
500
507
|
}) => {
|
|
501
508
|
if (isHeaderRow) {
|
|
502
509
|
let headerRow = <GridHeaderRow
|
|
510
|
+
ref={headerRowRef}
|
|
503
511
|
Repository={Repository}
|
|
504
512
|
columnsConfig={localColumnsConfig}
|
|
505
513
|
setColumnsConfig={setLocalColumnsConfig}
|
|
@@ -513,7 +521,7 @@ function GridComponent(props) {
|
|
|
513
521
|
isInlineEditorShown={isInlineEditorShown}
|
|
514
522
|
areRowsDragSource={areRowsDragSource}
|
|
515
523
|
showColumnsSelector={showColumnsSelector}
|
|
516
|
-
|
|
524
|
+
showRowHandle={showRowHandle}
|
|
517
525
|
/>;
|
|
518
526
|
if (showRowExpander) {
|
|
519
527
|
// align the header row to content rows by adding a spacer that matches the width of the Grid-rowExpander-expandBtn
|
|
@@ -527,7 +535,9 @@ function GridComponent(props) {
|
|
|
527
535
|
const
|
|
528
536
|
rowReorderProps = {},
|
|
529
537
|
rowDragProps = {};
|
|
530
|
-
let WhichRow = GridRow
|
|
538
|
+
let WhichRow = GridRow,
|
|
539
|
+
rowCanSelect = true,
|
|
540
|
+
rowCanDrag = false;
|
|
531
541
|
if (CURRENT_MODE === UI_MODE_WEB) { // DND is currently web-only TODO: implement for RN
|
|
532
542
|
// Create a method that gets an always-current copy of the selection ids
|
|
533
543
|
dragSelectionRef.current = selection;
|
|
@@ -545,11 +555,13 @@ function GridComponent(props) {
|
|
|
545
555
|
id: item.id,
|
|
546
556
|
getSelection,
|
|
547
557
|
isInSelection,
|
|
558
|
+
sourceComponentRef: gridRef, // Reference to the originating component
|
|
548
559
|
onDrag: (dragState) => {
|
|
549
560
|
onRowReorderDrag(dragState, dragIx);
|
|
550
561
|
},
|
|
551
562
|
};
|
|
552
563
|
rowReorderProps.onDragEnd = onRowReorderEnd;
|
|
564
|
+
rowCanDrag = true;
|
|
553
565
|
} else {
|
|
554
566
|
// Don't allow drag/drop from withDnd while reordering
|
|
555
567
|
if (areRowsDragSource && (!canRowDrag || canRowDrag(item))) {
|
|
@@ -558,6 +570,10 @@ function GridComponent(props) {
|
|
|
558
570
|
rowDragProps.dragSourceType = rowDragSourceType;
|
|
559
571
|
if (getRowDragSourceItem) {
|
|
560
572
|
rowDragProps.dragSourceItem = getRowDragSourceItem(item, getSelection, isInSelection, rowDragSourceType);
|
|
573
|
+
// Ensure all drag items have a component reference
|
|
574
|
+
if (!rowDragProps.dragSourceItem.sourceComponentRef) {
|
|
575
|
+
rowDragProps.dragSourceItem.sourceComponentRef = gridRef;
|
|
576
|
+
}
|
|
561
577
|
} else {
|
|
562
578
|
rowDragProps.dragSourceItem = {
|
|
563
579
|
id: item.id,
|
|
@@ -565,6 +581,7 @@ function GridComponent(props) {
|
|
|
565
581
|
getSelection,
|
|
566
582
|
isInSelection,
|
|
567
583
|
type: rowDragSourceType,
|
|
584
|
+
sourceComponentRef: gridRef, // Reference to the originating component
|
|
568
585
|
};
|
|
569
586
|
}
|
|
570
587
|
rowDragProps.dragSourceItem.onDragStart = () => {
|
|
@@ -572,6 +589,9 @@ function GridComponent(props) {
|
|
|
572
589
|
// reset the selection to just this one node if it's not already selected
|
|
573
590
|
setSelection([item]);
|
|
574
591
|
}
|
|
592
|
+
if (onDragStart) {
|
|
593
|
+
onDragStart(item, rowDragProps.dragSourceItem);
|
|
594
|
+
}
|
|
575
595
|
};
|
|
576
596
|
if (canRowDrag) {
|
|
577
597
|
rowDragProps.canDrag = () => canRowDrag(item, rowDragProps.dragSourceItem);
|
|
@@ -582,10 +602,17 @@ function GridComponent(props) {
|
|
|
582
602
|
rowDragProps.dragPreviewOptions = dragPreviewOptions;
|
|
583
603
|
}
|
|
584
604
|
|
|
605
|
+
// Add onDragEnd callback
|
|
606
|
+
if (onDragEnd) {
|
|
607
|
+
rowDragProps.onDragEnd = onDragEnd;
|
|
608
|
+
}
|
|
609
|
+
|
|
585
610
|
// Add drag preview rendering
|
|
586
611
|
rowDragProps.getDragProxy = getCustomDragProxy ?
|
|
587
612
|
(dragItem) => getCustomDragProxy(item, getSelection()) :
|
|
588
613
|
null; // Let GlobalDragProxy handle the default case
|
|
614
|
+
|
|
615
|
+
rowCanDrag = true;
|
|
589
616
|
}
|
|
590
617
|
if (areRowsDropTarget) {
|
|
591
618
|
WhichRow = DropTargetGridRow;
|
|
@@ -611,7 +638,20 @@ function GridComponent(props) {
|
|
|
611
638
|
}
|
|
612
639
|
|
|
613
640
|
}
|
|
641
|
+
|
|
642
|
+
// Use pre-created ref for row height measurement (sample first few rows)
|
|
643
|
+
let rowRef = null;
|
|
644
|
+
if (autoAdjustPageSizeToHeight && measurementPhase === PHASES_MEASURING &&
|
|
645
|
+
!isHeaderRow && index >= 1 && index <= 5) { // Sample first 5 data rows (index 1-5)
|
|
646
|
+
const refIndex = index - 1; // Convert to 0-based index
|
|
647
|
+
rowRef = rowRefs[refIndex];
|
|
648
|
+
if (rowRef && !sampleRowsRef.current.includes(rowRef)) {
|
|
649
|
+
sampleRowsRef.current.push(rowRef);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
|
|
614
653
|
return <WhichRow
|
|
654
|
+
ref={rowRef}
|
|
615
655
|
columnsConfig={localColumnsConfig}
|
|
616
656
|
columnProps={columnProps}
|
|
617
657
|
fields={fields}
|
|
@@ -622,7 +662,9 @@ function GridComponent(props) {
|
|
|
622
662
|
isSelected={isSelected}
|
|
623
663
|
isHovered={hovered}
|
|
624
664
|
showHovers={showHovers}
|
|
625
|
-
|
|
665
|
+
showRowHandle={showRowHandle}
|
|
666
|
+
rowCanSelect={rowCanSelect}
|
|
667
|
+
rowCanDrag={rowCanDrag}
|
|
626
668
|
index={index}
|
|
627
669
|
alternatingInterval={alternatingInterval}
|
|
628
670
|
alternateRowBackgrounds={alternateRowBackgrounds}
|
|
@@ -816,19 +858,107 @@ function GridComponent(props) {
|
|
|
816
858
|
marker.remove();
|
|
817
859
|
cachedDragElements.current = null;
|
|
818
860
|
},
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
861
|
+
// Refs for measuring actual row heights
|
|
862
|
+
headerRowRef = useRef(null),
|
|
863
|
+
paginationToolbarRef = useRef(null),
|
|
864
|
+
sampleRowsRef = useRef([]),
|
|
865
|
+
|
|
866
|
+
// Pre-create refs for first 5 rows for measurement
|
|
867
|
+
rowRefs = [useRef(null), useRef(null), useRef(null), useRef(null), useRef(null)],
|
|
868
|
+
|
|
869
|
+
// State for tracking measurement phases
|
|
870
|
+
[measurementPhase, setMeasurementPhase] = useState(PHASES_INITIAL), //
|
|
871
|
+
[lastMeasuredContainerHeight, setLastMeasuredContainerHeight] = useState(0),
|
|
872
|
+
[measuredRowHeight, setMeasuredRowHeight] = useState(null),
|
|
873
|
+
calculatePageSize = (containerHeight, useActualMeasurements = false) => {
|
|
874
|
+
// Phase 1: Initial calculation using estimated heights
|
|
875
|
+
if (!useActualMeasurements || measurementPhase === PHASES_INITIAL) {
|
|
876
|
+
const
|
|
877
|
+
headerHeight = showHeaders ? 50 : 0,
|
|
878
|
+
footerHeight = !disablePagination ? 50 : 0,
|
|
879
|
+
availableHeight = containerHeight - headerHeight - footerHeight,
|
|
880
|
+
maxClassNormal = styles.GRID_ROW_MAX_HEIGHT_NORMAL, // e.g. max-h-[40px]
|
|
881
|
+
rowNormalHeight = parseInt(maxClassNormal.match(/\d+/)[0]);
|
|
882
|
+
|
|
883
|
+
let pageSize = Math.floor(availableHeight / rowNormalHeight);
|
|
884
|
+
// Add 20% buffer for better measurement accuracy
|
|
885
|
+
pageSize = Math.floor(pageSize * 1.2);
|
|
886
|
+
if (pageSize < 1) {
|
|
887
|
+
pageSize = 1;
|
|
888
|
+
}
|
|
889
|
+
return pageSize;
|
|
890
|
+
}
|
|
826
891
|
|
|
827
|
-
|
|
828
|
-
if (
|
|
829
|
-
|
|
892
|
+
// Phase 3: Optimized calculation using actual measurements
|
|
893
|
+
if (useActualMeasurements && measurementPhase === PHASES_OPTIMIZED && measuredRowHeight) {
|
|
894
|
+
let actualHeaderHeight = 0;
|
|
895
|
+
let actualFooterHeight = 0;
|
|
896
|
+
let actualRowHeight = measuredRowHeight;
|
|
897
|
+
|
|
898
|
+
// Measure actual header height
|
|
899
|
+
if (showHeaders && headerRowRef.current) {
|
|
900
|
+
actualHeaderHeight = headerRowRef.current.offsetHeight || headerRowRef.current.clientHeight || 50;
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
// Measure actual pagination toolbar height
|
|
904
|
+
if (!disablePagination && paginationToolbarRef.current) {
|
|
905
|
+
actualFooterHeight = paginationToolbarRef.current.offsetHeight || paginationToolbarRef.current.clientHeight || 50;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
const availableHeight = containerHeight - actualHeaderHeight - actualFooterHeight;
|
|
909
|
+
let pageSize = Math.floor(availableHeight / actualRowHeight);
|
|
910
|
+
|
|
911
|
+
if (pageSize < 1) {
|
|
912
|
+
pageSize = 1;
|
|
913
|
+
}
|
|
914
|
+
return pageSize;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
// Fallback to Phase 1 logic
|
|
918
|
+
return calculatePageSize(containerHeight, false);
|
|
919
|
+
},
|
|
920
|
+
measureActualRowHeights = () => {
|
|
921
|
+
if (CURRENT_MODE !== UI_MODE_WEB || !gridContainerRef.current) {
|
|
922
|
+
return;
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
// Measure a sample of rendered rows to get average height
|
|
926
|
+
const sampleRows = sampleRowsRef.current.filter(ref => ref && ref.current);
|
|
927
|
+
if (sampleRows.length === 0) {
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
let totalHeight = 0;
|
|
932
|
+
let measuredCount = 0;
|
|
933
|
+
|
|
934
|
+
sampleRows.forEach(rowRef => {
|
|
935
|
+
if (rowRef.current) {
|
|
936
|
+
const height = rowRef.current.offsetHeight || rowRef.current.clientHeight;
|
|
937
|
+
if (height > 0) {
|
|
938
|
+
totalHeight += height;
|
|
939
|
+
measuredCount++;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
|
|
944
|
+
if (measuredCount > 0) {
|
|
945
|
+
const averageHeight = totalHeight / measuredCount;
|
|
946
|
+
console.log(`[Grid] Measured actual row height: ${averageHeight}px from ${measuredCount} sample rows`);
|
|
947
|
+
setMeasuredRowHeight(averageHeight);
|
|
948
|
+
setMeasurementPhase(PHASES_OPTIMIZED);
|
|
949
|
+
|
|
950
|
+
// Clear sample refs for next measurement cycle
|
|
951
|
+
sampleRowsRef.current = [];
|
|
952
|
+
|
|
953
|
+
// Recalculate pageSize with actual measurements
|
|
954
|
+
if (lastMeasuredContainerHeight > 0) {
|
|
955
|
+
const newPageSize = calculatePageSize(lastMeasuredContainerHeight, true);
|
|
956
|
+
console.log(`[Grid] Optimized pageSize: ${newPageSize} (was ${Repository.pageSize})`);
|
|
957
|
+
if (newPageSize !== Repository.pageSize) {
|
|
958
|
+
Repository.setPageSize(newPageSize);
|
|
959
|
+
}
|
|
960
|
+
}
|
|
830
961
|
}
|
|
831
|
-
return pageSize;
|
|
832
962
|
},
|
|
833
963
|
adjustPageSizeToHeight = (e) => {
|
|
834
964
|
if (CURRENT_MODE !== UI_MODE_WEB) { // TODO: Remove this conditional, and don't even do the double render for RN
|
|
@@ -846,9 +976,19 @@ function GridComponent(props) {
|
|
|
846
976
|
if (doAdjustment) {
|
|
847
977
|
const containerHeight = e.nativeEvent.layout.height;
|
|
848
978
|
if (containerHeight > 0) {
|
|
849
|
-
|
|
979
|
+
setLastMeasuredContainerHeight(containerHeight);
|
|
980
|
+
|
|
981
|
+
// Phase 1: Initial calculation with buffer
|
|
982
|
+
const pageSize = calculatePageSize(containerHeight, false);
|
|
983
|
+
console.log(`[Grid] Adjusting pageSize: containerHeight=${containerHeight}, phase=${measurementPhase}, calculatedPageSize=${pageSize}, currentPageSize=${Repository.pageSize}`);
|
|
984
|
+
|
|
850
985
|
if (pageSize !== Repository.pageSize) {
|
|
851
986
|
Repository.setPageSize(pageSize);
|
|
987
|
+
|
|
988
|
+
// Trigger Phase 2: Enable measurement mode after render
|
|
989
|
+
if (measurementPhase === PHASES_INITIAL) {
|
|
990
|
+
setMeasurementPhase(PHASES_MEASURING);
|
|
991
|
+
}
|
|
852
992
|
}
|
|
853
993
|
}
|
|
854
994
|
}
|
|
@@ -1006,8 +1146,6 @@ function GridComponent(props) {
|
|
|
1006
1146
|
(async () => {
|
|
1007
1147
|
|
|
1008
1148
|
// second call -- do other necessary setup
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
1149
|
let columnsConfigVariable = columnsConfig,
|
|
1012
1150
|
localColumnsConfig = [],
|
|
1013
1151
|
savedLocalColumnsConfig,
|
|
@@ -1100,6 +1238,20 @@ function GridComponent(props) {
|
|
|
1100
1238
|
if (!Repository.isAutoLoad) {
|
|
1101
1239
|
Repository.reload();
|
|
1102
1240
|
}
|
|
1241
|
+
|
|
1242
|
+
// Reset measurement phase and recalculate pageSize if auto-adjust is enabled
|
|
1243
|
+
if (autoAdjustPageSizeToHeight && lastMeasuredContainerHeight > 0) {
|
|
1244
|
+
console.log(`[Grid] Filters changed - resetting pageSize measurement`);
|
|
1245
|
+
setMeasurementPhase(PHASES_INITIAL);
|
|
1246
|
+
setMeasuredRowHeight(null);
|
|
1247
|
+
sampleRowsRef.current = [];
|
|
1248
|
+
|
|
1249
|
+
// Recalculate pageSize with fresh measurements
|
|
1250
|
+
const pageSize = calculatePageSize(lastMeasuredContainerHeight, false);
|
|
1251
|
+
if (pageSize !== Repository.pageSize) {
|
|
1252
|
+
Repository.setPageSize(pageSize);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1103
1255
|
},
|
|
1104
1256
|
onChangeSorters = () => {
|
|
1105
1257
|
if (!Repository.isAutoLoad) {
|
|
@@ -1151,6 +1303,26 @@ function GridComponent(props) {
|
|
|
1151
1303
|
|
|
1152
1304
|
}, [selectorId, selectorSelected]);
|
|
1153
1305
|
|
|
1306
|
+
// Effect to trigger row height measurement after render
|
|
1307
|
+
useEffect(() => {
|
|
1308
|
+
if (measurementPhase === PHASES_MEASURING && data && data.length > 0) {
|
|
1309
|
+
// Small delay to ensure DOM is fully rendered
|
|
1310
|
+
const timer = setTimeout(() => {
|
|
1311
|
+
measureActualRowHeights();
|
|
1312
|
+
}, 100);
|
|
1313
|
+
return () => clearTimeout(timer);
|
|
1314
|
+
}
|
|
1315
|
+
}, [measurementPhase, data]);
|
|
1316
|
+
|
|
1317
|
+
// Effect to reset measurement state when autoAdjustPageSizeToHeight changes
|
|
1318
|
+
useEffect(() => {
|
|
1319
|
+
if (autoAdjustPageSizeToHeight) {
|
|
1320
|
+
setMeasurementPhase(PHASES_INITIAL);
|
|
1321
|
+
setMeasuredRowHeight(null);
|
|
1322
|
+
sampleRowsRef.current = [];
|
|
1323
|
+
}
|
|
1324
|
+
}, [autoAdjustPageSizeToHeight]);
|
|
1325
|
+
|
|
1154
1326
|
if (canUser && !canUser('view')) {
|
|
1155
1327
|
return <Unauthorized />;
|
|
1156
1328
|
}
|
|
@@ -1203,6 +1375,7 @@ function GridComponent(props) {
|
|
|
1203
1375
|
showMoreOnly = true;
|
|
1204
1376
|
}
|
|
1205
1377
|
listFooterComponent = <PaginationToolbar
|
|
1378
|
+
ref={paginationToolbarRef}
|
|
1206
1379
|
Repository={Repository}
|
|
1207
1380
|
self={self}
|
|
1208
1381
|
toolbarItems={footerToolbarItemComponents}
|
|
@@ -1297,7 +1470,7 @@ function GridComponent(props) {
|
|
|
1297
1470
|
'border-grey-300',
|
|
1298
1471
|
);
|
|
1299
1472
|
if (props.className) {
|
|
1300
|
-
className += props.className;
|
|
1473
|
+
className += ' ' + props.className;
|
|
1301
1474
|
}
|
|
1302
1475
|
|
|
1303
1476
|
grid = <VStackNative
|
|
@@ -1321,7 +1494,7 @@ function GridComponent(props) {
|
|
|
1321
1494
|
className={clsx(
|
|
1322
1495
|
'gridContainer',
|
|
1323
1496
|
'w-full',
|
|
1324
|
-
'h-full',
|
|
1497
|
+
// 'h-full',
|
|
1325
1498
|
'flex-1',
|
|
1326
1499
|
'min-h-[40px]',
|
|
1327
1500
|
gridContainerBorderClassName,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useEffect, useMemo, } from 'react';
|
|
1
|
+
import { useState, useEffect, useMemo, forwardRef, } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Box,
|
|
4
4
|
HStack,
|
|
@@ -30,9 +30,7 @@ import SortDown from '../Icons/SortDown.js';
|
|
|
30
30
|
import SortUp from '../Icons/SortUp.js';
|
|
31
31
|
import _ from 'lodash';
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
export default function GridHeaderRow(props) {
|
|
33
|
+
export default forwardRef(function GridHeaderRow(props, ref) {
|
|
36
34
|
let {
|
|
37
35
|
canColumnsReorder,
|
|
38
36
|
canColumnsResize,
|
|
@@ -49,7 +47,7 @@ export default function GridHeaderRow(props) {
|
|
|
49
47
|
isInlineEditorShown,
|
|
50
48
|
areRowsDragSource,
|
|
51
49
|
showColumnsSelector,
|
|
52
|
-
|
|
50
|
+
showRowHandle,
|
|
53
51
|
} = props,
|
|
54
52
|
styles = UiGlobals.styles,
|
|
55
53
|
sortFn = Repository && Repository.getSortFn(),
|
|
@@ -467,18 +465,10 @@ export default function GridHeaderRow(props) {
|
|
|
467
465
|
/>}
|
|
468
466
|
</Pressable>;
|
|
469
467
|
});
|
|
470
|
-
if (
|
|
471
|
-
headerColumns.unshift(<Box
|
|
472
|
-
key="RowSelectHandle"
|
|
473
|
-
className="Spacer-RowSelectHandle px-2 items-center justify-center flex-none w-[40px]"
|
|
474
|
-
>
|
|
475
|
-
<Icon as={Arcs} className={`Arcs w-[20px] h-[20px] text-[#aaa]`} />
|
|
476
|
-
</Box>);
|
|
477
|
-
}
|
|
478
|
-
if (areRowsDragSource) {
|
|
468
|
+
if (showRowHandle) {
|
|
479
469
|
headerColumns.unshift(<Box
|
|
480
|
-
key="
|
|
481
|
-
className="Spacer w-[
|
|
470
|
+
key="RowHandleSpacer"
|
|
471
|
+
className="Spacer-RowHandle w-[40px] flex-none"
|
|
482
472
|
/>);
|
|
483
473
|
}
|
|
484
474
|
if (!hideNavColumn) {
|
|
@@ -488,6 +478,7 @@ export default function GridHeaderRow(props) {
|
|
|
488
478
|
};
|
|
489
479
|
|
|
490
480
|
return <HStack
|
|
481
|
+
ref={ref}
|
|
491
482
|
style={{
|
|
492
483
|
scrollbarWidth: 'none',
|
|
493
484
|
}}
|
|
@@ -515,6 +506,8 @@ export default function GridHeaderRow(props) {
|
|
|
515
506
|
sortFn,
|
|
516
507
|
sortField,
|
|
517
508
|
isInlineEditorShown,
|
|
509
|
+
areRowsDragSource,
|
|
510
|
+
showRowHandle,
|
|
518
511
|
]);
|
|
519
|
-
}
|
|
512
|
+
});
|
|
520
513
|
|