1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-04-28 03:10:45 +00:00

upgrade react-dnd react-dnd-html5-backend

This commit is contained in:
zhouwenxuan 2025-04-21 11:02:49 +08:00
parent b43ad4132b
commit bba5014f6d
10 changed files with 320 additions and 332 deletions

View File

@ -46,8 +46,8 @@
"react-app-polyfill": "^2.0.0",
"react-chartjs-2": "5.3.0",
"react-cookies": "^0.1.0",
"react-dnd": "^2.6.0",
"react-dnd-html5-backend": "^2.6.0",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "18.3.1",
"react-i18next": "^10.12.2",
"react-mentions": "4.4.10",
@ -3106,19 +3106,6 @@
}
}
},
"node_modules/@emotion/react/node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"dependencies": {
"react-is": "^16.7.0"
}
},
"node_modules/@emotion/react/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/@emotion/serialize": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz",
@ -5391,6 +5378,21 @@
"resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz",
"integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg=="
},
"node_modules/@react-dnd/asap": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz",
"integrity": "sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A=="
},
"node_modules/@react-dnd/invariant": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@react-dnd/invariant/-/invariant-4.0.2.tgz",
"integrity": "sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw=="
},
"node_modules/@react-dnd/shallowequal": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz",
"integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA=="
},
"node_modules/@replit/codemirror-lang-csharp": {
"version": "6.2.0",
"resolved": "https://registry.npmmirror.com/@replit/codemirror-lang-csharp/-/codemirror-lang-csharp-6.2.0.tgz",
@ -11612,12 +11614,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/disposables": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/disposables/-/disposables-1.0.2.tgz",
"integrity": "sha512-q1XTvs/XGdfubRSemB2+QRhJjIX4PerKkSom+i8Nkw3hCv6xISNrgaN442n2BunyBI4x77Om4ZAzSlqmhM9pwA==",
"license": "Apache-2.0"
},
"node_modules/dlv": {
"version": "1.1.3",
"resolved": "https://registry.npmmirror.com/dlv/-/dlv-1.1.3.tgz",
@ -11626,15 +11622,13 @@
"license": "MIT"
},
"node_modules/dnd-core": {
"version": "2.6.0",
"resolved": "https://registry.npmmirror.com/dnd-core/-/dnd-core-2.6.0.tgz",
"integrity": "sha512-5BfQHIp0XVd4ioF0q4GyUeHQQNCbqP+0SnUiP9TssoQ50wrP1NgSzDqZkjD5pFngsVz9txGin6rvTQD7w0qC3w==",
"license": "BSD-3-Clause",
"version": "16.0.1",
"resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-16.0.1.tgz",
"integrity": "sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==",
"dependencies": {
"asap": "^2.0.6",
"invariant": "^2.0.0",
"lodash": "^4.2.0",
"redux": "^3.7.1"
"@react-dnd/asap": "^5.0.1",
"@react-dnd/invariant": "^4.0.1",
"redux": "^4.2.0"
}
},
"node_modules/dns-packet": {
@ -13510,7 +13504,6 @@
"version": "3.1.3",
"resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true,
"license": "MIT"
},
"node_modules/fast-glob": {
@ -15283,10 +15276,17 @@
}
},
"node_modules/hoist-non-react-statics": {
"version": "2.5.5",
"resolved": "https://registry.npmmirror.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
"integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==",
"license": "BSD-3-Clause"
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"dependencies": {
"react-is": "^16.7.0"
}
},
"node_modules/hoist-non-react-statics/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/hoopy": {
"version": "0.1.4",
@ -24069,29 +24069,40 @@
}
},
"node_modules/react-dnd": {
"version": "2.6.0",
"resolved": "https://registry.npmmirror.com/react-dnd/-/react-dnd-2.6.0.tgz",
"integrity": "sha512-2KHNpeg2SyaxXYq+xO1TM+tOtN9hViI41otJuiYiu6DRYGw+WMvDFDMP4aw7zIKRRm1xd0gizXuKWhb8iJYHBw==",
"license": "BSD-3-Clause",
"version": "16.0.1",
"resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-16.0.1.tgz",
"integrity": "sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==",
"dependencies": {
"disposables": "^1.0.1",
"dnd-core": "^2.6.0",
"hoist-non-react-statics": "^2.1.0",
"invariant": "^2.1.0",
"lodash": "^4.2.0",
"prop-types": "^15.5.10"
"@react-dnd/invariant": "^4.0.1",
"@react-dnd/shallowequal": "^4.0.1",
"dnd-core": "^16.0.1",
"fast-deep-equal": "^3.1.3",
"hoist-non-react-statics": "^3.3.2"
},
"peerDependencies": {
"react": "*"
"@types/hoist-non-react-statics": ">= 3.3.1",
"@types/node": ">= 12",
"@types/react": ">= 16",
"react": ">= 16.14"
},
"peerDependenciesMeta": {
"@types/hoist-non-react-statics": {
"optional": true
},
"@types/node": {
"optional": true
},
"@types/react": {
"optional": true
}
}
},
"node_modules/react-dnd-html5-backend": {
"version": "2.6.0",
"resolved": "https://registry.npmmirror.com/react-dnd-html5-backend/-/react-dnd-html5-backend-2.6.0.tgz",
"integrity": "sha512-8gOfBfqFikWmXvAGSZz1mgoctwkcsKdUC9POt/WGnMoZwGB4ivB0Ex5D6pwHTNjvAs0ixqqWdJKy57CzjDg5Sg==",
"license": "BSD-3-Clause",
"version": "16.0.1",
"resolved": "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz",
"integrity": "sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==",
"dependencies": {
"lodash": "^4.2.0"
"dnd-core": "^16.0.1"
}
},
"node_modules/react-dom": {
@ -24436,15 +24447,11 @@
}
},
"node_modules/redux": {
"version": "3.7.2",
"resolved": "https://registry.npmmirror.com/redux/-/redux-3.7.2.tgz",
"integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==",
"license": "MIT",
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
"integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
"dependencies": {
"lodash": "^4.2.1",
"lodash-es": "^4.2.1",
"loose-envify": "^1.1.0",
"symbol-observable": "^1.0.3"
"@babel/runtime": "^7.9.2"
}
},
"node_modules/reflect.getprototypeof": {
@ -28510,15 +28517,6 @@
"node": ">=4"
}
},
"node_modules/symbol-observable": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/symbol-observable/-/symbol-observable-1.2.0.tgz",
"integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/symbol-tree": {
"version": "3.2.4",
"resolved": "https://registry.npmmirror.com/symbol-tree/-/symbol-tree-3.2.4.tgz",

View File

@ -41,8 +41,8 @@
"react-app-polyfill": "^2.0.0",
"react-chartjs-2": "5.3.0",
"react-cookies": "^0.1.0",
"react-dnd": "^2.6.0",
"react-dnd-html5-backend": "^2.6.0",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "18.3.1",
"react-i18next": "^10.12.2",
"react-mentions": "4.4.10",

View File

@ -3,6 +3,8 @@ import { createRoot } from 'react-dom/client';
import { Router, navigate, LocationProvider, globalHistory } from '@gatsbyjs/reach-router';
import MediaQuery from 'react-responsive';
import { Modal } from 'reactstrap';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { siteRoot, siteTitle, mediaUrl, faviconPath } from './utils/constants';
import { Utils, isMobile } from './utils/utils';
import SystemNotification from './components/system-notification';
@ -315,44 +317,46 @@ class App extends Component {
/>
}
<div className="main-panel" style={mainPanelStyle}>
<Router className="reach-router">
<Libraries path={siteRoot} />
<Libraries path={siteRoot + 'libraries'} />
<MyLibraries path={siteRoot + 'my-libs'} />
<MyLibDeleted path={siteRoot + 'my-libs/deleted/'} />
<ShareAdminShareLinks path={siteRoot + 'share-admin-share-links'} />
<ShareAdminUploadLinks path={siteRoot + 'share-admin-upload-links'} />
<SharedWithAll path={siteRoot + 'org/'} />
<Wikis
path={siteRoot + 'published'}
sidePanelRate={sidePanelRate}
isSidePanelFolded={isSidePanelFolded}
/>
<Starred path={siteRoot + 'starred'} />
<InvitationsView path={siteRoot + 'invitations/'} />
<FilesActivities path={siteRoot + 'dashboard'} />
<MyFileActivities path={siteRoot + 'my-activities'} />
<GroupView path={siteRoot + 'group/:groupID'} />
<LinkedDevices path={siteRoot + 'linked-devices'} />
<ShareAdminLibraries path={siteRoot + 'share-admin-libs'} />
<ShareAdminFolders path={siteRoot + 'share-admin-folders'} />
<SharedLibraries path={siteRoot + 'shared-libs'} />
<ShareWithOCM path={siteRoot + 'shared-with-ocm'} />
<OCMViaWebdav path={siteRoot + 'ocm-via-webdav'} />
<OCMRepoDir
path={siteRoot + 'remote-library/:providerID/:repoID/*'}
pathPrefix={this.state.pathPrefix}
onTabNavClick={this.tabItemClick}
/>
<LibContentView
path={siteRoot + 'library/:repoID/*'}
pathPrefix={this.state.pathPrefix}
isSidePanelFolded={isSidePanelFolded}
onTabNavClick={this.tabItemClick}
eventBus={this.eventBus}
resetTitle={this.resetTitle}
/>
</Router>
<DndProvider backend={HTML5Backend}>
<Router className="reach-router">
<Libraries path={siteRoot} />
<Libraries path={siteRoot + 'libraries'} />
<MyLibraries path={siteRoot + 'my-libs'} />
<MyLibDeleted path={siteRoot + 'my-libs/deleted/'} />
<ShareAdminShareLinks path={siteRoot + 'share-admin-share-links'} />
<ShareAdminUploadLinks path={siteRoot + 'share-admin-upload-links'} />
<SharedWithAll path={siteRoot + 'org/'} />
<Wikis
path={siteRoot + 'published'}
sidePanelRate={sidePanelRate}
isSidePanelFolded={isSidePanelFolded}
/>
<Starred path={siteRoot + 'starred'} />
<InvitationsView path={siteRoot + 'invitations/'} />
<FilesActivities path={siteRoot + 'dashboard'} />
<MyFileActivities path={siteRoot + 'my-activities'} />
<GroupView path={siteRoot + 'group/:groupID'} />
<LinkedDevices path={siteRoot + 'linked-devices'} />
<ShareAdminLibraries path={siteRoot + 'share-admin-libs'} />
<ShareAdminFolders path={siteRoot + 'share-admin-folders'} />
<SharedLibraries path={siteRoot + 'shared-libs'} />
<ShareWithOCM path={siteRoot + 'shared-with-ocm'} />
<OCMViaWebdav path={siteRoot + 'ocm-via-webdav'} />
<OCMRepoDir
path={siteRoot + 'remote-library/:providerID/:repoID/*'}
pathPrefix={this.state.pathPrefix}
onTabNavClick={this.tabItemClick}
/>
<LibContentView
path={siteRoot + 'library/:repoID/*'}
pathPrefix={this.state.pathPrefix}
isSidePanelFolded={isSidePanelFolded}
onTabNavClick={this.tabItemClick}
eventBus={this.eventBus}
resetTitle={this.resetTitle}
/>
</Router>
</DndProvider>
</div>
<MediaQuery query="(max-width: 767.8px)">
<Modal zIndex="1030" isOpen={!isSidePanelClosed} toggle={this.toggleSidePanel} contentClassName="d-none"></Modal>

View File

@ -1,7 +1,7 @@
import React, { Fragment, useCallback, useMemo } from 'react';
import React, { Fragment, useCallback, useMemo, useRef } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { DragSource, DropTarget } from 'react-dnd';
import { useDrag, useDrop } from 'react-dnd';
import CustomizeSelect from '../../../../../components/customize-select';
import Icon from '../../../../../components/icon';
import { gettext } from '../../../../../utils/constants';
@ -9,49 +9,6 @@ import { getColumnByKey } from '../../../../utils/column';
import { COLUMNS_ICON_CONFIG, SORT_TYPE, SORT_COLUMN_OPTIONS } from '../../../../constants';
import { getGroupbyGranularityByColumn, isShowGroupCountType, getSelectedCountType, getDefaultCountType } from '../../../../utils/group';
const dragSource = {
beginDrag: props => {
return { idx: props.index, data: props.groupby, mode: 'sfMetadataGroupbyItem' };
},
endDrag(props, monitor) {
const groupSource = monitor.getItem();
const didDrop = monitor.didDrop();
let groupTarget = {};
if (!didDrop) {
return { groupSource, groupTarget };
}
},
isDragging(props) {
const { index, dragged } = props;
const { idx } = dragged;
return idx > index;
}
};
const dropTarget = {
drop(props, monitor) {
const groupSource = monitor.getItem();
const { index: targetIdx } = props;
if (targetIdx !== groupSource.idx) {
let groupTarget = { idx: targetIdx, data: props.groupby };
props.onMove(groupSource, groupTarget);
}
}
};
const dragCollect = (connect, monitor) => ({
connectDragSource: connect.dragSource(),
connectDragPreview: connect.dragPreview(),
isDragging: monitor.isDragging(),
});
const dropCollect = (connect, monitor) => ({
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver(),
canDrop: monitor.canDrop(),
dragged: monitor.getItem(),
});
/*
groupby: {
column_key: 'xxx',
@ -59,10 +16,39 @@ const dropCollect = (connect, monitor) => ({
sort_type: 'xxx',
}
*/
const GroupbyItem = ({
isOver, isDragging, canDrop, connectDragSource, connectDragPreview, connectDropTarget,
showDragBtn, index, readOnly, groupby, columns, onDelete, onUpdate
}) => {
const GroupbyItem = ({ showDragBtn, index, readOnly, groupby, columns, onDelete, onUpdate, onMove }) => {
const ref = useRef(null);
// drag and drop
const [{ isDragging }, drag] = useDrag({
type: 'sfMetadataGroupbyItem',
item: () => ({
idx: index,
data: groupby,
}),
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
});
const [{ isOver, canDrop }, drop] = useDrop({
accept: 'sfMetadataGroupbyItem',
hover: (item) => {
if (item.idx !== index) {
onMove(
{ idx: item.idx, data: item.data },
{ idx: index, data: groupby }
);
item.idx = index;
}
},
collect: (monitor) => ({
isOver: monitor.isOver(),
canDrop: monitor.canDrop(),
})
});
const dragDropRef = drag(drop(ref));
const column = useMemo(() => {
return getColumnByKey(columns, groupby.column_key);
}, [groupby, columns]);
@ -165,59 +151,58 @@ const GroupbyItem = ({
onUpdate(newGroupby, index);
}, [groupby, index, onUpdate]);
return connectDropTarget(
connectDragPreview(
<div
className={classnames('groupby-item',
{ 'group-can-drop-top': isOver && canDrop && isDragging },
{ 'group-can-drop': isOver && canDrop && !isDragging }
)}
>
{!readOnly && (
<div className="delete-groupby" onClick={deleteGroupby} aria-label={gettext('Delete')}>
<Icon className="sf-metadata-icon" symbol="fork-number"/>
</div>
)}
<div className="condition">
<div className="groupby-column">
return (
<div
ref={dragDropRef}
className={classnames('groupby-item',
{ 'group-can-drop-top': isOver && canDrop && isDragging },
{ 'group-can-drop': isOver && canDrop && !isDragging }
)}
>
{!readOnly && (
<div className="delete-groupby" onClick={deleteGroupby} aria-label={gettext('Delete')}>
<Icon className="sf-metadata-icon" symbol="fork-number"/>
</div>
)}
<div className="condition">
<div className="groupby-column">
<CustomizeSelect
readOnly={readOnly}
value={selectedColumn}
options={columnsOptions}
onSelectOption={selectColumn}
searchable={true}
searchPlaceholder={gettext('Search property')}
noOptionsPlaceholder={gettext('No results')}
/>
</div>
{isShowGroupCountType(column) && (
<div className="groupby-count-type">
<CustomizeSelect
readOnly={readOnly}
value={selectedColumn}
options={columnsOptions}
onSelectOption={selectColumn}
searchable={true}
searchPlaceholder={gettext('Search property')}
noOptionsPlaceholder={gettext('No results')}
value={selectedCountType}
onSelectOption={selectCountType}
options={countTypeOptions}
/>
</div>
{isShowGroupCountType(column) && (
<div className="groupby-count-type">
<CustomizeSelect
readOnly={readOnly}
value={selectedCountType}
onSelectOption={selectCountType}
options={countTypeOptions}
/>
</div>
)}
<div className="groupby-predicate">
{(!column.key || SORT_COLUMN_OPTIONS.includes(column.type)) && (
<CustomizeSelect
readOnly={readOnly}
value={selectedSortType}
options={sortOptions}
onSelectOption={selectSortType}
/>
)}
</div>
</div>
{!readOnly && showDragBtn && connectDragSource(
<div className="groupby-drag">
<Icon symbol="drag" />
</div>
)}
<div className="groupby-predicate">
{(!column.key || SORT_COLUMN_OPTIONS.includes(column.type)) && (
<CustomizeSelect
readOnly={readOnly}
value={selectedSortType}
options={sortOptions}
onSelectOption={selectSortType}
/>
)}
</div>
</div>
)
{!readOnly && showDragBtn && (
<div className="groupby-drag">
<Icon symbol="drag" />
</div>
)}
</div>
);
};
@ -229,16 +214,7 @@ GroupbyItem.propTypes = {
columns: PropTypes.array,
onDelete: PropTypes.func,
onUpdate: PropTypes.func,
// drag
isDragging: PropTypes.bool,
isOver: PropTypes.bool,
canDrop: PropTypes.bool,
connectDropTarget: PropTypes.func,
connectDragSource: PropTypes.func,
connectDragPreview: PropTypes.func,
onMove: PropTypes.func,
};
export default DropTarget('sfMetadataGroupbyItem', dropTarget, dropCollect)(
DragSource('sfMetadataGroupbyItem', dragSource, dragCollect)(GroupbyItem)
);
export default GroupbyItem;

View File

@ -1,8 +1,7 @@
import React, { useMemo } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { DropTarget } from 'react-dnd';
import html5DragDropContext from '../../../../../pages/wiki2/wiki-nav/html5DragDropContext';
import { useDrop } from 'react-dnd';
import GroupbyItem from './groupby-item';
import { gettext } from '../../../../../utils/constants';
@ -17,8 +16,20 @@ const Groupbys = ({ readOnly, groupbys, columns, onDelete, onUpdate, onMove }) =
return groupbys.length > 1;
}, [readOnly, groupbys]);
const [, drop] = useDrop({
accept: 'sfMetadataGroupbyItem',
drop: (item, monitor) => {
if (!monitor.didDrop()) {
onMove(item, { idx: groupbys.length });
}
},
collect: monitor => ({
isOver: monitor.isOver(),
}),
});
return (
<div className={classnames('groupbys-list', { 'empty-groupbys-container': isEmpty })}>
<div ref={drop} className={classnames('groupbys-list', { 'empty-groupbys-container': isEmpty })}>
{isEmpty && <div className="empty-groupbys-list">{gettext('No groupings applied to this view.')}</div>}
{!isEmpty && groupbys.map((groupby, index) => {
return (
@ -47,8 +58,4 @@ Groupbys.propTypes = {
onMove: PropTypes.func,
};
const DndGroupbysContainer = DropTarget('sfMetadataGroupbyItem', {}, connect => ({
connectDropTarget: connect.dropTarget()
}))(Groupbys);
export default html5DragDropContext(DndGroupbysContainer);
export default Groupbys;

View File

@ -1,6 +1,6 @@
import React, { useCallback } from 'react';
import PropTypes from 'prop-types';
import { DragSource, DropTarget } from 'react-dnd';
import { useDrag, useDrop } from 'react-dnd';
import classnames from 'classnames';
import Icon from '../../../../../components/icon';
import IconBtn from '../../../../../components/icon-btn';
@ -9,56 +9,73 @@ import Name from './name';
import './index.css';
const dragSource = {
beginDrag: props => {
return { idx: props.index, data: props.option, mode: 'sfMetadataSingleSelectOption' };
},
endDrag(props, monitor) {
const optionSource = monitor.getItem();
const didDrop = monitor.didDrop();
let optionTarget = {};
if (!didDrop) {
return { optionSource, optionTarget };
}
},
isDragging(props, monitor) {
const { index, dragged } = props;
const { idx } = dragged;
return idx > index;
}
};
// const dragSource = {
// beginDrag: props => {
// return { idx: props.index, data: props.option, mode: 'sfMetadataSingleSelectOption' };
// },
// endDrag(props, monitor) {
// const optionSource = monitor.getItem();
// const didDrop = monitor.didDrop();
// let optionTarget = {};
// if (!didDrop) {
// return { optionSource, optionTarget };
// }
// },
// isDragging(props, monitor) {
// const { index, dragged } = props;
// const { idx } = dragged;
// return idx > index;
// }
// };
const dragCollect = (connect, monitor) => ({
connectDragSource: connect.dragSource(),
connectDragPreview: connect.dragPreview(),
isDragging: monitor.isDragging()
});
// const dragCollect = (connect, monitor) => ({
// connectDragSource: connect.dragSource(),
// connectDragPreview: connect.dragPreview(),
// isDragging: monitor.isDragging()
// });
const dropTarget = {
drop(props, monitor) {
const optionSource = monitor.getItem();
const { index: targetIdx } = props;
if (targetIdx !== optionSource.idx) {
const optionTarget = { idx: targetIdx, data: props.option };
props.onMove(optionSource, optionTarget);
}
}
};
// const dropTarget = {
// drop(props, monitor) {
// const optionSource = monitor.getItem();
// const { index: targetIdx } = props;
// if (targetIdx !== optionSource.idx) {
// const optionTarget = { idx: targetIdx, data: props.option };
// props.onMove(optionSource, optionTarget);
// }
// }
// };
const dropCollect = (connect, monitor) => ({
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver(),
canDrop: monitor.canDrop(),
dragged: monitor.getItem()
});
// const dropCollect = (connect, monitor) => ({
// connectDropTarget: connect.dropTarget(),
// isOver: monitor.isOver(),
// canDrop: monitor.canDrop(),
// dragged: monitor.getItem()
// });
const Option = ({
isOver, isDragging, canDrop, connectDragSource, connectDragPreview, connectDropTarget,
isViewing, isDeleting, isEditing, isPredefined,
option,
onDelete: propsDelete, onUpdate,
onMouseLeave, onMouseEnter: propsMouseEnter, onToggleFreeze, onOpenNameEditor, onCloseNameEditor,
}) => {
const [{ isDragging }, drag] = useDrag({
type: 'sfMetadataSingleSelectOption',
item: () => ({
idx: option.id,
data: option,
}),
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
});
const [{ isOver, canDrop }, drop] = useDrop({
accept: 'sfMetadataSingleSelectOption',
collect: (monitor) => ({
isOver: monitor.isOver(),
canDrop: monitor.canDrop(),
})
});
const onDelete = useCallback((event) => {
event.nativeEvent.stopImmediatePropagation();
@ -69,44 +86,41 @@ const Option = ({
propsMouseEnter(option.id);
}, [option, propsMouseEnter]);
return connectDropTarget(
connectDragPreview(
<div
className={classnames('sf-metadata-edit-option-container', {
'sf-metadata-edit-option-can-drop': isOver && canDrop && !isDragging,
'sf-metadata-edit-deleting-option': isDeleting,
'sf-metadata-edit-option-can-drop-top': isOver && canDrop && isDragging,
'sf-metadata-edit-option-viewing': isViewing,
'sf-metadata-edit-option-editing': isEditing,
'sf-metadata-edit-option-disabled': isPredefined,
})}
onMouseEnter={() => onMouseEnter()}
onMouseLeave={onMouseLeave}
>
{connectDragSource(
<div className="sf-metadata-edit-option-drag-container">
<Icon symbol="drag" />
</div>
)}
<div className="sf-metadata-edit-option-content">
<Color option={option} onChange={onUpdate} isViewing={isViewing} isPredefined={isPredefined} />
<Name
option={option}
isPredefined={isPredefined}
isEditing={isEditing}
onChange={onUpdate}
onToggleFreeze={onToggleFreeze}
onOpen={onOpenNameEditor}
onClose={onCloseNameEditor}
/>
</div>
<div id={`sf-metadata-edit-option-more-operation-${option.id}`} className="sf-metadata-edit-option-more-operations">
{(isViewing || isDeleting) && (
<IconBtn className="sf-metadata-edit-option-operation-item" onClick={onDelete} symbol="delete" />
)}
</div>
return (
<div
ref={(node) => drag(drop(node))}
className={classnames('sf-metadata-edit-option-container', {
'sf-metadata-edit-option-can-drop': isOver && canDrop && !isDragging,
'sf-metadata-edit-deleting-option': isDeleting,
'sf-metadata-edit-option-can-drop-top': isOver && canDrop && isDragging,
'sf-metadata-edit-option-viewing': isViewing,
'sf-metadata-edit-option-editing': isEditing,
'sf-metadata-edit-option-disabled': isPredefined,
})}
onMouseEnter={() => onMouseEnter()}
onMouseLeave={onMouseLeave}
>
<div className="sf-metadata-edit-option-drag-container">
<Icon symbol="drag" />
</div>
)
<div className="sf-metadata-edit-option-content">
<Color option={option} onChange={onUpdate} isViewing={isViewing} isPredefined={isPredefined} />
<Name
option={option}
isPredefined={isPredefined}
isEditing={isEditing}
onChange={onUpdate}
onToggleFreeze={onToggleFreeze}
onOpen={onOpenNameEditor}
onClose={onCloseNameEditor}
/>
</div>
<div id={`sf-metadata-edit-option-more-operation-${option.id}`} className="sf-metadata-edit-option-more-operations">
{(isViewing || isDeleting) && (
<IconBtn className="sf-metadata-edit-option-operation-item" onClick={onDelete} symbol="delete" />
)}
</div>
</div>
);
};
@ -127,15 +141,13 @@ Option.propTypes = {
onOpenNameEditor: PropTypes.func.isRequired,
onCloseNameEditor: PropTypes.func.isRequired,
// drag
isOver: PropTypes.bool,
canDrop: PropTypes.bool,
dragged: PropTypes.object,
connectDragSource: PropTypes.func.isRequired,
connectDropTarget: PropTypes.func.isRequired,
connectDragPreview: PropTypes.func.isRequired,
// // drag
// isOver: PropTypes.bool,
// canDrop: PropTypes.bool,
// dragged: PropTypes.object,
// connectDragSource: PropTypes.func.isRequired,
// connectDropTarget: PropTypes.func.isRequired,
// connectDragPreview: PropTypes.func.isRequired,
};
export default DropTarget('sfMetadataSingleSelectOption', dropTarget, dropCollect)(
DragSource('sfMetadataSingleSelectOption', dragSource, dragCollect)(Option)
);
export default Option;

View File

@ -1,7 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
import { DropTarget } from 'react-dnd';
import html5DragDropContext from '../../../../pages/wiki2/wiki-nav/html5DragDropContext';
const OptionsContainer = ({ inputRef, options }) => {
if (!Array.isArray(options) || options.length === 0) return null;
@ -17,8 +15,4 @@ OptionsContainer.propTypes = {
options: PropTypes.array
};
const DndOptionsContainer = DropTarget('sfMetadataSingleSelectOption', {}, connect => ({
connectDropTarget: connect.dropTarget()
}))(OptionsContainer);
export default html5DragDropContext(DndOptionsContainer);
export default OptionsContainer;

View File

@ -1,4 +1,4 @@
import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
// import { DragDropContext } from 'react-dnd';
// import HTML5Backend from 'react-dnd-html5-backend';
export default DragDropContext(HTML5Backend);
// export default DragDropContext(HTML5Backend);

View File

@ -1,4 +1,4 @@
import { DragSource, DropTarget } from 'react-dnd';
import { useDrag, useDrop } from 'react-dnd';
import PageItem from './page-item';
import wikiAPI from '../../../../utils/wiki-api';
import { wikiId, gettext } from '../../../../utils/constants';
@ -77,6 +77,4 @@ const dropCollect = (connect, monitor) => ({
draggedPage: monitor.getItem()
});
export default DropTarget('WikiNav', dropTarget, dropCollect)(
DragSource('WikiNav', dragSource, dragCollect)(PageItem)
);
export default PageItem;

View File

@ -2,8 +2,7 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { UncontrolledTooltip } from 'reactstrap';
import { DropTarget, DragLayer } from 'react-dnd';
import html5DragDropContext from './html5DragDropContext';
import { useDragLayer, useDrop } from 'react-dnd';
import DraggedPageItem from './pages/dragged-page-item';
import { gettext, wikiPermission } from '../../../utils/constants';
import { Utils } from '../../../utils/utils';
@ -158,14 +157,14 @@ class WikiNav extends Component {
};
render() {
const StructureBody = html5DragDropContext(
DropTarget('WikiNav', {}, connect => ({
connectDropTarget: connect.dropTarget()
}))(DragLayer(this.collect)(this.renderStructureBody))
);
// const StructureBody = html5DragDropContext(
// DropTarget('WikiNav', {}, connect => ({
// connectDropTarget: connect.dropTarget()
// }))(DragLayer(this.collect)(this.renderStructureBody))
// );
return (
<div className='wiki-nav'>
<StructureBody />
{this.renderStructureBody()}
</div>
);
}