Skip to content

Commit 5cf92ae

Browse files
authored
Merge pull request #10754 from marmelab/integrate-datatable-in-guessers
Integrate `DataTable` in Guessers
2 parents e25da34 + e4695e9 commit 5cf92ae

File tree

9 files changed

+486
-259
lines changed

9 files changed

+486
-259
lines changed

docs/Tutorial.md

Lines changed: 137 additions & 107 deletions
Large diffs are not rendered by default.

packages/ra-ui-materialui/src/detail/ShowGuesser.spec.tsx

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,44 @@
11
import * as React from 'react';
22
import expect from 'expect';
3-
import { render, screen, waitFor } from '@testing-library/react';
4-
import { CoreAdminContext } from 'ra-core';
3+
import { render, screen } from '@testing-library/react';
54

6-
import { ShowGuesser } from './ShowGuesser';
7-
import { ThemeProvider } from '../theme/ThemeProvider';
5+
import { ShowGuesser } from './ShowGuesser.stories';
86

97
describe('<ShowGuesser />', () => {
108
it('should log the guessed Show view based on the fetched record', async () => {
119
const logSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
12-
const dataProvider = {
13-
getOne: () =>
14-
Promise.resolve({
15-
data: {
16-
id: 123,
17-
author: 'john doe',
18-
post_id: 6,
19-
score: 3,
20-
body: "Queen, tossing her head through the wood. 'If it had lost something; and she felt sure it.",
21-
created_at: new Date('2012-08-02'),
22-
tags_ids: [1, 2],
23-
},
24-
}),
25-
};
26-
render(
27-
<ThemeProvider>
28-
<CoreAdminContext dataProvider={dataProvider as any}>
29-
<ShowGuesser resource="comments" id={123} enableLog />
30-
</CoreAdminContext>
31-
</ThemeProvider>
32-
);
33-
await waitFor(() => {
34-
screen.getByText('john doe');
35-
});
10+
render(<ShowGuesser />);
11+
await screen.findByText('john doe');
3612
expect(logSpy).toHaveBeenCalledWith(`Guessed Show:
3713
38-
import { DateField, NumberField, ReferenceArrayField, ReferenceField, Show, SimpleShowLayout, TextField } from 'react-admin';
14+
import { ArrayField, BooleanField, DataTable, DateField, EmailField, NumberField, ReferenceArrayField, ReferenceField, RichTextField, Show, SimpleShowLayout, TextField, UrlField } from 'react-admin';
3915
40-
export const CommentShow = () => (
16+
export const BookShow = () => (
4117
<Show>
4218
<SimpleShowLayout>
4319
<TextField source="id" />
44-
<TextField source="author" />
20+
<ArrayField source="authors">
21+
<DataTable>
22+
<DataTable.Col source="id">
23+
<TextField source="id" />
24+
</DataTable.Col>
25+
<DataTable.Col source="name">
26+
<TextField source="name" />
27+
</DataTable.Col>
28+
<DataTable.Col source="dob">
29+
<DateField source="dob" />
30+
</DataTable.Col>
31+
</DataTable>
32+
</ArrayField>
4533
<ReferenceField source="post_id" reference="posts" />
4634
<NumberField source="score" />
4735
<TextField source="body" />
36+
<RichTextField source="description" />
4837
<DateField source="created_at" />
4938
<ReferenceArrayField source="tags_ids" reference="tags" />
39+
<UrlField source="url" />
40+
<EmailField source="email" />
41+
<BooleanField source="isAlreadyPublished" />
5042
</SimpleShowLayout>
5143
</Show>
5244
);`);
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import * as React from 'react';
2+
import { Admin } from 'react-admin';
3+
import { Resource, TestMemoryRouter } from 'ra-core';
4+
import fakeRestProvider from 'ra-data-fakerest';
5+
6+
import { ShowGuesser as RAShowGuesser } from './ShowGuesser';
7+
8+
export default { title: 'ra-ui-materialui/detail/ShowGuesser' };
9+
10+
const data = {
11+
books: [
12+
{
13+
id: 123,
14+
authors: [
15+
{ id: 1, name: 'john doe', dob: '1990-01-01' },
16+
{ id: 2, name: 'jane doe', dob: '1992-01-01' },
17+
],
18+
post_id: 6,
19+
score: 3,
20+
body: "Queen, tossing her head through the wood. 'If it had lost something; and she felt sure it.",
21+
description: `<p><strong>War and Peace</strong> is a novel by the Russian author <a href="https://en.wikipedia.org/wiki/Leo_Tolstoy">Leo Tolstoy</a>,
22+
published serially, then in its entirety in 1869.</p>
23+
<p>It is regarded as one of Tolstoy's finest literary achievements and remains a classic of world literature.</p>`,
24+
created_at: new Date('2012-08-02'),
25+
tags_ids: [1, 2],
26+
url: 'https://www.myshop.com/tags/top-seller',
27+
28+
isAlreadyPublished: true,
29+
},
30+
],
31+
tags: [
32+
{ id: 1, name: 'top seller' },
33+
{ id: 2, name: 'new' },
34+
],
35+
posts: [
36+
{ id: 6, title: 'War and Peace', body: 'A great novel by Leo Tolstoy' },
37+
],
38+
};
39+
40+
const ShowGuesserWithProdLogs = () => <RAShowGuesser enableLog />;
41+
42+
export const ShowGuesser = () => (
43+
<TestMemoryRouter initialEntries={['/books/123/show']}>
44+
<Admin dataProvider={fakeRestProvider(data)}>
45+
<Resource name="books" show={ShowGuesserWithProdLogs} />
46+
</Admin>
47+
</TestMemoryRouter>
48+
);

packages/ra-ui-materialui/src/detail/ShowGuesser.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ const ShowViewGuesser = (
7070
)
7171
)
7272
)
73+
.filter(component => !component.match(/[A-Za-z]+\.[A-Za-z]+/i))
7374
.sort();
7475

7576
console.log(

packages/ra-ui-materialui/src/detail/showFieldTypes.tsx

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as React from 'react';
22
import { ReactNode } from 'react';
3-
import { Datagrid } from '../list/datagrid/Datagrid';
3+
import type { InferredElement, InferredTypeMap, InputProps } from 'ra-core';
44
import {
55
ArrayField,
66
BooleanField,
@@ -17,8 +17,7 @@ import {
1717
ChipField,
1818
} from '../field';
1919
import { SimpleShowLayout, SimpleShowLayoutProps } from './SimpleShowLayout';
20-
import { InferredElement, InferredTypeMap, InputProps } from 'ra-core';
21-
import { SingleFieldList } from '../list';
20+
import { DataTable, SingleFieldList } from '../list';
2221

2322
export const showFieldTypes: InferredTypeMap = {
2423
show: {
@@ -30,18 +29,31 @@ ${children.map(child => ` ${child.getRepresentation()}`).join('\n')}
3029
</SimpleShowLayout>`,
3130
},
3231
array: {
33-
component: ({
34-
children,
35-
...props
36-
}: { children: ReactNode } & InputProps) => (
32+
component: ({ children, ...props }: { children } & InputProps) => (
3733
<ArrayField {...props}>
38-
<Datagrid>{children}</Datagrid>
34+
<DataTable>
35+
{children && children.length > 0
36+
? children.map((child, index) => (
37+
<DataTable.Col key={index} {...child.props}>
38+
{child}
39+
</DataTable.Col>
40+
))
41+
: children}
42+
</DataTable>
3943
</ArrayField>
4044
),
4145
representation: (props: InputProps, children: InferredElement[]) =>
42-
`<ArrayField source="${props.source}"><Datagrid>${children
43-
.map(child => child.getRepresentation())
44-
.join('\n')}</Datagrid></ArrayField>`,
46+
`<ArrayField source="${props.source}">
47+
<DataTable>
48+
${children
49+
.map(
50+
child => `<DataTable.Col source="${child.getProps().source}">
51+
${child.getRepresentation()}
52+
</DataTable.Col>`
53+
)
54+
.join('\n ')}
55+
</DataTable>
56+
</ArrayField>`,
4557
},
4658
boolean: {
4759
component: BooleanField,

packages/ra-ui-materialui/src/list/ListGuesser.spec.tsx

Lines changed: 69 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,81 @@
11
import * as React from 'react';
22
import expect from 'expect';
3-
import { render, screen, waitFor } from '@testing-library/react';
4-
import { CoreAdminContext, testDataProvider } from 'ra-core';
5-
6-
import { ListGuesser } from './ListGuesser';
7-
import { ThemeProvider } from '../theme/ThemeProvider';
3+
import { fireEvent, render, screen } from '@testing-library/react';
4+
import { ManyResources } from './ListGuesser.stories';
85

96
describe('<ListGuesser />', () => {
10-
it('should log the guessed List view based on the fetched records', async () => {
7+
it('should log the guessed List views based on the fetched records', async () => {
118
const logSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
12-
const dataProvider = testDataProvider({
13-
getList: () =>
14-
Promise.resolve({
15-
data: [
16-
{
17-
id: 123,
18-
author: 'john doe',
19-
post_id: 6,
20-
score: 3,
21-
body: "Queen, tossing her head through the wood. 'If it had lost something; and she felt sure it.",
22-
created_at: new Date('2012-08-02'),
23-
tags_ids: [1, 2],
24-
},
25-
],
26-
total: 1,
27-
}),
28-
getMany: () => Promise.resolve({ data: [], total: 0 }),
29-
});
30-
render(
31-
<ThemeProvider>
32-
<CoreAdminContext dataProvider={dataProvider as any}>
33-
<ListGuesser resource="comments" enableLog />
34-
</CoreAdminContext>
35-
</ThemeProvider>
36-
);
37-
await waitFor(() => {
38-
screen.getByText('john doe');
39-
});
9+
render(<ManyResources />);
10+
await screen.findAllByText('top seller', undefined, { timeout: 2000 });
11+
expect(logSpy).toHaveBeenCalledWith(`Guessed List:
12+
13+
import { DataTable, DateField, EmailField, List, ReferenceArrayField, ReferenceField } from 'react-admin';
14+
15+
export const ProductList = () => (
16+
<List>
17+
<DataTable>
18+
<DataTable.Col source="id" />
19+
<DataTable.Col source="name" />
20+
<DataTable.NumberCol source="price" />
21+
<DataTable.Col source="category_id">
22+
<ReferenceField source="category_id" reference="categories" />
23+
</DataTable.Col>
24+
<DataTable.Col source="tags_ids">
25+
<ReferenceArrayField source="tags_ids" reference="tags" />
26+
</DataTable.Col>
27+
<DataTable.Col source="last_update">
28+
<DateField source="last_update" />
29+
</DataTable.Col>
30+
<DataTable.Col source="email">
31+
<EmailField source="email" />
32+
</DataTable.Col>
33+
</DataTable>
34+
</List>
35+
);`);
36+
logSpy.mockClear();
37+
38+
fireEvent.click(screen.getByText('Categories'));
39+
await screen.findByText('Jeans');
40+
expect(logSpy).toHaveBeenCalledWith(`Guessed List:
41+
42+
import { ArrayField, BooleanField, ChipField, DataTable, List, SingleFieldList } from 'react-admin';
43+
44+
export const CategoryList = () => (
45+
<List>
46+
<DataTable>
47+
<DataTable.Col source="id" />
48+
<DataTable.Col source="name" />
49+
<DataTable.Col source="alternativeName">
50+
<ArrayField source="alternativeName">
51+
<SingleFieldList>
52+
<ChipField source="name" />
53+
</SingleFieldList>
54+
</ArrayField>
55+
</DataTable.Col>
56+
<DataTable.Col source="isVeganProduction">
57+
<BooleanField source="isVeganProduction" />
58+
</DataTable.Col>
59+
</DataTable>
60+
</List>
61+
);`);
62+
63+
logSpy.mockClear();
64+
fireEvent.click(screen.getByText('Tags'));
65+
await screen.findByText('top seller');
4066
expect(logSpy).toHaveBeenCalledWith(`Guessed List:
4167
42-
import { Datagrid, DateField, List, NumberField, ReferenceArrayField, ReferenceField, TextField } from 'react-admin';
68+
import { DataTable, List, UrlField } from 'react-admin';
4369
44-
export const CommentList = () => (
70+
export const TagList = () => (
4571
<List>
46-
<Datagrid>
47-
<TextField source="id" />
48-
<TextField source="author" />
49-
<ReferenceField source="post_id" reference="posts" />
50-
<NumberField source="score" />
51-
<TextField source="body" />
52-
<DateField source="created_at" />
53-
<ReferenceArrayField source="tags_ids" reference="tags" />
54-
</Datagrid>
72+
<DataTable>
73+
<DataTable.Col source="id" />
74+
<DataTable.Col source="name" />
75+
<DataTable.Col source="url">
76+
<UrlField source="url" />
77+
</DataTable.Col>
78+
</DataTable>
5579
</List>
5680
);`);
5781
});

0 commit comments

Comments
 (0)