Skip to content

Commit e43233f

Browse files
authored
Merge pull request #11165 from marmelab/guesser-i18n-translations
Add guesser empty i18n messages
2 parents 9fac1bf + 981b732 commit e43233f

6 files changed

Lines changed: 107 additions & 1 deletion

File tree

packages/ra-core/src/i18n/TranslationMessages.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,12 @@ export interface TranslationMessages extends StringMap {
194194
remove_message: string;
195195
help: string;
196196
};
197+
guesser?: {
198+
empty: {
199+
title: string;
200+
message: string;
201+
};
202+
};
197203
configurable?: {
198204
customize: string;
199205
configureMode: string;

packages/ra-language-english/src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,12 @@ const englishMessages: TranslationMessages = {
199199
'Are you sure you want to remove that item from your list of saved queries?',
200200
help: 'Filter the list and save this query for later',
201201
},
202+
guesser: {
203+
empty: {
204+
title: 'No data to display',
205+
message: 'Please check your data provider',
206+
},
207+
},
202208
configurable: {
203209
customize: 'Customize',
204210
configureMode: 'Configure this page',

packages/ra-language-french/src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,12 @@ const frenchMessages: TranslationMessages = {
207207
'Etes-vous sûr(e) de vouloir supprimer cette requête de votre liste de requêtes ?',
208208
help: 'Filtrez la liste et ajoutez cette requête à votre liste',
209209
},
210+
guesser: {
211+
empty: {
212+
title: 'Aucune donnée à afficher',
213+
message: 'Veuillez vérifier votre dataProvider',
214+
},
215+
},
210216
configurable: {
211217
customize: 'Personnaliser',
212218
configureMode: 'Configurer cette page',

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
import * as React from 'react';
22
import expect from 'expect';
33
import { fireEvent, render, screen } from '@testing-library/react';
4-
import { ManyResources } from './ListGuesser.stories';
4+
import { Empty, ManyResources } from './ListGuesser.stories';
55

66
describe('<ListGuesser />', () => {
7+
it('should render an empty state dedicated to guessers', async () => {
8+
render(<Empty />);
9+
10+
await screen.findByText('No data to display');
11+
expect(
12+
screen.getByText('Please check your data provider')
13+
).toBeTruthy();
14+
});
15+
716
it('should log the guessed List views based on the fetched records', async () => {
817
const logSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
918
render(<ManyResources />);

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ const delayedDataProvider = fakeRestProvider(
194194
process.env.NODE_ENV !== 'test',
195195
300
196196
);
197+
const emptyDataProvider = fakeRestProvider(
198+
{ products: [] },
199+
process.env.NODE_ENV !== 'test'
200+
);
197201

198202
const ListGuesserWithProdLogs = () => <ListGuesser enableLog />;
199203

@@ -221,3 +225,18 @@ export const ManyResources = () => (
221225
</AdminUI>
222226
</AdminContext>
223227
);
228+
229+
export const Empty = () => (
230+
<AdminContext
231+
dataProvider={emptyDataProvider}
232+
i18nProvider={polyglotI18nProvider(() => defaultMessages, 'en')}
233+
>
234+
<AdminUI>
235+
<Resource
236+
name="products"
237+
list={ListGuesser}
238+
recordRepresentation="name"
239+
/>
240+
</AdminUI>
241+
</AdminContext>
242+
);

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

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import * as React from 'react';
22
import { useState, useEffect } from 'react';
3+
import { styled, useThemeProps } from '@mui/material/styles';
4+
import { Box, Typography } from '@mui/material';
5+
import Inbox from '@mui/icons-material/Inbox';
36

47
import {
58
ListBase,
@@ -10,6 +13,7 @@ import {
1013
RaRecord,
1114
usePrevious,
1215
useLocation,
16+
useTranslate,
1317
} from 'ra-core';
1418

1519
import { ListProps } from './List';
@@ -44,6 +48,7 @@ export const ListGuesser = <RecordType extends RaRecord = any>(
4448
debounce,
4549
disableAuthentication,
4650
disableSyncWithLocation,
51+
empty,
4752
exporter,
4853
filter,
4954
filterDefaultValues,
@@ -66,6 +71,7 @@ export const ListGuesser = <RecordType extends RaRecord = any>(
6671
debounce={debounce}
6772
disableAuthentication={disableAuthentication}
6873
disableSyncWithLocation={disableSyncWithLocation}
74+
empty={empty === undefined ? <GuesserEmpty /> : empty}
6975
exporter={exporter}
7076
filter={filter}
7177
filterDefaultValues={filterDefaultValues}
@@ -150,3 +156,57 @@ ${inferredChild.getRepresentation()}
150156

151157
return <ListView {...rest}>{child}</ListView>;
152158
};
159+
160+
const GuesserEmpty = (inProps: GuesserEmptyProps) => {
161+
const props = useThemeProps({
162+
props: inProps,
163+
name: GUESSER_EMPTY_PREFIX,
164+
});
165+
const { className } = props;
166+
const translate = useTranslate();
167+
168+
return (
169+
<GuesserEmptyRoot className={className}>
170+
<Box className={GuesserEmptyClasses.message}>
171+
<Inbox className={GuesserEmptyClasses.icon} />
172+
<Typography variant="h4" paragraph>
173+
{translate('ra.guesser.empty.title', {
174+
_: 'No data to display',
175+
})}
176+
</Typography>
177+
<Typography variant="body1">
178+
{translate('ra.guesser.empty.message', {
179+
_: 'Please check your data provider',
180+
})}
181+
</Typography>
182+
</Box>
183+
</GuesserEmptyRoot>
184+
);
185+
};
186+
187+
interface GuesserEmptyProps {
188+
className?: string;
189+
}
190+
191+
const GUESSER_EMPTY_PREFIX = 'RaGuesserEmpty';
192+
193+
const GuesserEmptyClasses = {
194+
message: `${GUESSER_EMPTY_PREFIX}-message`,
195+
icon: `${GUESSER_EMPTY_PREFIX}-icon`,
196+
};
197+
198+
const GuesserEmptyRoot = styled('span', {
199+
name: GUESSER_EMPTY_PREFIX,
200+
overridesResolver: (props, styles) => styles.root,
201+
})(({ theme }) => ({
202+
flex: 1,
203+
[`& .${GuesserEmptyClasses.message}`]: {
204+
textAlign: 'center',
205+
margin: '0 1em',
206+
color: (theme.vars || theme).palette.text.disabled,
207+
},
208+
[`& .${GuesserEmptyClasses.icon}`]: {
209+
width: '9em',
210+
height: '9em',
211+
},
212+
}));

0 commit comments

Comments
 (0)