@mui/x-data-grid-generator 8.13.0 → 8.14.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 +171 -1
- package/columns/commodities.columns.js +1 -0
- package/esm/columns/commodities.columns.js +1 -0
- package/esm/hooks/serverUtils.d.ts +22 -6
- package/esm/hooks/serverUtils.js +318 -12
- package/esm/hooks/useMockServer.d.ts +1 -1
- package/esm/hooks/useMockServer.js +70 -19
- package/esm/hooks/useQuery.d.ts +3 -0
- package/esm/index.js +1 -1
- package/esm/renderer/renderProgress.d.ts +1 -1
- package/esm/renderer/renderProgress.js +3 -0
- package/esm/renderer/renderTotalPrice.js +14 -4
- package/esm/services/gridColDefGenerator.d.ts +4 -0
- package/hooks/serverUtils.d.ts +22 -6
- package/hooks/serverUtils.js +320 -13
- package/hooks/useMockServer.d.ts +1 -1
- package/hooks/useMockServer.js +69 -18
- package/hooks/useQuery.d.ts +3 -0
- package/index.js +1 -1
- package/package.json +5 -5
- package/renderer/renderProgress.d.ts +1 -1
- package/renderer/renderProgress.js +3 -0
- package/renderer/renderTotalPrice.js +14 -4
- package/services/gridColDefGenerator.d.ts +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,176 @@
|
|
|
5
5
|
All notable changes to this project will be documented in this file.
|
|
6
6
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
7
7
|
|
|
8
|
+
## 8.14.0
|
|
9
|
+
|
|
10
|
+
_Oct 9, 2025_
|
|
11
|
+
|
|
12
|
+
We'd like to extend a big thank you to the 14 contributors who made this release possible. Here are some highlights ✨:
|
|
13
|
+
|
|
14
|
+
- 📊 The [Chart zoom now supports the `pressAndDrag` gesture](https://mui.com/x/react-charts/zoom-and-pan/#zoom-interactions-configuration). Pan by pressing and dragging.
|
|
15
|
+
- 🔄 [Server-side pivoting](https://mui.com/x/react-data-grid/server-side-data/pivoting/) support for the Data Grid
|
|
16
|
+
- 🐞 Bugfixes
|
|
17
|
+
- 📚 Documentation improvements
|
|
18
|
+
|
|
19
|
+
Special thanks go out to the community members for their valuable contributions:
|
|
20
|
+
@djpremier, @Utkarsh-0304
|
|
21
|
+
|
|
22
|
+
The following are all team members who have contributed to this release:
|
|
23
|
+
@alexfauquette, @bernardobelchior, @flaviendelangle, @hasdfa, @Janpot, @JCQuintas, @prakhargupta1, @rita-codes, @noraleonte, @brijeshb42, @arminmeh, @michelengelen
|
|
24
|
+
|
|
25
|
+
### Data Grid
|
|
26
|
+
|
|
27
|
+
#### `@mui/x-data-grid@8.14.0`
|
|
28
|
+
|
|
29
|
+
- [l10n] Improve Brazilian Portuguese (pt-BR) locale (#19658) @djpremier
|
|
30
|
+
|
|
31
|
+
#### `@mui/x-data-grid-pro@8.14.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
32
|
+
|
|
33
|
+
Same changes as in `@mui/x-data-grid@8.14.0`.
|
|
34
|
+
|
|
35
|
+
#### `@mui/x-data-grid-premium@8.14.0` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
36
|
+
|
|
37
|
+
Same changes as in `@mui/x-data-grid-pro@8.14.0`, plus:
|
|
38
|
+
|
|
39
|
+
- [DataGridPremium] Server-side pivoting (#19575) @arminmeh
|
|
40
|
+
|
|
41
|
+
### Date and Time Pickers
|
|
42
|
+
|
|
43
|
+
#### `@mui/x-date-pickers@8.14.0`
|
|
44
|
+
|
|
45
|
+
- [pickers] Fixed the extra element for the disabled date picker (#19387) @Utkarsh-0304
|
|
46
|
+
- [pickers] Fix input `autoCapitalize` value for Firefox compatibility (#19285) @michelengelen
|
|
47
|
+
- [l10n] Improve Brazilian Portuguese (pt-BR) locale (#19658) @djpremier
|
|
48
|
+
|
|
49
|
+
#### `@mui/x-date-pickers-pro@8.14.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
50
|
+
|
|
51
|
+
Same changes as in `@mui/x-date-pickers@8.14.0`.
|
|
52
|
+
|
|
53
|
+
### Charts
|
|
54
|
+
|
|
55
|
+
#### `@mui/x-charts@8.14.0`
|
|
56
|
+
|
|
57
|
+
- [charts] Add `pressAndDrag` pan gesture (#19779) @JCQuintas
|
|
58
|
+
- [charts] Allow `minPointers` and `maxPointers` to be configured by pointer type (#19794) @JCQuintas
|
|
59
|
+
- [charts] Correct scale domain types (#19844) @bernardobelchior
|
|
60
|
+
- [charts] Fix tooltip position when scrolling (#19857) @alexfauquette
|
|
61
|
+
- [charts] Link item highlight with keyboard navigation (#19768) @alexfauquette
|
|
62
|
+
- [charts] Refactor domain/scale selectors (#19832) @bernardobelchior
|
|
63
|
+
- [charts] Remove min/max from ordinal configuration (#19789) @alexfauquette
|
|
64
|
+
- [charts] Simplify axes filters selectors (#19833) @bernardobelchior
|
|
65
|
+
- [l10n] Improve Brazilian Portuguese (pt-BR) locale (#19658) @djpremier
|
|
66
|
+
|
|
67
|
+
#### `@mui/x-charts-pro@8.14.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
68
|
+
|
|
69
|
+
Same changes as in `@mui/x-charts@8.14.0`.
|
|
70
|
+
|
|
71
|
+
#### `@mui/x-charts-premium@8.14.0` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
72
|
+
|
|
73
|
+
Same changes as in `@mui/x-charts-pro@8.14.0`.
|
|
74
|
+
|
|
75
|
+
### Tree View
|
|
76
|
+
|
|
77
|
+
#### `@mui/x-tree-view@8.14.0`
|
|
78
|
+
|
|
79
|
+
- [tree view] Fix Tree View tooltip anchoring on overview page (#19806) @noraleonte
|
|
80
|
+
|
|
81
|
+
#### `@mui/x-tree-view-pro@8.14.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
82
|
+
|
|
83
|
+
Same changes as in `@mui/x-tree-view@8.14.0`.
|
|
84
|
+
|
|
85
|
+
### Codemod
|
|
86
|
+
|
|
87
|
+
#### `@mui/x-codemod@8.14.0`
|
|
88
|
+
|
|
89
|
+
Internal changes.
|
|
90
|
+
|
|
91
|
+
### Docs
|
|
92
|
+
|
|
93
|
+
- [docs] Add overview section for pie chart (#19672) @prakhargupta1
|
|
94
|
+
- [docs] Fix demo title knob keys (#19843) @JCQuintas
|
|
95
|
+
- [docs] Hide UI elements of unsupported features in the data source demos (#19849) @arminmeh
|
|
96
|
+
|
|
97
|
+
### Core
|
|
98
|
+
|
|
99
|
+
- [code-infra] Cleanup unused dependencies (#19788) @brijeshb42
|
|
100
|
+
- [code-infra] Fix pnpm-lock issue (#19861) @JCQuintas
|
|
101
|
+
- [code-infra] Improve publishing docs (#19404) @Janpot
|
|
102
|
+
- [code-infra] Remove tsconfig `baseUrl` (#19837) @Janpot
|
|
103
|
+
- [code-infra] Support custom npm dist tags during release (#19803) @Janpot
|
|
104
|
+
- [code-infra] Wait longer for print dialog (#19795) @JCQuintas
|
|
105
|
+
- [code-infra] Replace `lodash` with `es-toolkit` (#19853) @bernardobelchior
|
|
106
|
+
- [code-infra] Update release script PR checklist (#19785) @bernardobelchior
|
|
107
|
+
- [code-infra] Remove remaining usages of `lodash` (#19864) @bernardobelchior
|
|
108
|
+
- [docs-infra] Add `title` knob (#19792) @JCQuintas
|
|
109
|
+
- [docs-infra] Fix missing key in title knob (#19804) @JCQuintas
|
|
110
|
+
|
|
111
|
+
### Miscellaneous
|
|
112
|
+
|
|
113
|
+
- [x-telemetry] Fix transpile issues (#19761) @hasdfa
|
|
114
|
+
- [x-telemetry] Fix ref to deleted file (#19842) @JCQuintas
|
|
115
|
+
|
|
116
|
+
## 8.13.1
|
|
117
|
+
|
|
118
|
+
_Oct 1, 2025_
|
|
119
|
+
|
|
120
|
+
- 🐛 Fix `@mui/x-charts-pro` failure on import due to missing `@mui/x-internals` release
|
|
121
|
+
|
|
122
|
+
### Data Grid
|
|
123
|
+
|
|
124
|
+
#### `@mui/x-data-grid@8.13.1`
|
|
125
|
+
|
|
126
|
+
Internal changes.
|
|
127
|
+
|
|
128
|
+
#### `@mui/x-data-grid-pro@8.13.1` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
129
|
+
|
|
130
|
+
Same changes as in `@mui/x-data-grid@8.13.1`.
|
|
131
|
+
|
|
132
|
+
#### `@mui/x-data-grid-premium@8.13.1` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
133
|
+
|
|
134
|
+
Same changes as in `@mui/x-data-grid-pro@8.13.1`.
|
|
135
|
+
|
|
136
|
+
### Date and Time Pickers
|
|
137
|
+
|
|
138
|
+
#### `@mui/x-date-pickers@8.12.0`
|
|
139
|
+
|
|
140
|
+
Internal changes.
|
|
141
|
+
|
|
142
|
+
#### `@mui/x-date-pickers-pro@8.12.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
143
|
+
|
|
144
|
+
Same changes as in `@mui/x-date-pickers@8.12.0`.
|
|
145
|
+
|
|
146
|
+
### Charts
|
|
147
|
+
|
|
148
|
+
#### `@mui/x-charts@8.13.1`
|
|
149
|
+
|
|
150
|
+
Internal changes.
|
|
151
|
+
|
|
152
|
+
#### `@mui/x-charts-pro@8.13.1` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
153
|
+
|
|
154
|
+
Same changes as in `@mui/x-charts@8.13.1`, plus:
|
|
155
|
+
|
|
156
|
+
- [charts-pro] Fix `@mui/x-charts-pro` failure on import due to missing `@mui/x-internals` release @bernardobelchior
|
|
157
|
+
|
|
158
|
+
#### `@mui/x-charts-premium@8.13.1` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
159
|
+
|
|
160
|
+
Same changes as in `@mui/x-charts-pro@8.13.1`.
|
|
161
|
+
|
|
162
|
+
### Tree View
|
|
163
|
+
|
|
164
|
+
#### `@mui/x-tree-view@8.13.1`
|
|
165
|
+
|
|
166
|
+
Internal changes.
|
|
167
|
+
|
|
168
|
+
#### `@mui/x-tree-view-pro@8.13.1` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
169
|
+
|
|
170
|
+
Same changes as in `@mui/x-tree-view@8.13.1`.
|
|
171
|
+
|
|
172
|
+
### Codemod
|
|
173
|
+
|
|
174
|
+
#### `@mui/x-codemod@8.12.0`
|
|
175
|
+
|
|
176
|
+
Internal changes.
|
|
177
|
+
|
|
8
178
|
## 8.13.0
|
|
9
179
|
|
|
10
180
|
_Oct 1, 2025_
|
|
@@ -160,7 +330,7 @@ We'd like to extend a big thank you to the 15 contributors who made this release
|
|
|
160
330
|
|
|
161
331
|

|
|
162
332
|
|
|
163
|
-
|
|
333
|
+
👉 [🎥 Watch the full video](https://github.com/user-attachments/assets/28f1848e-dc85-4077-8756-a3e88afd4e54)
|
|
164
334
|
|
|
165
335
|
- ⌨️ Charts keyboard navigation
|
|
166
336
|
- ⚡️ Charts: Add new `renderer="svg-batch"` prop to Scatter charts that provides improved performance for large datasets
|
|
@@ -70,6 +70,7 @@ const getCommodityColumns = (editable = false) => [{
|
|
|
70
70
|
renderEditCell: _renderer.renderEditStatus,
|
|
71
71
|
type: 'singleSelect',
|
|
72
72
|
valueOptions: _staticData.STATUS_OPTIONS,
|
|
73
|
+
valueFormatter: value => value === 'PartiallyFilled' ? 'Partially Filled' : value,
|
|
73
74
|
width: 150,
|
|
74
75
|
editable
|
|
75
76
|
}, {
|
|
@@ -64,6 +64,7 @@ export const getCommodityColumns = (editable = false) => [{
|
|
|
64
64
|
renderEditCell: renderEditStatus,
|
|
65
65
|
type: 'singleSelect',
|
|
66
66
|
valueOptions: STATUS_OPTIONS,
|
|
67
|
+
valueFormatter: value => value === 'PartiallyFilled' ? 'Partially Filled' : value,
|
|
67
68
|
width: 150,
|
|
68
69
|
editable
|
|
69
70
|
}, {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GridRowModel, GridFilterModel, GridSortModel, GridColDef, GridRowId, GridPaginationModel, GridValidRowModel, GridAggregationModel } from '@mui/x-data-grid-premium';
|
|
1
|
+
import { GridRowModel, GridFilterModel, GridSortModel, GridColDef, GridRowId, GridPaginationModel, GridValidRowModel, GridAggregationModel, GridPivotModel, GridGetRowsResponse } from '@mui/x-data-grid-premium';
|
|
2
2
|
export interface FakeServerResponse {
|
|
3
3
|
returnedRows: GridRowModel[];
|
|
4
4
|
aggregateRow?: GridValidRowModel;
|
|
@@ -13,7 +13,15 @@ export interface PageInfo {
|
|
|
13
13
|
pageSize?: number;
|
|
14
14
|
}
|
|
15
15
|
export interface DefaultServerOptions {
|
|
16
|
+
/**
|
|
17
|
+
* The minimum response delay in milliseconds.
|
|
18
|
+
* For a large dataset, the response delay can be larger than the minimum delay.
|
|
19
|
+
*/
|
|
16
20
|
minDelay: number;
|
|
21
|
+
/**
|
|
22
|
+
* The maximum response delay in milliseconds
|
|
23
|
+
* For a large dataset, the response delay can be larger than the maximum delay.
|
|
24
|
+
*/
|
|
17
25
|
maxDelay: number;
|
|
18
26
|
useCursorPagination?: boolean;
|
|
19
27
|
}
|
|
@@ -38,6 +46,15 @@ export interface ServerSideQueryOptions {
|
|
|
38
46
|
start?: number;
|
|
39
47
|
end?: number;
|
|
40
48
|
groupFields?: string[];
|
|
49
|
+
pivotModel?: GridPivotModel;
|
|
50
|
+
}
|
|
51
|
+
interface NestedDataRowsResponse {
|
|
52
|
+
rows: GridRowModel[];
|
|
53
|
+
rootRowCount: number;
|
|
54
|
+
aggregateRow?: GridRowModel;
|
|
55
|
+
}
|
|
56
|
+
interface PivotingDataRowsResponse extends NestedDataRowsResponse {
|
|
57
|
+
pivotColumns: GridGetRowsResponse['pivotColumns'];
|
|
41
58
|
}
|
|
42
59
|
export declare const disableDelay: any;
|
|
43
60
|
export declare const DEFAULT_SERVER_OPTIONS: DefaultServerOptions;
|
|
@@ -45,11 +62,6 @@ export declare const DEFAULT_SERVER_OPTIONS: DefaultServerOptions;
|
|
|
45
62
|
* Simulates server data loading
|
|
46
63
|
*/
|
|
47
64
|
export declare const loadServerRows: (rows: GridRowModel[], queryOptions: QueryOptions, serverOptions: ServerOptions, columnsWithDefaultColDef: GridColDef[]) => Promise<FakeServerResponse>;
|
|
48
|
-
interface NestedDataRowsResponse {
|
|
49
|
-
rows: GridRowModel[];
|
|
50
|
-
rootRowCount: number;
|
|
51
|
-
aggregateRow?: GridRowModel;
|
|
52
|
-
}
|
|
53
65
|
/**
|
|
54
66
|
* Simulates server data for tree-data feature
|
|
55
67
|
*/
|
|
@@ -58,4 +70,8 @@ export declare const processTreeDataRows: (rows: GridRowModel[], queryOptions: S
|
|
|
58
70
|
* Simulates server data for row grouping feature
|
|
59
71
|
*/
|
|
60
72
|
export declare const processRowGroupingRows: (rows: GridValidRowModel[], queryOptions: ServerSideQueryOptions, serverOptions: ServerOptions, columnsWithDefaultColDef: GridColDef[]) => Promise<NestedDataRowsResponse>;
|
|
73
|
+
/**
|
|
74
|
+
* Simulates server data for pivoting feature
|
|
75
|
+
*/
|
|
76
|
+
export declare const processPivotingRows: (rows: GridValidRowModel[], queryOptions: ServerSideQueryOptions, serverOptions: ServerOptions, columnsWithDefaultColDef: GridColDef[]) => Promise<PivotingDataRowsResponse>;
|
|
61
77
|
export {};
|
package/esm/hooks/serverUtils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
|
-
import { GridLogicOperator, GRID_AGGREGATION_FUNCTIONS } from '@mui/x-data-grid-premium';
|
|
2
|
+
import { GridLogicOperator, GRID_AGGREGATION_FUNCTIONS, gridStringOrNumberComparator } from '@mui/x-data-grid-premium';
|
|
3
3
|
import { randomInt } from "../services/random-generator.js";
|
|
4
4
|
const getAvailableAggregationFunctions = columnType => {
|
|
5
5
|
const availableAggregationFunctions = new Map();
|
|
@@ -27,7 +27,7 @@ const getRowComparator = (sortModel, aggregationModel, columnsWithDefaultColDef)
|
|
|
27
27
|
return comparator;
|
|
28
28
|
}
|
|
29
29
|
const sortOperators = sortModel.map(sortItem => {
|
|
30
|
-
const columnField =
|
|
30
|
+
const columnField = sortItem.field;
|
|
31
31
|
const colDef = columnsWithDefaultColDef.find(({
|
|
32
32
|
field
|
|
33
33
|
}) => field === sortItem.field);
|
|
@@ -187,7 +187,7 @@ const applyAggregation = (aggregationModel, colDefs, rows, groupId = 'root') =>
|
|
|
187
187
|
return;
|
|
188
188
|
}
|
|
189
189
|
const values = rows.map(row => row[field]);
|
|
190
|
-
aggregateValues[
|
|
190
|
+
aggregateValues[field] = aggregationFunction.apply({
|
|
191
191
|
values,
|
|
192
192
|
field,
|
|
193
193
|
groupId
|
|
@@ -195,6 +195,49 @@ const applyAggregation = (aggregationModel, colDefs, rows, groupId = 'root') =>
|
|
|
195
195
|
});
|
|
196
196
|
return aggregateValues;
|
|
197
197
|
};
|
|
198
|
+
const generateParentRows = pathsToAutogenerate => {
|
|
199
|
+
return Array.from(pathsToAutogenerate).map(path => {
|
|
200
|
+
const pathArray = path.split(',');
|
|
201
|
+
return {
|
|
202
|
+
id: `auto-generated-parent-${pathArray.join('-')}`,
|
|
203
|
+
path: pathArray.slice(0, pathArray.length),
|
|
204
|
+
group: pathArray.slice(-1)[0]
|
|
205
|
+
};
|
|
206
|
+
});
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Computes pivot aggregations for given pivot column keys
|
|
211
|
+
*/
|
|
212
|
+
const computePivotAggregations = (pivotColumnKeys, rows, visibleValues, columnTypeMap, groupId = 'root', columnGroupIdSeparator = '>->') => {
|
|
213
|
+
const pivotAggregations = {};
|
|
214
|
+
pivotColumnKeys.forEach(pivotColumnKey => {
|
|
215
|
+
const values = rows.map(row => row[pivotColumnKey]).filter(v => v !== undefined);
|
|
216
|
+
if (values.length > 0) {
|
|
217
|
+
// Find the corresponding pivot value configuration
|
|
218
|
+
const pivotValueConfig = visibleValues.find(v => {
|
|
219
|
+
if (visibleValues.length === 0 || !visibleValues[0].field) {
|
|
220
|
+
return v.field === pivotColumnKey;
|
|
221
|
+
}
|
|
222
|
+
// For pivot columns with column grouping, extract the value field from the column name
|
|
223
|
+
const columnParts = pivotColumnKey.split(columnGroupIdSeparator);
|
|
224
|
+
return columnParts[columnParts.length - 1] === v.field;
|
|
225
|
+
});
|
|
226
|
+
if (pivotValueConfig) {
|
|
227
|
+
const availableAggregationFunctions = getAvailableAggregationFunctions(columnTypeMap.get(pivotValueConfig.field));
|
|
228
|
+
const aggregationFunction = availableAggregationFunctions.get(pivotValueConfig.aggFunc);
|
|
229
|
+
if (aggregationFunction) {
|
|
230
|
+
pivotAggregations[pivotColumnKey] = aggregationFunction.apply({
|
|
231
|
+
values,
|
|
232
|
+
field: pivotValueConfig.field,
|
|
233
|
+
groupId
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
return pivotAggregations;
|
|
240
|
+
};
|
|
198
241
|
|
|
199
242
|
/**
|
|
200
243
|
* Simulates server data loading
|
|
@@ -435,7 +478,10 @@ export const processRowGroupingRows = (rows, queryOptions, serverOptions, column
|
|
|
435
478
|
field: f
|
|
436
479
|
}) => f === field);
|
|
437
480
|
if (colDef?.groupingValueGetter) {
|
|
438
|
-
return colDef.groupingValueGetter(row[field], row, colDef, apiRef);
|
|
481
|
+
return String(colDef.groupingValueGetter(row[field], row, colDef, apiRef));
|
|
482
|
+
}
|
|
483
|
+
if (colDef?.valueGetter) {
|
|
484
|
+
return String(colDef.valueGetter(row[field], row, colDef, apiRef));
|
|
439
485
|
}
|
|
440
486
|
return String(row[field]);
|
|
441
487
|
});
|
|
@@ -465,14 +511,7 @@ export const processRowGroupingRows = (rows, queryOptions, serverOptions, column
|
|
|
465
511
|
path: ['']
|
|
466
512
|
}));
|
|
467
513
|
}
|
|
468
|
-
const autogeneratedRows =
|
|
469
|
-
const pathArray = path.split(',');
|
|
470
|
-
return {
|
|
471
|
-
id: `auto-generated-parent-${pathArray.join('-')}`,
|
|
472
|
-
path: pathArray.slice(0, pathArray.length),
|
|
473
|
-
group: pathArray.slice(-1)[0]
|
|
474
|
-
};
|
|
475
|
-
});
|
|
514
|
+
const autogeneratedRows = generateParentRows(pathsToAutogenerate);
|
|
476
515
|
|
|
477
516
|
// apply plain filtering
|
|
478
517
|
const filteredRows = getTreeDataFilteredRows([...autogeneratedRows, ...rowsWithPaths, ...rowsWithMissingGroups], queryOptions.filterModel, columnsWithDefaultColDef);
|
|
@@ -533,4 +572,271 @@ export const processRowGroupingRows = (rows, queryOptions, serverOptions, column
|
|
|
533
572
|
});
|
|
534
573
|
}, delay); // simulate network latency
|
|
535
574
|
});
|
|
575
|
+
};
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Simulates server data for pivoting feature
|
|
579
|
+
*/
|
|
580
|
+
export const processPivotingRows = (rows, queryOptions, serverOptions, columnsWithDefaultColDef) => {
|
|
581
|
+
const {
|
|
582
|
+
minDelay = 100,
|
|
583
|
+
maxDelay = 300
|
|
584
|
+
} = serverOptions;
|
|
585
|
+
if (maxDelay < minDelay) {
|
|
586
|
+
throw new Error('serverOptions.minDelay is larger than serverOptions.maxDelay ');
|
|
587
|
+
}
|
|
588
|
+
if (!queryOptions.pivotModel) {
|
|
589
|
+
throw new Error('queryOptions.pivotModel must be defined to compute pivoting data');
|
|
590
|
+
}
|
|
591
|
+
const delay = randomInt(minDelay, maxDelay);
|
|
592
|
+
const {
|
|
593
|
+
pivotModel
|
|
594
|
+
} = queryOptions;
|
|
595
|
+
const visibleColumns = pivotModel.columns.filter(column => !column.hidden);
|
|
596
|
+
const visibleRows = pivotModel.rows.filter(row => !row.hidden);
|
|
597
|
+
const visibleValues = pivotModel.values.filter(value => !value.hidden);
|
|
598
|
+
|
|
599
|
+
// Create column lookup map for O(1) access
|
|
600
|
+
const columnLookup = new Map();
|
|
601
|
+
for (const column of columnsWithDefaultColDef) {
|
|
602
|
+
columnLookup.set(column.field, column);
|
|
603
|
+
}
|
|
604
|
+
if (visibleRows.length === 0) {
|
|
605
|
+
return new Promise(resolve => {
|
|
606
|
+
setTimeout(() => {
|
|
607
|
+
resolve({
|
|
608
|
+
rows: [],
|
|
609
|
+
rootRowCount: 0,
|
|
610
|
+
pivotColumns: []
|
|
611
|
+
});
|
|
612
|
+
}, delay); // simulate network latency
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// Apply filtering if provided
|
|
617
|
+
let filteredRows = rows;
|
|
618
|
+
if (queryOptions.filterModel) {
|
|
619
|
+
filteredRows = getFilteredRows(rows, queryOptions.filterModel, columnsWithDefaultColDef);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// Create pivot columns based on the pivot model
|
|
623
|
+
const columnGroupIdSeparator = '>->';
|
|
624
|
+
const pivotColumns = [];
|
|
625
|
+
const uniqueColumnGroups = new Map();
|
|
626
|
+
|
|
627
|
+
// Generate pivot column names based on pivot model columns
|
|
628
|
+
if (visibleColumns.length > 0 || visibleValues.length > 0) {
|
|
629
|
+
// Create column groups based on unique combinations of row values
|
|
630
|
+
|
|
631
|
+
filteredRows = filteredRows.map(row => {
|
|
632
|
+
const columnGroupPath = [];
|
|
633
|
+
const updatedRow = _extends({}, row);
|
|
634
|
+
for (let i = 0; i < visibleColumns.length; i += 1) {
|
|
635
|
+
const {
|
|
636
|
+
field: colGroupField
|
|
637
|
+
} = visibleColumns[i];
|
|
638
|
+
const column = columnLookup.get(colGroupField);
|
|
639
|
+
if (!column) {
|
|
640
|
+
continue;
|
|
641
|
+
}
|
|
642
|
+
if (!column.valueGetter && !column.valueFormatter) {
|
|
643
|
+
columnGroupPath.push(row[colGroupField]);
|
|
644
|
+
} else {
|
|
645
|
+
columnGroupPath.push({
|
|
646
|
+
[colGroupField]: column.valueGetter ? column.valueGetter(row[colGroupField], row, column, apiRef) : row[colGroupField]
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// Create pivot columns for each value field within this column group
|
|
652
|
+
visibleValues.forEach(pivotValue => {
|
|
653
|
+
let valueKey = pivotValue.field;
|
|
654
|
+
const column = columnLookup.get(valueKey);
|
|
655
|
+
if (!column) {
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
if (visibleColumns.length > 0) {
|
|
659
|
+
const columnGroupPathValue = columnGroupPath.map((path, pathIndex) => {
|
|
660
|
+
const value = path[visibleColumns[pathIndex].field];
|
|
661
|
+
if (value instanceof Date) {
|
|
662
|
+
return value.toLocaleDateString();
|
|
663
|
+
}
|
|
664
|
+
return value;
|
|
665
|
+
});
|
|
666
|
+
valueKey = `${columnGroupPathValue.join(columnGroupIdSeparator)}${columnGroupIdSeparator}${pivotValue.field}`;
|
|
667
|
+
}
|
|
668
|
+
uniqueColumnGroups.set(valueKey, [...columnGroupPath, pivotValue.field]);
|
|
669
|
+
updatedRow[valueKey] = column.valueGetter ? column.valueGetter(row[pivotValue.field], row, column, apiRef) : row[pivotValue.field];
|
|
670
|
+
});
|
|
671
|
+
return updatedRow;
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
// Convert uniqueColumnGroups to the pivot column structure
|
|
675
|
+
const columnGroupMap = new Map();
|
|
676
|
+
uniqueColumnGroups.forEach(columnGroupPath => {
|
|
677
|
+
let currentLevel = columnGroupMap;
|
|
678
|
+
let currentPath = '';
|
|
679
|
+
for (let i = 0; i < columnGroupPath.length - 1; i += 1) {
|
|
680
|
+
const groupValue = columnGroupPath[i];
|
|
681
|
+
let groupKey = typeof groupValue === 'string' ? groupValue : groupValue[visibleColumns[i].field];
|
|
682
|
+
if (groupKey instanceof Date) {
|
|
683
|
+
groupKey = groupKey.toLocaleDateString();
|
|
684
|
+
}
|
|
685
|
+
const pathKey = currentPath ? `${currentPath}-${groupKey}` : groupKey;
|
|
686
|
+
if (!currentLevel.has(groupKey)) {
|
|
687
|
+
currentLevel.set(groupKey, {
|
|
688
|
+
group: groupValue,
|
|
689
|
+
children: new Map()
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
const group = currentLevel.get(groupKey);
|
|
693
|
+
currentLevel = group.children;
|
|
694
|
+
currentPath = pathKey;
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
const convertMapToArray = map => {
|
|
698
|
+
return Array.from(map.entries()).map(([key, group]) => _extends({
|
|
699
|
+
key,
|
|
700
|
+
group: group.group
|
|
701
|
+
}, group.children.size > 0 ? {
|
|
702
|
+
children: convertMapToArray(group.children)
|
|
703
|
+
} : {}));
|
|
704
|
+
};
|
|
705
|
+
pivotColumns.push(...convertMapToArray(columnGroupMap));
|
|
706
|
+
}
|
|
707
|
+
const pivotColumnKeys = Array.from(uniqueColumnGroups.keys());
|
|
708
|
+
|
|
709
|
+
// Add paths and generate parent rows based on `visibleRows` (pivot row fields)
|
|
710
|
+
const pathsToAutogenerate = new Set();
|
|
711
|
+
let rowsWithPaths = filteredRows;
|
|
712
|
+
const rowsWithMissingGroups = [];
|
|
713
|
+
if (visibleRows.length > 0) {
|
|
714
|
+
rowsWithPaths = filteredRows.reduce((acc, row) => {
|
|
715
|
+
const partialPath = visibleRows.map(pivotRow => {
|
|
716
|
+
const field = pivotRow.field;
|
|
717
|
+
const colDef = columnLookup.get(field);
|
|
718
|
+
if (colDef?.groupingValueGetter) {
|
|
719
|
+
return String(colDef.groupingValueGetter(row[field], row, colDef, apiRef));
|
|
720
|
+
}
|
|
721
|
+
if (colDef?.valueGetter) {
|
|
722
|
+
return String(colDef.valueGetter(row[field], row, colDef, apiRef));
|
|
723
|
+
}
|
|
724
|
+
return String(row[field]);
|
|
725
|
+
});
|
|
726
|
+
for (let index = 0; index < partialPath.length; index += 1) {
|
|
727
|
+
const value = partialPath[index];
|
|
728
|
+
if (value === undefined) {
|
|
729
|
+
if (index === 0) {
|
|
730
|
+
rowsWithMissingGroups.push(_extends({}, row, {
|
|
731
|
+
group: false
|
|
732
|
+
}));
|
|
733
|
+
}
|
|
734
|
+
return acc;
|
|
735
|
+
}
|
|
736
|
+
const parentPath = partialPath.slice(0, index + 1);
|
|
737
|
+
const stringifiedPath = parentPath.join(',');
|
|
738
|
+
if (!pathsToAutogenerate.has(stringifiedPath)) {
|
|
739
|
+
pathsToAutogenerate.add(stringifiedPath);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
acc.push(_extends({}, row, {
|
|
743
|
+
path: [...partialPath, '']
|
|
744
|
+
}));
|
|
745
|
+
return acc;
|
|
746
|
+
}, []);
|
|
747
|
+
} else {
|
|
748
|
+
rowsWithPaths = filteredRows.map(row => _extends({}, row, {
|
|
749
|
+
path: ['']
|
|
750
|
+
}));
|
|
751
|
+
}
|
|
752
|
+
const autogeneratedRows = generateParentRows(pathsToAutogenerate);
|
|
753
|
+
|
|
754
|
+
// Apply tree data filtering to include missing parents and children
|
|
755
|
+
const filteredRowsWithGroups = getTreeDataFilteredRows([...autogeneratedRows, ...rowsWithPaths, ...rowsWithMissingGroups], queryOptions.filterModel, columnsWithDefaultColDef);
|
|
756
|
+
|
|
757
|
+
// Get root rows
|
|
758
|
+
const rootRows = findTreeDataRowChildren(filteredRowsWithGroups, []);
|
|
759
|
+
const rootRowCount = rootRows.length;
|
|
760
|
+
let filteredRowsWithMissingGroups = [];
|
|
761
|
+
let childRows = rootRows;
|
|
762
|
+
if (queryOptions.groupKeys?.length === 0) {
|
|
763
|
+
filteredRowsWithMissingGroups = filteredRowsWithGroups.filter(({
|
|
764
|
+
group
|
|
765
|
+
}) => group === false);
|
|
766
|
+
} else {
|
|
767
|
+
childRows = findTreeDataRowChildren(filteredRowsWithGroups, queryOptions.groupKeys || []);
|
|
768
|
+
}
|
|
769
|
+
const columnTypeMap = new Map();
|
|
770
|
+
for (const column of columnsWithDefaultColDef) {
|
|
771
|
+
if (column.type) {
|
|
772
|
+
columnTypeMap.set(column.field, column.type);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
let childRowsWithDescendantCounts = childRows.map(row => {
|
|
776
|
+
const descendants = findTreeDataRowChildren(filteredRowsWithGroups, row.path, 'path', -1, ({
|
|
777
|
+
id
|
|
778
|
+
}) => typeof id !== 'string' || !id.startsWith('auto-generated-parent-'));
|
|
779
|
+
const descendantCount = descendants.length;
|
|
780
|
+
if (descendantCount > 0) {
|
|
781
|
+
// Parent row, compute aggregation for both regular aggregation model and pivot values
|
|
782
|
+
const regularAggregation = applyAggregation(queryOptions.pivotModel.values.map(value => ({
|
|
783
|
+
[value.field]: value.aggFunc
|
|
784
|
+
})), columnsWithDefaultColDef, descendants, row.id);
|
|
785
|
+
|
|
786
|
+
// Compute aggregations for each pivot column
|
|
787
|
+
const pivotAggregations = computePivotAggregations(pivotColumnKeys, descendants, visibleValues, columnTypeMap, row.id, columnGroupIdSeparator);
|
|
788
|
+
return _extends({}, row, {
|
|
789
|
+
descendantCount
|
|
790
|
+
}, regularAggregation, pivotAggregations);
|
|
791
|
+
}
|
|
792
|
+
return _extends({}, row, {
|
|
793
|
+
descendantCount
|
|
794
|
+
});
|
|
795
|
+
});
|
|
796
|
+
|
|
797
|
+
// Apply sorting if provided
|
|
798
|
+
if (queryOptions.sortModel) {
|
|
799
|
+
const rowComparator = getRowComparator(queryOptions.sortModel, {}, pivotColumnKeys.map(key => ({
|
|
800
|
+
field: key,
|
|
801
|
+
type: 'number',
|
|
802
|
+
sortComparator: gridStringOrNumberComparator
|
|
803
|
+
})));
|
|
804
|
+
const sortedMissingGroups = [...filteredRowsWithMissingGroups].sort(rowComparator);
|
|
805
|
+
const sortedChildRows = [...childRowsWithDescendantCounts].sort(rowComparator);
|
|
806
|
+
childRowsWithDescendantCounts = [...sortedMissingGroups, ...sortedChildRows];
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// Apply pagination if provided
|
|
810
|
+
if (queryOptions.paginationModel && queryOptions.groupKeys?.length === 0) {
|
|
811
|
+
// Only paginate root rows, grid should refetch root rows when `paginationModel` updates
|
|
812
|
+
const {
|
|
813
|
+
pageSize,
|
|
814
|
+
page
|
|
815
|
+
} = queryOptions.paginationModel;
|
|
816
|
+
if (pageSize < childRowsWithDescendantCounts.length) {
|
|
817
|
+
childRowsWithDescendantCounts = childRowsWithDescendantCounts.slice(page * pageSize, (page + 1) * pageSize);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
// Compute aggregate row if pivot values are provided
|
|
822
|
+
let aggregateRow;
|
|
823
|
+
if (visibleValues.length > 0) {
|
|
824
|
+
const regularAggregation = applyAggregation(visibleValues.map(value => ({
|
|
825
|
+
[value.field]: value.aggFunc
|
|
826
|
+
})), columnsWithDefaultColDef, filteredRowsWithGroups);
|
|
827
|
+
|
|
828
|
+
// Compute aggregations for each pivot column for the entire dataset
|
|
829
|
+
const pivotAggregations = computePivotAggregations(pivotColumnKeys, filteredRowsWithGroups.filter(row => typeof row.id !== 'string' || !row.id.startsWith('auto-generated-parent-')), visibleValues, columnTypeMap, 'root', columnGroupIdSeparator);
|
|
830
|
+
aggregateRow = _extends({}, regularAggregation, pivotAggregations);
|
|
831
|
+
}
|
|
832
|
+
return new Promise(resolve => {
|
|
833
|
+
setTimeout(() => {
|
|
834
|
+
resolve({
|
|
835
|
+
rows: childRowsWithDescendantCounts,
|
|
836
|
+
rootRowCount,
|
|
837
|
+
pivotColumns,
|
|
838
|
+
aggregateRow
|
|
839
|
+
});
|
|
840
|
+
}, delay); // simulate network latency
|
|
841
|
+
});
|
|
536
842
|
};
|
|
@@ -23,7 +23,7 @@ interface UseMockServerOptions {
|
|
|
23
23
|
visibleFields?: string[];
|
|
24
24
|
editable?: boolean;
|
|
25
25
|
treeData?: AddPathToDemoDataOptions;
|
|
26
|
-
|
|
26
|
+
derivedColumns?: boolean;
|
|
27
27
|
}
|
|
28
28
|
export declare const useMockServer: <T extends GridGetRowsResponse>(dataSetOptions?: Partial<UseMockServerOptions>, serverOptions?: ServerOptions & {
|
|
29
29
|
verbose?: boolean;
|