Skip to content

Commit

Permalink
Merge pull request #6028 from marmelab/optional-basepath
Browse files Browse the repository at this point in the history
Add ability to omit basePath in Reference fields
  • Loading branch information
djhi authored Mar 15, 2021
2 parents 76def6e + 2d2e4ed commit 557f384
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 46 deletions.
6 changes: 4 additions & 2 deletions examples/simple/src/comments/CommentList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
CardHeader,
Grid,
Toolbar,
Typography,
useMediaQuery,
} from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
Expand Down Expand Up @@ -160,13 +161,14 @@ const CommentGrid = () => {
<TextField record={data[id]} source="body" />
</CardContent>
<CardContent className={classes.cardLink}>
{translate('comment.list.about')}&nbsp;
<Typography component="span" variant="body2">
{translate('comment.list.about')}&nbsp;
</Typography>
<ReferenceField
resource="comments"
record={data[id]}
source="post_id"
reference="posts"
basePath={basePath}
>
<TextField
source="title"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ describe('<ReferenceArrayFieldController />', () => {
<ReferenceArrayFieldController
resource="foo"
reference="bar"
basePath=""
record={{ id: 1, barIds: [1, 2] }}
source="barIds"
>
Expand All @@ -30,7 +29,7 @@ describe('<ReferenceArrayFieldController />', () => {
}
);
expect(children.mock.calls[0][0]).toMatchObject({
basePath: '',
basePath: '/bar',
currentSort: { field: 'id', order: 'ASC' },
loaded: false,
loading: true,
Expand All @@ -49,7 +48,6 @@ describe('<ReferenceArrayFieldController />', () => {
resource="foo"
reference="bar"
source="barIds"
basePath=""
>
{children}
</ReferenceArrayFieldController>,
Expand All @@ -70,7 +68,7 @@ describe('<ReferenceArrayFieldController />', () => {
);

expect(children.mock.calls[0][0]).toMatchObject({
basePath: '',
basePath: '/bar',
currentSort: { field: 'id', order: 'ASC' },
loaded: false,
loading: true,
Expand All @@ -93,7 +91,6 @@ describe('<ReferenceArrayFieldController />', () => {
resource="foo"
reference="bar"
source="barIds"
basePath=""
>
{children}
</ReferenceArrayFieldController>,
Expand All @@ -111,7 +108,7 @@ describe('<ReferenceArrayFieldController />', () => {
}
);
expect(children.mock.calls[0][0]).toMatchObject({
basePath: '',
basePath: '/bar',
currentSort: { field: 'id', order: 'ASC' },
loaded: true,
loading: true,
Expand All @@ -132,7 +129,6 @@ describe('<ReferenceArrayFieldController />', () => {
resource="foo"
reference="bar"
source="barIds"
basePath=""
>
{children}
</ReferenceArrayFieldController>,
Expand All @@ -150,7 +146,7 @@ describe('<ReferenceArrayFieldController />', () => {
}
);
expect(children.mock.calls[0][0]).toMatchObject({
basePath: '',
basePath: '/bar',
currentSort: { field: 'id', order: 'ASC' },
loaded: true,
loading: true,
Expand Down Expand Up @@ -182,7 +178,6 @@ describe('<ReferenceArrayFieldController />', () => {
resource="foo"
reference="bar"
source="barIds"
basePath=""
>
{children}
</ReferenceArrayFieldController>
Expand Down Expand Up @@ -212,7 +207,6 @@ describe('<ReferenceArrayFieldController />', () => {
resource="foo"
reference="bar"
source="barIds"
basePath=""
>
{children}
</ReferenceArrayFieldController>,
Expand All @@ -230,7 +224,7 @@ describe('<ReferenceArrayFieldController />', () => {
}
);
expect(children.mock.calls[0][0]).toMatchObject({
basePath: '',
basePath: '/bar',
currentSort: { field: 'id', order: 'ASC' },
loaded: true,
loading: true,
Expand All @@ -251,7 +245,6 @@ describe('<ReferenceArrayFieldController />', () => {
resource="foo"
reference="bar"
source="barIds"
basePath=""
>
{children}
</ReferenceArrayFieldController>,
Expand All @@ -271,7 +264,7 @@ describe('<ReferenceArrayFieldController />', () => {
}
);
expect(children.mock.calls[0][0]).toMatchObject({
basePath: '',
basePath: '/bar',
currentSort: { field: 'id', order: 'ASC' },
loaded: true,
loading: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
47 changes: 22 additions & 25 deletions packages/ra-core/src/controller/field/getResourceLinkPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ export type LinkToFunctionType = (record: Record, reference: string) => 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;
}

/**
Expand All @@ -31,7 +34,7 @@ interface Option {
* },
* resource: 'comments',
* source: 'userId',
* });
* }); // '/users/7'
*
* @param {Object} option
* @param {string} option.basePath basepath to current resource
Expand All @@ -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 <ReferenceField />"
);
}
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;
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import useSortState from '../useSortState';
import { useResourceContext } from '../../core';

interface Options {
basePath: string;
basePath?: string;
data?: RecordMap;
filter?: any;
ids?: any[];
Expand Down Expand Up @@ -186,7 +186,9 @@ const useReferenceManyFieldController = (
);

return {
basePath: basePath.replace(resource, reference),
basePath: basePath
? basePath.replace(resource, reference)
: `/${reference}`,
currentSort: sort,
data,
defaultTitle: null,
Expand Down
22 changes: 22 additions & 0 deletions packages/ra-ui-materialui/src/field/ReferenceField.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -335,5 +335,27 @@ describe('<ReferenceField />', () => {
const links = container.getElementsByTagName('a');
expect(links).toHaveLength(0);
});

it('should work without basePath', () => {
const { container } = render(
<MemoryRouter>
<ReferenceFieldView
record={record}
source="postId"
referenceRecord={{ id: 123, title: 'foo' }}
reference="posts"
resource="comments"
resourceLinkPath="/posts/123"
loaded={true}
loading={false}
>
<TextField source="title" />
</ReferenceFieldView>
</MemoryRouter>
);
const links = container.getElementsByTagName('a');
expect(links).toHaveLength(1);
expect(links.item(0).href).toBe('http://localhost/posts/123');
});
});
});
2 changes: 1 addition & 1 deletion packages/ra-ui-materialui/src/field/ReferenceManyField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down

0 comments on commit 557f384

Please sign in to comment.