Skip to content

Commit

Permalink
[test] Add tests for DataGrid filtering feature (#715)
Browse files Browse the repository at this point in the history
  • Loading branch information
dtassone authored Dec 16, 2020
1 parent 3a02879 commit 6e87cb3
Show file tree
Hide file tree
Showing 18 changed files with 858 additions and 121 deletions.
4 changes: 1 addition & 3 deletions packages/grid/_modules_/grid/GridComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,7 @@ export const GridComponent = React.forwardRef<HTMLDivElement, GridComponentProps
minWidth: gridState.containerSizes?.dataContainerSizes?.width,
}}
>
{gridState.rendering.renderContext != null && (
<Viewport ref={renderingZoneRef} />
)}
<Viewport ref={renderingZoneRef} />
</GridDataContainer>
</GridWindow>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export function GridColumnHeaderMenu() {
};
}, []);

if (!target) {
if (!target || !currentColumn) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ export const useStyles = makeStyles(
alignSelf: 'center',
alignItems: 'center',
justifyContent: 'center',
zIndex: 10,
backgroundColor: fade(
theme.palette.background.default,
theme.palette.action.disabledOpacity,
Expand Down
3 changes: 2 additions & 1 deletion packages/grid/_modules_/grid/constants/eventsConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ export const COL_REORDER_DRAG_ENTER = 'colReordering:dragEnter';
export const COL_REORDER_STOP = 'colReordering:dragStop';

export const ROWS_UPDATED = 'rowsUpdated';
export const RESET_ROWS = 'resetRows';
export const ROWS_SET = 'rowsSet';
export const ROWS_CLEARED = 'rowsCleared';
export const COLUMNS_UPDATED = 'columnsUpdated';

export const SORT_MODEL_CHANGE = 'sortModelChange';
Expand Down
60 changes: 27 additions & 33 deletions packages/grid/_modules_/grid/hooks/features/filter/useFilter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { FILTER_MODEL_CHANGE, RESET_ROWS, ROWS_UPDATED } from '../../../constants/eventsConstants';
import { FILTER_MODEL_CHANGE, ROWS_SET, ROWS_UPDATED } from '../../../constants/eventsConstants';
import { ApiRef } from '../../../models/api/apiRef';
import { FilterApi } from '../../../models/api/filterApi';
import { FeatureModeConstant } from '../../../models/featureMode';
Expand All @@ -17,7 +17,7 @@ import { useGridSelector } from '../core/useGridSelector';
import { useGridState } from '../core/useGridState';
import { PreferencePanelsValue } from '../preferencesPanel/preferencesPanelValue';
import { sortedRowsSelector } from '../sorting/sortingSelector';
import { FilterModel, FilterModelState } from './FilterModelState';
import { FilterModel, FilterModelState, getInitialFilterState } from './FilterModelState';
import { getInitialVisibleRowsState } from './visibleRowsState';

export const useFilter = (apiRef: ApiRef, rowsProp: RowsProp): void => {
Expand Down Expand Up @@ -69,9 +69,12 @@ export const useFilter = (apiRef: ApiRef, rowsProp: RowsProp): void => {

setGridState((state) => {
const visibleRowsLookup = { ...state.visibleRows.visibleRowsLookup };
const visibleRows: RowId[] = [];
const visibleRows: RowId[] = !state.visibleRows.visibleRows
? []
: [...state.visibleRows.visibleRows];
// We run the selector on the state here to avoid rendering the rows and then filtering again.
// This way we have latest rows on the first rendering

const rows = sortedRowsSelector(state);

rows.forEach((row, rowIndex) => {
Expand All @@ -96,6 +99,7 @@ export const useFilter = (apiRef: ApiRef, rowsProp: RowsProp): void => {
visibleRows.push(row.id);
}
});

return {
...state,
visibleRows: { visibleRowsLookup, visibleRows },
Expand All @@ -106,25 +110,19 @@ export const useFilter = (apiRef: ApiRef, rowsProp: RowsProp): void => {
[apiRef, forceUpdate, logger, setGridState],
);

const applyFilters = React.useCallback(
(noRerender = false) => {
if (options.filterMode === FeatureModeConstant.server) {
return;
}
const applyFilters = React.useCallback(() => {
if (options.filterMode === FeatureModeConstant.server) {
return;
}

clearFilteredRows();
clearFilteredRows();

const { items, linkOperator } = apiRef.current.state.filter;
items.forEach((filterItem) => {
applyFilter(filterItem, linkOperator);
});

if (!noRerender) {
forceUpdate();
}
},
[apiRef, applyFilter, clearFilteredRows, forceUpdate, options.filterMode],
);
const { items, linkOperator } = apiRef.current.state.filter;
items.forEach((filterItem) => {
apiRef.current.applyFilter(filterItem, linkOperator);
});
forceUpdate();
}, [apiRef, clearFilteredRows, forceUpdate, options.filterMode]);

const upsertFilter = React.useCallback(
(item: FilterItem) => {
Expand Down Expand Up @@ -229,14 +227,20 @@ export const useFilter = (apiRef: ApiRef, rowsProp: RowsProp): void => {
[applyFilters, setGridState],
);

const clearFilterModel = React.useCallback(() => {
clearFilteredRows();
setGridState((state) => ({ ...state, filter: getInitialFilterState() }));
}, [clearFilteredRows, setGridState]);

const setFilterModel = React.useCallback(
(model: FilterModel) => {
clearFilterModel();
applyFilterLinkOperator(model.linkOperator);
model.items.forEach((item) => upsertFilter(item));

apiRef.current.publishEvent(FILTER_MODEL_CHANGE, getFilterModelParams());
},
[apiRef, applyFilterLinkOperator, getFilterModelParams, upsertFilter],
[apiRef, applyFilterLinkOperator, clearFilterModel, getFilterModelParams, upsertFilter],
);

const onFilterModelChange = React.useCallback(
Expand All @@ -262,18 +266,8 @@ export const useFilter = (apiRef: ApiRef, rowsProp: RowsProp): void => {
'FilterApi',
);

const onRowsUpdated = React.useCallback(() => {
if (gridState.filter.items.length > 0) {
apiRef.current.applyFilters();
}
}, [gridState.filter.items.length, apiRef]);

const onResetRows = React.useCallback(() => {
apiRef.current.applyFilters(true);
}, [apiRef]);

useApiEventHandler(apiRef, RESET_ROWS, onResetRows);
useApiEventHandler(apiRef, ROWS_UPDATED, onRowsUpdated);
useApiEventHandler(apiRef, ROWS_SET, apiRef.current.applyFilters);
useApiEventHandler(apiRef, ROWS_UPDATED, apiRef.current.applyFilters);
useApiEventHandler(apiRef, FILTER_MODEL_CHANGE, options.onFilterModelChange);

React.useEffect(() => {
Expand Down
21 changes: 12 additions & 9 deletions packages/grid/_modules_/grid/hooks/features/rows/useRows.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { RESET_ROWS, ROWS_UPDATED } from '../../../constants/eventsConstants';
import { ROWS_CLEARED, ROWS_SET, ROWS_UPDATED } from '../../../constants/eventsConstants';
import { ApiRef } from '../../../models/api/apiRef';
import { RowApi } from '../../../models/api/rowApi';
import { checkRowHasId, RowModel, RowId, RowsProp } from '../../../models/rows';
Expand Down Expand Up @@ -34,15 +34,15 @@ export const useRows = (rows: RowsProp, apiRef: ApiRef): void => {
const updateTimeout = React.useRef<any>();

const forceUpdate = React.useCallback(
(callback?: Function) => {
(preUpdateCallback?: Function) => {
if (updateTimeout.current == null) {
updateTimeout.current = setTimeout(() => {
logger.debug(`Updating component`);
updateTimeout.current = null;
updateComponent();
if (callback) {
callback();
if (preUpdateCallback) {
preUpdateCallback();
}
updateComponent();
}, 100);
}
},
Expand Down Expand Up @@ -82,6 +82,10 @@ export const useRows = (rows: RowsProp, apiRef: ApiRef): void => {
(allNewRows: RowModel[]) => {
logger.debug(`updating all rows, new length ${allNewRows.length}`);

if (internalRowsState.current.allRows.length > 0) {
apiRef.current.publishEvent(ROWS_CLEARED);
}

const idRowsLookup = allNewRows.reduce((lookup, row) => {
lookup[row.id] = row;
return lookup;
Expand All @@ -98,8 +102,7 @@ export const useRows = (rows: RowsProp, apiRef: ApiRef): void => {

setGridState((state) => ({ ...state, rows: internalRowsState.current }));

apiRef.current.publishEvent(RESET_ROWS);
forceUpdate();
forceUpdate(() => apiRef.current.publishEvent(ROWS_SET));
},
[logger, gridState.options, apiRef, setGridState, forceUpdate],
);
Expand Down Expand Up @@ -135,9 +138,9 @@ export const useRows = (rows: RowsProp, apiRef: ApiRef): void => {
...addedRows,
];
setRows(newRows);
} else {
forceUpdate(() => apiRef.current.publishEvent(ROWS_UPDATED));
}

forceUpdate(() => apiRef.current.publishEvent(ROWS_UPDATED));
},
[apiRef, forceUpdate, getRowFromId, setGridState, setRows],
);
Expand Down
113 changes: 65 additions & 48 deletions packages/grid/_modules_/grid/hooks/features/sorting/useSorting.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import * as React from 'react';
import {
COLUMN_HEADER_CLICK,
COLUMNS_UPDATED,
MULTIPLE_KEY_PRESS_CHANGED,
RESET_ROWS,
ROWS_CLEARED,
ROWS_SET,
ROWS_UPDATED,
SORT_MODEL_CHANGE,
} from '../../../constants/eventsConstants';
Expand All @@ -23,7 +25,7 @@ import { useApiEventHandler } from '../../root/useApiEventHandler';
import { useApiMethod } from '../../root/useApiMethod';
import { useLogger } from '../../utils/useLogger';
import { optionsSelector } from '../../utils/useOptionsProp';
import { visibleColumnsSelector } from '../columns/columnsSelector';
import { allColumnsSelector, visibleColumnsSelector } from '../columns/columnsSelector';
import { GridState } from '../core/gridState';
import { useGridSelector } from '../core/useGridSelector';
import { useGridState } from '../core/useGridState';
Expand Down Expand Up @@ -137,49 +139,44 @@ export const useSorting = (apiRef: ApiRef, rowsProp: RowsProp) => {
[apiRef],
);

const applySorting = React.useCallback(
(noRerender = false) => {
const rowModels = apiRef.current.getRowModels();

if (options.sortingMode === FeatureModeConstant.server) {
logger.info('Skipping sorting rows as sortingMode = server');
setGridState((oldState) => {
return {
...oldState,
sorting: { ...oldState.sorting, sortedRows: rowModels.map((row) => row.id) },
};
});
return;
}

const sortModel = apiRef.current.getState<GridState>().sorting.sortModel;
logger.info('Sorting rows with ', sortModel);
const sorted = [...rowModels];
if (sortModel.length > 0) {
comparatorList.current = buildComparatorList(sortModel);
sorted.sort(comparatorListAggregate);
}
const applySorting = React.useCallback(() => {
const rowModels = apiRef.current.getRowModels();

if (options.sortingMode === FeatureModeConstant.server) {
logger.info('Skipping sorting rows as sortingMode = server');
setGridState((oldState) => {
return {
...oldState,
sorting: { ...oldState.sorting, sortedRows: sorted.map((row) => row.id) },
sorting: { ...oldState.sorting, sortedRows: rowModels.map((row) => row.id) },
};
});
if (!noRerender) {
forceUpdate();
}
},
[
apiRef,
logger,
setGridState,
forceUpdate,
buildComparatorList,
comparatorListAggregate,
options.sortingMode,
],
);
return;
}

const sortModel = apiRef.current.getState<GridState>().sorting.sortModel;
logger.info('Sorting rows with ', sortModel);
const sorted = [...rowModels];
if (sortModel.length > 0) {
comparatorList.current = buildComparatorList(sortModel);
sorted.sort(comparatorListAggregate);
}

setGridState((oldState) => {
return {
...oldState,
sorting: { ...oldState.sorting, sortedRows: sorted.map((row) => row.id) },
};
});
forceUpdate();
}, [
apiRef,
logger,
setGridState,
forceUpdate,
buildComparatorList,
comparatorListAggregate,
options.sortingMode,
]);

const setSortModel = React.useCallback(
(sortModel: SortModel) => {
Expand Down Expand Up @@ -222,13 +219,11 @@ export const useSorting = (apiRef: ApiRef, rowsProp: RowsProp) => {
[sortColumn],
);

const onRowsUpdated = React.useCallback(() => {
apiRef.current.applySorting();
}, [apiRef]);

const onResetRows = React.useCallback(() => {
apiRef.current.applySorting(true);
}, [apiRef]);
const onRowsCleared = React.useCallback(() => {
setGridState((state) => {
return { ...state, sorting: { ...state.sorting, sortedRows: [] } };
});
}, [setGridState]);

const getSortModel = React.useCallback(() => gridState.sorting.sortModel, [
gridState.sorting.sortModel,
Expand All @@ -248,9 +243,31 @@ export const useSorting = (apiRef: ApiRef, rowsProp: RowsProp) => {
[apiRef],
);

const onColUpdated = React.useCallback(() => {
// When the columns change we check that the sorted columns are still part of the dataset
setGridState((state) => {
const sortModel = state.sorting.sortModel;
const latestColumns = allColumnsSelector(state);
let newModel = sortModel;
if (sortModel.length > 0) {
newModel = sortModel.reduce((model, sortedCol) => {
const exist = latestColumns.find((col) => col.field === sortedCol.field);
if (exist) {
model.push(sortedCol);
}
return model;
}, [] as SortModel);
}

return { ...state, sorting: { ...state.sorting, sortModel: newModel } };
});
}, [setGridState]);

useApiEventHandler(apiRef, COLUMN_HEADER_CLICK, headerClickHandler);
useApiEventHandler(apiRef, RESET_ROWS, onResetRows);
useApiEventHandler(apiRef, ROWS_UPDATED, onRowsUpdated);
useApiEventHandler(apiRef, ROWS_SET, apiRef.current.applySorting);
useApiEventHandler(apiRef, ROWS_CLEARED, onRowsCleared);
useApiEventHandler(apiRef, ROWS_UPDATED, apiRef.current.applySorting);
useApiEventHandler(apiRef, COLUMNS_UPDATED, onColUpdated);
useApiEventHandler(apiRef, MULTIPLE_KEY_PRESS_CHANGED, onMultipleKeyPressed);

useApiEventHandler(apiRef, SORT_MODEL_CHANGE, options.onSortModelChange);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,21 @@ export const useVirtualColumns = (
);
logger.debug(`Difference with first: ${diffFirst} and last: ${diffLast} `);

const renderNewColState = diffLast > tolerance || diffFirst > tolerance;
const renderNewColState =
lastDisplayedIdx > 0 && (diffLast > tolerance || diffFirst > tolerance);

let newRenderedColState: RenderColumnsProps | null = renderedColRef.current;
let newRenderedColState: RenderColumnsProps | null =
renderedColRef.current != null ? { ...renderedColRef.current } : null;

const lastVisibleIndex = visibleColumns.length > 0 ? visibleColumns.length - 1 : 0;
if (renderNewColState || newRenderedColState == null) {
newRenderedColState = {
leftEmptyWidth: 0,
rightEmptyWidth: 0,
firstColIdx: firstDisplayedIdx - columnBuffer >= 0 ? firstDisplayedIdx - columnBuffer : 0,
lastColIdx:
lastDisplayedIdx + columnBuffer >= visibleColumns.length - 1
? visibleColumns.length - 1
lastDisplayedIdx + columnBuffer >= lastVisibleIndex
? lastVisibleIndex
: lastDisplayedIdx + columnBuffer,
};
}
Expand Down
Loading

0 comments on commit 6e87cb3

Please sign in to comment.