UNPKG

@mui/x-data-grid

Version:

The community edition of the data grid component (MUI X).

378 lines (370 loc) 17 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import { GridLogicOperator } from '../../../models'; import { GLOBAL_API_REF, isInternalFilter } from '../../../colDef/utils'; import { getDefaultGridFilterModel } from './gridFilterState'; import { buildWarning } from '../../../utils/warning'; import { getPublicApiRef } from '../../../utils/getPublicApiRef'; import { gridColumnFieldsSelector, gridColumnLookupSelector, gridVisibleColumnFieldsSelector } from '../columns'; // Fixes https://github.com/mui/mui-x/issues/10056 var globalScope = typeof window === 'undefined' ? globalThis : window; var evalCode = globalScope[atob('ZXZhbA==')]; var hasEval; try { hasEval = evalCode('true'); } catch (_) { hasEval = false; } /** * Adds default values to the optional fields of a filter items. * @param {GridFilterItem} item The raw filter item. * @param {React.MutableRefObject<GridPrivateApiCommunity>} apiRef The API of the grid. * @return {GridFilterItem} The clean filter item with an uniq ID and an always-defined operator. * TODO: Make the typing reflect the different between GridFilterInputItem and GridFilterItem. */ export var cleanFilterItem = function cleanFilterItem(item, apiRef) { var cleanItem = _extends({}, item); if (cleanItem.id == null) { cleanItem.id = Math.round(Math.random() * 1e5); } if (cleanItem.operator == null) { // Selects a default operator // We don't use `apiRef.current.getColumn` because it is not ready during state initialization var column = gridColumnLookupSelector(apiRef)[cleanItem.field]; cleanItem.operator = column && column.filterOperators[0].value; } return cleanItem; }; var filterModelDisableMultiColumnsFilteringWarning = buildWarning(['MUI: The `filterModel` can only contain a single item when the `disableMultipleColumnsFiltering` prop is set to `true`.', 'If you are using the community version of the `DataGrid`, this prop is always `true`.'], 'error'); var filterModelMissingItemIdWarning = buildWarning('MUI: The `id` field is required on `filterModel.items` when you use multiple filters.', 'error'); var filterModelMissingItemOperatorWarning = buildWarning('MUI: The `operator` field is required on `filterModel.items`, one or more of your filtering item has no `operator` provided.', 'error'); export var sanitizeFilterModel = function sanitizeFilterModel(model, disableMultipleColumnsFiltering, apiRef) { var hasSeveralItems = model.items.length > 1; var items; if (hasSeveralItems && disableMultipleColumnsFiltering) { filterModelDisableMultiColumnsFilteringWarning(); items = [model.items[0]]; } else { items = model.items; } var hasItemsWithoutIds = hasSeveralItems && items.some(function (item) { return item.id == null; }); var hasItemWithoutOperator = items.some(function (item) { return item.operator == null; }); if (hasItemsWithoutIds) { filterModelMissingItemIdWarning(); } if (hasItemWithoutOperator) { filterModelMissingItemOperatorWarning(); } if (hasItemWithoutOperator || hasItemsWithoutIds) { return _extends({}, model, { items: items.map(function (item) { return cleanFilterItem(item, apiRef); }) }); } if (model.items !== items) { return _extends({}, model, { items: items }); } return model; }; export var mergeStateWithFilterModel = function mergeStateWithFilterModel(filterModel, disableMultipleColumnsFiltering, apiRef) { return function (filteringState) { return _extends({}, filteringState, { filterModel: sanitizeFilterModel(filterModel, disableMultipleColumnsFiltering, apiRef) }); }; }; export var removeDiacritics = function removeDiacritics(value) { if (typeof value === 'string') { return value.normalize('NFD').replace(/[\u0300-\u036f]/g, ''); } return value; }; var getFilterCallbackFromItem = function getFilterCallbackFromItem(filterItem, apiRef) { if (!filterItem.field || !filterItem.operator) { return null; } var column = apiRef.current.getColumn(filterItem.field); if (!column) { return null; } var parsedValue; if (column.valueParser) { var _filterItem$value; var parser = column.valueParser; parsedValue = Array.isArray(filterItem.value) ? (_filterItem$value = filterItem.value) == null ? void 0 : _filterItem$value.map(function (x) { return parser(x); }) : parser(filterItem.value); } else { parsedValue = filterItem.value; } var ignoreDiacritics = apiRef.current.rootProps.ignoreDiacritics; if (ignoreDiacritics) { parsedValue = removeDiacritics(parsedValue); } var newFilterItem = _extends({}, filterItem, { value: parsedValue }); var filterOperators = column.filterOperators; if (!(filterOperators != null && filterOperators.length)) { throw new Error("MUI: No filter operators found for column '".concat(column.field, "'.")); } var filterOperator = filterOperators.find(function (operator) { return operator.value === newFilterItem.operator; }); if (!filterOperator) { throw new Error("MUI: No filter operator found for column '".concat(column.field, "' and operator value '").concat(newFilterItem.operator, "'.")); } var hasUserFunctionLegacy = !isInternalFilter(filterOperator.getApplyFilterFn); var hasUserFunctionV7 = !isInternalFilter(filterOperator.getApplyFilterFnV7); var publicApiRef = getPublicApiRef(apiRef); if (filterOperator.getApplyFilterFnV7 && !(hasUserFunctionLegacy && !hasUserFunctionV7)) { var _applyFilterOnRow = filterOperator.getApplyFilterFnV7(newFilterItem, column); if (typeof _applyFilterOnRow !== 'function') { return null; } return { v7: true, item: newFilterItem, fn: function fn(row) { var value = apiRef.current.getRowValue(row, column); if (ignoreDiacritics) { value = removeDiacritics(value); } return _applyFilterOnRow(value, row, column, publicApiRef); } }; } var applyFilterOnRow = filterOperator.getApplyFilterFn(newFilterItem, column); if (typeof applyFilterOnRow !== 'function') { return null; } return { v7: false, item: newFilterItem, fn: function fn(rowId) { var params = apiRef.current.getCellParams(rowId, newFilterItem.field); GLOBAL_API_REF.current = publicApiRef; if (ignoreDiacritics) { params.value = removeDiacritics(params.value); } var result = applyFilterOnRow(params); GLOBAL_API_REF.current = null; return result; } }; }; var filterItemsApplierId = 1; /** * Generates a method to easily check if a row is matching the current filter model. * @param {GridFilterModel} filterModel The model with which we want to filter the rows. * @param {React.MutableRefObject<GridPrivateApiCommunity>} apiRef The API of the grid. * @returns {GridAggregatedFilterItemApplier | null} A method that checks if a row is matching the current filter model. If `null`, we consider that all the rows are matching the filters. */ var buildAggregatedFilterItemsApplier = function buildAggregatedFilterItemsApplier(filterModel, apiRef, disableEval) { var items = filterModel.items; var appliers = items.map(function (item) { return getFilterCallbackFromItem(item, apiRef); }).filter(function (callback) { return !!callback; }); if (appliers.length === 0) { return null; } if (!hasEval || disableEval) { // This is the original logic, which is used if `eval()` is not supported (aka prevented by CSP). return function (row, shouldApplyFilter) { var resultPerItemId = {}; for (var i = 0; i < appliers.length; i += 1) { var applier = appliers[i]; if (!shouldApplyFilter || shouldApplyFilter(applier.item.field)) { resultPerItemId[applier.item.id] = applier.v7 ? applier.fn(row) : applier.fn(apiRef.current.getRowId(row)); } } return resultPerItemId; }; } // We generate a new function with `eval()` to avoid expensive patterns for JS engines // such as a dynamic object assignment, e.g. `{ [dynamicKey]: value }`. var filterItemTemplate = "(function filterItem$$(getRowId, appliers, row, shouldApplyFilter) {\n ".concat(appliers.map(function (applier, i) { return "const shouldApply".concat(i, " = !shouldApplyFilter || shouldApplyFilter(").concat(JSON.stringify(applier.item.field), ");"); }).join('\n'), "\n\n const result$$ = {\n ").concat(appliers.map(function (applier, i) { return "".concat(JSON.stringify(String(applier.item.id)), ":\n !shouldApply").concat(i, " ?\n false :\n ").concat(applier.v7 ? "appliers[".concat(i, "].fn(row)") : "appliers[".concat(i, "].fn(getRowId(row))"), ",\n "); }).join('\n'), "};\n\n return result$$;\n })"); var filterItemCore = evalCode(filterItemTemplate.replaceAll('$$', String(filterItemsApplierId))); var filterItem = function filterItem(row, shouldApplyItem) { return filterItemCore(apiRef.current.getRowId, appliers, row, shouldApplyItem); }; filterItemsApplierId += 1; return filterItem; }; /** * Generates a method to easily check if a row is matching the current quick filter. * @param {any[]} filterModel The model with which we want to filter the rows. * @param {React.MutableRefObject<GridPrivateApiCommunity>} apiRef The API of the grid. * @returns {GridAggregatedFilterItemApplier | null} A method that checks if a row is matching the current filter model. If `null`, we consider that all the rows are matching the filters. */ var buildAggregatedQuickFilterApplier = function buildAggregatedQuickFilterApplier(filterModel, apiRef) { var _filterModel$quickFil, _filterModel$quickFil2, _filterModel$quickFil3; var quickFilterValues = (_filterModel$quickFil = (_filterModel$quickFil2 = filterModel.quickFilterValues) == null ? void 0 : _filterModel$quickFil2.filter(Boolean)) != null ? _filterModel$quickFil : []; if (quickFilterValues.length === 0) { return null; } var quickFilterExcludeHiddenColumns = (_filterModel$quickFil3 = filterModel.quickFilterExcludeHiddenColumns) != null ? _filterModel$quickFil3 : false; var columnFields = quickFilterExcludeHiddenColumns ? gridVisibleColumnFieldsSelector(apiRef) : gridColumnFieldsSelector(apiRef); var appliersPerField = []; var ignoreDiacritics = apiRef.current.rootProps.ignoreDiacritics; var publicApiRef = getPublicApiRef(apiRef); columnFields.forEach(function (field) { var column = apiRef.current.getColumn(field); var getApplyQuickFilterFn = column == null ? void 0 : column.getApplyQuickFilterFn; var getApplyQuickFilterFnV7 = column == null ? void 0 : column.getApplyQuickFilterFnV7; var hasUserFunctionLegacy = !isInternalFilter(getApplyQuickFilterFn); var hasUserFunctionV7 = !isInternalFilter(getApplyQuickFilterFnV7); if (getApplyQuickFilterFnV7 && !(hasUserFunctionLegacy && !hasUserFunctionV7)) { appliersPerField.push({ column: column, appliers: quickFilterValues.map(function (quickFilterValue) { var value = ignoreDiacritics ? removeDiacritics(quickFilterValue) : quickFilterValue; return { v7: true, fn: getApplyQuickFilterFnV7(value, column, publicApiRef) }; }) }); } else if (getApplyQuickFilterFn) { appliersPerField.push({ column: column, appliers: quickFilterValues.map(function (quickFilterValue) { var value = ignoreDiacritics ? removeDiacritics(quickFilterValue) : quickFilterValue; return { v7: false, fn: getApplyQuickFilterFn(value, column, publicApiRef) }; }) }); } }); return function isRowMatchingQuickFilter(row, shouldApplyFilter) { var result = {}; var usedCellParams = {}; /* eslint-disable no-restricted-syntax, no-labels */ outer: for (var v = 0; v < quickFilterValues.length; v += 1) { var filterValue = quickFilterValues[v]; for (var i = 0; i < appliersPerField.length; i += 1) { var _appliersPerField$i = appliersPerField[i], column = _appliersPerField$i.column, appliers = _appliersPerField$i.appliers; var _field = column.field; if (shouldApplyFilter && !shouldApplyFilter(_field)) { continue; } var applier = appliers[v]; var value = apiRef.current.getRowValue(row, column); if (applier.fn === null) { continue; } if (applier.v7) { if (ignoreDiacritics) { value = removeDiacritics(value); } var isMatching = applier.fn(value, row, column, publicApiRef); if (isMatching) { result[filterValue] = true; continue outer; } } else { var _usedCellParams$_fiel; var cellParams = (_usedCellParams$_fiel = usedCellParams[_field]) != null ? _usedCellParams$_fiel : apiRef.current.getCellParams(apiRef.current.getRowId(row), _field); if (ignoreDiacritics) { cellParams.value = removeDiacritics(cellParams.value); } usedCellParams[_field] = cellParams; var _isMatching = applier.fn(cellParams); if (_isMatching) { result[filterValue] = true; continue outer; } } } result[filterValue] = false; } /* eslint-enable no-restricted-syntax, no-labels */ return result; }; }; export var buildAggregatedFilterApplier = function buildAggregatedFilterApplier(filterModel, apiRef, disableEval) { var isRowMatchingFilterItems = buildAggregatedFilterItemsApplier(filterModel, apiRef, disableEval); var isRowMatchingQuickFilter = buildAggregatedQuickFilterApplier(filterModel, apiRef); return function isRowMatchingFilters(row, shouldApplyFilter, result) { var _isRowMatchingFilterI, _isRowMatchingQuickFi; result.passingFilterItems = (_isRowMatchingFilterI = isRowMatchingFilterItems == null ? void 0 : isRowMatchingFilterItems(row, shouldApplyFilter)) != null ? _isRowMatchingFilterI : null; result.passingQuickFilterValues = (_isRowMatchingQuickFi = isRowMatchingQuickFilter == null ? void 0 : isRowMatchingQuickFilter(row, shouldApplyFilter)) != null ? _isRowMatchingQuickFi : null; }; }; var isNotNull = function isNotNull(result) { return result != null; }; var filterModelItems = function filterModelItems(cache, apiRef, items) { if (!cache.cleanedFilterItems) { cache.cleanedFilterItems = items.filter(function (item) { return getFilterCallbackFromItem(item, apiRef) !== null; }); } return cache.cleanedFilterItems; }; export var passFilterLogic = function passFilterLogic(allFilterItemResults, allQuickFilterResults, filterModel, apiRef, cache) { var cleanedFilterItems = filterModelItems(cache, apiRef, filterModel.items); var cleanedFilterItemResults = allFilterItemResults.filter(isNotNull); var cleanedQuickFilterResults = allQuickFilterResults.filter(isNotNull); // get result for filter items model if (cleanedFilterItemResults.length > 0) { var _filterModel$logicOpe; // Return true if the item pass with one of the rows var filterItemPredicate = function filterItemPredicate(item) { return cleanedFilterItemResults.some(function (filterItemResult) { return filterItemResult[item.id]; }); }; var logicOperator = (_filterModel$logicOpe = filterModel.logicOperator) != null ? _filterModel$logicOpe : getDefaultGridFilterModel().logicOperator; if (logicOperator === GridLogicOperator.And) { var passesAllFilters = cleanedFilterItems.every(filterItemPredicate); if (!passesAllFilters) { return false; } } else { var passesSomeFilters = cleanedFilterItems.some(filterItemPredicate); if (!passesSomeFilters) { return false; } } } // get result for quick filter model if (cleanedQuickFilterResults.length > 0 && filterModel.quickFilterValues != null) { var _filterModel$quickFil4; // Return true if the item pass with one of the rows var quickFilterValuePredicate = function quickFilterValuePredicate(value) { return cleanedQuickFilterResults.some(function (quickFilterValueResult) { return quickFilterValueResult[value]; }); }; var quickFilterLogicOperator = (_filterModel$quickFil4 = filterModel.quickFilterLogicOperator) != null ? _filterModel$quickFil4 : getDefaultGridFilterModel().quickFilterLogicOperator; if (quickFilterLogicOperator === GridLogicOperator.And) { var passesAllQuickFilterValues = filterModel.quickFilterValues.every(quickFilterValuePredicate); if (!passesAllQuickFilterValues) { return false; } } else { var passesSomeQuickFilterValues = filterModel.quickFilterValues.some(quickFilterValuePredicate); if (!passesSomeQuickFilterValues) { return false; } } } return true; };