Skip to content

Commit

Permalink
refacto(SimpleList): deprecate linkType => rowClick
Browse files Browse the repository at this point in the history
  • Loading branch information
Quentin Decré committed Nov 13, 2024
1 parent 41c4d36 commit 68c7c65
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 60 deletions.
21 changes: 11 additions & 10 deletions docs/SimpleList.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const PostList = () => (
primaryText={record => record.title}
secondaryText={record => `${record.views} views`}
tertiaryText={record => new Date(record.published_at).toLocaleDateString()}
linkType={record => record.canEdit ? "edit" : "show"}
rowClick={record => record.canEdit ? "edit" : "show"}
rowSx={record => ({ backgroundColor: record.nb_views >= 500 ? '#efe' : 'white' })}
/>
</List>
Expand All @@ -44,7 +44,7 @@ export const PostList = () => (
| `primaryText` | Optional | mixed | record representation | The primary text to display. |
| `secondaryText` | Optional | mixed | | The secondary text to display. |
| `tertiaryText` | Optional | mixed | | The tertiary text to display. |
| `linkType` | Optional |mixed | `"edit"` | The target of each item click. |
| `rowClick` | Optional |mixed | `"edit"` | The action to trigger when the user clicks on a row. |
| `leftAvatar` | Optional | function | | A function returning an `<Avatar>` component to display before the primary text. |
| `leftIcon` | Optional | function | | A function returning an `<Icon>` component to display before the primary text. |
| `rightAvatar` | Optional | function | | A function returning an `<Avatar>` component to display after the primary text. |
Expand Down Expand Up @@ -80,9 +80,9 @@ This prop should be a function returning an `<Avatar>` component. When present,

This prop should be a function returning an `<Icon>` component. When present, the `<ListItem>` renders a `<ListIcon>` before the `<ListItemText>`

## `linkType`
## `rowClick`

The `<SimpleList>` items link to the edition page by default. You can also set the `linkType` prop to `show` directly to link to the `<Show>` page instead.
The `<SimpleList>` items link to the edition page by default. You can also set the `rowClick` prop to `show` directly to link to the `<Show>` page instead.

```jsx
import { List, SimpleList } from 'react-admin';
Expand All @@ -93,17 +93,18 @@ export const PostList = () => (
primaryText={record => record.title}
secondaryText={record => `${record.views} views`}
tertiaryText={record => new Date(record.published_at).toLocaleDateString()}
linkType="show"
rowClick="show"
/>
</List>
);
```

`linkType` accepts the following values:
`rowClick` accepts the following values:

* `linkType="edit"`: links to the edit page. This is the default behavior.
* `linkType="show"`: links to the show page.
* `linkType={false}`: does not create any link.
* `rowClick="edit"`: links to the edit page. This is the default behavior.
* `rowClick="show"`: links to the show page.
* `rowClick={false}`: does not link to anything.
* `rowClick={(id, resource, record) => path}`: path can be any of the above values

## `primaryText`

Expand Down Expand Up @@ -254,7 +255,7 @@ export const PostList = () => {
primaryText={record => record.title}
secondaryText={record => `${record.views} views`}
tertiaryText={record => new Date(record.published_at).toLocaleDateString()}
linkType={record => record.canEdit ? "edit" : "show"}
rowClick={record => record.canEdit ? "edit" : "show"}
/>
) : (
<Datagrid>
Expand Down
155 changes: 105 additions & 50 deletions packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,39 @@
import * as React from 'react';
import { styled } from '@mui/material/styles';
import type { SxProps } from '@mui/material';
import { isValidElement, ReactNode, ReactElement } from 'react';
import {
Avatar,
List,
ListProps,
ListItem,
ListItemAvatar,
ListItemButton,
ListItemIcon,
ListItemProps,
ListItemSecondaryAction,
ListItemText,
ListProps,
} from '@mui/material';
import { Link } from 'react-router-dom';
import { styled } from '@mui/material/styles';
import {
Identifier,
RaRecord,
RecordContextProvider,
sanitizeListRestProps,
useGetRecordRepresentation,
useListContextWithProps,
useResourceContext,
useGetRecordRepresentation,
useCreatePath,
useTranslate,
} from 'ra-core';
import * as React from 'react';
import { isValidElement, ReactElement, ReactNode } from 'react';
import { Link } from 'react-router-dom';

import { SimpleListLoading } from './SimpleListLoading';
import { ListNoResults } from '../ListNoResults';
import { SimpleListLoading } from './SimpleListLoading';

import { useGetPathForRecordCallback } from 'ra-core';
import { useCallback } from 'react';
import { useNavigate } from 'react-router-dom';

import { RowClickFunction } from 'react-admin';

/**
* The <SimpleList> component renders a list of records as a Material UI <List>.
Expand All @@ -44,7 +49,8 @@ import { ListNoResults } from '../ListNoResults';
* - leftIcon: same
* - rightAvatar: same
* - rightIcon: same
* - linkType: 'edit' or 'show', or a function returning 'edit' or 'show' based on the record
* - linkType: deprecated 'edit' or 'show', or a function returning 'edit' or 'show' based on the record
* - rowClick: The action to trigger when the user clicks on a row. @see https://marmelab.com/react-admin/Datagrid.html#rowclick
* - rowStyle: function returning a style object based on (record, index)
* - rowSx: function returning a sx object based on (record, index)
*
Expand All @@ -65,7 +71,7 @@ import { ListNoResults } from '../ListNoResults';
* </List>
* );
*/
export const SimpleList = <RecordType extends RaRecord = any>(
export const SimpleListJarvi = <RecordType extends RaRecord = any>(
props: SimpleListProps<RecordType>
) => {
const {
Expand All @@ -74,7 +80,8 @@ export const SimpleList = <RecordType extends RaRecord = any>(
hasBulkActions,
leftAvatar,
leftIcon,
linkType = 'edit',
linkType,
rowClick = 'edit',
primaryText,
rightAvatar,
rightIcon,
Expand All @@ -84,8 +91,9 @@ export const SimpleList = <RecordType extends RaRecord = any>(
rowStyle,
...rest
} = props;
const { data, isPending, total } =
useListContextWithProps<RecordType>(props);
const { data, isPending, total } = useListContextWithProps<RecordType>(

Check failure on line 94 in packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Replace `·useListContextWithProps<RecordType>(⏎········props⏎····` with `⏎········useListContextWithProps<RecordType>(props`
props
);
const resource = useResourceContext(props);
const getRecordRepresentation = useGetRecordRepresentation(resource);
const translate = useTranslate();
Expand Down Expand Up @@ -131,7 +139,9 @@ export const SimpleList = <RecordType extends RaRecord = any>(
<RecordContextProvider key={record.id} value={record}>
<ListItem disablePadding>
<LinkOrNot
//@deprecated: use rowClick instead
linkType={linkType}
rowClick={rowClick}
resource={resource}
id={record.id}
record={record}
Expand Down Expand Up @@ -162,12 +172,9 @@ export const SimpleList = <RecordType extends RaRecord = any>(
_: primaryText,
})
: isValidElement(primaryText)
? primaryText
: // @ts-ignore
primaryText(
record,
record.id
)
? primaryText

Check failure on line 175 in packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Insert `··`
: // @ts-ignore

Check failure on line 176 in packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Insert `··`
primaryText(record, record.id)

Check failure on line 177 in packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Replace `primaryText(record,·record.id` with `··primaryText(⏎························································record,⏎························································record.id⏎····················································`
: getRecordRepresentation(record)}

{!!tertiaryText &&
Expand All @@ -189,14 +196,14 @@ export const SimpleList = <RecordType extends RaRecord = any>(
}
)
: isValidElement(
tertiaryText
)
? tertiaryText
: // @ts-ignore
tertiaryText(
record,
record.id
)}
tertiaryText

Check failure on line 199 in packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Insert `··`
)

Check failure on line 200 in packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Insert `··`
? tertiaryText

Check failure on line 201 in packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Insert `··`
: // @ts-ignore

Check failure on line 202 in packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Insert `··`
tertiaryText(

Check failure on line 203 in packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Insert `··`
record,

Check failure on line 204 in packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Insert `··`
record.id
)}
</span>
))}
</div>
Expand All @@ -209,9 +216,9 @@ export const SimpleList = <RecordType extends RaRecord = any>(
_: secondaryText,
})
: isValidElement(secondaryText)
? secondaryText
: // @ts-ignore
secondaryText(record, record.id))
? secondaryText
: // @ts-ignore
secondaryText(record, record.id))
}
/>
{(rightAvatar || rightIcon) && (
Expand Down Expand Up @@ -249,7 +256,27 @@ export interface SimpleListProps<RecordType extends RaRecord = any>
leftAvatar?: FunctionToElement<RecordType>;
leftIcon?: FunctionToElement<RecordType>;
primaryText?: FunctionToElement<RecordType> | ReactElement | string;
/**
* @deprecated use rowClick instead
*/
linkType?: string | FunctionLinkType | false;

/**
* The action to trigger when the user clicks on a row.
*
* @see https://marmelab.com/react-admin/Datagrid.html#rowclick
* @example
* import { List, Datagrid } from 'react-admin';
*
* export const PostList = () => (
* <List>
* <Datagrid rowClick="edit">
* ...
* </Datagrid>
* </List>
* );
*/
rowClick?: string | RowClickFunction | false;
rightAvatar?: FunctionToElement<RecordType>;
rightIcon?: FunctionToElement<RecordType>;
secondaryText?: FunctionToElement<RecordType> | ReactElement | string;
Expand All @@ -270,35 +297,61 @@ const LinkOrNot = (
) => {
const {
classes: classesOverride,
//@deprecated: use rowClick instead
linkType,
rowClick,
resource,
id,
children,
record,
...rest
} = props;
const createPath = useCreatePath();
const type =
typeof linkType === 'function' ? linkType(record, id) : linkType;

if (type === false) {
return (
<ListItemText
// @ts-ignore
component="div"
{...rest}
>
{children}
</ListItemText>
);
}
const navigate = useNavigate();
const getPathForRecord = useGetPathForRecordCallback();
const handleClick = useCallback(
async event => {
event.persist();
const link =
// v this is to maintain compatibility with deprecated linkType
typeof linkType === 'function'
? linkType(record, id)
: typeof linkType !== 'undefined'
? linkType
: // v this is the new way to handle links
typeof rowClick === 'function'
? (record, resource) =>
rowClick(record.id, resource, record)
: typeof rowClick !== 'undefined'
? rowClick
: 'edit';
const path = await getPathForRecord({
record,
resource,
link,
});
console.debug('LinkOrNot handleClick', {
event,
path,
record,
resource,
link,
rowClick,
linkType,
});
if (path === false || path == null) {
return;
}
navigate(path, {
state: { _scrollToTop: true },
});
},
[record, resource, rowClick, navigate, getPathForRecord]

Check warning on line 349 in packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx

View workflow job for this annotation

GitHub Actions / typecheck

React Hook useCallback has missing dependencies: 'id' and 'linkType'. Either include them or remove the dependency array
);

return (
// @ts-ignore
<ListItemButton
component={Link}
to={createPath({ resource, id, type })}
{...rest}
>
<ListItemButton component={Link} onClick={handleClick} {...rest}>
{children}
</ListItemButton>
);
Expand All @@ -307,7 +360,9 @@ const LinkOrNot = (
export type FunctionLinkType = (record: RaRecord, id: Identifier) => string;

export interface LinkOrNotProps {
linkType: string | FunctionLinkType | false;
// @deprecated: use rowClick instead
linkType?: string | FunctionLinkType | false;
rowClick?: string | RowClickFunction | false;
resource?: string;
id: Identifier;
record: RaRecord;
Expand Down

0 comments on commit 68c7c65

Please sign in to comment.