Skip to content

Commit 3d3c0eb

Browse files
authored
Merge pull request #11173 from marmelab/saved-queries-disableSyncWithLocation
update SavedQueryFilterListItem to update listContext state
2 parents 873b7c8 + 6c50a2c commit 3d3c0eb

3 files changed

Lines changed: 155 additions & 21 deletions

File tree

packages/ra-ui-materialui/src/list/filter/SavedQueriesList.stories.tsx

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ const Aside = () => (
133133
</Root>
134134
);
135135

136-
const SongList = () => (
136+
const SongList = (
137137
<List aside={<Aside />}>
138138
<DataTable rowClick="edit">
139139
<DataTable.Col source="title" />
@@ -307,3 +307,34 @@ const dataProvider = fakeRestProvider(
307307
},
308308
true
309309
);
310+
311+
export const WithDisableSyncWithLocation = () => {
312+
return (
313+
<TestMemoryRouter>
314+
<Admin dataProvider={dataProvider}>
315+
<Resource
316+
name="songs"
317+
list={props => (
318+
<List
319+
{...props}
320+
disableSyncWithLocation
321+
aside={<Aside />}
322+
>
323+
<DataTable rowClick="edit">
324+
<DataTable.Col source="title" />
325+
<DataTable.Col source="artist" />
326+
<DataTable.Col source="writer" />
327+
<DataTable.Col source="producer" />
328+
<DataTable.Col source="recordCompany" />
329+
<DataTable.NumberCol source="rank" />
330+
<DataTable.Col source="released">
331+
<DateField source="released" />
332+
</DataTable.Col>
333+
</DataTable>
334+
</List>
335+
)}
336+
/>
337+
</Admin>
338+
</TestMemoryRouter>
339+
);
340+
};
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import * as React from 'react';
2+
import expect from 'expect';
3+
import { render, screen, fireEvent } from '@testing-library/react';
4+
import { ListContextProvider, ListControllerResult } from 'ra-core';
5+
6+
import { SavedQueryFilterListItem } from './SavedQueryFilterListItem';
7+
8+
const defaultListContext: ListControllerResult = {
9+
data: [],
10+
displayedFilters: {},
11+
filterValues: {},
12+
hasNextPage: false,
13+
hasPreviousPage: false,
14+
hideFilter: () => {},
15+
isFetching: false,
16+
isLoading: false,
17+
onSelect: () => {},
18+
onToggleItem: () => {},
19+
onUnselectItems: () => {},
20+
page: 1,
21+
perPage: 10,
22+
refetch: () => {},
23+
resource: 'posts',
24+
selectedIds: [],
25+
setFilters: () => {},
26+
setPage: () => {},
27+
setPerPage: () => {},
28+
setSort: () => {},
29+
showFilter: () => {},
30+
sort: { field: 'id', order: 'ASC' },
31+
total: 0,
32+
error: null,
33+
isPending: false,
34+
onSelectAll: () => {},
35+
};
36+
37+
const savedQuery = {
38+
label: 'My Saved Query',
39+
value: {
40+
filter: { status: 'published' },
41+
displayedFilters: [],
42+
sort: { field: 'title', order: 'ASC' as const },
43+
perPage: 25,
44+
},
45+
};
46+
47+
describe('<SavedQueryFilterListItem />', () => {
48+
it('should display the item label', () => {
49+
render(
50+
<ListContextProvider value={defaultListContext}>
51+
<SavedQueryFilterListItem
52+
label={savedQuery.label}
53+
value={savedQuery.value}
54+
/>
55+
</ListContextProvider>
56+
);
57+
expect(screen.queryByText('My Saved Query')).not.toBeNull();
58+
});
59+
60+
it('should call setFilters and setPage when the item is clicked and not selected', () => {
61+
const setFilters = jest.fn();
62+
const setPage = jest.fn();
63+
64+
render(
65+
<ListContextProvider
66+
value={{ ...defaultListContext, setFilters, setPage }}
67+
>
68+
<SavedQueryFilterListItem
69+
label={savedQuery.label}
70+
value={savedQuery.value}
71+
/>
72+
</ListContextProvider>
73+
);
74+
75+
fireEvent.click(screen.getByText('My Saved Query'));
76+
expect(setFilters).toHaveBeenCalledWith(
77+
savedQuery.value.filter,
78+
savedQuery.value.displayedFilters
79+
);
80+
expect(setPage).toHaveBeenCalledWith(1);
81+
});
82+
83+
it('should call setFilters with empty objects and setPage when the item is clicked and already selected', () => {
84+
const setFilters = jest.fn();
85+
const setPage = jest.fn();
86+
87+
render(
88+
<ListContextProvider
89+
value={{
90+
...defaultListContext,
91+
filterValues: savedQuery.value.filter,
92+
sort: savedQuery.value.sort,
93+
perPage: savedQuery.value.perPage,
94+
displayedFilters: savedQuery.value.displayedFilters,
95+
setFilters,
96+
setPage,
97+
}}
98+
>
99+
<SavedQueryFilterListItem
100+
label={savedQuery.label}
101+
value={savedQuery.value}
102+
/>
103+
</ListContextProvider>
104+
);
105+
106+
fireEvent.click(screen.getByText('My Saved Query'));
107+
expect(setFilters).toHaveBeenCalledWith({}, {});
108+
expect(setPage).toHaveBeenCalledWith(1);
109+
});
110+
});

packages/ra-ui-materialui/src/list/filter/SavedQueryFilterListItem.tsx

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ import {
1212
} from '@mui/material';
1313
import CancelIcon from '@mui/icons-material/CancelOutlined';
1414
import isEqual from 'lodash/isEqual.js';
15-
import { stringify } from 'query-string';
16-
import { useListContext, SavedQuery, useNavigate } from 'ra-core';
15+
import { useListContext, SavedQuery } from 'ra-core';
1716

1817
const arePropsEqual = (
1918
prevProps: SavedQueryFilterListItemProps,
@@ -29,9 +28,14 @@ export const SavedQueryFilterListItem = memo(
2928
name: PREFIX,
3029
});
3130
const { className, label, sx, value } = props;
32-
const { filterValues, sort, perPage, displayedFilters } =
33-
useListContext();
34-
const navigate = useNavigate();
31+
const {
32+
filterValues,
33+
sort,
34+
perPage,
35+
displayedFilters,
36+
setFilters,
37+
setPage,
38+
} = useListContext();
3539

3640
const isSelected = isEqual(value, {
3741
filter: filterValues,
@@ -41,24 +45,13 @@ export const SavedQueryFilterListItem = memo(
4145
});
4246

4347
const addFilter = (): void => {
44-
navigate({
45-
search: stringify({
46-
filter: JSON.stringify(value.filter),
47-
sort: value.sort?.field,
48-
order: value.sort?.order,
49-
page: 1,
50-
perPage: value.perPage ?? perPage,
51-
displayedFilters: JSON.stringify(value.displayedFilters),
52-
}),
53-
});
48+
setFilters(value.filter, value.displayedFilters);
49+
setPage(1);
5450
};
5551

5652
const removeFilter = (): void => {
57-
navigate({
58-
search: stringify({
59-
filter: JSON.stringify({}),
60-
}),
61-
});
53+
setFilters({}, {});
54+
setPage(1);
6255
};
6356

6457
const toggleFilter = (): void =>

0 commit comments

Comments
 (0)