@mui/x-data-grid-pro 5.6.0 → 5.8.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 +187 -0
- package/DataGridPro/DataGridPro.d.ts +7 -1
- package/DataGridPro/DataGridPro.js +63 -20
- package/DataGridPro/useDataGridProComponent.js +29 -18
- package/DataGridPro/useDataGridProProps.d.ts +2 -1
- package/DataGridPro/useDataGridProProps.js +2 -2
- package/components/DataGridProColumnHeaders.js +10 -10
- package/components/DataGridProVirtualScroller.js +12 -23
- package/components/GridDetailPanelToggleCell.js +4 -3
- package/components/GridGroupingCriteriaCell.d.ts +2 -5
- package/components/GridGroupingCriteriaCell.js +2 -74
- package/components/GridTreeDataGroupingCell.js +4 -3
- package/components/index.d.ts +1 -0
- package/components/index.js +2 -1
- package/hooks/features/columnPinning/useGridColumnPinning.js +6 -6
- package/hooks/features/columnPinning/useGridColumnPinningPreProcessors.js +2 -2
- package/hooks/features/columnReorder/useGridColumnReorder.d.ts +2 -0
- package/hooks/features/columnReorder/useGridColumnReorder.js +7 -8
- package/hooks/features/columnResize/useGridColumnResize.d.ts +2 -0
- package/hooks/features/columnResize/useGridColumnResize.js +7 -7
- package/hooks/features/detailPanel/useGridDetailPanel.d.ts +2 -0
- package/hooks/features/detailPanel/useGridDetailPanel.js +10 -10
- package/hooks/features/detailPanel/useGridDetailPanelPreProcessors.js +2 -2
- package/hooks/features/infiniteLoader/useGridInfiniteLoader.js +2 -2
- package/hooks/features/rowGrouping/gridRowGroupingInterfaces.d.ts +6 -0
- package/hooks/features/rowGrouping/gridRowGroupingUtils.d.ts +5 -2
- package/hooks/features/rowGrouping/gridRowGroupingUtils.js +18 -3
- package/hooks/features/rowGrouping/useGridRowGrouping.js +46 -167
- package/hooks/features/rowGrouping/useGridRowGroupingPreProcessors.d.ts +1 -1
- package/hooks/features/rowGrouping/useGridRowGroupingPreProcessors.js +131 -4
- package/hooks/features/treeData/gridTreeDataUtils.d.ts +1 -0
- package/hooks/features/treeData/gridTreeDataUtils.js +2 -0
- package/hooks/features/treeData/useGridTreeData.d.ts +1 -5
- package/hooks/features/treeData/useGridTreeData.js +3 -82
- package/hooks/features/treeData/useGridTreeDataPreProcessors.d.ts +1 -1
- package/hooks/features/treeData/useGridTreeDataPreProcessors.js +73 -4
- package/index.d.ts +2 -1
- package/index.js +3 -2
- package/legacy/DataGridPro/DataGridPro.js +63 -20
- package/legacy/DataGridPro/useDataGridProComponent.js +29 -18
- package/legacy/DataGridPro/useDataGridProProps.js +7 -2
- package/legacy/components/DataGridProColumnHeaders.js +10 -10
- package/legacy/components/DataGridProVirtualScroller.js +12 -22
- package/legacy/components/GridDetailPanelToggleCell.js +4 -3
- package/legacy/components/GridGroupingCriteriaCell.js +2 -74
- package/legacy/components/GridTreeDataGroupingCell.js +4 -3
- package/legacy/components/index.js +2 -1
- package/legacy/hooks/features/columnPinning/useGridColumnPinning.js +6 -6
- package/legacy/hooks/features/columnPinning/useGridColumnPinningPreProcessors.js +2 -2
- package/legacy/hooks/features/columnReorder/useGridColumnReorder.js +9 -10
- package/legacy/hooks/features/columnResize/useGridColumnResize.js +9 -9
- package/legacy/hooks/features/detailPanel/useGridDetailPanel.js +10 -10
- package/legacy/hooks/features/detailPanel/useGridDetailPanelPreProcessors.js +2 -2
- package/legacy/hooks/features/infiniteLoader/useGridInfiniteLoader.js +2 -2
- package/legacy/hooks/features/rowGrouping/gridRowGroupingUtils.js +19 -2
- package/legacy/hooks/features/rowGrouping/useGridRowGrouping.js +48 -172
- package/legacy/hooks/features/rowGrouping/useGridRowGroupingPreProcessors.js +138 -4
- package/legacy/hooks/features/treeData/gridTreeDataUtils.js +2 -0
- package/legacy/hooks/features/treeData/useGridTreeData.js +3 -90
- package/legacy/hooks/features/treeData/useGridTreeDataPreProcessors.js +85 -4
- package/legacy/index.js +3 -2
- package/legacy/utils/releaseInfo.js +15 -0
- package/models/dataGridProProps.d.ts +9 -8
- package/models/gridGroupingColDefOverride.d.ts +2 -2
- package/models/gridGroupingValueGetterParams.d.ts +1 -1
- package/modern/DataGridPro/DataGridPro.js +63 -20
- package/modern/DataGridPro/useDataGridProComponent.js +27 -18
- package/modern/DataGridPro/useDataGridProProps.js +2 -2
- package/modern/components/DataGridProColumnHeaders.js +10 -10
- package/modern/components/DataGridProVirtualScroller.js +12 -23
- package/modern/components/GridDetailPanelToggleCell.js +4 -3
- package/modern/components/GridGroupingCriteriaCell.js +2 -74
- package/modern/components/GridTreeDataGroupingCell.js +4 -3
- package/modern/components/index.js +2 -1
- package/modern/hooks/features/columnPinning/useGridColumnPinning.js +6 -6
- package/modern/hooks/features/columnPinning/useGridColumnPinningPreProcessors.js +2 -2
- package/modern/hooks/features/columnReorder/useGridColumnReorder.js +7 -8
- package/modern/hooks/features/columnResize/useGridColumnResize.js +7 -7
- package/modern/hooks/features/detailPanel/useGridDetailPanel.js +9 -9
- package/modern/hooks/features/detailPanel/useGridDetailPanelPreProcessors.js +2 -2
- package/modern/hooks/features/infiniteLoader/useGridInfiniteLoader.js +2 -2
- package/modern/hooks/features/rowGrouping/gridRowGroupingUtils.js +18 -3
- package/modern/hooks/features/rowGrouping/useGridRowGrouping.js +46 -167
- package/modern/hooks/features/rowGrouping/useGridRowGroupingPreProcessors.js +131 -4
- package/modern/hooks/features/treeData/gridTreeDataUtils.js +2 -0
- package/modern/hooks/features/treeData/useGridTreeData.js +3 -82
- package/modern/hooks/features/treeData/useGridTreeDataPreProcessors.js +73 -4
- package/modern/index.js +3 -2
- package/modern/utils/releaseInfo.js +15 -0
- package/node/DataGridPro/DataGridPro.js +61 -19
- package/node/DataGridPro/useDataGridProComponent.js +26 -15
- package/node/DataGridPro/useDataGridProProps.js +2 -2
- package/node/components/DataGridProColumnHeaders.js +10 -10
- package/node/components/DataGridProVirtualScroller.js +11 -22
- package/node/components/GridDetailPanelToggleCell.js +4 -3
- package/node/components/GridGroupingCriteriaCell.js +1 -72
- package/node/components/GridTreeDataGroupingCell.js +4 -3
- package/node/components/index.js +13 -0
- package/node/hooks/features/columnPinning/useGridColumnPinning.js +5 -5
- package/node/hooks/features/columnPinning/useGridColumnPinningPreProcessors.js +1 -1
- package/node/hooks/features/columnReorder/useGridColumnReorder.js +10 -9
- package/node/hooks/features/columnResize/useGridColumnResize.js +9 -6
- package/node/hooks/features/detailPanel/useGridDetailPanel.js +13 -10
- package/node/hooks/features/detailPanel/useGridDetailPanelPreProcessors.js +1 -1
- package/node/hooks/features/infiniteLoader/useGridInfiniteLoader.js +1 -1
- package/node/hooks/features/rowGrouping/gridRowGroupingUtils.js +24 -5
- package/node/hooks/features/rowGrouping/useGridRowGrouping.js +42 -165
- package/node/hooks/features/rowGrouping/useGridRowGroupingPreProcessors.js +134 -1
- package/node/hooks/features/treeData/gridTreeDataUtils.js +5 -2
- package/node/hooks/features/treeData/useGridTreeData.js +2 -91
- package/node/hooks/features/treeData/useGridTreeDataPreProcessors.js +75 -3
- package/node/index.js +23 -9
- package/node/utils/releaseInfo.js +25 -0
- package/package.json +5 -4
- package/typeOverloads/modules.d.ts +6 -6
- package/typeOverloads/reexports.d.ts +1 -1
- package/utils/releaseInfo.d.ts +1 -0
- package/utils/releaseInfo.js +15 -0
- package/utils/tree/buildRowTree.d.ts +3 -3
- package/components/Watermark.d.ts +0 -2
- package/components/Watermark.js +0 -43
- package/legacy/components/Watermark.js +0 -43
- package/modern/components/Watermark.js +0 -43
- package/node/components/Watermark.js +0 -56
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import Divider from '@mui/material/Divider';
|
|
4
|
-
import { GridEvents,
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { filterRowTreeFromGroupingColumns, getRowGroupingFieldFromGroupingCriteria, GROUPING_COLUMNS_FEATURE_NAME, isGroupingColumn, mergeStateWithRowGroupingModel } from './gridRowGroupingUtils';
|
|
9
|
-
import { sortRowTree } from '../../../utils/tree/sortRowTree';
|
|
4
|
+
import { GridEvents, useGridApiEventHandler, useGridApiMethod, gridFilteredDescendantCountLookupSelector } from '@mui/x-data-grid';
|
|
5
|
+
import { useGridRegisterPipeProcessor, isDeepEqual } from '@mui/x-data-grid/internals';
|
|
6
|
+
import { gridRowGroupingModelSelector, gridRowGroupingSanitizedModelSelector, gridRowGroupingStateSelector } from './gridRowGroupingSelector';
|
|
7
|
+
import { getRowGroupingFieldFromGroupingCriteria, ROW_GROUPING_STRATEGY, isGroupingColumn, mergeStateWithRowGroupingModel, setStrategyAvailability } from './gridRowGroupingUtils';
|
|
10
8
|
import { GridRowGroupableColumnMenuItems } from '../../../components/GridRowGroupableColumnMenuItems';
|
|
11
9
|
import { GridRowGroupingColumnMenuItems } from '../../../components/GridRowGroupingColumnMenuItems';
|
|
12
10
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
11
|
export const rowGroupingStateInitializer = (state, props) => _extends({}, state, {
|
|
14
12
|
rowGrouping: {
|
|
15
|
-
model: props.rowGroupingModel ?? props.initialState?.rowGrouping?.model ?? []
|
|
13
|
+
model: props.rowGroupingModel ?? props.initialState?.rowGrouping?.model ?? [],
|
|
14
|
+
unstable_sanitizedModelOnLastRowTreeCreation: []
|
|
16
15
|
}
|
|
17
16
|
});
|
|
18
17
|
/**
|
|
@@ -31,158 +30,6 @@ export const useGridRowGrouping = (apiRef, props) => {
|
|
|
31
30
|
stateSelector: gridRowGroupingModelSelector,
|
|
32
31
|
changeEvent: GridEvents.rowGroupingModelChange
|
|
33
32
|
});
|
|
34
|
-
/**
|
|
35
|
-
* ROW GROUPING
|
|
36
|
-
*/
|
|
37
|
-
// Tracks the model on the last pre-processing to check if we need to re-build the grouping columns when the grid upserts a column.
|
|
38
|
-
|
|
39
|
-
const sanitizedModelOnLastRowPreProcessing = React.useRef([]);
|
|
40
|
-
const updateRowGrouping = React.useCallback(() => {
|
|
41
|
-
const groupRows = params => {
|
|
42
|
-
const rowGroupingModel = gridRowGroupingSanitizedModelSelector(apiRef);
|
|
43
|
-
const columnsLookup = gridColumnLookupSelector(apiRef);
|
|
44
|
-
sanitizedModelOnLastRowPreProcessing.current = rowGroupingModel;
|
|
45
|
-
|
|
46
|
-
if (props.disableRowGrouping || rowGroupingModel.length === 0) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const distinctValues = Object.fromEntries(rowGroupingModel.map(groupingField => [groupingField, {
|
|
51
|
-
lookup: {},
|
|
52
|
-
list: []
|
|
53
|
-
}]));
|
|
54
|
-
|
|
55
|
-
const getCellGroupingCriteria = ({
|
|
56
|
-
row,
|
|
57
|
-
id,
|
|
58
|
-
colDef
|
|
59
|
-
}) => {
|
|
60
|
-
let key;
|
|
61
|
-
|
|
62
|
-
if (colDef.groupingValueGetter) {
|
|
63
|
-
const groupingValueGetterParams = {
|
|
64
|
-
colDef,
|
|
65
|
-
field: colDef.field,
|
|
66
|
-
value: row[colDef.field],
|
|
67
|
-
id,
|
|
68
|
-
row,
|
|
69
|
-
rowNode: {
|
|
70
|
-
isAutoGenerated: false,
|
|
71
|
-
id
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
key = colDef.groupingValueGetter(groupingValueGetterParams);
|
|
75
|
-
} else {
|
|
76
|
-
key = row[colDef.field];
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return {
|
|
80
|
-
key,
|
|
81
|
-
field: colDef.field
|
|
82
|
-
};
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
params.ids.forEach(rowId => {
|
|
86
|
-
const row = params.idRowsLookup[rowId];
|
|
87
|
-
rowGroupingModel.forEach(groupingCriteria => {
|
|
88
|
-
const {
|
|
89
|
-
key
|
|
90
|
-
} = getCellGroupingCriteria({
|
|
91
|
-
row,
|
|
92
|
-
id: rowId,
|
|
93
|
-
colDef: columnsLookup[groupingCriteria]
|
|
94
|
-
});
|
|
95
|
-
const groupingFieldsDistinctKeys = distinctValues[groupingCriteria];
|
|
96
|
-
|
|
97
|
-
if (key != null && !groupingFieldsDistinctKeys.lookup[key.toString()]) {
|
|
98
|
-
groupingFieldsDistinctKeys.lookup[key.toString()] = true;
|
|
99
|
-
groupingFieldsDistinctKeys.list.push(key);
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
const rows = params.ids.map(rowId => {
|
|
104
|
-
const row = params.idRowsLookup[rowId];
|
|
105
|
-
const parentPath = rowGroupingModel.map(groupingField => getCellGroupingCriteria({
|
|
106
|
-
row,
|
|
107
|
-
id: rowId,
|
|
108
|
-
colDef: columnsLookup[groupingField]
|
|
109
|
-
})).filter(cell => cell.key != null);
|
|
110
|
-
const leafGroupingCriteria = {
|
|
111
|
-
key: rowId.toString(),
|
|
112
|
-
field: null
|
|
113
|
-
};
|
|
114
|
-
return {
|
|
115
|
-
path: [...parentPath, leafGroupingCriteria],
|
|
116
|
-
id: rowId
|
|
117
|
-
};
|
|
118
|
-
});
|
|
119
|
-
return buildRowTree(_extends({}, params, {
|
|
120
|
-
rows,
|
|
121
|
-
defaultGroupingExpansionDepth: props.defaultGroupingExpansionDepth,
|
|
122
|
-
isGroupExpandedByDefault: props.isGroupExpandedByDefault,
|
|
123
|
-
groupingName: GROUPING_COLUMNS_FEATURE_NAME
|
|
124
|
-
}));
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
return apiRef.current.unstable_registerRowGroupsBuilder('rowGrouping', groupRows);
|
|
128
|
-
}, [apiRef, props.defaultGroupingExpansionDepth, props.isGroupExpandedByDefault, props.disableRowGrouping]);
|
|
129
|
-
useFirstRender(() => {
|
|
130
|
-
updateRowGrouping();
|
|
131
|
-
});
|
|
132
|
-
const isFirstRender = React.useRef(true);
|
|
133
|
-
React.useEffect(() => {
|
|
134
|
-
if (isFirstRender.current) {
|
|
135
|
-
isFirstRender.current = false;
|
|
136
|
-
return () => {};
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return updateRowGrouping();
|
|
140
|
-
}, [updateRowGrouping]);
|
|
141
|
-
/**
|
|
142
|
-
* PRE-PROCESSING
|
|
143
|
-
*/
|
|
144
|
-
|
|
145
|
-
const addColumnMenuButtons = React.useCallback((initialValue, columns) => {
|
|
146
|
-
if (props.disableRowGrouping) {
|
|
147
|
-
return initialValue;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
let menuItems;
|
|
151
|
-
|
|
152
|
-
if (isGroupingColumn(columns.field)) {
|
|
153
|
-
menuItems = /*#__PURE__*/_jsx(GridRowGroupingColumnMenuItems, {});
|
|
154
|
-
} else if (columns.groupable) {
|
|
155
|
-
menuItems = /*#__PURE__*/_jsx(GridRowGroupableColumnMenuItems, {});
|
|
156
|
-
} else {
|
|
157
|
-
menuItems = null;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if (menuItems == null) {
|
|
161
|
-
return initialValue;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
return [...initialValue, /*#__PURE__*/_jsx(Divider, {}), menuItems];
|
|
165
|
-
}, [props.disableRowGrouping]);
|
|
166
|
-
const filteringMethod = React.useCallback(params => {
|
|
167
|
-
const rowTree = gridRowTreeSelector(apiRef);
|
|
168
|
-
return filterRowTreeFromGroupingColumns({
|
|
169
|
-
rowTree,
|
|
170
|
-
isRowMatchingFilters: params.isRowMatchingFilters
|
|
171
|
-
});
|
|
172
|
-
}, [apiRef]);
|
|
173
|
-
const sortingMethod = React.useCallback(params => {
|
|
174
|
-
const rowTree = gridRowTreeSelector(apiRef);
|
|
175
|
-
const rowIds = gridRowIdsSelector(apiRef);
|
|
176
|
-
return sortRowTree({
|
|
177
|
-
rowTree,
|
|
178
|
-
rowIds,
|
|
179
|
-
sortRowList: params.sortRowList,
|
|
180
|
-
disableChildrenSorting: false
|
|
181
|
-
});
|
|
182
|
-
}, [apiRef]);
|
|
183
|
-
useGridRegisterPreProcessor(apiRef, 'columnMenu', addColumnMenuButtons);
|
|
184
|
-
useGridRegisterFilteringMethod(apiRef, GROUPING_COLUMNS_FEATURE_NAME, filteringMethod);
|
|
185
|
-
useGridRegisterSortingMethod(apiRef, GROUPING_COLUMNS_FEATURE_NAME, sortingMethod);
|
|
186
33
|
/**
|
|
187
34
|
* API METHODS
|
|
188
35
|
*/
|
|
@@ -192,10 +39,10 @@ export const useGridRowGrouping = (apiRef, props) => {
|
|
|
192
39
|
|
|
193
40
|
if (currentModel !== model) {
|
|
194
41
|
apiRef.current.setState(mergeStateWithRowGroupingModel(model));
|
|
195
|
-
|
|
42
|
+
setStrategyAvailability(apiRef, props.disableRowGrouping);
|
|
196
43
|
apiRef.current.forceUpdate();
|
|
197
44
|
}
|
|
198
|
-
}, [apiRef,
|
|
45
|
+
}, [apiRef, props.disableRowGrouping]);
|
|
199
46
|
const addRowGroupingCriteria = React.useCallback((field, groupingIndex) => {
|
|
200
47
|
const currentModel = gridRowGroupingModelSelector(apiRef);
|
|
201
48
|
|
|
@@ -239,6 +86,27 @@ export const useGridRowGrouping = (apiRef, props) => {
|
|
|
239
86
|
* PRE-PROCESSING
|
|
240
87
|
*/
|
|
241
88
|
|
|
89
|
+
const addColumnMenuButtons = React.useCallback((initialValue, columns) => {
|
|
90
|
+
if (props.disableRowGrouping) {
|
|
91
|
+
return initialValue;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
let menuItems;
|
|
95
|
+
|
|
96
|
+
if (isGroupingColumn(columns.field)) {
|
|
97
|
+
menuItems = /*#__PURE__*/_jsx(GridRowGroupingColumnMenuItems, {});
|
|
98
|
+
} else if (columns.groupable) {
|
|
99
|
+
menuItems = /*#__PURE__*/_jsx(GridRowGroupableColumnMenuItems, {});
|
|
100
|
+
} else {
|
|
101
|
+
menuItems = null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (menuItems == null) {
|
|
105
|
+
return initialValue;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return [...initialValue, /*#__PURE__*/_jsx(Divider, {}), menuItems];
|
|
109
|
+
}, [props.disableRowGrouping]);
|
|
242
110
|
const stateExportPreProcessing = React.useCallback(prevState => {
|
|
243
111
|
if (props.disableRowGrouping) {
|
|
244
112
|
return prevState;
|
|
@@ -269,8 +137,9 @@ export const useGridRowGrouping = (apiRef, props) => {
|
|
|
269
137
|
|
|
270
138
|
return params;
|
|
271
139
|
}, [apiRef, props.disableRowGrouping]);
|
|
272
|
-
|
|
273
|
-
|
|
140
|
+
useGridRegisterPipeProcessor(apiRef, 'columnMenu', addColumnMenuButtons);
|
|
141
|
+
useGridRegisterPipeProcessor(apiRef, 'exportState', stateExportPreProcessing);
|
|
142
|
+
useGridRegisterPipeProcessor(apiRef, 'restoreState', stateRestorePreProcessing);
|
|
274
143
|
/**
|
|
275
144
|
* EVENTS
|
|
276
145
|
*/
|
|
@@ -293,15 +162,25 @@ export const useGridRowGrouping = (apiRef, props) => {
|
|
|
293
162
|
}, [apiRef, props.rowGroupingColumnMode]);
|
|
294
163
|
const checkGroupingColumnsModelDiff = React.useCallback(() => {
|
|
295
164
|
const rowGroupingModel = gridRowGroupingSanitizedModelSelector(apiRef);
|
|
296
|
-
const lastGroupingColumnsModelApplied =
|
|
165
|
+
const lastGroupingColumnsModelApplied = gridRowGroupingStateSelector(apiRef.current.state).unstable_sanitizedModelOnLastRowTreeCreation;
|
|
297
166
|
|
|
298
167
|
if (!isDeepEqual(lastGroupingColumnsModelApplied, rowGroupingModel)) {
|
|
299
|
-
|
|
168
|
+
apiRef.current.setState(state => _extends({}, state, {
|
|
169
|
+
rowGrouping: _extends({}, state.rowGrouping, {
|
|
170
|
+
unstable_sanitizedModelOnLastRowTreeCreation: rowGroupingModel
|
|
171
|
+
})
|
|
172
|
+
})); // Refresh the column pre-processing
|
|
173
|
+
// TODO: Add a clean way to re-run a pipe processing without faking a change
|
|
300
174
|
|
|
301
175
|
apiRef.current.updateColumns([]);
|
|
302
|
-
|
|
176
|
+
setStrategyAvailability(apiRef, props.disableRowGrouping); // Refresh the row tree creation strategy processing
|
|
177
|
+
// TODO: Add a clean way to re-run a strategy processing without publishing a private event
|
|
178
|
+
|
|
179
|
+
if (apiRef.current.unstable_getActiveStrategy('rowTree') === ROW_GROUPING_STRATEGY) {
|
|
180
|
+
apiRef.current.publishEvent(GridEvents.activeStrategyProcessorChange, 'rowTreeCreation');
|
|
181
|
+
}
|
|
303
182
|
}
|
|
304
|
-
}, [apiRef,
|
|
183
|
+
}, [apiRef, props.disableRowGrouping]);
|
|
305
184
|
useGridApiEventHandler(apiRef, GridEvents.cellKeyDown, handleCellKeyDown);
|
|
306
185
|
useGridApiEventHandler(apiRef, GridEvents.columnsChange, checkGroupingColumnsModelDiff);
|
|
307
186
|
useGridApiEventHandler(apiRef, GridEvents.rowGroupingModelChange, checkGroupingColumnsModelDiff);
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
1
2
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
3
|
+
import { gridColumnLookupSelector, gridRowIdsSelector, gridRowTreeSelector, useFirstRender } from '@mui/x-data-grid';
|
|
4
|
+
import { useGridRegisterPipeProcessor, useGridRegisterStrategyProcessor } from '@mui/x-data-grid/internals';
|
|
5
|
+
import { gridRowGroupingModelSelector, gridRowGroupingSanitizedModelSelector } from './gridRowGroupingSelector';
|
|
4
6
|
import { createGroupingColDefForAllGroupingCriteria, createGroupingColDefForOneGroupingCriteria } from './createGroupingColDef';
|
|
5
|
-
import { getColDefOverrides, isGroupingColumn } from './gridRowGroupingUtils';
|
|
7
|
+
import { filterRowTreeFromGroupingColumns, getColDefOverrides, ROW_GROUPING_STRATEGY, isGroupingColumn, setStrategyAvailability } from './gridRowGroupingUtils';
|
|
8
|
+
import { buildRowTree } from '../../../utils/tree/buildRowTree';
|
|
9
|
+
import { sortRowTree } from '../../../utils/tree/sortRowTree';
|
|
6
10
|
export const useGridRowGroupingPreProcessors = (apiRef, props) => {
|
|
7
11
|
const getGroupingColDefs = React.useCallback(columnsState => {
|
|
8
12
|
if (props.disableRowGrouping) {
|
|
@@ -72,5 +76,128 @@ export const useGridRowGroupingPreProcessors = (apiRef, props) => {
|
|
|
72
76
|
columnsState.lookup = newColumnsLookup;
|
|
73
77
|
return columnsState;
|
|
74
78
|
}, [getGroupingColDefs]);
|
|
75
|
-
|
|
79
|
+
const createRowTree = React.useCallback(params => {
|
|
80
|
+
const rowGroupingModel = gridRowGroupingSanitizedModelSelector(apiRef);
|
|
81
|
+
const columnsLookup = gridColumnLookupSelector(apiRef);
|
|
82
|
+
apiRef.current.setState(state => _extends({}, state, {
|
|
83
|
+
rowGrouping: _extends({}, state.rowGrouping, {
|
|
84
|
+
unstable_sanitizedModelOnLastRowTreeCreation: rowGroupingModel
|
|
85
|
+
})
|
|
86
|
+
}));
|
|
87
|
+
const distinctValues = Object.fromEntries(rowGroupingModel.map(groupingField => [groupingField, {
|
|
88
|
+
lookup: {},
|
|
89
|
+
list: []
|
|
90
|
+
}]));
|
|
91
|
+
|
|
92
|
+
const getCellGroupingCriteria = ({
|
|
93
|
+
row,
|
|
94
|
+
id,
|
|
95
|
+
colDef
|
|
96
|
+
}) => {
|
|
97
|
+
let key;
|
|
98
|
+
|
|
99
|
+
if (colDef.groupingValueGetter) {
|
|
100
|
+
const groupingValueGetterParams = {
|
|
101
|
+
colDef,
|
|
102
|
+
field: colDef.field,
|
|
103
|
+
value: row[colDef.field],
|
|
104
|
+
id,
|
|
105
|
+
row,
|
|
106
|
+
rowNode: {
|
|
107
|
+
isAutoGenerated: false,
|
|
108
|
+
id
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
key = colDef.groupingValueGetter(groupingValueGetterParams);
|
|
112
|
+
} else {
|
|
113
|
+
key = row[colDef.field];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
key,
|
|
118
|
+
field: colDef.field
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
params.ids.forEach(rowId => {
|
|
123
|
+
const row = params.idRowsLookup[rowId];
|
|
124
|
+
rowGroupingModel.forEach(groupingCriteria => {
|
|
125
|
+
const {
|
|
126
|
+
key
|
|
127
|
+
} = getCellGroupingCriteria({
|
|
128
|
+
row,
|
|
129
|
+
id: rowId,
|
|
130
|
+
colDef: columnsLookup[groupingCriteria]
|
|
131
|
+
});
|
|
132
|
+
const groupingFieldsDistinctKeys = distinctValues[groupingCriteria];
|
|
133
|
+
|
|
134
|
+
if (key != null && !groupingFieldsDistinctKeys.lookup[key.toString()]) {
|
|
135
|
+
groupingFieldsDistinctKeys.lookup[key.toString()] = true;
|
|
136
|
+
groupingFieldsDistinctKeys.list.push(key);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
const rows = params.ids.map(rowId => {
|
|
141
|
+
const row = params.idRowsLookup[rowId];
|
|
142
|
+
const parentPath = rowGroupingModel.map(groupingField => getCellGroupingCriteria({
|
|
143
|
+
row,
|
|
144
|
+
id: rowId,
|
|
145
|
+
colDef: columnsLookup[groupingField]
|
|
146
|
+
})).filter(cell => cell.key != null);
|
|
147
|
+
const leafGroupingCriteria = {
|
|
148
|
+
key: rowId.toString(),
|
|
149
|
+
field: null
|
|
150
|
+
};
|
|
151
|
+
return {
|
|
152
|
+
path: [...parentPath, leafGroupingCriteria],
|
|
153
|
+
id: rowId
|
|
154
|
+
};
|
|
155
|
+
});
|
|
156
|
+
return buildRowTree(_extends({}, params, {
|
|
157
|
+
rows,
|
|
158
|
+
defaultGroupingExpansionDepth: props.defaultGroupingExpansionDepth,
|
|
159
|
+
isGroupExpandedByDefault: props.isGroupExpandedByDefault,
|
|
160
|
+
groupingName: ROW_GROUPING_STRATEGY
|
|
161
|
+
}));
|
|
162
|
+
}, [apiRef, props.defaultGroupingExpansionDepth, props.isGroupExpandedByDefault]);
|
|
163
|
+
const filterRows = React.useCallback(params => {
|
|
164
|
+
const rowTree = gridRowTreeSelector(apiRef);
|
|
165
|
+
return filterRowTreeFromGroupingColumns({
|
|
166
|
+
rowTree,
|
|
167
|
+
isRowMatchingFilters: params.isRowMatchingFilters
|
|
168
|
+
});
|
|
169
|
+
}, [apiRef]);
|
|
170
|
+
const sortRows = React.useCallback(params => {
|
|
171
|
+
const rowTree = gridRowTreeSelector(apiRef);
|
|
172
|
+
const rowIds = gridRowIdsSelector(apiRef);
|
|
173
|
+
return sortRowTree({
|
|
174
|
+
rowTree,
|
|
175
|
+
rowIds,
|
|
176
|
+
sortRowList: params.sortRowList,
|
|
177
|
+
disableChildrenSorting: false
|
|
178
|
+
});
|
|
179
|
+
}, [apiRef]);
|
|
180
|
+
useGridRegisterPipeProcessor(apiRef, 'hydrateColumns', updateGroupingColumn);
|
|
181
|
+
useGridRegisterStrategyProcessor(apiRef, ROW_GROUPING_STRATEGY, 'rowTreeCreation', createRowTree);
|
|
182
|
+
useGridRegisterStrategyProcessor(apiRef, ROW_GROUPING_STRATEGY, 'filtering', filterRows);
|
|
183
|
+
useGridRegisterStrategyProcessor(apiRef, ROW_GROUPING_STRATEGY, 'sorting', sortRows);
|
|
184
|
+
/**
|
|
185
|
+
* 1ST RENDER
|
|
186
|
+
*/
|
|
187
|
+
|
|
188
|
+
useFirstRender(() => {
|
|
189
|
+
setStrategyAvailability(apiRef, props.disableRowGrouping);
|
|
190
|
+
});
|
|
191
|
+
/**
|
|
192
|
+
* EFFECTS
|
|
193
|
+
*/
|
|
194
|
+
|
|
195
|
+
const isFirstRender = React.useRef(true);
|
|
196
|
+
React.useEffect(() => {
|
|
197
|
+
if (!isFirstRender.current) {
|
|
198
|
+
setStrategyAvailability(apiRef, props.disableRowGrouping);
|
|
199
|
+
} else {
|
|
200
|
+
isFirstRender.current = false;
|
|
201
|
+
}
|
|
202
|
+
}, [apiRef, props.disableRowGrouping]);
|
|
76
203
|
};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
export const TREE_DATA_STRATEGY = 'tree-data';
|
|
1
2
|
/**
|
|
2
3
|
* A node is visible if one of the following criteria is met:
|
|
3
4
|
* - One of its children is passing the filter
|
|
4
5
|
* - It is passing the filter
|
|
5
6
|
*/
|
|
7
|
+
|
|
6
8
|
export const filterRowTreeFromTreeData = params => {
|
|
7
9
|
const {
|
|
8
10
|
rowTree,
|
|
@@ -1,92 +1,13 @@
|
|
|
1
|
-
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
1
|
import * as React from 'react';
|
|
3
|
-
import { useGridApiEventHandler, GridEvents,
|
|
4
|
-
|
|
5
|
-
import { buildRowTree } from '../../../utils/tree/buildRowTree';
|
|
6
|
-
import { sortRowTree } from '../../../utils/tree/sortRowTree';
|
|
7
|
-
import { filterRowTreeFromTreeData } from './gridTreeDataUtils';
|
|
8
|
-
export const TREE_DATA_GROUPING_NAME = 'tree-data';
|
|
2
|
+
import { useGridApiEventHandler, GridEvents, gridFilteredDescendantCountLookupSelector } from '@mui/x-data-grid';
|
|
3
|
+
|
|
9
4
|
/**
|
|
10
5
|
* Only available in DataGridPro
|
|
11
|
-
* @requires useGridPreProcessing (method)
|
|
12
|
-
* @requires useGridRowGroupsPreProcessing (method)
|
|
13
6
|
*/
|
|
14
|
-
|
|
15
|
-
export const useGridTreeData = (apiRef, props) => {
|
|
16
|
-
/**
|
|
17
|
-
* ROW GROUPING
|
|
18
|
-
*/
|
|
19
|
-
const updateRowGrouping = React.useCallback(() => {
|
|
20
|
-
if (!props.treeData) {
|
|
21
|
-
return apiRef.current.unstable_registerRowGroupsBuilder('treeData', null);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const groupRows = params => {
|
|
25
|
-
if (!props.getTreeDataPath) {
|
|
26
|
-
throw new Error('MUI: No getTreeDataPath given.');
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const rows = params.ids.map(rowId => ({
|
|
30
|
-
id: rowId,
|
|
31
|
-
path: props.getTreeDataPath(params.idRowsLookup[rowId]).map(key => ({
|
|
32
|
-
key,
|
|
33
|
-
field: null
|
|
34
|
-
}))
|
|
35
|
-
})).sort((a, b) => a.path.length - b.path.length);
|
|
36
|
-
return buildRowTree(_extends({
|
|
37
|
-
rows
|
|
38
|
-
}, params, {
|
|
39
|
-
defaultGroupingExpansionDepth: props.defaultGroupingExpansionDepth,
|
|
40
|
-
isGroupExpandedByDefault: props.isGroupExpandedByDefault,
|
|
41
|
-
groupingName: TREE_DATA_GROUPING_NAME,
|
|
42
|
-
onDuplicatePath: (firstId, secondId, path) => {
|
|
43
|
-
throw new Error(['MUI: The path returned by `getTreeDataPath` should be unique.', `The rows with id #${firstId} and #${secondId} have the same.`, `Path: ${JSON.stringify(path.map(step => step.key))}.`].join('\n'));
|
|
44
|
-
}
|
|
45
|
-
}));
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
return apiRef.current.unstable_registerRowGroupsBuilder('treeData', groupRows);
|
|
49
|
-
}, [apiRef, props.getTreeDataPath, props.treeData, props.defaultGroupingExpansionDepth, props.isGroupExpandedByDefault]);
|
|
50
|
-
useFirstRender(() => {
|
|
51
|
-
updateRowGrouping();
|
|
52
|
-
});
|
|
53
|
-
const isFirstRender = React.useRef(true);
|
|
54
|
-
React.useEffect(() => {
|
|
55
|
-
if (isFirstRender.current) {
|
|
56
|
-
isFirstRender.current = false;
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
updateRowGrouping();
|
|
61
|
-
}, [updateRowGrouping]);
|
|
62
|
-
/**
|
|
63
|
-
* PRE-PROCESSING
|
|
64
|
-
*/
|
|
65
|
-
|
|
66
|
-
const filteringMethod = React.useCallback(params => {
|
|
67
|
-
const rowTree = gridRowTreeSelector(apiRef);
|
|
68
|
-
return filterRowTreeFromTreeData({
|
|
69
|
-
rowTree,
|
|
70
|
-
isRowMatchingFilters: params.isRowMatchingFilters,
|
|
71
|
-
disableChildrenFiltering: props.disableChildrenFiltering
|
|
72
|
-
});
|
|
73
|
-
}, [apiRef, props.disableChildrenFiltering]);
|
|
74
|
-
const sortingMethod = React.useCallback(params => {
|
|
75
|
-
const rowTree = gridRowTreeSelector(apiRef);
|
|
76
|
-
const rowIds = gridRowIdsSelector(apiRef);
|
|
77
|
-
return sortRowTree({
|
|
78
|
-
rowTree,
|
|
79
|
-
rowIds,
|
|
80
|
-
sortRowList: params.sortRowList,
|
|
81
|
-
disableChildrenSorting: props.disableChildrenSorting
|
|
82
|
-
});
|
|
83
|
-
}, [apiRef, props.disableChildrenSorting]);
|
|
84
|
-
useGridRegisterFilteringMethod(apiRef, TREE_DATA_GROUPING_NAME, filteringMethod);
|
|
85
|
-
useGridRegisterSortingMethod(apiRef, TREE_DATA_GROUPING_NAME, sortingMethod);
|
|
7
|
+
export const useGridTreeData = apiRef => {
|
|
86
8
|
/**
|
|
87
9
|
* EVENTS
|
|
88
10
|
*/
|
|
89
|
-
|
|
90
11
|
const handleCellKeyDown = React.useCallback((params, event) => {
|
|
91
12
|
const cellParams = apiRef.current.getCellParams(params.id, params.field);
|
|
92
13
|
|
|
@@ -2,19 +2,25 @@ import _extends from "@babel/runtime/helpers/esm/extends";
|
|
|
2
2
|
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
3
3
|
const _excluded = ["hideDescendantCount"];
|
|
4
4
|
import * as React from 'react';
|
|
5
|
-
import {
|
|
5
|
+
import { gridRowIdsSelector, gridRowTreeSelector, useFirstRender } from '@mui/x-data-grid';
|
|
6
|
+
import { useGridRegisterPipeProcessor, useGridRegisterStrategyProcessor } from '@mui/x-data-grid/internals';
|
|
6
7
|
import { GRID_TREE_DATA_GROUPING_COL_DEF, GRID_TREE_DATA_GROUPING_COL_DEF_FORCED_PROPERTIES } from './gridTreeDataGroupColDef';
|
|
7
|
-
import {
|
|
8
|
+
import { filterRowTreeFromTreeData, TREE_DATA_STRATEGY } from './gridTreeDataUtils';
|
|
8
9
|
import { GridTreeDataGroupingCell } from '../../../components';
|
|
10
|
+
import { buildRowTree } from '../../../utils/tree/buildRowTree';
|
|
11
|
+
import { sortRowTree } from '../../../utils/tree/sortRowTree';
|
|
9
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
10
13
|
export const useGridTreeDataPreProcessors = (apiRef, props) => {
|
|
14
|
+
const setStrategyAvailability = React.useCallback(() => {
|
|
15
|
+
apiRef.current.unstable_setStrategyAvailability('rowTree', TREE_DATA_STRATEGY, props.treeData ? () => true : () => false);
|
|
16
|
+
}, [apiRef, props.treeData]);
|
|
11
17
|
const getGroupingColDef = React.useCallback(() => {
|
|
12
18
|
const groupingColDefProp = props.groupingColDef;
|
|
13
19
|
let colDefOverride;
|
|
14
20
|
|
|
15
21
|
if (typeof groupingColDefProp === 'function') {
|
|
16
22
|
const params = {
|
|
17
|
-
groupingName:
|
|
23
|
+
groupingName: TREE_DATA_STRATEGY,
|
|
18
24
|
fields: []
|
|
19
25
|
};
|
|
20
26
|
colDefOverride = groupingColDefProp(params);
|
|
@@ -63,5 +69,68 @@ export const useGridTreeDataPreProcessors = (apiRef, props) => {
|
|
|
63
69
|
|
|
64
70
|
return columnsState;
|
|
65
71
|
}, [props.treeData, getGroupingColDef]);
|
|
66
|
-
|
|
72
|
+
const createRowTree = React.useCallback(params => {
|
|
73
|
+
if (!props.getTreeDataPath) {
|
|
74
|
+
throw new Error('MUI: No getTreeDataPath given.');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const rows = params.ids.map(rowId => ({
|
|
78
|
+
id: rowId,
|
|
79
|
+
path: props.getTreeDataPath(params.idRowsLookup[rowId]).map(key => ({
|
|
80
|
+
key,
|
|
81
|
+
field: null
|
|
82
|
+
}))
|
|
83
|
+
})).sort((a, b) => a.path.length - b.path.length);
|
|
84
|
+
return buildRowTree(_extends({
|
|
85
|
+
rows
|
|
86
|
+
}, params, {
|
|
87
|
+
defaultGroupingExpansionDepth: props.defaultGroupingExpansionDepth,
|
|
88
|
+
isGroupExpandedByDefault: props.isGroupExpandedByDefault,
|
|
89
|
+
groupingName: TREE_DATA_STRATEGY,
|
|
90
|
+
onDuplicatePath: (firstId, secondId, path) => {
|
|
91
|
+
throw new Error(['MUI: The path returned by `getTreeDataPath` should be unique.', `The rows with id #${firstId} and #${secondId} have the same.`, `Path: ${JSON.stringify(path.map(step => step.key))}.`].join('\n'));
|
|
92
|
+
}
|
|
93
|
+
}));
|
|
94
|
+
}, [props.getTreeDataPath, props.defaultGroupingExpansionDepth, props.isGroupExpandedByDefault]);
|
|
95
|
+
const filterRows = React.useCallback(params => {
|
|
96
|
+
const rowTree = gridRowTreeSelector(apiRef);
|
|
97
|
+
return filterRowTreeFromTreeData({
|
|
98
|
+
rowTree,
|
|
99
|
+
isRowMatchingFilters: params.isRowMatchingFilters,
|
|
100
|
+
disableChildrenFiltering: props.disableChildrenFiltering
|
|
101
|
+
});
|
|
102
|
+
}, [apiRef, props.disableChildrenFiltering]);
|
|
103
|
+
const sortRows = React.useCallback(params => {
|
|
104
|
+
const rowTree = gridRowTreeSelector(apiRef);
|
|
105
|
+
const rowIds = gridRowIdsSelector(apiRef);
|
|
106
|
+
return sortRowTree({
|
|
107
|
+
rowTree,
|
|
108
|
+
rowIds,
|
|
109
|
+
sortRowList: params.sortRowList,
|
|
110
|
+
disableChildrenSorting: props.disableChildrenSorting
|
|
111
|
+
});
|
|
112
|
+
}, [apiRef, props.disableChildrenSorting]);
|
|
113
|
+
useGridRegisterPipeProcessor(apiRef, 'hydrateColumns', updateGroupingColumn);
|
|
114
|
+
useGridRegisterStrategyProcessor(apiRef, TREE_DATA_STRATEGY, 'rowTreeCreation', createRowTree);
|
|
115
|
+
useGridRegisterStrategyProcessor(apiRef, TREE_DATA_STRATEGY, 'filtering', filterRows);
|
|
116
|
+
useGridRegisterStrategyProcessor(apiRef, TREE_DATA_STRATEGY, 'sorting', sortRows);
|
|
117
|
+
/**
|
|
118
|
+
* 1ST RENDER
|
|
119
|
+
*/
|
|
120
|
+
|
|
121
|
+
useFirstRender(() => {
|
|
122
|
+
setStrategyAvailability();
|
|
123
|
+
});
|
|
124
|
+
/**
|
|
125
|
+
* EFFECTS
|
|
126
|
+
*/
|
|
127
|
+
|
|
128
|
+
const isFirstRender = React.useRef(true);
|
|
129
|
+
React.useEffect(() => {
|
|
130
|
+
if (!isFirstRender.current) {
|
|
131
|
+
setStrategyAvailability();
|
|
132
|
+
} else {
|
|
133
|
+
isFirstRender.current = false;
|
|
134
|
+
}
|
|
135
|
+
}, [setStrategyAvailability]);
|
|
67
136
|
};
|
package/modern/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MUI v5.
|
|
1
|
+
/** @license MUI v5.8.0
|
|
2
2
|
*
|
|
3
3
|
* This source code is licensed under the MIT license found in the
|
|
4
4
|
* LICENSE file in the root directory of this source tree.
|
|
@@ -11,9 +11,10 @@ export * from '@mui/x-data-grid/hooks';
|
|
|
11
11
|
export * from '@mui/x-data-grid/locales';
|
|
12
12
|
export * from '@mui/x-data-grid/models';
|
|
13
13
|
export * from '@mui/x-data-grid/context';
|
|
14
|
-
export * from '@mui/x-data-grid/colDef';
|
|
15
14
|
export * from '@mui/x-data-grid/utils';
|
|
15
|
+
export * from '@mui/x-data-grid/colDef';
|
|
16
16
|
export * from './DataGridPro';
|
|
17
17
|
export * from './hooks';
|
|
18
18
|
export * from './models';
|
|
19
|
+
export * from './components';
|
|
19
20
|
export { useGridApiContext, useGridApiRef, useGridRootProps } from './typeOverloads/reexports';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ponyfillGlobal } from '@mui/utils';
|
|
2
|
+
export const getReleaseInfo = () => {
|
|
3
|
+
const releaseInfo = "MTY0OTAyMzIwMDAwMA==";
|
|
4
|
+
|
|
5
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
6
|
+
// A simple hack to set the value in the test environment (has no build step).
|
|
7
|
+
// eslint-disable-next-line no-useless-concat
|
|
8
|
+
if (releaseInfo === '__RELEASE' + '_INFO__') {
|
|
9
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
10
|
+
return ponyfillGlobal.__MUI_RELEASE_INFO__;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return releaseInfo;
|
|
15
|
+
};
|