From 07d596f620479bb9c078500c820a587aa6e3c917 Mon Sep 17 00:00:00 2001
From: zxj96 <35951769+zxj96@users.noreply.github.com>
Date: Mon, 8 Apr 2019 11:35:46 +0800
Subject: [PATCH] Item right menu (#3203)
* Add item right menu
* Add item right menu
* Pass value bug
* Add item right menu
* modify style problem
* Add some style
* Modifying naming issues
* Modify Priority
* Add showShare jurisdiction and modify priority
* Modify subscript to itemIndex
* Communication between sibling components
* Improve interaction
* modify style problem
* Promotion isItemFreezed and onUnfreezedItem level
* modify bugs
* have tree-node bug
* Solve tree-node item-click bug
* Complete right click menu
* modify style
* modify style
* item-right-menu finash
* modify style to dirent-=list-item
* modify some style problem
* modify styles
* stop thead contextmenu
---
.../dir-view-mode/dir-column-nav.js | 4 +
.../dir-view-mode/dir-column-view.js | 7 +
.../components/dir-view-mode/dir-list-view.js | 172 +++++++++--
.../dirent-list-view/dirent-list-item.js | 100 +++++-
.../dirent-list-view/dirent-list-view.js | 26 +-
.../dirent-list-view/dirent-menu.js | 7 +
.../dirent-list-view/dirent-right-menu.js | 291 ++++++++++++++++++
.../components/tree-view/tree-node-menu.js | 10 +-
.../components/tree-view/tree-node-view.js | 12 +
.../src/components/tree-view/tree-view.js | 23 +-
frontend/src/css/layout.css | 6 +
frontend/src/css/tree-view-contextmenu.css | 4 +-
.../lib-content-view/lib-content-container.js | 26 ++
13 files changed, 648 insertions(+), 40 deletions(-)
create mode 100644 frontend/src/components/dirent-list-view/dirent-right-menu.js
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 c86196a45a..a22e1203b0 100644
--- a/frontend/src/components/dir-view-mode/dir-column-nav.js
+++ b/frontend/src/components/dir-view-mode/dir-column-nav.js
@@ -32,6 +32,8 @@ const propTypes = {
navRate: PropTypes.number,
inResizing: PropTypes.bool.isRequired,
currentRepoInfo: PropTypes.object.isRequired,
+ switchAnotherMenuToShow: PropTypes.func,
+ appMenuType: PropTypes.oneOf(['list_view_contextmenu', 'item_contextmenu', 'tree_contextmenu', 'item_op_menu']),
};
class DirColumnNav extends React.Component {
@@ -282,6 +284,8 @@ class DirColumnNav extends React.Component {
onUnFreezedItem={this.onUnFreezedItem}
onItemMove={this.props.onItemMove}
currentRepoInfo={this.props.currentRepoInfo}
+ switchAnotherMenuToShow={this.props.switchAnotherMenuToShow}
+ appMenuType={this.props.appMenuType}
/>)
}
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 41ab1b3a50..884a2cd68a 100644
--- a/frontend/src/components/dir-view-mode/dir-column-view.js
+++ b/frontend/src/components/dir-view-mode/dir-column-view.js
@@ -63,6 +63,8 @@ const propTypes = {
onDirentClick: PropTypes.func.isRequired,
isAllItemSelected: PropTypes.bool.isRequired,
onAllItemSelected: PropTypes.func.isRequired,
+ switchAnotherMenuToShow: PropTypes.func,
+ appMenuType: PropTypes.oneOf(['list_view_contextmenu', 'item_contextmenu', 'tree_contextmenu', 'item_op_menu']),
};
class DirColumnView extends React.Component {
@@ -165,6 +167,8 @@ class DirColumnView extends React.Component {
currentRepoInfo={this.props.currentRepoInfo}
onItemMove={this.props.onItemMove}
onItemCopy={this.props.onItemCopy}
+ switchAnotherMenuToShow={this.props.switchAnotherMenuToShow}
+ appMenuType={this.props.appMenuType}
/>
@@ -213,6 +217,9 @@ class DirColumnView extends React.Component {
updateDirent={this.props.updateDirent}
isAllItemSelected={this.props.isAllItemSelected}
onAllItemSelected={this.props.onAllItemSelected}
+ switchAnotherMenuToShow={this.props.switchAnotherMenuToShow}
+ appMenuType={this.props.appMenuType}
+ onAddFolder={this.props.onAddFolder}
/>
)}
diff --git a/frontend/src/components/dir-view-mode/dir-list-view.js b/frontend/src/components/dir-view-mode/dir-list-view.js
index 60de02eb87..ced53459b4 100644
--- a/frontend/src/components/dir-view-mode/dir-list-view.js
+++ b/frontend/src/components/dir-view-mode/dir-list-view.js
@@ -1,7 +1,11 @@
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import RepoInfoBar from '../../components/repo-info-bar';
+import ModalPortal from '../modal-portal';
import DirentListView from '../../components/dirent-list-view/dirent-list-view';
+import CreateFile from '../../components/dialog/create-file-dialog';
+import CreateFolder from '../../components/dialog/create-folder-dialog';
+import DirentListMenu from '../dirent-list-view/dirent-right-menu';
const propTypes = {
path: PropTypes.string.isRequired,
@@ -31,9 +35,94 @@ const propTypes = {
updateDirent: PropTypes.func.isRequired,
isAllItemSelected: PropTypes.bool.isRequired,
onAllItemSelected: PropTypes.func.isRequired,
+ switchAnotherMenuToShow: PropTypes.func,
+ appMenuType: PropTypes.oneOf(['list_view_contextmenu', 'item_contextmenu', 'tree_contextmenu', 'item_op_menu']),
+ onAddFolder: PropTypes.func,
};
class DirListView extends React.Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ isCreateFileDialogShow: false,
+ fileType: '',
+ isContainerContextmenuShow: false,
+ isCreateFolderDialogShow: false,
+ itemMousePosition: {clientX: '', clientY: ''},
+ }
+ }
+
+ componentDidUpdate() {
+ this.registerTableContainerContextmenuHandler();
+ }
+
+ componentWillUnmount() {
+ this.unregisterTableContainerContextmenuHandler();
+ }
+
+ registerTableContainerContextmenuHandler = () => {
+ let tableContainer = document.querySelector('.table-container');
+ if (tableContainer) {
+ tableContainer.addEventListener('contextmenu', this.tableContainerContextmenuHandler);
+ }
+ }
+
+ unregisterTableContainerContextmenuHandler = () => {
+ let tableContainer = document.querySelector('.table-container');
+ tableContainer.removeEventListener('contextmenu', this.tableContainerContextmenuHandler);
+ }
+
+ tableContainerContextmenuHandler = (e) => {
+ e.preventDefault();
+
+ this.props.switchAnotherMenuToShow('list_view_contextmenu');
+
+ this.setState({isContainerContextmenuShow: false}, () => {
+ this.setState({
+ isContainerContextmenuShow: true,
+ itemMousePosition: {clientX: e.clientX, clientY: e.clientY}
+ })
+ });
+ }
+
+ closeTableContainerRightMenu = () => {
+ this.setState({
+ isContainerContextmenuShow: false,
+ });
+ this.props.switchAnotherMenuToShow('item_op_menu');
+ }
+
+ onCreateFolderToggle = () => {
+ this.setState({
+ isCreateFolderDialogShow: !this.state.isCreateFolderDialogShow,
+ });
+ }
+
+ onCreateFileToggle = () => {
+ this.setState({
+ isCreateFileDialogShow: !this.state.isCreateFileDialogShow,
+ fileType: ''
+ });
+ }
+
+ onAddFile = (filePath, isDraft) => {
+ this.setState({isCreateFileDialogShow: false});
+ this.props.onAddFile(filePath, isDraft);
+ }
+
+ onAddFolder = (dirPath) => {
+ this.setState({isCreateFolderDialogShow: false});
+ this.props.onAddFolder(dirPath);
+ }
+
+ checkDuplicatedName = (newName) => {
+ let direntList = this.props.direntList;
+ let isDuplicated = direntList.some(object => {
+ return object.name === newName;
+ });
+ return isDuplicated;
+ }
render() {
return (
@@ -48,30 +137,65 @@ class DirListView extends React.Component {
updateUsedRepoTags={this.props.updateUsedRepoTags}
/>
)}
-
+
+
+
+ {this.state.isContainerContextmenuShow && this.props.appMenuType === 'list_view_contextmenu' && (
+
+ )}
+ {this.state.isCreateFolderDialogShow && (
+
+
+
+ )}
+ {this.state.isCreateFileDialogShow && (
+
+
+
+ )}
);
}
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 13e538bad2..32265ae802 100644
--- a/frontend/src/components/dirent-list-view/dirent-list-item.js
+++ b/frontend/src/components/dirent-list-view/dirent-list-item.js
@@ -13,6 +13,7 @@ import ZipDownloadDialog from '../dialog/zip-download-dialog';
import MoveDirentDialog from '../dialog/move-dirent-dialog';
import CopyDirentDialog from '../dialog/copy-dirent-dialog';
import ShareDialog from '../dialog/share-dialog';
+import DirentRightMenu from './dirent-right-menu';
import '../../css/dirent-list-item.css';
@@ -39,6 +40,8 @@ const propTypes = {
isAdmin: PropTypes.bool.isRequired,
repoEncrypted: PropTypes.bool.isRequired,
isGroupOwnedRepo: PropTypes.bool.isRequired,
+ switchAnotherMenuToShow: PropTypes.func,
+ appMenuType: PropTypes.oneOf(['list_view_contextmenu', 'item_contextmenu', 'tree_contextmenu', 'item_op_menu']),
};
class DirentListItem extends React.Component {
@@ -57,10 +60,70 @@ class DirentListItem extends React.Component {
isShowTagTooltip: false,
isDragTipShow: false,
isDropTipshow: false,
+ enterItemData: '',
+ enterItemIndex: -1,
+ contextmenuItemData: {},
+ contextmenuItemIndex: -1,
+ isItemContextMenuShow: false,
};
this.zipToken = null;
}
+ componentWillReceiveProps(nextProp) {
+ if (nextProp.appMenuType === 'list_view_contextmenu' || nextProp.appMenuType === 'item_contextmenu') {
+ this.setState({
+ highlight: false,
+ isOperationShow: false,
+ })
+ }
+ }
+
+ componentDidUpdate() {
+ this.itemRegisterHandlers();
+ }
+
+ componentWillUnmount() {
+ this.itemUnregisterHandlers();
+ }
+
+ itemUnregisterHandlers = () => {
+ let itemTbody = document.querySelector('tbody');
+ itemTbody.removeEventListener('contextmenu', this.itemRightContextMenu);
+ }
+
+ itemRegisterHandlers = () => {
+ let itemTbody = document.querySelector('tbody');
+ if (itemTbody) {
+ itemTbody.addEventListener('contextmenu', this.itemRightContextMenu);
+ }
+ }
+
+ itemRightContextMenu = (e) =>{
+ e.preventDefault();
+ e.stopPropagation();
+
+ this.props.switchAnotherMenuToShow('item_contextmenu');
+ this.setState({
+ isItemContextMenuShow: false,
+ itemMousePosition: {clientX: e.clientX, clientY: e.clientY},
+ contextmenuItemData: this.state.enterItemData,
+ contextmenuItemIndex: this.state.enterItemIndex,
+ })
+ setTimeout(() => {
+ this.setState({
+ isItemContextMenuShow: true,
+ })
+ },40)
+ }
+
+ closeRightMenu = () => {
+ this.setState({
+ isItemContextMenuShow: false,
+ });
+ this.onUnfreezedItem();
+ this.props.switchAnotherMenuToShow('item_op_menu');
+ }
+
//UI Interactive
onMouseEnter = () => {
if (!this.props.isItemFreezed) {
@@ -69,7 +132,11 @@ class DirentListItem extends React.Component {
isOperationShow: true,
});
}
- this.setState({isDragTipShow: true});
+ this.setState({
+ isDragTipShow: true,
+ enterItemData: this.props.dirent,
+ enterItemIndex: this.props.itemIndex,
+ });
}
onMouseOver = () => {
@@ -79,7 +146,10 @@ class DirentListItem extends React.Component {
isOperationShow: true,
});
}
- this.setState({isDragTipShow: true});
+ this.setState({
+ isDragTipShow: true,
+ enterItemData: this.props.dirent,
+ enterItemIndex: this.props.itemIndex});
}
onMouseLeave = () => {
@@ -89,7 +159,11 @@ class DirentListItem extends React.Component {
isOperationShow: false,
});
}
- this.setState({isDragTipShow: false});
+ this.setState({
+ isDragTipShow: false,
+ enterItemData: '',
+ enterItemIndex: -1,
+ });
}
onUnfreezedItem = () => {
@@ -209,7 +283,7 @@ class DirentListItem extends React.Component {
onRenameCancel = () => {
this.setState({isRenameing: false});
- this.props.onUnfreezedItem();
+ this.onUnfreezedItem();
}
onItemMoveToggle = () => {
@@ -484,11 +558,29 @@ class DirentListItem extends React.Component {
isRepoOwner={this.props.isRepoOwner}
onFreezedItem={this.props.onFreezedItem}
onUnfreezedItem={this.onUnfreezedItem}
+ appMenuType={this.props.appMenuType}
/>
}
+ {this.state.isItemContextMenuShow && this.state.contextmenuItemIndex === this.props.itemIndex && this.props.appMenuType === 'item_contextmenu' &&
+
+ }
{dirent.size && dirent.size} |
{dirent.mtime_relative} |
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 31dc7be7cf..1cc815f8e2 100644
--- a/frontend/src/components/dirent-list-view/dirent-list-view.js
+++ b/frontend/src/components/dirent-list-view/dirent-list-view.js
@@ -34,6 +34,8 @@ const propTypes = {
onDirentClick: PropTypes.func.isRequired,
onItemDetails: PropTypes.func.isRequired,
updateDirent: PropTypes.func.isRequired,
+ switchAnotherMenuToShow: PropTypes.func,
+ appMenuType: PropTypes.oneOf(['list_view_contextmenu', 'item_contextmenu', 'tree_contextmenu', 'item_op_menu']),
};
class DirentListView extends React.Component {
@@ -48,7 +50,7 @@ class DirentListView extends React.Component {
imageIndex: 0,
isCreateFileDialogShow: false,
- fileType: ''
+ fileType: '',
};
this.isRepoOwner = props.currentRepoInfo.owner_email === username;
@@ -56,6 +58,23 @@ class DirentListView extends React.Component {
this.repoEncrypted = props.currentRepoInfo.encrypted;
}
+ componentWillReceiveProps(nextProps) {
+ if (nextProps.appMenuType === 'item_op_menu' || nextProps.appMenuType === 'tree_contextmenu') {
+ this.setState({isItemFreezed: false});
+ } else {
+ this.setState({isItemFreezed: true});
+ }
+ }
+
+ componentDidUpdate() {
+ let thead = document.querySelector('thead');
+ if (thead) {
+ thead.addEventListener('contextmenu', (e) => {
+ e.stopPropagation();
+ })
+ }
+ }
+
onFreezedItem = () => {
this.setState({isItemFreezed: true});
}
@@ -254,7 +273,7 @@ class DirentListView extends React.Component {
-
+ |
|
{/*icon */} |
@@ -296,6 +315,9 @@ class DirentListView extends React.Component {
onDirentClick={this.props.onDirentClick}
onItemDetails={this.onItemDetails}
showImagePopup={this.showImagePopup}
+ switchAnotherMenuToShow={this.props.switchAnotherMenuToShow}
+ appMenuType={this.props.appMenuType}
+ itemIndex={index}
/>
);
})
diff --git a/frontend/src/components/dirent-list-view/dirent-menu.js b/frontend/src/components/dirent-list-view/dirent-menu.js
index 3c2f06e7ae..8296cdfcb4 100644
--- a/frontend/src/components/dirent-list-view/dirent-menu.js
+++ b/frontend/src/components/dirent-list-view/dirent-menu.js
@@ -10,6 +10,7 @@ const propTypes = {
onMenuItemClick: PropTypes.func.isRequired,
onFreezedItem: PropTypes.func.isRequired,
onUnfreezedItem: PropTypes.func.isRequired,
+ appMenuType: PropTypes.oneOf(['list_view_contextmenu', 'item_contextmenu', 'tree_contextmenu', 'item_op_menu']),
};
class DirentMenu extends React.Component {
@@ -26,6 +27,12 @@ class DirentMenu extends React.Component {
this.menuList = this.calculateMenuList();
}
+ componentWillReceiveProps(nextProp) {
+ if (nextProp.appMenuType === 'list_view_contextmenu' || nextProp.appMenuType === 'item_contextmenu') {
+ this.setState({isItemMenuShow: false});
+ }
+ }
+
calculateMenuList() {
let { currentRepoInfo, dirent, isRepoOwner } = this.props;
diff --git a/frontend/src/components/dirent-list-view/dirent-right-menu.js b/frontend/src/components/dirent-list-view/dirent-right-menu.js
new file mode 100644
index 0000000000..1afeaadd08
--- /dev/null
+++ b/frontend/src/components/dirent-list-view/dirent-right-menu.js
@@ -0,0 +1,291 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { gettext, isPro, enableFileComment, fileAuditEnabled, folderPermEnabled } from '../../utils/constants';
+
+import '../../css/tree-view-contextmenu.css'
+
+const propTypes = {
+ dirent: PropTypes.object,
+ mousePosition: PropTypes.object,
+ isRepoOwner: PropTypes.bool,
+ currentRepoInfo: PropTypes.object,
+ onMenuItemClick: PropTypes.func,
+ onItemDownload: PropTypes.func,
+ onItemShare: PropTypes.func,
+ onItemDelete: PropTypes.func,
+ itemRegisterHandlers: PropTypes.func,
+ itemUnregisterHandlers: PropTypes.func,
+ closeRightMenu: PropTypes.func,
+ onCreateFolderToggle: PropTypes.func,
+ onCreateFileToggle: PropTypes.func,
+};
+
+class DirentRightMenu extends React.Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ isItemMenuShow: false,
+ menuList: [],
+ };
+ }
+
+ componentDidMount() {
+ let menuList = this.caculateMenuList();
+ this.setState({menuList: menuList});
+ }
+
+ componentDidUpdate() {
+ this.calculateMenuDistance();
+ }
+
+ componentWillUnmount() {
+ document.removeEventListener('click', this.listenClick);
+ document.removeEventListener('mousemove', this.handleContextMenu);
+ }
+
+ caculateMenuList() {
+ if (!this.props.dirent) {
+ let menuList = ['New Folder', 'New File'];
+ return menuList;
+ }
+
+ let { currentRepoInfo, dirent, isRepoOwner, showShare } = this.props;
+
+ let type = dirent.type ? dirent.type : '';
+ let permission = dirent.permission ? dirent.permission : '';
+ let can_set_folder_perm = folderPermEnabled && ((isRepoOwner && currentRepoInfo.has_been_shared_out) || currentRepoInfo.is_admin);
+ if (type === 'dir' && permission === 'rw') {
+ let subscriptList = showShare ? ['Share', 'Download', 'Delete'] : ['Download', 'Delete'];
+ let menuList = [];
+ if (can_set_folder_perm) {
+ menuList = [...subscriptList, 'Rename', 'Move', 'Copy', 'Permission', 'Details', 'Open via Client'];
+ } else {
+ menuList = [...subscriptList, 'Rename', 'Move', 'Copy', 'Details', 'Open via Client'];
+ }
+ return menuList;
+ }
+
+ if (type === 'dir' && permission === 'r') {
+ let menuList = showShare ? ['Share', 'Download', 'Delete', 'Copy', 'Details'] : ['Download', 'Delete', 'Details'];
+ return menuList;
+ }
+
+ if (type === 'file' && permission === 'rw') {
+ let menuList = showShare ? ['Share', 'Download', 'Delete'] : ['Download', 'Delete'];
+
+ if (!dirent.is_locked || (dirent.is_locked && dirent.locked_by_me)) {
+ menuList.push('Rename');
+ menuList.push('Move');
+ }
+ menuList.push('Copy');
+ if (isPro) {
+ if (dirent.is_locked) {
+ if (dirent.locked_by_me || (dirent.lock_owner === 'OnlineOffice' && permission === 'rw')) {
+ menuList.push('Unlock');
+ }
+ } else {
+ menuList.push('Lock');
+ }
+ }
+ if (enableFileComment) {
+ menuList.push('Comment');
+ }
+ menuList.push('History');
+ if (fileAuditEnabled) {
+ menuList.push('Access Log');
+ }
+ menuList.push('Details');
+ menuList.push('Open via Client');
+ return menuList;
+ }
+
+ if (type === 'file' && permission === 'r') {
+ let menuList = showShare ? ['Share', 'Download', 'Delete'] : ['Download', 'Delete'];
+ if (!currentRepoInfo.encrypted) {
+ menuList.push('Copy');
+ }
+ if (enableFileComment) {
+ menuList.push('Comment');
+ }
+ menuList.push('History');
+ menuList.push('Details');
+ return menuList;
+ }
+ }
+
+ calculateMenuDistance = () => {
+ let { mousePosition } = this.props;
+ let rightTreeMenu = document.querySelector('.right-tree-menu');
+ let rightTreeMenuHeight = rightTreeMenu.offsetHeight;
+ let rightTreeMenuWidth = rightTreeMenu.offsetWidth;
+
+ if (mousePosition.clientY + rightTreeMenuHeight > document.body.clientHeight) {
+ rightTreeMenu.style.top = mousePosition.clientY - rightTreeMenuHeight + 'px';
+ } else {
+ rightTreeMenu.style.top = mousePosition.clientY + 'px';
+ }
+
+ if (mousePosition.clientX + rightTreeMenuWidth > document.body.clientWidth) {
+ rightTreeMenu.style.left = mousePosition.clientX - rightTreeMenuWidth + 'px';
+ } else {
+ rightTreeMenu.style.left = mousePosition.clientX + 'px';
+ }
+
+ document.addEventListener('click', this.listenClick);
+ document.addEventListener('mousemove', this.handleContextMenu);
+ }
+
+ translateMenuItem = (menuItem) => {
+ let translateResult = '';
+ switch(menuItem) {
+ case 'New Folder':
+ translateResult = gettext('New Folder');
+ break;
+ case 'Share':
+ translateResult = gettext('Share');
+ break;
+ case 'Download':
+ translateResult = gettext('Download');
+ break;
+ case 'New File':
+ translateResult = gettext('New File');
+ break;
+ case 'Rename':
+ translateResult = gettext('Rename');
+ break;
+ case 'Copy':
+ translateResult = gettext('Copy');
+ break;
+ case 'Move':
+ translateResult = gettext('Move');
+ break;
+ case 'Delete':
+ translateResult = gettext('Delete');
+ break;
+ case 'Details':
+ translateResult = gettext('Details');
+ break;
+ case 'Unlock':
+ translateResult = gettext('Unlock');
+ break;
+ case 'Lock':
+ translateResult = gettext('Lock');
+ break;
+ case 'History':
+ translateResult = gettext('History');
+ break;
+ case 'Open via Client':
+ translateResult = gettext('Open via Client');
+ break;
+ default:
+ break;
+ }
+ return translateResult;
+ }
+
+ handleContextMenu = (e) => {
+ let { mousePosition } = this.props;
+ let rightTreeMenu = document.querySelector('.right-tree-menu');
+ let rightTreeMenuHeight = rightTreeMenu.offsetHeight;
+ let rightTreeMenuWidth = rightTreeMenu.offsetWidth;
+
+ rightTreeMenu.addEventListener('contextmenu', (e) => {
+ e.stopPropagation();
+ })
+
+ if (mousePosition.clientY + rightTreeMenuHeight > document.body.clientHeight) {
+ if (mousePosition.clientX + rightTreeMenuWidth > document.body.clientWidth) {
+ if ((e.clientX >= (mousePosition.clientX - rightTreeMenuWidth)) && (e.clientX <= mousePosition.clientX) && (e.clientY <= mousePosition.clientY) && (e.clientY >= (mousePosition.clientY - rightTreeMenuHeight))) {
+ this.props.itemUnregisterHandlers();
+ } else {
+ this.props.itemRegisterHandlers();
+ }
+ } else {
+ if ((e.clientX >= mousePosition.clientX) && (e.clientX <= (mousePosition.clientX + rightTreeMenuWidth)) && (e.clientY <= mousePosition.clientY) && (e.clientY >= (mousePosition.clientY - rightTreeMenuHeight))) {
+ this.props.itemUnregisterHandlers();
+ } else {
+ this.props.itemRegisterHandlers();
+ }
+ }
+ } else {
+ if (mousePosition.clientX + rightTreeMenuWidth > document.body.clientWidth) {
+ if ((e.clientX >= (mousePosition.clientX - rightTreeMenuWidth)) && (e.clientX <= mousePosition.clientX) && (e.clientY >= mousePosition.clientY) && (e.clientY <= (mousePosition.clientY + rightTreeMenuHeight))) {
+ this.props.itemUnregisterHandlers();
+ } else {
+ this.props.itemRegisterHandlers();
+ }
+ } else {
+ if ((e.clientX >= mousePosition.clientX) && (e.clientX <= (mousePosition.clientX + rightTreeMenuWidth)) && (e.clientY >= mousePosition.clientY) && (e.clientY <= (mousePosition.clientY + rightTreeMenuHeight))) {
+ this.props.itemUnregisterHandlers();
+ } else {
+ this.props.itemRegisterHandlers();
+ }
+ }
+ }
+ }
+
+ listenClick = (e) => {
+ let { mousePosition } = this.props;
+ let rightTreeMenu = document.querySelector('.right-tree-menu');
+ let rightTreeMenuHeight = rightTreeMenu.offsetHeight;
+ let rightTreeMenuWidth = rightTreeMenu.offsetWidth;
+
+ if (mousePosition.clientX + rightTreeMenuWidth > document.body.clientWidth) {
+ if (e.clientX <= (mousePosition.clientX - rightTreeMenuWidth) || e.clientX >= mousePosition.clientX) {
+ this.props.closeRightMenu();
+ }
+ } else {
+ if (e.clientX <= mousePosition.clientX || e.clientX >= (mousePosition.clientX + rightTreeMenuWidth)) {
+ this.props.closeRightMenu();
+ }
+ }
+
+ if (mousePosition.clientY + rightTreeMenuHeight > document.body.clientHeight) {
+ if ((e.clientY <= (mousePosition.clientY - rightTreeMenuHeight)) || e.clientY >= mousePosition.clientY) {
+ this.props.closeRightMenu();
+ }
+ } else {
+ if ((e.clientY <= mousePosition.clientY) || (e.clientY >= (mousePosition.clientY + rightTreeMenuHeight))) {
+ this.props.closeRightMenu();
+ }
+ }
+ }
+
+ onMenuItemClick = (event) => {
+ let operation = event.target.dataset.toggle;
+ if (operation === 'Share') {
+ this.props.onItemShare(event);
+ } else if (operation === 'Delete') {
+ this.props.onItemDelete(event);
+ } else if (operation === 'Download') {
+ this.props.onItemDownload(event);
+ } else if (operation === 'New Folder') {
+ this.props.onCreateFolderToggle()
+ } else if (operation === 'New File') {
+ this.props.onCreateFileToggle();
+ } else {
+ this.props.onMenuItemClick(operation);
+ }
+ this.props.closeRightMenu();
+ if(this.props.onUnfreezedItem){
+ this.props.onUnfreezedItem();
+ }
+ }
+
+ render() {
+ return (
+
+ {this.state.menuList.map((menuItem, index) => {
+ return (
+
+ );
+ })}
+
+ );
+ }
+}
+
+DirentRightMenu.propTypes = propTypes;
+
+export default DirentRightMenu;
diff --git a/frontend/src/components/tree-view/tree-node-menu.js b/frontend/src/components/tree-view/tree-node-menu.js
index d165bdfd01..337b7810c6 100644
--- a/frontend/src/components/tree-view/tree-node-menu.js
+++ b/frontend/src/components/tree-view/tree-node-menu.js
@@ -10,6 +10,7 @@ const propTypes = {
onUnFreezedItem: PropTypes.func.isRequired,
registerHandlers: PropTypes.func,
unregisterHandlers: PropTypes.func,
+ appMenuType: PropTypes.oneOf(['list_view_contextmenu', 'item_contextmenu', 'tree_contextmenu', 'item_op_menu']),
};
class TreeNodeMenu extends React.Component {
@@ -27,6 +28,13 @@ class TreeNodeMenu extends React.Component {
this.setState({menuList: menuList});
}
+ componentWillReceiveProps(nextProps) {
+ if (nextProps.appMenuType !== 'item_op_menu') {
+ this.setState({isItemMenuShow: false});
+ this.props.onUnFreezedItem();
+ }
+ }
+
caculateMenuList() {
let { node } = this.props;
let menuList = [];
@@ -93,8 +101,6 @@ class TreeNodeMenu extends React.Component {
}
render() {
- this.state.isItemMenuShow ? this.props.unregisterHandlers() : this.props.registerHandlers()
-
return (
{
if (!this.props.isItemFreezed) {
this.setState({
@@ -163,6 +173,7 @@ class TreeNodeView extends React.Component {
onNodeDrop={this.props.onNodeDrop}
onNodeDragEnter={this.props.onNodeDragEnter}
onNodeDragLeave={this.props.onNodeDragLeave}
+ appMenuType={this.props.appMenuType}
/>
);
})}
@@ -203,6 +214,7 @@ class TreeNodeView extends React.Component {
onFreezedItem={this.props.onFreezedItem}
registerHandlers={this.props.registerHandlers}
unregisterHandlers={this.props.unregisterHandlers}
+ appMenuType={this.props.appMenuType}
/>
)}
diff --git a/frontend/src/components/tree-view/tree-view.js b/frontend/src/components/tree-view/tree-view.js
index 687905e8ae..316cbdc877 100644
--- a/frontend/src/components/tree-view/tree-view.js
+++ b/frontend/src/components/tree-view/tree-view.js
@@ -15,6 +15,8 @@ const propTypes = {
onNodeCollapse: PropTypes.func.isRequired,
onItemMove: PropTypes.func,
currentRepoInfo: PropTypes.object,
+ switchAnotherMenuToShow: PropTypes.func,
+ appMenuType: PropTypes.oneOf(['list_view_contextmenu', 'item_contextmenu', 'tree_contextmenu', 'item_op_menu']),
};
const PADDING_LEFT = 20;
@@ -36,6 +38,10 @@ class TreeView extends React.Component {
this.registerHandlers();
}
+ componentDidUpdate() {
+ this.registerHandlers();
+ }
+
componentWillUnmount() {
this.unregisterHandlers();
}
@@ -100,6 +106,7 @@ class TreeView extends React.Component {
onFreezedItem = () => {
this.setState({isItemFreezed: true});
+ this.props.switchAnotherMenuToShow('item_op_menu');
}
onUnFreezedItem = () => {
@@ -108,16 +115,18 @@ class TreeView extends React.Component {
contextMenu = (e) => {
e.preventDefault();
+
+ this.props.switchAnotherMenuToShow('tree_contextmenu');
+
this.setState({
isRightMenuShow:false,
- });
- setTimeout(() => {
+ }, () => {
this.setState({
- isRightMenuShow:true,
- fileData:this.state.nodeData,
+ isRightMenuShow: true,
+ fileData: this.state.nodeData,
mousePosition: {clientX: e.clientX, clientY: e.clientY}
})
- },40)
+ })
}
unregisterHandlers = () => {
@@ -140,6 +149,7 @@ class TreeView extends React.Component {
this.setState({
isRightMenuShow:false,
})
+ this.onUnFreezedItem();
}
onMenuItemClick = (operation, node) => {
@@ -170,8 +180,9 @@ class TreeView extends React.Component {
onNodeDrop={this.onNodeDrop}
onNodeDragEnter={this.onNodeDragEnter}
onNodeDragLeave={this.onNodeDragLeave}
+ appMenuType={this.props.appMenuType}
/>
- {this.state.isRightMenuShow && (
+ {this.state.isRightMenuShow && this.props.appMenuType === 'tree_contextmenu' && (
{gettext('Folder does not exist.')});
@@ -117,6 +118,25 @@ class LibContentContainer extends React.Component {
this.props.closeDirentDetail();
}
+ switchAnotherMenuToShow = (type) => {
+ switch(type) {
+ case 'list_view_contextmenu':
+ this.setState({appMenuType: 'list_view_contextmenu'});
+ break;
+ case 'item_contextmenu':
+ this.setState({appMenuType: 'item_contextmenu'});
+ break;
+ case 'tree_contextmenu':
+ this.setState({appMenuType: 'tree_contextmenu'});
+ break;
+ case 'item_op_menu':
+ this.setState({appMenuType: 'item_op_menu'});
+ break;
+ default:
+ break;
+ }
+ }
+
componentWillReceiveProps (nextProps) {
if (nextProps.isDirentDetailShow) {
this.setState({
@@ -190,6 +210,9 @@ class LibContentContainer extends React.Component {
updateDirent={this.props.updateDirent}
isAllItemSelected={this.props.isAllDirentSelected}
onAllItemSelected={this.props.onAllDirentSelected}
+ appMenuType={this.state.appMenuType}
+ switchAnotherMenuToShow={this.switchAnotherMenuToShow}
+ onAddFolder={this.props.onAddFolder}
/>
)}
{this.props.currentMode === 'grid' && (
@@ -248,6 +271,9 @@ class LibContentContainer extends React.Component {
updateDirent={this.props.updateDirent}
isAllItemSelected={this.props.isAllDirentSelected}
onAllItemSelected={this.props.onAllDirentSelected}
+ appMenuType={this.state.appMenuType}
+ switchAnotherMenuToShow={this.switchAnotherMenuToShow}
+ onAddFolder={this.props.onAddFolder}
/>
)}