2018-08-06 10:29:12 +00:00
|
|
|
import React from 'react';
|
2018-10-16 10:19:51 +00:00
|
|
|
import PropTypes from 'prop-types';
|
2018-08-06 10:29:12 +00:00
|
|
|
import TreeNodeView from './tree-node-view';
|
|
|
|
|
2019-03-23 06:16:48 +00:00
|
|
|
import TreeViewContextMenu from './tree-view-contextmenu'
|
|
|
|
|
2018-10-16 10:19:51 +00:00
|
|
|
const propTypes = {
|
2019-02-20 03:54:25 +00:00
|
|
|
repoPermission: PropTypes.bool,
|
2019-01-28 08:48:03 +00:00
|
|
|
isNodeMenuShow: PropTypes.bool.isRequired,
|
2018-10-16 10:19:51 +00:00
|
|
|
treeData: PropTypes.object.isRequired,
|
2019-01-28 08:48:03 +00:00
|
|
|
currentPath: PropTypes.string.isRequired,
|
|
|
|
onMenuItemClick: PropTypes.func,
|
2018-10-16 10:19:51 +00:00
|
|
|
onNodeClick: PropTypes.func.isRequired,
|
2019-01-28 08:48:03 +00:00
|
|
|
onNodeExpanded: PropTypes.func.isRequired,
|
|
|
|
onNodeCollapse: PropTypes.func.isRequired,
|
2019-03-27 03:25:27 +00:00
|
|
|
onItemMove: PropTypes.func,
|
|
|
|
currentRepoInfo: PropTypes.object,
|
2018-10-16 10:19:51 +00:00
|
|
|
};
|
|
|
|
|
2019-03-04 09:45:28 +00:00
|
|
|
const PADDING_LEFT = 20;
|
2019-01-28 08:48:03 +00:00
|
|
|
|
|
|
|
class TreeView extends React.Component {
|
2018-08-06 10:29:12 +00:00
|
|
|
|
2019-01-28 08:48:03 +00:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state = {
|
|
|
|
isItemFreezed: false,
|
2019-03-23 06:16:48 +00:00
|
|
|
isRightMenuShow: false,
|
|
|
|
nodeData: null,
|
|
|
|
fileData: null,
|
|
|
|
mousePosition: {clientX: '', clientY: ''},
|
2019-01-28 08:48:03 +00:00
|
|
|
};
|
2018-08-06 10:29:12 +00:00
|
|
|
}
|
|
|
|
|
2019-03-23 06:16:48 +00:00
|
|
|
componentDidMount() {
|
|
|
|
this.registerHandlers();
|
|
|
|
}
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
|
this.unregisterHandlers();
|
|
|
|
}
|
|
|
|
|
2019-03-27 03:25:27 +00:00
|
|
|
onItemMove = (repo, dirent, selectedPath, currentPath) => {
|
|
|
|
this.props.onItemMove(repo, dirent, selectedPath, currentPath);
|
|
|
|
}
|
|
|
|
|
2019-01-28 08:48:03 +00:00
|
|
|
onNodeDragStart = (e, node) => {
|
2019-03-27 03:25:27 +00:00
|
|
|
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);
|
2018-08-06 10:29:12 +00:00
|
|
|
}
|
|
|
|
|
2019-01-28 08:48:03 +00:00
|
|
|
onFreezedItem = () => {
|
|
|
|
this.setState({isItemFreezed: true});
|
2018-08-22 08:39:42 +00:00
|
|
|
}
|
|
|
|
|
2019-01-28 08:48:03 +00:00
|
|
|
onUnFreezedItem = () => {
|
|
|
|
this.setState({isItemFreezed: false});
|
2018-08-22 08:39:42 +00:00
|
|
|
}
|
|
|
|
|
2019-03-23 06:16:48 +00:00
|
|
|
contextMenu = (e) => {
|
|
|
|
e.preventDefault();
|
|
|
|
this.setState({
|
|
|
|
isRightMenuShow:false,
|
|
|
|
});
|
|
|
|
setTimeout(() => {
|
|
|
|
this.setState({
|
|
|
|
isRightMenuShow:true,
|
|
|
|
fileData:this.state.nodeData,
|
|
|
|
mousePosition: {clientX: e.clientX, clientY: e.clientY}
|
|
|
|
})
|
|
|
|
},40)
|
|
|
|
}
|
|
|
|
|
|
|
|
unregisterHandlers = () => {
|
|
|
|
let treeView = document.querySelector('.tree-view');
|
|
|
|
treeView.removeEventListener('contextmenu', this.contextMenu);
|
|
|
|
}
|
|
|
|
|
|
|
|
registerHandlers = () => {
|
|
|
|
let treeView = document.querySelector('.tree-view');
|
|
|
|
treeView.addEventListener('contextmenu', this.contextMenu);
|
|
|
|
}
|
|
|
|
|
|
|
|
onNodeChanged = (node) => {
|
|
|
|
this.setState({
|
|
|
|
nodeData:node
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
closeRightMenu = () => {
|
|
|
|
this.setState({
|
|
|
|
isRightMenuShow:false,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
onMenuItemClick = (operation, node) => {
|
|
|
|
this.props.onMenuItemClick(operation, node)
|
|
|
|
}
|
|
|
|
|
2018-08-22 08:39:42 +00:00
|
|
|
render() {
|
|
|
|
return (
|
|
|
|
<div className="tree-view tree">
|
2019-01-28 08:48:03 +00:00
|
|
|
<TreeNodeView
|
2019-02-20 03:54:25 +00:00
|
|
|
repoPermission={this.props.repoPermission}
|
2018-08-22 08:39:42 +00:00
|
|
|
node={this.props.treeData.root}
|
2018-11-22 03:26:00 +00:00
|
|
|
currentPath={this.props.currentPath}
|
2019-01-28 08:48:03 +00:00
|
|
|
paddingLeft={PADDING_LEFT}
|
|
|
|
isNodeMenuShow={this.props.isNodeMenuShow}
|
|
|
|
isItemFreezed={this.state.isItemFreezed}
|
|
|
|
onNodeClick={this.props.onNodeClick}
|
|
|
|
onMenuItemClick={this.props.onMenuItemClick}
|
|
|
|
onNodeExpanded={this.props.onNodeExpanded}
|
|
|
|
onNodeCollapse={this.props.onNodeCollapse}
|
|
|
|
onNodeDragStart={this.onNodeDragStart}
|
|
|
|
onFreezedItem={this.onFreezedItem}
|
|
|
|
onUnFreezedItem={this.onUnFreezedItem}
|
2019-03-23 06:16:48 +00:00
|
|
|
onNodeChanged={this.onNodeChanged}
|
|
|
|
registerHandlers={this.registerHandlers}
|
|
|
|
unregisterHandlers={this.unregisterHandlers}
|
2019-03-27 03:25:27 +00:00
|
|
|
onNodeDragMove={this.onNodeDragMove}
|
|
|
|
onNodeDrop={this.onNodeDrop}
|
|
|
|
onNodeDragEnter={this.onNodeDragEnter}
|
|
|
|
onNodeDragLeave={this.onNodeDragLeave}
|
2018-08-22 08:39:42 +00:00
|
|
|
/>
|
2019-03-23 06:16:48 +00:00
|
|
|
{this.state.isRightMenuShow && (
|
|
|
|
<TreeViewContextMenu
|
|
|
|
node={this.state.fileData}
|
|
|
|
onMenuItemClick={this.onMenuItemClick}
|
|
|
|
mousePosition={this.state.mousePosition}
|
|
|
|
closeRightMenu={this.closeRightMenu}
|
|
|
|
registerHandlers={this.registerHandlers}
|
|
|
|
unregisterHandlers={this.unregisterHandlers}
|
|
|
|
/>
|
|
|
|
)}
|
2018-08-22 08:39:42 +00:00
|
|
|
</div>
|
|
|
|
);
|
2018-08-06 10:29:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-16 10:19:51 +00:00
|
|
|
TreeView.propTypes = propTypes;
|
|
|
|
|
2018-08-06 10:29:12 +00:00
|
|
|
export default TreeView;
|