mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-04 08:28:11 +00:00
Support wiki page create/rename operations (#2295)
This commit is contained in:
committed by
Daniel Pan
parent
e4a255206f
commit
00388d3cda
@@ -100,6 +100,33 @@ class Node {
|
||||
return this.type == "dir";
|
||||
}
|
||||
|
||||
getleafPaths() {
|
||||
let paths = new Map();
|
||||
function getleafPath(node){
|
||||
if (node.hasChildren()) {
|
||||
let children = node.children;
|
||||
children.forEach(child => {
|
||||
if (child.hasChildren()) {
|
||||
getleafPath(child);
|
||||
} else {
|
||||
let path = child.path;
|
||||
paths.set(path,child);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
getleafPath(this);
|
||||
return paths;
|
||||
}
|
||||
|
||||
getNodeByPath(path) {
|
||||
let paths = this.getleafPaths();
|
||||
if (paths.has(path)) {
|
||||
return paths.get(path);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a JSON representation of the node.
|
||||
*
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import MenuControl from '../menu-component/node-menu-control'
|
||||
|
||||
function sortByType(a, b) {
|
||||
if (a.type == "dir" && b.type != "dir") {
|
||||
@@ -12,6 +13,69 @@ function sortByType(a, b) {
|
||||
|
||||
class TreeNodeView extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isMenuIconShow: false
|
||||
}
|
||||
}
|
||||
|
||||
onClick = (e) => {
|
||||
// e.nativeEvent.stopImmediatePropagation();
|
||||
let { node } = this.props;
|
||||
this.props.treeView.onNodeClick(e, node);
|
||||
}
|
||||
|
||||
onMouseEnter = () => {
|
||||
if (!this.props.isNodeItemFrezee) {
|
||||
this.setState({
|
||||
isMenuIconShow: true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
onMouseLeave = () => {
|
||||
if (!this.props.isNodeItemFrezee) {
|
||||
this.setState({
|
||||
isMenuIconShow: false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
handleCollapse = (e) => {
|
||||
e.stopPropagation();
|
||||
const { node } = this.props;
|
||||
if (this.props.treeView.toggleCollapse) {
|
||||
this.props.treeView.toggleCollapse(node);
|
||||
}
|
||||
}
|
||||
|
||||
onDragStart = (e) => {
|
||||
const { node } = this.props;
|
||||
this.props.treeView.onDragStart(e, node);
|
||||
}
|
||||
|
||||
onMenuControlClick = (e) => {
|
||||
e.stopPropagation();
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
const { node } = this.props;
|
||||
this.props.treeView.onShowContextMenu(e, node);
|
||||
}
|
||||
|
||||
hideMenuIcon = () => {
|
||||
this.setState({
|
||||
isMenuIconShow: false
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
document.addEventListener('click', this.hideMenuIcon);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
document.removeEventListener('click', this.hideMenuIcon);
|
||||
}
|
||||
|
||||
renderCollapse = () => {
|
||||
const { node } = this.props;
|
||||
|
||||
@@ -50,6 +114,8 @@ class TreeNodeView extends React.Component {
|
||||
key={child.path}
|
||||
paddingLeft={this.props.paddingLeft}
|
||||
treeView={this.props.treeView}
|
||||
isNodeItemFrezee={this.props.isNodeItemFrezee}
|
||||
permission={this.props.permission}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
@@ -60,16 +126,30 @@ class TreeNodeView extends React.Component {
|
||||
return null;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { node } = this.props;
|
||||
const styles = {};
|
||||
var icon, type;
|
||||
if (node.type === "dir") {
|
||||
renderMenuController() {
|
||||
if (this.props.permission === "rw") {
|
||||
return (
|
||||
<div className="right-icon">
|
||||
<MenuControl
|
||||
isShow={this.state.isMenuIconShow}
|
||||
onClick={this.onMenuControlClick}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
getNodeTypeAndIcon() {
|
||||
const node = this.props.node;
|
||||
let icon = '';
|
||||
let type = '';
|
||||
if (node.type === 'dir') {
|
||||
icon = <i className="far fa-folder"/>;
|
||||
type = 'dir';
|
||||
} else {
|
||||
} else {
|
||||
let index = node.name.lastIndexOf(".");
|
||||
if (index === -1) {
|
||||
if (index === -1) {
|
||||
icon = <i className="far fa-file"/>;
|
||||
type = 'file';
|
||||
} else {
|
||||
@@ -84,52 +164,37 @@ class TreeNodeView extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
return { type, icon };
|
||||
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
const styles = {};
|
||||
let node = this.props.node;
|
||||
let { type, icon } = this.getNodeTypeAndIcon();
|
||||
|
||||
return (
|
||||
<div type={type}
|
||||
className="tree-node"
|
||||
style={styles}
|
||||
>
|
||||
<div onMouseLeave={this.onMouseLeave} onMouseEnter={this.onMouseEnter}
|
||||
<div type={type} className="tree-node" style={styles}>
|
||||
<div
|
||||
onMouseLeave={this.onMouseLeave}
|
||||
onMouseEnter={this.onMouseEnter}
|
||||
onClick={this.onClick}
|
||||
type={type} className={`tree-node-inner text-nowrap ${node.name === '/'? 'hide': ''}`}>
|
||||
{this.renderCollapse()}
|
||||
<span type={type} className="tree-node-icon">
|
||||
{icon}
|
||||
</span>
|
||||
<span type={type} draggable="true" onDragStart={this.onDragStart}>{node.name}</span>
|
||||
type={type}
|
||||
className={`tree-node-inner text-nowrap ${node.name === '/'? 'hide': ''}`}
|
||||
>
|
||||
<div className="tree-node-text" type={type} draggable="true" onDragStart={this.onDragStart}>{node.name}</div>
|
||||
<div className="left-icon">
|
||||
{this.renderCollapse()}
|
||||
<i type={type} className="tree-node-icon">{icon}</i>
|
||||
</div>
|
||||
{this.renderMenuController()}
|
||||
</div>
|
||||
{node.isExpanded ? this.renderChildren() : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
onClick = e => {
|
||||
let { node } = this.props;
|
||||
this.props.treeView.onClick(e, node);
|
||||
}
|
||||
|
||||
onMouseEnter = e => {
|
||||
let { node } = this.props;
|
||||
this.props.treeView.showImagePreview(e, node);
|
||||
}
|
||||
|
||||
onMouseLeave = e => {
|
||||
this.props.treeView.hideImagePreview(e);
|
||||
}
|
||||
|
||||
handleCollapse = e => {
|
||||
e.stopPropagation();
|
||||
const { node } = this.props;
|
||||
if (this.props.treeView.toggleCollapse) {
|
||||
this.props.treeView.toggleCollapse(node);
|
||||
}
|
||||
}
|
||||
|
||||
onDragStart = e => {
|
||||
const { node } = this.props;
|
||||
this.props.treeView.onDragStart(e, node);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default TreeNodeView;
|
||||
|
@@ -1,110 +1,8 @@
|
||||
import React from 'react';
|
||||
import TreeNodeView from './tree-node-view';
|
||||
import Tree from './tree';
|
||||
|
||||
class TreeView extends React.PureComponent {
|
||||
|
||||
static defaultProps = {
|
||||
paddingLeft: 20
|
||||
};
|
||||
|
||||
imagePreviewTimeout = null
|
||||
|
||||
state = {
|
||||
tree: new Tree(),
|
||||
loadingFailed: false,
|
||||
imagePreviewPosition: {
|
||||
left: 10+'px',
|
||||
top: 10+'px'
|
||||
},
|
||||
isShowImagePreview: false,
|
||||
imagePreviewLoading: false,
|
||||
imageSrc: '',
|
||||
}
|
||||
|
||||
showImagePreview = (e, node) => {
|
||||
e.persist();
|
||||
|
||||
let type = e.target.getAttribute('type');
|
||||
if (type === 'image') {
|
||||
this.imagePreviewTimeout = setTimeout(() => {
|
||||
let X = e.clientX + 20;
|
||||
let Y = e.clientY - 55;
|
||||
if (e.view.innerHeight < e.clientY + 150) {
|
||||
Y = e.clientY - 219;
|
||||
}
|
||||
this.setState({
|
||||
isShowImagePreview: true,
|
||||
imagePreviewLoading: true,
|
||||
imageSrc: this.props.editorUtilities.getFileURL(node),
|
||||
imagePreviewPosition: {
|
||||
left: X + 'px',
|
||||
top: Y + 'px'
|
||||
}
|
||||
});
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
hideImagePreview = (e) => {
|
||||
clearTimeout(this.imagePreviewTimeout);
|
||||
this.setState({
|
||||
isShowImagePreview: false,
|
||||
imagePreviewLoading: false,
|
||||
});
|
||||
}
|
||||
|
||||
imageLoaded = () => {
|
||||
this.setState({
|
||||
imagePreviewLoading: false,
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.editorUtilities.getFiles().then((files) => {
|
||||
// construct the tree object
|
||||
var rootObj = {
|
||||
name: '/',
|
||||
type: 'dir',
|
||||
isExpanded: true
|
||||
}
|
||||
var treeData = new Tree();
|
||||
treeData.parseFromList(rootObj, files);
|
||||
this.setState({
|
||||
tree: treeData
|
||||
})
|
||||
}, () => {
|
||||
console.log("failed to load files");
|
||||
this.setState({
|
||||
loadingFailed: true
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const tree = this.state.tree;
|
||||
if (!tree.root) {
|
||||
return <div>Loading...</div>
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="tree-view tree">
|
||||
<TreeNodeView
|
||||
node={tree.root}
|
||||
paddingLeft={20}
|
||||
treeView={this}
|
||||
/>
|
||||
{ this.state.isShowImagePreview &&
|
||||
<div style={this.state.imagePreviewPosition} className={'image-view'}>
|
||||
{ this.state.imagePreviewLoading && <i className={'rotate fa fa-spinner'}/> }
|
||||
<img src={this.state.imageSrc} onLoad={this.imageLoaded} alt=""/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
change = (tree) => {
|
||||
/*
|
||||
this._updated = true;
|
||||
@@ -113,7 +11,7 @@ class TreeView extends React.PureComponent {
|
||||
}
|
||||
|
||||
toggleCollapse = (node) => {
|
||||
const tree = this.state.tree;
|
||||
const tree = this.props.treeData;
|
||||
node.isExpanded = !node.isExpanded;
|
||||
|
||||
// copy the tree to make PureComponent work
|
||||
@@ -130,12 +28,35 @@ class TreeView extends React.PureComponent {
|
||||
e.dataTransfer.setData("text/plain", url);
|
||||
}
|
||||
|
||||
onClick = (e, node) => {
|
||||
onNodeClick = (e, node) => {
|
||||
if (node.isDir()) {
|
||||
this.toggleCollapse(node);
|
||||
return;
|
||||
}
|
||||
this.props.onClick(e, node);
|
||||
this.props.onNodeClick(e, node);
|
||||
}
|
||||
|
||||
onShowContextMenu = (e, node) => {
|
||||
this.props.onShowContextMenu(e, node);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.props.treeData.root) {
|
||||
return <div>Loading...</div>
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="tree-view tree">
|
||||
<TreeNodeView
|
||||
paddingLeft={20}
|
||||
treeView={this}
|
||||
node={this.props.treeData.root}
|
||||
isNodeItemFrezee={this.props.isNodeItemFrezee}
|
||||
permission={this.props.permission}
|
||||
onShowContextMenu={this.props.onShowContextMenu}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user