mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-01 23:20:51 +00:00
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
This commit is contained in:
@@ -32,6 +32,8 @@ const propTypes = {
|
|||||||
navRate: PropTypes.number,
|
navRate: PropTypes.number,
|
||||||
inResizing: PropTypes.bool.isRequired,
|
inResizing: PropTypes.bool.isRequired,
|
||||||
currentRepoInfo: PropTypes.object.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 {
|
class DirColumnNav extends React.Component {
|
||||||
@@ -282,6 +284,8 @@ class DirColumnNav extends React.Component {
|
|||||||
onUnFreezedItem={this.onUnFreezedItem}
|
onUnFreezedItem={this.onUnFreezedItem}
|
||||||
onItemMove={this.props.onItemMove}
|
onItemMove={this.props.onItemMove}
|
||||||
currentRepoInfo={this.props.currentRepoInfo}
|
currentRepoInfo={this.props.currentRepoInfo}
|
||||||
|
switchAnotherMenuToShow={this.props.switchAnotherMenuToShow}
|
||||||
|
appMenuType={this.props.appMenuType}
|
||||||
/>)
|
/>)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -63,6 +63,8 @@ const propTypes = {
|
|||||||
onDirentClick: PropTypes.func.isRequired,
|
onDirentClick: PropTypes.func.isRequired,
|
||||||
isAllItemSelected: PropTypes.bool.isRequired,
|
isAllItemSelected: PropTypes.bool.isRequired,
|
||||||
onAllItemSelected: PropTypes.func.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 {
|
class DirColumnView extends React.Component {
|
||||||
@@ -165,6 +167,8 @@ class DirColumnView extends React.Component {
|
|||||||
currentRepoInfo={this.props.currentRepoInfo}
|
currentRepoInfo={this.props.currentRepoInfo}
|
||||||
onItemMove={this.props.onItemMove}
|
onItemMove={this.props.onItemMove}
|
||||||
onItemCopy={this.props.onItemCopy}
|
onItemCopy={this.props.onItemCopy}
|
||||||
|
switchAnotherMenuToShow={this.props.switchAnotherMenuToShow}
|
||||||
|
appMenuType={this.props.appMenuType}
|
||||||
/>
|
/>
|
||||||
<div className="dir-content-resize" onMouseDown={this.onResizeMouseDown}></div>
|
<div className="dir-content-resize" onMouseDown={this.onResizeMouseDown}></div>
|
||||||
<div className="dir-content-main" style={{userSelect: select, flex: mainFlex}}>
|
<div className="dir-content-main" style={{userSelect: select, flex: mainFlex}}>
|
||||||
@@ -213,6 +217,9 @@ class DirColumnView extends React.Component {
|
|||||||
updateDirent={this.props.updateDirent}
|
updateDirent={this.props.updateDirent}
|
||||||
isAllItemSelected={this.props.isAllItemSelected}
|
isAllItemSelected={this.props.isAllItemSelected}
|
||||||
onAllItemSelected={this.props.onAllItemSelected}
|
onAllItemSelected={this.props.onAllItemSelected}
|
||||||
|
switchAnotherMenuToShow={this.props.switchAnotherMenuToShow}
|
||||||
|
appMenuType={this.props.appMenuType}
|
||||||
|
onAddFolder={this.props.onAddFolder}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,7 +1,11 @@
|
|||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import RepoInfoBar from '../../components/repo-info-bar';
|
import RepoInfoBar from '../../components/repo-info-bar';
|
||||||
|
import ModalPortal from '../modal-portal';
|
||||||
import DirentListView from '../../components/dirent-list-view/dirent-list-view';
|
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 = {
|
const propTypes = {
|
||||||
path: PropTypes.string.isRequired,
|
path: PropTypes.string.isRequired,
|
||||||
@@ -31,9 +35,94 @@ const propTypes = {
|
|||||||
updateDirent: PropTypes.func.isRequired,
|
updateDirent: PropTypes.func.isRequired,
|
||||||
isAllItemSelected: PropTypes.bool.isRequired,
|
isAllItemSelected: PropTypes.bool.isRequired,
|
||||||
onAllItemSelected: PropTypes.func.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 {
|
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() {
|
render() {
|
||||||
return (
|
return (
|
||||||
@@ -48,30 +137,65 @@ class DirListView extends React.Component {
|
|||||||
updateUsedRepoTags={this.props.updateUsedRepoTags}
|
updateUsedRepoTags={this.props.updateUsedRepoTags}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<DirentListView
|
<div className="table-container">
|
||||||
path={this.props.path}
|
<DirentListView
|
||||||
currentRepoInfo={this.props.currentRepoInfo}
|
path={this.props.path}
|
||||||
repoID={this.props.repoID}
|
currentRepoInfo={this.props.currentRepoInfo}
|
||||||
isGroupOwnedRepo={this.props.isGroupOwnedRepo}
|
repoID={this.props.repoID}
|
||||||
enableDirPrivateShare={this.props.enableDirPrivateShare}
|
isGroupOwnedRepo={this.props.isGroupOwnedRepo}
|
||||||
direntList={this.props.direntList}
|
enableDirPrivateShare={this.props.enableDirPrivateShare}
|
||||||
sortBy={this.props.sortBy}
|
direntList={this.props.direntList}
|
||||||
sortOrder={this.props.sortOrder}
|
sortBy={this.props.sortBy}
|
||||||
sortItems={this.props.sortItems}
|
sortOrder={this.props.sortOrder}
|
||||||
onAddFile={this.props.onAddFile}
|
sortItems={this.props.sortItems}
|
||||||
onItemClick={this.props.onItemClick}
|
onAddFile={this.props.onAddFile}
|
||||||
onItemSelected={this.props.onItemSelected}
|
onItemClick={this.props.onItemClick}
|
||||||
onItemDelete={this.props.onItemDelete}
|
onItemSelected={this.props.onItemSelected}
|
||||||
onItemRename={this.props.onItemRename}
|
onItemDelete={this.props.onItemDelete}
|
||||||
onItemMove={this.props.onItemMove}
|
onItemRename={this.props.onItemRename}
|
||||||
onItemCopy={this.props.onItemCopy}
|
onItemMove={this.props.onItemMove}
|
||||||
onDirentClick={this.props.onDirentClick}
|
onItemCopy={this.props.onItemCopy}
|
||||||
onItemDetails={this.props.onItemDetails}
|
onDirentClick={this.props.onDirentClick}
|
||||||
isDirentListLoading={this.props.isDirentListLoading}
|
onItemDetails={this.props.onItemDetails}
|
||||||
updateDirent={this.props.updateDirent}
|
isDirentListLoading={this.props.isDirentListLoading}
|
||||||
isAllItemSelected={this.props.isAllItemSelected}
|
updateDirent={this.props.updateDirent}
|
||||||
onAllItemSelected={this.props.onAllItemSelected}
|
isAllItemSelected={this.props.isAllItemSelected}
|
||||||
/>
|
onAllItemSelected={this.props.onAllItemSelected}
|
||||||
|
switchAnotherMenuToShow={this.props.switchAnotherMenuToShow}
|
||||||
|
appMenuType={this.props.appMenuType}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{this.state.isContainerContextmenuShow && this.props.appMenuType === 'list_view_contextmenu' && (
|
||||||
|
<DirentListMenu
|
||||||
|
mousePosition={this.state.itemMousePosition}
|
||||||
|
itemUnregisterHandlers={this.unregisterTableContainerContextmenuHandler}
|
||||||
|
itemRegisterHandlers={this.registerTableContainerContextmenuHandler}
|
||||||
|
closeRightMenu={this.closeTableContainerRightMenu}
|
||||||
|
onCreateFolderToggle={this.onCreateFolderToggle}
|
||||||
|
onCreateFileToggle={this.onCreateFileToggle}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{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}
|
||||||
|
fileType={this.state.fileType}
|
||||||
|
onAddFile={this.onAddFile}
|
||||||
|
checkDuplicatedName={this.checkDuplicatedName}
|
||||||
|
addFileCancel={this.onCreateFileToggle}
|
||||||
|
/>
|
||||||
|
</ModalPortal>
|
||||||
|
)}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,7 @@ import ZipDownloadDialog from '../dialog/zip-download-dialog';
|
|||||||
import MoveDirentDialog from '../dialog/move-dirent-dialog';
|
import MoveDirentDialog from '../dialog/move-dirent-dialog';
|
||||||
import CopyDirentDialog from '../dialog/copy-dirent-dialog';
|
import CopyDirentDialog from '../dialog/copy-dirent-dialog';
|
||||||
import ShareDialog from '../dialog/share-dialog';
|
import ShareDialog from '../dialog/share-dialog';
|
||||||
|
import DirentRightMenu from './dirent-right-menu';
|
||||||
|
|
||||||
import '../../css/dirent-list-item.css';
|
import '../../css/dirent-list-item.css';
|
||||||
|
|
||||||
@@ -39,6 +40,8 @@ const propTypes = {
|
|||||||
isAdmin: PropTypes.bool.isRequired,
|
isAdmin: PropTypes.bool.isRequired,
|
||||||
repoEncrypted: PropTypes.bool.isRequired,
|
repoEncrypted: PropTypes.bool.isRequired,
|
||||||
isGroupOwnedRepo: 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 {
|
class DirentListItem extends React.Component {
|
||||||
@@ -57,10 +60,70 @@ class DirentListItem extends React.Component {
|
|||||||
isShowTagTooltip: false,
|
isShowTagTooltip: false,
|
||||||
isDragTipShow: false,
|
isDragTipShow: false,
|
||||||
isDropTipshow: false,
|
isDropTipshow: false,
|
||||||
|
enterItemData: '',
|
||||||
|
enterItemIndex: -1,
|
||||||
|
contextmenuItemData: {},
|
||||||
|
contextmenuItemIndex: -1,
|
||||||
|
isItemContextMenuShow: false,
|
||||||
};
|
};
|
||||||
this.zipToken = null;
|
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
|
//UI Interactive
|
||||||
onMouseEnter = () => {
|
onMouseEnter = () => {
|
||||||
if (!this.props.isItemFreezed) {
|
if (!this.props.isItemFreezed) {
|
||||||
@@ -69,7 +132,11 @@ class DirentListItem extends React.Component {
|
|||||||
isOperationShow: true,
|
isOperationShow: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.setState({isDragTipShow: true});
|
this.setState({
|
||||||
|
isDragTipShow: true,
|
||||||
|
enterItemData: this.props.dirent,
|
||||||
|
enterItemIndex: this.props.itemIndex,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseOver = () => {
|
onMouseOver = () => {
|
||||||
@@ -79,7 +146,10 @@ class DirentListItem extends React.Component {
|
|||||||
isOperationShow: true,
|
isOperationShow: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.setState({isDragTipShow: true});
|
this.setState({
|
||||||
|
isDragTipShow: true,
|
||||||
|
enterItemData: this.props.dirent,
|
||||||
|
enterItemIndex: this.props.itemIndex});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseLeave = () => {
|
onMouseLeave = () => {
|
||||||
@@ -89,7 +159,11 @@ class DirentListItem extends React.Component {
|
|||||||
isOperationShow: false,
|
isOperationShow: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.setState({isDragTipShow: false});
|
this.setState({
|
||||||
|
isDragTipShow: false,
|
||||||
|
enterItemData: '',
|
||||||
|
enterItemIndex: -1,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onUnfreezedItem = () => {
|
onUnfreezedItem = () => {
|
||||||
@@ -209,7 +283,7 @@ class DirentListItem extends React.Component {
|
|||||||
|
|
||||||
onRenameCancel = () => {
|
onRenameCancel = () => {
|
||||||
this.setState({isRenameing: false});
|
this.setState({isRenameing: false});
|
||||||
this.props.onUnfreezedItem();
|
this.onUnfreezedItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemMoveToggle = () => {
|
onItemMoveToggle = () => {
|
||||||
@@ -484,11 +558,29 @@ class DirentListItem extends React.Component {
|
|||||||
isRepoOwner={this.props.isRepoOwner}
|
isRepoOwner={this.props.isRepoOwner}
|
||||||
onFreezedItem={this.props.onFreezedItem}
|
onFreezedItem={this.props.onFreezedItem}
|
||||||
onUnfreezedItem={this.onUnfreezedItem}
|
onUnfreezedItem={this.onUnfreezedItem}
|
||||||
|
appMenuType={this.props.appMenuType}
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
{this.state.isItemContextMenuShow && this.state.contextmenuItemIndex === this.props.itemIndex && this.props.appMenuType === 'item_contextmenu' &&
|
||||||
|
<DirentRightMenu
|
||||||
|
dirent={this.state.contextmenuItemData}
|
||||||
|
mousePosition={this.state.itemMousePosition}
|
||||||
|
isRepoOwner={this.props.isRepoOwner}
|
||||||
|
currentRepoInfo={this.props.currentRepoInfo}
|
||||||
|
onMenuItemClick={this.onMenuItemClick}
|
||||||
|
onItemDownload={this.onItemDownload}
|
||||||
|
onItemShare={this.onItemShare}
|
||||||
|
onItemDelete={this.onItemDelete}
|
||||||
|
itemRegisterHandlers={this.itemRegisterHandlers}
|
||||||
|
itemUnregisterHandlers={this.itemUnregisterHandlers}
|
||||||
|
closeRightMenu={this.closeRightMenu}
|
||||||
|
onUnfreezedItem={this.onUnfreezedItem}
|
||||||
|
showShare={showShare}
|
||||||
|
/>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
<td className="file-size">{dirent.size && dirent.size}</td>
|
<td className="file-size">{dirent.size && dirent.size}</td>
|
||||||
<td className="last-update">{dirent.mtime_relative}</td>
|
<td className="last-update">{dirent.mtime_relative}</td>
|
||||||
|
@@ -34,6 +34,8 @@ const propTypes = {
|
|||||||
onDirentClick: PropTypes.func.isRequired,
|
onDirentClick: PropTypes.func.isRequired,
|
||||||
onItemDetails: PropTypes.func.isRequired,
|
onItemDetails: PropTypes.func.isRequired,
|
||||||
updateDirent: 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 {
|
class DirentListView extends React.Component {
|
||||||
@@ -48,7 +50,7 @@ class DirentListView extends React.Component {
|
|||||||
imageIndex: 0,
|
imageIndex: 0,
|
||||||
|
|
||||||
isCreateFileDialogShow: false,
|
isCreateFileDialogShow: false,
|
||||||
fileType: ''
|
fileType: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
this.isRepoOwner = props.currentRepoInfo.owner_email === username;
|
this.isRepoOwner = props.currentRepoInfo.owner_email === username;
|
||||||
@@ -56,6 +58,23 @@ class DirentListView extends React.Component {
|
|||||||
this.repoEncrypted = props.currentRepoInfo.encrypted;
|
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 = () => {
|
onFreezedItem = () => {
|
||||||
this.setState({isItemFreezed: true});
|
this.setState({isItemFreezed: true});
|
||||||
}
|
}
|
||||||
@@ -254,7 +273,7 @@ class DirentListView extends React.Component {
|
|||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th width="3%" className="pl10">
|
<th width="3%" className="pl10">
|
||||||
<input type="checkbox" className="vam" onChange={this.props.onAllItemSelected} checked={this.props.isAllItemSelected}/>
|
<input type="checkbox" className="vam" onChange={this.props.onAllItemSelected} checked={this.props.isAllItemSelected}/>
|
||||||
</th>
|
</th>
|
||||||
<th width="3%" className="pl10">{/*icon */}</th>
|
<th width="3%" className="pl10">{/*icon */}</th>
|
||||||
@@ -296,6 +315,9 @@ class DirentListView extends React.Component {
|
|||||||
onDirentClick={this.props.onDirentClick}
|
onDirentClick={this.props.onDirentClick}
|
||||||
onItemDetails={this.onItemDetails}
|
onItemDetails={this.onItemDetails}
|
||||||
showImagePopup={this.showImagePopup}
|
showImagePopup={this.showImagePopup}
|
||||||
|
switchAnotherMenuToShow={this.props.switchAnotherMenuToShow}
|
||||||
|
appMenuType={this.props.appMenuType}
|
||||||
|
itemIndex={index}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
@@ -10,6 +10,7 @@ const propTypes = {
|
|||||||
onMenuItemClick: PropTypes.func.isRequired,
|
onMenuItemClick: PropTypes.func.isRequired,
|
||||||
onFreezedItem: PropTypes.func.isRequired,
|
onFreezedItem: PropTypes.func.isRequired,
|
||||||
onUnfreezedItem: 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 {
|
class DirentMenu extends React.Component {
|
||||||
@@ -26,6 +27,12 @@ class DirentMenu extends React.Component {
|
|||||||
this.menuList = this.calculateMenuList();
|
this.menuList = this.calculateMenuList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProp) {
|
||||||
|
if (nextProp.appMenuType === 'list_view_contextmenu' || nextProp.appMenuType === 'item_contextmenu') {
|
||||||
|
this.setState({isItemMenuShow: false});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
calculateMenuList() {
|
calculateMenuList() {
|
||||||
let { currentRepoInfo, dirent, isRepoOwner } = this.props;
|
let { currentRepoInfo, dirent, isRepoOwner } = this.props;
|
||||||
|
|
||||||
|
291
frontend/src/components/dirent-list-view/dirent-right-menu.js
Normal file
291
frontend/src/components/dirent-list-view/dirent-right-menu.js
Normal file
@@ -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 (
|
||||||
|
<div className='right-tree-menu'>
|
||||||
|
{this.state.menuList.map((menuItem, index) => {
|
||||||
|
return (
|
||||||
|
<button className='right-tree-item' key={index} data-toggle={menuItem} onClick={this.onMenuItemClick}>{this.translateMenuItem(menuItem)}</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DirentRightMenu.propTypes = propTypes;
|
||||||
|
|
||||||
|
export default DirentRightMenu;
|
@@ -10,6 +10,7 @@ const propTypes = {
|
|||||||
onUnFreezedItem: PropTypes.func.isRequired,
|
onUnFreezedItem: PropTypes.func.isRequired,
|
||||||
registerHandlers: PropTypes.func,
|
registerHandlers: PropTypes.func,
|
||||||
unregisterHandlers: PropTypes.func,
|
unregisterHandlers: PropTypes.func,
|
||||||
|
appMenuType: PropTypes.oneOf(['list_view_contextmenu', 'item_contextmenu', 'tree_contextmenu', 'item_op_menu']),
|
||||||
};
|
};
|
||||||
|
|
||||||
class TreeNodeMenu extends React.Component {
|
class TreeNodeMenu extends React.Component {
|
||||||
@@ -27,6 +28,13 @@ class TreeNodeMenu extends React.Component {
|
|||||||
this.setState({menuList: menuList});
|
this.setState({menuList: menuList});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if (nextProps.appMenuType !== 'item_op_menu') {
|
||||||
|
this.setState({isItemMenuShow: false});
|
||||||
|
this.props.onUnFreezedItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
caculateMenuList() {
|
caculateMenuList() {
|
||||||
let { node } = this.props;
|
let { node } = this.props;
|
||||||
let menuList = [];
|
let menuList = [];
|
||||||
@@ -93,8 +101,6 @@ class TreeNodeMenu extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
this.state.isItemMenuShow ? this.props.unregisterHandlers() : this.props.registerHandlers()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dropdown isOpen={this.state.isItemMenuShow} toggle={this.toggleOperationMenu}>
|
<Dropdown isOpen={this.state.isItemMenuShow} toggle={this.toggleOperationMenu}>
|
||||||
<DropdownToggle
|
<DropdownToggle
|
||||||
|
@@ -21,6 +21,7 @@ const propTypes = {
|
|||||||
unregisterHandlers: PropTypes.func,
|
unregisterHandlers: PropTypes.func,
|
||||||
onNodeDragMove: PropTypes.func,
|
onNodeDragMove: PropTypes.func,
|
||||||
onNodeDrop: PropTypes.func,
|
onNodeDrop: PropTypes.func,
|
||||||
|
appMenuType: PropTypes.oneOf(['list_view_contextmenu', 'item_contextmenu', 'tree_contextmenu', 'item_op_menu']),
|
||||||
};
|
};
|
||||||
|
|
||||||
class TreeNodeView extends React.Component {
|
class TreeNodeView extends React.Component {
|
||||||
@@ -34,6 +35,15 @@ class TreeNodeView extends React.Component {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProp) {
|
||||||
|
if (nextProp.appMenuType === 'list_view_contextmenu' && nextProp.appMenuType === 'item_contextmenu') {
|
||||||
|
this.setState({
|
||||||
|
isShowOperationMenu: false,
|
||||||
|
isHighlight: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMouseEnter = () => {
|
onMouseEnter = () => {
|
||||||
if (!this.props.isItemFreezed) {
|
if (!this.props.isItemFreezed) {
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -163,6 +173,7 @@ class TreeNodeView extends React.Component {
|
|||||||
onNodeDrop={this.props.onNodeDrop}
|
onNodeDrop={this.props.onNodeDrop}
|
||||||
onNodeDragEnter={this.props.onNodeDragEnter}
|
onNodeDragEnter={this.props.onNodeDragEnter}
|
||||||
onNodeDragLeave={this.props.onNodeDragLeave}
|
onNodeDragLeave={this.props.onNodeDragLeave}
|
||||||
|
appMenuType={this.props.appMenuType}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -203,6 +214,7 @@ class TreeNodeView extends React.Component {
|
|||||||
onFreezedItem={this.props.onFreezedItem}
|
onFreezedItem={this.props.onFreezedItem}
|
||||||
registerHandlers={this.props.registerHandlers}
|
registerHandlers={this.props.registerHandlers}
|
||||||
unregisterHandlers={this.props.unregisterHandlers}
|
unregisterHandlers={this.props.unregisterHandlers}
|
||||||
|
appMenuType={this.props.appMenuType}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -15,6 +15,8 @@ const propTypes = {
|
|||||||
onNodeCollapse: PropTypes.func.isRequired,
|
onNodeCollapse: PropTypes.func.isRequired,
|
||||||
onItemMove: PropTypes.func,
|
onItemMove: PropTypes.func,
|
||||||
currentRepoInfo: PropTypes.object,
|
currentRepoInfo: PropTypes.object,
|
||||||
|
switchAnotherMenuToShow: PropTypes.func,
|
||||||
|
appMenuType: PropTypes.oneOf(['list_view_contextmenu', 'item_contextmenu', 'tree_contextmenu', 'item_op_menu']),
|
||||||
};
|
};
|
||||||
|
|
||||||
const PADDING_LEFT = 20;
|
const PADDING_LEFT = 20;
|
||||||
@@ -36,6 +38,10 @@ class TreeView extends React.Component {
|
|||||||
this.registerHandlers();
|
this.registerHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
this.registerHandlers();
|
||||||
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.unregisterHandlers();
|
this.unregisterHandlers();
|
||||||
}
|
}
|
||||||
@@ -100,6 +106,7 @@ class TreeView extends React.Component {
|
|||||||
|
|
||||||
onFreezedItem = () => {
|
onFreezedItem = () => {
|
||||||
this.setState({isItemFreezed: true});
|
this.setState({isItemFreezed: true});
|
||||||
|
this.props.switchAnotherMenuToShow('item_op_menu');
|
||||||
}
|
}
|
||||||
|
|
||||||
onUnFreezedItem = () => {
|
onUnFreezedItem = () => {
|
||||||
@@ -108,16 +115,18 @@ class TreeView extends React.Component {
|
|||||||
|
|
||||||
contextMenu = (e) => {
|
contextMenu = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
this.props.switchAnotherMenuToShow('tree_contextmenu');
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
isRightMenuShow:false,
|
isRightMenuShow:false,
|
||||||
});
|
}, () => {
|
||||||
setTimeout(() => {
|
|
||||||
this.setState({
|
this.setState({
|
||||||
isRightMenuShow:true,
|
isRightMenuShow: true,
|
||||||
fileData:this.state.nodeData,
|
fileData: this.state.nodeData,
|
||||||
mousePosition: {clientX: e.clientX, clientY: e.clientY}
|
mousePosition: {clientX: e.clientX, clientY: e.clientY}
|
||||||
})
|
})
|
||||||
},40)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
unregisterHandlers = () => {
|
unregisterHandlers = () => {
|
||||||
@@ -140,6 +149,7 @@ class TreeView extends React.Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
isRightMenuShow:false,
|
isRightMenuShow:false,
|
||||||
})
|
})
|
||||||
|
this.onUnFreezedItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
onMenuItemClick = (operation, node) => {
|
onMenuItemClick = (operation, node) => {
|
||||||
@@ -170,8 +180,9 @@ class TreeView extends React.Component {
|
|||||||
onNodeDrop={this.onNodeDrop}
|
onNodeDrop={this.onNodeDrop}
|
||||||
onNodeDragEnter={this.onNodeDragEnter}
|
onNodeDragEnter={this.onNodeDragEnter}
|
||||||
onNodeDragLeave={this.onNodeDragLeave}
|
onNodeDragLeave={this.onNodeDragLeave}
|
||||||
|
appMenuType={this.props.appMenuType}
|
||||||
/>
|
/>
|
||||||
{this.state.isRightMenuShow && (
|
{this.state.isRightMenuShow && this.props.appMenuType === 'tree_contextmenu' && (
|
||||||
<TreeViewContextMenu
|
<TreeViewContextMenu
|
||||||
node={this.state.fileData}
|
node={this.state.fileData}
|
||||||
onMenuItemClick={this.onMenuItemClick}
|
onMenuItemClick={this.onMenuItemClick}
|
||||||
|
@@ -110,6 +110,12 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cur-view-content .article {
|
.cur-view-content .article {
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
.right-tree-menu {
|
.right-tree-menu {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 15rem;
|
left: -1000rem;
|
||||||
top: 20rem;
|
top: -1000rem;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
float: left;
|
float: left;
|
||||||
min-width: 10rem;
|
min-width: 10rem;
|
||||||
|
@@ -84,6 +84,7 @@ class LibContentContainer extends React.Component {
|
|||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
currentDirent: null,
|
currentDirent: null,
|
||||||
|
appMenuType: 'item_op_menu',
|
||||||
};
|
};
|
||||||
|
|
||||||
this.errMessage = (<div className="message err-tip">{gettext('Folder does not exist.')}</div>);
|
this.errMessage = (<div className="message err-tip">{gettext('Folder does not exist.')}</div>);
|
||||||
@@ -117,6 +118,25 @@ class LibContentContainer extends React.Component {
|
|||||||
this.props.closeDirentDetail();
|
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) {
|
componentWillReceiveProps (nextProps) {
|
||||||
if (nextProps.isDirentDetailShow) {
|
if (nextProps.isDirentDetailShow) {
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -190,6 +210,9 @@ class LibContentContainer extends React.Component {
|
|||||||
updateDirent={this.props.updateDirent}
|
updateDirent={this.props.updateDirent}
|
||||||
isAllItemSelected={this.props.isAllDirentSelected}
|
isAllItemSelected={this.props.isAllDirentSelected}
|
||||||
onAllItemSelected={this.props.onAllDirentSelected}
|
onAllItemSelected={this.props.onAllDirentSelected}
|
||||||
|
appMenuType={this.state.appMenuType}
|
||||||
|
switchAnotherMenuToShow={this.switchAnotherMenuToShow}
|
||||||
|
onAddFolder={this.props.onAddFolder}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{this.props.currentMode === 'grid' && (
|
{this.props.currentMode === 'grid' && (
|
||||||
@@ -248,6 +271,9 @@ class LibContentContainer extends React.Component {
|
|||||||
updateDirent={this.props.updateDirent}
|
updateDirent={this.props.updateDirent}
|
||||||
isAllItemSelected={this.props.isAllDirentSelected}
|
isAllItemSelected={this.props.isAllDirentSelected}
|
||||||
onAllItemSelected={this.props.onAllDirentSelected}
|
onAllItemSelected={this.props.onAllDirentSelected}
|
||||||
|
appMenuType={this.state.appMenuType}
|
||||||
|
switchAnotherMenuToShow={this.switchAnotherMenuToShow}
|
||||||
|
onAddFolder={this.props.onAddFolder}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
Reference in New Issue
Block a user