mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-17 07:41:26 +00:00
Merge pull request #3332 from haiwen/Add-container-contextmenu
Add container contextmenu
This commit is contained in:
@@ -28,6 +28,7 @@ const propTypes = {
|
||||
updateDirent: PropTypes.func.isRequired,
|
||||
showShareBtn: PropTypes.bool.isRequired,
|
||||
showDirentDetail: PropTypes.func.isRequired,
|
||||
onAddFolder: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class DirGridView extends React.Component {
|
||||
@@ -74,6 +75,7 @@ class DirGridView extends React.Component {
|
||||
onGridItemClick={this.props.onGridItemClick}
|
||||
isDirentDetailShow={this.props.isDirentDetailShow}
|
||||
onItemRename={this.props.onItemRename}
|
||||
onAddFolder={this.props.onAddFolder}
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
|
@@ -9,14 +9,54 @@ const propTypes = {
|
||||
dirent: PropTypes.object.isRequired,
|
||||
onItemClick: PropTypes.func.isRequired,
|
||||
showImagePopup: PropTypes.func.isRequired,
|
||||
handleContextClick: PropTypes.func.isRequired,
|
||||
onGridItemContextMenu: PropTypes.func.isRequired,
|
||||
onGridItemClick: PropTypes.func.isRequired,
|
||||
activeDirent: PropTypes.object,
|
||||
onGridItemMouseDown: PropTypes.func,
|
||||
};
|
||||
|
||||
class DirentGridItem extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isGridSelected: false,
|
||||
isGridDropTipShow: false,
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.setState({isGridSelected: false}, () => {
|
||||
if (nextProps.activeDirent && nextProps.activeDirent.name === nextProps.dirent.name) {
|
||||
this.setState({isGridSelected: true});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onItemMove = (destRepo, dirent, selectedPath, currentPath) => {
|
||||
this.props.onItemMove(destRepo, dirent, selectedPath, currentPath);
|
||||
}
|
||||
|
||||
onItemClick = (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const dirent = this.props.dirent;
|
||||
if (this.props.dirent === this.props.activeDirent) {
|
||||
this.setState({isGridSelected: false});
|
||||
if (Utils.imageCheck(dirent.name)) {
|
||||
this.props.showImagePopup(dirent);
|
||||
} else {
|
||||
this.props.onItemClick(dirent);
|
||||
}
|
||||
} else {
|
||||
this.setState({isGridSelected: false});
|
||||
this.props.onGridItemClick(this.props.dirent)
|
||||
}
|
||||
}
|
||||
|
||||
onItemLinkClick = (e) => {
|
||||
e.preventDefault();
|
||||
const dirent = this.props.dirent;
|
||||
if (Utils.imageCheck(dirent.name)) {
|
||||
this.props.showImagePopup(dirent);
|
||||
@@ -25,6 +65,55 @@ class DirentGridItem extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
onGridItemDragStart = (e) => {
|
||||
let dragStartItemData = {nodeDirent: this.props.dirent, nodeParentPath: this.props.path};
|
||||
dragStartItemData = JSON.stringify(dragStartItemData);
|
||||
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
e.dataTransfer.setData('applicaiton/drag-item-info', dragStartItemData);
|
||||
}
|
||||
|
||||
onGridItemDragEnter = (e) => {
|
||||
if (this.props.dirent.type === 'dir') {
|
||||
this.setState({isGridDropTipShow: true});
|
||||
}
|
||||
}
|
||||
|
||||
onGridItemDragOver = (e) => {
|
||||
e.preventDefault();
|
||||
e.dataTransfer.dropEffect = 'move';
|
||||
}
|
||||
|
||||
onGridItemDragLeave = (e) => {
|
||||
this.setState({isGridDropTipShow: false});
|
||||
}
|
||||
|
||||
onGridItemDragDrop = (e) => {
|
||||
this.setState({isGridDropTipShow: 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} = dragStartItemData;
|
||||
let dropItemData = this.props.dirent;
|
||||
|
||||
if (nodeDirent.name === dropItemData.name) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dropItemData.type !== 'dir') {
|
||||
return;
|
||||
}
|
||||
|
||||
let selectedPath = Utils.joinPath(this.props.path, this.props.dirent.name);
|
||||
this.onItemMove(this.props.currentRepoInfo, nodeDirent, selectedPath, nodeParentPath);
|
||||
}
|
||||
|
||||
onGridItemMouseDown = (event) =>{
|
||||
this.props.onGridItemMouseDown(event);
|
||||
}
|
||||
|
||||
getFileUrl = (url) => {
|
||||
let fileUrlArr = url.split('/');
|
||||
if (fileUrlArr.indexOf('48') !== -1) {
|
||||
@@ -34,12 +123,9 @@ class DirentGridItem extends React.Component {
|
||||
return fileUrl;
|
||||
}
|
||||
|
||||
onItemContextMenu = (event) => {
|
||||
this.handleContextClick(event);
|
||||
}
|
||||
|
||||
handleContextClick = (event) => {
|
||||
this.props.handleContextClick(event, this.props.dirent);
|
||||
onGridItemContextMenu = (event) => {
|
||||
let dirent = this.props.dirent;
|
||||
this.props.onGridItemContextMenu(event, dirent);
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -54,13 +140,22 @@ class DirentGridItem extends React.Component {
|
||||
}
|
||||
let fileHref = siteRoot + 'lib/' + this.props.repoID + '/file' + Utils.encodePath(direntPath);
|
||||
|
||||
let gridClass = 'grid-file-img-link cursor-pointer'
|
||||
gridClass += this.state.isGridSelected ? " grid-selected-active" : " ";
|
||||
gridClass += this.state.isGridDropTipShow ? " grid-drop-show" : " ";
|
||||
|
||||
return(
|
||||
<Fragment>
|
||||
<li className="grid-item" onContextMenu={this.onItemContextMenu}>
|
||||
<li className="grid-item" onContextMenu={this.onGridItemContextMenu} onMouseDown={this.onGridItemMouseDown}>
|
||||
<div
|
||||
className="grid-file-img-link cursor-pointer"
|
||||
className={gridClass}
|
||||
draggable="true"
|
||||
onClick={this.onItemClick}
|
||||
onDragStart={this.onGridItemDragStart}
|
||||
onDragEnter={this.onGridItemDragEnter}
|
||||
onDragOver={this.onGridItemDragOver}
|
||||
onDragLeave={this.onGridItemDragLeave}
|
||||
onDrop={this.onGridItemDragDrop}
|
||||
>
|
||||
{dirent.encoded_thumbnail_src ?
|
||||
<img src={`${siteRoot}${fileUrl}`} ref={this.gridIcon} className="thumbnail" onClick={this.onItemClick} alt=""/> :
|
||||
@@ -68,8 +163,8 @@ class DirentGridItem extends React.Component {
|
||||
}
|
||||
{dirent.is_locked && <img className="grid-file-locked-icon" src={mediaUrl + 'img/file-locked-32.png'} alt={gettext('locked')} title={dirent.lock_owner_name}/>}
|
||||
</div>
|
||||
<div className="grid-file-name">
|
||||
<a className="grid-file-name-link" href={dirent.type === 'dir' ? dirHref : fileHref} onClick={this.onItemClick}>{dirent.name}</a>
|
||||
<div className="grid-file-name" onDragStart={this.onGridItemDragStart} draggable="true" >
|
||||
<a className={`grid-file-name-link ${this.state.isGridSelected ? "grid-link-selected-active" : ""}`} href={dirent.type === 'dir' ? dirHref : fileHref} onClick={this.onItemLinkClick}>{dirent.name}</a>
|
||||
</div>
|
||||
</li>
|
||||
</Fragment>
|
||||
|
@@ -16,6 +16,8 @@ import CopyDirentDialog from '../dialog/copy-dirent-dialog';
|
||||
import ShareDialog from '../dialog/share-dialog';
|
||||
import ZipDownloadDialog from '../dialog/zip-download-dialog';
|
||||
import Rename from '../../components/dialog/rename-grid-item-dialog';
|
||||
import CreateFile from '../dialog/create-file-dialog';
|
||||
import CreateFolder from '../dialog/create-folder-dialog';
|
||||
|
||||
import '../../css/grid-view.css';
|
||||
|
||||
@@ -37,6 +39,7 @@ const propTypes = {
|
||||
updateDirent: PropTypes.func.isRequired,
|
||||
isDirentDetailShow: PropTypes.bool.isRequired,
|
||||
onGridItemClick: PropTypes.func,
|
||||
onAddFolder: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class DirentGridView extends React.Component{
|
||||
@@ -46,20 +49,33 @@ class DirentGridView extends React.Component{
|
||||
isImagePopupOpen: false,
|
||||
imageItems: [],
|
||||
imageIndex: 0,
|
||||
isCreateFileDialogShow: false,
|
||||
// onmenuClick
|
||||
isShareDialogShow: false,
|
||||
isMoveDialogShow: false,
|
||||
isCopyDialogShow: false,
|
||||
isZipDialogOpen: false,
|
||||
isRenameDialogShow: false,
|
||||
isCreateFolderDialogShow: false,
|
||||
isCreateFileDialogShow: false,
|
||||
|
||||
isMutipleOperation: false,
|
||||
dirent: '',
|
||||
isGridItemFreezed: false,
|
||||
activeDirent: null,
|
||||
}
|
||||
this.isRepoOwner = props.currentRepoInfo.owner_email === username;
|
||||
}
|
||||
|
||||
onCreateFileToggle = () => {
|
||||
this.setState({
|
||||
isCreateFileDialogShow: !this.state.isCreateFileDialogShow,
|
||||
});
|
||||
}
|
||||
|
||||
onGridItemClick = (dirent) => {
|
||||
this.setState({activeDirent: dirent});
|
||||
this.props.onGridItemClick(dirent);
|
||||
}
|
||||
|
||||
onMoveToggle = () => {
|
||||
this.setState({isMoveDialogShow: !this.state.isMoveDialogShow});
|
||||
}
|
||||
@@ -73,6 +89,11 @@ class DirentGridView extends React.Component{
|
||||
this.props.onAddFile(filePath, isDraft);
|
||||
}
|
||||
|
||||
onAddFolder = (dirPath) => {
|
||||
this.setState({isCreateFolderDialogShow: false});
|
||||
this.props.onAddFolder(dirPath);
|
||||
}
|
||||
|
||||
onItemShare = (e) => {
|
||||
e.nativeEvent.stopImmediatePropagation(); //for document event
|
||||
this.setState({isShareDialogShow: !this.state.isShareDialogShow});
|
||||
@@ -126,6 +147,12 @@ class DirentGridView extends React.Component{
|
||||
case 'Details':
|
||||
this.onDetails(currentObject);
|
||||
break;
|
||||
case 'New Folder':
|
||||
this.onCreateFolderToggle(currentObject);
|
||||
break;
|
||||
case 'New File':
|
||||
this.onCreateFileToggle(currentObject);
|
||||
break;
|
||||
case 'Access Log':
|
||||
this.onAccessLog();
|
||||
break;
|
||||
@@ -168,6 +195,12 @@ class DirentGridView extends React.Component{
|
||||
}
|
||||
}
|
||||
|
||||
onCreateFolderToggle = () => {
|
||||
this.setState({
|
||||
isCreateFolderDialogShow: !this.state.isCreateFolderDialogShow,
|
||||
});
|
||||
}
|
||||
|
||||
onItemRenameToggle = () => {
|
||||
this.setState({
|
||||
isRenameDialogShow: !this.state.isRenameDialogShow,
|
||||
@@ -230,7 +263,7 @@ class DirentGridView extends React.Component{
|
||||
this.setState({
|
||||
isRenameDialogShow: !this.state.isRenameDialogShow,
|
||||
});
|
||||
this.props.onItemRename(this.state.dirent, newName)
|
||||
this.props.onItemRename(this.state.activeDirent, newName)
|
||||
}
|
||||
|
||||
|
||||
@@ -299,13 +332,41 @@ class DirentGridView extends React.Component{
|
||||
return isDuplicated;
|
||||
}
|
||||
|
||||
gridContainerClick = () => {
|
||||
if (!this.props.isDirentDetailShow) {
|
||||
this.props.onGridItemClick(null);
|
||||
// common contextmenu handle
|
||||
onMouseDown = (event) => {
|
||||
event.stopPropagation();
|
||||
if (event.button === 2) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
handleContextClick = (event, currentObject) => {
|
||||
onGridContainerMouseDown = (event) => {
|
||||
this.onMouseDown(event)
|
||||
}
|
||||
|
||||
onGridItemMouseDown = (event) => {
|
||||
this.onMouseDown(event);
|
||||
}
|
||||
|
||||
gridContainerClick = () => {
|
||||
if (!this.props.isDirentDetailShow) {
|
||||
this.onGridItemClick(null);
|
||||
}
|
||||
}
|
||||
|
||||
onGridContainerContextMenu = (event) => {
|
||||
let id = "dirent-grid-container-menu"
|
||||
let menuList = [TextTranslation.NEW_FOLDER, TextTranslation.NEW_FILE];
|
||||
this.handleContextClick(event, id, menuList);
|
||||
}
|
||||
|
||||
onGridItemContextMenu = (event, dirent) => {
|
||||
let id = 'grid-item-contextmenu';
|
||||
let menuList = this.getDirentItemMenuList(dirent, true);
|
||||
this.handleContextClick(event, id, menuList, dirent);
|
||||
}
|
||||
|
||||
handleContextClick = (event, id, menuList, currentObject = null) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
@@ -320,13 +381,11 @@ class DirentGridView extends React.Component{
|
||||
}
|
||||
|
||||
hideMenu();
|
||||
|
||||
let menuList = this.getDirentItemMenuList(currentObject, true);
|
||||
|
||||
this.setState({dirent: currentObject});
|
||||
|
||||
this.setState({activeDirent: currentObject});
|
||||
|
||||
let showMenuConfig = {
|
||||
id: 'grid-item-contextmenu',
|
||||
id: id,
|
||||
position: { x, y },
|
||||
target: event.target,
|
||||
currentObject: currentObject,
|
||||
@@ -415,7 +474,7 @@ class DirentGridView extends React.Component{
|
||||
|
||||
render() {
|
||||
let {direntList, path} = this.props;
|
||||
let dirent = this.state.dirent;
|
||||
let dirent = this.state.activeDirent ? this.state.activeDirent : '';
|
||||
let direntPath = Utils.joinPath(path, dirent.name);
|
||||
|
||||
if (this.props.isDirentListLoading) {
|
||||
@@ -424,7 +483,7 @@ class DirentGridView extends React.Component{
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<ul className="grid-view" onClick={this.gridContainerClick}>
|
||||
<ul className="grid-view" onClick={this.gridContainerClick} onContextMenu={this.onGridContainerContextMenu} onMouseDown={this.onGridContainerMouseDown}>
|
||||
{
|
||||
direntList.length !== 0 && direntList.map((dirent, index) => {
|
||||
return (
|
||||
@@ -436,8 +495,11 @@ class DirentGridView extends React.Component{
|
||||
onItemClick={this.props.onItemClick}
|
||||
currentRepoInfo={this.props.currentRepoInfo}
|
||||
showImagePopup={this.showImagePopup}
|
||||
handleContextClick={this.handleContextClick}
|
||||
onGridItemContextMenu={this.onGridItemContextMenu}
|
||||
onItemMove={this.props.onItemMove}
|
||||
onGridItemMouseDown={this.onGridItemMouseDown}
|
||||
onGridItemClick={this.onGridItemClick}
|
||||
activeDirent={this.state.activeDirent}
|
||||
/>
|
||||
)
|
||||
})
|
||||
@@ -447,6 +509,30 @@ class DirentGridView extends React.Component{
|
||||
id={'grid-item-contextmenu'}
|
||||
onMenuItemClick={this.onMenuItemClick}
|
||||
/>
|
||||
<ContextMenu
|
||||
id={'dirent-grid-container-menu'}
|
||||
onMenuItemClick={this.onMenuItemClick}
|
||||
/>
|
||||
{this.state.isCreateFolderDialogShow && (
|
||||
<ModalPortal>
|
||||
<CreateFolder
|
||||
parentPath={this.props.path}
|
||||
onAddFolder={this.onAddFolder}
|
||||
checkDuplicatedName={this.checkDuplicatedName}
|
||||
addFolderCancel={this.onCreateFolderToggle}
|
||||
/>
|
||||
</ModalPortal>
|
||||
)}
|
||||
{this.state.isCreateFileDialogShow && (
|
||||
<ModalPortal>
|
||||
<CreateFile
|
||||
parentPath={this.props.path}
|
||||
onAddFile={this.onAddFile}
|
||||
checkDuplicatedName={this.checkDuplicatedName}
|
||||
addFileCancel={this.onCreateFileToggle}
|
||||
/>
|
||||
</ModalPortal>
|
||||
)}
|
||||
{this.state.isMoveDialogShow &&
|
||||
<MoveDirentDialog
|
||||
path={this.props.path}
|
||||
@@ -455,7 +541,7 @@ class DirentGridView extends React.Component{
|
||||
isMutipleOperation={this.state.isMutipleOperation}
|
||||
onItemMove={this.props.onItemMove}
|
||||
onCancelMove={this.onMoveToggle}
|
||||
dirent={this.state.dirent}
|
||||
dirent={this.state.activeDirent}
|
||||
/>
|
||||
}
|
||||
{this.state.isZipDialogOpen &&
|
||||
@@ -476,7 +562,7 @@ class DirentGridView extends React.Component{
|
||||
isMutipleOperation={this.state.isMutipleOperation}
|
||||
onItemCopy={this.props.onItemCopy}
|
||||
onCancelCopy={this.onCopyToggle}
|
||||
dirent={this.state.dirent}
|
||||
dirent={this.state.activeDirent}
|
||||
/>
|
||||
}
|
||||
{this.state.isShareDialogShow &&
|
||||
@@ -497,7 +583,7 @@ class DirentGridView extends React.Component{
|
||||
{this.state.isRenameDialogShow && (
|
||||
<ModalPortal>
|
||||
<Rename
|
||||
dirent={this.state.dirent}
|
||||
dirent={this.state.activeDirent}
|
||||
onRename={this.onItemRename}
|
||||
checkDuplicatedName={this.checkDuplicatedName}
|
||||
toggleCancel={this.onItemRenameToggle}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
.grid-view {
|
||||
padding-top: 10px;
|
||||
padding: 0.625rem 1rem 10rem;
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -24,15 +24,14 @@
|
||||
}
|
||||
|
||||
.grid-file-img-link {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
width: 96px;
|
||||
height: 96px;
|
||||
margin: 0 auto 6px;
|
||||
position: relative;
|
||||
border-radius: 3px;
|
||||
font-size: 0;
|
||||
text-align: center;
|
||||
line-height: 0;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.grid-file-img-link .thumbnail {
|
||||
@@ -71,4 +70,16 @@
|
||||
bottom: 0;
|
||||
right: 10px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.grid-selected-active {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
.grid-link-selected-active {
|
||||
color: #eb8205;
|
||||
}
|
||||
|
||||
.grid-drop-show {
|
||||
background: #f8f8f8;
|
||||
}
|
@@ -116,6 +116,7 @@ class LibContentContainer extends React.Component {
|
||||
|
||||
onGridItemClick = (dirent) => {
|
||||
this.setState({currentDirent: dirent});
|
||||
this.props.onDirentClick(dirent);
|
||||
}
|
||||
|
||||
// on '<tr>'
|
||||
|
Reference in New Issue
Block a user