UNPKG

@mui/x-data-grid-premium

Version:

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

403 lines (398 loc) 16.7 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.CrossParentLeafOperation = exports.CrossParentGroupOperation = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _xDataGridPro = require("@mui/x-data-grid-pro"); var _internals = require("@mui/x-data-grid-pro/internals"); var _rowGrouping = require("../rowGrouping"); var _gridRowGroupingUtils = require("../rowGrouping/gridRowGroupingUtils"); /** * Handles moving leaf nodes between different parent groups. */ class CrossParentLeafOperation extends _internals.BaseReorderOperation { operationType = 'cross-parent-leaf'; detectOperation(ctx) { const { sourceRowId, placeholderIndex, sortedFilteredRowIds, rowTree, apiRef } = ctx; const sourceNode = (0, _xDataGridPro.gridRowNodeSelector)(apiRef, sourceRowId); if (!sourceNode || sourceNode.type === 'footer') { return null; } let targetNode = (0, _xDataGridPro.gridRowNodeSelector)(apiRef, sortedFilteredRowIds[placeholderIndex]); let isLastChild = false; if (!targetNode) { if (placeholderIndex >= sortedFilteredRowIds.length && sortedFilteredRowIds.length > 0) { targetNode = (0, _xDataGridPro.gridRowNodeSelector)(apiRef, sortedFilteredRowIds[sortedFilteredRowIds.length - 1]); isLastChild = true; } else { return null; } } let adjustedTargetNode = targetNode; // Case D adjustment if (sourceNode.type === 'leaf' && targetNode.type === 'group' && targetNode.depth < sourceNode.depth) { const prevIndex = placeholderIndex - 1; if (prevIndex >= 0) { const prevRowId = sortedFilteredRowIds[prevIndex]; const leafTargetNode = (0, _xDataGridPro.gridRowNodeSelector)(apiRef, prevRowId); if (leafTargetNode && leafTargetNode.type === 'leaf') { adjustedTargetNode = leafTargetNode; isLastChild = true; } } } const operationType = _internals.rowReorderUtils.determineOperationType(sourceNode, adjustedTargetNode); if (operationType !== 'cross-parent-leaf') { return null; } const actualTargetIndex = _internals.rowReorderUtils.calculateTargetIndex(sourceNode, adjustedTargetNode, isLastChild, rowTree); targetNode = adjustedTargetNode; // Validate depth constraints if (sourceNode.type === 'leaf' && targetNode.type === 'leaf') { if (sourceNode.depth !== targetNode.depth) { return null; } } else if (sourceNode.type === 'leaf' && targetNode.type === 'group') { if (targetNode.depth >= sourceNode.depth) { return null; } } return { sourceNode, targetNode: adjustedTargetNode, actualTargetIndex, isLastChild, operationType }; } async executeOperation(operation, ctx) { const { sourceNode, targetNode, isLastChild } = operation; const { apiRef, sourceRowId, processRowUpdate, onProcessRowUpdateError } = ctx; let target = targetNode; if (targetNode.type === 'group') { const prevIndex = ctx.placeholderIndex - 1; if (prevIndex >= 0) { const prevRowId = ctx.sortedFilteredRowIds[prevIndex]; const prevNode = (0, _xDataGridPro.gridRowNodeSelector)(apiRef, prevRowId); if (prevNode && prevNode.type === 'leaf') { target = prevNode; } } } const rowTree = (0, _xDataGridPro.gridRowTreeSelector)(apiRef); const sourceGroup = rowTree[sourceNode.parent]; const targetGroup = rowTree[target.parent]; const sourceChildren = sourceGroup.children; const targetChildren = targetGroup.children; const sourceIndex = sourceChildren.findIndex(row => row === sourceRowId); const targetIndex = targetChildren.findIndex(row => row === target.id); if (sourceIndex === -1 || targetIndex === -1) { return; } const dataRowIdToModelLookup = (0, _xDataGridPro.gridRowsLookupSelector)(apiRef); const columnsLookup = (0, _xDataGridPro.gridColumnLookupSelector)(apiRef); const sanitizedRowGroupingModel = (0, _rowGrouping.gridRowGroupingSanitizedModelSelector)(apiRef); const originalSourceRow = dataRowIdToModelLookup[sourceRowId]; let updatedSourceRow = (0, _extends2.default)({}, originalSourceRow); const targetRow = dataRowIdToModelLookup[target.id]; const groupingRules = (0, _gridRowGroupingUtils.getGroupingRules)({ sanitizedRowGroupingModel, columnsLookup }); for (const groupingRule of groupingRules) { const colDef = columnsLookup[groupingRule.field]; if (groupingRule.groupingValueSetter && colDef) { const targetGroupingValue = (0, _gridRowGroupingUtils.getCellGroupingCriteria)({ row: targetRow, colDef, groupingRule, apiRef }).key; updatedSourceRow = groupingRule.groupingValueSetter(targetGroupingValue, updatedSourceRow, colDef, apiRef); } else { updatedSourceRow[groupingRule.field] = targetRow[groupingRule.field]; } } const updater = new _internals.rowReorderUtils.BatchRowUpdater(apiRef, processRowUpdate, onProcessRowUpdateError); updater.queueUpdate(sourceRowId, originalSourceRow, updatedSourceRow); const { successful, updates } = await updater.executeAll(); if (successful.length === 0) { return; } const finalSourceRow = updates[0]; apiRef.current.setState(state => { const updatedSourceChildren = sourceChildren.filter(rowId => rowId !== sourceRowId); const updatedTree = (0, _extends2.default)({}, state.rows.tree); const removedGroups = new Set(); let rootLevelRemovals = 0; if (updatedSourceChildren.length === 0) { removedGroups.add(sourceGroup.id); rootLevelRemovals = _internals.rowReorderUtils.removeEmptyAncestors(sourceGroup.parent, updatedTree, removedGroups); } removedGroups.forEach(groupId => { const group = updatedTree[groupId]; if (group && group.parent && updatedTree[group.parent]) { const parent = updatedTree[group.parent]; updatedTree[group.parent] = (0, _extends2.default)({}, parent, { children: parent.children.filter(childId => childId !== groupId) }); } delete updatedTree[groupId]; }); if (!removedGroups.has(sourceGroup.id)) { updatedTree[sourceNode.parent] = (0, _extends2.default)({}, sourceGroup, { children: updatedSourceChildren }); } const updatedTargetChildren = isLastChild ? [...targetChildren, sourceRowId] : [...targetChildren.slice(0, targetIndex), sourceRowId, ...targetChildren.slice(targetIndex)]; updatedTree[target.parent] = (0, _extends2.default)({}, targetGroup, { children: updatedTargetChildren }); updatedTree[sourceNode.id] = (0, _extends2.default)({}, sourceNode, { parent: target.parent }); return (0, _extends2.default)({}, state, { rows: (0, _extends2.default)({}, state.rows, { totalTopLevelRowCount: state.rows.totalTopLevelRowCount - rootLevelRemovals, tree: updatedTree }) }); }); apiRef.current.updateRows([finalSourceRow]); apiRef.current.publishEvent('rowsSet'); } } /** * Handles moving entire groups between different parents. */ exports.CrossParentLeafOperation = CrossParentLeafOperation; class CrossParentGroupOperation extends _internals.BaseReorderOperation { operationType = 'cross-parent-group'; detectOperation(ctx) { const { sourceRowId, placeholderIndex, sortedFilteredRowIds, rowTree, apiRef } = ctx; const sourceNode = (0, _xDataGridPro.gridRowNodeSelector)(apiRef, sourceRowId); if (!sourceNode || sourceNode.type === 'footer') { return null; } let targetIndex = placeholderIndex; let targetNode = (0, _xDataGridPro.gridRowNodeSelector)(apiRef, sortedFilteredRowIds[placeholderIndex]); let isLastChild = false; if (!targetNode) { if (placeholderIndex >= sortedFilteredRowIds.length && sortedFilteredRowIds.length > 0) { targetNode = (0, _xDataGridPro.gridRowNodeSelector)(apiRef, sortedFilteredRowIds[sortedFilteredRowIds.length - 1]); targetIndex = sortedFilteredRowIds.length - 1; isLastChild = true; } else { return null; } } let adjustedTargetNode = targetNode; // Case G adjustment if (sourceNode.type === 'group' && targetNode.type === 'group' && sourceNode.parent !== targetNode.parent && sourceNode.depth > targetNode.depth) { let prevIndex = targetIndex - 1; if (prevIndex < 0) { return null; } let prevNode = (0, _xDataGridPro.gridRowNodeSelector)(apiRef, sortedFilteredRowIds[prevIndex]); if (prevNode && prevNode.depth !== sourceNode.depth) { while (prevNode.depth > sourceNode.depth && prevIndex >= 0) { prevIndex -= 1; prevNode = (0, _xDataGridPro.gridRowNodeSelector)(apiRef, sortedFilteredRowIds[prevIndex]); } } if (!prevNode || prevNode.type !== 'group' || prevNode.depth !== sourceNode.depth) { return null; } isLastChild = true; adjustedTargetNode = prevNode; } const operationType = _internals.rowReorderUtils.determineOperationType(sourceNode, adjustedTargetNode); if (operationType !== 'cross-parent-group') { return null; } const actualTargetIndex = _internals.rowReorderUtils.calculateTargetIndex(sourceNode, adjustedTargetNode, isLastChild, rowTree); const operation = { sourceNode, targetNode: adjustedTargetNode, actualTargetIndex, isLastChild, operationType }; targetNode = adjustedTargetNode; if (sourceNode.depth !== targetNode.depth) { return null; } return operation; } async executeOperation(operation, ctx) { const { sourceNode, targetNode, isLastChild } = operation; const { apiRef, processRowUpdate, onProcessRowUpdateError } = ctx; const tree = (0, _xDataGridPro.gridRowTreeSelector)(apiRef); const dataRowIdToModelLookup = (0, _xDataGridPro.gridRowsLookupSelector)(apiRef); const columnsLookup = (0, _xDataGridPro.gridColumnLookupSelector)(apiRef); const sanitizedRowGroupingModel = (0, _rowGrouping.gridRowGroupingSanitizedModelSelector)(apiRef); const allLeafIds = _internals.rowReorderUtils.collectAllLeafDescendants(sourceNode, tree); if (allLeafIds.length === 0) { return; } const updater = new _internals.rowReorderUtils.BatchRowUpdater(apiRef, processRowUpdate, onProcessRowUpdateError); const groupingRules = (0, _gridRowGroupingUtils.getGroupingRules)({ sanitizedRowGroupingModel, columnsLookup }); const targetParentPath = _internals.rowReorderUtils.getNodePathInTree({ id: targetNode.parent, tree }); for (const leafId of allLeafIds) { const originalRow = dataRowIdToModelLookup[leafId]; let updatedRow = (0, _extends2.default)({}, originalRow); for (let depth = 0; depth < targetParentPath.length; depth += 1) { const pathItem = targetParentPath[depth]; if (pathItem.field) { const groupingRule = groupingRules.find(rule => rule.field === pathItem.field); if (groupingRule) { const colDef = columnsLookup[groupingRule.field]; if (groupingRule.groupingValueSetter && colDef) { updatedRow = groupingRule.groupingValueSetter(pathItem.key, updatedRow, colDef, apiRef); } else { updatedRow[groupingRule.field] = pathItem.key; } } } } updater.queueUpdate(leafId, originalRow, updatedRow); } const { successful, failed, updates } = await updater.executeAll(); if (successful.length > 0) { apiRef.current.setState(state => { const updatedTree = (0, _extends2.default)({}, state.rows.tree); const treeDepths = (0, _extends2.default)({}, state.rows.treeDepths); let rootLevelRemovals = 0; if (failed.length === 0) { const sourceParentNode = updatedTree[sourceNode.parent]; if (!sourceParentNode) { const targetParentNode = updatedTree[targetNode.parent]; const targetIndex = targetParentNode.children.indexOf(targetNode.id); const newTargetChildren = [...targetParentNode.children]; if (isLastChild) { newTargetChildren.push(sourceNode.id); } else { newTargetChildren.splice(targetIndex, 0, sourceNode.id); } updatedTree[targetNode.parent] = (0, _extends2.default)({}, targetParentNode, { children: newTargetChildren }); updatedTree[sourceNode.id] = (0, _extends2.default)({}, sourceNode, { parent: targetNode.parent }); } else { const updatedSourceParentChildren = sourceParentNode.children.filter(id => id !== sourceNode.id); if (updatedSourceParentChildren.length === 0) { const removedGroups = new Set(); removedGroups.add(sourceNode.parent); const parentOfSourceParent = updatedTree[sourceNode.parent].parent; if (parentOfSourceParent) { rootLevelRemovals = _internals.rowReorderUtils.removeEmptyAncestors(parentOfSourceParent, updatedTree, removedGroups); } removedGroups.forEach(groupId => { const group = updatedTree[groupId]; if (group && group.parent && updatedTree[group.parent]) { const parent = updatedTree[group.parent]; updatedTree[group.parent] = (0, _extends2.default)({}, parent, { children: parent.children.filter(childId => childId !== groupId) }); } delete updatedTree[groupId]; }); } else { updatedTree[sourceNode.parent] = (0, _extends2.default)({}, sourceParentNode, { children: updatedSourceParentChildren }); } const targetParentNode = updatedTree[targetNode.parent]; const sourceGroupNode = sourceNode; const existingGroup = sourceGroupNode.groupingKey !== null && sourceGroupNode.groupingField !== null ? _internals.rowReorderUtils.findExistingGroupWithSameKey(targetParentNode, sourceGroupNode.groupingKey, sourceGroupNode.groupingField, updatedTree) : null; if (existingGroup) { const updatedExistingGroup = (0, _extends2.default)({}, existingGroup, { children: [...existingGroup.children, ...sourceGroupNode.children] }); updatedTree[existingGroup.id] = updatedExistingGroup; sourceGroupNode.children.forEach(childId => { const childNode = updatedTree[childId]; if (childNode) { updatedTree[childId] = (0, _extends2.default)({}, childNode, { parent: existingGroup.id }); } }); delete updatedTree[sourceNode.id]; } else { const targetIndex = targetParentNode.children.indexOf(targetNode.id); const newTargetChildren = [...targetParentNode.children]; if (isLastChild) { newTargetChildren.push(sourceNode.id); } else { newTargetChildren.splice(targetIndex, 0, sourceNode.id); } updatedTree[targetNode.parent] = (0, _extends2.default)({}, targetParentNode, { children: newTargetChildren }); updatedTree[sourceNode.id] = (0, _extends2.default)({}, sourceNode, { parent: targetNode.parent }); } } } return (0, _extends2.default)({}, state, { rows: (0, _extends2.default)({}, state.rows, { totalTopLevelRowCount: state.rows.totalTopLevelRowCount - rootLevelRemovals, tree: updatedTree, treeDepths }) }); }); apiRef.current.updateRows(updates); apiRef.current.publishEvent('rowsSet'); } } } exports.CrossParentGroupOperation = CrossParentGroupOperation;