Skip to content

Commit a236d4b

Browse files
authored
fix(AnalyticalTable - useIndeterminateRowSelection): improve performance (#8924)
Fixes #4886
1 parent 19af447 commit a236d4b

1 file changed

Lines changed: 29 additions & 50 deletions

File tree

‎packages/main/src/components/AnalyticalTable/pluginHooks/useIndeterminateRowSelection.tsx‎

Lines changed: 29 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -10,64 +10,43 @@ type onIndeterminateChange = (e: {
1010
tableInstance: TableInstance;
1111
}) => void;
1212

13-
const getParentRow = (id: string, rowsById: TableInstance['rowsById']): [RowType, number] => {
14-
let lastDotIndex = id.lastIndexOf('.');
15-
if (lastDotIndex === -1) {
16-
lastDotIndex = Infinity;
17-
}
18-
const parentRowId = id.slice(0, lastDotIndex);
19-
return [rowsById[parentRowId], lastDotIndex];
20-
};
21-
22-
const getIndeterminateRowIds = (id: string): Record<string, boolean> => {
23-
const indeterminateRowsById: Record<string, boolean> = {};
24-
const lastDotIndex = id.lastIndexOf('.');
25-
indeterminateRowsById[id] = true;
26-
if (lastDotIndex !== -1) {
27-
// set all parent rows to indeterminate
28-
Object.assign(indeterminateRowsById, getIndeterminateRowIds(id.slice(0, lastDotIndex)));
29-
}
30-
return indeterminateRowsById;
31-
};
32-
13+
/**
14+
* Marks a row indeterminate if its subtree contains a node whose direct sub-rows are partially selected (some, not all).
15+
* A single O(n) post-order traversal visits each row once and reads every sub-row reference once.
16+
*/
3317
const getIndeterminate = (
3418
rows: RowType[],
35-
rowsById: TableInstance['rowsById'],
3619
state: { selectedRowIds: AnalyticalTableState['selectedRowIds'] },
3720
): Record<string, boolean> => {
3821
const indeterminateRowsById: Record<string, boolean> = {};
39-
let usedParentIndex = '';
40-
const getIndeterminateRecursive = (subRows: RowType[], rowIdScope: string | null = null) => {
41-
for (const row of subRows) {
42-
if (row.subRows.length > 0) {
43-
// find leaf nodes
44-
getIndeterminateRecursive(row.subRows, row.id);
45-
} else if (rowIdScope !== null && usedParentIndex !== rowIdScope) {
46-
usedParentIndex = rowIdScope;
47-
const checkIndeterminate = (rowId: string) => {
48-
const [parentRow, dotIndex] = getParentRow(rowId, rowsById);
49-
const selectedRows = parentRow.subRows.filter((item) => state.selectedRowIds[item.id]);
50-
const areAllSelected = parentRow.subRows.length === selectedRows.length;
51-
const isOneSelected = selectedRows.length > 0;
52-
53-
// if not all, but at least one subRow is selected, set the parent row's state to indeterminate
54-
if (isOneSelected && !areAllSelected) {
55-
const parentRowId = parentRow.id;
56-
Object.assign(indeterminateRowsById, getIndeterminateRowIds(parentRowId));
57-
return;
58-
}
59-
if (dotIndex !== Infinity) {
60-
// recursively check indeterminate state until root nodes are reached
61-
checkIndeterminate(parentRow.id);
62-
}
63-
return;
64-
};
22+
const { selectedRowIds } = state;
6523

66-
checkIndeterminate(row.id);
24+
const markSubtree = (row: RowType): boolean => {
25+
const subRows = row.subRows;
26+
if (!subRows?.length) {
27+
return false;
28+
}
29+
let selectedCount = 0;
30+
let subtreeHasIndeterminate = false;
31+
for (const subRow of subRows) {
32+
if (selectedRowIds[subRow.id]) {
33+
selectedCount++;
6734
}
35+
if (markSubtree(subRow)) {
36+
subtreeHasIndeterminate = true;
37+
}
38+
}
39+
const isPartiallySelected = selectedCount > 0 && selectedCount < subRows.length;
40+
if (isPartiallySelected || subtreeHasIndeterminate) {
41+
indeterminateRowsById[row.id] = true;
42+
return true;
6843
}
44+
return false;
6945
};
70-
getIndeterminateRecursive(rows);
46+
47+
for (const row of rows) {
48+
markSubtree(row);
49+
}
7150
return indeterminateRowsById;
7251
};
7352

@@ -138,7 +117,7 @@ export const useIndeterminateRowSelection = (onIndeterminateChange?: onIndetermi
138117
};
139118
}
140119

141-
const indeterminateRowsById = getIndeterminate(rows, rowsById, { selectedRowIds: newState.selectedRowIds });
120+
const indeterminateRowsById = getIndeterminate(rows, { selectedRowIds: newState.selectedRowIds });
142121

143122
return {
144123
...newState,

0 commit comments

Comments
 (0)