diff --git a/UPGRADE.md b/UPGRADE.md index d74197e75cd..b3f981320e9 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1061,6 +1061,47 @@ const CommentGrid = () => { }; ``` +## `currentSort` Renamed To `sort` + +If one of your components displays the curent sort order, it probably uses the injected `currentSort` prop (or reads it from the `ListContext`). This prop has been renamed to `sort` in v4. + +Upgrade your code by replacing `currentSort` with `sort`: + +```diff +import { useListContext } from 'react-admin'; + +const BookListIterator = () => { +- const { data, loading, currentSort } = useListContext(); ++ const { data, isLoading, sort } = useListContext(); + + if (loading) return ; + if (data.length === 0) return

No data

; + + return (<> +-
Books sorted by {currentSort.field}
++
Books sorted by {sort.field}
+ + ); +}; +``` + +The same happens for ``: when used in standalone, it used to accept a `currentSort` prop, but now it only accepts a `sort` prop. + + +```diff +- ++ + + + + + +``` + ## `setSort()` Signature Changed Some react-admin components have access to a `setSort()` callback to sort the current list of items. This callback is also present in the `ListContext`. Its signature has changed: @@ -1074,16 +1115,16 @@ This impacts your code if you built a custom sort component: ```diff const SortButton = () => { - const { currentSort, setSort } = useListContext(); + const { sort, setSort } = useListContext(); const handleChangeSort = (event) => { const field = event.currentTarget.dataset.sort; - setSort( - field, -- field === currentSort.field ? inverseOrder(currentSort.order) : 'ASC', +- field === sort.field ? inverseOrder(sort.order) : 'ASC', - }); + setSort({ + field, -+ order: field === currentSort.field ? inverseOrder(currentSort.order) : 'ASC', ++ order: field === sort.field ? inverseOrder(sort.order) : 'ASC', + }); setAnchorEl(null); }; diff --git a/docs/Datagrid.md b/docs/Datagrid.md index 8c7a0451aee..bfc01d34d35 100644 --- a/docs/Datagrid.md +++ b/docs/Datagrid.md @@ -890,12 +890,12 @@ You can use the `` component to display data that you've fetched yours ```jsx import { useGetList, Datagrid, TextField } from 'react-admin'; -const currentSort = { field: 'id', order: 'DESC' }; +const sort = { field: 'id', order: 'DESC' }; const MyCustomList = () => { const { data, total, isLoading } = useGetList('books', { pagination: { page: 1, perPage: 10 }, - sort: currentSort, + sort, }); return ( @@ -903,7 +903,7 @@ const MyCustomList = () => { data={data} total={total} isLoading={isLoading} - currentSort={currentSort} + sort={sort} bulkActionButtons={false} > @@ -924,12 +924,12 @@ import { TextField } from 'react-admin'; -const currentSort = { field: 'id', order: 'DESC' }; +const sort = { field: 'id', order: 'DESC' }; const MyCustomList = () => { const { data, isLoading } = useGetList('books', { pagination: { page: 1, perPage: 10 }, - sort: currentSort, + sort, }); const listContext = useList({ data, isLoading }); diff --git a/docs/ListTutorial.md b/docs/ListTutorial.md index e3f02d948a4..0060ae239db 100644 --- a/docs/ListTutorial.md +++ b/docs/ListTutorial.md @@ -111,11 +111,11 @@ const BookList = () => { const [filter, setFilter] = useState(''); const [page, setPage] = useState(1); const perPage = 10; - const currentSort = { field: 'id', order: 'ASC' }; + const sort = { field: 'id', order: 'ASC' }; const { data, total, isLoading } = useGetList('books', { filter: { q: filter }, pagination: { page, perPage }, - sort: currentSort, + sort, }); if (isLoading) { return
Loading...
; @@ -132,7 +132,7 @@ const BookList = () => { margin="dense" /> - + @@ -173,11 +173,11 @@ const BookList = () => { const [filter, setFilter] = useState(''); const [page, setPage] = useState(1); const perPage = 10; - const currentSort = { field: 'id', order: 'ASC' }; + const sort = { field: 'id', order: 'ASC' }; const { data, total, isLoading } = useGetList('books', { filter: { q: filter }, pagination: { page, perPage }, - sort: currentSort, + sort, }); if (isLoading) { return
Loading...
; @@ -186,7 +186,7 @@ const BookList = () => { const filterValues = { q: filter }; const setFilters = filters => setFilter(filters.q); return ( - +
<FilterForm filters={filters} /> @@ -534,7 +534,7 @@ const SortByViews = () => ( ## Building a Custom Sort Control -When neither the `<Datagrid>` or the `<SortButton>` fit your UI needs, you have to write a custom sort control. As with custom filters, this boils down to grabbing the required data and callbacks from the `ListContext`. Let's use the `<SortButton>` source as an example usage of `currentSort` and `setSort`: +When neither the `<Datagrid>` or the `<SortButton>` fit your UI needs, you have to write a custom sort control. As with custom filters, this boils down to grabbing the required data and callbacks from the `ListContext`. Let's use the `<SortButton>` source as an example usage of `sort` and `setSort`: ```jsx import * as React from 'react'; @@ -544,9 +544,9 @@ import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'; import { useListSortContext, useTranslate } from 'react-admin'; const SortButton = ({ fields }) => { - // currentSort is an object { field, order } containing the current sort + // sort is an object { field, order } containing the current sort // setSort is a callback ({ field, order }) => void allowing to change the sort field and order - const { currentSort, setSort } = useListSortContext(); + const { sort, setSort } = useListSortContext(); // rely on the translations to display labels like 'Sort by sales descending' const translate = useTranslate(); // open/closed state for dropdown @@ -563,15 +563,15 @@ const SortButton = ({ fields }) => { const field = event.currentTarget.dataset.sort; setSort({ field, - order: field === currentSort.field ? inverseOrder(currentSort.order) : 'ASC' + order: field === sort.field ? inverseOrder(sort.order) : 'ASC' }); setAnchorEl(null); }; // English stranslation is 'Sort by %{field} %{order}' const buttonLabel = translate('ra.sort.sort_by', { - field: translate(`resources.products.fields.${currentSort.field}`), - order: translate(`ra.sort.${currentSort.order}`), + field: translate(`resources.products.fields.${sort.field}`), + order: translate(`ra.sort.${sort.order}`), }); return (<> @@ -603,8 +603,8 @@ const SortButton = ({ fields }) => { {translate(`resources.products.fields.${field}`)}{' '} {translate( `ra.sort.${ - currentSort.field === field - ? inverseOrder(currentSort.order) + sort.field === field + ? inverseOrder(sort.order) : 'ASC' }` )} diff --git a/docs/useList.md b/docs/useList.md index e3a927712ac..93c0a1f67b3 100644 --- a/docs/useList.md +++ b/docs/useList.md @@ -221,7 +221,7 @@ const { setPage, // a callback to change the page, e.g. setPage(3) setPerPage, // a callback to change the number of results per page, e.g. setPerPage(25) // sorting - currentSort, // a sort object { field, order }, e.g. { field: 'date', order: 'DESC' } + sort, // a sort object { field, order }, e.g. { field: 'date', order: 'DESC' } setSort, // a callback to change the sort, e.g. setSort({ field: 'name', order: 'ASC' }) // filtering filterValues, // a dictionary of filter values, e.g. { title: 'lorem', nationality: 'fr' } diff --git a/docs/useListContext.md b/docs/useListContext.md index 404267a174c..2c21460ac0b 100644 --- a/docs/useListContext.md +++ b/docs/useListContext.md @@ -71,7 +71,7 @@ const { setPage, // a callback to change the page, e.g. setPage(3) setPerPage, // a callback to change the number of results per page, e.g. setPerPage(25) // sorting - currentSort, // a sort object { field, order }, e.g. { field: 'date', order: 'DESC' } + sort, // a sort object { field, order }, e.g. { field: 'date', order: 'DESC' } setSort, // a callback to change the sort, e.g. setSort({ field: 'name', orfer: 'ASC' }) // filtering filterValues, // a dictionary of filter values, e.g. { title: 'lorem', nationality: 'fr' } diff --git a/docs/useListController.md b/docs/useListController.md index 50ebcb5d555..c21666a6cb4 100644 --- a/docs/useListController.md +++ b/docs/useListController.md @@ -102,7 +102,7 @@ const { setPage, // a callback to change the page, e.g. setPage(3) setPerPage, // a callback to change the number of results per page, e.g. setPerPage(25) // sorting - currentSort, // a sort object { field, order }, e.g. { field: 'date', order: 'DESC' } + sort, // a sort object { field, order }, e.g. { field: 'date', order: 'DESC' } setSort, // a callback to change the sort, e.g. setSort({ field: 'name', order: 'ASC' }) // filtering filterValues, // a dictionary of filter values, e.g. { title: 'lorem', nationality: 'fr' } diff --git a/examples/simple/src/customRouteLayout.tsx b/examples/simple/src/customRouteLayout.tsx index d2512a285ef..45a42caddc4 100644 --- a/examples/simple/src/customRouteLayout.tsx +++ b/examples/simple/src/customRouteLayout.tsx @@ -7,14 +7,14 @@ import { Title, } from 'react-admin'; -const currentSort = { field: 'published_at', order: 'DESC' }; +const sort = { field: 'published_at', order: 'DESC' }; const CustomRouteLayout = ({ title = 'Posts' }) => { useAuthenticated(); const { data, total, isLoading } = useGetList('posts', { pagination: { page: 1, perPage: 10 }, - sort: currentSort, + sort, }); return !isLoading ? ( @@ -25,7 +25,7 @@ const CustomRouteLayout = ({ title = 'Posts' }) => { Found <span className="total">{total}</span> posts ! </p> <Datagrid - currentSort={currentSort} + sort={sort} data={data} isLoading={isLoading} total={total} diff --git a/packages/ra-core/src/controller/field/useReferenceArrayFieldController.spec.tsx b/packages/ra-core/src/controller/field/useReferenceArrayFieldController.spec.tsx index c6fa46dd6f1..68f5504e589 100644 --- a/packages/ra-core/src/controller/field/useReferenceArrayFieldController.spec.tsx +++ b/packages/ra-core/src/controller/field/useReferenceArrayFieldController.spec.tsx @@ -51,7 +51,7 @@ describe('<useReferenceArrayFieldController />', () => { ); expect(children).toHaveBeenCalledWith( expect.objectContaining({ - currentSort: { field: 'id', order: 'ASC' }, + sort: { field: 'id', order: 'ASC' }, isFetching: true, isLoading: true, data: undefined, @@ -79,7 +79,7 @@ describe('<useReferenceArrayFieldController />', () => { ); expect(children).toHaveBeenCalledWith( expect.objectContaining({ - currentSort: { field: 'id', order: 'ASC' }, + sort: { field: 'id', order: 'ASC' }, isFetching: false, isLoading: false, data: [ @@ -111,7 +111,7 @@ describe('<useReferenceArrayFieldController />', () => { ); expect(children).toHaveBeenCalledWith( expect.objectContaining({ - currentSort: { field: 'id', order: 'ASC' }, + sort: { field: 'id', order: 'ASC' }, isFetching: false, isLoading: false, data: [{ id: 1, title: 'bar1' }], @@ -150,7 +150,7 @@ describe('<useReferenceArrayFieldController />', () => { ); expect(children).toHaveBeenCalledWith( expect.objectContaining({ - currentSort: { field: 'id', order: 'ASC' }, + sort: { field: 'id', order: 'ASC' }, isFetching: false, isLoading: false, data: [ diff --git a/packages/ra-core/src/controller/field/useReferenceManyFieldController.ts b/packages/ra-core/src/controller/field/useReferenceManyFieldController.ts index 45e2dc9be10..c0643bdddda 100644 --- a/packages/ra-core/src/controller/field/useReferenceManyFieldController.ts +++ b/packages/ra-core/src/controller/field/useReferenceManyFieldController.ts @@ -186,7 +186,7 @@ export const useReferenceManyFieldController = ( ); return { - currentSort: sort, + sort, data, defaultTitle: null, displayedFilters, diff --git a/packages/ra-core/src/controller/input/useReferenceArrayInputController.ts b/packages/ra-core/src/controller/input/useReferenceArrayInputController.ts index b738cb3f368..5b9954b8f27 100644 --- a/packages/ra-core/src/controller/input/useReferenceArrayInputController.ts +++ b/packages/ra-core/src/controller/input/useReferenceArrayInputController.ts @@ -254,7 +254,7 @@ export const useReferenceArrayInputController = < return { choices: dataStatus.choices, - currentSort: sort, + sort, data: matchingReferences, displayedFilters, error: diff --git a/packages/ra-core/src/controller/input/useReferenceInputController.spec.tsx b/packages/ra-core/src/controller/input/useReferenceInputController.spec.tsx index fe1a6eaa448..bc0d634126b 100644 --- a/packages/ra-core/src/controller/input/useReferenceInputController.spec.tsx +++ b/packages/ra-core/src/controller/input/useReferenceInputController.spec.tsx @@ -149,7 +149,7 @@ describe('useReferenceInputController', () => { expect(children).toHaveBeenCalledWith( expect.objectContaining({ possibleValues: { - currentSort: { + sort: { field: 'title', order: 'ASC', }, diff --git a/packages/ra-core/src/controller/input/useReferenceInputController.ts b/packages/ra-core/src/controller/input/useReferenceInputController.ts index 269983443e8..816a0b8c998 100644 --- a/packages/ra-core/src/controller/input/useReferenceInputController.ts +++ b/packages/ra-core/src/controller/input/useReferenceInputController.ts @@ -170,7 +170,7 @@ export const useReferenceInputController = <RecordType extends Record = Record>( setPage, perPage, setPerPage, - currentSort: sort, + sort, setSort, filterValues, displayedFilters, diff --git a/packages/ra-core/src/controller/list/ListContext.tsx b/packages/ra-core/src/controller/list/ListContext.tsx index 288dafe313c..1a55cb48ccd 100644 --- a/packages/ra-core/src/controller/list/ListContext.tsx +++ b/packages/ra-core/src/controller/list/ListContext.tsx @@ -16,7 +16,7 @@ import { ListControllerResult } from './useListController'; * @prop {Function} setPage a callback to change the page, e.g. setPage(3) * @prop {integer} perPage the number of results per page. Defaults to 25 * @prop {Function} setPerPage a callback to change the number of results per page, e.g. setPerPage(25) - * @prop {Object} currentSort a sort object { field, order }, e.g. { field: 'date', order: 'DESC' } + * @prop {Object} sort a sort object { field, order }, e.g. { field: 'date', order: 'DESC' } * @prop {Function} setSort a callback to change the sort, e.g. setSort({ field: 'name', order: 'ASC' }) * @prop {Object} filterValues a dictionary of filter values, e.g. { title: 'lorem', nationality: 'fr' } * @prop {Function} setFilters a callback to update the filters, e.g. setFilters(filters, displayedFilters) @@ -53,7 +53,7 @@ import { ListControllerResult } from './useListController'; * }; */ export const ListContext = createContext<ListControllerResult>({ - currentSort: null, + sort: null, data: null, defaultTitle: null, displayedFilters: null, diff --git a/packages/ra-core/src/controller/list/ListSortContext.tsx b/packages/ra-core/src/controller/list/ListSortContext.tsx index 28075c19835..04668304ffe 100644 --- a/packages/ra-core/src/controller/list/ListSortContext.tsx +++ b/packages/ra-core/src/controller/list/ListSortContext.tsx @@ -9,7 +9,7 @@ import { ListControllerResult } from './useListController'; * List components do in react-admin (e.g. <SortButton>). * * @typedef {Object} ListSortContextValue - * @prop {Object} currentSort a sort object { field, order }, e.g. { field: 'date', order: 'DESC' } + * @prop {Object} sort a sort object { field, order }, e.g. { field: 'date', order: 'DESC' } * @prop {Function} setSort a callback to change the sort, e.g. setSort({ field: 'name', order: 'ASC' }) * @prop {string} resource the resource name, deduced from the location. e.g. 'posts' * @@ -35,23 +35,23 @@ import { ListControllerResult } from './useListController'; * }; */ export const ListSortContext = createContext<ListSortContextValue>({ - currentSort: null, + sort: null, setSort: null, resource: null, }); export type ListSortContextValue = Pick< ListControllerResult, - 'currentSort' | 'setSort' | 'resource' + 'sort' | 'setSort' | 'resource' >; export const usePickSortContext = ( context: ListControllerResult ): ListSortContextValue => useMemo( - () => pick(context, ['currentSort', 'setSort', 'resource']), + () => pick(context, ['sort', 'setSort', 'resource']), // eslint-disable-next-line react-hooks/exhaustive-deps - [context.currentSort, context.setSort] + [context.sort, context.setSort] ); ListSortContext.displayName = 'ListSortContext'; diff --git a/packages/ra-core/src/controller/list/useList.spec.tsx b/packages/ra-core/src/controller/list/useList.spec.tsx index 839724cee24..41056bea0c7 100644 --- a/packages/ra-core/src/controller/list/useList.spec.tsx +++ b/packages/ra-core/src/controller/list/useList.spec.tsx @@ -39,7 +39,7 @@ describe('<useList />', () => { expect(callback).toHaveBeenCalledWith( expect.objectContaining({ - currentSort: { field: 'id', order: 'ASC' }, + sort: { field: 'id', order: 'ASC' }, isFetching: false, isLoading: false, data: [{ id: 2, title: 'world' }], @@ -70,7 +70,7 @@ describe('<useList />', () => { await waitFor(() => { expect(callback).toHaveBeenCalledWith( expect.objectContaining({ - currentSort: { field: 'id', order: 'ASC' }, + sort: { field: 'id', order: 'ASC' }, isFetching: false, isLoading: false, data: [ @@ -119,7 +119,7 @@ describe('<useList />', () => { await waitFor(() => { expect(callback).toHaveBeenCalledWith( expect.objectContaining({ - currentSort: { field: 'title', order: 'DESC' }, + sort: { field: 'title', order: 'DESC' }, isFetching: false, isLoading: false, data: [ @@ -136,7 +136,7 @@ describe('<useList />', () => { await waitFor(() => { expect(callback).toHaveBeenCalledWith( expect.objectContaining({ - currentSort: { field: 'title', order: 'ASC' }, + sort: { field: 'title', order: 'ASC' }, isFetching: false, isLoading: false, data: [ @@ -175,7 +175,7 @@ describe('<useList />', () => { await waitFor(() => { expect(callback).toHaveBeenCalledWith( expect.objectContaining({ - currentSort: { field: 'id', order: 'ASC' }, + sort: { field: 'id', order: 'ASC' }, isFetching: false, isLoading: false, data: [ @@ -219,7 +219,7 @@ describe('<useList />', () => { expect(callback).toHaveBeenCalledWith( expect.objectContaining({ - currentSort: { field: 'id', order: 'ASC' }, + sort: { field: 'id', order: 'ASC' }, isFetching: true, isLoading: false, data: [{ id: 2, title: 'world' }], diff --git a/packages/ra-core/src/controller/list/useList.ts b/packages/ra-core/src/controller/list/useList.ts index 503d0141090..357489a4581 100644 --- a/packages/ra-core/src/controller/list/useList.ts +++ b/packages/ra-core/src/controller/list/useList.ts @@ -217,7 +217,7 @@ export const useList = <RecordType extends Record = Record>( }, [isLoading, loadingState, setLoadingState]); return { - currentSort: sort, + sort, data: finalItems.data, defaultTitle: '', error, diff --git a/packages/ra-core/src/controller/list/useListContext.ts b/packages/ra-core/src/controller/list/useListContext.ts index 3467d5242e2..103c459445e 100644 --- a/packages/ra-core/src/controller/list/useListContext.ts +++ b/packages/ra-core/src/controller/list/useListContext.ts @@ -25,7 +25,7 @@ import { Record } from '../../types'; * @prop {Function} setPage a callback to change the page, e.g. setPage(3) * @prop {integer} perPage the number of results per page. Defaults to 25 * @prop {Function} setPerPage a callback to change the number of results per page, e.g. setPerPage(25) - * @prop {Object} currentSort a sort object { field, order }, e.g. { field: 'date', order: 'DESC' } + * @prop {Object} sort a sort object { field, order }, e.g. { field: 'date', order: 'DESC' } * @prop {Function} setSort a callback to change the sort, e.g. setSort({ field : 'name', order: 'ASC' }) * @prop {Object} filterValues a dictionary of filter values, e.g. { title: 'lorem', nationality: 'fr' } * @prop {Function} setFilters a callback to update the filters, e.g. setFilters(filters, displayedFilters) @@ -117,7 +117,7 @@ export const useListContext = <RecordType extends Record = Record>( */ const extractListContextProps = ({ basePath, - currentSort, + sort, data, defaultTitle, displayedFilters, @@ -142,7 +142,7 @@ const extractListContextProps = ({ total, }) => ({ basePath, - currentSort, + sort, data, defaultTitle, displayedFilters, diff --git a/packages/ra-core/src/controller/list/useListController.spec.tsx b/packages/ra-core/src/controller/list/useListController.spec.tsx index 0c40b85d0c1..c2f935612c3 100644 --- a/packages/ra-core/src/controller/list/useListController.spec.tsx +++ b/packages/ra-core/src/controller/list/useListController.spec.tsx @@ -355,7 +355,7 @@ describe('useListController', () => { }) ).toEqual({ basePath: undefined, - currentSort: undefined, + sort: undefined, data: [4, 5], defaultTitle: undefined, displayedFilters: undefined, diff --git a/packages/ra-core/src/controller/list/useListController.ts b/packages/ra-core/src/controller/list/useListController.ts index c97fb6dad56..2c21c352cdd 100644 --- a/packages/ra-core/src/controller/list/useListController.ts +++ b/packages/ra-core/src/controller/list/useListController.ts @@ -127,7 +127,7 @@ export const useListController = <RecordType extends Record = Record>( }); return { - currentSort, + sort: currentSort, data, defaultTitle, displayedFilters: query.displayedFilters, @@ -177,7 +177,7 @@ const defaultSort = { }; export interface ListControllerResult<RecordType extends Record = Record> { - currentSort: SortPayload; + sort: SortPayload; data: RecordType[]; defaultTitle?: string; displayedFilters: any; @@ -210,7 +210,7 @@ export interface ListControllerResult<RecordType extends Record = Record> { export const injectedProps = [ 'basePath', - 'currentSort', + 'sort', 'data', 'defaultTitle', 'displayedFilters', diff --git a/packages/ra-core/src/controller/list/useListSortContext.ts b/packages/ra-core/src/controller/list/useListSortContext.ts index 2a0f04967f7..9884f36076e 100644 --- a/packages/ra-core/src/controller/list/useListSortContext.ts +++ b/packages/ra-core/src/controller/list/useListSortContext.ts @@ -9,7 +9,7 @@ import { ListSortContext, ListSortContextValue } from './ListSortContext'; * or <ListBase>). * * @typedef {Object} ListSortContextValue - * @prop {Object} currentSort a sort object { field, order }, e.g. { field: 'date', order: 'DESC' } + * @prop {Object} sort a sort object { field, order }, e.g. { field: 'date', order: 'DESC' } * @prop {Function} setSort a callback to change the sort, e.g. setSort({ field: 'name', order: 'ASC' }) * @prop {string} resource the resource name, deduced from the location. e.g. 'posts' * diff --git a/packages/ra-ui-materialui/src/button/ExportButton.tsx b/packages/ra-ui-materialui/src/button/ExportButton.tsx index 2e29bdb8312..bcdea0a3e23 100644 --- a/packages/ra-ui-materialui/src/button/ExportButton.tsx +++ b/packages/ra-ui-materialui/src/button/ExportButton.tsx @@ -21,13 +21,12 @@ export const ExportButton = (props: ExportButtonProps) => { label = 'ra.action.export', icon = defaultIcon, exporter: customExporter, - sort, // deprecated, to be removed in v4 ...rest } = props; const { filter, filterValues, - currentSort, + sort, exporter: exporterFromContext, total, } = useListContext(props); @@ -39,7 +38,7 @@ export const ExportButton = (props: ExportButtonProps) => { event => { dataProvider .getList(resource, { - sort: currentSort || sort, + sort, filter: filter ? { ...filterValues, ...filter } : filterValues, @@ -64,7 +63,7 @@ export const ExportButton = (props: ExportButtonProps) => { } }, [ - currentSort, + sort, dataProvider, exporter, filter, diff --git a/packages/ra-ui-materialui/src/button/SortButton.tsx b/packages/ra-ui-materialui/src/button/SortButton.tsx index 6ab054963a4..d454340013e 100644 --- a/packages/ra-ui-materialui/src/button/SortButton.tsx +++ b/packages/ra-ui-materialui/src/button/SortButton.tsx @@ -45,7 +45,7 @@ import { */ const SortButton = (props: SortButtonProps) => { const { fields, label = 'ra.sort.sort_by', icon = defaultIcon } = props; - const { resource, currentSort, setSort } = useListSortContext(); + const { resource, sort, setSort } = useListSortContext(); const translate = useTranslate(); const isXSmall = useMediaQuery((theme: Theme) => theme.breakpoints.down('sm') @@ -65,10 +65,7 @@ const SortButton = (props: SortButtonProps) => { const field = event.currentTarget.dataset.sort; setSort({ field, - order: - field === currentSort.field - ? inverseOrder(currentSort.order) - : 'ASC', + order: field === sort.field ? inverseOrder(sort.order) : 'ASC', }); setAnchorEl(null); }; @@ -77,10 +74,10 @@ const SortButton = (props: SortButtonProps) => { field: translate( ...getFieldLabelTranslationArgs({ resource, - source: currentSort.field, + source: sort.field, }) ), - order: translate(`ra.sort.${currentSort.order}`), + order: translate(`ra.sort.${sort.order}`), _: label, }); @@ -131,8 +128,8 @@ const SortButton = (props: SortButtonProps) => { )}{' '} {translate( `ra.sort.${ - currentSort.field === field - ? inverseOrder(currentSort.order) + sort.field === field + ? inverseOrder(sort.order) : 'ASC' }` )} diff --git a/packages/ra-ui-materialui/src/field/ArrayField.spec.tsx b/packages/ra-ui-materialui/src/field/ArrayField.spec.tsx index a1d6f9c74c0..4225b9c832f 100644 --- a/packages/ra-ui-materialui/src/field/ArrayField.spec.tsx +++ b/packages/ra-ui-materialui/src/field/ArrayField.spec.tsx @@ -10,10 +10,10 @@ import { Datagrid } from '../list'; import { SimpleList } from '../list'; describe('<ArrayField />', () => { - const currentSort = { field: 'id', order: 'ASC' }; + const sort = { field: 'id', order: 'ASC' }; const DummyIterator = props => ( - <Datagrid {...props} currentSort={currentSort}> + <Datagrid {...props} sort={sort}> <NumberField source="id" /> <TextField source="foo" /> </Datagrid> diff --git a/packages/ra-ui-materialui/src/field/ArrayField.tsx b/packages/ra-ui-materialui/src/field/ArrayField.tsx index 945c31d2313..401489963ae 100644 --- a/packages/ra-ui-materialui/src/field/ArrayField.tsx +++ b/packages/ra-ui-materialui/src/field/ArrayField.tsx @@ -94,7 +94,7 @@ export const ArrayField: FC<ArrayFieldProps> = memo(props => { data, basePath, selectedIds: [], - currentSort: { field: null, order: null }, + sort: { field: null, order: null }, displayedFilters: null, filterValues: null, hasCreate: null, @@ -119,7 +119,7 @@ export const ArrayField: FC<ArrayFieldProps> = memo(props => { data, isLoading: false, basePath, - currentSort: { field: null, order: null }, + sort: { field: null, order: null }, resource, ...rest, })} diff --git a/packages/ra-ui-materialui/src/field/ReferenceManyField.tsx b/packages/ra-ui-materialui/src/field/ReferenceManyField.tsx index 6c43e7df9c0..ca8f70f37a3 100644 --- a/packages/ra-ui-materialui/src/field/ReferenceManyField.tsx +++ b/packages/ra-ui-materialui/src/field/ReferenceManyField.tsx @@ -158,7 +158,10 @@ export const ReferenceManyFieldView: FC<ReferenceManyFieldViewProps> = props => }; export interface ReferenceManyFieldViewProps - extends Omit<ReferenceManyFieldProps, 'resource' | 'page' | 'perPage'>, + extends Omit< + ReferenceManyFieldProps, + 'resource' | 'page' | 'perPage' | 'sort' + >, ListControllerResult { children: ReactElement; } @@ -166,7 +169,7 @@ export interface ReferenceManyFieldViewProps ReferenceManyFieldView.propTypes = { children: PropTypes.element, className: PropTypes.string, - currentSort: PropTypes.exact({ + sort: PropTypes.exact({ field: PropTypes.string, order: PropTypes.string, }), diff --git a/packages/ra-ui-materialui/src/field/ReferenceOneField.stories.tsx b/packages/ra-ui-materialui/src/field/ReferenceOneField.stories.tsx index 99d8df501a7..c7435467524 100644 --- a/packages/ra-ui-materialui/src/field/ReferenceOneField.stories.tsx +++ b/packages/ra-ui-materialui/src/field/ReferenceOneField.stories.tsx @@ -170,7 +170,7 @@ const ListWrapper = ({ children }) => ( value={{ total: 1, data: [{ id: 1, title: 'War and Peace' }], - currentSort: { field: 'title', order: 'ASC' }, + sort: { field: 'title', order: 'ASC' }, }} > {children} diff --git a/packages/ra-ui-materialui/src/input/ReferenceInput.spec.tsx b/packages/ra-ui-materialui/src/input/ReferenceInput.spec.tsx index f5e17a67977..61935a52f9d 100644 --- a/packages/ra-ui-materialui/src/input/ReferenceInput.spec.tsx +++ b/packages/ra-ui-materialui/src/input/ReferenceInput.spec.tsx @@ -17,7 +17,7 @@ describe('<ReferenceInput />', () => { setPage: () => {}, perPage: 25, setPerPage: () => {}, - currentSort: {}, + sort: {}, setSort: () => {}, filterValues: {}, displayedFilters: [], diff --git a/packages/ra-ui-materialui/src/list/ListActions.tsx b/packages/ra-ui-materialui/src/list/ListActions.tsx index 1a6688cca0f..4808ac28772 100644 --- a/packages/ra-ui-materialui/src/list/ListActions.tsx +++ b/packages/ra-ui-materialui/src/list/ListActions.tsx @@ -54,10 +54,9 @@ export const ListActions = (props: ListActionsProps) => { ...rest } = props; const { - currentSort, + sort, displayedFilters, filterValues, - selectedIds, showFilter, total, } = useListContext(props); @@ -81,7 +80,7 @@ export const ListActions = (props: ListActionsProps) => { <ExportButton disabled={total === 0} resource={resource} - sort={currentSort} + sort={sort} filterValues={filterValues} /> )} @@ -97,7 +96,7 @@ export const ListActions = (props: ListActionsProps) => { filters, total, className, - currentSort, + sort, exporter, hasCreate, ] @@ -106,7 +105,7 @@ export const ListActions = (props: ListActionsProps) => { ListActions.propTypes = { className: PropTypes.string, - currentSort: PropTypes.any, + sort: PropTypes.any, displayedFilters: PropTypes.object, exporter: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]), filters: PropTypes.element, @@ -125,7 +124,7 @@ ListActions.defaultProps = { }; export interface ListActionsProps extends ToolbarProps { - currentSort?: SortPayload; + sort?: SortPayload; className?: string; resource?: string; filters?: ReactElement<any>; diff --git a/packages/ra-ui-materialui/src/list/ListView.tsx b/packages/ra-ui-materialui/src/list/ListView.tsx index ab490204afe..cf2277c490e 100644 --- a/packages/ra-ui-materialui/src/list/ListView.tsx +++ b/packages/ra-ui-materialui/src/list/ListView.tsx @@ -98,7 +98,7 @@ ListView.propTypes = { className: PropTypes.string, component: ComponentPropType, // @ts-ignore-line - currentSort: PropTypes.shape({ + sort: PropTypes.shape({ field: PropTypes.string.isRequired, order: PropTypes.string.isRequired, }), diff --git a/packages/ra-ui-materialui/src/list/datagrid/Datagrid.spec.tsx b/packages/ra-ui-materialui/src/list/datagrid/Datagrid.spec.tsx index 934fdb71717..b757f1e9be7 100644 --- a/packages/ra-ui-materialui/src/list/datagrid/Datagrid.spec.tsx +++ b/packages/ra-ui-materialui/src/list/datagrid/Datagrid.spec.tsx @@ -36,7 +36,7 @@ describe('<Datagrid />', () => { isFetching: false, isLoading: false, selectedIds: [], - currentSort: { field: 'title', order: 'ASC' }, + sort: { field: 'title', order: 'ASC' }, onToggleItem: jest.fn(), onSelect: jest.fn(), }; diff --git a/packages/ra-ui-materialui/src/list/datagrid/Datagrid.stories.tsx b/packages/ra-ui-materialui/src/list/datagrid/Datagrid.stories.tsx index cbc33ccc6c2..c9100fa0bd0 100644 --- a/packages/ra-ui-materialui/src/list/datagrid/Datagrid.stories.tsx +++ b/packages/ra-ui-materialui/src/list/datagrid/Datagrid.stories.tsx @@ -57,7 +57,7 @@ const SubWrapper = ({ children }) => { data, total: 4, isLoading: false, - currentSort: { field: 'id', order: 'ASC' }, + sort: { field: 'id', order: 'ASC' }, selectedIds, onSelect: selectionModifiers.select, onToggleItem: selectionModifiers.toggle, @@ -285,12 +285,12 @@ export const ColumnStyles = () => ( </Wrapper> ); -const currentSort = { field: 'id', order: 'DESC' }; +const sort = { field: 'id', order: 'DESC' }; const MyCustomList = () => { const { data, total, isLoading } = useGetList('books', { pagination: { page: 1, perPage: 10 }, - sort: currentSort, + sort: sort, }); return ( @@ -298,7 +298,7 @@ const MyCustomList = () => { data={data} total={total} isLoading={isLoading} - currentSort={currentSort} + sort={sort} bulkActionButtons={false} > <TextField source="id" /> @@ -310,7 +310,7 @@ const MyCustomList = () => { const MyCustomListInteractive = () => { const { data, isLoading } = useGetList('books', { pagination: { page: 1, perPage: 10 }, - sort: currentSort, + sort, }); const listContext = useList({ data, isLoading }); diff --git a/packages/ra-ui-materialui/src/list/datagrid/Datagrid.tsx b/packages/ra-ui-materialui/src/list/datagrid/Datagrid.tsx index 6453d78a671..8745797bd26 100644 --- a/packages/ra-ui-materialui/src/list/datagrid/Datagrid.tsx +++ b/packages/ra-ui-materialui/src/list/datagrid/Datagrid.tsx @@ -82,12 +82,12 @@ const defaultBulkActionButtons = <BulkDeleteButton />; * * @example // Usage outside of a <List> or a <ReferenceManyField>. * - * const currentSort = { field: 'published_at', order: 'DESC' }; + * const sort = { field: 'published_at', order: 'DESC' }; * * export const MyCustomList = (props) => { * const { data, total, isLoading } = useGetList( * 'posts', - * { pagination: { page: 1, perPage: 10 }, sort: currentSort } + * { pagination: { page: 1, perPage: 10 }, sort: sort } * ); * * return ( @@ -95,7 +95,7 @@ const defaultBulkActionButtons = <BulkDeleteButton />; * data={data} * total={total} * isLoading={isLoading} - * currentSort={currentSort} + * sort={sort} * selectedIds={[]} * setSort={() => { * console.log('set sort'); @@ -134,7 +134,7 @@ export const Datagrid: FC<DatagridProps> = React.forwardRef((props, ref) => { } = props; const { - currentSort, + sort, data, isLoading, onSelect, @@ -242,7 +242,7 @@ export const Datagrid: FC<DatagridProps> = React.forwardRef((props, ref) => { header, { children, - currentSort, + sort, data, hasExpand: !!expand, hasBulkActions, @@ -289,7 +289,7 @@ Datagrid.propTypes = { bulkActionButtons: PropTypes.oneOfType([PropTypes.bool, PropTypes.element]), children: PropTypes.node.isRequired, className: PropTypes.string, - currentSort: PropTypes.exact({ + sort: PropTypes.exact({ field: PropTypes.string, order: PropTypes.string, }), @@ -338,7 +338,7 @@ export interface DatagridProps<RecordType extends Record = Record> size?: 'medium' | 'small'; // can be injected when using the component without context basePath?: string; - currentSort?: SortPayload; + sort?: SortPayload; data?: RecordType[]; isLoading?: boolean; onSelect?: (ids: Identifier[]) => void; diff --git a/packages/ra-ui-materialui/src/list/datagrid/DatagridHeader.tsx b/packages/ra-ui-materialui/src/list/datagrid/DatagridHeader.tsx index a329dee5f76..6a4c402bd22 100644 --- a/packages/ra-ui-materialui/src/list/datagrid/DatagridHeader.tsx +++ b/packages/ra-ui-materialui/src/list/datagrid/DatagridHeader.tsx @@ -30,28 +30,24 @@ export const DatagridHeader = (props: DatagridHeaderProps) => { } = props; const resource = useResourceContext(props); const translate = useTranslate(); - const { - currentSort, - data, - onSelect, - selectedIds, - setSort, - } = useListContext(props); + const { sort, data, onSelect, selectedIds, setSort } = useListContext( + props + ); const updateSortCallback = useCallback( event => { event.stopPropagation(); const newField = event.currentTarget.dataset.field; const newOrder = - currentSort.field === newField - ? currentSort.order === 'ASC' + sort.field === newField + ? sort.order === 'ASC' ? 'DESC' : 'ASC' : event.currentTarget.dataset.order; setSort({ field: newField, order: newOrder }); }, - [currentSort.field, currentSort.order, setSort] + [sort.field, sort.order, setSort] ); const updateSort = setSort ? updateSortCallback : null; @@ -131,10 +127,10 @@ export const DatagridHeader = (props: DatagridHeaderProps) => { DatagridClasses.headerCell, `column-${(field.props as any).source}` )} - currentSort={currentSort} + sort={sort} field={field} isSorting={ - currentSort.field === + sort.field === ((field.props as any).sortBy || (field.props as any).source) } @@ -152,7 +148,7 @@ export const DatagridHeader = (props: DatagridHeaderProps) => { DatagridHeader.propTypes = { children: PropTypes.node, className: PropTypes.string, - currentSort: PropTypes.exact({ + sort: PropTypes.exact({ field: PropTypes.string, order: PropTypes.string, }), @@ -177,7 +173,7 @@ export interface DatagridHeaderProps<RecordType extends Record = Record> { isRowExpandable?: (record: Record) => boolean; size?: 'medium' | 'small'; // can be injected when using the component without context - currentSort?: SortPayload; + sort?: SortPayload; data?: RecordType[]; onSelect?: (ids: Identifier[]) => void; onToggleItem?: (id: Identifier) => void; diff --git a/packages/ra-ui-materialui/src/list/datagrid/DatagridHeaderCell.spec.tsx b/packages/ra-ui-materialui/src/list/datagrid/DatagridHeaderCell.spec.tsx index 4a5bb0ba70d..b7d1eee1f02 100644 --- a/packages/ra-ui-materialui/src/list/datagrid/DatagridHeaderCell.spec.tsx +++ b/packages/ra-ui-materialui/src/list/datagrid/DatagridHeaderCell.spec.tsx @@ -14,7 +14,7 @@ describe('<DatagridHeaderCell />', () => { <tr> <DatagridHeaderCell resource="posts" - currentSort={{ field: 'title', order: 'ASC' }} + sort={{ field: 'title', order: 'ASC' }} field={<Field source="title" label={<Label />} />} updateSort={() => true} /> @@ -45,7 +45,7 @@ describe('<DatagridHeaderCell />', () => { <tr> <DatagridHeaderCell resource="posts" - currentSort={{ field: 'title', order: 'ASC' }} + sort={{ field: 'title', order: 'ASC' }} field={<Field source="title" />} updateSort={() => true} /> @@ -65,7 +65,7 @@ describe('<DatagridHeaderCell />', () => { <tr> <DatagridHeaderCell resource="posts" - currentSort={{ field: 'title', order: 'ASC' }} + sort={{ field: 'title', order: 'ASC' }} field={<Field sortBy="title" />} updateSort={() => true} /> @@ -85,7 +85,7 @@ describe('<DatagridHeaderCell />', () => { <tr> <DatagridHeaderCell resource="posts" - currentSort={{ field: 'title', order: 'ASC' }} + sort={{ field: 'title', order: 'ASC' }} field={ <Field sortBy="title" sortByOrder="DESC" /> } @@ -105,7 +105,7 @@ describe('<DatagridHeaderCell />', () => { <tr> <DatagridHeaderCell resource="posts" - currentSort={{ field: 'title', order: 'ASC' }} + sort={{ field: 'title', order: 'ASC' }} field={<Field source="title" />} updateSort={() => true} /> @@ -123,7 +123,7 @@ describe('<DatagridHeaderCell />', () => { <tr> <DatagridHeaderCell resource="posts" - currentSort={{ field: 'title', order: 'ASC' }} + sort={{ field: 'title', order: 'ASC' }} field={<Field />} updateSort={() => true} /> @@ -141,7 +141,7 @@ describe('<DatagridHeaderCell />', () => { <tr> <DatagridHeaderCell resource="posts" - currentSort={{ field: 'title', order: 'ASC' }} + sort={{ field: 'title', order: 'ASC' }} field={ <Field source="title" sortable={false} /> } @@ -161,7 +161,7 @@ describe('<DatagridHeaderCell />', () => { <tr> <DatagridHeaderCell resource="posts" - currentSort={{ field: 'title', order: 'ASC' }} + sort={{ field: 'title', order: 'ASC' }} updateSort={() => true} field={<Field />} className="blue" diff --git a/packages/ra-ui-materialui/src/list/datagrid/DatagridHeaderCell.tsx b/packages/ra-ui-materialui/src/list/datagrid/DatagridHeaderCell.tsx index 192b06f6043..fc0b6f6ad7c 100644 --- a/packages/ra-ui-materialui/src/list/datagrid/DatagridHeaderCell.tsx +++ b/packages/ra-ui-materialui/src/list/datagrid/DatagridHeaderCell.tsx @@ -15,14 +15,7 @@ import { export const DatagridHeaderCell = ( props: DatagridHeaderCellProps ): JSX.Element => { - const { - className, - field, - currentSort, - updateSort, - isSorting, - ...rest - } = props; + const { className, field, sort, updateSort, isSorting, ...rest } = props; const resource = useResourceContext(props); const translate = useTranslate(); @@ -48,10 +41,10 @@ export const DatagridHeaderCell = ( > <TableSortLabel active={ - currentSort.field === + sort.field === (field.props.sortBy || field.props.source) } - direction={currentSort.order === 'ASC' ? 'asc' : 'desc'} + direction={sort.order === 'ASC' ? 'asc' : 'desc'} data-field={field.props.sortBy || field.props.source} data-order={field.props.sortByOrder || 'ASC'} onClick={updateSort} @@ -78,7 +71,7 @@ export const DatagridHeaderCell = ( DatagridHeaderCell.propTypes = { className: PropTypes.string, field: PropTypes.element, - currentSort: PropTypes.shape({ + sort: PropTypes.shape({ field: PropTypes.string, order: PropTypes.string, }).isRequired, @@ -93,7 +86,7 @@ export interface DatagridHeaderCellProps field?: JSX.Element; isSorting?: boolean; resource: string; - currentSort: SortPayload; + sort: SortPayload; updateSort?: (event: any) => void; } @@ -101,8 +94,8 @@ export default memo( DatagridHeaderCell, (props, nextProps) => props.updateSort === nextProps.updateSort && - props.currentSort.field === nextProps.currentSort.field && - props.currentSort.order === nextProps.currentSort.order && + props.sort.field === nextProps.sort.field && + props.sort.order === nextProps.sort.order && props.isSorting === nextProps.isSorting && props.resource === nextProps.resource );