Skip to content
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
15 changes: 15 additions & 0 deletions packages/ra-ui-materialui/src/button/BulkDeleteButton.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import * as React from 'react';
import { render, screen } from '@testing-library/react';
import expect from 'expect';

import { Themed } from './BulkDeleteButton.stories';

describe('<BulkDeleteButton />', () => {
it('should be customized by a theme', async () => {
render(<Themed />);

const button = await screen.findByTestId('themed');
expect(button.textContent).toBe('Bulk Delete');
expect(button.classList).toContain('custom-class');
});
});
148 changes: 148 additions & 0 deletions packages/ra-ui-materialui/src/button/BulkDeleteButton.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import React from 'react';
import { ThemeOptions } from '@mui/material';
import { deepmerge } from '@mui/utils';
import { Resource } from 'ra-core';
import polyglotI18nProvider from 'ra-i18n-polyglot';
import englishMessages from 'ra-language-english';
import fakeRestDataProvider from 'ra-data-fakerest';

import { AdminContext } from '../AdminContext';
import { BulkDeleteButton } from './BulkDeleteButton';
import { defaultLightTheme } from '../theme';
import { Datagrid, List } from '../list';
import { NumberField, TextField } from '../field';
import { AdminUI } from '../AdminUI';

export default { title: 'ra-ui-materialui/button/BulkDeleteButton' };

const i18nProvider = polyglotI18nProvider(
() => englishMessages,
'en' // Default locale
);

const dataProvider = fakeRestDataProvider({
books: [
{
id: 1,
title: 'War and Peace',
author: 'Leo Tolstoy',
reads: 23,
},
{
id: 2,
title: 'Pride and Predjudice',
author: 'Jane Austen',
reads: 854,
},
{
id: 3,
title: 'The Picture of Dorian Gray',
author: 'Oscar Wilde',
reads: 126,
},
{
id: 4,
title: 'Le Petit Prince',
author: 'Antoine de Saint-Exupéry',
reads: 86,
},
{
id: 5,
title: "Alice's Adventures in Wonderland",
author: 'Lewis Carroll',
reads: 125,
},
{
id: 6,
title: 'Madame Bovary',
author: 'Gustave Flaubert',
reads: 452,
},
{
id: 7,
title: 'The Lord of the Rings',
author: 'J. R. R. Tolkien',
reads: 267,
},
{
id: 8,
title: "Harry Potter and the Philosopher's Stone",
author: 'J. K. Rowling',
reads: 1294,
},
{
id: 9,
title: 'The Alchemist',
author: 'Paulo Coelho',
reads: 23,
},
{
id: 10,
title: 'A Catcher in the Rye',
author: 'J. D. Salinger',
reads: 209,
},
{
id: 11,
title: 'Ulysses',
author: 'James Joyce',
reads: 12,
},
],
authors: [],
});

const Wrapper = ({ children, ...props }) => {
return (
<AdminContext
dataProvider={dataProvider}
i18nProvider={i18nProvider}
{...props}
>
<AdminUI>
<Resource
name="books"
list={() => (
<List>
<Datagrid bulkActionButtons={children}>
<TextField source="id" />
<TextField source="title" />
<TextField source="author" />
<NumberField source="reads" />
</Datagrid>
</List>
)}
/>
</AdminUI>
</AdminContext>
);
};

export const Basic = () => {
return (
<Wrapper>
<BulkDeleteButton />
</Wrapper>
);
};

export const Themed = () => {
return (
<Wrapper
theme={deepmerge(defaultLightTheme, {
components: {
RaBulkDeleteButton: {
defaultProps: {
label: 'Bulk Delete',
mutationMode: 'optimistic',
className: 'custom-class',
'data-testid': 'themed',
},
},
},
} as ThemeOptions)}
>
<BulkDeleteButton />
</Wrapper>
);
};
28 changes: 23 additions & 5 deletions packages/ra-ui-materialui/src/button/BulkDeleteButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import * as React from 'react';
import { MutationMode, useCanAccess, useResourceContext } from 'ra-core';
import { useThemeProps } from '@mui/material/styles';

import {
BulkDeleteWithConfirmButton,
BulkDeleteWithConfirmButtonProps,
Expand All @@ -7,7 +10,6 @@ import {
BulkDeleteWithUndoButton,
BulkDeleteWithUndoButtonProps,
} from './BulkDeleteWithUndoButton';
import { MutationMode, useCanAccess, useResourceContext } from 'ra-core';

/**
* Deletes the selected rows.
Expand All @@ -32,10 +34,12 @@ import { MutationMode, useCanAccess, useResourceContext } from 'ra-core';
* </List>
* );
*/
export const BulkDeleteButton = ({
mutationMode = 'undoable',
...props
}: BulkDeleteButtonProps) => {
export const BulkDeleteButton = (inProps: BulkDeleteButtonProps) => {
const { mutationMode = 'undoable', ...props } = useThemeProps({
name: PREFIX,
props: inProps,
});

const resource = useResourceContext(props);
if (!resource) {
throw new Error(
Expand All @@ -62,3 +66,17 @@ interface Props {

export type BulkDeleteButtonProps = Props &
(BulkDeleteWithUndoButtonProps | BulkDeleteWithConfirmButtonProps);

const PREFIX = 'RaBulkDeleteButton';

declare module '@mui/material/styles' {
interface ComponentsPropsList {
[PREFIX]: Partial<BulkDeleteButtonProps>;
}

interface Components {
[PREFIX]?: {
defaultProps?: ComponentsPropsList[typeof PREFIX];
};
}
}
19 changes: 14 additions & 5 deletions packages/ra-ui-materialui/src/button/BulkExportButton.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@ import {
import { createTheme, ThemeProvider } from '@mui/material/styles';

import { BulkExportButton } from './BulkExportButton';
import { Themed } from './BulkExportButton.stories';

const theme = createTheme();

describe('<BulkExportButton />', () => {
it('should invoke dataProvider with meta', async () => {
const exporter = jest.fn().mockName('exporter');
const dataProvider = testDataProvider({
getMany: jest.fn().mockResolvedValueOnce({ data: [], total: 0 }),
});
const exporter = jest.fn().mockName('exporter');
const dataProvider = testDataProvider({
getMany: jest.fn().mockResolvedValueOnce({ data: [], total: 0 }),
});

it('should invoke dataProvider with meta', async () => {
render(
<CoreAdminContext dataProvider={dataProvider}>
<ThemeProvider theme={theme}>
Expand Down Expand Up @@ -46,4 +47,12 @@ describe('<BulkExportButton />', () => {
expect(exporter).toHaveBeenCalled();
});
});

it('should be customized by a theme', async () => {
render(<Themed />);

const button = await screen.findByTestId('themed');
expect(button.textContent).toBe('Bulk Export');
expect(button.classList).toContain('custom-class');
});
});
Loading
Loading