2018-09-12 02:32:31 +00:00
|
|
|
import React, { Component } from 'react';
|
2018-10-16 10:19:51 +00:00
|
|
|
import PropTypes from 'prop-types';
|
2018-10-09 02:56:59 +00:00
|
|
|
import { gettext, siteRoot, logoPath, mediaUrl, siteTitle, logoWidth, logoHeight } from '../../utils/constants';
|
2018-09-12 02:32:31 +00:00
|
|
|
import TreeView from '../../components/tree-view/tree-view';
|
2018-10-16 06:27:21 +00:00
|
|
|
import NodeMenu from '../../components/tree-view/node-menu';
|
|
|
|
import MenuControl from '../../components/menu-control';
|
|
|
|
import Delete from '../../components/dialog/delete-dialog';
|
|
|
|
import Rename from '../../components/dialog/rename-dialog';
|
|
|
|
import CreateFolder from '../../components/dialog/create-folder-dialog';
|
|
|
|
import CreateFile from '../../components/dialog/create-file-dialog';
|
2018-09-12 02:32:31 +00:00
|
|
|
|
2018-10-16 10:19:51 +00:00
|
|
|
const propTypes = {
|
2018-11-22 03:26:00 +00:00
|
|
|
currentNode: PropTypes.object,
|
2018-10-16 10:19:51 +00:00
|
|
|
treeData: PropTypes.object.isRequired,
|
2018-11-22 03:26:00 +00:00
|
|
|
currentPath: PropTypes.string.isRequired,
|
2018-10-16 10:19:51 +00:00
|
|
|
closeSideBar: PropTypes.bool.isRequired,
|
|
|
|
onCloseSide: PropTypes.func.isRequired,
|
|
|
|
onDirCollapse: PropTypes.func.isRequired,
|
|
|
|
onNodeClick: PropTypes.func.isRequired,
|
|
|
|
onRenameNode: PropTypes.func.isRequired,
|
|
|
|
onDeleteNode: PropTypes.func.isRequired,
|
|
|
|
onAddFileNode: PropTypes.func.isRequired,
|
|
|
|
onAddFolderNode: PropTypes.func.isRequired,
|
|
|
|
};
|
|
|
|
|
2018-09-12 02:32:31 +00:00
|
|
|
class SidePanel extends Component {
|
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state = {
|
|
|
|
currentNode: null,
|
|
|
|
isNodeItemFrezee: false,
|
|
|
|
isShowMenu: false,
|
|
|
|
menuPosition: {
|
|
|
|
left: 0,
|
|
|
|
top: 0
|
|
|
|
},
|
|
|
|
isLoadFailed: false,
|
2018-09-12 06:15:27 +00:00
|
|
|
isMenuIconShow: false,
|
|
|
|
showDelete: false,
|
2018-10-16 06:27:21 +00:00
|
|
|
showFile: false,
|
|
|
|
showFolder: false,
|
2018-09-12 06:15:27 +00:00
|
|
|
showRename: false,
|
|
|
|
isFile: false
|
2018-09-29 10:32:53 +00:00
|
|
|
};
|
2018-09-12 02:32:31 +00:00
|
|
|
this.searchedPath = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
closeSide = () => {
|
|
|
|
this.props.onCloseSide();
|
|
|
|
}
|
|
|
|
|
|
|
|
onMouseEnter = () => {
|
|
|
|
this.setState({
|
|
|
|
isMenuIconShow: true
|
2018-09-29 10:32:53 +00:00
|
|
|
});
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
onMouseLeave = () => {
|
|
|
|
this.setState({
|
|
|
|
isMenuIconShow: false
|
2018-09-29 10:32:53 +00:00
|
|
|
});
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
onNodeClick = (node) => {
|
2018-09-29 10:32:53 +00:00
|
|
|
this.setState({currentNode: node});
|
2018-11-22 03:26:00 +00:00
|
|
|
this.props.onNodeClick(node);
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
onShowContextMenu = (e, node) => {
|
|
|
|
let left = e.clientX - 8*16;
|
|
|
|
let top = e.clientY + 10;
|
|
|
|
let position = Object.assign({},this.state.menuPosition, {left: left, top: top});
|
|
|
|
this.setState({
|
|
|
|
isShowMenu: !this.state.isShowMenu,
|
|
|
|
currentNode: node,
|
|
|
|
menuPosition: position,
|
|
|
|
isNodeItemFrezee: true
|
2018-09-29 10:32:53 +00:00
|
|
|
});
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
onHeadingMenuClick = (e) => {
|
|
|
|
e.nativeEvent.stopImmediatePropagation();
|
|
|
|
let node = this.props.treeData.root;
|
|
|
|
let left = e.clientX - 8*16;
|
|
|
|
let top = e.clientY + 10;
|
|
|
|
let position = Object.assign({},this.state.menuPosition, {left: left, top: top});
|
|
|
|
this.setState({
|
|
|
|
isShowMenu: !this.state.isShowMenu,
|
|
|
|
currentNode: node,
|
|
|
|
menuPosition: position
|
2018-09-29 10:32:53 +00:00
|
|
|
});
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
onHideContextMenu = () => {
|
2018-09-12 06:15:27 +00:00
|
|
|
if (!this.state.isShowMenu) {
|
|
|
|
return;
|
|
|
|
}
|
2018-09-12 02:32:31 +00:00
|
|
|
this.setState({
|
|
|
|
isShowMenu: false,
|
|
|
|
isNodeItemFrezee: false
|
2018-09-29 10:32:53 +00:00
|
|
|
});
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
2018-10-16 06:27:21 +00:00
|
|
|
toggleAddFile = () => {
|
|
|
|
this.setState({showFile: !this.state.showFile});
|
|
|
|
this.onHideContextMenu();
|
|
|
|
}
|
|
|
|
|
|
|
|
toggleAddFolder = () => {
|
|
|
|
this.setState({showFolder: !this.state.showFolder});
|
2018-09-12 06:15:27 +00:00
|
|
|
this.onHideContextMenu();
|
|
|
|
}
|
2018-11-22 03:26:00 +00:00
|
|
|
|
2018-09-12 06:15:27 +00:00
|
|
|
toggleRename = () => {
|
|
|
|
this.setState({showRename: !this.state.showRename});
|
|
|
|
this.onHideContextMenu();
|
|
|
|
}
|
2018-11-22 03:26:00 +00:00
|
|
|
|
2018-09-12 06:15:27 +00:00
|
|
|
toggleDelete = () => {
|
|
|
|
this.setState({showDelete: !this.state.showDelete});
|
|
|
|
this.onHideContextMenu();
|
|
|
|
}
|
|
|
|
|
2018-09-12 02:32:31 +00:00
|
|
|
onAddFolderNode = (dirPath) => {
|
2018-10-16 06:27:21 +00:00
|
|
|
this.setState({showFolder: !this.state.showFolder});
|
2018-09-12 02:32:31 +00:00
|
|
|
this.props.onAddFolderNode(dirPath);
|
|
|
|
}
|
2018-11-22 03:26:00 +00:00
|
|
|
|
2018-10-24 06:37:41 +00:00
|
|
|
onAddFileNode = (filePath, isDraft) => {
|
2018-10-16 06:27:21 +00:00
|
|
|
this.setState({showFile: !this.state.showFile});
|
2018-10-24 06:37:41 +00:00
|
|
|
this.props.onAddFileNode(filePath, isDraft);
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
2018-11-22 03:26:00 +00:00
|
|
|
|
2018-09-12 02:32:31 +00:00
|
|
|
onRenameNode = (newName) => {
|
2018-09-29 10:32:53 +00:00
|
|
|
this.setState({showRename: !this.state.showRename});
|
2018-09-12 02:32:31 +00:00
|
|
|
let node = this.state.currentNode;
|
2018-09-29 10:32:53 +00:00
|
|
|
this.props.onRenameNode(node, newName);
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
2018-11-22 03:26:00 +00:00
|
|
|
|
2018-09-12 02:32:31 +00:00
|
|
|
onDeleteNode = () => {
|
2018-09-29 10:32:53 +00:00
|
|
|
this.setState({showDelete: !this.state.showDelete});
|
2018-09-12 02:32:31 +00:00
|
|
|
let node = this.state.currentNode;
|
|
|
|
this.props.onDeleteNode(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
document.addEventListener('click', this.onHideContextMenu);
|
|
|
|
}
|
|
|
|
|
|
|
|
componentWillReceiveProps(nextProps) {
|
2018-11-22 03:26:00 +00:00
|
|
|
this.setState({currentNode: nextProps.currentNode});
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
|
document.removeEventListener('click', this.onHideContextMenu);
|
|
|
|
}
|
|
|
|
|
2018-09-12 06:15:27 +00:00
|
|
|
addFolderCancel = () => {
|
2018-10-16 06:27:21 +00:00
|
|
|
this.setState({showFolder: !this.state.showFolder});
|
2018-09-12 06:15:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
addFileCancel = () => {
|
2018-10-16 06:27:21 +00:00
|
|
|
this.setState({showFile: !this.state.showFile});
|
2018-09-12 06:15:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
deleteCancel = () => {
|
2018-09-29 10:32:53 +00:00
|
|
|
this.setState({showDelete: !this.state.showDelete});
|
2018-09-12 06:15:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
renameCancel = () => {
|
2018-09-29 10:32:53 +00:00
|
|
|
this.setState({showRename: !this.state.showRename});
|
2018-09-12 06:15:27 +00:00
|
|
|
}
|
|
|
|
|
2018-09-12 02:32:31 +00:00
|
|
|
render() {
|
|
|
|
return (
|
2018-09-29 10:32:53 +00:00
|
|
|
<div className={`side-panel wiki-side-panel ${this.props.closeSideBar ? '': 'left-zero'}`}>
|
2018-09-12 02:32:31 +00:00
|
|
|
<div className="side-panel-top panel-top">
|
|
|
|
<a href={siteRoot} id="logo">
|
|
|
|
<img src={mediaUrl + logoPath} title={siteTitle} alt="logo" width={logoWidth} height={logoHeight} />
|
|
|
|
</a>
|
|
|
|
<a title="Close" aria-label="Close" onClick={this.closeSide} className="sf2-icon-x1 sf-popover-close side-panel-close op-icon d-md-none "></a>
|
|
|
|
</div>
|
|
|
|
<div id="side-nav" className="wiki-side-nav" role="navigation">
|
2018-11-22 03:26:00 +00:00
|
|
|
<h3
|
|
|
|
className="wiki-pages-heading"
|
|
|
|
onMouseEnter={this.onMouseEnter}
|
2018-09-12 02:32:31 +00:00
|
|
|
onMouseLeave={this.onMouseLeave}
|
|
|
|
>
|
2018-09-29 10:32:53 +00:00
|
|
|
{gettext('Files')}
|
2018-09-12 02:32:31 +00:00
|
|
|
<div className="heading-icon">
|
2018-11-22 03:26:00 +00:00
|
|
|
<MenuControl
|
2018-09-12 02:32:31 +00:00
|
|
|
isShow={this.state.isMenuIconShow}
|
|
|
|
onClick={this.onHeadingMenuClick}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</h3>
|
|
|
|
<div className="wiki-pages-container">
|
2018-11-22 03:26:00 +00:00
|
|
|
{this.props.treeData &&
|
2018-09-12 02:32:31 +00:00
|
|
|
<TreeView
|
2018-11-22 03:26:00 +00:00
|
|
|
currentPath={this.props.currentPath}
|
2018-09-12 02:32:31 +00:00
|
|
|
treeData={this.props.treeData}
|
|
|
|
currentNode={this.state.currentNode}
|
|
|
|
isNodeItemFrezee={this.state.isNodeItemFrezee}
|
|
|
|
onNodeClick={this.onNodeClick}
|
|
|
|
onShowContextMenu={this.onShowContextMenu}
|
|
|
|
onDirCollapse={this.props.onDirCollapse}
|
|
|
|
/>
|
|
|
|
}
|
2018-11-22 03:26:00 +00:00
|
|
|
{this.state.isShowMenu &&
|
|
|
|
<NodeMenu
|
2018-09-12 02:32:31 +00:00
|
|
|
menuPosition={this.state.menuPosition}
|
|
|
|
currentNode={this.state.currentNode}
|
2018-10-16 06:27:21 +00:00
|
|
|
toggleAddFile={this.toggleAddFile}
|
|
|
|
toggleAddFolder={this.toggleAddFolder}
|
2018-09-12 06:15:27 +00:00
|
|
|
toggleRename={this.toggleRename}
|
|
|
|
toggleDelete={this.toggleDelete}
|
|
|
|
/>
|
|
|
|
}
|
|
|
|
{this.state.showDelete &&
|
2018-11-22 03:26:00 +00:00
|
|
|
<Delete
|
2018-09-12 06:15:27 +00:00
|
|
|
currentNode={this.state.currentNode}
|
|
|
|
handleSubmit={this.onDeleteNode}
|
|
|
|
toggleCancel={this.deleteCancel}
|
2018-09-12 02:32:31 +00:00
|
|
|
/>
|
2018-09-12 06:15:27 +00:00
|
|
|
}
|
2018-11-22 03:26:00 +00:00
|
|
|
{this.state.showFile &&
|
2018-10-16 06:27:21 +00:00
|
|
|
<CreateFile
|
|
|
|
fileType={'.md'}
|
|
|
|
parentPath={this.state.currentNode.path}
|
2018-09-12 06:15:27 +00:00
|
|
|
onAddFile={this.onAddFileNode}
|
|
|
|
addFileCancel={this.addFileCancel}
|
|
|
|
/>
|
|
|
|
}
|
2018-10-16 06:27:21 +00:00
|
|
|
{this.state.showFolder &&
|
2018-11-22 03:26:00 +00:00
|
|
|
<CreateFolder
|
2018-10-16 06:27:21 +00:00
|
|
|
parentPath={this.state.currentNode.path}
|
|
|
|
onAddFolder={this.onAddFolderNode}
|
|
|
|
addFolderCancel={this.addFolderCancel}
|
|
|
|
/>
|
|
|
|
}
|
2018-09-12 06:15:27 +00:00
|
|
|
{this.state.showRename &&
|
2018-11-22 03:26:00 +00:00
|
|
|
<Rename
|
2018-09-12 06:15:27 +00:00
|
|
|
currentNode={this.state.currentNode}
|
2018-11-22 03:26:00 +00:00
|
|
|
onRename={this.onRenameNode}
|
|
|
|
toggleCancel={this.renameCancel}
|
2018-09-12 06:15:27 +00:00
|
|
|
/>
|
|
|
|
}
|
2018-09-12 02:32:31 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2018-09-29 10:32:53 +00:00
|
|
|
);
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
}
|
2018-10-16 10:19:51 +00:00
|
|
|
|
|
|
|
SidePanel.propTypes = propTypes;
|
|
|
|
|
2018-09-12 02:32:31 +00:00
|
|
|
export default SidePanel;
|