Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add translate in emptyText on ra-ui-material fields #8132

Merged
merged 4 commits into from
Sep 8, 2022
Merged
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
2 changes: 1 addition & 1 deletion docs/Fields.md
Original file line number Diff line number Diff line change
@@ -144,7 +144,7 @@ CSS class name passed to the root component.

## `emptyText`

By default, a Field renders an empty string when the record has no value for that field. You can override this behavior by setting the `emptyText` prop.
By default, a Field renders an empty string when the record has no value for that field. You can override this behavior by setting the `emptyText` prop. The emptyText supports i8nProvider translation, if the translation is not found it will display the value as default.

```jsx
const PostList = () => (
35 changes: 34 additions & 1 deletion packages/ra-ui-materialui/src/field/BooleanField.spec.tsx
Original file line number Diff line number Diff line change
@@ -2,7 +2,8 @@ import * as React from 'react';
import expect from 'expect';
import { BooleanField } from './BooleanField';
import { screen, render } from '@testing-library/react';
import { RecordContextProvider } from 'ra-core';
import { RecordContextProvider, I18nContextProvider } from 'ra-core';
import polyglotI18nProvider from 'ra-i18n-polyglot';

const defaultProps = {
record: { id: 123, published: true },
@@ -11,6 +12,24 @@ const defaultProps = {
classes: {},
};

const i18nProvider = polyglotI18nProvider(
_locale => ({
resources: {
books: {
name: 'Books',
fields: {
id: 'Id',
title: 'Title',
author: 'Author',
year: 'Year',
},
not_found: 'Not found',
},
},
}),
'en'
);

describe('<BooleanField />', () => {
it('should display tick and truthy text if value is true', () => {
render(<BooleanField {...defaultProps} />);
@@ -152,4 +171,18 @@ describe('<BooleanField />', () => {
);
expect(screen.queryByLabelText('ra.boolean.true')).not.toBeNull();
});

it('should translate emptyText', () => {
const { getByText } = render(
<I18nContextProvider value={i18nProvider}>
<BooleanField
record={{ id: 123 }}
source="foo.bar"
emptyText="resources.books.not_found"
/>
</I18nContextProvider>
);

expect(getByText('Not found')).not.toBeNull();
});
});
2 changes: 1 addition & 1 deletion packages/ra-ui-materialui/src/field/BooleanField.tsx
Original file line number Diff line number Diff line change
@@ -62,7 +62,7 @@ export const BooleanField: FunctionComponent<BooleanFieldProps> = memo(
className={className}
{...sanitizeFieldRestProps(rest)}
>
{emptyText}
{translate(emptyText, { _: emptyText })}
</Typography>
);
}
35 changes: 34 additions & 1 deletion packages/ra-ui-materialui/src/field/ChipField.spec.tsx
Original file line number Diff line number Diff line change
@@ -2,7 +2,26 @@ import * as React from 'react';
import expect from 'expect';
import { ChipField } from './ChipField';
import { render } from '@testing-library/react';
import { RecordContextProvider } from 'ra-core';
import { RecordContextProvider, I18nContextProvider } from 'ra-core';
import polyglotI18nProvider from 'ra-i18n-polyglot';

const i18nProvider = polyglotI18nProvider(
_locale => ({
resources: {
books: {
name: 'Books',
fields: {
id: 'Id',
title: 'Title',
author: 'Author',
year: 'Year',
},
not_found: 'Not found',
},
},
}),
'en'
);

describe('<ChipField />', () => {
it('should display the record value added as source', () => {
@@ -54,4 +73,18 @@ describe('<ChipField />', () => {
expect(getByText('NA')).not.toBeNull();
}
);

it('should translate emptyText', () => {
const { getByText } = render(
<I18nContextProvider value={i18nProvider}>
<ChipField
record={{ id: 123 }}
source="foo.bar"
emptyText="resources.books.not_found"
/>
</I18nContextProvider>
);

expect(getByText('Not found')).not.toBeNull();
});
});
6 changes: 3 additions & 3 deletions packages/ra-ui-materialui/src/field/ChipField.tsx
Original file line number Diff line number Diff line change
@@ -5,16 +5,16 @@ import get from 'lodash/get';
import Chip, { ChipProps } from '@mui/material/Chip';
import Typography from '@mui/material/Typography';
import clsx from 'clsx';
import { useRecordContext } from 'ra-core';
import { useRecordContext, useTranslate } from 'ra-core';

import { sanitizeFieldRestProps } from './sanitizeFieldRestProps';
import { PublicFieldProps, InjectedFieldProps, fieldPropTypes } from './types';

export const ChipField: FC<ChipFieldProps> = memo(props => {
const { className, source, emptyText, ...rest } = props;
const record = useRecordContext(props);

const value = get(record, source);
const translate = useTranslate();

if (value == null && emptyText) {
return (
@@ -24,7 +24,7 @@ export const ChipField: FC<ChipFieldProps> = memo(props => {
className={className}
{...sanitizeFieldRestProps(rest)}
>
{emptyText}
{translate(emptyText, { _: emptyText })}
</Typography>
);
}
35 changes: 34 additions & 1 deletion packages/ra-ui-materialui/src/field/DateField.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
import * as React from 'react';
import expect from 'expect';
import { render } from '@testing-library/react';
import { RecordContextProvider } from 'ra-core';
import { RecordContextProvider, I18nContextProvider } from 'ra-core';
import polyglotI18nProvider from 'ra-i18n-polyglot';

import { DateField } from './DateField';

const i18nProvider = polyglotI18nProvider(
_locale => ({
resources: {
books: {
name: 'Books',
fields: {
id: 'Id',
title: 'Title',
author: 'Author',
year: 'Year',
},
not_found: 'Not found',
},
},
}),
'en'
);

describe('<DateField />', () => {
it('should return null when the record is not set', () => {
const { container } = render(<DateField source="foo" />);
@@ -161,4 +180,18 @@ describe('<DateField />', () => {
expect(queryByText('NA')).not.toBeNull();
}
);

it('should translate emptyText', () => {
const { getByText } = render(
<I18nContextProvider value={i18nProvider}>
<DateField
record={{ id: 123 }}
source="foo.bar"
emptyText="resources.books.not_found"
/>
</I18nContextProvider>
);

expect(getByText('Not found')).not.toBeNull();
});
});
6 changes: 4 additions & 2 deletions packages/ra-ui-materialui/src/field/DateField.tsx
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ import { memo, FC } from 'react';
import PropTypes from 'prop-types';
import get from 'lodash/get';
import { Typography, TypographyProps } from '@mui/material';
import { useRecordContext } from 'ra-core';
import { useRecordContext, useTranslate } from 'ra-core';

import { sanitizeFieldRestProps } from './sanitizeFieldRestProps';
import { PublicFieldProps, InjectedFieldProps, fieldPropTypes } from './types';
@@ -43,6 +43,7 @@ export const DateField: FC<DateFieldProps> = memo(props => {
source,
...rest
} = props;
const translate = useTranslate();

if (!showTime && !showDate) {
throw new Error(
@@ -54,6 +55,7 @@ export const DateField: FC<DateFieldProps> = memo(props => {
if (!record) {
return null;
}

const value = get(record, source);
if (value == null || value === '') {
return emptyText ? (
@@ -63,7 +65,7 @@ export const DateField: FC<DateFieldProps> = memo(props => {
className={className}
{...sanitizeFieldRestProps(rest)}
>
{emptyText}
{translate(emptyText, { _: emptyText })}
</Typography>
) : null;
}
35 changes: 34 additions & 1 deletion packages/ra-ui-materialui/src/field/EmailField.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
import * as React from 'react';
import expect from 'expect';
import { render } from '@testing-library/react';
import { RecordContextProvider } from 'ra-core';
import { RecordContextProvider, I18nContextProvider } from 'ra-core';
import polyglotI18nProvider from 'ra-i18n-polyglot';

import { EmailField } from './EmailField';

const i18nProvider = polyglotI18nProvider(
_locale => ({
resources: {
books: {
name: 'Books',
fields: {
id: 'Id',
title: 'Title',
author: 'Author',
year: 'Year',
},
not_found: 'Not found',
},
},
}),
'en'
);

const url = 'foo@bar.com';

describe('<EmailField />', () => {
@@ -87,4 +106,18 @@ describe('<EmailField />', () => {
);
expect(container.firstChild).toBeNull();
});

it('should translate emptyText', () => {
const { getByText } = render(
<I18nContextProvider value={i18nProvider}>
<EmailField
record={{ id: 123 }}
source="foo.bar"
emptyText="resources.books.not_found"
/>
</I18nContextProvider>
);

expect(getByText('Not found')).not.toBeNull();
});
});
5 changes: 3 additions & 2 deletions packages/ra-ui-materialui/src/field/EmailField.tsx
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ import { memo, FC } from 'react';
import get from 'lodash/get';
import Typography from '@mui/material/Typography';
import { Link, LinkProps } from '@mui/material';
import { useRecordContext } from 'ra-core';
import { useRecordContext, useTranslate } from 'ra-core';

import { sanitizeFieldRestProps } from './sanitizeFieldRestProps';
import { PublicFieldProps, InjectedFieldProps, fieldPropTypes } from './types';
@@ -12,6 +12,7 @@ export const EmailField: FC<EmailFieldProps> = memo(props => {
const { className, source, emptyText, ...rest } = props;
const record = useRecordContext(props);
const value = get(record, source);
const translate = useTranslate();

if (value == null) {
return emptyText ? (
@@ -21,7 +22,7 @@ export const EmailField: FC<EmailFieldProps> = memo(props => {
className={className}
{...sanitizeFieldRestProps(rest)}
>
{emptyText}
{translate(emptyText, { _: emptyText })}
</Typography>
) : null;
}
35 changes: 34 additions & 1 deletion packages/ra-ui-materialui/src/field/FileField.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as React from 'react';
import expect from 'expect';
import { render } from '@testing-library/react';
import { RecordContextProvider } from 'ra-core';
import { RecordContextProvider, I18nContextProvider } from 'ra-core';
import polyglotI18nProvider from 'ra-i18n-polyglot';

import { FileField } from './FileField';

@@ -10,6 +11,24 @@ const defaultProps = {
source: 'url',
};

const i18nProvider = polyglotI18nProvider(
_locale => ({
resources: {
books: {
name: 'Books',
fields: {
id: 'Id',
title: 'Title',
author: 'Author',
year: 'Year',
},
not_found: 'Not found',
},
},
}),
'en'
);

describe('<FileField />', () => {
it('should return an empty div when record is not set', () => {
const { container } = render(<FileField {...defaultProps} />);
@@ -163,4 +182,18 @@ describe('<FileField />', () => {
);
expect(container.children[0].classList.contains('foo')).toBe(true);
});

it('should translate emptyText', () => {
const { getByText } = render(
<I18nContextProvider value={i18nProvider}>
<FileField
record={{ id: 123 }}
source="foo.bar"
emptyText="resources.books.not_found"
/>
</I18nContextProvider>
);

expect(getByText('Not found')).not.toBeNull();
});
});
5 changes: 3 additions & 2 deletions packages/ra-ui-materialui/src/field/FileField.tsx
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ import { styled } from '@mui/material/styles';
import PropTypes from 'prop-types';
import get from 'lodash/get';
import Typography from '@mui/material/Typography';
import { useRecordContext } from 'ra-core';
import { useRecordContext, useTranslate } from 'ra-core';

import { sanitizeFieldRestProps } from './sanitizeFieldRestProps';
import { PublicFieldProps, InjectedFieldProps, fieldPropTypes } from './types';
@@ -38,6 +38,7 @@ export const FileField = (props: FileFieldProps) => {
} = props;
const record = useRecordContext(props);
const sourceValue = get(record, source);
const translate = useTranslate();

if (!sourceValue) {
return emptyText ? (
@@ -47,7 +48,7 @@ export const FileField = (props: FileFieldProps) => {
className={className}
{...sanitizeFieldRestProps(rest)}
>
{emptyText}
{translate(emptyText, { _: emptyText })}
</Typography>
) : (
<Root className={className} {...sanitizeFieldRestProps(rest)} />
Loading