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});
}