diff --git a/docs/Count.md b/docs/Count.md index 96257cb08cc..7bc36a50186 100644 --- a/docs/Count.md +++ b/docs/Count.md @@ -68,12 +68,13 @@ const TicketListAside = () => { ## Props -| Prop | Required | Type | Default | Description | -| ---------- | -------- | ------ | ------- | ----------------------------------------------------------------------- | -| `filter` | Optional | Object | - | Filter to apply to the query. | -| `link` | Optional | bool | `false` | If true, the count is wrapped in a `` to the list view. | -| `resource` | Optional | string | - | Resource to count. Default to the current `ResourceContext` | -| `timeout` | Optional | number | 1000 | Number of milliseconds to wait before displaying the loading indicator. | +| Prop | Required | Type | Default | Description | +| ---------- | -------- | ------------------------------------------ | --------------------------------- | ----------------------------------------------------------------------- | +| `filter` | Optional | Object | - | Filter to apply to the query. | +| `link` | Optional | bool | `false` | If true, the count is wrapped in a `` to the list view. | +| `resource` | Optional | string | - | Resource to count. Default to the current `ResourceContext` | +| `sort` | Optional | `{ field: string, order: 'ASC' or 'DESC' }` | `{ field: 'id', order: 'DESC' }` | The sort option sent to `getList` | +| `timeout` | Optional | number | 1000 | Number of milliseconds to wait before displaying the loading indicator. | Additional props are passed to [the underlying MUI `` element](https://mui.com/material-ui/api/typography/). @@ -116,6 +117,16 @@ If you want to count a different resource, pass it as the `resource` prop. ``` +## `sort` + +If you want to customize the sort options passed to `getList` (for instance because your table does not have an `id` column), you can pass a custom `sort` prop: + +{% raw %} +```jsx +; +``` +{% endraw %} + ## `timeout` The `` component displays a loading indicator after 1 second. This is useful to avoid displaying a loading indicator when the count is retrieved in a few milliseconds. You can change this delay by passing a `timeout` prop. diff --git a/docs/ReferenceManyCount.md b/docs/ReferenceManyCount.md index c826ae30075..d265862ab6f 100644 --- a/docs/ReferenceManyCount.md +++ b/docs/ReferenceManyCount.md @@ -60,14 +60,15 @@ export const PostList = () => ( ## Props -| Prop | Required | Type | Default | Description | -| ----------- | -------- | ------ | ------- | ------------------------------------------------------------------------- | -| `reference` | Required | string | - | Name of the related resource to fetch (e.g. `comments`) | -| `target` | Required | string | - | Name of the field in the related resource that points to the current one. | -| `filter` | Optional | Object | - | Filter to apply to the query. | -| `link` | Optional | bool | `false` | If true, the count is wrapped in a `` to the filtered list view. | -| `resource` | Optional | string | - | Resource to count. Default to the current `ResourceContext` | -| `timeout` | Optional | number | 1000 | Number of milliseconds to wait before displaying the loading indicator. | +| Prop | Required | Type | Default | Description | +| ----------- | -------- | ------------------------------------------ | --------------------------------- | ------------------------------------------------------------------------- | +| `reference` | Required | string | - | Name of the related resource to fetch (e.g. `comments`) | +| `target` | Required | string | - | Name of the field in the related resource that points to the current one. | +| `filter` | Optional | Object | - | Filter to apply to the query. | +| `link` | Optional | bool | `false` | If true, the count is wrapped in a `` to the filtered list view. | +| `resource` | Optional | string | - | Resource to count. Default to the current `ResourceContext` | +| `sort` | Optional | `{ field: string, order: 'ASC' or 'DESC' }` | `{ field: 'id', order: 'DESC' }` | The sort option sent to `getManyReference` | +| `timeout` | Optional | number | 1000 | Number of milliseconds to wait before displaying the loading indicator. | `` also accepts the [common field props](./Fields.md#common-field-props). @@ -140,6 +141,21 @@ By default, the `` component uses the current `ResourceConte /> ``` +## `sort` + +If you want to customize the sort options passed to `getManyReference` (for instance because your relation table does not have an `id` column), you can pass a custom `sort` prop: + +{% raw %} +```jsx + +``` +{% endraw %} + ## `target` The `target` prop is required and must be the name of the field in the related resource that points to the current one. For instance, when fetching the number of comments related to the current post, if a comment relates to a post via a `post_id` foreign key, you must set the `target` prop to `post_id`: diff --git a/packages/ra-ui-materialui/src/field/ReferenceManyCount.spec.tsx b/packages/ra-ui-materialui/src/field/ReferenceManyCount.spec.tsx index 5dc97daefc5..ff701ee9dd1 100644 --- a/packages/ra-ui-materialui/src/field/ReferenceManyCount.spec.tsx +++ b/packages/ra-ui-materialui/src/field/ReferenceManyCount.spec.tsx @@ -1,7 +1,13 @@ import * as React from 'react'; import { render, screen } from '@testing-library/react'; -import { Basic, ErrorState, WithFilter } from './ReferenceManyCount.stories'; +import { + Basic, + ErrorState, + WithFilter, + Wrapper, +} from './ReferenceManyCount.stories'; +import { ReferenceManyCount } from './ReferenceManyCount'; describe('', () => { it('should return the number of related records of a given reference', async () => { @@ -17,4 +23,26 @@ describe('', () => { render(); await screen.findByText('2'); }); + it('should accept a sort prop', async () => { + const dataProvider = { + getManyReference: jest.fn(), + } as any; + render( + + + + ); + expect(dataProvider.getManyReference).toHaveBeenCalledWith('comments', { + target: 'post_id', + id: 1, + filter: {}, + pagination: { page: 1, perPage: 1 }, + sort: { field: 'custom_id', order: 'ASC' }, + meta: undefined, + }); + }); }); diff --git a/packages/ra-ui-materialui/src/field/ReferenceManyCount.stories.tsx b/packages/ra-ui-materialui/src/field/ReferenceManyCount.stories.tsx index a9630b2e002..deab236bccc 100644 --- a/packages/ra-ui-materialui/src/field/ReferenceManyCount.stories.tsx +++ b/packages/ra-ui-materialui/src/field/ReferenceManyCount.stories.tsx @@ -11,6 +11,7 @@ import { ReferenceManyCount } from './ReferenceManyCount'; export default { title: 'ra-ui-materialui/fields/ReferenceManyCount', + excludeStories: ['Wrapper'], }; const post = { @@ -25,7 +26,7 @@ const comments = [ { id: 5, post_id: 2, is_published: false }, ]; -const Wrapper = ({ dataProvider, children }) => ( +export const Wrapper = ({ dataProvider, children }) => ( { reference, target, filter, + sort, link, resource, source = 'id', @@ -43,6 +45,7 @@ export const ReferenceManyCount = (props: ReferenceManyCountProps) => { const { isLoading, error, total } = useReferenceManyFieldController({ filter, + sort, page: 1, perPage: 1, record, @@ -99,6 +102,7 @@ export interface ReferenceManyCountProps Omit { reference: string; target: string; + sort?: SortPayload; filter?: any; label?: string; link?: boolean; diff --git a/packages/ra-ui-materialui/src/list/Count.spec.tsx b/packages/ra-ui-materialui/src/list/Count.spec.tsx index 4768391ec00..c0530f314d2 100644 --- a/packages/ra-ui-materialui/src/list/Count.spec.tsx +++ b/packages/ra-ui-materialui/src/list/Count.spec.tsx @@ -1,7 +1,9 @@ -import * as React from 'react'; import { render, screen } from '@testing-library/react'; +import * as React from 'react'; -import { Basic, ErrorState, WithFilter } from './Count.stories'; +import { ResourceContextProvider } from 'ra-core'; +import { Count } from './Count'; +import { Basic, ErrorState, WithFilter, Wrapper } from './Count.stories'; describe('', () => { it('should return the number of records of a given resource', async () => { @@ -17,4 +19,22 @@ describe('', () => { render(); await screen.findByText('3'); }); + it('should accept a sort prop', async () => { + const dataProvider = { + getList: jest.fn(), + } as any; + render( + + + + + + ); + expect(dataProvider.getList).toHaveBeenCalledWith('posts', { + filter: {}, + pagination: { page: 1, perPage: 1 }, + sort: { field: 'custom_id', order: 'ASC' }, + meta: undefined, + }); + }); }); diff --git a/packages/ra-ui-materialui/src/list/Count.stories.tsx b/packages/ra-ui-materialui/src/list/Count.stories.tsx index b8c403509f1..5b348ee8e0d 100644 --- a/packages/ra-ui-materialui/src/list/Count.stories.tsx +++ b/packages/ra-ui-materialui/src/list/Count.stories.tsx @@ -7,6 +7,7 @@ import { Count } from './Count'; export default { title: 'ra-ui-materialui/list/Count', + excludeStories: ['Wrapper'], }; const posts = [ @@ -17,7 +18,7 @@ const posts = [ { id: 5, is_published: false }, ]; -const Wrapper = ({ dataProvider, children }) => ( +export const Wrapper = ({ dataProvider, children }) => ( { const { filter, + sort, link, resource: resourceFromProps, timeout = 1000, @@ -43,6 +45,7 @@ export const Count = (props: CountProps) => { const { total, isLoading, error } = useGetList(resource, { filter, + sort, pagination: { perPage: 1, page: 1 }, }); @@ -80,6 +83,7 @@ export const Count = (props: CountProps) => { export interface CountProps extends TypographyProps { filter?: any; + sort?: SortPayload; link?: Boolean; resource?: string; timeout?: number;