mirror of
https://github.com/strapi/strapi.git
synced 2025-09-09 08:39:45 +00:00
Merge pull request #9760 from strapi/i18n/cm-fix-relations
[I18n] CM fix navigation between localised content types
This commit is contained in:
commit
0e336b4e31
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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} </Span>
|
<Span>{formattedValue} </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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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}
|
||||||
/>
|
/>
|
||||||
|
@ -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 });
|
||||||
|
@ -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: {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user