Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to omit basePath in Reference fields #6028

Merged
merged 2 commits into from
Mar 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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