Skip to content

Commit

Permalink
Handle redirection via onClick
Browse files Browse the repository at this point in the history
  • Loading branch information
Travis CI committed Sep 20, 2021
1 parent 2ac4a7a commit dac4459
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 35 deletions.
37 changes: 33 additions & 4 deletions packages/ra-ui-materialui/src/list/SimpleList.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { render, waitFor, within } from '@testing-library/react';
import { fireEvent, render, waitFor, within } from '@testing-library/react';
import { createMemoryHistory } from 'history';
import { Router } from 'react-router-dom';
import { ListContext } from 'ra-core';
Expand All @@ -8,7 +8,7 @@ import SimpleList from './SimpleList';
import TextField from '../field/TextField';

const renderWithRouter = children => {
const history = createMemoryHistory();
const history = createMemoryHistory({ initialEntries: ['/posts'] });

return {
history,
Expand Down Expand Up @@ -60,7 +60,7 @@ describe('<SimpleList />', () => {
(record, id, basePath) => `${basePath}/${id}/details`,
],
])('should support %s linkType', async (_, expectedUrl, linkType) => {
const { getByText } = renderWithRouter(
const { history, getByText } = renderWithRouter(
<ListContext.Provider
value={{
loaded: true,
Expand All @@ -83,10 +83,39 @@ describe('<SimpleList />', () => {
</ListContext.Provider>
);

fireEvent.click(getByText('1'));
await waitFor(() => {
expect(getByText('1').closest('a').getAttribute('href')).toEqual(
expect(history.entries[history.length - 1].pathname).toEqual(
expectedUrl
);
});
});
it('should not render a link if linkType is false', async () => {
const { getByText } = renderWithRouter(
<ListContext.Provider
value={{
loaded: true,
loading: false,
ids: [1, 2],
data: {
1: { id: 1, title: 'foo' },
2: { id: 2, title: 'bar' },
},
total: 2,
resource: 'posts',
basePath: '/posts',
}}
>
<SimpleList
linkType={false}
primaryText={record => record.id.toString()}
secondaryText={<TextField source="title" />}
/>
</ListContext.Provider>
);

await waitFor(() => {
expect(getByText('1').closest('a')).toBeNull();
});
});
});
64 changes: 33 additions & 31 deletions packages/ra-ui-materialui/src/list/SimpleList.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import * as React from 'react';
import {
isValidElement,
ReactNode,
ReactElement,
useEffect,
useState,
} from 'react';
import { isValidElement, ReactNode, ReactElement, useCallback } from 'react';
import PropTypes from 'prop-types';
import {
Avatar,
Expand All @@ -18,7 +12,7 @@ import {
ListItemText,
} from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
import { Link } from 'react-router-dom';
import { useHistory } from 'react-router-dom';
import {
Identifier,
linkToRecord,
Expand Down Expand Up @@ -140,7 +134,7 @@ const SimpleList = <RecordType extends Record = Record>(
resource={resource}
>
<ListItem
button={!!linkType as any}
component="div"
style={
rowStyle
? rowStyle(data[id], rowIndex)
Expand Down Expand Up @@ -283,38 +277,46 @@ const LinkOrNot = (props: LinkOrNotProps) => {
resource,
} = props;
const classes = useLinkOrNotStyles({ classes: classesOverride });
const [effect, setEffect] = useState<string>(() =>
linkType === 'edit' || linkType === true
? linkToRecord(basePath || `/${resource}`, id)
: linkToRecord(basePath || `/${resource}`, id, 'show')
);
const history = useHistory();

useEffect(() => {
if (typeof linkType !== 'function') {
return;
}
const getEffect = async () => {
if (typeof linkType === 'function') {
setEffect(
await linkType(record, id, basePath || `/${resource}`)
);
}
};
const handleClick = useCallback(
async event => {
if (!linkType) return;
event.persist();

getEffect();
}, [basePath, id, linkType, record, resource]);
const effect =
typeof linkType === 'function'
? await linkType(record, id, basePath || `/${resource}`)
: linkType;
switch (effect) {
case true:
case 'edit':
history.push(linkToRecord(basePath || `/${resource}`, id));
return;
case 'show':
history.push(
linkToRecord(basePath || `/${resource}`, id, 'show')
);
return;
default:
if (effect) history.push(effect);
return;
}
},
[basePath, history, id, record, resource, linkType]
);

return typeof effect === 'string' ? (
<Link to={effect} className={classes.link}>
return linkType !== false ? (
<button onClick={handleClick} className={classes.link}>
{children}
</Link>
</button>
) : (
<span>{children}</span>
);
};

export type FunctionLinkType = (
record: Record,
recordOrId: Record,
id: Identifier,
basePath?: string
) => string | Promise<string>;
Expand Down

0 comments on commit dac4459

Please sign in to comment.