From 1a7b3b91581f6628a3ed577aff1ccaac65de2235 Mon Sep 17 00:00:00 2001 From: Gildas Garcia <1122076+djhi@users.noreply.github.com> Date: Tue, 9 Jan 2024 17:51:32 +0100 Subject: [PATCH] Replace LabelPrefix with SourceContext --- packages/ra-core/src/form/Form.tsx | 11 +++++--- .../src/i18n/useTranslateLabel.spec.tsx | 24 ++++++++++++++++- .../ra-core/src/i18n/useTranslateLabel.ts | 6 ++--- .../ra-core/src/util/LabelPrefixContext.ts | 3 --- .../src/util/LabelPrefixContextProvider.tsx | 18 ------------- .../util/getFieldLabelTranslationArgs.spec.ts | 10 +++---- .../src/util/getFieldLabelTranslationArgs.ts | 26 +++++++++---------- packages/ra-core/src/util/index.ts | 6 +---- packages/ra-core/src/util/useLabelPrefix.ts | 4 --- .../ArrayInput/SimpleFormIteratorItem.tsx | 16 +++++++++--- .../input/TranslatableInputsTabContent.tsx | 16 +++++++----- .../src/list/filter/FilterForm.tsx | 16 +++++++++--- 12 files changed, 86 insertions(+), 70 deletions(-) delete mode 100644 packages/ra-core/src/util/LabelPrefixContext.ts delete mode 100644 packages/ra-core/src/util/LabelPrefixContextProvider.tsx delete mode 100644 packages/ra-core/src/util/useLabelPrefix.ts diff --git a/packages/ra-core/src/form/Form.tsx b/packages/ra-core/src/form/Form.tsx index ebd01f28910..5d440bf6d4a 100644 --- a/packages/ra-core/src/form/Form.tsx +++ b/packages/ra-core/src/form/Form.tsx @@ -14,8 +14,7 @@ import { OptionalRecordContextProvider, SaveHandler, } from '../controller'; -import { useResourceContext } from '../core'; -import { LabelPrefixContextProvider } from '../util'; +import { SourceContextProvider, SourceContextValue, useResourceContext } from '../core'; import { ValidateForm } from './getSimpleValidationResolver'; import { useAugmentedForm } from './useAugmentedForm'; @@ -53,10 +52,14 @@ export const Form = (props: FormProps) => { const record = useRecordContext(props); const resource = useResourceContext(props); const { form, formHandleSubmit } = useAugmentedForm(props); + const sourceContext = React.useMemo(() => ({ + getSource: (source: string) => source, + getLabel: (source: string) => `resources.${resource}.fields.${source}`, + }), [resource]); return ( - +
(props: FormProps) => {
-
+
); }; diff --git a/packages/ra-core/src/i18n/useTranslateLabel.spec.tsx b/packages/ra-core/src/i18n/useTranslateLabel.spec.tsx index d166e0367ae..a863f289493 100644 --- a/packages/ra-core/src/i18n/useTranslateLabel.spec.tsx +++ b/packages/ra-core/src/i18n/useTranslateLabel.spec.tsx @@ -146,10 +146,32 @@ describe('useTranslateLabel', () => { getLabel: source => `test.${source}`, }} > - + ); screen.getByText('Label for title'); }); + + it('should return the inferred label when a resource prop is provided even when a SourceContext is present', () => { + render( + + source, + getLabel: source => `test.${source}`, + }} + > + + + + ); + screen.getByText('Title'); + }); }); diff --git a/packages/ra-core/src/i18n/useTranslateLabel.ts b/packages/ra-core/src/i18n/useTranslateLabel.ts index 7e3875d6d08..1bebd4cd78a 100644 --- a/packages/ra-core/src/i18n/useTranslateLabel.ts +++ b/packages/ra-core/src/i18n/useTranslateLabel.ts @@ -1,12 +1,11 @@ import { useCallback, ReactElement } from 'react'; import { useTranslate } from './useTranslate'; -import { useLabelPrefix, getFieldLabelTranslationArgs } from '../util'; +import { getFieldLabelTranslationArgs } from '../util'; import { useResourceContext, useSourceContext } from '../core'; export const useTranslateLabel = () => { const translate = useTranslate(); - const prefix = useLabelPrefix(); const resourceFromContext = useResourceContext(); const sourceContext = useSourceContext(); @@ -34,13 +33,12 @@ export const useTranslateLabel = () => { ...getFieldLabelTranslationArgs({ label: label as string, defaultLabel: sourceContext?.getLabel(source), - prefix, resource, resourceFromContext, source: finalSource, }) ); }, - [prefix, resourceFromContext, translate, sourceContext] + [resourceFromContext, translate, sourceContext] ); }; diff --git a/packages/ra-core/src/util/LabelPrefixContext.ts b/packages/ra-core/src/util/LabelPrefixContext.ts deleted file mode 100644 index 5ade1aa9910..00000000000 --- a/packages/ra-core/src/util/LabelPrefixContext.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { createContext } from 'react'; - -export const LabelPrefixContext = createContext(''); diff --git a/packages/ra-core/src/util/LabelPrefixContextProvider.tsx b/packages/ra-core/src/util/LabelPrefixContextProvider.tsx deleted file mode 100644 index b5d0efa6cf0..00000000000 --- a/packages/ra-core/src/util/LabelPrefixContextProvider.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import * as React from 'react'; -import { LabelPrefixContext } from './LabelPrefixContext'; -import { useLabelPrefix } from './useLabelPrefix'; - -export const LabelPrefixContextProvider = ({ - prefix, - concatenate = true, - children, -}) => { - const oldPrefix = useLabelPrefix(); - const newPrefix = - oldPrefix && concatenate ? `${oldPrefix}.${prefix}` : prefix; - return ( - - {children} - - ); -}; diff --git a/packages/ra-core/src/util/getFieldLabelTranslationArgs.spec.ts b/packages/ra-core/src/util/getFieldLabelTranslationArgs.spec.ts index f693abe149f..8bf08f8aef7 100644 --- a/packages/ra-core/src/util/getFieldLabelTranslationArgs.spec.ts +++ b/packages/ra-core/src/util/getFieldLabelTranslationArgs.spec.ts @@ -80,17 +80,17 @@ describe('getFieldLabelTranslationArgs', () => { getFieldLabelTranslationArgs({ resource: 'posts', resourceFromContext: 'users', - prefix: 'resources.users.fields', + defaultLabel: 'resources.users.fields.name', source: 'referenceOne.users@@name', }) ).toEqual(['resources.users.fields.name', { _: 'Name' }]); }); - it('should prefer the resource over the prefix', () => { + it('should prefer the resource over the defaultLabel', () => { expect( getFieldLabelTranslationArgs({ resource: 'books', - prefix: 'resources.posts.fields', + defaultLabel: 'resources.posts.fields.title', source: 'title', }) ).toEqual([`resources.books.fields.title`, { _: 'Title' }]); @@ -106,10 +106,10 @@ describe('getFieldLabelTranslationArgs', () => { ).toEqual([`resources.posts.fields.title`, { _: 'Title' }]); }); - it('should prefer the prefix over the resourceFromContext', () => { + it('should prefer the defaultLabel over the resourceFromContext', () => { expect( getFieldLabelTranslationArgs({ - prefix: 'resources.posts.fields', + defaultLabel: 'resources.posts.fields.title', resourceFromContext: 'books', source: 'title', }) diff --git a/packages/ra-core/src/util/getFieldLabelTranslationArgs.ts b/packages/ra-core/src/util/getFieldLabelTranslationArgs.ts index 424eae6866e..e929def61df 100644 --- a/packages/ra-core/src/util/getFieldLabelTranslationArgs.ts +++ b/packages/ra-core/src/util/getFieldLabelTranslationArgs.ts @@ -3,7 +3,6 @@ import inflection from 'inflection'; interface Args { label?: string; defaultLabel?: string; - prefix?: string; resource?: string; resourceFromContext?: string; source?: string; @@ -22,13 +21,14 @@ type TranslationArguments = [string, any?]; * * @see useTranslateLabel for a ready-to-use hook */ -export default (options?: Args): TranslationArguments => { +export const getFieldLabelTranslationArgs = ( + options?: Args +): TranslationArguments => { if (!options) return ['']; const { label, defaultLabel, - prefix, resource, resourceFromContext, source, @@ -45,30 +45,28 @@ export default (options?: Args): TranslationArguments => { ['underscore', 'humanize'] ); - if (defaultLabel) { - return [defaultLabel, { _: defaultLabelTranslation }]; - } - if (resource) { return [ - `resources.${resource}.fields.${sourceWithoutDigits}`, + getResourceFieldLabelKey(resource, sourceWithoutDigits), { _: defaultLabelTranslation }, ]; } - if (prefix) { - return [ - `${prefix}.${sourceWithoutDigits}`, - { _: defaultLabelTranslation }, - ]; + if (defaultLabel) { + return [defaultLabel, { _: defaultLabelTranslation }]; } return [ - `resources.${resourceFromContext}.fields.${sourceWithoutDigits}`, + getResourceFieldLabelKey(resourceFromContext, sourceWithoutDigits), { _: defaultLabelTranslation }, ]; }; +export default getFieldLabelTranslationArgs; + +export const getResourceFieldLabelKey = (resource: string, source: string) => + `resources.${resource}.fields.${source}`; + /** * Uses the source string to guess a translation message and a default label. * diff --git a/packages/ra-core/src/util/index.ts b/packages/ra-core/src/util/index.ts index c3aa327aeec..d02a278ad07 100644 --- a/packages/ra-core/src/util/index.ts +++ b/packages/ra-core/src/util/index.ts @@ -1,6 +1,5 @@ import escapePath from './escapePath'; import FieldTitle, { FieldTitleProps } from './FieldTitle'; -import getFieldLabelTranslationArgs from './getFieldLabelTranslationArgs'; import ComponentPropType from './ComponentPropType'; import removeEmpty from './removeEmpty'; import removeKey from './removeKey'; @@ -8,13 +7,13 @@ import Ready from './Ready'; import warning from './warning'; import useWhyDidYouUpdate from './useWhyDidYouUpdate'; import { getMutationMode } from './getMutationMode'; +export * from './getFieldLabelTranslationArgs'; export * from './mergeRefs'; export * from './useEvent'; export { escapePath, FieldTitle, - getFieldLabelTranslationArgs, ComponentPropType, Ready, removeEmpty, @@ -28,7 +27,4 @@ export type { FieldTitleProps }; export * from './asyncDebounce'; export * from './hooks'; export * from './shallowEqual'; -export * from './LabelPrefixContext'; -export * from './LabelPrefixContextProvider'; -export * from './useLabelPrefix'; export * from './useCheckForApplicationUpdate'; diff --git a/packages/ra-core/src/util/useLabelPrefix.ts b/packages/ra-core/src/util/useLabelPrefix.ts deleted file mode 100644 index 24dda069ddf..00000000000 --- a/packages/ra-core/src/util/useLabelPrefix.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { useContext } from 'react'; -import { LabelPrefixContext } from './LabelPrefixContext'; - -export const useLabelPrefix = () => useContext(LabelPrefixContext); diff --git a/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIteratorItem.tsx b/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIteratorItem.tsx index 29a27bc4ecb..18fc6aa36bf 100644 --- a/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIteratorItem.tsx +++ b/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIteratorItem.tsx @@ -9,7 +9,13 @@ import { } from 'react'; import { Typography } from '@mui/material'; import clsx from 'clsx'; -import { RaRecord, SourceContextProvider, useResourceContext } from 'ra-core'; +import { + getResourceFieldLabelKey, + RaRecord, + SourceContextProvider, + useResourceContext, + useSourceContext, +} from 'ra-core'; import { SimpleFormIteratorClasses } from './useSimpleFormIteratorStyles'; import { useSimpleFormIterator } from './useSimpleFormIterator'; @@ -74,19 +80,23 @@ export const SimpleFormIteratorItem = React.forwardRef( ? getItemLabel(index) : getItemLabel; + const parentSourceContext = useSourceContext(); const sourceContext = useMemo( () => ({ getSource: (source: string) => source ? `${member}.${source}` : member, getLabel: (source: string) => { // remove digits, e.g. 'book.authors.2.categories.3.identifier.name' => 'book.authors.categories.identifier.name' - return `resources.${resource}.fields.${member.replace( + const itemSource = `${member.replace( /\.\d+/g, '' )}.${source}`; + return parentSourceContext + ? parentSourceContext.getLabel(itemSource) + : getResourceFieldLabelKey(resource, itemSource); }, }), - [member, resource] + [member, parentSourceContext, resource] ); return ( diff --git a/packages/ra-ui-materialui/src/input/TranslatableInputsTabContent.tsx b/packages/ra-ui-materialui/src/input/TranslatableInputsTabContent.tsx index 3d3b1229233..f1a4f44fd49 100644 --- a/packages/ra-ui-materialui/src/input/TranslatableInputsTabContent.tsx +++ b/packages/ra-ui-materialui/src/input/TranslatableInputsTabContent.tsx @@ -7,7 +7,9 @@ import { FormGroupContextProvider, RaRecord, SourceContextProvider, + getResourceFieldLabelKey, useResourceContext, + useSourceContext, useTranslatableContext, } from 'ra-core'; @@ -21,16 +23,18 @@ export const TranslatableInputsTabContent = ( const { children, groupKey = '', locale, ...other } = props; const resource = useResourceContext(props); const { selectedLocale } = useTranslatableContext(); + const parentSourceContext = useSourceContext(); const sourceContext = useMemo( () => ({ getSource: (source: string) => `${source}.${locale}`, - getLabel: (source: string) => - `resources.${resource}.fields.${source.replace( - `.${locale}`, - '' - )}`, + getLabel: (source: string) => { + const itemSource = source.replace(`.${locale}`, ''); + return parentSourceContext + ? parentSourceContext.getLabel(itemSource) + : getResourceFieldLabelKey(resource, itemSource); + }, }), - [locale, resource] + [locale, parentSourceContext, resource] ); return ( diff --git a/packages/ra-ui-materialui/src/list/filter/FilterForm.tsx b/packages/ra-ui-materialui/src/list/filter/FilterForm.tsx index 6bbba186fd6..3a6f05d3edd 100644 --- a/packages/ra-ui-materialui/src/list/filter/FilterForm.tsx +++ b/packages/ra-ui-materialui/src/list/filter/FilterForm.tsx @@ -9,8 +9,9 @@ import { import PropTypes from 'prop-types'; import { styled } from '@mui/material/styles'; import { - LabelPrefixContextProvider, ListFilterContextValue, + SourceContextProvider, + SourceContextValue, useListContext, useResourceContext, } from 'ra-core'; @@ -130,8 +131,17 @@ export const FilterFormBase = (props: FilterFormBaseProps) => { [hideFilter] ); + const sourceContext = React.useMemo( + () => ({ + getSource: (source: string) => source, + getLabel: (source: string) => + `resources.${resource}.fields.${source}`, + }), + [resource] + ); + return ( - + { ))}
- + ); };