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

[RFR] [Rework] Datagrid rowclick toggle #3270

Merged
merged 7 commits into from
May 24, 2019
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
1 change: 1 addition & 0 deletions docs/List.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
43 changes: 22 additions & 21 deletions packages/ra-ui-materialui/src/list/DatagridRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const sanitizeRestProps = ({
...rest
}) => rest;

class DatagridRow extends Component {
export class DatagridRow extends Component {
constructor(props) {
super(props);
this.state = {
Expand Down Expand Up @@ -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 => {
Expand Down
108 changes: 108 additions & 0 deletions packages/ra-ui-materialui/src/list/DatagridRow.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import React from 'react';
import { shallow } from 'enzyme';
import { linkToRecord } from 'ra-core';

import { DatagridRow } from './DatagridRow';

describe('<DatagridRow />', () => {
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(
<DatagridRow {...defaultProps} rowClick="edit" push={push} />
);

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(
<DatagridRow {...defaultProps} rowClick="show" push={push} />
);

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(
<DatagridRow {...defaultProps} rowClick="expand" />
);
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(
<DatagridRow
{...defaultProps}
onToggleItem={onToggleItem}
rowClick="toggleSelection"
/>
);

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(
<DatagridRow {...defaultProps} rowClick={path} push={push} />
);

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(
<DatagridRow
{...defaultProps}
rowClick={customRowClick}
push={push}
/>
);

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(
<DatagridRow
{...defaultProps}
rowClick=""
push={push}
/>
);

wrapper.instance().handleClick(event);
expect(push.mock.calls.length).toEqual(0);
})
});
fargito marked this conversation as resolved.
Show resolved Hide resolved
});