UNPKG

@mui/x-data-grid-pro

Version:

The Pro plan edition of the MUI X Data Grid components.

246 lines (245 loc) 10.2 kB
"use strict"; 'use client'; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.useGridDataSourceBasePro = exports.INITIAL_STATE = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var React = _interopRequireWildcard(require("react")); var _isDeepEqual = require("@mui/x-internals/isDeepEqual"); var _useLazyRef = _interopRequireDefault(require("@mui/utils/useLazyRef")); var _xDataGrid = require("@mui/x-data-grid"); var _internals = require("@mui/x-data-grid/internals"); var _warning = require("@mui/x-internals/warning"); var _utils = require("./utils"); var _gridDataSourceSelector = require("./gridDataSourceSelector"); const INITIAL_STATE = exports.INITIAL_STATE = { loading: {}, errors: {} }; const useGridDataSourceBasePro = (apiRef, props, options = {}) => { const groupsToAutoFetch = (0, _xDataGrid.useGridSelector)(apiRef, _internals.gridRowGroupsToFetchSelector); const nestedDataManager = (0, _useLazyRef.default)(() => new _utils.NestedDataManager(apiRef)).current; const scheduledGroups = React.useRef(0); const clearDataSourceState = React.useCallback(() => { nestedDataManager.clear(); scheduledGroups.current = 0; const dataSourceState = apiRef.current.state.dataSource; if (dataSourceState !== INITIAL_STATE) { apiRef.current.resetDataSourceState(); } return null; }, [apiRef, nestedDataManager]); const handleEditRow = React.useCallback((params, updatedRow) => { const groupKeys = (0, _utils.getGroupKeys)((0, _xDataGrid.gridRowTreeSelector)(apiRef), params.rowId); apiRef.current.updateNestedRows([updatedRow], groupKeys); if (updatedRow && !(0, _isDeepEqual.isDeepEqual)(updatedRow, params.previousRow)) { // Reset the outdated cache, only if the row is _actually_ updated apiRef.current.dataSource.cache.clear(); } }, [apiRef]); const { api, debouncedFetchRows, strategyProcessor, events, cacheChunkManager, cache } = (0, _internals.useGridDataSourceBase)(apiRef, props, (0, _extends2.default)({ fetchRowChildren: nestedDataManager.queue, clearDataSourceState, handleEditRow }, options)); const setStrategyAvailability = React.useCallback(() => { apiRef.current.setStrategyAvailability(_internals.GridStrategyGroup.DataSource, _internals.DataSourceRowsUpdateStrategy.Default, props.dataSource && !props.lazyLoading ? () => true : () => false); }, [apiRef, props.dataSource, props.lazyLoading]); const onDataSourceErrorProp = props.onDataSourceError; const fetchRowChildren = React.useCallback(async id => { const pipedParams = apiRef.current.unstable_applyPipeProcessors('getRowsParams', {}); if (!props.treeData && (pipedParams.groupFields?.length ?? 0) === 0) { nestedDataManager.clearPendingRequest(id); return; } const getRows = props.dataSource?.getRows; if (!getRows) { nestedDataManager.clearPendingRequest(id); return; } const rowNode = apiRef.current.getRowNode(id); if (!rowNode) { nestedDataManager.clearPendingRequest(id); return; } const fetchParams = (0, _extends2.default)({}, (0, _internals.gridGetRowsParamsSelector)(apiRef), pipedParams, { groupKeys: rowNode.path }); const cacheKeys = cacheChunkManager.getCacheKeys(fetchParams); const responses = cacheKeys.map(cacheKey => cache.get(cacheKey)); const cachedData = responses.some(response => response === undefined) ? undefined : _internals.CacheChunkManager.mergeResponses(responses); if (cachedData !== undefined) { const rows = cachedData.rows; nestedDataManager.setRequestSettled(id); apiRef.current.updateNestedRows(rows, rowNode.path); if (cachedData.rowCount !== undefined) { apiRef.current.setRowCount(cachedData.rowCount); } apiRef.current.setRowChildrenExpansion(id, true); apiRef.current.dataSource.setChildrenLoading(id, false); return; } const existingError = (0, _gridDataSourceSelector.gridDataSourceErrorsSelector)(apiRef)[id] ?? null; if (existingError) { apiRef.current.dataSource.setChildrenFetchError(id, null); } try { const getRowsResponse = await getRows(fetchParams); if (!apiRef.current.getRowNode(id)) { // The row has been removed from the grid nestedDataManager.clearPendingRequest(id); return; } if (nestedDataManager.getRequestStatus(id) === _utils.RequestStatus.UNKNOWN) { apiRef.current.dataSource.setChildrenLoading(id, false); return; } nestedDataManager.setRequestSettled(id); const cacheResponses = cacheChunkManager.splitResponse(fetchParams, getRowsResponse); cacheResponses.forEach((response, key) => { cache.set(key, response); }); if (getRowsResponse.rowCount !== undefined) { apiRef.current.setRowCount(getRowsResponse.rowCount); } // Remove existing outdated rows before setting the new ones const rowsToDelete = []; getRowsResponse.rows.forEach(row => { const rowId = (0, _xDataGrid.gridRowIdSelector)(apiRef, row); const treeNode = (0, _xDataGrid.gridRowNodeSelector)(apiRef, rowId); if (treeNode) { rowsToDelete.push({ id: rowId, _action: 'delete' }); } }); if (rowsToDelete.length > 0) { // TODO: Make this happen in a single pass by modifying the pre-processing of the rows apiRef.current.updateNestedRows(rowsToDelete, rowNode.path); } apiRef.current.updateNestedRows(getRowsResponse.rows, rowNode.path); apiRef.current.setRowChildrenExpansion(id, true); } catch (error) { const childrenFetchError = error; apiRef.current.dataSource.setChildrenFetchError(id, childrenFetchError); if (typeof onDataSourceErrorProp === 'function') { onDataSourceErrorProp(new _xDataGrid.GridGetRowsError({ message: childrenFetchError.message, params: fetchParams, cause: childrenFetchError })); } else if (process.env.NODE_ENV !== 'production') { (0, _warning.warnOnce)(['MUI X: A call to `dataSource.getRows()` threw an error which was not handled because `onDataSourceError()` is missing.', 'To handle the error pass a callback to the `onDataSourceError` prop, for example `<DataGrid onDataSourceError={(error) => ...} />`.', 'For more detail, see https://mui.com/x/react-data-grid/server-side-data/#error-handling.'], 'error'); } } finally { apiRef.current.dataSource.setChildrenLoading(id, false); nestedDataManager.setRequestSettled(id); } }, [nestedDataManager, cacheChunkManager, cache, onDataSourceErrorProp, apiRef, props.treeData, props.dataSource?.getRows]); const setChildrenLoading = React.useCallback((parentId, isLoading) => { apiRef.current.setState(state => { if (!state.dataSource.loading[parentId] && isLoading === false) { return state; } const newLoadingState = (0, _extends2.default)({}, state.dataSource.loading); if (isLoading === false) { delete newLoadingState[parentId]; } else { newLoadingState[parentId] = isLoading; } return (0, _extends2.default)({}, state, { dataSource: (0, _extends2.default)({}, state.dataSource, { loading: newLoadingState }) }); }); }, [apiRef]); const setChildrenFetchError = React.useCallback((parentId, error) => { apiRef.current.setState(state => { const newErrorsState = (0, _extends2.default)({}, state.dataSource.errors); if (error === null && newErrorsState[parentId] !== undefined) { delete newErrorsState[parentId]; } else { newErrorsState[parentId] = error; } return (0, _extends2.default)({}, state, { dataSource: (0, _extends2.default)({}, state.dataSource, { errors: newErrorsState }) }); }); }, [apiRef]); const resetDataSourceState = React.useCallback(() => { apiRef.current.setState(state => { return (0, _extends2.default)({}, state, { dataSource: INITIAL_STATE }); }); }, [apiRef]); const removeChildrenRows = React.useCallback(parentId => { const rowNode = (0, _xDataGrid.gridRowNodeSelector)(apiRef, parentId); if (!rowNode || rowNode.type !== 'group' || rowNode.children.length === 0) { return; } const removedRows = []; const traverse = nodeId => { const node = (0, _xDataGrid.gridRowNodeSelector)(apiRef, nodeId); if (!node) { return; } if (node.type === 'group' && node.children.length > 0) { node.children.forEach(traverse); } removedRows.push({ id: nodeId, _action: 'delete' }); }; rowNode.children.forEach(traverse); if (removedRows.length > 0) { apiRef.current.updateNestedRows(removedRows, rowNode.path); } }, [apiRef]); const dataSourceApi = { dataSource: (0, _extends2.default)({}, api.public.dataSource, { setChildrenLoading, setChildrenFetchError }) }; const dataSourcePrivateApi = { fetchRowChildren, resetDataSourceState, removeChildrenRows }; React.useEffect(() => { if (groupsToAutoFetch && groupsToAutoFetch.length && scheduledGroups.current < groupsToAutoFetch.length) { const groupsToSchedule = groupsToAutoFetch.slice(scheduledGroups.current); nestedDataManager.queue(groupsToSchedule); scheduledGroups.current = groupsToAutoFetch.length; } }, [apiRef, nestedDataManager, groupsToAutoFetch]); return { api: { public: dataSourceApi, private: dataSourcePrivateApi }, debouncedFetchRows, strategyProcessor, events, setStrategyAvailability, cacheChunkManager, cache }; }; exports.useGridDataSourceBasePro = useGridDataSourceBasePro;