Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions packages/ra-core/src/controller/ListController.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ describe('ListController', () => {
toggleItem: jest.fn(),
total: 100,
translate: jest.fn(),
perPage: 25,
sort: {
field: 'id',
order: 'ASC',
},
};

describe('setFilters', () => {
Expand Down Expand Up @@ -113,6 +118,34 @@ describe('ListController', () => {
expect(props.changeListParams.mock.calls[0][1].filter).toEqual({});
});

it('should update data if permanent filters change', () => {
const children = jest.fn();
const props = {
...defaultProps,
debounce: 200,
crudGetList: jest.fn(),
filter: { foo: 1 },
children,
};

const wrapper = shallow(<ListController {...props} />);

// Check that the permanent filter was used in the query
expect(props.crudGetList.mock.calls[0][3]).toEqual({ foo: 1 });
// Check that the permanent filter is not included in the displayedFilters (passed to Filter form and button)
expect(children.mock.calls[0][0].displayedFilters).toEqual({});
// Check that the permanent filter is not included in the filterValues (passed to Filter form and button)
expect(children.mock.calls[0][0].filterValues).toEqual({});

wrapper.setProps({ filter: { foo: 2 } });
// Check that the permanent filter was used in the query
expect(props.crudGetList.mock.calls[1][3]).toEqual({ foo: 2 });
// Check that the permanent filter is not included in the displayedFilters (passed to Filter form and button)
expect(children.mock.calls[0][0].displayedFilters).toEqual({});
// Check that the permanent filter is not included in the filterValues (passed to Filter form and button)
expect(children.mock.calls[0][0].filterValues).toEqual({});
});

Comment thread
Kmaschta marked this conversation as resolved.
afterEach(() => {
clock.uninstall();
});
Expand Down
109 changes: 48 additions & 61 deletions packages/ra-core/src/controller/ListController.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint no-console: ["error", { allow: ["warn", "error"] }] */
import {
Component,
isValidElement,
Expand Down Expand Up @@ -207,24 +206,14 @@ export class UnconnectedListController extends Component<

componentWillReceiveProps(nextProps: Props & EnhancedProps) {
if (
nextProps.version !== this.props.version ||
nextProps.resource !== this.props.resource ||
nextProps.query.sort !== this.props.query.sort ||
nextProps.query.order !== this.props.query.order ||
nextProps.query.page !== this.props.query.page ||
nextProps.query.perPage !== this.props.query.perPage ||
!isEqual(nextProps.query.filter, this.props.query.filter) ||
!isEqual(nextProps.query, this.props.query) ||
!isEqual(nextProps.filter, this.props.filter) ||
!isEqual(nextProps.sort, this.props.sort) ||
!isEqual(nextProps.perPage, this.props.perPage)
) {
this.updateData(
Object.keys(nextProps.query).length > 0
Comment thread
fzaninotto marked this conversation as resolved.
? nextProps.query
: nextProps.params
);
}
if (nextProps.version !== this.props.version) {
this.updateData();
this.updateData(nextProps);
}
}

Expand All @@ -244,56 +233,33 @@ export class UnconnectedListController extends Component<
return true;
}

/**
* Check if user has already set custom sort, page, or filters for this list
*
* User params come from the Redux store as the params props. By default,
* this object is:
*
* { filter: {}, order: null, page: 1, perPage: null, sort: null }
*
* To check if the user has custom params, we must compare the params
* to these initial values.
*
* @param {object} params
*/
hasCustomParams(params: ListParams) {
return (
params &&
params.filter &&
(Object.keys(params.filter).length > 0 ||
params.order != null ||
params.page !== 1 ||
params.perPage != null ||
params.sort != null)
);
}

/**
* Merge list params from 4 different sources:
* - the query string
* - the params stored in the state (from previous navigation)
* - the filter defaultValues
* - the props passed to the List component
*/
getQuery() {
getQuery(props = this.props) {
const query: Partial<ListParams> =
Object.keys(this.props.query).length > 0
? this.props.query
: this.hasCustomParams(this.props.params)
? { ...this.props.params }
: { filter: this.props.filterDefaultValues || {} };
Object.keys(props.query).length > 0
? props.query
: hasCustomParams(props.params)
? { ...props.params }
: { filter: props.filterDefaultValues || {} };

if (!query.sort) {
query.sort = this.props.sort.field;
query.order = this.props.sort.order;
}
if (!query.perPage) {
query.perPage = this.props.perPage;
}
if (!query.page) {
query.page = 1;
query.sort = props.sort.field;
query.order = props.sort.order;
}

query.perPage = parseInt(
// @ts-ignore
query.perPage ? query.perPage : props.perPage,
10
);
// @ts-ignore
query.page = query.page ? parseInt(query.page, 10) : 1;

return query as ListParams;
}

Expand All @@ -302,19 +268,19 @@ export class UnconnectedListController extends Component<
return query.filter || {};
}

updateData(query?: any) {
const params = query || this.getQuery();
const { sort, order, page = 1, perPage, filter } = params;
updateData(props = this.props) {
const query = this.getQuery(props);

const { sort, order, page = 1, perPage, filter } = query;
const pagination = {
page: parseInt(page, 10),
Comment thread
Kmaschta marked this conversation as resolved.
perPage: parseInt(perPage, 10),
page,
perPage,
};
const permanentFilter = this.props.filter;
this.props.crudGetList(
this.props.resource,
pagination,
{ field: sort, order },
{ ...filter, ...permanentFilter }
{ ...filter, ...props.filter }
);
}

Expand Down Expand Up @@ -429,6 +395,27 @@ export class UnconnectedListController extends Component<
}
}

/**
* Check if user has already set custom sort, page, or filters for this list
*
* User params come from the Redux store as the params props. By default,
* this object is:
*
* { filter: {}, order: null, page: 1, perPage: null, sort: null }
*
* To check if the user has custom params, we must compare the params
* to these initial values.
*
* @param {object} params
*/
const hasCustomParams = (params: ListParams) =>
params &&
((params.filter && Object.keys(params.filter).length > 0) ||
params.order != null ||
params.page !== 1 ||
params.perPage != null ||
params.sort != null);

const injectedProps = [
'basePath',
'currentSort',
Expand Down