Skip to content

Commit

Permalink
Merge pull request #4422 from marmelab/Fix-clone-tab
Browse files Browse the repository at this point in the history
Fix Clone Button does not work with Tabbedform
  • Loading branch information
JulienMattiussi committed Feb 14, 2020
2 parents e2697fa + a098271 commit 8969c5a
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 7 deletions.
26 changes: 25 additions & 1 deletion cypress/integration/edit.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import createPageFactory from '../support/CreatePage';
import editPageFactory from '../support/EditPage';
import listPageFactory from '../support/ListPage';
import loginPageFactory from '../support/LoginPage';

describe('Edit Page', () => {
const EditPostPage = editPageFactory('/#/posts/5');
const ListPagePosts = listPageFactory('/#/posts');
const CreatePostPage = createPageFactory('/#/posts/create');
const EditCommentPage = editPageFactory('/#/comments/5');
const ListPagePosts = listPageFactory('/#/posts');
const LoginPage = loginPageFactory('/#/login');
const EditUserPage = editPageFactory('/#/users/3');
const CreateUserPage = createPageFactory('/#/users/create');

describe('Title', () => {
it('should show the correct title in the appBar', () => {
Expand Down Expand Up @@ -165,6 +169,26 @@ describe('Edit Page', () => {
});
});

it('should not lose the cloned values when switching tabs', () => {
EditPostPage.navigate();
EditPostPage.logout();
LoginPage.navigate();
LoginPage.login('admin', 'password');
EditUserPage.navigate();
cy.get(EditUserPage.elements.input('name')).should(el =>
expect(el).to.have.value('Annamarie Mayer')
);
EditUserPage.clone();
cy.get(CreateUserPage.elements.input('name')).then(el => {
expect(el).to.have.value('Annamarie Mayer');
});
CreateUserPage.gotoTab(2);
CreateUserPage.gotoTab(1);
cy.get(CreateUserPage.elements.input('name')).then(el => {
expect(el).to.have.value('Annamarie Mayer');
});
});

it('should persit emptied inputs', () => {
EditPostPage.navigate();
EditPostPage.gotoTab(3);
Expand Down
7 changes: 7 additions & 0 deletions cypress/support/EditPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export default url => ({
cloneButton: '.button-clone',
tab: index => `.form-tab:nth-of-type(${index})`,
title: '#react-admin-title',
userMenu: 'button[title="Profile"]',
logout: '.logout',
},

navigate() {
Expand Down Expand Up @@ -57,4 +59,9 @@ export default url => ({
clone() {
cy.get(this.elements.cloneButton).click();
},

logout() {
cy.get(this.elements.userMenu).click();
cy.get(this.elements.logout).click();
},
});
23 changes: 21 additions & 2 deletions examples/simple/src/users/UserEdit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
CloneButton,
DeleteWithConfirmButton,
Edit,
FormTab,
required,
SaveButton,
SelectInput,
ShowButton,
TabbedForm,
TextInput,
Toolbar,
required,
TopToolbar,
} from 'react-admin';
import { makeStyles } from '@material-ui/core/styles';

Expand Down Expand Up @@ -39,8 +42,24 @@ const UserEditToolbar = props => {
);
};

const EditActions = ({ basePath, data, hasShow }) => (
<TopToolbar>
<CloneButton
className="button-clone"
basePath={basePath}
record={data}
/>
<ShowButton basePath={basePath} record={data} />
</TopToolbar>
);

const UserEdit = ({ permissions, ...props }) => (
<Edit title={<UserTitle />} aside={<Aside />} {...props}>
<Edit
title={<UserTitle />}
aside={<Aside />}
actions={<EditActions />}
{...props}
>
<TabbedForm
defaultValue={{ role: 'user' }}
toolbar={<UserEditToolbar />}
Expand Down
12 changes: 10 additions & 2 deletions packages/ra-core/src/sideEffect/useRedirect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export type RedirectionSideEffect = string | boolean | RedirectToFunction;
*/
const useRedirect = () => {
const dispatch = useDispatch();
const history = useHistory();
const history = useHistory(); // Note: history is mutable. This prevents render loops in useCallback.
return useCallback(
(
redirectTo: RedirectionSideEffect,
Expand All @@ -40,7 +40,15 @@ const useRedirect = () => {
data?: Partial<Record>
) => {
if (!redirectTo) {
dispatch(refreshView());
if (history.location.state || history.location.search) {
history.replace({
...history.location,
state: {},
search: undefined,
});
} else {
dispatch(refreshView());
}
return;
}

Expand Down
5 changes: 3 additions & 2 deletions packages/ra-ui-materialui/src/form/FormTab.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import { Link, useLocation } from 'react-router-dom';
import MuiTab from '@material-ui/core/Tab';
import classnames from 'classnames';
import { useTranslate } from 'ra-core';
Expand Down Expand Up @@ -35,6 +35,7 @@ const FormTab = ({
...rest
}) => {
const translate = useTranslate();
const location = useLocation();

const renderHeader = () => (
<MuiTab
Expand All @@ -44,7 +45,7 @@ const FormTab = ({
icon={icon}
className={classnames('form-tab', className)}
component={Link}
to={{ pathname: value }}
to={{ ...location, pathname: value }}
{...sanitizeRestProps(rest)}
/>
);
Expand Down

0 comments on commit 8969c5a

Please sign in to comment.