mirror of
https://github.com/strapi/strapi.git
synced 2025-12-27 07:03:38 +00:00
Add dnd relation state
Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
parent
bb4cea6019
commit
d3082807d1
@ -19,8 +19,8 @@
|
||||
"type": "string"
|
||||
},
|
||||
"categories": {
|
||||
"via": "addresses",
|
||||
"collection": "category",
|
||||
"via": "addresses",
|
||||
"dominant": true
|
||||
},
|
||||
"cover": {
|
||||
@ -46,6 +46,10 @@
|
||||
"city": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"likes": {
|
||||
"collection": "like",
|
||||
"via": "address"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,8 +16,8 @@
|
||||
"type": "string"
|
||||
},
|
||||
"addresses": {
|
||||
"collection": "address",
|
||||
"via": "categories"
|
||||
"via": "categories",
|
||||
"collection": "address"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
{
|
||||
"kind": "collectionType",
|
||||
"collectionName": "likes",
|
||||
"info": {
|
||||
"name": "like",
|
||||
@ -18,6 +19,10 @@
|
||||
"review": {
|
||||
"model": "review",
|
||||
"via": "likes"
|
||||
},
|
||||
"address": {
|
||||
"via": "likes",
|
||||
"model": "address"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +66,13 @@ const CustomDragLayer = () => {
|
||||
case ItemTypes.RELATION:
|
||||
return (
|
||||
<Li>
|
||||
<RelationItem data={item.data} mainField={item.mainField} isDisabled={false} />
|
||||
<RelationItem
|
||||
data={item.data}
|
||||
mainField={item.mainField}
|
||||
isDisabled={false}
|
||||
isDragging
|
||||
hasDraftAndPublish={item.hasDraftAndPublish}
|
||||
/>
|
||||
</Li>
|
||||
);
|
||||
case ItemTypes.EDIT_FIELD:
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const RelationDPState = styled.div`
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
display: flex;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
margin-bottom: 1px;
|
||||
margin-left: 10px;
|
||||
border-radius: 50%;
|
||||
background-color: ${({ theme, isDraft }) =>
|
||||
isDraft ? theme.main.colors.mediumBlue : theme.main.colors.green};
|
||||
}
|
||||
`;
|
||||
|
||||
export default RelationDPState;
|
||||
@ -12,6 +12,7 @@ import Relation from './Relation';
|
||||
function ListItem({
|
||||
data,
|
||||
findRelation,
|
||||
hasDraftAndPublish,
|
||||
isDisabled,
|
||||
mainField,
|
||||
moveRelation,
|
||||
@ -27,6 +28,7 @@ function ListItem({
|
||||
id: data.id,
|
||||
originalIndex,
|
||||
data,
|
||||
hasDraftAndPublish,
|
||||
mainField,
|
||||
},
|
||||
collect: monitor => ({
|
||||
@ -60,6 +62,7 @@ function ListItem({
|
||||
style={{ opacity }}
|
||||
>
|
||||
<Relation
|
||||
hasDraftAndPublish={hasDraftAndPublish}
|
||||
mainField={mainField}
|
||||
onRemove={onRemove}
|
||||
data={data}
|
||||
@ -80,6 +83,7 @@ ListItem.defaultProps = {
|
||||
ListItem.propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
findRelation: PropTypes.func,
|
||||
hasDraftAndPublish: PropTypes.bool.isRequired,
|
||||
isDisabled: PropTypes.bool.isRequired,
|
||||
mainField: PropTypes.string.isRequired,
|
||||
moveRelation: PropTypes.func,
|
||||
|
||||
@ -2,30 +2,53 @@
|
||||
import React, { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import pluginId from '../../pluginId';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { getTrad } from '../../utils';
|
||||
import IconRemove from '../../assets/images/icon_remove.svg';
|
||||
import RelationDPState from '../RelationDPState';
|
||||
import { Span } from './components';
|
||||
|
||||
/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
|
||||
|
||||
const Relation = ({ data, isDisabled, mainField, onRemove, to }) => {
|
||||
const Relation = ({
|
||||
data,
|
||||
hasDraftAndPublish,
|
||||
isDisabled,
|
||||
isDragging,
|
||||
mainField,
|
||||
onRemove,
|
||||
to,
|
||||
}) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const cursor = isDisabled ? 'not-allowed' : 'pointer';
|
||||
const { pathname } = useLocation();
|
||||
const isDraft = isEmpty(data.published_at);
|
||||
const titleLabelID = isDraft
|
||||
? 'components.Select.draft-info-title'
|
||||
: 'components.Select.publish-info-title';
|
||||
let title = hasDraftAndPublish
|
||||
? formatMessage({ id: getTrad(titleLabelID) })
|
||||
: formatMessage({ id: getTrad('containers.Edit.clickToJump') });
|
||||
|
||||
if (isDragging) {
|
||||
title = '';
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div style={{ cursor }}>
|
||||
<div style={{ cursor }} title={title}>
|
||||
<div className="dragHandle">
|
||||
<span />
|
||||
</div>
|
||||
<FormattedMessage id={`${pluginId}.containers.Edit.clickToJump`}>
|
||||
{title => (
|
||||
<Link to={{ pathname: to, state: { from: pathname } }} title={title}>
|
||||
<Span>{data[mainField]}</Span>
|
||||
</Link>
|
||||
)}
|
||||
</FormattedMessage>
|
||||
{hasDraftAndPublish && (
|
||||
<div>
|
||||
<RelationDPState isDraft={isDraft} />
|
||||
</div>
|
||||
)}
|
||||
<Link to={{ pathname: to, state: { from: pathname } }} title={title}>
|
||||
<Span>{data[mainField]}</Span>
|
||||
</Link>
|
||||
</div>
|
||||
<div style={{ cursor }}>
|
||||
<img src={IconRemove} alt="Remove Icon" onClick={onRemove} />
|
||||
@ -35,13 +58,16 @@ const Relation = ({ data, isDisabled, mainField, onRemove, to }) => {
|
||||
};
|
||||
|
||||
Relation.defaultProps = {
|
||||
isDragging: false,
|
||||
onRemove: () => {},
|
||||
to: '',
|
||||
};
|
||||
|
||||
Relation.propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
hasDraftAndPublish: PropTypes.bool.isRequired,
|
||||
isDisabled: PropTypes.bool.isRequired,
|
||||
isDragging: PropTypes.bool,
|
||||
mainField: PropTypes.string.isRequired,
|
||||
onRemove: PropTypes.func,
|
||||
to: PropTypes.string,
|
||||
|
||||
@ -2,10 +2,8 @@ import React, { memo, useCallback } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { useDrop } from 'react-dnd';
|
||||
|
||||
import Select, { createFilter } from 'react-select';
|
||||
import ItemTypes from '../../utils/ItemTypes';
|
||||
|
||||
import { ListShadow, ListWrapper } from './components';
|
||||
import ListItem from './ListItem';
|
||||
|
||||
@ -13,6 +11,7 @@ function SelectMany({
|
||||
addRelation,
|
||||
mainField,
|
||||
name,
|
||||
hasDraftAndPublish,
|
||||
isDisabled,
|
||||
isLoading,
|
||||
move,
|
||||
@ -95,6 +94,7 @@ function SelectMany({
|
||||
<ListItem
|
||||
key={data.id}
|
||||
data={data}
|
||||
hasDraftAndPublish={hasDraftAndPublish}
|
||||
isDisabled={isDisabled}
|
||||
findRelation={findRelation}
|
||||
mainField={mainField}
|
||||
@ -122,11 +122,12 @@ SelectMany.defaultProps = {
|
||||
|
||||
SelectMany.propTypes = {
|
||||
addRelation: PropTypes.func.isRequired,
|
||||
hasDraftAndPublish: PropTypes.bool.isRequired,
|
||||
isDisabled: PropTypes.bool.isRequired,
|
||||
isLoading: PropTypes.bool.isRequired,
|
||||
mainField: PropTypes.string.isRequired,
|
||||
move: PropTypes.func,
|
||||
name: PropTypes.string.isRequired,
|
||||
isLoading: PropTypes.bool.isRequired,
|
||||
onInputChange: PropTypes.func.isRequired,
|
||||
onMenuClose: PropTypes.func.isRequired,
|
||||
onMenuScrollToBottom: PropTypes.func.isRequired,
|
||||
|
||||
@ -3,7 +3,7 @@ import React, { useState, useEffect, useMemo, useRef, memo } from 'react';
|
||||
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 { cloneDeep, findIndex, get, isArray, isEmpty, set, has } from 'lodash';
|
||||
import { request } from 'strapi-helper-plugin';
|
||||
import pluginId from '../../pluginId';
|
||||
import useDataManager from '../../hooks/useDataManager';
|
||||
@ -34,6 +34,7 @@ function SelectWrapper({
|
||||
const isMorph = relationType.toLowerCase().includes('morph');
|
||||
const { addRelation, modifiedData, moveRelation, onChange, onRemoveRelation } = useDataManager();
|
||||
const { isDraggingComponent } = useEditView();
|
||||
const [hasDraftAndPublish, setHasDraftAndPublish] = useState(false);
|
||||
|
||||
// This is needed for making requests when used in a component
|
||||
const fieldName = useMemo(() => {
|
||||
@ -102,6 +103,10 @@ function SelectWrapper({
|
||||
signal,
|
||||
});
|
||||
|
||||
if (data.some(value => has(value, 'published_at'))) {
|
||||
setHasDraftAndPublish(true);
|
||||
}
|
||||
|
||||
const formattedData = data.map(obj => {
|
||||
return { value: obj, label: obj[mainField] };
|
||||
});
|
||||
@ -240,6 +245,7 @@ function SelectWrapper({
|
||||
addRelation={value => {
|
||||
addRelation({ target: { name, value } });
|
||||
}}
|
||||
hasDraftAndPublish={hasDraftAndPublish}
|
||||
id={name}
|
||||
isDisabled={isDisabled}
|
||||
isLoading={isLoading}
|
||||
|
||||
@ -20,6 +20,8 @@
|
||||
"components.FiltersPickWrapper.hide": "Hide",
|
||||
"components.LimitSelect.itemsPerPage": "Items per page",
|
||||
"components.NotAllowedInput.text": "No permissions to see this field",
|
||||
"components.Select.draft-info-title": "State: Draft",
|
||||
"components.Select.publish-info-title": "State: Published",
|
||||
"components.Search.placeholder": "Search for an entry...",
|
||||
"components.SettingsViewWrapper.pluginHeader.description.edit-settings": "Customize how the edit view will look like.",
|
||||
"components.SettingsViewWrapper.pluginHeader.description.list-settings": "Define the settings of the list view.",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user