From 0d7e45b5032f882c564f085635f60ca91a39d648 Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Thu, 17 Jun 2021 19:02:53 +0200 Subject: [PATCH 1/6] Add ability to define filters as array of Inputs --- examples/simple/src/posts/PostList.tsx | 26 +-- .../src/controller/useListController.ts | 2 +- .../src/list/FilterContext.tsx | 8 + packages/ra-ui-materialui/src/list/List.tsx | 5 +- .../ra-ui-materialui/src/list/ListActions.tsx | 24 ++- .../ra-ui-materialui/src/list/ListToolbar.tsx | 27 ++- .../ra-ui-materialui/src/list/ListView.tsx | 5 +- .../src/list/filter/FilterButton.tsx | 30 +-- .../src/list/filter/FilterForm.tsx | 187 ++++++++++-------- packages/ra-ui-materialui/src/list/index.ts | 1 + packages/ra-ui-materialui/src/types.ts | 2 +- 11 files changed, 190 insertions(+), 127 deletions(-) create mode 100644 packages/ra-ui-materialui/src/list/FilterContext.tsx diff --git a/examples/simple/src/posts/PostList.tsx b/examples/simple/src/posts/PostList.tsx index a361ba87544..3d677466242 100644 --- a/examples/simple/src/posts/PostList.tsx +++ b/examples/simple/src/posts/PostList.tsx @@ -14,7 +14,6 @@ import { DateField, downloadCSV, EditButton, - Filter, List, NumberField, ReferenceArrayField, @@ -41,20 +40,15 @@ const QuickFilter = ({ label, source, defaultValue }) => { return ; }; -const PostFilter = props => ( - - - - - -); +const postFilter = [ + , + , + , +]; const exporter = posts => { const data = posts.map(post => ({ @@ -126,7 +120,7 @@ const PostList = props => { } - filters={} + filters={postFilter} sort={{ field: 'published_at', order: 'DESC' }} exporter={exporter} > diff --git a/packages/ra-core/src/controller/useListController.ts b/packages/ra-core/src/controller/useListController.ts index f33b694156e..85acdbf0cae 100644 --- a/packages/ra-core/src/controller/useListController.ts +++ b/packages/ra-core/src/controller/useListController.ts @@ -24,7 +24,7 @@ import { useResourceContext, useGetResourceLabel } from '../core'; export interface ListProps { // the props you can change filter?: FilterPayload; - filters?: ReactElement; + filters?: ReactElement | ReactElement[]; filterDefaultValues?: object; perPage?: number; sort?: SortPayload; diff --git a/packages/ra-ui-materialui/src/list/FilterContext.tsx b/packages/ra-ui-materialui/src/list/FilterContext.tsx new file mode 100644 index 00000000000..d5bdf879512 --- /dev/null +++ b/packages/ra-ui-materialui/src/list/FilterContext.tsx @@ -0,0 +1,8 @@ +import * as React from 'react'; + +export type FilterContextType = React.ReactNode[]; + +/** + * Make filters accessible to sub components + */ +export const FilterContext = React.createContext(undefined); diff --git a/packages/ra-ui-materialui/src/list/List.tsx b/packages/ra-ui-materialui/src/list/List.tsx index 8359e12118d..67768ec5c3f 100644 --- a/packages/ra-ui-materialui/src/list/List.tsx +++ b/packages/ra-ui-materialui/src/list/List.tsx @@ -84,7 +84,10 @@ List.propTypes = { className: PropTypes.string, filter: PropTypes.object, filterDefaultValues: PropTypes.object, - filters: PropTypes.element, + filters: PropTypes.oneOfType([ + PropTypes.element, + PropTypes.arrayOf(PropTypes.element), + ]), // @ts-ignore-line pagination: PropTypes.oneOfType([PropTypes.element, PropTypes.bool]), perPage: PropTypes.number.isRequired, diff --git a/packages/ra-ui-materialui/src/list/ListActions.tsx b/packages/ra-ui-materialui/src/list/ListActions.tsx index 0e68b5a278b..29423ce50ef 100644 --- a/packages/ra-ui-materialui/src/list/ListActions.tsx +++ b/packages/ra-ui-materialui/src/list/ListActions.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { cloneElement, useMemo, FC, ReactElement } from 'react'; +import { cloneElement, useMemo, useContext, FC, ReactElement } from 'react'; import PropTypes from 'prop-types'; import { sanitizeListRestProps, @@ -14,6 +14,8 @@ import { ToolbarProps } from '@material-ui/core'; import TopToolbar from '../layout/TopToolbar'; import { CreateButton, ExportButton } from '../button'; +import { FilterContext } from './FilterContext'; +import FilterButton from './filter/FilterButton'; /** * Action Toolbar for the List view @@ -44,7 +46,7 @@ import { CreateButton, ExportButton } from '../button'; * ); */ const ListActions: FC = props => { - const { className, exporter, filters, ...rest } = props; + const { className, exporter, filters: filtersProp, ...rest } = props; const { currentSort, displayedFilters, @@ -56,17 +58,19 @@ const ListActions: FC = props => { } = useListContext(props); const resource = useResourceContext(rest); const { hasCreate } = useResourceDefinition(rest); + const filters = useContext(FilterContext) || filtersProp; return useMemo( () => ( - {filters && - cloneElement(filters, { - resource, - showFilter, - displayedFilters, - filterValues, - context: 'button', - })} + {filtersProp + ? cloneElement(filtersProp, { + resource, + showFilter, + displayedFilters, + filterValues, + context: 'button', + }) + : filters && } {hasCreate && } {exporter !== false && ( ({ @@ -36,7 +38,21 @@ const useStyles = makeStyles( const ListToolbar: FC = props => { const { classes: classesOverride, filters, actions, ...rest } = props; const classes = useStyles(props); - return ( + + return Array.isArray(filters) ? ( + + + + + {actions && + React.cloneElement(actions, { + ...rest, + className: classes.actions, + ...actions.props, + })} + + + ) : ( {filters && React.cloneElement(filters, { @@ -57,7 +73,10 @@ const ListToolbar: FC = props => { ListToolbar.propTypes = { classes: PropTypes.object, - filters: PropTypes.element, + filters: PropTypes.oneOfType([ + PropTypes.element, + PropTypes.arrayOf(PropTypes.element), + ]), // @ts-ignore actions: PropTypes.oneOfType([PropTypes.bool, PropTypes.element]), // @ts-ignore @@ -68,7 +87,7 @@ export interface ListToolbarProps extends Omit { actions?: ReactElement | false; classes?: ClassesOverride; - filters?: ReactElement; + filters?: ReactElement | ReactElement[]; exporter?: Exporter | false; } diff --git a/packages/ra-ui-materialui/src/list/ListView.tsx b/packages/ra-ui-materialui/src/list/ListView.tsx index d84d8f97ce9..f0f26ca09cc 100644 --- a/packages/ra-ui-materialui/src/list/ListView.tsx +++ b/packages/ra-ui-materialui/src/list/ListView.tsx @@ -124,7 +124,10 @@ ListView.propTypes = { // @ts-ignore-line exporter: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]), filterDefaultValues: PropTypes.object, - filters: PropTypes.element, + filters: PropTypes.oneOfType([ + PropTypes.element, + PropTypes.arrayOf(PropTypes.element), + ]), filterValues: PropTypes.object, hasCreate: PropTypes.bool, hideFilter: PropTypes.func, diff --git a/packages/ra-ui-materialui/src/list/filter/FilterButton.tsx b/packages/ra-ui-materialui/src/list/filter/FilterButton.tsx index 3c15203b3c9..aa7c43e33a0 100644 --- a/packages/ra-ui-materialui/src/list/filter/FilterButton.tsx +++ b/packages/ra-ui-materialui/src/list/filter/FilterButton.tsx @@ -5,6 +5,7 @@ import { useRef, ReactNode, HtmlHTMLAttributes, + useContext, } from 'react'; import PropTypes from 'prop-types'; import Menu from '@material-ui/core/Menu'; @@ -17,6 +18,7 @@ import { useListContext, useResourceContext } from 'ra-core'; import { FilterButtonMenuItem } from './FilterButtonMenuItem'; import Button from '../../button/Button'; import { ClassesOverride } from '../../types'; +import { FilterContext } from '../FilterContext'; const useStyles = makeStyles( { @@ -26,7 +28,13 @@ const useStyles = makeStyles( ); const FilterButton = (props: FilterButtonProps): JSX.Element => { - const { filters, classes: classesOverride, className, ...rest } = props; + const { + filters: filtersProp, + classes: classesOverride, + className, + ...rest + } = props; + const filters = useContext(FilterContext) || filtersProp; const resource = useResourceContext(props); const { displayedFilters = {}, filterValues, showFilter } = useListContext( props @@ -97,18 +105,18 @@ const FilterButton = (props: FilterButtonProps): JSX.Element => { }; const sanitizeRestProps = ({ - displayedFilters, - filterValues, - showFilter, + displayedFilters = null, + filterValues = null, + showFilter = null, ...rest }) => rest; FilterButton.propTypes = { resource: PropTypes.string, - filters: PropTypes.arrayOf(PropTypes.node).isRequired, + filters: PropTypes.arrayOf(PropTypes.node), displayedFilters: PropTypes.object, - filterValues: PropTypes.object.isRequired, - showFilter: PropTypes.func.isRequired, + filterValues: PropTypes.object, + showFilter: PropTypes.func, classes: PropTypes.object, className: PropTypes.string, }; @@ -117,10 +125,10 @@ export interface FilterButtonProps extends HtmlHTMLAttributes { classes?: ClassesOverride; className?: string; resource?: string; - filterValues: any; - showFilter: (filterName: string, defaultValue: any) => void; - displayedFilters: any; - filters: ReactNode[]; + filterValues?: any; + showFilter?: (filterName: string, defaultValue: any) => void; + displayedFilters?: any; + filters?: ReactNode[]; } export default FilterButton; diff --git a/packages/ra-ui-materialui/src/list/filter/FilterForm.tsx b/packages/ra-ui-materialui/src/list/filter/FilterForm.tsx index db3a4fb56f9..a9bb3f0d601 100644 --- a/packages/ra-ui-materialui/src/list/filter/FilterForm.tsx +++ b/packages/ra-ui-materialui/src/list/filter/FilterForm.tsx @@ -1,6 +1,13 @@ import * as React from 'react'; -import { useEffect, useCallback, HtmlHTMLAttributes, ReactNode } from 'react'; +import { + useEffect, + useCallback, + useContext, + HtmlHTMLAttributes, + ReactNode, +} from 'react'; import PropTypes from 'prop-types'; +import { useListContext } from 'ra-core'; import { Form, FormRenderProps, FormSpy } from 'react-final-form'; import arrayMutators from 'final-form-arrays'; import classnames from 'classnames'; @@ -10,6 +17,79 @@ import lodashGet from 'lodash/get'; import FilterFormInput from './FilterFormInput'; import { ClassesOverride } from '../../types'; +import { FilterContext } from '../FilterContext'; + +export const FilterForm = (props: FilterFormProps) => { + const { + classes = {}, + className, + resource, + margin, + filters, + variant, + initialValues, + ...rest + } = props; + const { displayedFilters = {}, hideFilter } = useListContext(props); + useEffect(() => { + filters.forEach((filter: JSX.Element) => { + if (filter.props.alwaysOn && filter.props.defaultValue) { + throw new Error( + 'Cannot use alwaysOn and defaultValue on a filter input. Please set the filterDefaultValues props on the element instead.' + ); + } + }); + }, [filters]); + + const getShownFilters = () => + filters.filter( + (filterElement: JSX.Element) => + filterElement.props.alwaysOn || + displayedFilters[filterElement.props.source] || + typeof lodashGet(initialValues, filterElement.props.source) !== + 'undefined' + ); + + const handleHide = useCallback( + event => hideFilter(event.currentTarget.dataset.key), + [hideFilter] + ); + + return ( +
+ {getShownFilters().map((filterElement: JSX.Element) => ( + + ))} +
+ + ); +}; + +const handleSubmit = event => { + event.preventDefault(); + return false; +}; + +FilterForm.propTypes = { + resource: PropTypes.string, + filters: PropTypes.arrayOf(PropTypes.node).isRequired, + displayedFilters: PropTypes.object, + hideFilter: PropTypes.func, + initialValues: PropTypes.object, + classes: PropTypes.object, + className: PropTypes.string, +}; const useStyles = makeStyles( theme => ({ @@ -33,6 +113,7 @@ const sanitizeRestProps = ({ dirtyFields, dirtyFieldsSinceLastSubmit, dirtySinceLastSubmit, + displayedFilters, error, errors, filterValues, @@ -40,6 +121,7 @@ const sanitizeRestProps = ({ handleSubmit, hasSubmitErrors, hasValidationErrors, + hideFilter, invalid, modified, modifiedSinceLastSubmit, @@ -74,82 +156,10 @@ export interface FilterFormProps variant?: 'standard' | 'outlined' | 'filled'; } -export const FilterForm = ({ - classes = {}, - className, - resource, - margin, - variant, - filters, - displayedFilters = {}, - hideFilter, +export const mergeInitialValuesWithDefaultValues = ( initialValues, - ...rest -}: FilterFormProps) => { - useEffect(() => { - filters.forEach((filter: JSX.Element) => { - if (filter.props.alwaysOn && filter.props.defaultValue) { - throw new Error( - 'Cannot use alwaysOn and defaultValue on a filter input. Please set the filterDefaultValues props on the element instead.' - ); - } - }); - }, [filters]); - - const getShownFilters = () => - filters.filter( - (filterElement: JSX.Element) => - filterElement.props.alwaysOn || - displayedFilters[filterElement.props.source] || - typeof lodashGet(initialValues, filterElement.props.source) !== - 'undefined' - ); - - const handleHide = useCallback( - event => hideFilter(event.currentTarget.dataset.key), - [hideFilter] - ); - - return ( -
- {getShownFilters().map((filterElement: JSX.Element) => ( - - ))} -
- - ); -}; - -const handleSubmit = event => { - event.preventDefault(); - return false; -}; - -FilterForm.propTypes = { - resource: PropTypes.string, - filters: PropTypes.arrayOf(PropTypes.node).isRequired, - displayedFilters: PropTypes.object, - hideFilter: PropTypes.func.isRequired, - initialValues: PropTypes.object, - classes: PropTypes.object, - className: PropTypes.string, -}; - -export const mergeInitialValuesWithDefaultValues = ({ - initialValues, - filters, -}) => ({ + filters +) => ({ ...filters .filter( (filterElement: JSX.Element) => @@ -168,14 +178,22 @@ export const mergeInitialValuesWithDefaultValues = ({ }); const EnhancedFilterForm = props => { - const { classes: classesOverride, ...rest } = props; + const { + classes: classesOverride, + filters: filtersProps, + initialValues, + ...rest + } = props; const classes = useStyles(props); - - const mergedInitialValuesWithDefaultValues = mergeInitialValuesWithDefaultValues( + const { setFilters, displayedFilters, filterValues } = useListContext( props ); + const filters = useContext(FilterContext) || filtersProps; - const { initialValues, ...rest2 } = rest; + const mergedInitialValuesWithDefaultValues = mergeInitialValuesWithDefaultValues( + initialValues || filterValues, + filters + ); return (
{ if (pristine || invalid) { return; } - rest && rest.setFilters(values); + setFilters(values, displayedFilters); }} /> - + )} /> diff --git a/packages/ra-ui-materialui/src/list/index.ts b/packages/ra-ui-materialui/src/list/index.ts index b64f9702ef9..d41ae97a187 100644 --- a/packages/ra-ui-materialui/src/list/index.ts +++ b/packages/ra-ui-materialui/src/list/index.ts @@ -11,6 +11,7 @@ import SimpleList, { SimpleListProps } from './SimpleList'; import SimpleListLoading from './SimpleListLoading'; import SingleFieldList from './SingleFieldList'; +export * from './FilterContext'; export * from './filter'; export * from './datagrid'; export * from './ListView'; diff --git a/packages/ra-ui-materialui/src/types.ts b/packages/ra-ui-materialui/src/types.ts index df192154b1d..1b24698f70b 100644 --- a/packages/ra-ui-materialui/src/types.ts +++ b/packages/ra-ui-materialui/src/types.ts @@ -23,7 +23,7 @@ export interface ListProps extends ResourceComponentProps { exporter?: Exporter | false; filter?: FilterPayload; filterDefaultValues?: any; - filters?: ReactElement; + filters?: ReactElement | ReactElement[]; pagination?: ReactElement | false; perPage?: number; sort?: SortPayload; From ad1dc604ffb3322f90c0f4649913ad3d2ba7f847 Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Tue, 22 Jun 2021 15:53:12 +0200 Subject: [PATCH 2/6] Update documentation to remove traces of --- docs/Buttons.md | 2 +- docs/Inputs.md | 8 +- docs/List.md | 308 ++++++++---------- docs/Tutorial.md | 22 +- .../ra-core/src/controller/ListContext.tsx | 2 +- .../src/controller/ListFilterContext.tsx | 2 +- 6 files changed, 160 insertions(+), 184 deletions(-) diff --git a/docs/Buttons.md b/docs/Buttons.md index 53e7a108307..df9fd8fe47d 100644 --- a/docs/Buttons.md +++ b/docs/Buttons.md @@ -257,7 +257,7 @@ export const PostList = (props) => ( ### `` -This button is an internal component used by react-admin in [the `` button/form combo](./List.md#the-filter-buttonform-combo). +This button is an internal component used by react-admin in [the Filter button/form combo](./List.md#the-filter-buttonform-combo). ![List Filters](./img/list_filter.gif) diff --git a/docs/Inputs.md b/docs/Inputs.md index 6ff608c647f..e64e39563f4 100644 --- a/docs/Inputs.md +++ b/docs/Inputs.md @@ -5,7 +5,7 @@ title: "Input Components" # Input Components -An `Input` component displays an input, or a dropdown list, a list of radio buttons, etc. Such components allow to edit a record property, and are common in the ``, ``, and `` views. +An `Input` component displays an input, or a dropdown list, a list of radio buttons, etc. Such components allow to edit a record property, and are common in the ``, `` component, and in the List Filters. ```jsx // in src/posts.js @@ -534,7 +534,7 @@ import { AutocompleteInput } from 'react-admin'; | `optionText` | Optional | `string` | `Function` | `Component` | `name` | Field name of record to display in the suggestion item or function which accepts the correct record as argument (`(record)=> {string}`) | | `optionValue` | Optional | `string` | `id` | Field name of record containing the value to use as input value | | `inputText` | Optional | `Function` | `-` | If `optionText` is a custom Component, this function is needed to determine the text displayed for the current selection. | -| `resettable` | Optional | `boolean` | `false` | Display a button to reset the text filter. Useful when using `` inside `` | +| `resettable` | Optional | `boolean` | `false` | Display a button to reset the text filter. Useful when using `` inside the list filters | | `setFilter` | Optional | `Function` | `null` | A callback to inform the `searchText` has changed and new `choices` can be retrieved based on this `searchText`. Signature `searchText => void`. This function is automatically setup when using `ReferenceInput`. | | `shouldRenderSuggestions` | Optional | `Function` | `() => true` | A function that returns a `boolean` to determine whether or not suggestions are rendered. Use this when working with large collections of data to improve performance and user experience. This function is passed into the underlying react-autosuggest component. Ex.`(value) => value.trim() > 2` | | `suggestionLimit` | Optional | `number` | `null` | Limits the numbers of suggestions that are shown in the dropdown list | @@ -1930,7 +1930,7 @@ import { ReferenceArrayInput, SelectArrayInput } from 'react-admin'; ``` -**Tip**: `allowEmpty` is set by default for all Input components children of the `` component +**Tip**: `allowEmpty` is set by default for all Input components passed as ``. You can tweak how this component fetches the possible values using the `perPage`, `sort`, and `filter` props. @@ -2045,7 +2045,7 @@ import { ReferenceInput, SelectInput } from 'react-admin'; ``` -**Tip**: `allowEmpty` is set by default for all Input components children of the `` component: +**Tip**: `allowEmpty` is set by default for all Input components passed as ``: ```jsx const CommentFilter = (props) => ( diff --git a/docs/List.md b/docs/List.md index 18273c3d154..044ff114ea5 100644 --- a/docs/List.md +++ b/docs/List.md @@ -513,28 +513,24 @@ const CustomResetViewsButton = ({ selectedIds }) => { ![List Filters](./img/list_filter.gif) -You can add a filter component to the List using the `filters` prop: +You can add an array of filter Inputs to the List using the `filters` prop: ```jsx -const PostFilter = (props) => ( - - - - -); +const postFilters = [ + , + , +]; export const PostList = (props) => ( - }> + ... ); ``` -The filter component must be a `` with `` children. - -**Tip**: Don't mix up this `filters` prop, expecting a React element, with the `filter` props, which expects an object to define permanent filters (see below). +**Tip**: Don't mix up this `filters` prop, expecting an array of `` elements, with the `filter` props, which expects an object to define permanent filters (see below). -Children of the `` form are regular inputs. `` hides them all by default, except those that have the `alwaysOn` prop. +Filter Inputs are regular inputs. `` hides them all by default, except those that have the `alwaysOn` prop. You can also display filters as a sidebar: @@ -568,16 +564,14 @@ There is one exception: inputs with `alwaysOn` don't accept `defaultValue`. You {% raw %} ```jsx // in src/posts.js -const PostFilter = (props) => ( - - - - - -); +const postFilters = [ + , + , + , +]; export const PostList = (props) => ( - } filterDefaultValues={{ is_published: true }}> + ... ); @@ -857,7 +851,7 @@ export default PostList;
- + @@ -873,7 +867,7 @@ The next sections explain how to use the filter functionality. And first, a few React-admin proposes several UI components to let users see and modify filters, and gives you the tools to build custom ones. -- The `` Button/Form Combo +- The Filter Button/Form Combo - [Usage](#the-filter-buttonform-combo) - [Full-Text Search](#full-text-search) - [Quick Filters](#quick-filters) @@ -933,48 +927,39 @@ const LinkToRelatedProducts = ({ record }) => { You can use this button e.g. as a child of ``. You can also create a custom Menu button with that technique to link to the unfiltered list by setting the filter value to `{}`. -### The `` Button/Form Combo +### The Filter Button/Form Combo ![List Filters](./img/list_filter.gif) -The default appearance for filters is an inline form displayed on top of the list. Users also see a dropdown button allowing to add more inputs to that form. This functionality relies on the `` component: +The default appearance for filters is an inline form displayed on top of the list. Users also see a dropdown button allowing to add more inputs to that form. This functionality relies on the `filters` prop: ```jsx -import { Filter, TextInput } from 'react-admin'; +import { TextInput } from 'react-admin'; -const PostFilter = (props) => ( - - - - -); +const postFilters = [ + , + , +]; ``` -Children of the `` component are regular inputs. That means you can build sophisticated filters based on references, array values, etc. `` hides all inputs in the filter form by default, except those that have the `alwaysOn` prop. +Elements of the `filters` array are regular inputs. That means you can build sophisticated filters based on references, array values, etc. `` hides all inputs in the filter form by default, except those that have the `alwaysOn` prop. -**Tip**: For technical reasons, react-admin does not accept children of `` having both a `defaultValue` and `alwaysOn`. To set default values for always on filters, use the [`filterDefaultValues`](#filterdefaultvalues) prop of the component instead. +**Tip**: For technical reasons, react-admin does not accept Filter inputs having both a `defaultValue` and `alwaysOn`. To set default values for always on filters, use the [`filterDefaultValues`](#filterdefaultvalues) prop of the `` component instead. To inject the filter form in a ``, use the `filters` prop: ```jsx export const PostList = (props) => ( - }> + ... ); ``` -`` clones the component passed as `filters` twice: - -- once with the prop `context="form"`, to render the filter *form* -- once with the prop `context="button"`, to render the filter *button* - -The component passed as `filters` should know how to render differently according to the `context` prop. +`` uses the elements passed as `filters` twice: -That's the case of the react-admin `` component: - -- `` renders an inline form based on its children which must be `` components -- `` renders a dropdown allowing enabling filters based on the `source` prop of its children. +- once to render the filter *form* +- once to render the filter *button* (using each element `label`, falling back to the humanized `source`) #### Full-Text Search @@ -983,13 +968,11 @@ That's the case of the react-admin `` component: In addition to [the usual input types](./Inputs.md) (``, ``, ``, etc.), you can use the ``, which is designed especially for the filter form. It's like a `` with a magnifier glass icon - exactly the type of input users look for when they want to do a full-text search. ```jsx -import { Filter, SearchInput, TextInput } from 'react-admin'; +import { SearchInput, TextInput } from 'react-admin'; -const PostFilter = props => ( - - - -); +const postFilters = [ + +]; ``` In the example given above, the `q` filter triggers a full-text search on all fields. It's your responsibility to implement the full-text filtering capabilities in your `dataProvider`, or in your API. @@ -1001,8 +984,9 @@ In the example given above, the `q` filter triggers a full-text search on all fi Users usually dislike using their keyboard to filter a list (especially on mobile). A good way to satisfy this user requirement is to turn filters into *quick filter*. A Quick filter is a filter with a non-editable `defaultValue`. Users can only enable or disable them. Here is how to implement a generic `` component: + ```jsx -import { Filter, SearchInput } from 'react-admin'; +import { SearchInput } from 'react-admin'; import { makeStyles, Chip } from '@material-ui/core'; const useQuickFilterStyles = makeStyles(theme => ({ @@ -1016,14 +1000,12 @@ const QuickFilter = ({ label }) => { return ; }; -const PostFilter = props => ( - - - - - - -); +const postFilters = [ + , + , + , + , +]; ``` **Tip**: It's currently not possible to use two quick filters for the same source. @@ -1032,7 +1014,7 @@ const PostFilter = props => ( ![Filter Sidebar](./img/filter-sidebar.gif) -An alternative UI to the `` 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 ``. +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 ``. #### Basic usage @@ -1196,7 +1178,7 @@ const CustomerList = props => ( ) ``` -**Tip**: The `` Sidebar is not a good UI for small screens. You can choose to hide it on small screens (as in the previous example). A good tradeoff is to use `` on large screens, and the `` Button/Form combo on Mobile. +**Tip**: The `` Sidebar is not a good UI for small screens. You can choose to hide it on small screens (as in the previous example). A good tradeoff is to use `` on large screens, and the Filter Button/Form combo on Mobile. #### Live Search @@ -1228,7 +1210,7 @@ const FilterSidebar = () => ( [![Saved Queries in FilterList](https://marmelab.com/ra-enterprise/modules/assets/ra-preferences-SavedQueriesList.gif)](https://marmelab.com/ra-enterprise/modules/assets/ra-preferences-SavedQueriesList.gif) -Saved Queries are an [Enterprise Edition](https://marmelab.com/ra-enterprise) feature letting users save a combination of filters and sort parameters into a new, personal filter. Saved queries persist between sessions, so users can find their custom queries even after closing and reopening the admin. Saved queries are available both for the `` Button/Form combo and for the `` Sidebar: +Saved Queries are an [Enterprise Edition](https://marmelab.com/ra-enterprise) feature letting users save a combination of filters and sort parameters into a new, personal filter. Saved queries persist between sessions, so users can find their custom queries even after closing and reopening the admin. Saved queries are available both for the Filter Button/Form combo and for the `` Sidebar: - `` is a drop-in replacement for react-admin's `` component @@ -1319,16 +1301,17 @@ For mode details about Saved Queries, check the [`ra-preferences` module](https: ![Filters with submit button](./img/filter_with_submit.gif) -If neither the `` button/form combo or the `` sidebar match your need, you can always build your own. React-admin provides shortcuts to facilitate the development of custom filters. - +If neither the Filter button/form combo or the `` sidebar match your need, you can always build your own. React-admin provides shortcuts to facilitate the development of custom filters. For instance, by default, the filter button/form combo doesn't provide a submit button, and submits automatically after the user has finished interacting with the form. This provides a smooth user experience, but for some APIs, it can cause too many calls. -In that case, the solution is to process the filter when users click on a submit button, rather than when they type values in form inputs. React-admin doesn't provide any component for that, but it's a good opportunity to illustrate the internals of the filter functionality. We'll actually provide an alternative implementation to the `` button/form combo. +In that case, the solution is to process the filter when users click on a submit button, rather than when they type values in form inputs. React-admin doesn't provide any component for that, but it's a good opportunity to illustrate the internals of the filter functionality. We'll actually provide an alternative implementation to the Filter button/form combo. + +To create a custom filter UI, we'll have to override the default List Actions component, which will contain both a Filter Button and a Filetr Form, interacting with the List filters via the ListContext. #### Filter Callbacks -The new filter element can use the `useListContext()` hook to interact with the URI query parameter more easily. The hook returns the following constants: +The new element can use the `useListContext()` hook to interact with the URI query parameter more easily. The hook returns the following constants: - `filterValues`: Value of the filters based on the URI, e.g. `{"commentable":true,"q":"lorem "}` - `setFilters()`: Callback to set the filter values, e.g. `setFilters({"commentable":true})` @@ -1336,25 +1319,11 @@ The new filter element can use the `useListContext()` hook to interact with the - `showFilter()`: Callback to display an additional filter in the form, e.g. `showFilter('views')` - `hideFilter()`: Callback to hide a filter in the form, e.g. `hideFilter('title')` -Let's use this knowledge to write a custom `` component that filters on submit. - -#### Double Rendering - -As explained earlier, `` clones the element passed as `filters` prop twice - once to display the filter *button*, and once to display the filter *form*. So first, let's create a `` component rendering either a button or a form depending on the `context`: - -```jsx -const PostFilter = props => { - return props.context === "button" ? ( - - ) : ( - - ); -}; -``` +Let's use this knowledge to write a custom `` component that filters on submit. #### Custom Filter Button -The `` simply shows the filter form on click. We'll take advantage of the `showFilter` function: +The `` shows the filter form on click. We'll take advantage of the `showFilter` function: ```jsx import { useListContext } from 'react-admin'; @@ -1378,9 +1347,9 @@ const PostFilterButton = () => { Normally, `showFilter()` adds one input to the `displayedFilters` list. As the filter form will be entirely hidden or shown, we use `showFilter()` with a virtual "main" input, which represents the entire form. -#### Custom Form Component +#### Custom Filter Form -Next is the form component, based on `react-final-form`. The form inputs appear directly in the form, and the form submission triggers the `setFilters()` callback passed as parameter: +Next is the filter form component, displayed only when the "main" filter is displayed (i.e. when a user has clicked the filter button). The form inputs appear directly in the form, and the form submission triggers the `setFilters()` callback passed as parameter. We'll use `react-final-form` to handle the form state: {% raw %} ```jsx @@ -1390,88 +1359,102 @@ import { Box, Button, InputAdornment } from '@material-ui/core'; import SearchIcon from '@material-ui/icons/Search'; import { TextInput, NullableBooleanInput, useListContext } from 'react-admin'; -const PostFilterForm = ({ open }) => { - const { - displayedFilters, - filterValues, - setFilters, - hideFilter, - } = useListContext(); - - if (!displayedFilters.main) return null; - - const onSubmit = values => { - if (Object.keys(values).length > 0) { - setFilters(values); - } else { - hideFilter("main"); - } - }; - - const resetFilter = () => { - setFilters({}, []); - }; - - return ( -
- - {({ handleSubmit }) => ( - - - - - {/* Full-text search filter. We don't use to force a large form input */} - - - - ) - }} - /> - - - {/* Commentable filter */} - - - - - - - - - - - )} - -
- ); +const PostFilterForm = () => { + const { + displayedFilters, + filterValues, + setFilters, + hideFilter + } = useListContext(); + + if (!displayedFilters.main) return null; + + const onSubmit = (values) => { + if (Object.keys(values).length > 0) { + setFilters(values); + } else { + hideFilter("main"); + } + }; + + const resetFilter = () => { + setFilters({}, []); + }; + + return ( +
+
+ {({ handleSubmit }) => ( + + + + {/* Full-text search filter. We don't use to force a large form input */} + + + + ) + }} + /> + + + {/* Commentable filter */} + + + + + + + + + +
+ )} + +
+ ); }; ``` {% endraw %} -#### Using The Custom Form +#### Using The Custom Filters in The List Actions -To finish, we pass the `` component to the `` component using the `filters` prop: +To finish, create a `` component and pass it to the `` component using the `actions` prop: ```jsx +import { TopToolbar, ExportButton } from 'react-admin'; +import { Box } from '@material-ui/core'; + +const ListActions = () => ( + + + + + + + +); + export const PostList = (props) => ( - }> + }> ... ); ``` -You can use a similar approach to customize the list filter completely, e.g. to display the filters in a sidebar, or as a line in the datagrid, etc. +**Tip**: No need to pass any `filters` to the list anymore, as the `` component will display them. + +You can use a similar approach to offer alternative User Experiences for data filtering, e.g. to display the filters as a line in the datagrid headers. ### Global Search @@ -1951,7 +1934,7 @@ The `` component accepts a subset of the props accepted by `` - The List components (``, ``, ``) take care of fetching the data, and put that data in a context called `ListContext` so that it's available for their descendants. This context also stores filters, pagination, sort state, and provides callbacks to update them. -Any component can grab information from the `ListContext` using the `useListContext` hook. As a matter of fact, react-admin's ``, ``, and `` components all use the `useListContext` hook. Here is what it returns: +Any component can grab information from the `ListContext` using the `useListContext` hook. As a matter of fact, react-admin's ``, ``, and `` components all use the `useListContext` hook. Here is what it returns: ```jsx const { @@ -2835,23 +2818,18 @@ Before rendering the `List`, react-admin calls the `authProvider.getPermissions( {% raw %} ```jsx -const UserFilter = ({ permissions, ...props }) => - - - - {permissions === 'admin' ? : null} - ; +const getUserFilters = (permissions) => ([ + , + , + permissions === 'admin' ? : null, +].filter(filter => filter !== null))); export const UserList = ({ permissions, ...props }) => { const isSmall = useMediaQuery(theme => theme.breakpoints.down('sm')); return ( } + filters={getUserFilters(permissions)} sort={{ field: 'name', order: 'ASC' }} > {isSmall ? ( diff --git a/docs/Tutorial.md b/docs/Tutorial.md index fe51be2784e..da92ae28e1a 100644 --- a/docs/Tutorial.md +++ b/docs/Tutorial.md @@ -632,23 +632,21 @@ export const PostEdit = props => ( Let's get back to the post list for a minute. It offers sorting and pagination, but one feature is missing: the ability to search content. -React-admin can use Input components to create a multi-criteria search engine in the list view. First, create a `` component just like you would write a `` component, using input components as children. Then, add it to the list using the `filters` prop: +React-admin can use Input components to create a multi-criteria search engine in the list view. Pass an array of such Input components to the List `filters` prop to enable filtering: ```jsx // in src/posts.js -import { Filter, ReferenceInput, SelectInput, TextInput, List } from 'react-admin'; - -const PostFilter = (props) => ( - - - - - - -); +import { ReferenceInput, SelectInput, TextInput, List } from 'react-admin'; + +const postFilters = [ + , + + + , +]; export const PostList = (props) => ( - } {...props}> + // ... ); diff --git a/packages/ra-core/src/controller/ListContext.tsx b/packages/ra-core/src/controller/ListContext.tsx index 985ea740d34..45e3eb8c1f8 100644 --- a/packages/ra-core/src/controller/ListContext.tsx +++ b/packages/ra-core/src/controller/ListContext.tsx @@ -5,7 +5,7 @@ import { ListControllerProps } from './useListController'; * Context to store the result of the useListController() hook. * * Use the useListContext() hook to read the context. That's what many - * List components do in react-admin (e.g. , , ). + * List components do in react-admin (e.g. , , ). * * @typedef {Object} ListControllerProps * @prop {Object} data an id-based dictionary of the list data, e.g. { 123: { id: 123, title: 'hello world' }, 456: { ... } } diff --git a/packages/ra-core/src/controller/ListFilterContext.tsx b/packages/ra-core/src/controller/ListFilterContext.tsx index 0911aa98689..be4a422cc1f 100644 --- a/packages/ra-core/src/controller/ListFilterContext.tsx +++ b/packages/ra-core/src/controller/ListFilterContext.tsx @@ -6,7 +6,7 @@ import { ListControllerProps } from './useListController'; * Context to store the filter part of the useListController() result. * * Use the useListFilterContext() hook to read the context. That's what many - * List components do in react-admin (e.g. , ). + * List components do in react-admin (e.g. , ). * * @typedef {Object} ListFilterContextValue * @prop {Object} filterValues a dictionary of filter values, e.g. { title: 'lorem', nationality: 'fr' } From ca7ab1968bb10d35317efc624698940c7c38955c Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Tue, 22 Jun 2021 18:10:01 +0200 Subject: [PATCH 3/6] Update docs and examples --- docs/Authentication.md | 22 ++---- docs/Inputs.md | 12 ++- docs/Theming.md | 73 +++++------------- docs/img/list_with_customized_css.png | Bin 31428 -> 95481 bytes examples/crm/src/deals/DealList.tsx | 24 +++--- examples/demo/src/invoices/InvoiceList.tsx | 14 ++-- examples/demo/src/orders/OrderList.tsx | 38 ++++----- examples/demo/src/products/ProductList.tsx | 63 +++++++-------- examples/demo/src/reviews/ReviewFilter.tsx | 51 ------------ examples/demo/src/reviews/ReviewList.tsx | 4 +- examples/demo/src/reviews/reviewFilters.tsx | 37 +++++++++ examples/demo/src/visitors/VisitorList.tsx | 20 ++--- examples/simple/src/comments/CommentList.tsx | 20 ++--- .../simple/src/users/UserEditEmbedded.tsx | 2 +- examples/simple/src/users/UserList.tsx | 20 +++-- examples/tutorial/src/posts.js | 22 ++---- packages/ra-ui-materialui/src/list/List.tsx | 14 ++-- .../src/list/filter/Filter.tsx | 19 +++++ 18 files changed, 191 insertions(+), 264 deletions(-) delete mode 100644 examples/demo/src/reviews/ReviewFilter.tsx create mode 100644 examples/demo/src/reviews/reviewFilters.tsx diff --git a/docs/Authentication.md b/docs/Authentication.md index af92d28116e..192f6e8f225 100644 --- a/docs/Authentication.md +++ b/docs/Authentication.md @@ -995,25 +995,17 @@ export const UserEdit = ({ permissions, ...props }) => ``` {% endraw %} -What about the `List` view, the `Datagrid`, `SimpleList` and `Filter` components? It works there, too. And in the next example, the `permissions` prop is passed down to a custom `filters` component. +What about the `List` view, the `Datagrid`, `SimpleList`? It works there, too. And in the next example, the `permissions` prop is passed down to a custom `filters` selector. ```jsx -const UserFilter = ({ permissions, ...props }) => - - - - {permissions === 'admin' && } - ; +const getUserFilters = (permissions) => ([ + , + , + permissions === 'admin' ? : null, +].filter(filter => filter !== null))); export const UserList = ({ permissions, ...props }) => - } - > + diff --git a/docs/Inputs.md b/docs/Inputs.md index e64e39563f4..a3a69740223 100644 --- a/docs/Inputs.md +++ b/docs/Inputs.md @@ -2048,13 +2048,11 @@ import { ReferenceInput, SelectInput } from 'react-admin'; **Tip**: `allowEmpty` is set by default for all Input components passed as ``: ```jsx -const CommentFilter = (props) => ( - - // no need for allowEmpty - - - -); +const commentFilters = [ + // no need for allowEmpty + + +]; ``` You can tweak how this component fetches the possible values using the `perPage`, `sort`, and `filter` props. diff --git a/docs/Theming.md b/docs/Theming.md index ce37aa2d51a..bc65811e214 100644 --- a/docs/Theming.md +++ b/docs/Theming.md @@ -46,7 +46,7 @@ export const ProductList = (props) => ( For some components, you may want to override not only the root component style, but also the style of components inside the root. In this case, the `className` property isn't enough. You can take advantage of the `classes` property to customize the classes that the component uses internally. -Here is an example using the `classes` property of the `Filter` and `List` components: +Here is an example using the `classes` property of the `` component: {% raw %} ```jsx @@ -55,76 +55,39 @@ import { BooleanField, Datagrid, DateField, - DateInput, EditButton, - Filter, List, - NullableBooleanInput, NumberField, - TextInput, + TextField, + ShowButton, } from 'react-admin'; import Icon from '@material-ui/icons/Person'; import { makeStyles } from '@material-ui/core/styles'; export const VisitorIcon = Icon; -// The Filter component supports the `form` and `button` CSS classes. Here we override the `form` class -const useFilterStyles = makeStyles({ - form: { - backgroundColor: 'Lavender', - }, -}); - -const VisitorFilter = props => { - const classes = useFilterStyles(); - return ( - - - - - - - ); -}; - -// The `List` component supports the `root`, `header`, `actions` and `noResults` CSS classes. Here we override the `header` and `actions` classes -const useListStyles = makeStyles({ - actions: { +// The `Datagrid` component uses makeStyles, and supports overriding styles through the `classes` property +const useStyles = makeStyles({ + table: { backgroundColor: 'Lavender', }, - header: { - backgroundColor: 'Lavender', + headerCell: { + backgroundColor: 'MistyRose', }, }); -export const VisitorList = props => { - const classes = useListStyles(); +export const PostList = props => { + const classes = useStyles(); return ( - } - sort={{ field: 'last_seen', order: 'DESC' }} - perPage={25} - > + - - - - - + + + + + + ) @@ -136,7 +99,7 @@ This example results in: ![Visitor List with customized CSS classes](./img/list_with_customized_css.png) -Take a look at a component documentation and source code to know which classes are available for styling. For instance, you can have a look at the [Datagrid CSS documentation](./List.md#the-datagrid-component). +Take a look at a component documentation and source code to know which classes are available for styling. For instance, you can have a look at the [Datagrid CSS documentation](./List.md##css-api-1). If you need more control over the HTML code, you can also create your own [Field](./Fields.md#writing-your-own-field-component) and [Input](./Inputs.md#writing-your-own-input-component) components. diff --git a/docs/img/list_with_customized_css.png b/docs/img/list_with_customized_css.png index b46c06e398f74c3a738908e822a788c135e95bc4..ab3c85eb627a3d427cb0f68eda85cff5212c3028 100644 GIT binary patch literal 95481 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
Y(2IzTnra;a)+2V44;-Vi%$*4O38sbZd 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

E{k`f_wc+pK&X}DZ6_P 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 { {...props} perPage={100} sort={{ field: 'index', order: 'ASC' }} - filters={} + filters={dealFilters} filterDefaultValues={{ sales_id: identity && identity?.id }} actions={} pagination={false} @@ -49,24 +49,22 @@ export const DealList = (props: ListProps) => { ) : null; }; -const DealFilters = (props: any) => ( - - - - - -); +const dealFilters = [ + , + , + , +]; const useActionStyles = makeStyles(theme => ({ createButton: { marginLeft: theme.spacing(2), }, })); -const DealActions = (props: any) => { +const DealActions = () => { const classes = useActionStyles(); return ( - + ) => ( - - - - -); +const listFilters = [ + , + , +]; const useStyles = makeStyles(theme => ({ hiddenOnSmallScreens: { @@ -39,7 +35,7 @@ const InvoiceList: FC = props => { return ( } + filters={listFilters} perPage={25} sort={{ field: 'date', order: 'desc' }} > diff --git a/examples/demo/src/orders/OrderList.tsx b/examples/demo/src/orders/OrderList.tsx index 1724092ad89..ebb9d006c97 100644 --- a/examples/demo/src/orders/OrderList.tsx +++ b/examples/demo/src/orders/OrderList.tsx @@ -7,8 +7,6 @@ import { DatagridProps, DateField, DateInput, - Filter, - FilterProps, Identifier, List, ListContextProvider, @@ -33,24 +31,22 @@ import AddressField from '../visitors/AddressField'; import MobileGrid from './MobileGrid'; import { Customer } from '../types'; -const OrderFilter: FC> = props => ( - - - - - choice.id // the empty choice is { id: '' } - ? `${choice.first_name} ${choice.last_name}` - : '' - } - /> - - - - - - -); +const orderFilters = [ + , + + + choice.id // the empty choice is { id: '' } + ? `${choice.first_name} ${choice.last_name}` + : '' + } + /> + , + , + , + , + , +]; const useDatagridStyles = makeStyles({ total: { fontWeight: 'bold' }, @@ -269,7 +265,7 @@ const OrderList: FC = props => ( filterDefaultValues={{ status: 'ordered' }} sort={{ field: 'date', order: 'DESC' }} perPage={25} - filters={} + filters={orderFilters} > diff --git a/examples/demo/src/products/ProductList.tsx b/examples/demo/src/products/ProductList.tsx index 4223d4d6a75..1361ca103b5 100644 --- a/examples/demo/src/products/ProductList.tsx +++ b/examples/demo/src/products/ProductList.tsx @@ -5,8 +5,9 @@ import { makeStyles } from '@material-ui/core/styles'; import { CreateButton, ExportButton, - Filter, - FilterProps, + FilterButton, + FilterForm, + FilterContext, InputProps, ListBase, ListProps, @@ -27,7 +28,7 @@ import Aside from './Aside'; const useQuickFilterStyles = makeStyles(theme => ({ root: { - marginBottom: theme.spacing(3), + marginBottom: theme.spacing(1), }, })); @@ -37,31 +38,29 @@ const QuickFilter: FC = ({ label }) => { return ; }; -export const ProductFilter: FC> = props => ( - - - - - - - - - - - -); +export const productFilters = [ + , + + + , + , + , + , + , + , +]; const ListActions: FC = ({ isSmall }) => ( - {isSmall && } + {isSmall && } @@ -86,12 +85,14 @@ const ProductListView: FC<{ isSmall: boolean }> = ({ isSmall }) => { return ( <> - <ListActions isSmall={isSmall} /> - {isSmall && ( - <Box m={1}> - <ProductFilter context="form" /> - </Box> - )} + <FilterContext.Provider value={productFilters}> + <ListActions isSmall={isSmall} /> + {isSmall && ( + <Box m={1}> + <FilterForm /> + </Box> + )} + </FilterContext.Provider> <Box display="flex"> <Aside /> <Box width={isSmall ? 'auto' : 'calc(100% - 16em)'}> diff --git a/examples/demo/src/reviews/ReviewFilter.tsx b/examples/demo/src/reviews/ReviewFilter.tsx deleted file mode 100644 index 35f0f5b7bc8..00000000000 --- a/examples/demo/src/reviews/ReviewFilter.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import * as React from 'react'; -import { FC } from 'react'; -import { - AutocompleteInput, - DateInput, - Filter, - ReferenceInput, - SearchInput, - SelectInput, - FilterProps, -} from 'react-admin'; -import { makeStyles } from '@material-ui/core/styles'; -import { Customer } from '../types'; - -const useFilterStyles = makeStyles({ - status: { width: 150 }, -}); - -const ReviewFilter: FC<Omit<FilterProps, 'children'>> = props => { - const classes = useFilterStyles(); - return ( - <Filter {...props}> - <SearchInput source="q" alwaysOn /> - <SelectInput - source="status" - choices={[ - { id: 'accepted', name: 'Accepted' }, - { id: 'pending', name: 'Pending' }, - { id: 'rejected', name: 'Rejected' }, - ]} - className={classes.status} - /> - <ReferenceInput source="customer_id" reference="customers"> - <AutocompleteInput - optionText={(choice?: Customer) => - choice?.id // the empty choice is { id: '' } - ? `${choice.first_name} ${choice.last_name}` - : '' - } - /> - </ReferenceInput> - <ReferenceInput source="product_id" reference="products"> - <AutocompleteInput optionText="reference" /> - </ReferenceInput> - <DateInput source="date_gte" /> - <DateInput source="date_lte" /> - </Filter> - ); -}; - -export default ReviewFilter; diff --git a/examples/demo/src/reviews/ReviewList.tsx b/examples/demo/src/reviews/ReviewList.tsx index 7222381096b..fd9a3181726 100644 --- a/examples/demo/src/reviews/ReviewList.tsx +++ b/examples/demo/src/reviews/ReviewList.tsx @@ -15,7 +15,7 @@ import BulkAcceptButton from './BulkAcceptButton'; import BulkRejectButton from './BulkRejectButton'; import ReviewListMobile from './ReviewListMobile'; import ReviewListDesktop from './ReviewListDesktop'; -import ReviewFilter from './ReviewFilter'; +import reviewFilters from './reviewFilters'; import ReviewEdit from './ReviewEdit'; const ReviewsBulkActionButtons = (props: BulkActionProps) => ( @@ -74,7 +74,7 @@ const ReviewList: FC<ListProps> = props => { [classes.listWithDrawer]: isMatch, })} bulkActionButtons={<ReviewsBulkActionButtons />} - filters={<ReviewFilter />} + filters={reviewFilters} perPage={25} sort={{ field: 'date', order: 'DESC' }} > diff --git a/examples/demo/src/reviews/reviewFilters.tsx b/examples/demo/src/reviews/reviewFilters.tsx new file mode 100644 index 00000000000..4e725c27f27 --- /dev/null +++ b/examples/demo/src/reviews/reviewFilters.tsx @@ -0,0 +1,37 @@ +import * as React from 'react'; +import { + AutocompleteInput, + DateInput, + ReferenceInput, + SearchInput, + SelectInput, +} from 'react-admin'; +import { Customer } from '../types'; + +const reviewFilters = [ + <SearchInput source="q" alwaysOn />, + <SelectInput + source="status" + choices={[ + { id: 'accepted', name: 'Accepted' }, + { id: 'pending', name: 'Pending' }, + { id: 'rejected', name: 'Rejected' }, + ]} + />, + <ReferenceInput source="customer_id" reference="customers"> + <AutocompleteInput + optionText={(choice?: Customer) => + choice?.id // the empty choice is { id: '' } + ? `${choice.first_name} ${choice.last_name}` + : '' + } + /> + </ReferenceInput>, + <ReferenceInput source="product_id" reference="products"> + <AutocompleteInput optionText="reference" /> + </ReferenceInput>, + <DateInput source="date_gte" />, + <DateInput source="date_lte" />, +]; + +export default reviewFilters; diff --git a/examples/demo/src/visitors/VisitorList.tsx b/examples/demo/src/visitors/VisitorList.tsx index 2325da84d92..c3ff4969832 100644 --- a/examples/demo/src/visitors/VisitorList.tsx +++ b/examples/demo/src/visitors/VisitorList.tsx @@ -4,8 +4,6 @@ import { Datagrid, DateField, DateInput, - Filter, - FilterProps, List, ListProps, NullableBooleanInput, @@ -23,15 +21,13 @@ import MobileGrid from './MobileGrid'; import VisitorListAside from './VisitorListAside'; import { ReactElement } from 'react'; -const VisitorFilter = (props: Omit<FilterProps, 'children'>) => ( - <Filter {...props}> - <SearchInput source="q" alwaysOn /> - <DateInput source="last_seen_gte" /> - <NullableBooleanInput source="has_ordered" /> - <NullableBooleanInput source="has_newsletter" defaultValue /> - <SegmentInput /> - </Filter> -); +const visitorFilters = [ + <SearchInput source="q" alwaysOn />, + <DateInput source="last_seen_gte" />, + <NullableBooleanInput source="has_ordered" />, + <NullableBooleanInput source="has_newsletter" defaultValue />, + <SegmentInput />, +]; const useStyles = makeStyles(theme => ({ nb_commands: { color: 'purple' }, @@ -52,7 +48,7 @@ const VisitorList = (props: ListProps): ReactElement => { return ( <List {...props} - filters={isSmall ? <VisitorFilter /> : undefined} + filters={isSmall ? visitorFilters : undefined} sort={{ field: 'last_seen', order: 'DESC' }} perPage={25} aside={<VisitorListAside />} diff --git a/examples/simple/src/comments/CommentList.tsx b/examples/simple/src/comments/CommentList.tsx index a2d54edaa74..41eafc43f3d 100644 --- a/examples/simple/src/comments/CommentList.tsx +++ b/examples/simple/src/comments/CommentList.tsx @@ -22,7 +22,6 @@ import { ListActions, DateField, EditButton, - Filter, PaginationLimit, ReferenceField, ReferenceInput, @@ -37,14 +36,12 @@ import { useTranslate, } from 'react-admin'; // eslint-disable-line import/no-unresolved -const CommentFilter = props => ( - <Filter {...props}> - <SearchInput source="q" alwaysOn /> - <ReferenceInput source="post_id" reference="posts"> - <SelectInput optionText="title" /> - </ReferenceInput> - </Filter> -); +const commentFilters = [ + <SearchInput source="q" alwaysOn />, + <ReferenceInput source="post_id" reference="posts"> + <SelectInput optionText="title" /> + </ReferenceInput>, +]; const exporter = (records, fetchRelatedRecords) => fetchRelatedRecords(records, 'post_id', 'posts').then(posts => { @@ -214,10 +211,7 @@ const ListView = () => { return ( <> <Title defaultTitle={defaultTitle} /> - <ListToolbar - filters={<CommentFilter />} - actions={<ListActions />} - /> + <ListToolbar filters={commentFilters} actions={<ListActions />} /> {isSmall ? <CommentMobileList /> : <CommentGrid />} <CommentPagination /> </> diff --git a/examples/simple/src/users/UserEditEmbedded.tsx b/examples/simple/src/users/UserEditEmbedded.tsx index 1228a8c9ff4..7296f43c189 100644 --- a/examples/simple/src/users/UserEditEmbedded.tsx +++ b/examples/simple/src/users/UserEditEmbedded.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { Edit, SimpleForm, TextInput, required } from 'react-admin'; -const UserEditEmbedded = ({ permissions, ...props }) => ( +const UserEditEmbedded = props => ( /* Passing " " as title disables the custom title */ <Edit title=" " {...props}> <SimpleForm initialValues={{ role: 'user' }}> diff --git a/examples/simple/src/users/UserList.tsx b/examples/simple/src/users/UserList.tsx index 8675cbbfbb3..e38d79b52a6 100644 --- a/examples/simple/src/users/UserList.tsx +++ b/examples/simple/src/users/UserList.tsx @@ -1,12 +1,11 @@ /* eslint react/jsx-key: off */ import PeopleIcon from '@material-ui/icons/People'; import memoize from 'lodash/memoize'; -import { useMediaQuery } from '@material-ui/core'; +import { useMediaQuery, Theme } from '@material-ui/core'; import * as React from 'react'; import { BulkDeleteWithConfirmButton, Datagrid, - Filter, List, SearchInput, SimpleList, @@ -18,13 +17,12 @@ import Aside from './Aside'; import UserEditEmbedded from './UserEditEmbedded'; export const UserIcon = PeopleIcon; -const UserFilter = ({ permissions, ...props }) => ( - <Filter {...props}> - <SearchInput source="q" alwaysOn /> - <TextInput source="name" /> - {permissions === 'admin' ? <TextInput source="role" /> : null} - </Filter> -); +const getUserFilters = permissions => + [ + <SearchInput source="q" alwaysOn />, + <TextInput source="name" />, + permissions === 'admin' ? <TextInput source="role" /> : null, + ].filter(filter => filter !== null); const UserBulkActionButtons = props => ( <BulkDeleteWithConfirmButton {...props} /> @@ -39,13 +37,13 @@ const rowClick = memoize(permissions => (id, basePath, record) => { const UserList = ({ permissions, ...props }) => ( <List {...props} - filters={<UserFilter permissions={permissions} />} + filters={getUserFilters(permissions)} filterDefaultValues={{ role: 'user' }} sort={{ field: 'name', order: 'ASC' }} aside={<Aside />} bulkActionButtons={<UserBulkActionButtons />} > - {useMediaQuery(theme => theme.breakpoints.down('sm')) ? ( + {useMediaQuery((theme: Theme) => theme.breakpoints.down('sm')) ? ( <SimpleList primaryText={record => record.name} secondaryText={record => diff --git a/examples/tutorial/src/posts.js b/examples/tutorial/src/posts.js index 74605950703..183f574823b 100644 --- a/examples/tutorial/src/posts.js +++ b/examples/tutorial/src/posts.js @@ -16,25 +16,17 @@ import { SelectInput, SimpleForm, TextInput, - Filter, } from 'react-admin'; -const PostFilter = props => ( - <Filter {...props}> - <TextInput label="Search" source="q" alwaysOn /> - <ReferenceInput - label="User" - source="userId" - reference="users" - allowEmpty - > - <SelectInput optionText="name" /> - </ReferenceInput> - </Filter> -); +const postFilters = [ + <TextInput source="q" label="Search" alwaysOn />, + <ReferenceInput source="userId" label="User" reference="users" allowEmpty> + <SelectInput optionText="name" /> + </ReferenceInput>, +]; export const PostList = props => ( - <List {...props} filters={<PostFilter />}> + <List {...props} filters={postFilters}> <Datagrid> <TextField source="id" /> <ReferenceField label="User" source="userId" reference="users"> diff --git a/packages/ra-ui-materialui/src/list/List.tsx b/packages/ra-ui-materialui/src/list/List.tsx index 67768ec5c3f..537b7b35e60 100644 --- a/packages/ra-ui-materialui/src/list/List.tsx +++ b/packages/ra-ui-materialui/src/list/List.tsx @@ -32,7 +32,7 @@ import { ListProps } from '../types'; * - exporter * - filter (the permanent filter to apply to the query) * - filterDefaultValues (the default values for `alwaysOn` filters) - * - filters (a React component used to display the filter form) + * - filters (a list of inputs used to display the filter button/form combo) * - pagination * - perPage * - sort @@ -41,18 +41,16 @@ import { ListProps } from '../types'; * * @example * - * const PostFilter = (props) => ( - * <Filter {...props}> - * <TextInput label="Search" source="q" alwaysOn /> - * <TextInput label="Title" source="title" /> - * </Filter> - * ); + * const postFilters = [ + * <TextInput label="Search" source="q" alwaysOn />, + * <TextInput label="Title" source="title" /> + * ]; * export const PostList = (props) => ( * <List {...props} * title="List of posts" * sort={{ field: 'published_at' }} * filter={{ is_published: true }} - * filters={PostFilter} + * filters={postFilters} * > * <Datagrid> * <TextField source="id" /> diff --git a/packages/ra-ui-materialui/src/list/filter/Filter.tsx b/packages/ra-ui-materialui/src/list/filter/Filter.tsx index a2977c41638..6c33e0cd3c4 100644 --- a/packages/ra-ui-materialui/src/list/filter/Filter.tsx +++ b/packages/ra-ui-materialui/src/list/filter/Filter.tsx @@ -23,6 +23,25 @@ export interface FilterProps { variant?: string; } +/** + * Filter button/form combo + * + * @example + * + * const PostFilter = (props) => ( + * <Filter {...props}> + * <TextInput label="Search" source="q" alwaysOn /> + * <TextInput label="Title" source="title" defaultValue="Hello, World!" /> + * </Filter> + * ); + * + * export const PostList = (props) => ( + * <List {...props} filters={<PostFilter />}> + * ... + * </List> + * ); + * + */ const Filter: FC<FilterProps> = props => { const classes = useStyles(props); const { From 0bb64b68a28af3647c97b16486904095b1014530 Mon Sep 17 00:00:00 2001 From: fzaninotto <fzaninotto@gmail.com> Date: Tue, 22 Jun 2021 18:16:55 +0200 Subject: [PATCH 4/6] Fix tests --- .../ra-ui-materialui/src/list/filter/FilterForm.spec.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/ra-ui-materialui/src/list/filter/FilterForm.spec.tsx b/packages/ra-ui-materialui/src/list/filter/FilterForm.spec.tsx index acb772f2552..3381353b830 100644 --- a/packages/ra-ui-materialui/src/list/filter/FilterForm.spec.tsx +++ b/packages/ra-ui-materialui/src/list/filter/FilterForm.spec.tsx @@ -57,7 +57,10 @@ describe('<FilterForm />', () => { fireEvent.change(queryByLabelText('Title'), { target: { value: 'foo' }, }); - expect(setFilters).toHaveBeenCalledWith({ title: 'foo' }); + expect(setFilters).toHaveBeenCalledWith( + { title: 'foo' }, + { title: true } + ); }); it('should not change the filter when the user updates an input with an invalid value', () => { @@ -211,7 +214,7 @@ describe('<FilterForm />', () => { ]; expect( - mergeInitialValuesWithDefaultValues({ initialValues, filters }) + mergeInitialValuesWithDefaultValues(initialValues, filters) ).toEqual({ title: 'initial title', url: 'default url', From 4a7f3b00d37631504474d53be05da058a1a6fc2c Mon Sep 17 00:00:00 2001 From: fzaninotto <fzaninotto@gmail.com> Date: Tue, 22 Jun 2021 19:29:18 +0200 Subject: [PATCH 5/6] Add junit tests --- .../ra-ui-materialui/src/list/List.spec.tsx | 79 ++++++++++++++++++- .../src/list/filter/FilterForm.tsx | 5 +- 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/packages/ra-ui-materialui/src/list/List.spec.tsx b/packages/ra-ui-materialui/src/list/List.spec.tsx index 7b3136e6fb0..34dc32708bc 100644 --- a/packages/ra-ui-materialui/src/list/List.spec.tsx +++ b/packages/ra-ui-materialui/src/list/List.spec.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import expect from 'expect'; -import { waitFor } from '@testing-library/react'; -import { DataProviderContext } from 'ra-core'; +import { waitFor, fireEvent } from '@testing-library/react'; +import { DataProviderContext, ResourceContextProvider } from 'ra-core'; import { renderWithRedux } from 'ra-test'; import { ThemeProvider } from '@material-ui/styles'; import { createMuiTheme } from '@material-ui/core/styles'; @@ -9,6 +9,8 @@ import { MemoryRouter } from 'react-router-dom'; import defaultTheme from '../defaultTheme'; import List from './List'; +import { Filter } from './filter'; +import { TextInput } from '../input'; const theme = createMuiTheme(defaultTheme); @@ -153,4 +155,77 @@ describe('<List />', () => { expect(queryAllByText('resources.posts.empty')).toHaveLength(1); }); }); + + it('should render a filter button/form combo when passed an element in filters', async () => { + const DummyFilters = props => ( + <Filter {...props}> + <TextInput source="foo" alwaysOn /> + <TextInput source="bar" /> + </Filter> + ); + const Dummy = () => <div>Dummy</div>; + const dataProvider = { + getList: jest.fn(() => + Promise.resolve({ data: [{ id: 0 }], total: 1 }) + ), + } as any; + const { getByText, queryAllByLabelText } = renderWithRedux( + <ThemeProvider theme={theme}> + <DataProviderContext.Provider value={dataProvider}> + <List filters={<DummyFilters />} {...defaultProps}> + <Dummy /> + </List> + </DataProviderContext.Provider> + </ThemeProvider>, + defaultStateForList + ); + await waitFor(() => new Promise(resolve => setTimeout(resolve, 0))); + expect(queryAllByLabelText('resources.posts.fields.foo')).toHaveLength( + 1 + ); + fireEvent.click(getByText('ra.action.add_filter')); + fireEvent.click(getByText('resources.posts.fields.bar')); + await waitFor(() => { + expect( + queryAllByLabelText('resources.posts.fields.bar') + ).toHaveLength(1); + }); + }); + + it('should render a filter button/form combo when passed an array in filters', async () => { + const dummyFilters = [ + <TextInput source="foo" alwaysOn />, + <TextInput source="bar" />, + ]; + const Dummy = () => <div>Dummy</div>; + const dataProvider = { + getList: jest.fn(() => + Promise.resolve({ data: [{ id: 0 }], total: 1 }) + ), + } as any; + const { getByText, queryAllByLabelText } = renderWithRedux( + // As FilterForm doesn't receive rest parameters, it must grab the resource from the context + <ResourceContextProvider value="posts"> + <ThemeProvider theme={theme}> + <DataProviderContext.Provider value={dataProvider}> + <List filters={dummyFilters} {...defaultProps}> + <Dummy /> + </List> + </DataProviderContext.Provider> + </ThemeProvider> + </ResourceContextProvider>, + defaultStateForList + ); + await waitFor(() => new Promise(resolve => setTimeout(resolve, 0))); + expect(queryAllByLabelText('resources.posts.fields.foo')).toHaveLength( + 1 + ); + fireEvent.click(getByText('ra.action.add_filter')); + fireEvent.click(getByText('resources.posts.fields.bar')); + await waitFor(() => { + expect( + queryAllByLabelText('resources.posts.fields.bar') + ).toHaveLength(1); + }); + }); }); diff --git a/packages/ra-ui-materialui/src/list/filter/FilterForm.tsx b/packages/ra-ui-materialui/src/list/filter/FilterForm.tsx index a9bb3f0d601..5a81947faca 100644 --- a/packages/ra-ui-materialui/src/list/filter/FilterForm.tsx +++ b/packages/ra-ui-materialui/src/list/filter/FilterForm.tsx @@ -7,7 +7,7 @@ import { ReactNode, } from 'react'; import PropTypes from 'prop-types'; -import { useListContext } from 'ra-core'; +import { useListContext, useResourceContext } from 'ra-core'; import { Form, FormRenderProps, FormSpy } from 'react-final-form'; import arrayMutators from 'final-form-arrays'; import classnames from 'classnames'; @@ -23,13 +23,13 @@ export const FilterForm = (props: FilterFormProps) => { const { classes = {}, className, - resource, margin, filters, variant, initialValues, ...rest } = props; + const resource = useResourceContext(props); const { displayedFilters = {}, hideFilter } = useListContext(props); useEffect(() => { filters.forEach((filter: JSX.Element) => { @@ -126,6 +126,7 @@ const sanitizeRestProps = ({ modified, modifiedSinceLastSubmit, pristine, + resource, setFilters, submitError, submitErrors, From 715e42a4ff61901c8c9fe4447bb0a59e6bd1fb32 Mon Sep 17 00:00:00 2001 From: Francois Zaninotto <francois@marmelab.com> Date: Mon, 28 Jun 2021 10:55:58 +0200 Subject: [PATCH 6/6] Update docs/Inputs.md Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com> --- docs/Inputs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Inputs.md b/docs/Inputs.md index a3a69740223..3ef70aa6cf3 100644 --- a/docs/Inputs.md +++ b/docs/Inputs.md @@ -5,7 +5,7 @@ title: "Input Components" # Input Components -An `Input` component displays an input, or a dropdown list, a list of radio buttons, etc. Such components allow to edit a record property, and are common in the `<Edit>`, `<Create>` component, and in the List Filters. +An `Input` component displays an input, or a dropdown list, a list of radio buttons, etc. Such components allow to edit a record property, and are common in the `<Edit>` and `<Create>` components, and in the List Filters. ```jsx // in src/posts.js