Skip to content

Commit 6046025

Browse files
authored
Merge pull request #9391 from marmelab/fix-update-button-cannot-be-used-in-a-list-v2
Fix update button cannot be used in a list
2 parents 9ee234d + a70c898 commit 6046025

File tree

3 files changed

+114
-89
lines changed

3 files changed

+114
-89
lines changed

packages/ra-ui-materialui/src/button/UpdateButton.stories.tsx

+98-85
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { AdminUI } from '../AdminUI';
1212
import { NumberField, TextField } from '../field';
1313
import { Show, SimpleShowLayout } from '../detail';
1414
import { TopToolbar } from '../layout';
15+
import { Datagrid, List } from '../list';
1516

1617
export default { title: 'ra-ui-materialui/button/UpdateButton' };
1718

@@ -44,7 +45,7 @@ const getDataProvider = () =>
4445
id: 1,
4546
title: 'Lorem Ipsum',
4647
body: 'Lorem ipsum dolor sit amet',
47-
views: 1000,
48+
views: 500,
4849
},
4950
],
5051
authors: [],
@@ -60,24 +61,42 @@ const getDataProvider = () =>
6061
]
6162
);
6263

63-
const PostShow = () => {
64-
return (
65-
<Show
66-
actions={
67-
<TopToolbar>
68-
<UpdateButton label="Reset views" data={{ views: 0 }} />
69-
</TopToolbar>
70-
}
71-
>
72-
<SimpleShowLayout>
73-
<TextField source="id" />
74-
<TextField source="title" />
75-
<TextField source="body" />
76-
<NumberField source="views" />
77-
</SimpleShowLayout>
78-
</Show>
79-
);
80-
};
64+
const PostShow = () => (
65+
<Show
66+
actions={
67+
<TopToolbar>
68+
<UpdateButton label="Reset views" data={{ views: 0 }} />
69+
</TopToolbar>
70+
}
71+
>
72+
<SimpleShowLayout>
73+
<TextField source="id" />
74+
<TextField source="title" />
75+
<TextField source="body" />
76+
<NumberField source="views" />
77+
</SimpleShowLayout>
78+
</Show>
79+
);
80+
81+
const PostList = () => (
82+
<List>
83+
<Datagrid rowClick="show">
84+
<TextField source="id" />
85+
<TextField source="title" />
86+
<TextField source="body" />
87+
<NumberField source="views" />
88+
<UpdateButton label="Reset views" data={{ views: 0 }} />
89+
</Datagrid>
90+
</List>
91+
);
92+
93+
export const InsideAList = () => (
94+
<AdminContext dataProvider={getDataProvider()} i18nProvider={i18nProvider}>
95+
<AdminUI>
96+
<Resource name="posts" list={<PostList />} show={<PostShow />} />
97+
</AdminUI>
98+
</AdminContext>
99+
);
81100

82101
export const Undoable = () => (
83102
<AdminContext
@@ -91,28 +110,26 @@ export const Undoable = () => (
91110
</AdminContext>
92111
);
93112

94-
const PostShowPessimistic = () => {
95-
return (
96-
<Show
97-
actions={
98-
<TopToolbar>
99-
<UpdateButton
100-
mutationMode="pessimistic"
101-
label="Reset views"
102-
data={{ views: 0 }}
103-
/>
104-
</TopToolbar>
105-
}
106-
>
107-
<SimpleShowLayout>
108-
<TextField source="id" />
109-
<TextField source="title" />
110-
<TextField source="body" />
111-
<NumberField source="views" />
112-
</SimpleShowLayout>
113-
</Show>
114-
);
115-
};
113+
const PostShowPessimistic = () => (
114+
<Show
115+
actions={
116+
<TopToolbar>
117+
<UpdateButton
118+
mutationMode="pessimistic"
119+
label="Reset views"
120+
data={{ views: 0 }}
121+
/>
122+
</TopToolbar>
123+
}
124+
>
125+
<SimpleShowLayout>
126+
<TextField source="id" />
127+
<TextField source="title" />
128+
<TextField source="body" />
129+
<NumberField source="views" />
130+
</SimpleShowLayout>
131+
</Show>
132+
);
116133

117134
export const Pessimistic = () => (
118135
<AdminContext
@@ -126,28 +143,26 @@ export const Pessimistic = () => (
126143
</AdminContext>
127144
);
128145

129-
const PostShowOptimistic = () => {
130-
return (
131-
<Show
132-
actions={
133-
<TopToolbar>
134-
<UpdateButton
135-
mutationMode="optimistic"
136-
label="Reset views"
137-
data={{ views: 0 }}
138-
/>
139-
</TopToolbar>
140-
}
141-
>
142-
<SimpleShowLayout>
143-
<TextField source="id" />
144-
<TextField source="title" />
145-
<TextField source="body" />
146-
<NumberField source="views" />
147-
</SimpleShowLayout>
148-
</Show>
149-
);
150-
};
146+
const PostShowOptimistic = () => (
147+
<Show
148+
actions={
149+
<TopToolbar>
150+
<UpdateButton
151+
mutationMode="optimistic"
152+
label="Reset views"
153+
data={{ views: 0 }}
154+
/>
155+
</TopToolbar>
156+
}
157+
>
158+
<SimpleShowLayout>
159+
<TextField source="id" />
160+
<TextField source="title" />
161+
<TextField source="body" />
162+
<NumberField source="views" />
163+
</SimpleShowLayout>
164+
</Show>
165+
);
151166

152167
export const Optimistic = () => (
153168
<AdminContext
@@ -202,28 +217,26 @@ export const MutationOptions = () => (
202217
</AdminContext>
203218
);
204219

205-
const PostShowSx = () => {
206-
return (
207-
<Show
208-
actions={
209-
<TopToolbar>
210-
<UpdateButton
211-
sx={{ border: '1px solid red' }}
212-
label="Reset views"
213-
data={{ views: 0 }}
214-
/>
215-
</TopToolbar>
216-
}
217-
>
218-
<SimpleShowLayout>
219-
<TextField source="id" />
220-
<TextField source="title" />
221-
<TextField source="body" />
222-
<NumberField source="views" />
223-
</SimpleShowLayout>
224-
</Show>
225-
);
226-
};
220+
const PostShowSx = () => (
221+
<Show
222+
actions={
223+
<TopToolbar>
224+
<UpdateButton
225+
sx={{ border: '1px solid red' }}
226+
label="Reset views"
227+
data={{ views: 0 }}
228+
/>
229+
</TopToolbar>
230+
}
231+
>
232+
<SimpleShowLayout>
233+
<TextField source="id" />
234+
<TextField source="title" />
235+
<TextField source="body" />
236+
<NumberField source="views" />
237+
</SimpleShowLayout>
238+
</Show>
239+
);
227240

228241
export const Sx = () => (
229242
<AdminContext

packages/ra-ui-materialui/src/button/UpdateWithUndoButton.spec.tsx

+14-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { Toolbar, SimpleForm } from '../form';
88
import { Edit } from '../detail';
99
import { TextInput } from '../input';
1010
import { UpdateWithUndoButton } from './UpdateWithUndoButton';
11+
import { InsideAList } from './UpdateButton.stories';
1112

1213
const theme = createTheme();
1314

@@ -58,7 +59,7 @@ describe('<UpdateWithUndoButton />', () => {
5859
// @ts-ignore
5960
getOne: () =>
6061
Promise.resolve({
61-
data: { id: 123, title: 'lorem', views: 1000 },
62+
data: { id: 123, title: 'lorem', views: 500 },
6263
}),
6364
// @ts-ignore
6465
update: () => Promise.resolve({ data: { id: 123 } }),
@@ -95,11 +96,22 @@ describe('<UpdateWithUndoButton />', () => {
9596
id: 123,
9697
data: { views: 0 },
9798
meta: undefined,
98-
previousData: { id: 123, title: 'lorem', views: 1000 },
99+
previousData: { id: 123, title: 'lorem', views: 500 },
99100
resource: 'posts',
100101
},
101102
{ snapshot: expect.any(Array) }
102103
);
103104
});
104105
});
106+
107+
it('should prevent click propagation', async () => {
108+
render(<InsideAList />);
109+
const resetButton = await screen.findByRole('button', {
110+
name: 'Reset views',
111+
});
112+
screen.getByText('500');
113+
fireEvent.click(resetButton);
114+
await screen.findByText('0');
115+
screen.getByRole('button', { name: 'Export' }); // check if we still are on the list page
116+
});
105117
});

packages/ra-ui-materialui/src/button/UpdateWithUndoButton.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import * as React from 'react';
2-
import { styled } from '@mui/material/styles';
2+
import { alpha, styled } from '@mui/material/styles';
33
import { ReactElement } from 'react';
44
import PropTypes from 'prop-types';
55
import ActionUpdate from '@mui/icons-material/Update';
6-
import { alpha } from '@mui/material/styles';
76
import {
87
useRefresh,
98
useNotify,
@@ -80,6 +79,7 @@ export const UpdateWithUndoButton = (props: UpdateWithUndoButtonProps) => {
8079
if (typeof onClick === 'function') {
8180
onClick(e);
8281
}
82+
e.stopPropagation();
8383
};
8484

8585
return (

0 commit comments

Comments
 (0)