1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-26 07:22:34 +00:00

Move file by drag and drop (#3168)

This commit is contained in:
zxj96
2019-03-27 11:25:27 +08:00
committed by Daniel Pan
parent d6470889c9
commit 4a9cfe8a46
19 changed files with 5503 additions and 2272 deletions

View File

@@ -280,6 +280,8 @@ class DirColumnNav extends React.Component {
onMenuItemClick={this.onMenuItemClick}
onFreezedItem={this.onFreezedItem}
onUnFreezedItem={this.onUnFreezedItem}
onItemMove={this.props.onItemMove}
currentRepoInfo={this.props.currentRepoInfo}
/>)
}
</div>

View File

@@ -55,6 +55,8 @@ class DirentListItem extends React.Component {
isShareDialogShow: false,
isMutipleOperation: false,
isShowTagTooltip: false,
isDragTipShow: false,
isDropTipshow: false,
};
this.zipToken = null;
}
@@ -67,6 +69,7 @@ class DirentListItem extends React.Component {
isOperationShow: true,
});
}
this.setState({isDragTipShow: true});
}
onMouseOver = () => {
@@ -76,6 +79,7 @@ class DirentListItem extends React.Component {
isOperationShow: true,
});
}
this.setState({isDragTipShow: true});
}
onMouseLeave = () => {
@@ -85,6 +89,7 @@ class DirentListItem extends React.Component {
isOperationShow: false,
});
}
this.setState({isDragTipShow: false});
}
onUnfreezedItem = () => {
@@ -323,6 +328,67 @@ class DirentListItem extends React.Component {
this.setState({isShowTagTooltip: !this.state.isShowTagTooltip});
}
onItemMove = (destRepo, dirent, selectedPath, currentPath) => {
this.props.onItemMove(destRepo, dirent, selectedPath, currentPath);
}
onItemDragStart = (e) => {
let nodeRootPath = '';
nodeRootPath = this.props.path === '/' ? `${this.props.path}${this.props.dirent.name}` : this.props.path;
let dragStartItemData = {nodeDirent: this.props.dirent, nodeParentPath: this.props.path, nodeRootPath: nodeRootPath};
dragStartItemData = JSON.stringify(dragStartItemData);
e.dataTransfer.effectAllowed = "move";
e.dataTransfer.setDragImage(this.refs.drag_icon, 15, 15);
e.dataTransfer.setData('applicaiton/drag-item-info', dragStartItemData);
}
onItemDragEnter = () => {
if (this.props.dirent.type === 'dir') {
this.setState({isDropTipshow: true});
}
}
onItemDragOver = (e) => {
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
}
onItemDragLeave = () => {
this.setState({isDropTipshow: false});
}
onItemDragDrop = (e) => {
this.setState({isDropTipshow: false});
if (e.dataTransfer.files.length) { // uploaded files
return;
}
let dragStartItemData = e.dataTransfer.getData('applicaiton/drag-item-info');
dragStartItemData = JSON.parse(dragStartItemData);
let {nodeDirent, nodeParentPath, nodeRootPath} = dragStartItemData;
let dropItemData = this.props.dirent;
if (nodeDirent.name === dropItemData.name) {
return;
}
if (dropItemData.type !== 'dir') {
return;
}
// copy the dirent to it's child. eg: A/B -> A/B/C
if (dropItemData.type === 'dir' && nodeDirent.type === 'dir') {
if (nodeParentPath !== this.props.path) {
if (this.props.path.indexOf(nodeRootPath) !== -1) {
return;
}
}
}
let selectedPath = Utils.joinPath(this.props.path, this.props.dirent.name);
this.onItemMove(this.props.currentRepoInfo, nodeDirent, selectedPath, nodeParentPath);
}
render() {
let { path, dirent } = this.props;
let direntPath = Utils.joinPath(path, dirent.name);
@@ -351,7 +417,7 @@ class DirentListItem extends React.Component {
return (
<Fragment>
<tr className={this.state.highlight ? 'tr-highlight' : ''} onMouseEnter={this.onMouseEnter} onMouseOver={this.onMouseOver} onMouseLeave={this.onMouseLeave} onClick={this.onDirentClick}>
<tr className={`${this.state.isDropTipshow ? 'tr-dragenter' : ''} ${this.state.isDragTipShow ? 'tr-style-nav' : ''} ${this.state.highlight ? 'tr-highlight' : ''}`} draggable="true" onMouseEnter={this.onMouseEnter} onMouseOver={this.onMouseOver} onMouseLeave={this.onMouseLeave} onClick={this.onDirentClick} onDragStart={this.onItemDragStart} onDragEnter={this.onItemDragEnter} onDragOver={this.onItemDragOver} onDragLeave={this.onItemDragLeave} onDrop={this.onItemDragDrop}>
<td className="text-center">
<input type="checkbox" className="vam" onChange={this.onItemSelected} checked={dirent.isSelected}/>
</td>
@@ -362,8 +428,8 @@ class DirentListItem extends React.Component {
<td className="text-center">
<div className="dir-icon">
{dirent.encoded_thumbnail_src ?
<img src={`${siteRoot}${dirent.encoded_thumbnail_src}`} className="thumbnail cursor-pointer" onClick={this.onItemClick} alt="" /> :
<img src={iconUrl} width="24" alt='' />
<img ref='drag_icon' src={`${siteRoot}${dirent.encoded_thumbnail_src}`} className="thumbnail cursor-pointer" onClick={this.onItemClick} alt="" /> :
<img ref='drag_icon' src={iconUrl} width="24" alt='' />
}
{dirent.is_locked && <img className="locked" src={mediaUrl + 'img/file-locked-32.png'} alt={gettext('locked')} title={dirent.lock_owner_name}/>}
</div>

View File

@@ -19,6 +19,8 @@ const propTypes = {
onMenuItemClick: PropTypes.func,
registerHandlers: PropTypes.func,
unregisterHandlers: PropTypes.func,
onNodeDragMove: PropTypes.func,
onNodeDrop: PropTypes.func,
};
class TreeNodeView extends React.Component {
@@ -27,7 +29,8 @@ class TreeNodeView extends React.Component {
super(props);
this.state = {
isHighlight: false,
isShowOperationMenu: false
isShowOperationMenu: false,
isNodeDropShow: false,
};
}
@@ -68,6 +71,27 @@ class TreeNodeView extends React.Component {
this.props.onNodeDragStart(e, this.props.node);
}
onNodeDragEnter = (e) => {
if (this.props.node.object.type === 'dir') {
this.setState({isNodeDropShow: true});
}
this.props.onNodeDragEnter(e, this.props.node);
}
onNodeDragMove = (e) => {
this.props.onNodeDragMove(e);
}
onNodeDragLeave = (e) => {
this.setState({isNodeDropShow: false});
this.props.onNodeDragLeave(e, this.props.node);
}
onNodeDrop = (e) => {
this.setState({isNodeDropShow: false});
this.props.onNodeDrop(e, this.props.node);
}
onUnFreezedItem = () => {
this.setState({isShowOperationMenu: false});
this.props.onUnFreezedItem();
@@ -134,6 +158,11 @@ class TreeNodeView extends React.Component {
onNodeChanged={this.props.onNodeChanged}
registerHandlers={this.props.registerHandlers}
unregisterHandlers={this.props.unregisterHandlers}
onNodeDragStart={this.props.onNodeDragStart}
onNodeDragMove={this.props.onNodeDragMove}
onNodeDrop={this.props.onNodeDrop}
onNodeDragEnter={this.props.onNodeDragEnter}
onNodeDragLeave={this.props.onNodeDragLeave}
/>
);
})}
@@ -152,8 +181,8 @@ class TreeNodeView extends React.Component {
<div className="tree-node">
<div type={type} title={node.object.name}
onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}
className={`tree-node-inner text-nowrap ${hlClass} ${node.path === '/'? 'hide': ''}`}>
<div className="tree-node-text" draggable="true" onDragStart={this.onNodeDragStart} onClick={this.onNodeClick}>{node.object.name}</div>
className={`tree-node-inner text-nowrap ${hlClass} ${node.path === '/'? 'hide': ''} ${this.state.isNodeDropShow ? 'tree-node-drop' : ''}`}>
<div className="tree-node-text" draggable="true" onDragStart={this.onNodeDragStart} onClick={this.onNodeClick} onDragEnter={this.onNodeDragEnter} onDragLeave={this.onNodeDragLeave} onDragOver={this.onNodeDragMove} onDrop={this.onNodeDrop}>{node.object.name}</div>
<div className="left-icon">
{type === 'dir' && (!node.isLoaded || (node.isLoaded && node.hasChildren())) && (
<i

View File

@@ -13,6 +13,8 @@ const propTypes = {
onNodeClick: PropTypes.func.isRequired,
onNodeExpanded: PropTypes.func.isRequired,
onNodeCollapse: PropTypes.func.isRequired,
onItemMove: PropTypes.func,
currentRepoInfo: PropTypes.object,
};
const PADDING_LEFT = 20;
@@ -38,8 +40,62 @@ class TreeView extends React.Component {
this.unregisterHandlers();
}
onItemMove = (repo, dirent, selectedPath, currentPath) => {
this.props.onItemMove(repo, dirent, selectedPath, currentPath);
}
onNodeDragStart = (e, node) => {
// todo
let dragStartNodeData = {nodeDirent: node.object, nodeParentPath: node.parentNode.path, nodeRootPath: node.path};
dragStartNodeData = JSON.stringify(dragStartNodeData);
e.dataTransfer.effectAllowed = "move";
e.dataTransfer.setData('applicaiton/drag-item-info', dragStartNodeData);
}
onNodeDragEnter = (e, node) => {
//todo
}
onNodeDragMove = (e) => {
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
}
onNodeDragLeave = (e, node) => {
//todo
}
onNodeDrop = (e, node) => {
if (e.dataTransfer.files.length) { // uploaded files
return;
}
let dragStartNodeData = e.dataTransfer.getData('applicaiton/drag-item-info');
dragStartNodeData = JSON.parse(dragStartNodeData);
let {nodeDirent, nodeParentPath, nodeRootPath} = dragStartNodeData;
let dropNodeData = node;
if (dropNodeData.object.type !== 'dir') {
return;
}
// copy the dirent to itself. eg: A/B -> A/B
if (nodeParentPath === dropNodeData.parentNode.path) {
if (dropNodeData.object.name === nodeDirent.name) {
return;
}
}
// copy the dirent to it's child. eg: A/B -> A/B/C
if (dropNodeData.object.type === 'dir' && nodeDirent.type === 'dir') {
if (dropNodeData.parentNode.path !== nodeParentPath) {
if (dropNodeData.path.indexOf(nodeRootPath) !== -1) {
return;
}
}
}
this.onItemMove(this.props.currentRepoInfo, nodeDirent, dropNodeData.path, nodeParentPath);
}
onFreezedItem = () => {
@@ -110,6 +166,10 @@ class TreeView extends React.Component {
onNodeChanged={this.onNodeChanged}
registerHandlers={this.registerHandlers}
unregisterHandlers={this.unregisterHandlers}
onNodeDragMove={this.onNodeDragMove}
onNodeDrop={this.onNodeDrop}
onNodeDragEnter={this.onNodeDragEnter}
onNodeDragLeave={this.onNodeDragLeave}
/>
{this.state.isRightMenuShow && (
<TreeViewContextMenu