1
0
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:
shanshuirenjia
2018-08-22 16:39:42 +08:00
committed by Daniel Pan
parent e4a255206f
commit 00388d3cda
21 changed files with 1149 additions and 484 deletions

View File

@@ -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.
*

View File

@@ -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;

View File

@@ -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>
);
}
}