@mui/x-data-grid-premium 8.7.0 → 8.9.0
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/CHANGELOG.md +199 -24
- package/DataGridPremium/DataGridPremium.js +1 -1
- package/DataGridPremium/useDataGridPremiumComponent.js +19 -7
- package/DataGridPremium/useDataGridPremiumProps.js +2 -1
- package/esm/DataGridPremium/DataGridPremium.js +1 -1
- package/esm/DataGridPremium/useDataGridPremiumComponent.js +21 -8
- package/esm/DataGridPremium/useDataGridPremiumProps.js +2 -1
- package/esm/hooks/features/aggregation/createAggregationLookup.d.ts +9 -4
- package/esm/hooks/features/aggregation/createAggregationLookup.js +78 -41
- package/esm/hooks/features/aggregation/gridAggregationFunctions.js +2 -2
- package/esm/hooks/features/aggregation/gridAggregationInterfaces.d.ts +13 -1
- package/esm/hooks/features/aggregation/gridAggregationUtils.d.ts +2 -1
- package/esm/hooks/features/aggregation/gridAggregationUtils.js +2 -1
- package/esm/hooks/features/aggregation/useGridAggregation.js +94 -18
- package/esm/hooks/features/pivoting/gridPivotingInterfaces.d.ts +12 -2
- package/esm/hooks/features/pivoting/useGridPivoting.d.ts +2 -1
- package/esm/hooks/features/pivoting/useGridPivoting.js +57 -35
- package/esm/hooks/features/pivoting/utils.d.ts +3 -1
- package/esm/hooks/features/pivoting/utils.js +22 -14
- package/esm/hooks/features/rowGrouping/gridRowGroupingUtils.js +5 -1
- package/esm/hooks/features/rowGrouping/useGridDataSourceRowGroupingPreProcessors.js +2 -2
- package/esm/index.js +3 -3
- package/esm/typeOverloads/modules.d.ts +2 -1
- package/hooks/features/aggregation/createAggregationLookup.d.ts +9 -4
- package/hooks/features/aggregation/createAggregationLookup.js +79 -41
- package/hooks/features/aggregation/gridAggregationFunctions.js +2 -2
- package/hooks/features/aggregation/gridAggregationInterfaces.d.ts +13 -1
- package/hooks/features/aggregation/gridAggregationUtils.d.ts +2 -1
- package/hooks/features/aggregation/gridAggregationUtils.js +4 -2
- package/hooks/features/aggregation/useGridAggregation.js +92 -16
- package/hooks/features/pivoting/gridPivotingInterfaces.d.ts +12 -2
- package/hooks/features/pivoting/useGridPivoting.d.ts +2 -1
- package/hooks/features/pivoting/useGridPivoting.js +60 -37
- package/hooks/features/pivoting/utils.d.ts +3 -1
- package/hooks/features/pivoting/utils.js +22 -14
- package/hooks/features/rowGrouping/gridRowGroupingUtils.js +5 -1
- package/hooks/features/rowGrouping/useGridDataSourceRowGroupingPreProcessors.js +1 -1
- package/index.js +3 -3
- package/package.json +6 -6
- package/typeOverloads/modules.d.ts +2 -1
|
@@ -2,6 +2,7 @@ import _extends from "@babel/runtime/helpers/esm/extends";
|
|
|
2
2
|
import { isLeaf, gridStringOrNumberComparator } from '@mui/x-data-grid-pro';
|
|
3
3
|
import { getDefaultColTypeDef } from '@mui/x-data-grid-pro/internals';
|
|
4
4
|
import { isGroupingColumn } from "../rowGrouping/index.js";
|
|
5
|
+
import { defaultGetAggregationPosition } from "../aggregation/gridAggregationUtils.js";
|
|
5
6
|
const columnGroupIdSeparator = '>->';
|
|
6
7
|
export const isPivotingAvailable = props => {
|
|
7
8
|
return !props.disablePivoting;
|
|
@@ -64,7 +65,8 @@ export const getPivotedData = ({
|
|
|
64
65
|
columns,
|
|
65
66
|
pivotModel,
|
|
66
67
|
apiRef,
|
|
67
|
-
pivotingColDef
|
|
68
|
+
pivotingColDef,
|
|
69
|
+
groupingColDef
|
|
68
70
|
}) => {
|
|
69
71
|
const visibleColumns = pivotModel.columns.filter(column => !column.hidden);
|
|
70
72
|
const visibleRows = pivotModel.rows.filter(row => !row.hidden);
|
|
@@ -129,26 +131,31 @@ export const getPivotedData = ({
|
|
|
129
131
|
const row = rows[i];
|
|
130
132
|
const newRow = _extends({}, row);
|
|
131
133
|
const columnGroupPath = [];
|
|
132
|
-
visibleColumns.
|
|
133
|
-
|
|
134
|
-
|
|
134
|
+
for (let j = 0; j < visibleColumns.length; j += 1) {
|
|
135
|
+
const {
|
|
136
|
+
field: colGroupField
|
|
137
|
+
} = visibleColumns[j];
|
|
138
|
+
const depth = j;
|
|
135
139
|
const column = initialColumns.get(colGroupField);
|
|
136
140
|
if (!column) {
|
|
137
|
-
|
|
141
|
+
continue;
|
|
138
142
|
}
|
|
139
143
|
let colValue = apiRef.current.getRowValue(row, column) ?? '(No value)';
|
|
144
|
+
if (column.type !== 'number') {
|
|
145
|
+
colValue = String(colValue);
|
|
146
|
+
}
|
|
140
147
|
if (column.type === 'singleSelect') {
|
|
141
148
|
const singleSelectColumn = column;
|
|
142
149
|
if (singleSelectColumn.getOptionLabel) {
|
|
143
150
|
colValue = singleSelectColumn.getOptionLabel(colValue);
|
|
144
151
|
}
|
|
145
152
|
}
|
|
146
|
-
columnGroupPath.push(
|
|
153
|
+
columnGroupPath.push(colValue);
|
|
147
154
|
const groupId = columnGroupPath.join(columnGroupIdSeparator);
|
|
148
155
|
if (!columnGroupingModelLookup.has(groupId)) {
|
|
149
156
|
const columnGroup = {
|
|
150
157
|
groupId,
|
|
151
|
-
headerName:
|
|
158
|
+
headerName: colValue,
|
|
152
159
|
children: []
|
|
153
160
|
};
|
|
154
161
|
columnGroupingModelLookup.set(groupId, columnGroup);
|
|
@@ -174,7 +181,7 @@ export const getPivotedData = ({
|
|
|
174
181
|
newRow[valueKey] = apiRef.current.getRowValue(row, originalColumn);
|
|
175
182
|
});
|
|
176
183
|
}
|
|
177
|
-
}
|
|
184
|
+
}
|
|
178
185
|
newRows.push(newRow);
|
|
179
186
|
}
|
|
180
187
|
sortColumnGroups(columnGroupingModel, visibleColumns);
|
|
@@ -239,19 +246,20 @@ export const getPivotedData = ({
|
|
|
239
246
|
}
|
|
240
247
|
}
|
|
241
248
|
createColumns(columnGroupingModel);
|
|
249
|
+
const groupingColDefOverrides = params => _extends({}, typeof groupingColDef === 'function' ? groupingColDef(params) : groupingColDef || {}, {
|
|
250
|
+
filterable: false,
|
|
251
|
+
aggregable: false,
|
|
252
|
+
hideable: false
|
|
253
|
+
});
|
|
242
254
|
return {
|
|
243
255
|
rows: visibleRows.length > 0 ? newRows : [],
|
|
244
256
|
columns: pivotColumns,
|
|
245
257
|
rowGroupingModel: visibleRows.map(row => row.field),
|
|
246
258
|
aggregationModel,
|
|
247
|
-
getAggregationPosition:
|
|
259
|
+
getAggregationPosition: defaultGetAggregationPosition,
|
|
248
260
|
columnVisibilityModel,
|
|
249
261
|
columnGroupingModel,
|
|
250
|
-
groupingColDef:
|
|
251
|
-
filterable: false,
|
|
252
|
-
aggregable: false,
|
|
253
|
-
hideable: false
|
|
254
|
-
},
|
|
262
|
+
groupingColDef: groupingColDefOverrides,
|
|
255
263
|
headerFilters: false,
|
|
256
264
|
disableAggregation: false,
|
|
257
265
|
disableRowGrouping: false
|
|
@@ -116,6 +116,11 @@ export const mergeStateWithRowGroupingModel = rowGroupingModel => state => _exte
|
|
|
116
116
|
})
|
|
117
117
|
});
|
|
118
118
|
export const setStrategyAvailability = (privateApiRef, disableRowGrouping, dataSource) => {
|
|
119
|
+
const strategy = dataSource ? RowGroupingStrategy.DataSource : RowGroupingStrategy.Default;
|
|
120
|
+
if (privateApiRef.current.getActiveStrategy(GridStrategyGroup.RowTree) === strategy) {
|
|
121
|
+
// If the strategy is already active, we don't need to set it again
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
119
124
|
let isAvailable;
|
|
120
125
|
if (disableRowGrouping) {
|
|
121
126
|
isAvailable = () => false;
|
|
@@ -125,7 +130,6 @@ export const setStrategyAvailability = (privateApiRef, disableRowGrouping, dataS
|
|
|
125
130
|
return rowGroupingSanitizedModel.length > 0;
|
|
126
131
|
};
|
|
127
132
|
}
|
|
128
|
-
const strategy = dataSource ? RowGroupingStrategy.DataSource : RowGroupingStrategy.Default;
|
|
129
133
|
privateApiRef.current.setStrategyAvailability(GridStrategyGroup.RowTree, strategy, isAvailable);
|
|
130
134
|
};
|
|
131
135
|
export const getCellGroupingCriteria = ({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { gridRowTreeSelector, gridColumnLookupSelector } from '@mui/x-data-grid-pro';
|
|
3
|
-
import { useGridRegisterStrategyProcessor, createRowTree, updateRowTree, getVisibleRowsLookup, skipSorting, skipFiltering } from '@mui/x-data-grid-pro/internals';
|
|
3
|
+
import { useGridRegisterStrategyProcessor, createRowTree, updateRowTree, getVisibleRowsLookup, skipSorting, skipFiltering, getParentPath } from '@mui/x-data-grid-pro/internals';
|
|
4
4
|
import { getGroupingRules, RowGroupingStrategy } from "./gridRowGroupingUtils.js";
|
|
5
5
|
import { gridRowGroupingSanitizedModelSelector } from "./gridRowGroupingSelector.js";
|
|
6
6
|
export const useGridDataSourceRowGroupingPreProcessors = (apiRef, props) => {
|
|
@@ -21,7 +21,7 @@ export const useGridDataSourceRowGroupingPreProcessors = (apiRef, props) => {
|
|
|
21
21
|
});
|
|
22
22
|
apiRef.current.caches.rowGrouping.rulesOnLastRowTreeCreation = groupingRules;
|
|
23
23
|
const getRowTreeBuilderNode = rowId => {
|
|
24
|
-
const parentPath = params.updates.groupKeys ??
|
|
24
|
+
const parentPath = params.updates.groupKeys ?? getParentPath(rowId, params);
|
|
25
25
|
const leafKey = getGroupKey(params.dataRowIdToModelLookup[rowId]);
|
|
26
26
|
return {
|
|
27
27
|
id: rowId,
|
package/esm/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @mui/x-data-grid-premium v8.
|
|
2
|
+
* @mui/x-data-grid-premium v8.9.0
|
|
3
3
|
*
|
|
4
|
-
* @license
|
|
5
|
-
* This source code is licensed under the
|
|
4
|
+
* @license SEE LICENSE IN LICENSE
|
|
5
|
+
* This source code is licensed under the SEE LICENSE IN LICENSE license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
import "./typeOverloads/index.js";
|
|
@@ -5,7 +5,7 @@ import type { GridRowGroupingModel, GridAggregationModel, GridAggregationCellMet
|
|
|
5
5
|
import { GridRowGroupingInternalCache } from "../hooks/features/rowGrouping/gridRowGroupingInterfaces.js";
|
|
6
6
|
import { GridAggregationInternalCache } from "../hooks/features/aggregation/gridAggregationInterfaces.js";
|
|
7
7
|
import type { GridExcelExportOptions } from "../hooks/features/export/gridExcelExportInterface.js";
|
|
8
|
-
import type { GridPivotModel } from "../hooks/features/pivoting/gridPivotingInterfaces.js";
|
|
8
|
+
import type { GridPivotingInternalCache, GridPivotModel } from "../hooks/features/pivoting/gridPivotingInterfaces.js";
|
|
9
9
|
export interface GridControlledStateEventLookupPremium {
|
|
10
10
|
/**
|
|
11
11
|
* Fired when the aggregation model changes.
|
|
@@ -105,6 +105,7 @@ export interface GridColumnHeaderParamsPremium<R extends GridValidRowModel = any
|
|
|
105
105
|
aggregation?: GridAggregationHeaderMeta;
|
|
106
106
|
}
|
|
107
107
|
export interface GridApiCachesPremium extends GridApiCachesPro {
|
|
108
|
+
pivoting: GridPivotingInternalCache;
|
|
108
109
|
rowGrouping: GridRowGroupingInternalCache;
|
|
109
110
|
aggregation: GridAggregationInternalCache;
|
|
110
111
|
}
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import { RefObject } from '@mui/x-internals/types';
|
|
2
2
|
import { GridPrivateApiPremium } from "../../../models/gridApiPremium.js";
|
|
3
3
|
import { DataGridPremiumProcessedProps } from "../../../models/dataGridPremiumProps.js";
|
|
4
|
-
import {
|
|
4
|
+
import { GridAggregationLookup, GridAggregationRules } from "./gridAggregationInterfaces.js";
|
|
5
|
+
export declare const shouldApplySorting: (aggregationRules: GridAggregationRules, aggregatedFields: string[]) => boolean;
|
|
5
6
|
export declare const createAggregationLookup: ({
|
|
6
7
|
apiRef,
|
|
7
|
-
|
|
8
|
+
aggregationRules,
|
|
9
|
+
aggregatedFields,
|
|
8
10
|
aggregationRowsScope,
|
|
9
11
|
getAggregationPosition,
|
|
10
|
-
isDataSource
|
|
12
|
+
isDataSource,
|
|
13
|
+
applySorting
|
|
11
14
|
}: {
|
|
12
15
|
apiRef: RefObject<GridPrivateApiPremium>;
|
|
13
|
-
|
|
16
|
+
aggregationRules: GridAggregationRules;
|
|
17
|
+
aggregatedFields: string[];
|
|
14
18
|
aggregationRowsScope: DataGridPremiumProcessedProps["aggregationRowsScope"];
|
|
15
19
|
getAggregationPosition: DataGridPremiumProcessedProps["getAggregationPosition"];
|
|
16
20
|
isDataSource: boolean;
|
|
21
|
+
applySorting: boolean;
|
|
17
22
|
}) => GridAggregationLookup;
|
|
@@ -3,55 +3,72 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.createAggregationLookup = void 0;
|
|
6
|
+
exports.shouldApplySorting = exports.createAggregationLookup = void 0;
|
|
7
7
|
var _xDataGridPro = require("@mui/x-data-grid-pro");
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
var _internals = require("@mui/x-data-grid/internals");
|
|
9
|
+
const shouldApplySorting = (aggregationRules, aggregatedFields) => {
|
|
10
|
+
return aggregatedFields.some(field => aggregationRules[field].aggregationFunction.applySorting);
|
|
11
|
+
};
|
|
12
|
+
exports.shouldApplySorting = shouldApplySorting;
|
|
13
|
+
const getGroupAggregatedValue = (groupId, apiRef, aggregationRowsScope, aggregatedFields, aggregationRules, position, applySorting, valueGetters, publicApi, groupAggregatedValuesLookup) => {
|
|
11
14
|
const groupAggregationLookup = {};
|
|
12
15
|
const aggregatedValues = [];
|
|
16
|
+
for (let i = 0; i < aggregatedFields.length; i += 1) {
|
|
17
|
+
aggregatedValues[i] = {
|
|
18
|
+
aggregatedField: aggregatedFields[i],
|
|
19
|
+
values: []
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const rowTree = (0, _xDataGridPro.gridRowTreeSelector)(apiRef);
|
|
23
|
+
const rowLookup = (0, _xDataGridPro.gridRowsLookupSelector)(apiRef);
|
|
24
|
+
const isPivotActive = apiRef.current.state.pivoting.active;
|
|
13
25
|
const rowIds = apiRef.current.getRowGroupChildren({
|
|
14
|
-
groupId
|
|
26
|
+
groupId,
|
|
27
|
+
applySorting,
|
|
28
|
+
directChildrenOnly: true,
|
|
29
|
+
skipAutoGeneratedRows: false,
|
|
30
|
+
applyFiltering: aggregationRowsScope === 'filtered'
|
|
15
31
|
});
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// If the row is a group, we want to aggregate based on its children
|
|
23
|
-
// For instance in the following tree, we want the aggregated values of A to be based on A.A, A.B.A and A.B.B but not A.B
|
|
24
|
-
// A
|
|
25
|
-
// A.A
|
|
26
|
-
// A.B
|
|
27
|
-
// A.B.A
|
|
28
|
-
// A.B.B
|
|
29
|
-
const rowNode = (0, _xDataGridPro.gridRowNodeSelector)(apiRef, rowId);
|
|
32
|
+
for (let i = 0; i < rowIds.length; i += 1) {
|
|
33
|
+
const rowId = rowIds[i];
|
|
34
|
+
const rowNode = rowTree[rowId];
|
|
30
35
|
if (rowNode.type === 'group') {
|
|
31
|
-
|
|
36
|
+
// MERGE EXISTING VALUES FROM THE LOOKUP TABLE
|
|
37
|
+
const childGroupValues = groupAggregatedValuesLookup.get(rowId);
|
|
38
|
+
if (childGroupValues) {
|
|
39
|
+
for (let j = 0; j < aggregatedFields.length; j += 1) {
|
|
40
|
+
aggregatedValues[j].values = aggregatedValues[j].values.concat(childGroupValues[j].values);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
continue;
|
|
32
44
|
}
|
|
33
|
-
const row =
|
|
45
|
+
const row = rowLookup[rowId];
|
|
34
46
|
for (let j = 0; j < aggregatedFields.length; j += 1) {
|
|
35
47
|
const aggregatedField = aggregatedFields[j];
|
|
36
48
|
const columnAggregationRules = aggregationRules[aggregatedField];
|
|
37
49
|
const aggregationFunction = columnAggregationRules.aggregationFunction;
|
|
38
50
|
const field = aggregatedField;
|
|
39
|
-
|
|
40
|
-
aggregatedValues[j] = {
|
|
41
|
-
aggregatedField,
|
|
42
|
-
values: []
|
|
43
|
-
};
|
|
44
|
-
}
|
|
51
|
+
let value;
|
|
45
52
|
if (typeof aggregationFunction.getCellValue === 'function') {
|
|
46
|
-
|
|
53
|
+
value = aggregationFunction.getCellValue({
|
|
54
|
+
field,
|
|
47
55
|
row
|
|
48
|
-
})
|
|
56
|
+
});
|
|
57
|
+
} else if (isPivotActive) {
|
|
58
|
+
// Since we know that pivoted fields are flat, we can use the row directly, and save lots of processing time
|
|
59
|
+
value = row[field];
|
|
49
60
|
} else {
|
|
50
|
-
|
|
51
|
-
|
|
61
|
+
if (!row) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const valueGetter = valueGetters[aggregatedField];
|
|
65
|
+
value = valueGetter(row);
|
|
66
|
+
}
|
|
67
|
+
if (value !== undefined) {
|
|
68
|
+
aggregatedValues[j].values.push(value);
|
|
52
69
|
}
|
|
53
70
|
}
|
|
54
|
-
}
|
|
71
|
+
}
|
|
55
72
|
for (let i = 0; i < aggregatedValues.length; i += 1) {
|
|
56
73
|
const {
|
|
57
74
|
aggregatedField,
|
|
@@ -62,13 +79,16 @@ const getGroupAggregatedValue = (groupId, apiRef, aggregationRowsScope, aggregat
|
|
|
62
79
|
values,
|
|
63
80
|
groupId,
|
|
64
81
|
field: aggregatedField // Added per user request in https://github.com/mui/mui-x/issues/6995#issuecomment-1327423455
|
|
65
|
-
});
|
|
82
|
+
}, publicApi);
|
|
66
83
|
groupAggregationLookup[aggregatedField] = {
|
|
67
84
|
position,
|
|
68
85
|
value
|
|
69
86
|
};
|
|
70
87
|
}
|
|
71
|
-
return
|
|
88
|
+
return {
|
|
89
|
+
groupAggregationLookup,
|
|
90
|
+
aggregatedValues
|
|
91
|
+
};
|
|
72
92
|
};
|
|
73
93
|
const getGroupAggregatedValueDataSource = (groupId, apiRef, aggregatedFields, position) => {
|
|
74
94
|
const groupAggregationLookup = {};
|
|
@@ -83,21 +103,37 @@ const getGroupAggregatedValueDataSource = (groupId, apiRef, aggregatedFields, po
|
|
|
83
103
|
};
|
|
84
104
|
const createAggregationLookup = ({
|
|
85
105
|
apiRef,
|
|
86
|
-
|
|
106
|
+
aggregationRules,
|
|
107
|
+
aggregatedFields,
|
|
87
108
|
aggregationRowsScope,
|
|
88
109
|
getAggregationPosition,
|
|
89
|
-
isDataSource
|
|
110
|
+
isDataSource,
|
|
111
|
+
applySorting = false
|
|
90
112
|
}) => {
|
|
91
|
-
const aggregationRules = (0, _gridAggregationUtils.getAggregationRules)((0, _xDataGridPro.gridColumnLookupSelector)(apiRef), (0, _gridAggregationSelectors.gridAggregationModelSelector)(apiRef), aggregationFunctions, isDataSource);
|
|
92
|
-
const aggregatedFields = Object.keys(aggregationRules);
|
|
93
113
|
if (aggregatedFields.length === 0) {
|
|
94
114
|
return {};
|
|
95
115
|
}
|
|
116
|
+
const columnsLookup = (0, _xDataGridPro.gridColumnLookupSelector)(apiRef);
|
|
117
|
+
const valueGetters = {};
|
|
118
|
+
for (let i = 0; i < aggregatedFields.length; i += 1) {
|
|
119
|
+
const field = aggregatedFields[i];
|
|
120
|
+
const column = columnsLookup[field];
|
|
121
|
+
const valueGetter = row => apiRef.current.getRowValue(row, column);
|
|
122
|
+
valueGetters[field] = valueGetter;
|
|
123
|
+
}
|
|
96
124
|
const aggregationLookup = {};
|
|
97
125
|
const rowTree = (0, _xDataGridPro.gridRowTreeSelector)(apiRef);
|
|
126
|
+
const groupAggregatedValuesLookup = new Map();
|
|
127
|
+
const {
|
|
128
|
+
rowIdToIndexMap
|
|
129
|
+
} = (0, _internals.getVisibleRows)(apiRef);
|
|
98
130
|
const createGroupAggregationLookup = groupNode => {
|
|
99
|
-
|
|
100
|
-
|
|
131
|
+
let children = groupNode.children;
|
|
132
|
+
if (applySorting) {
|
|
133
|
+
children = children.toSorted((a, b) => rowIdToIndexMap.get(a) - rowIdToIndexMap.get(b));
|
|
134
|
+
}
|
|
135
|
+
for (let i = 0; i < children.length; i += 1) {
|
|
136
|
+
const childId = children[i];
|
|
101
137
|
const childNode = rowTree[childId];
|
|
102
138
|
if (childNode.type === 'group') {
|
|
103
139
|
createGroupAggregationLookup(childNode);
|
|
@@ -108,7 +144,9 @@ const createAggregationLookup = ({
|
|
|
108
144
|
if (isDataSource) {
|
|
109
145
|
aggregationLookup[groupNode.id] = getGroupAggregatedValueDataSource(groupNode.id, apiRef, aggregatedFields, position);
|
|
110
146
|
} else if (groupNode.children.length) {
|
|
111
|
-
|
|
147
|
+
const result = getGroupAggregatedValue(groupNode.id, apiRef, aggregationRowsScope, aggregatedFields, aggregationRules, position, applySorting, valueGetters, apiRef.current, groupAggregatedValuesLookup);
|
|
148
|
+
aggregationLookup[groupNode.id] = result.groupAggregationLookup;
|
|
149
|
+
groupAggregatedValuesLookup.set(groupNode.id, result.aggregatedValues);
|
|
112
150
|
}
|
|
113
151
|
}
|
|
114
152
|
};
|
|
@@ -12,7 +12,7 @@ const sumAgg = {
|
|
|
12
12
|
let sum = 0;
|
|
13
13
|
for (let i = 0; i < values.length; i += 1) {
|
|
14
14
|
const value = values[i];
|
|
15
|
-
if (
|
|
15
|
+
if (typeof value === 'number' && !Number.isNaN(value)) {
|
|
16
16
|
sum += value;
|
|
17
17
|
}
|
|
18
18
|
}
|
|
@@ -31,7 +31,7 @@ const avgAgg = {
|
|
|
31
31
|
let valuesCount = 0;
|
|
32
32
|
for (let i = 0; i < values.length; i += 1) {
|
|
33
33
|
const value = values[i];
|
|
34
|
-
if (
|
|
34
|
+
if (typeof value === 'number' && !Number.isNaN(value)) {
|
|
35
35
|
valuesCount += 1;
|
|
36
36
|
sum += value;
|
|
37
37
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { GridRowId, GridRowModel, GridColDef, GridValueFormatter } from '@mui/x-data-grid-pro';
|
|
2
|
+
import { GridApiPremium } from "../../../models/gridApiPremium.js";
|
|
2
3
|
export interface GridAggregationState {
|
|
3
4
|
model: GridAggregationModel;
|
|
4
5
|
lookup: GridAggregationLookup;
|
|
@@ -28,6 +29,10 @@ export interface GridAggregationGetCellValueParams {
|
|
|
28
29
|
* The row model of the row that the current cell belongs to.
|
|
29
30
|
*/
|
|
30
31
|
row: GridRowModel;
|
|
32
|
+
/**
|
|
33
|
+
* The field of the cell that the aggregation function is applied to.
|
|
34
|
+
*/
|
|
35
|
+
field: GridColDef['field'];
|
|
31
36
|
}
|
|
32
37
|
/**
|
|
33
38
|
* Grid aggregation function definition interface.
|
|
@@ -39,9 +44,10 @@ export interface GridAggregationFunction<V = any, AV = V> {
|
|
|
39
44
|
* Function that takes the current cell values and generates the aggregated value.
|
|
40
45
|
* @template V, AV
|
|
41
46
|
* @param {GridAggregationParams<V>} params The params of the current aggregated cell.
|
|
47
|
+
* @param {GridApiPremium} api The grid API.
|
|
42
48
|
* @returns {AV} The aggregated value.
|
|
43
49
|
*/
|
|
44
|
-
apply: (params: GridAggregationParams<V
|
|
50
|
+
apply: (params: GridAggregationParams<V>, api: GridApiPremium) => AV | null | undefined;
|
|
45
51
|
/**
|
|
46
52
|
* Label of the aggregation function.
|
|
47
53
|
* Used for adding a label to the footer of the grouping column when this aggregation function is the only one being used.
|
|
@@ -72,6 +78,12 @@ export interface GridAggregationFunction<V = any, AV = V> {
|
|
|
72
78
|
* @returns {V} The value of the cell that will be passed to the aggregation `apply` function
|
|
73
79
|
*/
|
|
74
80
|
getCellValue?: (params: GridAggregationGetCellValueParams) => V;
|
|
81
|
+
/**
|
|
82
|
+
* Indicates if the aggregation function depends on rows being in a sorted order.
|
|
83
|
+
* If `true`, the values provided to `apply` will be sorted.
|
|
84
|
+
* @default false
|
|
85
|
+
*/
|
|
86
|
+
applySorting?: boolean;
|
|
75
87
|
}
|
|
76
88
|
/**
|
|
77
89
|
* Grid aggregation function data source definition interface.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RefObject } from '@mui/x-internals/types';
|
|
2
|
-
import { GridColDef, GridRowId } from '@mui/x-data-grid-pro';
|
|
2
|
+
import { GridColDef, GridRowId, GridGroupNode } from '@mui/x-data-grid-pro';
|
|
3
3
|
import { GridColumnRawLookup, GridHydrateRowsValue } from '@mui/x-data-grid-pro/internals';
|
|
4
4
|
import { GridAggregationFunction, GridAggregationFunctionDataSource, GridAggregationModel, GridAggregationRule, GridAggregationRules } from "./gridAggregationInterfaces.js";
|
|
5
5
|
import { GridStatePremium } from "../../../models/gridStatePremium.js";
|
|
@@ -59,4 +59,5 @@ export declare const getAggregationFunctionLabel: ({
|
|
|
59
59
|
apiRef: RefObject<GridApiPremium>;
|
|
60
60
|
aggregationRule: GridAggregationRule;
|
|
61
61
|
}) => string;
|
|
62
|
+
export declare const defaultGetAggregationPosition: (groupNode: GridGroupNode) => "inline" | "footer";
|
|
62
63
|
export {};
|
|
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.mergeStateWithAggregationModel = exports.getAvailableAggregationFunctions = exports.getAggregationRules = exports.getAggregationFunctionLabel = exports.getAggregationFooterRowIdFromGroupId = exports.canColumnHaveAggregationFunction = exports.areAggregationRulesEqual = exports.addFooterRows = exports.GRID_AGGREGATION_ROOT_FOOTER_ROW_ID = void 0;
|
|
7
|
+
exports.mergeStateWithAggregationModel = exports.getAvailableAggregationFunctions = exports.getAggregationRules = exports.getAggregationFunctionLabel = exports.getAggregationFooterRowIdFromGroupId = exports.defaultGetAggregationPosition = exports.canColumnHaveAggregationFunction = exports.areAggregationRulesEqual = exports.addFooterRows = exports.GRID_AGGREGATION_ROOT_FOOTER_ROW_ID = void 0;
|
|
8
8
|
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
9
9
|
var _capitalize = _interopRequireDefault(require("@mui/utils/capitalize"));
|
|
10
10
|
var _internals = require("@mui/x-data-grid/internals");
|
|
@@ -192,4 +192,6 @@ const getAggregationFunctionLabel = ({
|
|
|
192
192
|
return aggregationRule.aggregationFunctionName;
|
|
193
193
|
}
|
|
194
194
|
};
|
|
195
|
-
exports.getAggregationFunctionLabel = getAggregationFunctionLabel;
|
|
195
|
+
exports.getAggregationFunctionLabel = getAggregationFunctionLabel;
|
|
196
|
+
const defaultGetAggregationPosition = groupNode => groupNode.depth === -1 ? 'footer' : 'inline';
|
|
197
|
+
exports.defaultGetAggregationPosition = defaultGetAggregationPosition;
|
|
@@ -44,20 +44,95 @@ const useGridAggregation = (apiRef, props) => {
|
|
|
44
44
|
apiRef.current.setState((0, _gridAggregationUtils.mergeStateWithAggregationModel)(model));
|
|
45
45
|
}
|
|
46
46
|
}, [apiRef]);
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
47
|
+
const abortControllerRef = React.useRef(null);
|
|
48
|
+
const applyAggregation = React.useCallback(reason => {
|
|
49
|
+
// Abort previous if any
|
|
50
|
+
if (abortControllerRef.current) {
|
|
51
|
+
abortControllerRef.current.abort();
|
|
52
|
+
}
|
|
53
|
+
const abortController = new AbortController();
|
|
54
|
+
abortControllerRef.current = abortController;
|
|
55
|
+
const aggregationRules = (0, _gridAggregationUtils.getAggregationRules)((0, _xDataGridPro.gridColumnLookupSelector)(apiRef), (0, _gridAggregationSelectors.gridAggregationModelSelector)(apiRef), props.aggregationFunctions, !!props.dataSource);
|
|
56
|
+
const aggregatedFields = Object.keys(aggregationRules);
|
|
57
|
+
const needsSorting = (0, _createAggregationLookup.shouldApplySorting)(aggregationRules, aggregatedFields);
|
|
58
|
+
if (reason === 'sort' && !needsSorting) {
|
|
59
|
+
// no need to re-apply aggregation on `sortedRowsSet` if sorting is not needed
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const renderContext = (0, _xDataGridPro.gridRenderContextSelector)(apiRef);
|
|
63
|
+
const visibleColumns = (0, _xDataGridPro.gridVisibleColumnFieldsSelector)(apiRef);
|
|
64
|
+
const chunks = [];
|
|
65
|
+
const visibleAggregatedFields = visibleColumns.slice(renderContext.firstColumnIndex, renderContext.lastColumnIndex + 1).filter(field => aggregatedFields.includes(field));
|
|
66
|
+
if (visibleAggregatedFields.length > 0) {
|
|
67
|
+
chunks.push(visibleAggregatedFields);
|
|
68
|
+
}
|
|
69
|
+
const otherAggregatedFields = aggregatedFields.filter(field => !visibleAggregatedFields.includes(field));
|
|
70
|
+
const chunkSize = 20; // columns per chunk
|
|
71
|
+
for (let i = 0; i < otherAggregatedFields.length; i += chunkSize) {
|
|
72
|
+
chunks.push(otherAggregatedFields.slice(i, i + chunkSize));
|
|
73
|
+
}
|
|
74
|
+
let chunkIndex = 0;
|
|
75
|
+
const aggregationLookup = {};
|
|
76
|
+
let chunkStartTime = performance.now();
|
|
77
|
+
const timeLimit = 1000 / 120;
|
|
78
|
+
const processChunk = () => {
|
|
79
|
+
if (abortController.signal.aborted) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const currentChunk = chunks[chunkIndex];
|
|
83
|
+
if (!currentChunk) {
|
|
84
|
+
const sortModel = (0, _xDataGridPro.gridSortModelSelector)(apiRef).map(s => s.field);
|
|
85
|
+
const hasAggregatedSorting = sortModel.some(field => aggregationRules[field]);
|
|
86
|
+
if (hasAggregatedSorting) {
|
|
87
|
+
apiRef.current.applySorting();
|
|
88
|
+
}
|
|
89
|
+
abortControllerRef.current = null;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const applySorting = (0, _createAggregationLookup.shouldApplySorting)(aggregationRules, currentChunk);
|
|
93
|
+
|
|
94
|
+
// createAggregationLookup now RETURNS new partial lookup
|
|
95
|
+
const partialLookup = (0, _createAggregationLookup.createAggregationLookup)({
|
|
96
|
+
apiRef,
|
|
97
|
+
getAggregationPosition: props.getAggregationPosition,
|
|
98
|
+
aggregatedFields: currentChunk,
|
|
99
|
+
aggregationRules,
|
|
100
|
+
aggregationRowsScope: props.aggregationRowsScope,
|
|
101
|
+
isDataSource: !!props.dataSource,
|
|
102
|
+
applySorting
|
|
103
|
+
});
|
|
104
|
+
for (const key of Object.keys(partialLookup)) {
|
|
105
|
+
for (const field of Object.keys(partialLookup[key])) {
|
|
106
|
+
aggregationLookup[key] ?? (aggregationLookup[key] = {});
|
|
107
|
+
aggregationLookup[key][field] = partialLookup[key][field];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
|
|
111
|
+
aggregation: (0, _extends2.default)({}, state.aggregation, {
|
|
112
|
+
lookup: (0, _extends2.default)({}, aggregationLookup)
|
|
113
|
+
})
|
|
114
|
+
}));
|
|
115
|
+
chunkIndex += 1;
|
|
116
|
+
if (performance.now() - chunkStartTime < timeLimit) {
|
|
117
|
+
processChunk();
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
setTimeout(() => {
|
|
121
|
+
chunkStartTime = performance.now();
|
|
122
|
+
processChunk();
|
|
123
|
+
}, 0);
|
|
124
|
+
};
|
|
125
|
+
processChunk();
|
|
60
126
|
}, [apiRef, props.getAggregationPosition, props.aggregationFunctions, props.aggregationRowsScope, props.dataSource]);
|
|
127
|
+
React.useEffect(() => {
|
|
128
|
+
return () => {
|
|
129
|
+
if (abortControllerRef.current) {
|
|
130
|
+
abortControllerRef.current.abort();
|
|
131
|
+
abortControllerRef.current = null;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
}, []);
|
|
135
|
+
const deferredApplyAggregation = (0, _xDataGridPro.useRunOncePerLoop)(applyAggregation);
|
|
61
136
|
const aggregationApi = {
|
|
62
137
|
setAggregationModel
|
|
63
138
|
};
|
|
@@ -86,17 +161,18 @@ const useGridAggregation = (apiRef, props) => {
|
|
|
86
161
|
// Re-apply the row hydration to add / remove the aggregation footers
|
|
87
162
|
if (!props.dataSource && !(0, _gridAggregationUtils.areAggregationRulesEqual)(rulesOnLastRowHydration, aggregationRules)) {
|
|
88
163
|
apiRef.current.requestPipeProcessorsApplication('hydrateRows');
|
|
89
|
-
|
|
164
|
+
deferredApplyAggregation();
|
|
90
165
|
}
|
|
91
166
|
|
|
92
167
|
// Re-apply the column hydration to wrap / unwrap the aggregated columns
|
|
93
168
|
if (!(0, _gridAggregationUtils.areAggregationRulesEqual)(rulesOnLastColumnHydration, aggregationRules)) {
|
|
94
169
|
apiRef.current.requestPipeProcessorsApplication('hydrateColumns');
|
|
95
170
|
}
|
|
96
|
-
}, [apiRef,
|
|
171
|
+
}, [apiRef, deferredApplyAggregation, props.aggregationFunctions, props.disableAggregation, props.dataSource]);
|
|
97
172
|
(0, _xDataGridPro.useGridEvent)(apiRef, 'aggregationModelChange', checkAggregationRulesDiff);
|
|
98
173
|
(0, _xDataGridPro.useGridEvent)(apiRef, 'columnsChange', checkAggregationRulesDiff);
|
|
99
|
-
(0, _xDataGridPro.useGridEvent)(apiRef, 'filteredRowsSet',
|
|
174
|
+
(0, _xDataGridPro.useGridEvent)(apiRef, 'filteredRowsSet', deferredApplyAggregation);
|
|
175
|
+
(0, _xDataGridPro.useGridEvent)(apiRef, 'sortedRowsSet', () => deferredApplyAggregation('sort'));
|
|
100
176
|
|
|
101
177
|
/**
|
|
102
178
|
* EFFECTS
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import type { GridColDef } from '@mui/x-data-grid-pro';
|
|
1
|
+
import type { GridColDef, GridRowModel } from '@mui/x-data-grid-pro';
|
|
2
2
|
import type { GridPivotingPrivateApiCommunity, GridPivotingStatePartial } from '@mui/x-data-grid/internals';
|
|
3
|
+
import type { RefObject } from '@mui/x-internals/types';
|
|
3
4
|
import type { DataGridPremiumProcessedProps } from "../../../models/dataGridPremiumProps.js";
|
|
5
|
+
import type { GridInitialStatePremium } from "../../../models/gridStatePremium.js";
|
|
4
6
|
export type GridPivotingPropsOverrides = {
|
|
5
7
|
rows: DataGridPremiumProcessedProps['rows'];
|
|
6
8
|
columns: DataGridPremiumProcessedProps['columns'];
|
|
@@ -66,4 +68,12 @@ export interface GridPivotingPrivateApi extends GridPivotingPrivateApiCommunity
|
|
|
66
68
|
targetFieldPosition?: DropPosition;
|
|
67
69
|
}) => void;
|
|
68
70
|
}
|
|
69
|
-
export type GridPivotingColDefOverrides = Pick<GridColDef, 'width' | 'flex' | 'headerName' | 'description' | 'align' | 'headerAlign' | 'cellClassName' | 'headerClassName' | 'display' | 'maxWidth' | 'minWidth' | 'resizable' | 'sortingOrder'>;
|
|
71
|
+
export type GridPivotingColDefOverrides = Pick<GridColDef, 'width' | 'flex' | 'headerName' | 'description' | 'align' | 'headerAlign' | 'cellClassName' | 'headerClassName' | 'display' | 'maxWidth' | 'minWidth' | 'resizable' | 'sortingOrder'>;
|
|
72
|
+
export interface GridPivotingInternalCache {
|
|
73
|
+
nonPivotDataRef: RefObject<{
|
|
74
|
+
rows: GridRowModel[];
|
|
75
|
+
columns: Map<string, GridColDef>;
|
|
76
|
+
originalRowsProp: readonly GridRowModel[];
|
|
77
|
+
} | undefined>;
|
|
78
|
+
exportedStateRef: RefObject<GridInitialStatePremium | null>;
|
|
79
|
+
}
|
|
@@ -4,4 +4,5 @@ import { GridStateInitializer } from '@mui/x-data-grid-pro/internals';
|
|
|
4
4
|
import type { DataGridPremiumProcessedProps } from "../../../models/dataGridPremiumProps.js";
|
|
5
5
|
import { GridPrivateApiPremium } from "../../../models/gridApiPremium.js";
|
|
6
6
|
export declare const pivotingStateInitializer: GridStateInitializer<Pick<DataGridPremiumProcessedProps, 'pivotActive' | 'pivotModel' | 'pivotPanelOpen' | 'initialState' | 'disablePivoting' | 'getPivotDerivedColumns' | 'columns'>>;
|
|
7
|
-
export declare const useGridPivoting: (apiRef: RefObject<GridPrivateApiPremium>, props: Pick<DataGridPremiumProcessedProps, "pivotActive" | "onPivotActiveChange" | "pivotModel" | "onPivotModelChange" | "pivotPanelOpen" | "onPivotPanelOpenChange" | "disablePivoting" | "getPivotDerivedColumns" | "pivotingColDef" | "aggregationFunctions">, originalColumnsProp: readonly GridColDef[], originalRowsProp: readonly GridRowModel[]) => void;
|
|
7
|
+
export declare const useGridPivoting: (apiRef: RefObject<GridPrivateApiPremium>, props: Pick<DataGridPremiumProcessedProps, "pivotActive" | "onPivotActiveChange" | "pivotModel" | "onPivotModelChange" | "pivotPanelOpen" | "onPivotPanelOpenChange" | "disablePivoting" | "getPivotDerivedColumns" | "pivotingColDef" | "groupingColDef" | "aggregationFunctions">, originalColumnsProp: readonly GridColDef[], originalRowsProp: readonly GridRowModel[]) => void;
|
|
8
|
+
export declare const useGridPivotingExportState: (apiRef: RefObject<GridPrivateApiPremium>) => void;
|