diff --git a/frontend/src/components/dir-view-mode/dir-column-nav.js b/frontend/src/components/dir-view-mode/dir-column-nav.js index 845b4df570..d952464176 100644 --- a/frontend/src/components/dir-view-mode/dir-column-nav.js +++ b/frontend/src/components/dir-view-mode/dir-column-nav.js @@ -33,6 +33,7 @@ const propTypes = { onItemMove: PropTypes.func.isRequired, onItemCopy: PropTypes.func.isRequired, selectedDirentList: PropTypes.array.isRequired, + onItemsMove: PropTypes.func.isRequired, }; class DirColumnNav extends React.Component { @@ -276,6 +277,7 @@ class DirColumnNav extends React.Component { onItemMove={this.props.onItemMove} currentRepoInfo={this.props.currentRepoInfo} selectedDirentList={this.props.selectedDirentList} + onItemsMove={this.props.onItemsMove} />) } diff --git a/frontend/src/components/dir-view-mode/dir-column-view.js b/frontend/src/components/dir-view-mode/dir-column-view.js index 12ef40d4ef..65fa1c7017 100644 --- a/frontend/src/components/dir-view-mode/dir-column-view.js +++ b/frontend/src/components/dir-view-mode/dir-column-view.js @@ -171,6 +171,7 @@ class DirColumnView extends React.Component { onItemMove={this.props.onItemMove} onItemCopy={this.props.onItemCopy} selectedDirentList={this.props.selectedDirentList} + onItemsMove={this.props.onItemsMove} />
diff --git a/frontend/src/components/dirent-list-view/dirent-list-item.js b/frontend/src/components/dirent-list-view/dirent-list-item.js index 59338ef9d8..c34917042f 100644 --- a/frontend/src/components/dirent-list-view/dirent-list-item.js +++ b/frontend/src/components/dirent-list-view/dirent-list-item.js @@ -49,6 +49,7 @@ const propTypes = { onFileTagChanged: PropTypes.func, enableDirPrivateShare: PropTypes.bool.isRequired, showDirentDetail: PropTypes.func.isRequired, + onItemsMove: PropTypes.func.isRequired, }; class DirentListItem extends React.Component { @@ -349,15 +350,31 @@ class DirentListItem extends React.Component { if (Utils.isIEBrower()) { return false; } - let nodeRootPath = ''; - nodeRootPath = this.props.path === '/' ? `${this.props.path}${this.props.dirent.name}` : `${this.props.path}/${this.props.dirent.name}`; - let dragStartItemData = {nodeDirent: this.props.dirent, nodeParentPath: this.props.path, nodeRootPath: nodeRootPath}; - dragStartItemData = JSON.stringify(dragStartItemData); e.dataTransfer.effectAllowed = 'move'; if (e.dataTransfer && e.dataTransfer.setDragImage) { e.dataTransfer.setDragImage(this.refs.drag_icon, 15, 15); } + + let { selectedDirentList } = this.props; + let selectedList = []; + if (selectedDirentList.length > 0 && selectedDirentList.includes(this.props.dirent)) { // drag items and selectedDirentList include item + selectedDirentList.map(item => { + let nodeRootPath = ''; + nodeRootPath = this.props.path === '/' ? `${this.props.path}${item.name}` : `${this.props.path}/${item.name}`; + let dragStartItemData = {nodeDirent: item, nodeParentPath: this.props.path, nodeRootPath: nodeRootPath}; + return selectedList.push(dragStartItemData) + }) + selectedList = JSON.stringify(selectedList); + e.dataTransfer.setData('applicaiton/drag-item-info', selectedList); + return ; + } + + let nodeRootPath = ''; + nodeRootPath = this.props.path === '/' ? `${this.props.path}${this.props.dirent.name}` : `${this.props.path}/${this.props.dirent.name}`; + let dragStartItemData = {nodeDirent: this.props.dirent, nodeParentPath: this.props.path, nodeRootPath: nodeRootPath}; + dragStartItemData = JSON.stringify(dragStartItemData); + e.dataTransfer.setData('applicaiton/drag-item-info', dragStartItemData); } @@ -395,6 +412,23 @@ class DirentListItem extends React.Component { } let dragStartItemData = e.dataTransfer.getData('applicaiton/drag-item-info'); dragStartItemData = JSON.parse(dragStartItemData); + if (Array.isArray(dragStartItemData)) { //move items + let direntPaths = []; + dragStartItemData.forEach(dirent => { + let path = Utils.joinPath(this.props.path, dirent.nodeDirent.name); + direntPaths.push(path); + }); + + let selectedPath = Utils.joinPath(this.props.path, this.props.dirent.name); + + if (direntPaths.some(direntPath => { return direntPath === selectedPath;})) { //eg; A/B, A/C --> A/B + return; + } + + this.props.onItemsMove(this.props.currentRepoInfo, selectedPath); + return ; + } + let {nodeDirent, nodeParentPath, nodeRootPath} = dragStartItemData; let dropItemData = this.props.dirent; diff --git a/frontend/src/components/dirent-list-view/dirent-list-view.js b/frontend/src/components/dirent-list-view/dirent-list-view.js index a032e38998..dcb35eb2b6 100644 --- a/frontend/src/components/dirent-list-view/dirent-list-view.js +++ b/frontend/src/components/dirent-list-view/dirent-list-view.js @@ -577,6 +577,10 @@ class DirentListView extends React.Component { let {nodeDirent, nodeParentPath, nodeRootPath} = dragStartItemData; if (e.target.className === 'table-container table-drop-active') { + if (Array.isArray(dragStartItemData)) { + return; + } + if (nodeRootPath === this.props.path || nodeParentPath === this.props.path) { return; } @@ -664,6 +668,7 @@ class DirentListView extends React.Component { onFileTagChanged={this.props.onFileTagChanged} getDirentItemMenuList={this.getDirentItemMenuList} showDirentDetail={this.props.showDirentDetail} + onItemsMove={this.props.onItemsMove} /> ); })} diff --git a/frontend/src/components/tree-view/tree-view.js b/frontend/src/components/tree-view/tree-view.js index c3560ed5bc..48304b2c2a 100644 --- a/frontend/src/components/tree-view/tree-view.js +++ b/frontend/src/components/tree-view/tree-view.js @@ -18,6 +18,7 @@ const propTypes = { onItemMove: PropTypes.func, currentRepoInfo: PropTypes.object, selectedDirentList: PropTypes.array, + onItemsMove: PropTypes.func, }; const PADDING_LEFT = 20; @@ -91,6 +92,20 @@ class TreeView extends React.Component { let {nodeDirent, nodeParentPath, nodeRootPath} = dragStartNodeData; let dropNodeData = node; + if (Array.isArray(dragStartNodeData)) { //move items + if (!dropNodeData) { //move items to root + if (dragStartNodeData[0].nodeParentPath === '/') { + this.setState({isTreeViewDropTipShow: false}); + return; + } + this.props.onItemsMove(this.props.currentRepoInfo, '/'); + this.setState({isTreeViewDropTipShow: false}); + return ; + } + this.onMoveItems(dragStartNodeData, dropNodeData, this.props.currentRepoInfo, node.path); + return ; + } + if (!dropNodeData) { if (nodeParentPath === '/') { this.setState({isTreeViewDropTipShow: false}); @@ -128,6 +143,39 @@ class TreeView extends React.Component { this.onItemMove(this.props.currentRepoInfo, nodeDirent, dropNodeData.path, nodeParentPath); } + onMoveItems = (dragStartNodeData, dropNodeData, destRepo, destDirentPath) => { + let direntPaths = []; + dragStartNodeData.forEach(dirent => { + let path = dirent.nodeRootPath; + direntPaths.push(path); + }); + + if (dropNodeData.object.type !== 'dir') { + return; + } + + // move dirents to one of them. eg: A/B, A/C -> A/B + if (direntPaths.some(direntPath => { return direntPath === destDirentPath;})) { + return; + } + + // move dirents to one of their child. eg: A/B, A/D -> A/B/C + let isChildPath = direntPaths.some(direntPath => { + let flag = destDirentPath.length > direntPath.length && destDirentPath.indexOf(direntPath) > -1; + return flag; + }); + if (isChildPath) { + return; + } + + if (!dropNodeData) { //selectPath === '/' + this.setState({isTreeViewDropTipShow: false}); + return; + } + + this.props.onItemsMove(destRepo, destDirentPath); + } + freezeItem = () => { this.setState({isItemFreezed: true}); }