From 364785a4b11adc7d3058f3428c802a19e4ac9418 Mon Sep 17 00:00:00 2001 From: Antoine Fricker Date: Fri, 29 Jul 2022 23:22:44 +0200 Subject: [PATCH 01/44] Delete contexts don't send mutation meta --- .../controller/button/useDeleteWithConfirmController.tsx | 6 +++++- .../src/controller/button/useDeleteWithUndoController.tsx | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/ra-core/src/controller/button/useDeleteWithConfirmController.tsx b/packages/ra-core/src/controller/button/useDeleteWithConfirmController.tsx index df5fd83c971..bed184351a3 100644 --- a/packages/ra-core/src/controller/button/useDeleteWithConfirmController.tsx +++ b/packages/ra-core/src/controller/button/useDeleteWithConfirmController.tsx @@ -95,7 +95,11 @@ const useDeleteWithConfirmController = ( event.stopPropagation(); deleteOne( resource, - { id: record.id, previousData: record }, + { + id: record.id, + previousData: record, + meta: mutationOptions.meta, + }, { onSuccess: () => { setOpen(false); diff --git a/packages/ra-core/src/controller/button/useDeleteWithUndoController.tsx b/packages/ra-core/src/controller/button/useDeleteWithUndoController.tsx index 2b1f6e2117c..55590688ac5 100644 --- a/packages/ra-core/src/controller/button/useDeleteWithUndoController.tsx +++ b/packages/ra-core/src/controller/button/useDeleteWithUndoController.tsx @@ -63,7 +63,11 @@ const useDeleteWithUndoController = ( event.stopPropagation(); deleteOne( resource, - { id: record.id, previousData: record }, + { + id: record.id, + previousData: record, + meta: mutationOptions.meta, + }, { onSuccess: () => { notify('ra.notification.deleted', { From ae7aa5e71e2a6d117dbcbbdf07c35b35fb6a0f09 Mon Sep 17 00:00:00 2001 From: Antoine Fricker Date: Sat, 30 Jul 2022 00:09:24 +0200 Subject: [PATCH 02/44] Fix access error [skip ci] --- .../src/controller/button/useDeleteWithConfirmController.tsx | 2 +- .../src/controller/button/useDeleteWithUndoController.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ra-core/src/controller/button/useDeleteWithConfirmController.tsx b/packages/ra-core/src/controller/button/useDeleteWithConfirmController.tsx index bed184351a3..5f674ea4704 100644 --- a/packages/ra-core/src/controller/button/useDeleteWithConfirmController.tsx +++ b/packages/ra-core/src/controller/button/useDeleteWithConfirmController.tsx @@ -98,7 +98,7 @@ const useDeleteWithConfirmController = ( { id: record.id, previousData: record, - meta: mutationOptions.meta, + meta: mutationOptions?.meta, }, { onSuccess: () => { diff --git a/packages/ra-core/src/controller/button/useDeleteWithUndoController.tsx b/packages/ra-core/src/controller/button/useDeleteWithUndoController.tsx index 55590688ac5..1ff4f11fd63 100644 --- a/packages/ra-core/src/controller/button/useDeleteWithUndoController.tsx +++ b/packages/ra-core/src/controller/button/useDeleteWithUndoController.tsx @@ -66,7 +66,7 @@ const useDeleteWithUndoController = ( { id: record.id, previousData: record, - meta: mutationOptions.meta, + meta: mutationOptions?.meta, }, { onSuccess: () => { From 94a56781d994096affc7831dd49e2890716921eb Mon Sep 17 00:00:00 2001 From: Antoine Fricker Date: Sat, 30 Jul 2022 00:27:13 +0200 Subject: [PATCH 03/44] Add meta support for bulk delete buttons --- .../src/button/BulkDeleteWithConfirmButton.tsx | 17 ++++++++++++++--- .../src/button/BulkDeleteWithUndoButton.tsx | 17 ++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/packages/ra-ui-materialui/src/button/BulkDeleteWithConfirmButton.tsx b/packages/ra-ui-materialui/src/button/BulkDeleteWithConfirmButton.tsx index 03d465f57fc..83164f66d59 100644 --- a/packages/ra-ui-materialui/src/button/BulkDeleteWithConfirmButton.tsx +++ b/packages/ra-ui-materialui/src/button/BulkDeleteWithConfirmButton.tsx @@ -14,11 +14,14 @@ import { useTranslate, useUnselectAll, useSafeSetState, + RaRecord, + DeleteManyParams, } from 'ra-core'; import { Confirm } from '../layout'; import { Button, ButtonProps } from './Button'; import { BulkActionProps } from '../types'; +import { UseMutationOptions } from 'react-query'; export const BulkDeleteWithConfirmButton = ( props: BulkDeleteWithConfirmButtonProps @@ -29,6 +32,7 @@ export const BulkDeleteWithConfirmButton = ( icon = defaultIcon, label = 'ra.action.delete', mutationMode = 'pessimistic', + mutationOptions = null, onClick, ...rest } = props; @@ -41,7 +45,7 @@ export const BulkDeleteWithConfirmButton = ( const translate = useTranslate(); const [deleteMany, { isLoading }] = useDeleteMany( resource, - { ids: selectedIds }, + { ids: selectedIds, meta: mutationOptions?.meta }, { onSuccess: () => { refresh(); @@ -141,13 +145,20 @@ const sanitizeRestProps = ({ 'resource' | 'icon' | 'mutationMode' >) => rest; -export interface BulkDeleteWithConfirmButtonProps - extends BulkActionProps, +export interface BulkDeleteWithConfirmButtonProps< + RecordType extends RaRecord = any, + MutationOptionsError = unknown +> extends BulkActionProps, ButtonProps { confirmContent?: React.ReactNode; confirmTitle?: string; icon?: ReactElement; mutationMode: MutationMode; + mutationOptions?: UseMutationOptions< + RecordType, + MutationOptionsError, + DeleteManyParams + >; } const PREFIX = 'RaBulkDeleteWithConfirmButton'; diff --git a/packages/ra-ui-materialui/src/button/BulkDeleteWithUndoButton.tsx b/packages/ra-ui-materialui/src/button/BulkDeleteWithUndoButton.tsx index 42385231af4..e4d1b7aa31f 100644 --- a/packages/ra-ui-materialui/src/button/BulkDeleteWithUndoButton.tsx +++ b/packages/ra-ui-materialui/src/button/BulkDeleteWithUndoButton.tsx @@ -11,10 +11,13 @@ import { useUnselectAll, useResourceContext, useListContext, + RaRecord, + DeleteManyParams, } from 'ra-core'; import { Button, ButtonProps } from './Button'; import { BulkActionProps } from '../types'; +import { UseMutationOptions } from 'react-query'; export const BulkDeleteWithUndoButton = ( props: BulkDeleteWithUndoButtonProps @@ -23,6 +26,7 @@ export const BulkDeleteWithUndoButton = ( label = 'ra.action.delete', icon = defaultIcon, onClick, + mutationOptions = null, ...rest } = props; const { selectedIds } = useListContext(props); @@ -36,7 +40,7 @@ export const BulkDeleteWithUndoButton = ( const handleClick = e => { deleteMany( resource, - { ids: selectedIds }, + { ids: selectedIds, meta: mutationOptions?.meta }, { onSuccess: () => { notify('ra.notification.deleted', { @@ -95,10 +99,17 @@ const sanitizeRestProps = ({ ...rest }: Omit) => rest; -export interface BulkDeleteWithUndoButtonProps - extends BulkActionProps, +export interface BulkDeleteWithUndoButtonProps< + RecordType extends RaRecord = any, + MutationOptionsError = unknown +> extends BulkActionProps, ButtonProps { icon?: ReactElement; + mutationOptions?: UseMutationOptions< + RecordType, + MutationOptionsError, + DeleteManyParams + >; } const PREFIX = 'RaBulkDeleteWithUndoButton'; From 603ccdc494656aeb842b804898292a591cdfb004 Mon Sep 17 00:00:00 2001 From: Antoine Fricker Date: Sat, 30 Jul 2022 01:06:30 +0200 Subject: [PATCH 04/44] Update doc --- docs/Buttons.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/Buttons.md b/docs/Buttons.md index 060d22d3eb3..f9979595ca3 100644 --- a/docs/Buttons.md +++ b/docs/Buttons.md @@ -244,11 +244,11 @@ export const PostList = () => ( ![Bulk Delete button](./img/bulk-delete-button.png) -| Prop | Required | Type | Default | Description | -| ------------ | -------- | --------------- | ------------------ | ----------------------------------- | -| `label` | Optional | `string` | 'ra.action.delete' | label or translation message to use | -| `icon` | Optional | `ReactElement` | `` | iconElement, e.g. `` | -| `exporter` | Optional | `Function` | - | Override the List exporter function | +| Prop | Required | Type | Default | Description | +| --------------------| -------- | --------------- | ------------------ | ---------------------------------------------------| +| `label` | Optional | `string` | 'ra.action.delete' | label or translation message to use | +| `icon` | Optional | `ReactElement` | `` | iconElement, e.g. `` | +| `mutationOptions` | Optional | `object` | null | options for react-query `useMutation` hook | ### `` @@ -277,6 +277,7 @@ Delete the current record after a confirm dialog has been accepted. To be used i | `confirmContent` | Optional | `ReactNode` | 'ra.message.delete_content' | Message or React component to be used as the body of the confirm dialog | | `redirect` | Optional | `string | false | Function` | 'list' | Custom redirection after success side effect | | `translateOptions` | Optional | `{ id?: string, name?: string }` | {} | Custom id and name to be used in the confirm dialog's title | +| `mutationOptions` | Optional | | null | options for react-query `useMutation` hook | {% raw %} ```jsx From e55f8deee8099417c01400a922115024e4cfa1db Mon Sep 17 00:00:00 2001 From: Antoine Fricker Date: Mon, 1 Aug 2022 14:11:17 +0200 Subject: [PATCH 05/44] Comment from PR --- .../button/useDeleteWithConfirmController.tsx | 10 ++++++---- .../controller/button/useDeleteWithUndoController.tsx | 10 ++++++---- .../src/button/BulkDeleteWithConfirmButton.tsx | 8 +++++--- .../src/button/BulkDeleteWithUndoButton.tsx | 8 +++++--- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/packages/ra-core/src/controller/button/useDeleteWithConfirmController.tsx b/packages/ra-core/src/controller/button/useDeleteWithConfirmController.tsx index 5f674ea4704..3bd9cc09541 100644 --- a/packages/ra-core/src/controller/button/useDeleteWithConfirmController.tsx +++ b/packages/ra-core/src/controller/button/useDeleteWithConfirmController.tsx @@ -71,8 +71,9 @@ const useDeleteWithConfirmController = ( redirect: redirectTo, mutationMode, onClick, - mutationOptions, + mutationOptions = {}, } = props; + const { meta: mutationMeta, ...otherMutationOptions } = mutationOptions; const resource = useResourceContext(props); const [open, setOpen] = useState(false); const notify = useNotify(); @@ -98,7 +99,7 @@ const useDeleteWithConfirmController = ( { id: record.id, previousData: record, - meta: mutationOptions?.meta, + meta: mutationMeta, }, { onSuccess: () => { @@ -132,7 +133,7 @@ const useDeleteWithConfirmController = ( ); }, mutationMode, - ...mutationOptions, + ...otherMutationOptions, } ); if (typeof onClick === 'function') { @@ -141,8 +142,9 @@ const useDeleteWithConfirmController = ( }, [ deleteOne, + mutationMeta, mutationMode, - mutationOptions, + otherMutationOptions, notify, onClick, record, diff --git a/packages/ra-core/src/controller/button/useDeleteWithUndoController.tsx b/packages/ra-core/src/controller/button/useDeleteWithUndoController.tsx index 1ff4f11fd63..a7c8af9bc0d 100644 --- a/packages/ra-core/src/controller/button/useDeleteWithUndoController.tsx +++ b/packages/ra-core/src/controller/button/useDeleteWithUndoController.tsx @@ -50,8 +50,9 @@ const useDeleteWithUndoController = ( record, redirect: redirectTo = 'list', onClick, - mutationOptions, + mutationOptions = {}, } = props; + const { meta: mutationMeta, ...otherMutationOptions } = mutationOptions; const resource = useResourceContext(props); const notify = useNotify(); const unselect = useUnselect(resource); @@ -66,7 +67,7 @@ const useDeleteWithUndoController = ( { id: record.id, previousData: record, - meta: mutationOptions?.meta, + meta: mutationMeta, }, { onSuccess: () => { @@ -97,7 +98,7 @@ const useDeleteWithUndoController = ( ); }, mutationMode: 'undoable', - ...mutationOptions, + ...otherMutationOptions, } ); if (typeof onClick === 'function') { @@ -106,7 +107,8 @@ const useDeleteWithUndoController = ( }, [ deleteOne, - mutationOptions, + mutationMeta, + otherMutationOptions, notify, onClick, record, diff --git a/packages/ra-ui-materialui/src/button/BulkDeleteWithConfirmButton.tsx b/packages/ra-ui-materialui/src/button/BulkDeleteWithConfirmButton.tsx index 83164f66d59..d6517116343 100644 --- a/packages/ra-ui-materialui/src/button/BulkDeleteWithConfirmButton.tsx +++ b/packages/ra-ui-materialui/src/button/BulkDeleteWithConfirmButton.tsx @@ -32,10 +32,11 @@ export const BulkDeleteWithConfirmButton = ( icon = defaultIcon, label = 'ra.action.delete', mutationMode = 'pessimistic', - mutationOptions = null, + mutationOptions = {}, onClick, ...rest } = props; + const { meta: mutationMeta, ...otherMutationOptions } = mutationOptions; const { selectedIds } = useListContext(props); const [isOpen, setOpen] = useSafeSetState(false); const notify = useNotify(); @@ -45,7 +46,7 @@ export const BulkDeleteWithConfirmButton = ( const translate = useTranslate(); const [deleteMany, { isLoading }] = useDeleteMany( resource, - { ids: selectedIds, meta: mutationOptions?.meta }, + { ids: selectedIds, meta: mutationMeta }, { onSuccess: () => { refresh(); @@ -77,6 +78,7 @@ export const BulkDeleteWithConfirmButton = ( setOpen(false); }, mutationMode, + ...otherMutationOptions, } ); @@ -158,7 +160,7 @@ export interface BulkDeleteWithConfirmButtonProps< RecordType, MutationOptionsError, DeleteManyParams - >; + > & { meta?: any }; } const PREFIX = 'RaBulkDeleteWithConfirmButton'; diff --git a/packages/ra-ui-materialui/src/button/BulkDeleteWithUndoButton.tsx b/packages/ra-ui-materialui/src/button/BulkDeleteWithUndoButton.tsx index e4d1b7aa31f..9876404c80b 100644 --- a/packages/ra-ui-materialui/src/button/BulkDeleteWithUndoButton.tsx +++ b/packages/ra-ui-materialui/src/button/BulkDeleteWithUndoButton.tsx @@ -26,9 +26,10 @@ export const BulkDeleteWithUndoButton = ( label = 'ra.action.delete', icon = defaultIcon, onClick, - mutationOptions = null, + mutationOptions = {}, ...rest } = props; + const { meta: mutationMeta, ...otherMutationOptions } = mutationOptions; const { selectedIds } = useListContext(props); const notify = useNotify(); @@ -40,7 +41,7 @@ export const BulkDeleteWithUndoButton = ( const handleClick = e => { deleteMany( resource, - { ids: selectedIds, meta: mutationOptions?.meta }, + { ids: selectedIds, meta: mutationMeta }, { onSuccess: () => { notify('ra.notification.deleted', { @@ -70,6 +71,7 @@ export const BulkDeleteWithUndoButton = ( refresh(); }, mutationMode: 'undoable', + ...otherMutationOptions, } ); if (typeof onClick === 'function') { @@ -109,7 +111,7 @@ export interface BulkDeleteWithUndoButtonProps< RecordType, MutationOptionsError, DeleteManyParams - >; + > & { meta?: any }; } const PREFIX = 'RaBulkDeleteWithUndoButton'; From ea98f3c9f12612367ef3165edb7d363e1ed1faab Mon Sep 17 00:00:00 2001 From: React-Admin CI Date: Wed, 3 Aug 2022 10:57:35 +0200 Subject: [PATCH 06/44] Fix ArrayInput Adding Previously Removed Item Fixes #7385 --- .../ArrayInput/SimpleFormIterator.spec.tsx | 52 +++++++++++++++++++ .../input/ArrayInput/SimpleFormIterator.tsx | 30 +++++------ 2 files changed, 65 insertions(+), 17 deletions(-) diff --git a/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.spec.tsx b/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.spec.tsx index fc3cea9b686..ccd27ef8545 100644 --- a/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.spec.tsx +++ b/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.spec.tsx @@ -348,6 +348,58 @@ describe('', () => { expect(screen.queryAllByText('ra.action.remove').length).toBe(1); }); + it('should add correct children with default value after removing one', async () => { + render( + + + + + + + + + + ); + + const removeFirstButton = getByText( + (screen.queryAllByLabelText( + 'CustomLabel' + )[0] as HTMLElement).closest('li'), + 'ra.action.remove' + ).closest('button'); + + fireEvent.click(removeFirstButton); + await waitFor(() => { + expect(screen.queryAllByLabelText('CustomLabel').length).toEqual(0); + }); + + const addItemElement = screen + .getByText('ra.action.add') + .closest('button'); + + fireEvent.click(addItemElement); + await waitFor(() => { + const inputElements = screen.queryAllByLabelText('CustomLabel'); + + expect(inputElements.length).toBe(1); + }); + + expect( + screen + .queryAllByLabelText('CustomLabel') + .map(inputElement => inputElement.value) + ).toEqual(['default@marmelab.com']); + + expect(screen.queryAllByText('ra.action.remove').length).toBe(1); + }); + it('should remove children row on remove button click', async () => { const emails = [{ email: 'foo@bar.com' }, { email: 'bar@foo.com' }]; diff --git a/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.tsx b/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.tsx index 2fd2431102b..2c2b69edb76 100644 --- a/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.tsx +++ b/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.tsx @@ -1,8 +1,7 @@ import * as React from 'react'; import { + Children, cloneElement, - MouseEvent, - MouseEventHandler, ReactElement, ReactNode, useCallback, @@ -56,21 +55,21 @@ export const SimpleFormIterator = (props: SimpleFormIteratorProps) => { const addField = useCallback( (item: any = undefined) => { - append(item); + let defaultValue = item; + if (item == null) { + defaultValue = {} as Record; + Children.forEach(children, input => { + if (React.isValidElement(input)) { + defaultValue[input.props.source] = + input.props.defaultValue ?? ''; + } + }); + } + append(defaultValue); }, - [append] + [append, children] ); - // add field and call the onClick event of the button passed as addButton prop - const handleAddButtonClick = ( - originalOnClickHandler: MouseEventHandler - ) => (event: MouseEvent) => { - addField(); - if (originalOnClickHandler) { - originalOnClickHandler(event); - } - }; - const handleReorder = useCallback( (origin: number, destination: number) => { move(origin, destination); @@ -118,9 +117,6 @@ export const SimpleFormIterator = (props: SimpleFormIteratorProps) => {
  • {cloneElement(addButton, { - onClick: handleAddButtonClick( - addButton.props.onClick - ), className: clsx( 'button-add', `button-add-${source}` From c487662cb4669fa375d2902a4fa881e53a63b16f Mon Sep 17 00:00:00 2001 From: React-Admin CI Date: Wed, 3 Aug 2022 11:12:35 +0200 Subject: [PATCH 07/44] Apply review --- .../ArrayInput/SimpleFormIterator.spec.tsx | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.spec.tsx b/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.spec.tsx index ccd27ef8545..64da1a4c4a2 100644 --- a/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.spec.tsx +++ b/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.spec.tsx @@ -354,14 +354,17 @@ describe('', () => { + @@ -369,15 +372,15 @@ describe('', () => { ); const removeFirstButton = getByText( - (screen.queryAllByLabelText( - 'CustomLabel' - )[0] as HTMLElement).closest('li'), + (screen.queryAllByLabelText('Email')[0] as HTMLElement).closest( + 'li' + ), 'ra.action.remove' ).closest('button'); fireEvent.click(removeFirstButton); await waitFor(() => { - expect(screen.queryAllByLabelText('CustomLabel').length).toEqual(0); + expect(screen.queryAllByLabelText('Email').length).toEqual(0); }); const addItemElement = screen @@ -386,16 +389,20 @@ describe('', () => { fireEvent.click(addItemElement); await waitFor(() => { - const inputElements = screen.queryAllByLabelText('CustomLabel'); - + const inputElements = screen.queryAllByLabelText('Email'); expect(inputElements.length).toBe(1); }); expect( screen - .queryAllByLabelText('CustomLabel') + .queryAllByLabelText('Email') .map(inputElement => inputElement.value) ).toEqual(['default@marmelab.com']); + expect( + screen + .queryAllByLabelText('Name') + .map(inputElement => inputElement.value) + ).toEqual(['']); expect(screen.queryAllByText('ra.action.remove').length).toBe(1); }); From e9bfa4c411651a6c0a12071d72b8bb1b32829658 Mon Sep 17 00:00:00 2001 From: Gildas Garcia <1122076+djhi@users.noreply.github.com> Date: Thu, 4 Aug 2022 11:10:37 +0200 Subject: [PATCH 08/44] Apply review --- .../src/input/ArrayInput/AddItemButton.tsx | 2 +- .../src/input/ArrayInput/SimpleFormIterator.tsx | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/ra-ui-materialui/src/input/ArrayInput/AddItemButton.tsx b/packages/ra-ui-materialui/src/input/ArrayInput/AddItemButton.tsx index bdaa7f2bde9..1d64ee16bcf 100644 --- a/packages/ra-ui-materialui/src/input/ArrayInput/AddItemButton.tsx +++ b/packages/ra-ui-materialui/src/input/ArrayInput/AddItemButton.tsx @@ -4,7 +4,7 @@ import { useSimpleFormIterator } from './useSimpleFormIterator'; import { Button, ButtonProps } from '../../button'; -export const AddItemButton = (props: Omit) => { +export const AddItemButton = (props: ButtonProps) => { const { add } = useSimpleFormIterator(); return (
  • From 83ff11ac41e2d7e424f90333eb44ba6bdd8719d2 Mon Sep 17 00:00:00 2001 From: Anthony Rimet Date: Thu, 4 Aug 2022 11:42:01 +0200 Subject: [PATCH 09/44] Feat: Add filter redirection for pending reviews --- examples/demo/src/dashboard/CardWithIcon.tsx | 4 ++-- examples/demo/src/dashboard/PendingReviews.tsx | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/examples/demo/src/dashboard/CardWithIcon.tsx b/examples/demo/src/dashboard/CardWithIcon.tsx index 69148933ff6..0446456ac3e 100644 --- a/examples/demo/src/dashboard/CardWithIcon.tsx +++ b/examples/demo/src/dashboard/CardWithIcon.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { FC, createElement } from 'react'; import { Card, Box, Typography, Divider } from '@mui/material'; -import { Link } from 'react-router-dom'; +import { Link, To } from 'react-router-dom'; import { ReactNode } from 'react'; import cartouche from './cartouche.png'; @@ -9,7 +9,7 @@ import cartoucheDark from './cartoucheDark.png'; interface Props { icon: FC; - to: string; + to: To; title?: string; subtitle?: string | number; children?: ReactNode; diff --git a/examples/demo/src/dashboard/PendingReviews.tsx b/examples/demo/src/dashboard/PendingReviews.tsx index 840984811eb..193790d8c40 100644 --- a/examples/demo/src/dashboard/PendingReviews.tsx +++ b/examples/demo/src/dashboard/PendingReviews.tsx @@ -19,6 +19,8 @@ import { useIsDataLoaded, } from 'react-admin'; +import { stringify } from 'query-string'; + import CardWithIcon from './CardWithIcon'; import StarRatingField from '../reviews/StarRatingField'; import { Customer, Review } from '../types'; @@ -43,7 +45,12 @@ const PendingReviews = () => { return ( Date: Thu, 4 Aug 2022 16:19:36 +0200 Subject: [PATCH 10/44] Add unit tests --- .../useDeleteWithConfirmController.spec.tsx | 49 +++++++++++++++++++ .../useDeleteWithUndoController.spec.tsx | 49 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 packages/ra-core/src/controller/button/useDeleteWithConfirmController.spec.tsx create mode 100644 packages/ra-core/src/controller/button/useDeleteWithUndoController.spec.tsx diff --git a/packages/ra-core/src/controller/button/useDeleteWithConfirmController.spec.tsx b/packages/ra-core/src/controller/button/useDeleteWithConfirmController.spec.tsx new file mode 100644 index 00000000000..68caad1e0b8 --- /dev/null +++ b/packages/ra-core/src/controller/button/useDeleteWithConfirmController.spec.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import expect from 'expect'; +import { MemoryRouter, Route, Routes } from 'react-router'; +import { fireEvent, screen, render, waitFor } from '@testing-library/react'; + +import { testDataProvider } from '../../dataProvider'; +import { CoreAdminContext } from '../../core'; +import useDeleteWithConfirmController, { + UseDeleteWithConfirmControllerParams, +} from './useDeleteWithConfirmController'; + +describe('useDeleteWithConfirmController', () => { + it('should call the dataProvider.delete() function with the meta param', async () => { + let receivedMeta = null; + const dataProvider = testDataProvider({ + delete: jest.fn((ressource, params) => { + receivedMeta = params?.meta?.key; + console.log(receivedMeta); + return Promise.resolve({ data: params?.meta?.key }); + }), + }); + + const MockComponent = () => { + const { handleDelete } = useDeleteWithConfirmController({ + record: { id: 1 }, + resource: 'posts', + mutationMode: 'pessimistic', + mutationOptions: { meta: { key: 'metadata' } }, + } as UseDeleteWithConfirmControllerParams); + return ; + }; + + render( + + + + } /> + + + + ); + + await screen.getByText('Delete'); + fireEvent.click(screen.getByText('Delete')); + waitFor(() => expect(receivedMeta).toEqual('metadata'), { + timeout: 1000, + }); + }); +}); diff --git a/packages/ra-core/src/controller/button/useDeleteWithUndoController.spec.tsx b/packages/ra-core/src/controller/button/useDeleteWithUndoController.spec.tsx new file mode 100644 index 00000000000..10c70f1acc2 --- /dev/null +++ b/packages/ra-core/src/controller/button/useDeleteWithUndoController.spec.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import expect from 'expect'; +import { MemoryRouter, Route, Routes } from 'react-router'; +import { fireEvent, screen, render, waitFor } from '@testing-library/react'; + +import { testDataProvider } from '../../dataProvider'; +import { CoreAdminContext } from '../../core'; +import useDeleteWithUndoController, { + UseDeleteWithConfirmControllerParams, +} from './useDeleteWithConfirmController'; + +describe('useDeleteWithUndoController', () => { + it('should call the dataProvider.delete() function with the meta param', async () => { + let receivedMeta = null; + const dataProvider = testDataProvider({ + delete: jest.fn((ressource, params) => { + receivedMeta = params?.meta?.key; + console.log(receivedMeta); + return Promise.resolve({ data: params?.meta?.key }); + }), + }); + + const MockComponent = () => { + const { handleDelete } = useDeleteWithUndoController({ + record: { id: 1 }, + resource: 'posts', + mutationMode: 'undoable', + mutationOptions: { meta: { key: 'metadata' } }, + } as UseDeleteWithConfirmControllerParams); + return ; + }; + + render( + + + + } /> + + + + ); + + await screen.getByText('Delete'); + fireEvent.click(screen.getByText('Delete')); + waitFor(() => expect(receivedMeta).toEqual('metadata'), { + timeout: 1000, + }); + }); +}); From 35a81b928d4c2bceef170f48c0fa8b85b3a75fa2 Mon Sep 17 00:00:00 2001 From: Antoine Fricker Date: Thu, 4 Aug 2022 18:08:02 +0200 Subject: [PATCH 11/44] Unit test corrections --- .../button/useDeleteWithConfirmController.spec.tsx | 5 ++--- .../controller/button/useDeleteWithUndoController.spec.tsx | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/ra-core/src/controller/button/useDeleteWithConfirmController.spec.tsx b/packages/ra-core/src/controller/button/useDeleteWithConfirmController.spec.tsx index 68caad1e0b8..2b624854457 100644 --- a/packages/ra-core/src/controller/button/useDeleteWithConfirmController.spec.tsx +++ b/packages/ra-core/src/controller/button/useDeleteWithConfirmController.spec.tsx @@ -15,7 +15,6 @@ describe('useDeleteWithConfirmController', () => { const dataProvider = testDataProvider({ delete: jest.fn((ressource, params) => { receivedMeta = params?.meta?.key; - console.log(receivedMeta); return Promise.resolve({ data: params?.meta?.key }); }), }); @@ -40,8 +39,8 @@ describe('useDeleteWithConfirmController', () => { ); - await screen.getByText('Delete'); - fireEvent.click(screen.getByText('Delete')); + const button = await screen.findByText('Delete'); + fireEvent.click(button); waitFor(() => expect(receivedMeta).toEqual('metadata'), { timeout: 1000, }); diff --git a/packages/ra-core/src/controller/button/useDeleteWithUndoController.spec.tsx b/packages/ra-core/src/controller/button/useDeleteWithUndoController.spec.tsx index 10c70f1acc2..b3ec571e384 100644 --- a/packages/ra-core/src/controller/button/useDeleteWithUndoController.spec.tsx +++ b/packages/ra-core/src/controller/button/useDeleteWithUndoController.spec.tsx @@ -15,7 +15,6 @@ describe('useDeleteWithUndoController', () => { const dataProvider = testDataProvider({ delete: jest.fn((ressource, params) => { receivedMeta = params?.meta?.key; - console.log(receivedMeta); return Promise.resolve({ data: params?.meta?.key }); }), }); @@ -40,8 +39,8 @@ describe('useDeleteWithUndoController', () => { ); - await screen.getByText('Delete'); - fireEvent.click(screen.getByText('Delete')); + const button = await screen.findByText('Delete'); + fireEvent.click(button); waitFor(() => expect(receivedMeta).toEqual('metadata'), { timeout: 1000, }); From 0847d2b42ae69be5ee5e190896f4a9aa7a88f726 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Zaninotto?= Date: Thu, 4 Aug 2022 22:26:25 +0200 Subject: [PATCH 12/44] [Demo] Fix poster category selector shows id instead of name --- examples/demo/src/products/ProductEditDetails.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/demo/src/products/ProductEditDetails.tsx b/examples/demo/src/products/ProductEditDetails.tsx index e55fc2a8deb..1f492e74dda 100644 --- a/examples/demo/src/products/ProductEditDetails.tsx +++ b/examples/demo/src/products/ProductEditDetails.tsx @@ -15,7 +15,7 @@ export const ProductEditDetails = () => ( - + From ce98e65c39e5855b9dbf894fdf9155faf0312e69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Zaninotto?= Date: Fri, 5 Aug 2022 00:54:20 +0200 Subject: [PATCH 13/44] [TypeScript] Fix MenuItemLink prop type isn't exported --- packages/ra-ui-materialui/src/layout/MenuItemLink.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ra-ui-materialui/src/layout/MenuItemLink.tsx b/packages/ra-ui-materialui/src/layout/MenuItemLink.tsx index 572e84016ae..22475521d2c 100644 --- a/packages/ra-ui-materialui/src/layout/MenuItemLink.tsx +++ b/packages/ra-ui-materialui/src/layout/MenuItemLink.tsx @@ -65,7 +65,7 @@ import { useTranslate, useBasename } from 'ra-core'; * * ); */ -export const MenuItemLink = forwardRef((props: MenuItemLinkProps, ref) => { +export const MenuItemLink = forwardRef((props, ref) => { const { className, primaryText, @@ -101,8 +101,8 @@ export const MenuItemLink = forwardRef((props: MenuItemLinkProps, ref) => { className={clsx(className, { [MenuItemLinkClasses.active]: !!match, })} - component={LinkRef} // @ts-ignore + component={LinkRef} ref={ref} tabIndex={0} {...rest} From 847e35aec4fa31f6730fc0cefbbb658f11fd4d42 Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Fri, 5 Aug 2022 15:11:18 +0200 Subject: [PATCH 14/44] Prepare changelog for v4.2.6 --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f70dbdacf64..ea6dbdbe936 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## v4.2.6 + +* Fix `` ignores `meta` parameter ([#8023](https://github.com/marmelab/react-admin/pull/8023)) ([septentrion-730n](https://github.com/septentrion-730n)) +* Fix `` state only changes on blur ([#8033](https://github.com/marmelab/react-admin/pull/8033)) ([fzaninotto](https://github.com/fzaninotto)) +* Fix `` adds previously removed item ([#8029](https://github.com/marmelab/react-admin/pull/8029)) ([djhi](https://github.com/djhi)) +* [TypeScript] Fix `` prop type isn't exported ([#8040](https://github.com/marmelab/react-admin/pull/8040)) ([fzaninotto](https://github.com/fzaninotto)) +* [Doc] Add Search component ([#8021](https://github.com/marmelab/react-admin/pull/8021)) ([fzaninotto](https://github.com/fzaninotto)) +* [Doc] Fix typos in Search documentation ([#8024](https://github.com/marmelab/react-admin/pull/8024)) ([septentrion-730n](https://github.com/septentrion-730n)) +* [Demo] Fix Pending reviews link on Dashboard ([#8036](https://github.com/marmelab/react-admin/pull/8036)) ([arimet](https://github.com/arimet)) +* [Demo] Fix Category List does not use RecordContext ([#8035](https://github.com/marmelab/react-admin/pull/8035)) ([arimet](https://github.com/arimet)) + ## v4.2.5 - Fix Input label proptypes and `` imports ([#8019](https://github.com/marmelab/react-admin/pull/8019)) by ([megantaylor](https://github.com/megantaylor)) From 9592083f0454bc599826ec538125a796d93e8d15 Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Fri, 5 Aug 2022 15:11:53 +0200 Subject: [PATCH 15/44] v4.2.6 --- examples/data-generator/package.json | 4 ++-- examples/simple/package.json | 14 +++++++------- lerna.json | 2 +- packages/ra-core/package.json | 2 +- packages/ra-data-fakerest/package.json | 4 ++-- packages/ra-data-json-server/package.json | 4 ++-- packages/ra-data-localstorage/package.json | 4 ++-- packages/ra-data-simple-rest/package.json | 4 ++-- packages/ra-i18n-polyglot/package.json | 4 ++-- packages/ra-input-rich-text/package.json | 10 +++++----- packages/ra-language-english/package.json | 4 ++-- packages/ra-language-french/package.json | 4 ++-- packages/ra-no-code/package.json | 6 +++--- packages/ra-ui-materialui/package.json | 8 ++++---- packages/react-admin/package.json | 10 +++++----- 15 files changed, 42 insertions(+), 42 deletions(-) diff --git a/examples/data-generator/package.json b/examples/data-generator/package.json index de217c5a727..79fa4fa5133 100644 --- a/examples/data-generator/package.json +++ b/examples/data-generator/package.json @@ -1,6 +1,6 @@ { "name": "data-generator-retail", - "version": "4.2.5", + "version": "4.2.6", "homepage": "https://github.com/marmelab/react-admin/tree/master/examples/data-generator", "bugs": "https://github.com/marmelab/react-admin/issues", "license": "MIT", @@ -19,7 +19,7 @@ }, "devDependencies": { "cross-env": "^5.2.0", - "ra-core": "^4.2.5", + "ra-core": "^4.2.6", "rimraf": "^3.0.2", "typescript": "^4.4.0" }, diff --git a/examples/simple/package.json b/examples/simple/package.json index 696048e6342..72f4eee1c1d 100644 --- a/examples/simple/package.json +++ b/examples/simple/package.json @@ -1,6 +1,6 @@ { "name": "simple", - "version": "4.2.5", + "version": "4.2.6", "private": true, "scripts": { "dev": "webpack-dev-server --progress --color --hot --mode development", @@ -18,13 +18,13 @@ "lodash": "~4.17.5", "prop-types": "^15.7.2", "proxy-polyfill": "^0.3.0", - "ra-data-fakerest": "^4.2.5", - "ra-i18n-polyglot": "^4.2.5", - "ra-input-rich-text": "^4.2.5", - "ra-language-english": "^4.2.5", - "ra-language-french": "^4.2.5", + "ra-data-fakerest": "^4.2.6", + "ra-i18n-polyglot": "^4.2.6", + "ra-input-rich-text": "^4.2.6", + "ra-language-english": "^4.2.6", + "ra-language-french": "^4.2.6", "react": "^17.0.0", - "react-admin": "^4.2.5", + "react-admin": "^4.2.6", "react-dom": "^17.0.0", "react-hook-form": "^7.31.0", "react-query": "^3.32.1", diff --git a/lerna.json b/lerna.json index a0f0b08dbbc..9032f9a5249 100644 --- a/lerna.json +++ b/lerna.json @@ -5,5 +5,5 @@ "examples/simple", "packages/*" ], - "version": "4.2.5" + "version": "4.2.6" } diff --git a/packages/ra-core/package.json b/packages/ra-core/package.json index 0f63f36efd9..9bc739cfefd 100644 --- a/packages/ra-core/package.json +++ b/packages/ra-core/package.json @@ -1,6 +1,6 @@ { "name": "ra-core", - "version": "4.2.5", + "version": "4.2.6", "description": "Core components of react-admin, a frontend Framework for building admin applications on top of REST services, using ES6, React", "files": [ "*.md", diff --git a/packages/ra-data-fakerest/package.json b/packages/ra-data-fakerest/package.json index 8239dc68486..7cd2d2a9f1a 100644 --- a/packages/ra-data-fakerest/package.json +++ b/packages/ra-data-fakerest/package.json @@ -1,6 +1,6 @@ { "name": "ra-data-fakerest", - "version": "4.2.5", + "version": "4.2.6", "description": "JSON Server data provider for react-admin", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", @@ -41,7 +41,7 @@ }, "devDependencies": { "cross-env": "^5.2.0", - "ra-core": "^4.2.5", + "ra-core": "^4.2.6", "rimraf": "^3.0.2", "typescript": "^4.4.0" }, diff --git a/packages/ra-data-json-server/package.json b/packages/ra-data-json-server/package.json index ab3c9f1de63..e7701c6e120 100644 --- a/packages/ra-data-json-server/package.json +++ b/packages/ra-data-json-server/package.json @@ -1,6 +1,6 @@ { "name": "ra-data-json-server", - "version": "4.2.5", + "version": "4.2.6", "description": "JSON Server data provider for react-admin", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", @@ -26,7 +26,7 @@ }, "dependencies": { "query-string": "^7.1.1", - "ra-core": "^4.2.5" + "ra-core": "^4.2.6" }, "devDependencies": { "cross-env": "^5.2.0", diff --git a/packages/ra-data-localstorage/package.json b/packages/ra-data-localstorage/package.json index f2cf16ccc3f..e2be494505b 100644 --- a/packages/ra-data-localstorage/package.json +++ b/packages/ra-data-localstorage/package.json @@ -1,6 +1,6 @@ { "name": "ra-data-local-storage", - "version": "4.2.5", + "version": "4.2.6", "description": "Local storage data provider for react-admin", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", @@ -38,7 +38,7 @@ }, "dependencies": { "lodash": "~4.17.5", - "ra-data-fakerest": "^4.2.5" + "ra-data-fakerest": "^4.2.6" }, "devDependencies": { "cross-env": "^5.2.0", diff --git a/packages/ra-data-simple-rest/package.json b/packages/ra-data-simple-rest/package.json index eaeb476de8b..39d732cb4ca 100644 --- a/packages/ra-data-simple-rest/package.json +++ b/packages/ra-data-simple-rest/package.json @@ -1,6 +1,6 @@ { "name": "ra-data-simple-rest", - "version": "4.2.5", + "version": "4.2.6", "description": "Simple REST data provider for react-admin", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", @@ -29,7 +29,7 @@ }, "devDependencies": { "cross-env": "^5.2.0", - "ra-core": "^4.2.5", + "ra-core": "^4.2.6", "rimraf": "^3.0.2", "typescript": "^4.4.0" }, diff --git a/packages/ra-i18n-polyglot/package.json b/packages/ra-i18n-polyglot/package.json index 053ecdc61d8..4b803b37bed 100644 --- a/packages/ra-i18n-polyglot/package.json +++ b/packages/ra-i18n-polyglot/package.json @@ -1,6 +1,6 @@ { "name": "ra-i18n-polyglot", - "version": "4.2.5", + "version": "4.2.6", "description": "Polyglot i18n provider for react-admin", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", @@ -26,7 +26,7 @@ }, "dependencies": { "node-polyglot": "^2.2.2", - "ra-core": "^4.2.5" + "ra-core": "^4.2.6" }, "devDependencies": { "cross-env": "^5.2.0", diff --git a/packages/ra-input-rich-text/package.json b/packages/ra-input-rich-text/package.json index d8220835936..1188fcdd218 100644 --- a/packages/ra-input-rich-text/package.json +++ b/packages/ra-input-rich-text/package.json @@ -1,6 +1,6 @@ { "name": "ra-input-rich-text", - "version": "4.2.5", + "version": "4.2.6", "description": " component for react-admin, useful for editing HTML code in admin GUIs.", "author": "Gildas Garcia", "repository": "marmelab/react-admin", @@ -47,10 +47,10 @@ "@mui/icons-material": "^5.0.1", "@mui/material": "^5.0.2", "@testing-library/react": "^11.2.3", - "data-generator-retail": "^4.2.5", - "ra-core": "^4.2.5", - "ra-data-fakerest": "^4.2.5", - "ra-ui-materialui": "^4.2.5", + "data-generator-retail": "^4.2.6", + "ra-core": "^4.2.6", + "ra-data-fakerest": "^4.2.6", + "ra-ui-materialui": "^4.2.6", "react": "^17.0.0", "react-dom": "^17.0.0", "react-hook-form": "^7.31.0", diff --git a/packages/ra-language-english/package.json b/packages/ra-language-english/package.json index e4531d0fd4d..930576cb3e3 100644 --- a/packages/ra-language-english/package.json +++ b/packages/ra-language-english/package.json @@ -1,6 +1,6 @@ { "name": "ra-language-english", - "version": "4.2.5", + "version": "4.2.6", "description": "English messages for react-admin, the frontend framework for building admin applications on top of REST/GraphQL services", "repository": { "type": "git", @@ -21,7 +21,7 @@ "watch": "tsc --outDir dist/esm --module es2015 --watch" }, "dependencies": { - "ra-core": "^4.2.5" + "ra-core": "^4.2.6" }, "devDependencies": { "rimraf": "^3.0.2", diff --git a/packages/ra-language-french/package.json b/packages/ra-language-french/package.json index 9c8c3497c6f..2315de4a77c 100644 --- a/packages/ra-language-french/package.json +++ b/packages/ra-language-french/package.json @@ -1,6 +1,6 @@ { "name": "ra-language-french", - "version": "4.2.5", + "version": "4.2.6", "description": "French messages for react-admin, the frontend framework for building admin applications on top of REST/GraphQL services", "repository": { "type": "git", @@ -16,7 +16,7 @@ "watch": "tsc --outDir dist/esm --module es2015 --watch" }, "dependencies": { - "ra-core": "^4.2.5" + "ra-core": "^4.2.6" }, "devDependencies": { "rimraf": "^3.0.2", diff --git a/packages/ra-no-code/package.json b/packages/ra-no-code/package.json index 962d0fa51e0..3254f5cfb41 100644 --- a/packages/ra-no-code/package.json +++ b/packages/ra-no-code/package.json @@ -1,6 +1,6 @@ { "name": "ra-no-code", - "version": "4.2.5", + "version": "4.2.6", "description": "", "files": [ "*.md", @@ -48,8 +48,8 @@ "lodash": "~4.17.5", "papaparse": "^5.3.0", "prop-types": "^15.6.1", - "ra-data-local-storage": "^4.2.5", - "react-admin": "^4.2.5", + "ra-data-local-storage": "^4.2.6", + "react-admin": "^4.2.6", "react-dropzone": "^12.0.4", "react-query": "^3.32.1" } diff --git a/packages/ra-ui-materialui/package.json b/packages/ra-ui-materialui/package.json index 8c4182a9876..a33a1d33e44 100644 --- a/packages/ra-ui-materialui/package.json +++ b/packages/ra-ui-materialui/package.json @@ -1,6 +1,6 @@ { "name": "ra-ui-materialui", - "version": "4.2.5", + "version": "4.2.6", "description": "UI Components for react-admin with MUI", "files": [ "*.md", @@ -34,9 +34,9 @@ "file-api": "~0.10.4", "history": "^5.1.0", "ignore-styles": "~5.0.1", - "ra-core": "^4.2.5", - "ra-i18n-polyglot": "^4.2.5", - "ra-language-english": "^4.2.5", + "ra-core": "^4.2.6", + "ra-i18n-polyglot": "^4.2.6", + "ra-language-english": "^4.2.6", "react": "^17.0.0", "react-dom": "^17.0.0", "react-hook-form": "^7.31.0", diff --git a/packages/react-admin/package.json b/packages/react-admin/package.json index 62d69a283a5..e6663272f76 100644 --- a/packages/react-admin/package.json +++ b/packages/react-admin/package.json @@ -1,6 +1,6 @@ { "name": "react-admin", - "version": "4.2.5", + "version": "4.2.6", "description": "A frontend Framework for building admin applications on top of REST services, using ES6, React and Material UI", "files": [ "*.md", @@ -41,10 +41,10 @@ "@mui/icons-material": "^5.0.1", "@mui/material": "^5.0.2", "history": "^5.1.0", - "ra-core": "^4.2.5", - "ra-i18n-polyglot": "^4.2.5", - "ra-language-english": "^4.2.5", - "ra-ui-materialui": "^4.2.5", + "ra-core": "^4.2.6", + "ra-i18n-polyglot": "^4.2.6", + "ra-language-english": "^4.2.6", + "ra-ui-materialui": "^4.2.6", "react-hook-form": "^7.31.0", "react-router": "^6.1.0", "react-router-dom": "^6.1.0" From f956e85648a06e3db4b2e30319309c490280b447 Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Fri, 5 Aug 2022 15:16:52 +0200 Subject: [PATCH 16/44] Fix yarn.lock --- yarn.lock | 74 +++++++++++++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/yarn.lock b/yarn.lock index 0e9bdef678c..84e54090c36 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10626,14 +10626,14 @@ __metadata: languageName: node linkType: hard -"data-generator-retail@^4.0.0, data-generator-retail@^4.2.5, data-generator-retail@workspace:examples/data-generator": +"data-generator-retail@^4.0.0, data-generator-retail@^4.2.6, data-generator-retail@workspace:examples/data-generator": version: 0.0.0-use.local resolution: "data-generator-retail@workspace:examples/data-generator" dependencies: cross-env: ^5.2.0 date-fns: ^2.19.0 faker: ^4.1.0 - ra-core: ^4.2.5 + ra-core: ^4.2.6 rimraf: ^3.0.2 typescript: ^4.4.0 peerDependencies: @@ -20987,7 +20987,7 @@ __metadata: languageName: node linkType: hard -"ra-core@^4.2.5, ra-core@workspace:packages/ra-core": +"ra-core@^4.2.6, ra-core@workspace:packages/ra-core": version: 0.0.0-use.local resolution: "ra-core@workspace:packages/ra-core" dependencies: @@ -21031,13 +21031,13 @@ __metadata: languageName: unknown linkType: soft -"ra-data-fakerest@^4.0.0, ra-data-fakerest@^4.2.5, ra-data-fakerest@workspace:packages/ra-data-fakerest": +"ra-data-fakerest@^4.0.0, ra-data-fakerest@^4.2.6, ra-data-fakerest@workspace:packages/ra-data-fakerest": version: 0.0.0-use.local resolution: "ra-data-fakerest@workspace:packages/ra-data-fakerest" dependencies: cross-env: ^5.2.0 fakerest: ^3.0.0 - ra-core: ^4.2.5 + ra-core: ^4.2.6 rimraf: ^3.0.2 typescript: ^4.4.0 peerDependencies: @@ -21087,19 +21087,19 @@ __metadata: dependencies: cross-env: ^5.2.0 query-string: ^7.1.1 - ra-core: ^4.2.5 + ra-core: ^4.2.6 rimraf: ^3.0.2 typescript: ^4.4.0 languageName: unknown linkType: soft -"ra-data-local-storage@^4.0.0, ra-data-local-storage@^4.2.5, ra-data-local-storage@workspace:packages/ra-data-localstorage": +"ra-data-local-storage@^4.0.0, ra-data-local-storage@^4.2.6, ra-data-local-storage@workspace:packages/ra-data-localstorage": version: 0.0.0-use.local resolution: "ra-data-local-storage@workspace:packages/ra-data-localstorage" dependencies: cross-env: ^5.2.0 lodash: ~4.17.5 - ra-data-fakerest: ^4.2.5 + ra-data-fakerest: ^4.2.6 rimraf: ^3.0.2 typescript: ^4.4.0 peerDependencies: @@ -21113,7 +21113,7 @@ __metadata: dependencies: cross-env: ^5.2.0 query-string: ^7.1.1 - ra-core: ^4.2.5 + ra-core: ^4.2.6 rimraf: ^3.0.2 typescript: ^4.4.0 peerDependencies: @@ -21121,19 +21121,19 @@ __metadata: languageName: unknown linkType: soft -"ra-i18n-polyglot@^4.0.0, ra-i18n-polyglot@^4.2.5, ra-i18n-polyglot@workspace:packages/ra-i18n-polyglot": +"ra-i18n-polyglot@^4.0.0, ra-i18n-polyglot@^4.2.6, ra-i18n-polyglot@workspace:packages/ra-i18n-polyglot": version: 0.0.0-use.local resolution: "ra-i18n-polyglot@workspace:packages/ra-i18n-polyglot" dependencies: cross-env: ^5.2.0 node-polyglot: ^2.2.2 - ra-core: ^4.2.5 + ra-core: ^4.2.6 rimraf: ^3.0.2 typescript: ^4.4.0 languageName: unknown linkType: soft -"ra-input-rich-text@^4.0.0, ra-input-rich-text@^4.2.5, ra-input-rich-text@workspace:packages/ra-input-rich-text": +"ra-input-rich-text@^4.0.0, ra-input-rich-text@^4.2.6, ra-input-rich-text@workspace:packages/ra-input-rich-text": version: 0.0.0-use.local resolution: "ra-input-rich-text@workspace:packages/ra-input-rich-text" dependencies: @@ -21151,10 +21151,10 @@ __metadata: "@tiptap/react": ^2.0.0-beta.63 "@tiptap/starter-kit": ^2.0.0-beta.101 clsx: ^1.1.1 - data-generator-retail: ^4.2.5 - ra-core: ^4.2.5 - ra-data-fakerest: ^4.2.5 - ra-ui-materialui: ^4.2.5 + data-generator-retail: ^4.2.6 + ra-core: ^4.2.6 + ra-data-fakerest: ^4.2.6 + ra-ui-materialui: ^4.2.6 react: ^17.0.0 react-dom: ^17.0.0 react-hook-form: ^7.31.0 @@ -21170,21 +21170,21 @@ __metadata: languageName: unknown linkType: soft -"ra-language-english@^4.0.0, ra-language-english@^4.2.5, ra-language-english@workspace:packages/ra-language-english": +"ra-language-english@^4.0.0, ra-language-english@^4.2.6, ra-language-english@workspace:packages/ra-language-english": version: 0.0.0-use.local resolution: "ra-language-english@workspace:packages/ra-language-english" dependencies: - ra-core: ^4.2.5 + ra-core: ^4.2.6 rimraf: ^3.0.2 typescript: ^4.4.0 languageName: unknown linkType: soft -"ra-language-french@^4.0.0, ra-language-french@^4.2.5, ra-language-french@workspace:packages/ra-language-french": +"ra-language-french@^4.0.0, ra-language-french@^4.2.6, ra-language-french@workspace:packages/ra-language-french": version: 0.0.0-use.local resolution: "ra-language-french@workspace:packages/ra-language-french" dependencies: - ra-core: ^4.2.5 + ra-core: ^4.2.6 rimraf: ^3.0.2 typescript: ^4.4.0 languageName: unknown @@ -21205,9 +21205,9 @@ __metadata: lodash: ~4.17.5 papaparse: ^5.3.0 prop-types: ^15.6.1 - ra-data-local-storage: ^4.2.5 + ra-data-local-storage: ^4.2.6 react: ^17.0.0 - react-admin: ^4.2.5 + react-admin: ^4.2.6 react-dom: ^17.0.0 react-dropzone: ^12.0.4 react-query: ^3.32.1 @@ -21221,7 +21221,7 @@ __metadata: languageName: unknown linkType: soft -"ra-ui-materialui@^4.2.5, ra-ui-materialui@workspace:packages/ra-ui-materialui": +"ra-ui-materialui@^4.2.6, ra-ui-materialui@workspace:packages/ra-ui-materialui": version: 0.0.0-use.local resolution: "ra-ui-materialui@workspace:packages/ra-ui-materialui" dependencies: @@ -21241,9 +21241,9 @@ __metadata: lodash: ~4.17.5 prop-types: ^15.7.0 query-string: ^7.1.1 - ra-core: ^4.2.5 - ra-i18n-polyglot: ^4.2.5 - ra-language-english: ^4.2.5 + ra-core: ^4.2.6 + ra-i18n-polyglot: ^4.2.6 + ra-language-english: ^4.2.6 react: ^17.0.0 react-dom: ^17.0.0 react-dropzone: ^12.0.4 @@ -21428,7 +21428,7 @@ __metadata: languageName: unknown linkType: soft -"react-admin@^4.0.0, react-admin@^4.2.5, react-admin@workspace:packages/react-admin": +"react-admin@^4.0.0, react-admin@^4.2.6, react-admin@workspace:packages/react-admin": version: 0.0.0-use.local resolution: "react-admin@workspace:packages/react-admin" dependencies: @@ -21439,10 +21439,10 @@ __metadata: cross-env: ^5.2.0 expect: ^27.4.6 history: ^5.1.0 - ra-core: ^4.2.5 - ra-i18n-polyglot: ^4.2.5 - ra-language-english: ^4.2.5 - ra-ui-materialui: ^4.2.5 + ra-core: ^4.2.6 + ra-i18n-polyglot: ^4.2.6 + ra-language-english: ^4.2.6 + ra-ui-materialui: ^4.2.6 react-hook-form: ^7.31.0 react-router: ^6.1.0 react-router-dom: ^6.1.0 @@ -23472,13 +23472,13 @@ __metadata: lodash: ~4.17.5 prop-types: ^15.7.2 proxy-polyfill: ^0.3.0 - ra-data-fakerest: ^4.2.5 - ra-i18n-polyglot: ^4.2.5 - ra-input-rich-text: ^4.2.5 - ra-language-english: ^4.2.5 - ra-language-french: ^4.2.5 + ra-data-fakerest: ^4.2.6 + ra-i18n-polyglot: ^4.2.6 + ra-input-rich-text: ^4.2.6 + ra-language-english: ^4.2.6 + ra-language-french: ^4.2.6 react: ^17.0.0 - react-admin: ^4.2.5 + react-admin: ^4.2.6 react-app-polyfill: ^1.0.4 react-dom: ^17.0.0 react-hook-form: ^7.31.0 From 9454956ab578cecd99a9f3d82bdc3d311876bd6f Mon Sep 17 00:00:00 2001 From: Antoine Fricker Date: Sat, 6 Aug 2022 00:18:34 +0200 Subject: [PATCH 17/44] Add `customStoreKey` property [skip ci] --- .../src/controller/list/useListController.ts | 11 ++++++---- .../src/controller/list/useListParams.ts | 22 ++++++++++--------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/packages/ra-core/src/controller/list/useListController.ts b/packages/ra-core/src/controller/list/useListController.ts index b70c00c4ca9..a951ec78764 100644 --- a/packages/ra-core/src/controller/list/useListController.ts +++ b/packages/ra-core/src/controller/list/useListController.ts @@ -33,6 +33,7 @@ export const useListController = ( props: ListControllerProps = {} ): ListControllerResult => { const { + customStoreKey, disableAuthentication, exporter = defaultExporter, filterDefaultValues, @@ -62,12 +63,13 @@ export const useListController = ( const notify = useNotify(); const [query, queryModifiers] = useListParams({ - resource, - filterDefaultValues, - sort, - perPage, + customStoreKey, debounce, disableSyncWithLocation, + filterDefaultValues, + perPage, + resource, + sort, }); const [selectedIds, selectionModifiers] = useRecordSelection(resource); @@ -175,6 +177,7 @@ export const useListController = ( }; export interface ListControllerProps { + customStoreKey?: string; debounce?: number; disableAuthentication?: boolean; /** diff --git a/packages/ra-core/src/controller/list/useListParams.ts b/packages/ra-core/src/controller/list/useListParams.ts index 78af6a47c57..59be1705fae 100644 --- a/packages/ra-core/src/controller/list/useListParams.ts +++ b/packages/ra-core/src/controller/list/useListParams.ts @@ -77,17 +77,18 @@ export interface ListParams { * } = listParamsActions; */ export const useListParams = ({ - resource, - filterDefaultValues, - sort = defaultSort, - perPage = 10, + customStoreKey = '', debounce = 500, disableSyncWithLocation = false, + filterDefaultValues, + perPage = 10, + resource, + sort = defaultSort, }: ListParamsOptions): [Parameters, Modifiers] => { const location = useLocation(); const navigate = useNavigate(); const [localParams, setLocalParams] = useState(defaultParams); - const storeKey = `${resource}.listParams`; + const storeKey = `${resource}${customStoreKey}.listParams`; const [params, setParams] = useStore(storeKey, defaultParams); const tempParams = useRef(); const isMounted = useIsMounted(); @@ -367,15 +368,16 @@ export const getNumberOrDefault = ( }; export interface ListParamsOptions { - resource: string; - perPage?: number; - sort?: SortPayload; - // default value for a filter when displayed but not yet set - filterDefaultValues?: FilterPayload; + customStoreKey?: string; debounce?: number; // Whether to disable the synchronization of the list parameters with // the current location (URL search parameters) disableSyncWithLocation?: boolean; + // default value for a filter when displayed but not yet set + filterDefaultValues?: FilterPayload; + perPage?: number; + resource: string; + sort?: SortPayload; } interface Parameters extends ListParams { From d379cbaeb3e62226511177c7509c2124326b20fe Mon Sep 17 00:00:00 2001 From: Antoine Fricker Date: Sat, 6 Aug 2022 01:14:45 +0200 Subject: [PATCH 18/44] Add feature documentation [skip ci] --- docs/useListController.md | 6 ++++++ packages/ra-core/src/controller/list/useListController.ts | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/useListController.md b/docs/useListController.md index b9f970162e2..4313e7cb1f1 100644 --- a/docs/useListController.md +++ b/docs/useListController.md @@ -33,6 +33,7 @@ const MyList = () => { `useListController` expects one object as parameter. All keys are optional. +* [`customStoreKey`](#customStoreKey): additional key used to differenciate the list from another of the same resource * [`debounce`](./List.md#debounce): debounce time in ms for the setFilters callbacks * [`disableAuthentication`](./List.md#disableauthentication): set to true to allow anonymous access to the list * [`disableSyncWithLocation`](./List.md#disablesyncwithlocation): set to true to have more than one list per page @@ -54,6 +55,7 @@ import { } from 'react-admin'; const MyList = ({ + customStoreKey = '', debounce = 500, disableAuthentication = false, disableSyncWithLocation = false, @@ -85,6 +87,10 @@ const MyList = ({ }; ``` +## `customStoreKey` + +To display multiple lists of the same resource and keep distinct store states for each of them (filters, pagination, selection), specify unique keys with the `customStoreKey` property. + ## Return Value The return value of `useListController` has the following shape: diff --git a/packages/ra-core/src/controller/list/useListController.ts b/packages/ra-core/src/controller/list/useListController.ts index a951ec78764..377bdf58585 100644 --- a/packages/ra-core/src/controller/list/useListController.ts +++ b/packages/ra-core/src/controller/list/useListController.ts @@ -33,7 +33,7 @@ export const useListController = ( props: ListControllerProps = {} ): ListControllerResult => { const { - customStoreKey, + customStoreKey = '', disableAuthentication, exporter = defaultExporter, filterDefaultValues, From a65472a14f71304d86639680a84c056a57b1074d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Zaninotto?= Date: Mon, 8 Aug 2022 07:00:30 +0200 Subject: [PATCH 19/44] [Doc] Improve ImageField, NumberField and SelectField docs --- docs/ImageField.md | 74 +++++++++++++++++++------- docs/NumberField.md | 58 +++++++++++++++------ docs/SelectField.md | 104 +++++++++++++++++++++++++++++++------ docs/img/number-field.webp | Bin 0 -> 27482 bytes 4 files changed, 184 insertions(+), 52 deletions(-) create mode 100644 docs/img/number-field.webp diff --git a/docs/ImageField.md b/docs/ImageField.md index ada7254b909..9e37b9fb71a 100644 --- a/docs/ImageField.md +++ b/docs/ImageField.md @@ -5,7 +5,9 @@ title: "The ImageField Component" # `` -If you need to display an image based on a path contained in a record field, you can use the `` component: +When you need to display an image based on a path contained in a record field, use the `` component. + +## Usage ```jsx import { ImageField } from 'react-admin'; @@ -18,9 +20,28 @@ import { ImageField } from 'react-admin'; ``` +You can also use `` on fields that contain an array of image objects: + +```js + + +// Renders the record +// { +// id: 123, +// pictures: [ +// { url: 'image1.jpg', desc: 'First image' }, +// { url: 'image2.jpg', desc: 'Second image' }, +// ] +// } as +
      +
    • +
    • +
    +``` + This field is also often used within the [``](./ImageInput.md) component to display a preview. -## Properties +## Props | Prop | Required | Type | Default | Description | | ------- | -------- | ------ | ------------ | ---------------------------------------------------------------------------------------- | @@ -29,18 +50,23 @@ This field is also often used within the [``](./ImageInput.md) com `` also accepts the [common field props](./Fields.md#common-field-props). -## `sx`: CSS API +## `src` -The `` component accepts the usual `className` prop. You can also override many styles of the inner components thanks to the `sx` property (as most MUI components, see their [documentation about it](https://mui.com/customization/how-to-customize/#overriding-nested-component-styles)). This property accepts the following subclasses: +If the record actually contains an array of images in the property defined by the `source` prop, the `src` prop will be needed to determine the `src` value of the images, for example: -| Rule name | Description | -|-------------------------|--------------------------------------------------------------------------------| -| `& .RaImageField-list` | Applied to the underlying `