mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-04 08:28:11 +00:00
Grid view support drag drop item to path (#6429)
* feature - drag and drop file to target path in grid view fix typo * update target path item background color when drag enter * fix bug - select-all checkbox is actived after the last item is moved to another path * fix bug - drag drop action conflict with multi-select by keyboard * remove console log * fix type error
This commit is contained in:
@@ -10,6 +10,7 @@ import ViewFileToolbar from '../../components/toolbar/view-file-toolbar';
|
||||
import { PRIVATE_FILE_TYPE } from '../../constants';
|
||||
|
||||
const propTypes = {
|
||||
currentRepoInfo: PropTypes.object.isRequired,
|
||||
repoID: PropTypes.string.isRequired,
|
||||
repoName: PropTypes.string.isRequired,
|
||||
currentPath: PropTypes.string.isRequired,
|
||||
@@ -32,10 +33,18 @@ const propTypes = {
|
||||
repoTags: PropTypes.array.isRequired,
|
||||
filePermission: PropTypes.string,
|
||||
onFileTagChanged: PropTypes.func.isRequired,
|
||||
onItemMove: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class DirPath extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
dropTargetPath: '',
|
||||
};
|
||||
}
|
||||
|
||||
onPathClick = (e) => {
|
||||
let path = Utils.getEventData(e, 'path');
|
||||
this.props.onPathClick(path);
|
||||
@@ -54,6 +63,54 @@ class DirPath extends React.Component {
|
||||
this.props.onTabNavClick(tabName, id);
|
||||
};
|
||||
|
||||
onDragEnter = (e) => {
|
||||
e.preventDefault();
|
||||
if (Utils.isIEBrower()) {
|
||||
return false;
|
||||
}
|
||||
this.setState({
|
||||
dropTargetPath: e.target.dataset.path,
|
||||
});
|
||||
};
|
||||
|
||||
onDragLeave = (e) => {
|
||||
e.preventDefault();
|
||||
if (Utils.isIEBrower()) {
|
||||
return false;
|
||||
}
|
||||
this.setState({
|
||||
dropTargetPath: '',
|
||||
});
|
||||
};
|
||||
|
||||
onDragOver = (e) => {
|
||||
if (Utils.isIEBrower()) {
|
||||
return false;
|
||||
}
|
||||
e.preventDefault();
|
||||
e.dataTransfer.dropEffect = 'move';
|
||||
};
|
||||
|
||||
onDrop = (e) => {
|
||||
if (Utils.isIEBrower()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.dataTransfer.files.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
let dragStartItemData = e.dataTransfer.getData('application/drag-item-info');
|
||||
dragStartItemData = JSON.parse(dragStartItemData);
|
||||
let { nodeDirent, nodeParentPath } = dragStartItemData;
|
||||
|
||||
let selectedPath = Utils.getEventData(e, 'path');
|
||||
this.props.onItemMove(this.props.currentRepoInfo, nodeDirent, selectedPath, nodeParentPath);
|
||||
this.setState({
|
||||
dropTargetPath: '',
|
||||
});
|
||||
};
|
||||
|
||||
turnPathToLink = (path) => {
|
||||
path = path[path.length - 1] === '/' ? path.slice(0, path.length - 1) : path;
|
||||
let pathList = path.split('/');
|
||||
@@ -126,7 +183,16 @@ class DirPath extends React.Component {
|
||||
return (
|
||||
<Fragment key={index} >
|
||||
<span className="path-split">/</span>
|
||||
<span className="path-item" data-path={nodePath} onClick={this.onPathClick} role="button">{item}</span>
|
||||
<span
|
||||
className={`path-item ${nodePath === this.state.dropTargetPath ? 'path-item-drop' : ''}`}
|
||||
data-path={nodePath} onClick={this.onPathClick}
|
||||
onDragEnter={this.onDragEnter}
|
||||
onDragLeave={this.onDragLeave}
|
||||
onDragOver={this.onDragOver}
|
||||
onDrop={this.onDrop}
|
||||
role="button">
|
||||
{item}
|
||||
</span>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ import DirPath from './dir-path';
|
||||
import DirTool from './dir-tool';
|
||||
|
||||
const propTypes = {
|
||||
currentRepoInfo: PropTypes.object.isRequired,
|
||||
repoID: PropTypes.string.isRequired,
|
||||
repoName: PropTypes.string.isRequired,
|
||||
userPerm: PropTypes.string,
|
||||
@@ -38,6 +39,7 @@ const propTypes = {
|
||||
repoTags: PropTypes.array.isRequired,
|
||||
onFileTagChanged: PropTypes.func.isRequired,
|
||||
metadataViewId: PropTypes.string,
|
||||
onItemMove: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class CurDirPath extends React.Component {
|
||||
@@ -60,6 +62,7 @@ class CurDirPath extends React.Component {
|
||||
return (
|
||||
<div className="cur-dir-path d-flex justify-content-between align-items-center">
|
||||
<DirPath
|
||||
currentRepoInfo={this.props.currentRepoInfo}
|
||||
repoID={this.props.repoID}
|
||||
repoName={this.props.repoName}
|
||||
repoEncrypted={this.props.repoEncrypted}
|
||||
@@ -82,6 +85,7 @@ class CurDirPath extends React.Component {
|
||||
filePermission={this.props.filePermission}
|
||||
onFileTagChanged={this.props.onFileTagChanged}
|
||||
repoTags={this.props.repoTags}
|
||||
onItemMove={this.props.onItemMove}
|
||||
/>
|
||||
{isDesktop &&
|
||||
<DirTool
|
||||
|
@@ -56,27 +56,27 @@ class DirentGridItem extends React.Component {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const { dirent, activeDirent } = this.props;
|
||||
const { dirent } = this.props;
|
||||
|
||||
if (this.clickTimeout) {
|
||||
clearTimeout(this.clickTimeout);
|
||||
this.clickTimeout = null;
|
||||
this.handleSingleClick(dirent, activeDirent, e);
|
||||
this.handleSingleClick(dirent, e);
|
||||
return;
|
||||
}
|
||||
|
||||
this.clickTimeout = setTimeout(() => {
|
||||
this.clickTimeout = null;
|
||||
this.handleSingleClick(dirent, activeDirent, e);
|
||||
this.handleSingleClick(dirent, e);
|
||||
}, 100); // Clicks within 100 milliseconds is considered a single click.
|
||||
};
|
||||
|
||||
handleSingleClick = (dirent, activeDirent, event) => {
|
||||
handleSingleClick = (dirent, event) => {
|
||||
if (!this.canPreview) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dirent === activeDirent && !event.metaKey && !event.ctrlKey) {
|
||||
if (dirent.isSelected && !event.metaKey && !event.ctrlKey) {
|
||||
this.handleDoubleClick(dirent, event);
|
||||
} else {
|
||||
this.props.onGridItemClick(dirent, event);
|
||||
@@ -113,6 +113,7 @@ class DirentGridItem extends React.Component {
|
||||
if (Utils.isIEBrower() || !this.canDrag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let dragStartItemData = { nodeDirent: this.props.dirent, nodeParentPath: this.props.path };
|
||||
dragStartItemData = JSON.stringify(dragStartItemData);
|
||||
|
||||
|
@@ -597,7 +597,6 @@ class DirentGridView extends React.Component {
|
||||
|
||||
onGridItemMouseDown = (event) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
if (event.button === 2) {
|
||||
return;
|
||||
}
|
||||
|
@@ -130,7 +130,7 @@
|
||||
}
|
||||
|
||||
.tree-node-drop {
|
||||
background-color: rgb(255, 239, 178);
|
||||
background-color: #FFEFB2;
|
||||
}
|
||||
|
||||
.tree-node-icon {
|
||||
@@ -282,6 +282,10 @@
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.dir-view-path .path-item-drop{
|
||||
background-color: #FFEFB2;
|
||||
}
|
||||
|
||||
.dir-view-path .path-split {
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
@@ -191,6 +191,7 @@ class LibContentContainer extends React.Component {
|
||||
}
|
||||
<div className="cur-view-path d-block" style={curViewPathStyle}>
|
||||
<CurDirPath
|
||||
currentRepoInfo={this.props.currentRepoInfo}
|
||||
repoID={repoID}
|
||||
repoName={this.props.currentRepoInfo.repo_name}
|
||||
repoEncrypted={this.props.repoEncrypted}
|
||||
@@ -223,6 +224,7 @@ class LibContentContainer extends React.Component {
|
||||
onFileTagChanged={this.props.onToolbarFileTagChanged}
|
||||
repoTags={this.props.repoTags}
|
||||
metadataViewId={this.props.metadataViewId}
|
||||
onItemMove={this.props.onItemMove}
|
||||
/>
|
||||
<ToolbarForSelectedDirents
|
||||
repoID={this.props.repoID}
|
||||
|
@@ -1912,7 +1912,7 @@ class LibContentView extends React.Component {
|
||||
this.setState({
|
||||
selectedDirentList: selectedDirentList,
|
||||
isDirentSelected: selectedDirentList.length > 0,
|
||||
isAllDirentSelected: selectedDirentList.length === newDirentList.length,
|
||||
isAllDirentSelected: newDirentList.length ? selectedDirentList.length === newDirentList.length : false,
|
||||
});
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user