diff --git a/docs/List.md b/docs/List.md index 27ef41ac41e..c7ec0080fa3 100644 --- a/docs/List.md +++ b/docs/List.md @@ -814,6 +814,7 @@ export const PostList = (props) => ( * "edit" to redirect to the edition vue * "show" to redirect to the show vue * "expand" to open the `expand` panel +* "toggleSelection" to trigger the `onToggleItem` function * a function `(id, basePath, record) => path` to redirect to a custom path **Tip**: If you pass a function, it can return `edit`, `show` or a router path. This allows to redirect to either `edit` or `show` after checking a condition on the record. For example: diff --git a/packages/ra-ui-materialui/src/list/DatagridRow.js b/packages/ra-ui-materialui/src/list/DatagridRow.js index d3f15fdba87..810f4c14f31 100644 --- a/packages/ra-ui-materialui/src/list/DatagridRow.js +++ b/packages/ra-ui-materialui/src/list/DatagridRow.js @@ -31,7 +31,7 @@ const sanitizeRestProps = ({ ...rest }) => rest; -class DatagridRow extends Component { +export class DatagridRow extends Component { constructor(props) { super(props); this.state = { @@ -62,33 +62,34 @@ class DatagridRow extends Component { if (!rowClick) return; - if (typeof rowClick === 'function') { - const path = await rowClick(id, basePath, record); - this.handleRedirection(path, event); - return; - } + const path = + typeof rowClick === 'function' + ? await rowClick(id, basePath, record) + : rowClick; - this.handleRedirection(rowClick, event); + this.handleRedirection(path, event); }; handleRedirection = (path, event) => { const { basePath, id, push } = this.props; - if (path === 'edit') { - push(linkToRecord(basePath, id)); - return; - } - if (path === 'show') { - push(linkToRecord(basePath, id, 'show')); - return; + switch (path) { + case 'edit': + push(linkToRecord(basePath, id)); + return; + case 'show': + push(linkToRecord(basePath, id, 'show')); + return; + case 'expand': + this.handleToggleExpanded(event); + return; + case 'toggleSelection': + this.handleToggle(event); + return; + default: + if (path) push(path); + return; } - if (path === 'expand') { - this.handleToggleExpanded(event); - return; - } - if (!path) return; - - push(path); }; computeColSpan = props => { diff --git a/packages/ra-ui-materialui/src/list/DatagridRow.spec.js b/packages/ra-ui-materialui/src/list/DatagridRow.spec.js new file mode 100644 index 00000000000..b4fd923037b --- /dev/null +++ b/packages/ra-ui-materialui/src/list/DatagridRow.spec.js @@ -0,0 +1,108 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import { linkToRecord } from 'ra-core'; + +import { DatagridRow } from './DatagridRow'; + +describe('', () => { + const defaultProps = { + id: 15, + basePath: '/blob', + }; + + const event = { preventDefault: () => { }, stopPropagation: () => { } }; + + describe('rowClick', () => { + it("should redirect to edit page if the 'edit' option is selected", () => { + const push = jest.fn(); + const wrapper = shallow( + + ); + + wrapper.instance().handleClick(event); + expect(push.mock.calls).toEqual([ + [linkToRecord(defaultProps.basePath, defaultProps.id)], + ]); + }); + + it("should redirect to show page if the 'show' option is selected", () => { + const push = jest.fn(); + const wrapper = shallow( + + ); + + wrapper.instance().handleClick(event); + expect(push.mock.calls).toEqual([ + [linkToRecord(defaultProps.basePath, defaultProps.id, 'show')], + ]); + }); + + it("should change the expand state if the 'expand' option is selected", () => { + const wrapper = shallow( + + ); + expect(wrapper.state('expanded')).toBeFalsy(); + + wrapper.instance().handleClick(event); + expect(wrapper.state('expanded')).toBeTruthy(); + + wrapper.instance().handleClick(event); + expect(wrapper.state('expanded')).toBeFalsy(); + }); + + it("should execute the onToggleItem function if the 'toggleSelection' option is selected", () => { + const onToggleItem = jest.fn(); + const wrapper = shallow( + + ); + + wrapper.instance().handleClick(event); + + expect(onToggleItem.mock.calls.length).toEqual(1); + }); + + it('should redirect to the custom path if onRowClick is a string', () => { + const path = '/foo/bar'; + const push = jest.fn(); + const wrapper = shallow( + + ); + + wrapper.instance().handleClick(event); + expect(push.mock.calls).toEqual([[path]]); + }); + + it('should evaluate the function and redirect to the result of that function if onRowClick is a custom function', async () => { + const push = jest.fn(); + const customRowClick = () => '/bar/foo'; + const wrapper = shallow( + + ); + + await wrapper.instance().handleClick(event); + expect(push.mock.calls).toEqual([['/bar/foo']]); + }); + + it('should not call push if onRowClick is falsy', () => { + const push = jest.fn(); + const wrapper = shallow( + + ); + + wrapper.instance().handleClick(event); + expect(push.mock.calls.length).toEqual(0); + }) + }); +});