From 536b8131b4878d1b0a281fa95962f45a927e0f33 Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Fri, 9 Sep 2022 17:58:28 +0200 Subject: [PATCH 1/2] Improve FilterList doc --- docs/FilteringTutorial.md | 48 +++++++ docs/List.md | 46 ++++++- docs/navigation.html | 1 + .../src/list/filter/FilterList.stories.tsx | 125 +++++++++++++++++- 4 files changed, 218 insertions(+), 2 deletions(-) diff --git a/docs/FilteringTutorial.md b/docs/FilteringTutorial.md index b3d2e41f55e..a13b250bfde 100644 --- a/docs/FilteringTutorial.md +++ b/docs/FilteringTutorial.md @@ -161,12 +161,60 @@ const postFilters = [ An alternative UI to the Filter Button/Form Combo is the FilterList Sidebar. Similar to what users usually see on e-commerce websites, it's a panel with many simple filters that can be enabled and combined using the mouse. The user experience is better than the Button/Form Combo, because the filter values are explicit, and it doesn't require typing anything in a form. But it's a bit less powerful, as only filters with a finite set of values (or intervals) can be used in the ``. +Here is an example FilterList sidebar: + +{% raw %} +```jsx +import { SavedQueriesList, FilterLiveSearch, FilterList, FilterListItem } from 'react-admin'; +import { Card, CardContent } from '@mui/material'; +import MailIcon from '@mui/icons-material/MailOutline'; +import CategoryIcon from '@mui/icons-material/LocalOffer'; + +export const PostFilterSidebar = () => ( + + + + + }> + + + + }> + + + + + + + +); +``` +{% endraw %} + +Add it to the list view using the `` prop: + +```jsx +import { PostFilterSidebar } from './PostFilterSidebar'; + +export const PostList = () => ( + }> + ... + +); +``` + +**Tip**: the `` prop in the `PostFilterSidebar` component above is here to put the sidebar on the left side of the screen, instead of the default right side. + Check [the `` documentation](./FilterList.md) for more information. If you use the FilterList, you'll probably need a search input. As the FilterList sidebar is not a form, this requires a bit of extra work. Fortunately, react-admin provides a specialized search input component for that purpose: check [the `` documentation](./FilterLiveSearch.md) for details. ![Filter Live Search](./img/filter-live-search.gif) +Finally, a filter sidebar is the ideal place to display the user's favorite filters. Check [the `` documentation](./SavedQueriesList.md) for more information. + +![Filter Sidebar With SavedQueriesList](./img/SavedQueriesList.gif) + ## Filter Operators The internal format for storing filters and sending them to the dataProvider is an object, e.g.: diff --git a/docs/List.md b/docs/List.md index 896615de815..3688f3d8fea 100644 --- a/docs/List.md +++ b/docs/List.md @@ -137,7 +137,7 @@ const PostList = () => ( ``` {% endraw %} -The `aside` component can call the `useListContext()` hook to receive the same props as the `List` child component. This means you can display additional details of the current list in the aside component: +The `aside` component can call the `useListContext()` hook to receive the same props as the `` child component. This means you can display additional details of the current list in the aside component: {% raw %} ```jsx @@ -159,6 +159,50 @@ const Aside = () => { ``` {% endraw %} +The `aside` prop is also the preferred way to add a [Filter Sidebar](./FilteringTutorial.md#the-filterlist-sidebar) to a list view: + +{% raw %} +```jsx +// in src/PostFilterSidebar.js +import { SavedQueriesList, FilterLiveSearch, FilterList, FilterListItem } from 'react-admin'; +import { Card, CardContent } from '@mui/material'; +import MailIcon from '@mui/icons-material/MailOutline'; +import CategoryIcon from '@mui/icons-material/LocalOffer'; + +export const PostFilterSidebar = () => ( + + + + + }> + + + + }> + + + + + + + +); +``` +{% endraw %} + +```jsx +// in src/PostList.js +import { PostFilterSidebar } from './PostFilterSidebar'; + +export const PostList = () => ( + }> + ... + +); +``` + +**Tip**: the `` prop in the `PostFilterSidebar` component above is here to put the sidebar on the left side of the screen, instead of the default right side. + ## `children`: List Layout `` doesn't render any content by default - it delegates this to its child. List layout components grab the `data` from the `ListContext` and render them on screen. diff --git a/docs/navigation.html b/docs/navigation.html index 37a81aab97f..80e0f86d4d3 100644 --- a/docs/navigation.html +++ b/docs/navigation.html @@ -70,6 +70,7 @@
  • <FilterButton>
  • <FilterList>
  • <FilterLiveSearch>
  • +
  • <SavedQueriesList>
  • <Pagination>
  • <SortButton>
  • useList
  • diff --git a/packages/ra-ui-materialui/src/list/filter/FilterList.stories.tsx b/packages/ra-ui-materialui/src/list/filter/FilterList.stories.tsx index 4b4b49f59e5..480628e0d7b 100644 --- a/packages/ra-ui-materialui/src/list/filter/FilterList.stories.tsx +++ b/packages/ra-ui-materialui/src/list/filter/FilterList.stories.tsx @@ -1,10 +1,22 @@ import * as React from 'react'; -import { useList, useListContext, ListContextProvider } from 'ra-core'; +import { + useList, + useListContext, + ListContextProvider, + Resource, +} from 'ra-core'; +import fakeRestDataProvider from 'ra-data-fakerest'; import { Box, Typography, Card, CardContent } from '@mui/material'; import MailIcon from '@mui/icons-material/MailOutline'; import CategoryIcon from '@mui/icons-material/LocalOffer'; + import { FilterList } from './FilterList'; import { FilterListItem } from './FilterListItem'; +import { AdminContext } from '../../AdminContext'; +import { AdminUI } from '../../AdminUI'; +import { List } from '../List'; +import { Datagrid } from '../datagrid/Datagrid'; +import { TextField } from '../../field'; export default { title: 'ra-ui-materialui/list/filter/FilterList' }; @@ -74,3 +86,114 @@ const FilterValue = () => { ); }; + +const dataProvider = fakeRestDataProvider({ + books: [ + { + id: 1, + title: 'War and Peace', + author: 'Leo Tolstoy', + year: 1869, + }, + { + id: 2, + title: 'Pride and Predjudice', + author: 'Jane Austen', + year: 1813, + }, + { + id: 3, + title: 'The Picture of Dorian Gray', + author: 'Oscar Wilde', + year: 1890, + }, + { + id: 4, + title: 'Le Petit Prince', + author: 'Antoine de Saint-ExupĂ©ry', + year: 1943, + }, + { + id: 5, + title: "Alice's Adventures in Wonderland", + author: 'Lewis Carroll', + year: 1865, + }, + { + id: 6, + title: 'Madame Bovary', + author: 'Gustave Flaubert', + year: 1856, + }, + { + id: 7, + title: 'The Lord of the Rings', + author: 'J. R. R. Tolkien', + year: 1954, + }, + { + id: 8, + title: "Harry Potter and the Philosopher's Stone", + author: 'J. K. Rowling', + year: 1997, + }, + { + id: 9, + title: 'The Alchemist', + author: 'Paulo Coelho', + year: 1988, + }, + { + id: 10, + title: 'A Catcher in the Rye', + author: 'J. D. Salinger', + year: 1951, + }, + { + id: 11, + title: 'Ulysses', + author: 'James Joyce', + year: 1922, + }, + ], + authors: [], +}); + +const BookListAside = () => ( + + + }> + + + + + + +); + +const BookList = () => ( + }> + + + + + + +); + +export const FullApp = () => ( + + + + + +); From 1817ed46b7626eea2aba84c97517e86e3648aa0e Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Fri, 9 Sep 2022 21:26:44 +0200 Subject: [PATCH 2/2] Improve doc --- docs/FilterList.md | 156 +++++++++++--------------------------- docs/FilteringTutorial.md | 2 +- docs/SavedQueriesList.md | 7 +- 3 files changed, 48 insertions(+), 117 deletions(-) diff --git a/docs/FilterList.md b/docs/FilterList.md index 77c69e4fa0a..1bea8b3c8e8 100644 --- a/docs/FilterList.md +++ b/docs/FilterList.md @@ -5,130 +5,64 @@ title: "The FilterList Component" # `` +An alternative UI to the Filter Button/Form Combo is the FilterList Sidebar. Similar to what users usually see on e-commerce websites, it's a panel with many simple filters that can be enabled and combined using the mouse. + ![Filter Sidebar](./img/filter-sidebar.gif) -An alternative UI to the Filter Button/Form Combo is the FilterList Sidebar. Similar to what users usually see on e-commerce websites, it's a panel with many simple filters that can be enabled and combined using the mouse. The user experience is better than the Button/Form Combo, because the filter values are explicit, and it doesn't require typing anything in a form. But it's a bit less powerful, as only filters with a finite set of values (or intervals) can be used in the ``. +The user experience is better than the Button/Form Combo, because the filter values are explicit, and it doesn't require typing anything in a form. But it's a bit less powerful, as only filters with a finite set of values (or intervals) can be used in the ``. ## Usage -The `` component expects a list of `` as children. Each `` defines a filter `label` and a `value`, which is merged with the current filter value when enabled by the user. Here is an example usage for a list of customers: +Use the `` component in a sidebar for the `` view. It expects a list of `` as children. Each `` defines a filter `label` and a `value`, which is merged with the current filter value when enabled by the user. + +For instance, here is a filter sidebar for a post list, allowing users to filter on two fields: {% raw %} ```jsx -import AccessTimeIcon from '@mui/icons-material/AccessTime'; -import MonetizationOnIcon from '@mui/icons-material/MonetizationOnOutlined'; +import { SavedQueriesList, FilterLiveSearch, FilterList, FilterListItem } from 'react-admin'; +import { Card, CardContent } from '@mui/material'; import MailIcon from '@mui/icons-material/MailOutline'; -import LocalOfferIcon from '@mui/icons-material/LocalOfferOutlined'; -import { FilterList, FilterListItem } from 'react-admin'; -import { - endOfYesterday, - startOfWeek, - subWeeks, - startOfMonth, - subMonths, -} from 'date-fns'; - -import segments from '../segments/data'; - -const LastVisitedFilter = () => ( - }> - - - - - - - -); -const HasOrderedFilter = () => ( - } - > - - - -); -const HasNewsletterFilter = () => ( - } - > - - - -); -const SegmentFilter = () => ( - } - > - {segments.map(segment => ( - - ))} - +import CategoryIcon from '@mui/icons-material/LocalOffer'; + +export const PostFilterSidebar = () => ( + + + + + }> + + + + }> + + + + + + + ); ``` {% endraw %} +Add this component to the list view using [the `` prop](./List.md#aside): + +```jsx +import { PostFilterSidebar } from './PostFilterSidebar'; + +export const PostList = () => ( + }> + ... + +); +``` + +**Tip**: The `` prop in the `PostFilterSidebar` component above is here to put the sidebar on the left side of the screen, instead of the default right side. + +A more sophisticated example is the filter sidebar for the visitors list visible in the screencast at the beginning of this page. The code for this example is available in the [react-admin repository](https://github.com/marmelab/react-admin/blob/master/examples/demo/src/visitors/VisitorListAside.tsx). + +**Tip**: In a Filter List sidebar, you can use [the `` component](./FilterLiveSearch.md) to add a search input at the top of the sidebar, and [the `` component](./SavedQueriesList.md) to add a list of saved queries. + `` accepts 3 props: * [`children`](#children), which must be a list of `` diff --git a/docs/FilteringTutorial.md b/docs/FilteringTutorial.md index a13b250bfde..c139a0857c2 100644 --- a/docs/FilteringTutorial.md +++ b/docs/FilteringTutorial.md @@ -203,7 +203,7 @@ export const PostList = () => ( ); ``` -**Tip**: the `` prop in the `PostFilterSidebar` component above is here to put the sidebar on the left side of the screen, instead of the default right side. +**Tip**: The `` prop in the `PostFilterSidebar` component above is here to put the sidebar on the left side of the screen, instead of the default right side. Check [the `` documentation](./FilterList.md) for more information. diff --git a/docs/SavedQueriesList.md b/docs/SavedQueriesList.md index 65b260cb001..56d5f5a9f4e 100644 --- a/docs/SavedQueriesList.md +++ b/docs/SavedQueriesList.md @@ -7,7 +7,7 @@ title: "The SavedQueriesList Component" ![Filter Sidebar With SavedQueriesList](./img/SavedQueriesList.gif) -`` renders a list of filters saved by the end user (and kept in [the Store](./Store.md)). It is a complement to `` sections for the filter sidebar +`` renders a list of filters saved by the end user (and kept in [the Store](./Store.md)). It is a complement to `` sections for [the filter sidebar](./FilteringTutorial.md#the-filterlist-sidebar). ## Usage @@ -17,7 +17,7 @@ import { FilterListItem, List, Datagrid -+ SavedQueriesList ++ SavedQueriesList } from 'react-admin'; import { Card, CardContent } from '@mui/material'; @@ -82,6 +82,3 @@ const SongList = props => ( ``` {% endraw %} -## API - -[``]: https://github.com/marmelab/react-admin/blob/master/packages/ra-ui-materialui/src/list/filter/SavedQueriesList.tsx