From dc39f186bc946517c995194bfa3eb21015052210 Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Fri, 12 Mar 2021 08:28:12 +0100 Subject: [PATCH 1/2] Add ability to omit basePath in Reference fields --- examples/simple/src/comments/CommentList.tsx | 6 ++- .../controller/field/getResourceLinkPath.ts | 47 +++++++++---------- .../field/useReferenceArrayFieldController.ts | 6 ++- .../field/useReferenceManyFieldController.ts | 6 ++- .../src/field/ReferenceField.spec.tsx | 22 +++++++++ .../src/field/ReferenceManyField.tsx | 2 +- 6 files changed, 57 insertions(+), 32 deletions(-) diff --git a/examples/simple/src/comments/CommentList.tsx b/examples/simple/src/comments/CommentList.tsx index fcefb451c29..2ff2894a68c 100644 --- a/examples/simple/src/comments/CommentList.tsx +++ b/examples/simple/src/comments/CommentList.tsx @@ -11,6 +11,7 @@ import { CardHeader, Grid, Toolbar, + Typography, useMediaQuery, } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; @@ -160,13 +161,14 @@ const CommentGrid = () => { - {translate('comment.list.about')}  + + {translate('comment.list.about')}  + string; export type LinkToType = string | boolean | LinkToFunctionType; interface Option { - basePath: string; - record?: Record; source: string; reference: string; resource: string; + basePath?: string; + record?: Record; link?: LinkToType; - linkType?: LinkToType; // deprecated, use link instead + /** + * @deprecated use link instead + */ + linkType?: LinkToType; } /** @@ -31,7 +34,7 @@ interface Option { * }, * resource: 'comments', * source: 'userId', - * }); + * }); // '/users/7' * * @param {Object} option * @param {string} option.basePath basepath to current resource @@ -42,38 +45,32 @@ interface Option { * @param {string} option.resource The current resource name * @param {string} option.source The key of the linked resource identifier * - * @returns {string | false} The reference props + * @returns {string | false} The link to the reference record */ const getResourceLinkPath = ({ - basePath, - link = 'edit', - linkType, - reference, - record = { id: '' }, resource, source, + reference, + link = 'edit', + record = { id: '' }, + basePath = `/${resource}`, + linkType, }: Option): string | false => { - const sourceId = get(record, source); - const rootPath = basePath.replace(resource, reference); - // Backward compatibility: keep linkType but with warning - const getResourceLinkPath = (linkTo: LinkToType) => - !linkTo - ? false - : typeof linkTo === 'function' - ? linkTo(record, reference) - : linkToRecord(rootPath, sourceId, linkTo as string); - if (linkType !== undefined) { console.warn( "The 'linkType' prop is deprecated and should be named to 'link' in " ); } + const sourceId = get(record, source); + const rootPath = basePath.replace(resource, reference); + const linkTo: LinkToType = linkType !== undefined ? linkType : link; - const resourceLinkPath = getResourceLinkPath( - linkType !== undefined ? linkType : link - ); - - return resourceLinkPath; + // Backward compatibility: keep linkType but with warning + return !linkTo + ? false + : typeof linkTo === 'function' + ? linkTo(record, reference) + : linkToRecord(rootPath, sourceId, linkTo as string); }; export default getResourceLinkPath; diff --git a/packages/ra-core/src/controller/field/useReferenceArrayFieldController.ts b/packages/ra-core/src/controller/field/useReferenceArrayFieldController.ts index 25441498935..95d906b485f 100644 --- a/packages/ra-core/src/controller/field/useReferenceArrayFieldController.ts +++ b/packages/ra-core/src/controller/field/useReferenceArrayFieldController.ts @@ -14,7 +14,7 @@ import { useResourceContext } from '../../core'; import { indexById } from '../../util/indexById'; interface Option { - basePath: string; + basePath?: string; filter?: any; page?: number; perPage?: number; @@ -212,7 +212,9 @@ const useReferenceArrayFieldController = ( ]); return { - basePath: basePath.replace(resource, reference), + basePath: basePath + ? basePath.replace(resource, reference) + : `/${reference}`, currentSort: sort, data: finalData, defaultTitle: null, diff --git a/packages/ra-core/src/controller/field/useReferenceManyFieldController.ts b/packages/ra-core/src/controller/field/useReferenceManyFieldController.ts index d553641da66..534552c2162 100644 --- a/packages/ra-core/src/controller/field/useReferenceManyFieldController.ts +++ b/packages/ra-core/src/controller/field/useReferenceManyFieldController.ts @@ -13,7 +13,7 @@ import useSortState from '../useSortState'; import { useResourceContext } from '../../core'; interface Options { - basePath: string; + basePath?: string; data?: RecordMap; filter?: any; ids?: any[]; @@ -186,7 +186,9 @@ const useReferenceManyFieldController = ( ); return { - basePath: basePath.replace(resource, reference), + basePath: basePath + ? basePath.replace(resource, reference) + : `/${reference}`, currentSort: sort, data, defaultTitle: null, diff --git a/packages/ra-ui-materialui/src/field/ReferenceField.spec.tsx b/packages/ra-ui-materialui/src/field/ReferenceField.spec.tsx index fa376fa993b..76e0e9e2045 100644 --- a/packages/ra-ui-materialui/src/field/ReferenceField.spec.tsx +++ b/packages/ra-ui-materialui/src/field/ReferenceField.spec.tsx @@ -335,5 +335,27 @@ describe('', () => { const links = container.getElementsByTagName('a'); expect(links).toHaveLength(0); }); + + it('should work without basePath', () => { + const { container } = render( + + + + + + ); + const links = container.getElementsByTagName('a'); + expect(links).toHaveLength(1); + expect(links.item(0).href).toBe('http://localhost/posts/123'); + }); }); }); diff --git a/packages/ra-ui-materialui/src/field/ReferenceManyField.tsx b/packages/ra-ui-materialui/src/field/ReferenceManyField.tsx index 7cd85bcce43..3fa136b0613 100644 --- a/packages/ra-ui-materialui/src/field/ReferenceManyField.tsx +++ b/packages/ra-ui-materialui/src/field/ReferenceManyField.tsx @@ -170,7 +170,7 @@ export interface ReferenceManyFieldViewProps } ReferenceManyFieldView.propTypes = { - basePath: PropTypes.string, + basePath: PropTypes.string.isRequired, children: PropTypes.element, className: PropTypes.string, currentSort: PropTypes.exact({ From 2d2e4edcfe7c0ddb654db2bfc9b77df611dfe727 Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Fri, 12 Mar 2021 08:54:34 +0100 Subject: [PATCH 2/2] Fix unit tests --- .../ReferenceArrayFieldController.spec.tsx | 19 ++++++------------- .../field/ReferenceArrayFieldController.tsx | 2 +- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/packages/ra-core/src/controller/field/ReferenceArrayFieldController.spec.tsx b/packages/ra-core/src/controller/field/ReferenceArrayFieldController.spec.tsx index d957a5455e9..5ad3c41aa22 100644 --- a/packages/ra-core/src/controller/field/ReferenceArrayFieldController.spec.tsx +++ b/packages/ra-core/src/controller/field/ReferenceArrayFieldController.spec.tsx @@ -13,7 +13,6 @@ describe('', () => { @@ -30,7 +29,7 @@ describe('', () => { } ); expect(children.mock.calls[0][0]).toMatchObject({ - basePath: '', + basePath: '/bar', currentSort: { field: 'id', order: 'ASC' }, loaded: false, loading: true, @@ -49,7 +48,6 @@ describe('', () => { resource="foo" reference="bar" source="barIds" - basePath="" > {children} , @@ -70,7 +68,7 @@ describe('', () => { ); expect(children.mock.calls[0][0]).toMatchObject({ - basePath: '', + basePath: '/bar', currentSort: { field: 'id', order: 'ASC' }, loaded: false, loading: true, @@ -93,7 +91,6 @@ describe('', () => { resource="foo" reference="bar" source="barIds" - basePath="" > {children} , @@ -111,7 +108,7 @@ describe('', () => { } ); expect(children.mock.calls[0][0]).toMatchObject({ - basePath: '', + basePath: '/bar', currentSort: { field: 'id', order: 'ASC' }, loaded: true, loading: true, @@ -132,7 +129,6 @@ describe('', () => { resource="foo" reference="bar" source="barIds" - basePath="" > {children} , @@ -150,7 +146,7 @@ describe('', () => { } ); expect(children.mock.calls[0][0]).toMatchObject({ - basePath: '', + basePath: '/bar', currentSort: { field: 'id', order: 'ASC' }, loaded: true, loading: true, @@ -182,7 +178,6 @@ describe('', () => { resource="foo" reference="bar" source="barIds" - basePath="" > {children} @@ -212,7 +207,6 @@ describe('', () => { resource="foo" reference="bar" source="barIds" - basePath="" > {children} , @@ -230,7 +224,7 @@ describe('', () => { } ); expect(children.mock.calls[0][0]).toMatchObject({ - basePath: '', + basePath: '/bar', currentSort: { field: 'id', order: 'ASC' }, loaded: true, loading: true, @@ -251,7 +245,6 @@ describe('', () => { resource="foo" reference="bar" source="barIds" - basePath="" > {children} , @@ -271,7 +264,7 @@ describe('', () => { } ); expect(children.mock.calls[0][0]).toMatchObject({ - basePath: '', + basePath: '/bar', currentSort: { field: 'id', order: 'ASC' }, loaded: true, loading: true, diff --git a/packages/ra-core/src/controller/field/ReferenceArrayFieldController.tsx b/packages/ra-core/src/controller/field/ReferenceArrayFieldController.tsx index b68e5feed19..e82a6a4950e 100644 --- a/packages/ra-core/src/controller/field/ReferenceArrayFieldController.tsx +++ b/packages/ra-core/src/controller/field/ReferenceArrayFieldController.tsx @@ -5,7 +5,7 @@ import { ListControllerProps } from '../useListController'; import { Record, SortPayload } from '../../types'; interface Props { - basePath: string; + basePath?: string; filter?: any; page?: number; perPage?: number;