@mui/x-data-grid-generator 7.7.0 → 7.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.
@@ -0,0 +1,345 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import { GridLogicOperator } from '@mui/x-data-grid-pro';
3
+ import { randomInt } from '../services/random-generator';
4
+ export const DEFAULT_DATASET_OPTIONS = {
5
+ dataSet: 'Commodity',
6
+ rowLength: 100,
7
+ maxColumns: 6
8
+ };
9
+ export const disableDelay = typeof DISABLE_CHANCE_RANDOM !== 'undefined' && DISABLE_CHANCE_RANDOM;
10
+ export const DEFAULT_SERVER_OPTIONS = {
11
+ minDelay: disableDelay ? 0 : 100,
12
+ maxDelay: disableDelay ? 0 : 300,
13
+ useCursorPagination: true
14
+ };
15
+ const apiRef = {};
16
+ const simplifiedValueGetter = (field, colDef) => row => {
17
+ return colDef.valueGetter?.(row[row.id], row, colDef, apiRef) || row[field];
18
+ };
19
+ const getRowComparator = (sortModel, columnsWithDefaultColDef) => {
20
+ if (!sortModel) {
21
+ const comparator = () => 0;
22
+ return comparator;
23
+ }
24
+ const sortOperators = sortModel.map(sortItem => {
25
+ const columnField = sortItem.field;
26
+ const colDef = columnsWithDefaultColDef.find(({
27
+ field
28
+ }) => field === columnField);
29
+ return _extends({}, sortItem, {
30
+ valueGetter: simplifiedValueGetter(columnField, colDef),
31
+ sortComparator: colDef.sortComparator
32
+ });
33
+ });
34
+ const comparator = (row1, row2) => sortOperators.reduce((acc, {
35
+ valueGetter,
36
+ sort,
37
+ sortComparator
38
+ }) => {
39
+ if (acc !== 0) {
40
+ return acc;
41
+ }
42
+ const v1 = valueGetter(row1);
43
+ const v2 = valueGetter(row2);
44
+ return sort === 'desc' ? -1 * sortComparator(v1, v2) : sortComparator(v1, v2);
45
+ }, 0);
46
+ return comparator;
47
+ };
48
+ const buildQuickFilterApplier = (filterModel, columns) => {
49
+ const quickFilterValues = filterModel.quickFilterValues?.filter(Boolean) ?? [];
50
+ if (quickFilterValues.length === 0) {
51
+ return null;
52
+ }
53
+ const appliersPerField = [];
54
+ const stubApiRef = {
55
+ current: {
56
+ getRowFormattedValue: (row, c) => {
57
+ const field = c.field;
58
+ return row[field];
59
+ }
60
+ }
61
+ };
62
+ columns.forEach(column => {
63
+ const getApplyQuickFilterFn = column?.getApplyQuickFilterFn;
64
+ if (getApplyQuickFilterFn) {
65
+ appliersPerField.push({
66
+ column,
67
+ appliers: quickFilterValues.map(quickFilterValue => {
68
+ return {
69
+ fn: getApplyQuickFilterFn(quickFilterValue, column, stubApiRef)
70
+ };
71
+ })
72
+ });
73
+ }
74
+ });
75
+ return function isRowMatchingQuickFilter(row, shouldApplyFilter) {
76
+ const result = {};
77
+
78
+ /* eslint-disable no-labels */
79
+ outer: for (let v = 0; v < quickFilterValues.length; v += 1) {
80
+ const filterValue = quickFilterValues[v];
81
+ for (let i = 0; i < appliersPerField.length; i += 1) {
82
+ const {
83
+ column,
84
+ appliers
85
+ } = appliersPerField[i];
86
+ const {
87
+ field
88
+ } = column;
89
+ if (shouldApplyFilter && !shouldApplyFilter(field)) {
90
+ continue;
91
+ }
92
+ const applier = appliers[v];
93
+ const value = row[field];
94
+ if (applier.fn === null) {
95
+ continue;
96
+ }
97
+ const isMatching = applier.fn(value, row, column, stubApiRef);
98
+ if (isMatching) {
99
+ result[filterValue] = true;
100
+ continue outer;
101
+ }
102
+ }
103
+ result[filterValue] = false;
104
+ }
105
+ /* eslint-enable no-labels */
106
+
107
+ return result;
108
+ };
109
+ };
110
+ const getQuicklyFilteredRows = (rows, filterModel, columnsWithDefaultColDef) => {
111
+ if (filterModel === undefined || filterModel.quickFilterValues?.length === 0) {
112
+ return rows;
113
+ }
114
+ const isRowMatchingQuickFilter = buildQuickFilterApplier(filterModel, columnsWithDefaultColDef);
115
+ if (isRowMatchingQuickFilter) {
116
+ return rows.filter(row => {
117
+ const result = isRowMatchingQuickFilter(row);
118
+ return filterModel.quickFilterLogicOperator === GridLogicOperator.And ? Object.values(result).every(Boolean) : Object.values(result).some(Boolean);
119
+ });
120
+ }
121
+ return rows;
122
+ };
123
+ const getFilteredRows = (rows, filterModel, columnsWithDefaultColDef) => {
124
+ if (filterModel === undefined || filterModel.items.length === 0) {
125
+ return rows;
126
+ }
127
+ const valueGetters = filterModel.items.map(({
128
+ field
129
+ }) => simplifiedValueGetter(field, columnsWithDefaultColDef.find(column => column.field === field)));
130
+ const filterFunctions = filterModel.items.map(filterItem => {
131
+ const {
132
+ field,
133
+ operator
134
+ } = filterItem;
135
+ const colDef = columnsWithDefaultColDef.find(column => column.field === field);
136
+ if (!colDef.filterOperators) {
137
+ throw new Error(`MUI: No filter operator found for column '${field}'.`);
138
+ }
139
+ const filterOperator = colDef.filterOperators.find(({
140
+ value
141
+ }) => operator === value);
142
+ let parsedValue = filterItem.value;
143
+ if (colDef.valueParser) {
144
+ const parser = colDef.valueParser;
145
+ parsedValue = Array.isArray(filterItem.value) ? filterItem.value?.map(x => parser(x, {}, colDef, apiRef)) : parser(filterItem.value, {}, colDef, apiRef);
146
+ }
147
+ return filterOperator.getApplyFilterFn({
148
+ filterItem,
149
+ value: parsedValue
150
+ }, colDef);
151
+ });
152
+ if (filterModel.logicOperator === GridLogicOperator.Or) {
153
+ return rows.filter(row => filterModel.items.some((_, index) => {
154
+ const value = valueGetters[index](row);
155
+ return filterFunctions[index] === null ? true : filterFunctions[index](value);
156
+ }));
157
+ }
158
+ return rows.filter(row => filterModel.items.every((_, index) => {
159
+ const value = valueGetters[index](row);
160
+ return filterFunctions[index] === null ? true : filterFunctions[index](value);
161
+ }));
162
+ };
163
+
164
+ /**
165
+ * Simulates server data loading
166
+ */
167
+ export const loadServerRows = (rows, queryOptions, serverOptions, columnsWithDefaultColDef) => {
168
+ const {
169
+ minDelay = 100,
170
+ maxDelay = 300,
171
+ useCursorPagination
172
+ } = serverOptions;
173
+ if (maxDelay < minDelay) {
174
+ throw new Error('serverOptions.minDelay is larger than serverOptions.maxDelay ');
175
+ }
176
+ const delay = randomInt(minDelay, maxDelay);
177
+ const {
178
+ cursor,
179
+ page = 0,
180
+ pageSize
181
+ } = queryOptions;
182
+ let nextCursor;
183
+ let firstRowIndex;
184
+ let lastRowIndex;
185
+ let filteredRows = getFilteredRows(rows, queryOptions.filterModel, columnsWithDefaultColDef);
186
+ const rowComparator = getRowComparator(queryOptions.sortModel, columnsWithDefaultColDef);
187
+ filteredRows = [...filteredRows].sort(rowComparator);
188
+ const totalRowCount = filteredRows.length;
189
+ if (!pageSize) {
190
+ firstRowIndex = 0;
191
+ lastRowIndex = filteredRows.length;
192
+ } else if (useCursorPagination) {
193
+ firstRowIndex = cursor ? filteredRows.findIndex(({
194
+ id
195
+ }) => id === cursor) : 0;
196
+ firstRowIndex = Math.max(firstRowIndex, 0); // if cursor not found return 0
197
+ lastRowIndex = firstRowIndex + pageSize;
198
+ nextCursor = lastRowIndex >= filteredRows.length ? undefined : filteredRows[lastRowIndex].id;
199
+ } else {
200
+ firstRowIndex = page * pageSize;
201
+ lastRowIndex = (page + 1) * pageSize;
202
+ }
203
+ const hasNextPage = lastRowIndex < filteredRows.length - 1;
204
+ const response = {
205
+ returnedRows: filteredRows.slice(firstRowIndex, lastRowIndex),
206
+ hasNextPage,
207
+ nextCursor,
208
+ totalRowCount
209
+ };
210
+ return new Promise(resolve => {
211
+ setTimeout(() => {
212
+ resolve(response);
213
+ }, delay); // simulate network latency
214
+ });
215
+ };
216
+ const findTreeDataRowChildren = (allRows, parentPath, pathKey = 'path', depth = 1 // the depth of the children to find relative to parentDepth, `-1` to find all
217
+ ) => {
218
+ const parentDepth = parentPath.length;
219
+ const children = [];
220
+ for (let i = 0; i < allRows.length; i += 1) {
221
+ const row = allRows[i];
222
+ const rowPath = row[pathKey];
223
+ if (!rowPath) {
224
+ continue;
225
+ }
226
+ if ((depth < 0 && rowPath.length > parentDepth || rowPath.length === parentDepth + depth) && parentPath.every((value, index) => value === rowPath[index])) {
227
+ children.push(row);
228
+ }
229
+ }
230
+ return children;
231
+ };
232
+ const getTreeDataFilteredRows = (rows, filterModel, columnsWithDefaultColDef) => {
233
+ let filteredRows = [...rows];
234
+ if (filterModel && filterModel.quickFilterValues?.length > 0) {
235
+ filteredRows = getQuicklyFilteredRows(rows, filterModel, columnsWithDefaultColDef);
236
+ }
237
+ if ((filterModel?.items.length ?? 0) > 0) {
238
+ filteredRows = getFilteredRows(filteredRows, filterModel, columnsWithDefaultColDef);
239
+ }
240
+ if (filteredRows.length === rows.length || filteredRows.length === 0) {
241
+ return filteredRows;
242
+ }
243
+ const pathsToIndexesMap = new Map();
244
+ rows.forEach((row, index) => {
245
+ pathsToIndexesMap.set(row.path.join(','), index);
246
+ });
247
+ const includedPaths = new Set();
248
+ filteredRows.forEach(row => {
249
+ includedPaths.add(row.path.join(','));
250
+ });
251
+ const missingChildren = [];
252
+
253
+ // include missing children of filtered rows
254
+ filteredRows.forEach(row => {
255
+ const path = row.path;
256
+ if (path) {
257
+ const children = findTreeDataRowChildren(rows, path, 'path', -1);
258
+ children.forEach(child => {
259
+ const subPath = child.path.join(',');
260
+ if (!includedPaths.has(subPath)) {
261
+ missingChildren.push(child);
262
+ }
263
+ });
264
+ }
265
+ });
266
+ filteredRows = missingChildren.concat(filteredRows);
267
+ const missingParents = [];
268
+
269
+ // include missing parents of filtered rows
270
+ filteredRows.forEach(row => {
271
+ const path = row.path;
272
+ if (path) {
273
+ includedPaths.add(path.join(','));
274
+ for (let i = 0; i < path.length - 1; i += 1) {
275
+ const subPath = path.slice(0, i + 1).join(',');
276
+ if (!includedPaths.has(subPath)) {
277
+ const index = pathsToIndexesMap.get(subPath);
278
+ if (index !== undefined) {
279
+ missingParents.push(rows[index]);
280
+ includedPaths.add(subPath);
281
+ }
282
+ }
283
+ }
284
+ }
285
+ });
286
+ return missingParents.concat(filteredRows);
287
+ };
288
+
289
+ /**
290
+ * Simulates server data loading
291
+ */
292
+ export const processTreeDataRows = (rows, queryOptions, serverOptions, columnsWithDefaultColDef) => {
293
+ const {
294
+ minDelay = 100,
295
+ maxDelay = 300
296
+ } = serverOptions;
297
+ const pathKey = 'path';
298
+ // TODO: Support filtering and cursor based pagination
299
+ if (maxDelay < minDelay) {
300
+ throw new Error('serverOptions.minDelay is larger than serverOptions.maxDelay ');
301
+ }
302
+ if (queryOptions.groupKeys == null) {
303
+ throw new Error('serverOptions.groupKeys must be defined to compute tree data ');
304
+ }
305
+ const delay = randomInt(minDelay, maxDelay);
306
+
307
+ // apply plain filtering
308
+ const filteredRows = getTreeDataFilteredRows(rows, queryOptions.filterModel, columnsWithDefaultColDef);
309
+
310
+ // get root row count
311
+ const rootRowCount = findTreeDataRowChildren(filteredRows, []).length;
312
+
313
+ // find direct children referring to the `parentPath`
314
+ const childRows = findTreeDataRowChildren(filteredRows, queryOptions.groupKeys);
315
+ let childRowsWithDescendantCounts = childRows.map(row => {
316
+ const descendants = findTreeDataRowChildren(filteredRows, row[pathKey], pathKey, -1);
317
+ const descendantCount = descendants.length;
318
+ return _extends({}, row, {
319
+ descendantCount
320
+ });
321
+ });
322
+ if (queryOptions.sortModel) {
323
+ // apply sorting
324
+ const rowComparator = getRowComparator(queryOptions.sortModel, columnsWithDefaultColDef);
325
+ childRowsWithDescendantCounts = [...childRowsWithDescendantCounts].sort(rowComparator);
326
+ }
327
+ if (queryOptions.paginationModel && queryOptions.groupKeys.length === 0) {
328
+ // Only paginate root rows, grid should refetch root rows when `paginationModel` updates
329
+ const {
330
+ pageSize,
331
+ page
332
+ } = queryOptions.paginationModel;
333
+ if (pageSize < childRowsWithDescendantCounts.length) {
334
+ childRowsWithDescendantCounts = childRowsWithDescendantCounts.slice(page * pageSize, (page + 1) * pageSize);
335
+ }
336
+ }
337
+ return new Promise(resolve => {
338
+ setTimeout(() => {
339
+ resolve({
340
+ rows: childRowsWithDescendantCounts,
341
+ rootRowCount
342
+ });
343
+ }, delay); // simulate network latency
344
+ });
345
+ };
@@ -12,7 +12,7 @@ const dataCache = new LRUCache({
12
12
  });
13
13
  // Generate fake data from a seed.
14
14
  // It's about x20 faster than getRealData.
15
- async function extrapolateSeed(rowLength, data) {
15
+ export async function extrapolateSeed(rowLength, data) {
16
16
  return new Promise(resolve => {
17
17
  const seed = data.rows;
18
18
  const rows = data.rows.slice();
@@ -42,7 +42,7 @@ async function extrapolateSeed(rowLength, data) {
42
42
  });
43
43
  });
44
44
  }
45
- const deepFreeze = object => {
45
+ export const deepFreeze = object => {
46
46
  // Retrieve the property names defined on object
47
47
  const propNames = Object.getOwnPropertyNames(object);
48
48
 
@@ -0,0 +1,197 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import * as React from 'react';
3
+ import LRUCache from 'lru-cache';
4
+ import { getGridDefaultColumnTypes } from '@mui/x-data-grid-pro';
5
+ import { getColumnsFromOptions, extrapolateSeed, deepFreeze } from './useDemoData';
6
+ import { getRealGridData } from '../services/real-data-service';
7
+ import { addTreeDataOptionsToDemoData } from '../services/tree-data-generator';
8
+ import { loadServerRows, processTreeDataRows, DEFAULT_DATASET_OPTIONS, DEFAULT_SERVER_OPTIONS } from './serverUtils';
9
+ import { randomInt } from '../services';
10
+ const dataCache = new LRUCache({
11
+ max: 10,
12
+ ttl: 60 * 5 * 1e3 // 5 minutes
13
+ });
14
+ export const BASE_URL = 'https://mui.com/x/api/data-grid';
15
+ function decodeParams(url) {
16
+ const params = new URL(url).searchParams;
17
+ const decodedParams = {};
18
+ const array = Array.from(params.entries());
19
+ for (const [key, value] of array) {
20
+ try {
21
+ decodedParams[key] = JSON.parse(decodeURIComponent(value));
22
+ } catch (e) {
23
+ decodedParams[key] = value;
24
+ }
25
+ }
26
+ return decodedParams;
27
+ }
28
+ const getInitialState = (columns, groupingField) => {
29
+ const columnVisibilityModel = {};
30
+ columns.forEach(col => {
31
+ if (col.hide) {
32
+ columnVisibilityModel[col.field] = false;
33
+ }
34
+ });
35
+ if (groupingField) {
36
+ columnVisibilityModel[groupingField] = false;
37
+ }
38
+ return {
39
+ columns: {
40
+ columnVisibilityModel
41
+ }
42
+ };
43
+ };
44
+ const defaultColDef = getGridDefaultColumnTypes();
45
+ export const useMockServer = (dataSetOptions, serverOptions, shouldRequestsFail) => {
46
+ const [data, setData] = React.useState();
47
+ const [index, setIndex] = React.useState(0);
48
+ const shouldRequestsFailRef = React.useRef(shouldRequestsFail ?? false);
49
+ React.useEffect(() => {
50
+ if (shouldRequestsFail !== undefined) {
51
+ shouldRequestsFailRef.current = shouldRequestsFail;
52
+ }
53
+ }, [shouldRequestsFail]);
54
+ const options = _extends({}, DEFAULT_DATASET_OPTIONS, dataSetOptions);
55
+ const columns = React.useMemo(() => {
56
+ return getColumnsFromOptions({
57
+ dataSet: options.dataSet,
58
+ editable: options.editable,
59
+ maxColumns: options.maxColumns,
60
+ visibleFields: options.visibleFields
61
+ });
62
+ }, [options.dataSet, options.editable, options.maxColumns, options.visibleFields]);
63
+ const initialState = React.useMemo(() => getInitialState(columns, options.treeData?.groupingField), [columns, options.treeData?.groupingField]);
64
+ const columnsWithDefaultColDef = React.useMemo(() => columns.map(column => _extends({}, defaultColDef[column.type || 'string'], column)), [columns]);
65
+ const isTreeData = options.treeData?.groupingField != null;
66
+ const getGroupKey = React.useMemo(() => {
67
+ if (isTreeData) {
68
+ return row => row[options.treeData.groupingField];
69
+ }
70
+ return undefined;
71
+ // eslint-disable-next-line react-hooks/exhaustive-deps
72
+ }, [options.treeData?.groupingField, isTreeData]);
73
+ const getChildrenCount = React.useMemo(() => {
74
+ if (isTreeData) {
75
+ return row => row.descendantCount;
76
+ }
77
+ return undefined;
78
+ }, [isTreeData]);
79
+ React.useEffect(() => {
80
+ const cacheKey = `${options.dataSet}-${options.rowLength}-${index}-${options.maxColumns}`;
81
+
82
+ // Cache to allow fast switch between the JavaScript and TypeScript version
83
+ // of the demos.
84
+ if (dataCache.has(cacheKey)) {
85
+ const newData = dataCache.get(cacheKey);
86
+ setData(newData);
87
+ return undefined;
88
+ }
89
+ let active = true;
90
+ (async () => {
91
+ let rowData;
92
+ const rowLength = options.rowLength;
93
+ if (rowLength > 1000) {
94
+ rowData = await getRealGridData(1000, columns);
95
+ rowData = await extrapolateSeed(rowLength, rowData);
96
+ } else {
97
+ rowData = await getRealGridData(rowLength, columns);
98
+ }
99
+ if (!active) {
100
+ return;
101
+ }
102
+ if (isTreeData) {
103
+ rowData = addTreeDataOptionsToDemoData(rowData, {
104
+ maxDepth: options.treeData?.maxDepth,
105
+ groupingField: options.treeData?.groupingField,
106
+ averageChildren: options.treeData?.averageChildren
107
+ });
108
+ }
109
+ if (process.env.NODE_ENV !== 'production') {
110
+ deepFreeze(rowData);
111
+ }
112
+ dataCache.set(cacheKey, rowData);
113
+ setData(rowData);
114
+ })();
115
+ return () => {
116
+ active = false;
117
+ };
118
+ }, [columns, isTreeData, options.rowLength, options.treeData?.maxDepth, options.treeData?.groupingField, options.treeData?.averageChildren, options.dataSet, options.maxColumns, index]);
119
+ const fetchRows = React.useCallback(async requestUrl => {
120
+ if (!data || !requestUrl) {
121
+ return new Promise(resolve => {
122
+ resolve({
123
+ rows: [],
124
+ rowCount: 0
125
+ });
126
+ });
127
+ }
128
+ const params = decodeParams(requestUrl);
129
+ const verbose = serverOptions?.verbose ?? true;
130
+ // eslint-disable-next-line no-console
131
+ const print = console.info;
132
+ if (verbose) {
133
+ print('MUI X: DATASOURCE REQUEST', params);
134
+ }
135
+ let getRowsResponse;
136
+ const serverOptionsWithDefault = {
137
+ minDelay: serverOptions?.minDelay ?? DEFAULT_SERVER_OPTIONS.minDelay,
138
+ maxDelay: serverOptions?.maxDelay ?? DEFAULT_SERVER_OPTIONS.maxDelay,
139
+ useCursorPagination: serverOptions?.useCursorPagination ?? DEFAULT_SERVER_OPTIONS.useCursorPagination
140
+ };
141
+ if (shouldRequestsFailRef.current) {
142
+ const {
143
+ minDelay,
144
+ maxDelay
145
+ } = serverOptionsWithDefault;
146
+ const delay = randomInt(minDelay, maxDelay);
147
+ return new Promise((_, reject) => {
148
+ if (verbose) {
149
+ print('MUI X: DATASOURCE REQUEST FAILURE', params);
150
+ }
151
+ setTimeout(() => reject(new Error('Could not fetch the data')), delay);
152
+ });
153
+ }
154
+ if (isTreeData /* || TODO: `isRowGrouping` */) {
155
+ const {
156
+ rows,
157
+ rootRowCount
158
+ } = await processTreeDataRows(data.rows, params, serverOptionsWithDefault, columnsWithDefaultColDef);
159
+ getRowsResponse = {
160
+ rows: rows.slice().map(row => _extends({}, row, {
161
+ path: undefined
162
+ })),
163
+ rowCount: rootRowCount
164
+ };
165
+ } else {
166
+ // plain data
167
+ const {
168
+ returnedRows,
169
+ nextCursor,
170
+ totalRowCount
171
+ } = await loadServerRows(data.rows, _extends({}, params, params.paginationModel), serverOptionsWithDefault, columnsWithDefaultColDef);
172
+ getRowsResponse = {
173
+ rows: returnedRows,
174
+ rowCount: totalRowCount,
175
+ pageInfo: {
176
+ nextCursor
177
+ }
178
+ };
179
+ }
180
+ return new Promise(resolve => {
181
+ if (verbose) {
182
+ print('MUI X: DATASOURCE RESPONSE', params, getRowsResponse);
183
+ }
184
+ resolve(getRowsResponse);
185
+ });
186
+ }, [data, serverOptions?.verbose, serverOptions?.minDelay, serverOptions?.maxDelay, serverOptions?.useCursorPagination, isTreeData, columnsWithDefaultColDef]);
187
+ return {
188
+ columns: columnsWithDefaultColDef,
189
+ initialState,
190
+ getGroupKey,
191
+ getChildrenCount,
192
+ fetchRows,
193
+ loadNewData: () => {
194
+ setIndex(oldIndex => oldIndex + 1);
195
+ }
196
+ };
197
+ };
@@ -1,145 +1,9 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
- import { getGridDefaultColumnTypes, GridLogicOperator } from '@mui/x-data-grid-pro';
3
+ import { getGridDefaultColumnTypes } from '@mui/x-data-grid-pro';
4
4
  import { isDeepEqual } from '@mui/x-data-grid/internals';
5
5
  import { useDemoData, getColumnsFromOptions, getInitialState } from './useDemoData';
6
- import { randomInt } from '../services/random-generator';
7
- const apiRef = {};
8
- const simplifiedValueGetter = (field, colDef) => row => {
9
- return colDef.valueGetter?.(row[row.id], row, colDef, apiRef) || row[field];
10
- };
11
- const getRowComparator = (sortModel, columnsWithDefaultColDef) => {
12
- if (!sortModel) {
13
- const comparator = () => 0;
14
- return comparator;
15
- }
16
- const sortOperators = sortModel.map(sortItem => {
17
- const columnField = sortItem.field;
18
- const colDef = columnsWithDefaultColDef.find(({
19
- field
20
- }) => field === columnField);
21
- return _extends({}, sortItem, {
22
- valueGetter: simplifiedValueGetter(columnField, colDef),
23
- sortComparator: colDef.sortComparator
24
- });
25
- });
26
- const comparator = (row1, row2) => sortOperators.reduce((acc, {
27
- valueGetter,
28
- sort,
29
- sortComparator
30
- }) => {
31
- if (acc !== 0) {
32
- return acc;
33
- }
34
- const v1 = valueGetter(row1);
35
- const v2 = valueGetter(row2);
36
- return sort === 'desc' ? -1 * sortComparator(v1, v2) : sortComparator(v1, v2);
37
- }, 0);
38
- return comparator;
39
- };
40
- const getFilteredRows = (rows, filterModel, columnsWithDefaultColDef) => {
41
- if (filterModel === undefined || filterModel.items.length === 0) {
42
- return rows;
43
- }
44
- const valueGetters = filterModel.items.map(({
45
- field
46
- }) => simplifiedValueGetter(field, columnsWithDefaultColDef.find(column => column.field === field)));
47
- const filterFunctions = filterModel.items.map(filterItem => {
48
- const {
49
- field,
50
- operator
51
- } = filterItem;
52
- const colDef = columnsWithDefaultColDef.find(column => column.field === field);
53
- const filterOperator = colDef.filterOperators.find(({
54
- value
55
- }) => operator === value);
56
- let parsedValue = filterItem.value;
57
- if (colDef.valueParser) {
58
- const parser = colDef.valueParser;
59
- parsedValue = Array.isArray(filterItem.value) ? filterItem.value?.map(x => parser(x)) : parser(filterItem.value);
60
- }
61
- return filterOperator?.getApplyFilterFn({
62
- filterItem,
63
- value: parsedValue
64
- }, colDef);
65
- });
66
- if (filterModel.logicOperator === GridLogicOperator.Or) {
67
- return rows.filter(row => filterModel.items.some((_, index) => {
68
- const value = valueGetters[index](row);
69
- return filterFunctions[index] === null ? true : filterFunctions[index]({
70
- value
71
- });
72
- }));
73
- }
74
- return rows.filter(row => filterModel.items.every((_, index) => {
75
- const value = valueGetters[index](row);
76
- return filterFunctions[index] === null ? true : filterFunctions[index](value);
77
- }));
78
- };
79
-
80
- /**
81
- * Simulates server data loading
82
- */
83
- export const loadServerRows = (rows, queryOptions, serverOptions, columnsWithDefaultColDef) => {
84
- const {
85
- minDelay = 100,
86
- maxDelay = 300,
87
- useCursorPagination
88
- } = serverOptions;
89
- if (maxDelay < minDelay) {
90
- throw new Error('serverOptions.minDelay is larger than serverOptions.maxDelay ');
91
- }
92
- const delay = randomInt(minDelay, maxDelay);
93
- const {
94
- cursor,
95
- page = 0,
96
- pageSize
97
- } = queryOptions;
98
- let nextCursor;
99
- let firstRowIndex;
100
- let lastRowIndex;
101
- let filteredRows = getFilteredRows(rows, queryOptions.filterModel, columnsWithDefaultColDef);
102
- const rowComparator = getRowComparator(queryOptions.sortModel, columnsWithDefaultColDef);
103
- filteredRows = [...filteredRows].sort(rowComparator);
104
- const totalRowCount = filteredRows.length;
105
- if (!pageSize) {
106
- firstRowIndex = 0;
107
- lastRowIndex = filteredRows.length;
108
- } else if (useCursorPagination) {
109
- firstRowIndex = cursor ? filteredRows.findIndex(({
110
- id
111
- }) => id === cursor) : 0;
112
- firstRowIndex = Math.max(firstRowIndex, 0); // if cursor not found return 0
113
- lastRowIndex = firstRowIndex + pageSize;
114
- nextCursor = lastRowIndex >= filteredRows.length ? undefined : filteredRows[lastRowIndex].id;
115
- } else {
116
- firstRowIndex = page * pageSize;
117
- lastRowIndex = (page + 1) * pageSize;
118
- }
119
- const hasNextPage = lastRowIndex < filteredRows.length - 1;
120
- const response = {
121
- returnedRows: filteredRows.slice(firstRowIndex, lastRowIndex),
122
- nextCursor,
123
- hasNextPage,
124
- totalRowCount
125
- };
126
- return new Promise(resolve => {
127
- setTimeout(() => {
128
- resolve(response);
129
- }, delay); // simulate network latency
130
- });
131
- };
132
- const DEFAULT_DATASET_OPTIONS = {
133
- dataSet: 'Commodity',
134
- rowLength: 100,
135
- maxColumns: 6
136
- };
137
- const disableDelay = typeof DISABLE_CHANCE_RANDOM !== 'undefined' && DISABLE_CHANCE_RANDOM;
138
- const DEFAULT_SERVER_OPTIONS = {
139
- minDelay: disableDelay ? 0 : 100,
140
- maxDelay: disableDelay ? 0 : 300,
141
- useCursorPagination: true
142
- };
6
+ import { DEFAULT_DATASET_OPTIONS, DEFAULT_SERVER_OPTIONS, loadServerRows } from './serverUtils';
143
7
  export const createFakeServer = (dataSetOptions, serverOptions) => {
144
8
  const dataSetOptionsWithDefault = _extends({}, DEFAULT_DATASET_OPTIONS, dataSetOptions);
145
9
  const serverOptionsWithDefault = _extends({}, DEFAULT_SERVER_OPTIONS, serverOptions);