UNPKG

@mui/x-data-grid-premium

Version:

The Premium plan edition of the MUI X Data Grid Components.

165 lines (163 loc) 6.47 kB
import { gridColumnLookupSelector, gridRowTreeSelector, GRID_ROOT_GROUP_ID, gridRowsLookupSelector } from '@mui/x-data-grid-pro'; import { getVisibleRows } from '@mui/x-data-grid-pro/internals'; export const shouldApplySorting = (aggregationRules, aggregatedFields) => { return aggregatedFields.some(field => aggregationRules[field].aggregationFunction.applySorting); }; const getGroupAggregatedValue = (groupId, apiRef, aggregationRowsScope, aggregatedFields, aggregationRules, position, applySorting, valueGetters, publicApi, groupAggregatedValuesLookup, columnsLookup) => { const groupAggregationLookup = {}; const aggregatedValues = []; for (let i = 0; i < aggregatedFields.length; i += 1) { aggregatedValues[i] = { aggregatedField: aggregatedFields[i], values: [] }; } const rowTree = gridRowTreeSelector(apiRef); const rowLookup = gridRowsLookupSelector(apiRef); const isPivotActive = apiRef.current.state.pivoting.active; const rowIds = apiRef.current.getRowGroupChildren({ groupId, applySorting, directChildrenOnly: true, skipAutoGeneratedRows: false, applyFiltering: aggregationRowsScope === 'filtered' }); for (let i = 0; i < rowIds.length; i += 1) { const rowId = rowIds[i]; const rowNode = rowTree[rowId]; if (rowNode.type === 'group') { // MERGE EXISTING VALUES FROM THE LOOKUP TABLE const childGroupValues = groupAggregatedValuesLookup.get(rowId); if (childGroupValues) { for (let j = 0; j < aggregatedFields.length; j += 1) { aggregatedValues[j].values = aggregatedValues[j].values.concat(childGroupValues[j].values); } } continue; } const row = rowLookup[rowId]; if (!row) { continue; } for (let j = 0; j < aggregatedFields.length; j += 1) { const aggregatedField = aggregatedFields[j]; const columnAggregationRules = aggregationRules[aggregatedField]; const aggregationFunction = columnAggregationRules.aggregationFunction; const field = aggregatedField; let value; if (typeof aggregationFunction.getCellValue === 'function') { value = aggregationFunction.getCellValue({ field, row }); } else if (isPivotActive) { // Since we know that pivoted fields are flat, we can use the row directly, and save lots of processing time value = row[field]; } else { const valueGetter = valueGetters[aggregatedField]; value = valueGetter(row); } if (value !== undefined) { aggregatedValues[j].values.push(value); } } } for (let i = 0; i < aggregatedValues.length; i += 1) { const { aggregatedField, values } = aggregatedValues[i]; const aggregationFunction = aggregationRules[aggregatedField].aggregationFunction; const value = aggregationFunction.apply({ values, groupId, field: aggregatedField // Added per user request in https://github.com/mui/mui-x/issues/6995#issuecomment-1327423455 }, publicApi); // Use the actual row from rowLookup if it exists, otherwise pass a new autogenerated row const rowForFormatter = rowLookup[groupId] || { id: groupId, [aggregatedField]: value }; const formattedValue = aggregationFunction.valueFormatter ? aggregationFunction.valueFormatter(value, rowForFormatter, columnsLookup[aggregatedField], apiRef) : undefined; // Only add to groupAggregationLookup if position is not null if (position !== null) { groupAggregationLookup[aggregatedField] = { position, value, formattedValue }; } } return { groupAggregationLookup, aggregatedValues }; }; const getGroupAggregatedValueDataSource = (groupId, apiRef, aggregatedFields, position) => { const groupAggregationLookup = {}; for (let j = 0; j < aggregatedFields.length; j += 1) { const aggregatedField = aggregatedFields[j]; groupAggregationLookup[aggregatedField] = { position, value: apiRef.current.resolveGroupAggregation?.(groupId, aggregatedField) ?? '' }; } return groupAggregationLookup; }; export const createAggregationLookup = ({ apiRef, aggregationRules, aggregatedFields, aggregationRowsScope, getAggregationPosition, isDataSource, applySorting = false }) => { if (aggregatedFields.length === 0) { return {}; } const columnsLookup = gridColumnLookupSelector(apiRef); const valueGetters = {}; for (let i = 0; i < aggregatedFields.length; i += 1) { const field = aggregatedFields[i]; const column = columnsLookup[field]; const valueGetter = row => apiRef.current.getRowValue(row, column); valueGetters[field] = valueGetter; } const aggregationLookup = {}; const rowTree = gridRowTreeSelector(apiRef); const groupAggregatedValuesLookup = new Map(); const { rowIdToIndexMap } = getVisibleRows(apiRef); const createGroupAggregationLookup = groupNode => { let children = groupNode.children; if (applySorting) { children = children.toSorted((a, b) => rowIdToIndexMap.get(a) - rowIdToIndexMap.get(b)); } for (let i = 0; i < children.length; i += 1) { const childId = children[i]; const childNode = rowTree[childId]; if (childNode.type === 'group') { createGroupAggregationLookup(childNode); } } const position = getAggregationPosition(groupNode); if (isDataSource) { if (position !== null) { aggregationLookup[groupNode.id] = getGroupAggregatedValueDataSource(groupNode.id, apiRef, aggregatedFields, position); } } else if (groupNode.children.length) { const result = getGroupAggregatedValue(groupNode.id, apiRef, aggregationRowsScope, aggregatedFields, aggregationRules, position, applySorting, valueGetters, apiRef.current, groupAggregatedValuesLookup, columnsLookup); // Always populate groupAggregatedValuesLookup for groups with children // This ensures parent groups can access child aggregated values even when position is null groupAggregatedValuesLookup.set(groupNode.id, result.aggregatedValues); // Only set aggregationLookup if position is not null (meaning aggregation should be displayed) if (position !== null) { aggregationLookup[groupNode.id] = result.groupAggregationLookup; } } }; createGroupAggregationLookup(rowTree[GRID_ROOT_GROUP_ID]); return aggregationLookup; };