Fix navigation between relations

Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
soupette 2020-09-09 11:08:08 +02:00 committed by Pierre Noël
parent 92a43a8152
commit e10452c245
7 changed files with 74 additions and 39 deletions

View File

@ -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,

View File

@ -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]}&nbsp;</Span>
</Link>
) : (
<Span>{data[mainField]}&nbsp;</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,

View File

@ -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,

View File

@ -37,7 +37,7 @@ const Option = props => {
/>
<TextGrow ellipsis as="div" fontWeight={fontWeight}>
{props.label}
{props.label}&nbsp;
</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,

View File

@ -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,

View File

@ -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,

View File

@ -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,
};