Skip to content

Commit

Permalink
Merge pull request #2831 from marmelab/fix-default-value-filter
Browse files Browse the repository at this point in the history
[RFR] Fix default filter values cannot be removed by user
  • Loading branch information
Gildas Garcia authored Jan 30, 2019
2 parents 5a18708 + 3ada067 commit a466471
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 29 deletions.
35 changes: 29 additions & 6 deletions cypress/integration/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ describe('List Page', () => {
cy.viewport(1280, 500);

cy.scrollTo(0, 200);
cy.get(ListPagePosts.elements.headroomUnpinned).should('not.be.visible');
cy.get(ListPagePosts.elements.headroomUnpinned).should(
'not.be.visible'
);

cy.scrollTo(0, -100);
cy.get(ListPagePosts.elements.headroomUnfixed).should('be.visible');
Expand Down Expand Up @@ -109,6 +111,15 @@ describe('List Page', () => {
cy.contains('1-1 of 1');
ListPagePosts.setFilterValue('q', '');
});

it('should allow to disable alwaysOn filters with default value', () => {
LoginPage.navigate();
LoginPage.login('admin', 'password');
ListPageUsers.navigate();
cy.contains('1-2 of 2');
cy.get('button[tooltip="Remove this filter"]').click();
cy.contains('1-3 of 3');
});
});

describe('Bulk Actions', () => {
Expand Down Expand Up @@ -223,13 +234,15 @@ describe('List Page', () => {
});
});

describe("Sorting", () => {
describe('Sorting', () => {
it('should display a sort arrow when clicking on a sortable column header', () => {
ListPagePosts.toggleColumnSort('id');
cy.get(ListPagePosts.elements.svg('id')).should('be.visible');

ListPagePosts.toggleColumnSort('tags.name');
cy.get(ListPagePosts.elements.svg('tags.name')).should('be.visible');
cy.get(ListPagePosts.elements.svg('tags.name')).should(
'be.visible'
);
});

it('should hide the sort arrow when clicking on another sortable column header', () => {
Expand All @@ -241,10 +254,20 @@ describe('List Page', () => {
it('should reverse the sort arrow when clicking on an already sorted column header', () => {
ListPagePosts.toggleColumnSort('published_at');
ListPagePosts.toggleColumnSort('tags.name');
cy.get(ListPagePosts.elements.svg('tags.name', '[class*=iconDirectionAsc]')).should('exist');
cy.get(
ListPagePosts.elements.svg(
'tags.name',
'[class*=iconDirectionAsc]'
)
).should('exist');

ListPagePosts.toggleColumnSort('tags.name');
cy.get(ListPagePosts.elements.svg('tags.name', '[class*=iconDirectionDesc]')).should('exist');
cy.get(
ListPagePosts.elements.svg(
'tags.name',
'[class*=iconDirectionDesc]'
)
).should('exist');
});
})
});
});
59 changes: 38 additions & 21 deletions packages/ra-core/src/controller/ListController.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,31 @@ export class ListController 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) {
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
Expand All @@ -148,10 +173,9 @@ export class ListController extends Component {
const query =
Object.keys(this.props.query).length > 0
? this.props.query
: { ...this.props.params };
const filterDefaultValues = this.props.filterDefaultValues || {};

query.filter = { ...filterDefaultValues, ...query.filter };
: this.hasCustomParams(this.props.params)
? { ...this.props.params }
: { filter: this.props.filterDefaultValues || {} };

if (!query.sort) {
query.sort = this.props.sort.field;
Expand All @@ -166,6 +190,11 @@ export class ListController extends Component {
return query;
}

getFilterValues() {
const query = this.getQuery();
return query.filter || {};
}

updateData(query) {
const params = query || this.getQuery();
const { sort, order, page = 1, perPage, filter } = params;
Expand All @@ -190,7 +219,7 @@ export class ListController extends Component {
this.changeParams({ type: SET_PER_PAGE, payload: perPage });

setFilters = debounce(filters => {
if (isEqual(filters, this.props.filterValues)) {
if (isEqual(filters, this.getFilterValues())) {
return;
}

Expand All @@ -203,15 +232,15 @@ export class ListController extends Component {
this.setState({ [filterName]: true });
if (typeof defaultValue !== 'undefined') {
this.setFilters({
...this.props.filterValues,
...this.getFilterValues(),
[filterName]: defaultValue,
});
}
};

hideFilter = filterName => {
this.setState({ [filterName]: false });
const newFilters = removeKey(this.props.filterValues, filterName);
const newFilters = removeKey(this.getFilterValues(), filterName);
this.setFilters(newFilters);
};

Expand Down Expand Up @@ -255,9 +284,6 @@ export class ListController extends Component {
selectedIds,
} = this.props;
const query = this.getQuery();

const queryFilterValues = query.filter || {};

const resourceName = translate(`resources.${resource}.name`, {
smart_count: 2,
_: inflection.humanize(inflection.pluralize(resource)),
Expand All @@ -275,7 +301,7 @@ export class ListController extends Component {
data,
defaultTitle,
displayedFilters: this.state,
filterValues: queryFilterValues,
filterValues: this.getFilterValues(),
hasCreate,
hideFilter: this.hideFilter,
ids,
Expand Down Expand Up @@ -320,7 +346,6 @@ ListController.propTypes = {
crudGetList: PropTypes.func.isRequired,
data: PropTypes.object, // eslint-disable-line react/forbid-prop-types
debounce: PropTypes.number,
filterValues: PropTypes.object, // eslint-disable-line react/forbid-prop-types
hasCreate: PropTypes.bool,
hasEdit: PropTypes.bool,
hasList: PropTypes.bool,
Expand All @@ -345,7 +370,6 @@ ListController.propTypes = {
ListController.defaultProps = {
debounce: 500,
filter: {},
filterValues: {},
perPage: 10,
sort: {
field: 'id',
Expand Down Expand Up @@ -435,19 +459,12 @@ function mapStateToProps(state, props) {
total: resourceState.list.total,
data: resourceState.data,
isLoading: state.admin.loading > 0,
filterValues: resourceState.list.params.filter,
version: state.admin.ui.viewVersion,
};
}



export default compose(
checkMinimumRequiredProps('List', [
'basePath',
'location',
'resource',
]),
checkMinimumRequiredProps('List', ['basePath', 'location', 'resource']),
connect(
mapStateToProps,
{
Expand Down
4 changes: 2 additions & 2 deletions packages/ra-core/src/controller/ListController.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('ListController', () => {
location: {
pathname: '',
},
params: {},
params: { filter: {} },
push: () => {},
query: {},
resource: '',
Expand Down Expand Up @@ -74,7 +74,7 @@ describe('ListController', () => {
...defaultProps,
debounce: 200,
changeListParams: jest.fn(),
filterValues: { q: 'hello' },
params: { filter: { q: 'hello' } },
children: fakeComponent,
};

Expand Down

0 comments on commit a466471

Please sign in to comment.