Merge pull request #9760 from strapi/i18n/cm-fix-relations

[I18n] CM fix navigation between localised content types
This commit is contained in:
cyril lopez 2021-03-18 11:13:17 +01:00 committed by GitHub
commit 0e336b4e31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 68 additions and 10 deletions

View File

@ -18,6 +18,7 @@ function ListItem({
mainField, mainField,
moveRelation, moveRelation,
onRemove, onRemove,
searchToPersist,
targetModel, targetModel,
}) { }) {
const to = `/plugins/${pluginId}/collectionType/${targetModel}/${data.id}`; const to = `/plugins/${pluginId}/collectionType/${targetModel}/${data.id}`;
@ -72,6 +73,7 @@ function ListItem({
data={data} data={data}
to={to} to={to}
isDisabled={isDisabled} isDisabled={isDisabled}
searchToPersist={searchToPersist}
/> />
</Li> </Li>
); );
@ -81,6 +83,7 @@ ListItem.defaultProps = {
findRelation: () => {}, findRelation: () => {},
moveRelation: () => {}, moveRelation: () => {},
onRemove: () => {}, onRemove: () => {},
searchToPersist: null,
targetModel: '', targetModel: '',
}; };
@ -97,6 +100,7 @@ ListItem.propTypes = {
}).isRequired, }).isRequired,
moveRelation: PropTypes.func, moveRelation: PropTypes.func,
onRemove: PropTypes.func, onRemove: PropTypes.func,
searchToPersist: PropTypes.string,
targetModel: PropTypes.string, targetModel: PropTypes.string,
}; };

View File

@ -19,6 +19,7 @@ const Relation = ({
isDragging, isDragging,
mainField, mainField,
onRemove, onRemove,
searchToPersist,
to, to,
}) => { }) => {
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
@ -61,7 +62,10 @@ const Relation = ({
</div> </div>
)} )}
{displayNavigationLink ? ( {displayNavigationLink ? (
<Link to={{ pathname: to, state: { from: pathname } }} title={title}> <Link
to={{ pathname: to, state: { from: pathname }, search: searchToPersist }}
title={title}
>
<Span>{formattedValue}&nbsp;</Span> <Span>{formattedValue}&nbsp;</Span>
</Link> </Link>
) : ( ) : (
@ -78,6 +82,7 @@ const Relation = ({
Relation.defaultProps = { Relation.defaultProps = {
isDragging: false, isDragging: false,
onRemove: () => {}, onRemove: () => {},
searchToPersist: null,
to: '', to: '',
}; };
@ -94,6 +99,7 @@ Relation.propTypes = {
}).isRequired, }).isRequired,
}).isRequired, }).isRequired,
onRemove: PropTypes.func, onRemove: PropTypes.func,
searchToPersist: PropTypes.string,
to: PropTypes.string, to: PropTypes.string,
}; };

View File

@ -23,6 +23,7 @@ function SelectMany({
onRemove, onRemove,
options, options,
placeholder, placeholder,
searchToPersist,
styles, styles,
targetModel, targetModel,
value, value,
@ -109,6 +110,7 @@ function SelectMany({
onRemove(`${name}.${index}`); onRemove(`${name}.${index}`);
} }
}} }}
searchToPersist={searchToPersist}
targetModel={targetModel} targetModel={targetModel}
/> />
))} ))}
@ -123,6 +125,7 @@ function SelectMany({
SelectMany.defaultProps = { SelectMany.defaultProps = {
components: {}, components: {},
move: () => {}, move: () => {},
searchToPersist: null,
value: null, value: null,
}; };
@ -147,6 +150,7 @@ SelectMany.propTypes = {
onRemove: PropTypes.func.isRequired, onRemove: PropTypes.func.isRequired,
options: PropTypes.array.isRequired, options: PropTypes.array.isRequired,
placeholder: PropTypes.node.isRequired, placeholder: PropTypes.node.isRequired,
searchToPersist: PropTypes.string,
styles: PropTypes.object.isRequired, styles: PropTypes.object.isRequired,
targetModel: PropTypes.string.isRequired, targetModel: PropTypes.string.isRequired,
value: PropTypes.array, value: PropTypes.array,

View File

@ -2,14 +2,16 @@ import React, { useCallback, useState, useEffect, useMemo, memo } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { FormattedMessage, useIntl } from 'react-intl'; import { FormattedMessage, useIntl } from 'react-intl';
import { Link, useLocation } from 'react-router-dom'; import { Link, useLocation } from 'react-router-dom';
import { findIndex, get, isArray, isEmpty } from 'lodash'; import { findIndex, get, isArray, isEmpty, set } from 'lodash';
import { import {
LabelIconWrapper, LabelIconWrapper,
NotAllowedInput, NotAllowedInput,
request, request,
useContentManagerEditViewDataManager, useContentManagerEditViewDataManager,
useQueryParams,
} from 'strapi-helper-plugin'; } from 'strapi-helper-plugin';
import { Flex, Text, Padded } from '@buffetjs/core'; import { Flex, Text, Padded } from '@buffetjs/core';
import { stringify } from 'qs';
import pluginId from '../../pluginId'; import pluginId from '../../pluginId';
import SelectOne from '../SelectOne'; import SelectOne from '../SelectOne';
import SelectMany from '../SelectMany'; import SelectMany from '../SelectMany';
@ -25,6 +27,22 @@ const initialPaginationState = {
_limit: 20, _limit: 20,
_start: 0, _start: 0,
}; };
const buildParams = (query, paramsToKeep) => {
if (!paramsToKeep) {
return {};
}
return paramsToKeep.reduce((acc, current) => {
const value = get(query, current, null);
if (value) {
set(acc, current, value);
}
return acc;
}, {});
};
function SelectWrapper({ function SelectWrapper({
description, description,
editable, editable,
@ -41,6 +59,7 @@ function SelectWrapper({
queryInfos, queryInfos,
}) { }) {
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
const [{ query }] = useQueryParams();
// Disable the input in case of a polymorphic relation // Disable the input in case of a polymorphic relation
const isMorph = useMemo(() => relationType.toLowerCase().includes('morph'), [relationType]); const isMorph = useMemo(() => relationType.toLowerCase().includes('morph'), [relationType]);
const { const {
@ -74,7 +93,13 @@ function SelectWrapper({
}); });
}, [options, value]); }, [options, value]);
const { endPoint, containsKey, defaultParams, shouldDisplayRelationLink } = queryInfos; const {
endPoint,
containsKey,
defaultParams,
shouldDisplayRelationLink,
paramsToKeep,
} = queryInfos;
const isSingle = ['oneWay', 'oneToOne', 'manyToOne', 'oneToManyMorph', 'oneToOneMorph'].includes( const isSingle = ['oneWay', 'oneToOne', 'manyToOne', 'oneToManyMorph', 'oneToOneMorph'].includes(
relationType relationType
@ -206,6 +231,8 @@ function SelectWrapper({
const to = `/plugins/${pluginId}/collectionType/${targetModel}/${value ? value.id : null}`; const to = `/plugins/${pluginId}/collectionType/${targetModel}/${value ? value.id : null}`;
const searchToPersist = stringify(buildParams(query, paramsToKeep), { encode: false });
const link = useMemo(() => { const link = useMemo(() => {
if (!value) { if (!value) {
return null; return null;
@ -216,13 +243,13 @@ function SelectWrapper({
} }
return ( return (
<Link to={{ pathname: to, state: { from: pathname } }}> <Link to={{ pathname: to, state: { from: pathname }, search: searchToPersist }}>
<FormattedMessage id="content-manager.containers.Edit.seeDetails"> <FormattedMessage id="content-manager.containers.Edit.seeDetails">
{msg => <A color="mediumBlue">{msg}</A>} {msg => <A color="mediumBlue">{msg}</A>}
</FormattedMessage> </FormattedMessage>
</Link> </Link>
); );
}, [shouldDisplayRelationLink, pathname, to, value]); }, [shouldDisplayRelationLink, pathname, to, value, searchToPersist]);
const Component = isSingle ? SelectOne : SelectMany; const Component = isSingle ? SelectOne : SelectMany;
const associationsLength = isArray(value) ? value.length : 0; const associationsLength = isArray(value) ? value.length : 0;
@ -305,6 +332,7 @@ function SelectWrapper({
placeholder placeholder
) )
} }
searchToPersist={searchToPersist}
styles={styles} styles={styles}
targetModel={targetModel} targetModel={targetModel}
value={value} value={value}
@ -348,11 +376,12 @@ SelectWrapper.propTypes = {
placeholder: PropTypes.string, placeholder: PropTypes.string,
relationType: PropTypes.string.isRequired, relationType: PropTypes.string.isRequired,
targetModel: PropTypes.string.isRequired, targetModel: PropTypes.string.isRequired,
queryInfos: PropTypes.exact({ queryInfos: PropTypes.shape({
containsKey: PropTypes.string.isRequired, containsKey: PropTypes.string.isRequired,
defaultParams: PropTypes.object, defaultParams: PropTypes.object,
endPoint: PropTypes.string.isRequired, endPoint: PropTypes.string.isRequired,
shouldDisplayRelationLink: PropTypes.bool.isRequired, shouldDisplayRelationLink: PropTypes.bool.isRequired,
paramsToKeep: PropTypes.array,
}).isRequired, }).isRequired,
}; };

View File

@ -1,4 +1,4 @@
import React from 'react'; import React, { useMemo } from 'react';
import get from 'lodash/get'; import get from 'lodash/get';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
@ -16,11 +16,19 @@ const CMEditViewInjectedComponents = () => {
const id = get(params, 'id', null); const id = get(params, 'id', null);
const currentEntityId = id === 'create' ? null : id; const currentEntityId = id === 'create' ? null : id;
const currentLocale = get(query, 'plugins.i18n.locale', false); const defaultLocale = locales.find(loc => loc.isDefault);
const currentLocale = get(query, 'plugins.i18n.locale', defaultLocale.code);
const hasI18nEnabled = get(layout, ['pluginOptions', 'i18n', 'localized'], false); const hasI18nEnabled = get(layout, ['pluginOptions', 'i18n', 'localized'], false);
const hasDraftAndPublishEnabled = get(layout, ['options', 'draftAndPublish'], false); const hasDraftAndPublishEnabled = get(layout, ['options', 'draftAndPublish'], false);
const defaultQuery = useMemo(() => {
if (!query) {
return { plugins: { i18n: { locale: currentLocale } } };
}
return query;
}, [query, currentLocale]);
if (!hasI18nEnabled) { if (!hasI18nEnabled) {
return null; return null;
} }
@ -42,7 +50,7 @@ const CMEditViewInjectedComponents = () => {
createPermissions={createPermissions} createPermissions={createPermissions}
hasDraftAndPublishEnabled={hasDraftAndPublishEnabled} hasDraftAndPublishEnabled={hasDraftAndPublishEnabled}
localizations={localizations} localizations={localizations}
query={query} query={defaultQuery}
readPermissions={readPermissions} readPermissions={readPermissions}
slug={slug} slug={slug}
/> />

View File

@ -18,6 +18,7 @@ const enhanceRelationLayout = (layout, locale) =>
queryInfos = { queryInfos = {
...queryInfos, ...queryInfos,
defaultParams: { ...queryInfos.defaultParams, _locale: locale }, defaultParams: { ...queryInfos.defaultParams, _locale: locale },
paramsToKeep: ['plugins.i18n.locale'],
}; };
} }
@ -79,6 +80,7 @@ const enhanceComponentLayoutForRelations = (layout, locale) =>
const queryInfos = { const queryInfos = {
...field.queryInfos, ...field.queryInfos,
defaultParams: { ...field.queryInfos.defaultParams, _locale: locale }, defaultParams: { ...field.queryInfos.defaultParams, _locale: locale },
paramsToKeep: ['plugins.i18n.locale'],
}; };
acc.push({ ...field, queryInfos }); acc.push({ ...field, queryInfos });

View File

@ -107,6 +107,7 @@ describe('i18n | Middlewares | extendCMEditViewLayoutMiddleware', () => {
queryInfos: { queryInfos: {
test: true, test: true,
defaultParams: {}, defaultParams: {},
paramsToKeep: ['plugins.i18n.locale'],
}, },
size: 6, size: 6,
targetModelPluginOptions: {}, targetModelPluginOptions: {},
@ -143,6 +144,7 @@ describe('i18n | Middlewares | extendCMEditViewLayoutMiddleware', () => {
queryInfos: { queryInfos: {
test: true, test: true,
defaultParams: {}, defaultParams: {},
paramsToKeep: ['plugins.i18n.locale'],
}, },
size: 6, size: 6,
targetModelPluginOptions: {}, targetModelPluginOptions: {},
@ -305,6 +307,7 @@ describe('i18n | Middlewares | extendCMEditViewLayoutMiddleware', () => {
targetModelPluginOptions: { i18n: { localized: true } }, targetModelPluginOptions: { i18n: { localized: true } },
queryInfos: { queryInfos: {
defaultParams: { test: true, _locale: 'en' }, defaultParams: { test: true, _locale: 'en' },
paramsToKeep: ['plugins.i18n.locale'],
}, },
}, },
{ {
@ -326,6 +329,7 @@ describe('i18n | Middlewares | extendCMEditViewLayoutMiddleware', () => {
targetModelPluginOptions: { i18n: { localized: true } }, targetModelPluginOptions: { i18n: { localized: true } },
queryInfos: { queryInfos: {
defaultParams: { test: true, _locale: 'en' }, defaultParams: { test: true, _locale: 'en' },
paramsToKeep: ['plugins.i18n.locale'],
}, },
}, },
{ {
@ -515,6 +519,7 @@ describe('i18n | Middlewares | extendCMEditViewLayoutMiddleware', () => {
test: true, test: true,
_locale: 'en', _locale: 'en',
}, },
paramsToKeep: ['plugins.i18n.locale'],
}, },
size: 6, size: 6,
targetModelPluginOptions: { targetModelPluginOptions: {