mirror of
https://github.com/strapi/strapi.git
synced 2025-12-15 17:22:57 +00:00
Fix navigation between relations
Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
parent
92a43a8152
commit
e10452c245
@ -1,9 +1,8 @@
|
||||
import React, { memo, useEffect, useMemo } from 'react';
|
||||
import React, { memo, useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useDrag, useDrop } from 'react-dnd';
|
||||
import { getEmptyImage } from 'react-dnd-html5-backend';
|
||||
import { has } from 'lodash';
|
||||
import { useGlobalContext } from 'strapi-helper-plugin';
|
||||
|
||||
import pluginId from '../../pluginId';
|
||||
import ItemTypes from '../../utils/ItemTypes';
|
||||
@ -13,6 +12,7 @@ import Relation from './Relation';
|
||||
|
||||
function ListItem({
|
||||
data,
|
||||
displayNavigationLink,
|
||||
findRelation,
|
||||
isDisabled,
|
||||
mainField,
|
||||
@ -20,16 +20,7 @@ function ListItem({
|
||||
onRemove,
|
||||
targetModel,
|
||||
}) {
|
||||
const { settingsBaseURL } = useGlobalContext();
|
||||
const to = useMemo(() => {
|
||||
const isAdminUserModel = targetModel === 'strapi::user';
|
||||
|
||||
if (isAdminUserModel) {
|
||||
return `${settingsBaseURL}/users/${data.id}`;
|
||||
}
|
||||
|
||||
return `/plugins/${pluginId}/collectionType/${targetModel}/${data.id}`;
|
||||
}, [targetModel, data.id, settingsBaseURL]);
|
||||
const to = `/plugins/${pluginId}/collectionType/${targetModel}/${data.id}`;
|
||||
|
||||
const hasDraftAndPublish = has(data, 'published_at');
|
||||
|
||||
@ -74,6 +65,7 @@ function ListItem({
|
||||
style={{ opacity }}
|
||||
>
|
||||
<Relation
|
||||
displayNavigationLink={displayNavigationLink}
|
||||
hasDraftAndPublish={hasDraftAndPublish}
|
||||
mainField={mainField}
|
||||
onRemove={onRemove}
|
||||
@ -94,6 +86,7 @@ ListItem.defaultProps = {
|
||||
|
||||
ListItem.propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
displayNavigationLink: PropTypes.bool.isRequired,
|
||||
findRelation: PropTypes.func,
|
||||
isDisabled: PropTypes.bool.isRequired,
|
||||
mainField: PropTypes.string.isRequired,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
||||
import React, { memo } from 'react';
|
||||
import React, { memo, useMemo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { isEmpty } from 'lodash';
|
||||
@ -13,6 +13,7 @@ import { Span } from './components';
|
||||
|
||||
const Relation = ({
|
||||
data,
|
||||
displayNavigationLink,
|
||||
hasDraftAndPublish,
|
||||
isDisabled,
|
||||
isDragging,
|
||||
@ -21,7 +22,17 @@ const Relation = ({
|
||||
to,
|
||||
}) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const cursor = isDisabled ? 'not-allowed' : 'pointer';
|
||||
const cursor = useMemo(() => {
|
||||
if (isDisabled) {
|
||||
return 'not-allowed';
|
||||
}
|
||||
|
||||
if (!displayNavigationLink) {
|
||||
return 'default';
|
||||
}
|
||||
|
||||
return 'pointer';
|
||||
}, [displayNavigationLink, isDisabled]);
|
||||
const { pathname } = useLocation();
|
||||
const isDraft = isEmpty(data.published_at);
|
||||
const titleLabelID = isDraft
|
||||
@ -31,7 +42,7 @@ const Relation = ({
|
||||
? formatMessage({ id: getTrad(titleLabelID) })
|
||||
: formatMessage({ id: getTrad('containers.Edit.clickToJump') });
|
||||
|
||||
if (isDragging) {
|
||||
if (isDragging || !displayNavigationLink) {
|
||||
title = '';
|
||||
}
|
||||
|
||||
@ -46,9 +57,13 @@ const Relation = ({
|
||||
<RelationDPState isDraft={isDraft} />
|
||||
</div>
|
||||
)}
|
||||
<Link to={{ pathname: to, state: { from: pathname } }} title={title}>
|
||||
<Span>{data[mainField]}</Span>
|
||||
</Link>
|
||||
{displayNavigationLink ? (
|
||||
<Link to={{ pathname: to, state: { from: pathname } }} title={title}>
|
||||
<Span>{data[mainField]} </Span>
|
||||
</Link>
|
||||
) : (
|
||||
<Span>{data[mainField]} </Span>
|
||||
)}
|
||||
</div>
|
||||
<div style={{ cursor }}>
|
||||
<img src={IconRemove} alt="Remove Icon" onClick={onRemove} />
|
||||
@ -65,6 +80,7 @@ Relation.defaultProps = {
|
||||
|
||||
Relation.propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
displayNavigationLink: PropTypes.bool.isRequired,
|
||||
hasDraftAndPublish: PropTypes.bool.isRequired,
|
||||
isDisabled: PropTypes.bool.isRequired,
|
||||
isDragging: PropTypes.bool,
|
||||
|
||||
@ -10,6 +10,7 @@ import ListItem from './ListItem';
|
||||
function SelectMany({
|
||||
addRelation,
|
||||
components,
|
||||
displayNavigationLink,
|
||||
mainField,
|
||||
name,
|
||||
isDisabled,
|
||||
@ -95,6 +96,7 @@ function SelectMany({
|
||||
<ListItem
|
||||
key={data.id}
|
||||
data={data}
|
||||
displayNavigationLink={displayNavigationLink}
|
||||
isDisabled={isDisabled}
|
||||
findRelation={findRelation}
|
||||
mainField={mainField}
|
||||
@ -124,7 +126,7 @@ SelectMany.defaultProps = {
|
||||
SelectMany.propTypes = {
|
||||
addRelation: PropTypes.func.isRequired,
|
||||
components: PropTypes.object,
|
||||
|
||||
displayNavigationLink: PropTypes.bool.isRequired,
|
||||
isDisabled: PropTypes.bool.isRequired,
|
||||
isLoading: PropTypes.bool.isRequired,
|
||||
mainField: PropTypes.string.isRequired,
|
||||
|
||||
@ -37,7 +37,7 @@ const Option = props => {
|
||||
/>
|
||||
|
||||
<TextGrow ellipsis as="div" fontWeight={fontWeight}>
|
||||
{props.label}
|
||||
{props.label}
|
||||
</TextGrow>
|
||||
</Flex>
|
||||
</Component>
|
||||
@ -53,8 +53,12 @@ const Option = props => {
|
||||
);
|
||||
};
|
||||
|
||||
Option.defaultProps = {
|
||||
label: '',
|
||||
};
|
||||
|
||||
Option.propTypes = {
|
||||
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
||||
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
isFocused: PropTypes.bool.isRequired,
|
||||
selectProps: PropTypes.shape({
|
||||
hasDraftAndPublish: PropTypes.bool,
|
||||
|
||||
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { cloneDeep, findIndex, get, isArray, isEmpty, set } from 'lodash';
|
||||
import { request, useGlobalContext } from 'strapi-helper-plugin';
|
||||
import { request } from 'strapi-helper-plugin';
|
||||
import { Flex, Text, Padded } from '@buffetjs/core';
|
||||
import pluginId from '../../pluginId';
|
||||
import useDataManager from '../../hooks/useDataManager';
|
||||
@ -22,6 +22,7 @@ import { connect, select, styles } from './utils';
|
||||
function SelectWrapper({
|
||||
componentUid,
|
||||
description,
|
||||
displayNavigationLink,
|
||||
editable,
|
||||
label,
|
||||
isCreatingEntry,
|
||||
@ -34,8 +35,6 @@ function SelectWrapper({
|
||||
targetModel,
|
||||
placeholder,
|
||||
}) {
|
||||
const { settingsBaseURL } = useGlobalContext();
|
||||
|
||||
// Disable the input in case of a polymorphic relation
|
||||
const isMorph = relationType.toLowerCase().includes('morph');
|
||||
const { addRelation, modifiedData, moveRelation, onChange, onRemoveRelation } = useDataManager();
|
||||
@ -187,28 +186,26 @@ function SelectWrapper({
|
||||
relationType
|
||||
);
|
||||
|
||||
const to = useMemo(() => {
|
||||
const isAdminUserModel = targetModel === 'strapi::user';
|
||||
const to = `/plugins/${pluginId}/collectionType/${targetModel}/${value ? value.id : null}`;
|
||||
|
||||
if (isAdminUserModel) {
|
||||
return `${settingsBaseURL}/users/${value ? value.id : null}`;
|
||||
const link = useMemo(() => {
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return `/plugins/${pluginId}/collectionType/${targetModel}/${value ? value.id : null}`;
|
||||
}, [targetModel, value, settingsBaseURL]);
|
||||
if (!displayNavigationLink) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const link =
|
||||
value === null ||
|
||||
value === undefined ||
|
||||
['plugins::users-permissions.role', 'plugins::users-permissions.permission'].includes(
|
||||
targetModel
|
||||
) ? null : (
|
||||
return (
|
||||
<Link to={{ pathname: to, state: { from: pathname } }}>
|
||||
<FormattedMessage id="content-manager.containers.Edit.seeDetails">
|
||||
{msg => <A color="mediumBlue">{msg}</A>}
|
||||
</FormattedMessage>
|
||||
</Link>
|
||||
);
|
||||
}, [displayNavigationLink, pathname, to, value]);
|
||||
|
||||
const Component = isSingle ? SelectOne : SelectMany;
|
||||
const associationsLength = isArray(value) ? value.length : 0;
|
||||
|
||||
@ -258,6 +255,7 @@ function SelectWrapper({
|
||||
addRelation({ target: { name, value } });
|
||||
}}
|
||||
components={{ ClearIndicator, DropdownIndicator, IndicatorSeparator, Option }}
|
||||
displayNavigationLink={displayNavigationLink}
|
||||
id={name}
|
||||
isDisabled={isDisabled}
|
||||
isLoading={isLoading}
|
||||
@ -303,6 +301,7 @@ SelectWrapper.defaultProps = {
|
||||
|
||||
SelectWrapper.propTypes = {
|
||||
componentUid: PropTypes.string,
|
||||
displayNavigationLink: PropTypes.bool.isRequired,
|
||||
editable: PropTypes.bool,
|
||||
description: PropTypes.string,
|
||||
label: PropTypes.string,
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { useMemo } from 'react';
|
||||
import { get } from 'lodash';
|
||||
import useDataManager from '../../../hooks/useDataManager';
|
||||
import useEditView from '../../../hooks/useEditView';
|
||||
|
||||
function useSelect({ isUserAllowedToEditField, isUserAllowedToReadField, name }) {
|
||||
function useSelect({ isUserAllowedToEditField, isUserAllowedToReadField, name, targetModel }) {
|
||||
const {
|
||||
isCreatingEntry,
|
||||
createActionAllowedFields,
|
||||
@ -9,6 +11,13 @@ function useSelect({ isUserAllowedToEditField, isUserAllowedToReadField, name })
|
||||
slug,
|
||||
updateActionAllowedFields,
|
||||
} = useDataManager();
|
||||
const { models } = useEditView();
|
||||
|
||||
const displayNavigationLink = useMemo(() => {
|
||||
const targetModelSchema = models.find(obj => obj.uid === targetModel);
|
||||
|
||||
return get(targetModelSchema, 'isDisplayed', false);
|
||||
}, [targetModel, models]);
|
||||
|
||||
const isFieldAllowed = useMemo(() => {
|
||||
if (isUserAllowedToEditField === true) {
|
||||
@ -37,6 +46,7 @@ function useSelect({ isUserAllowedToEditField, isUserAllowedToReadField, name })
|
||||
}, [isCreatingEntry, isUserAllowedToReadField, name, readActionAllowedFields]);
|
||||
|
||||
return {
|
||||
displayNavigationLink,
|
||||
isCreatingEntry,
|
||||
isFieldAllowed,
|
||||
isFieldReadable,
|
||||
|
||||
@ -27,10 +27,19 @@ import InformationCard from './InformationCard';
|
||||
|
||||
/* eslint-disable react/no-array-index-key */
|
||||
|
||||
const EditView = ({ components, currentEnvironment, deleteLayout, layouts, plugins, slug }) => {
|
||||
const EditView = ({
|
||||
components,
|
||||
currentEnvironment,
|
||||
deleteLayout,
|
||||
layouts,
|
||||
models,
|
||||
plugins,
|
||||
slug,
|
||||
}) => {
|
||||
const formatLayoutRef = useRef();
|
||||
formatLayoutRef.current = createAttributesLayout;
|
||||
const { goBack } = useHistory();
|
||||
|
||||
// Retrieve the search and the pathname
|
||||
const { pathname } = useLocation();
|
||||
const {
|
||||
@ -117,9 +126,10 @@ const EditView = ({ components, currentEnvironment, deleteLayout, layouts, plugi
|
||||
allowedActions={allowedActions}
|
||||
allLayoutData={allLayoutData}
|
||||
components={components}
|
||||
layout={currentContentTypeLayoutData}
|
||||
isDraggingComponent={isDraggingComponent}
|
||||
isSingleType={isSingleType}
|
||||
layout={currentContentTypeLayoutData}
|
||||
models={models}
|
||||
setIsDraggingComponent={() => {
|
||||
dispatch({
|
||||
type: 'SET_IS_DRAGGING_COMPONENT',
|
||||
@ -286,6 +296,7 @@ EditView.propTypes = {
|
||||
deleteLayout: PropTypes.func.isRequired,
|
||||
emitEvent: PropTypes.func,
|
||||
layouts: PropTypes.object.isRequired,
|
||||
models: PropTypes.array.isRequired,
|
||||
plugins: PropTypes.object,
|
||||
slug: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user