1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-04 16:31:13 +00:00

update repo wiki mode

This commit is contained in:
ilearnit
2018-09-12 14:15:27 +08:00
parent 15b5be489d
commit 0fc103e9b9
3 changed files with 156 additions and 45 deletions

View File

@@ -1,12 +1,10 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { gettext, repoID, serviceUrl, slug, siteRoot } from '../../components/constance'; import { gettext, repoID, serviceUrl, slug, siteRoot, isPro } from '../../components/constance';
import Search from '../../components/search'; import Search from '../../components/search';
import Account from '../../components/account'; import Account from '../../components/account';
import MarkdownViewer from '../../components/markdown-viewer'; import MarkdownViewer from '../../components/markdown-viewer';
import TreeDirView from '../../components/tree-dir-view/tree-dir-view'; import TreeDirView from '../../components/tree-dir-view/tree-dir-view';
// const repoName = window.repo.config.repo_name
class MainPanel extends Component { class MainPanel extends Component {
onMenuClick = () => { onMenuClick = () => {
@@ -60,15 +58,17 @@ class MainPanel extends Component {
<a className="btn btn-secondary btn-topbar sf2-icon-grid-view" id='grid' title={gettext("Grid")} onClick={this.switchViewMode}></a> <a className="btn btn-secondary btn-topbar sf2-icon-grid-view" id='grid' title={gettext("Grid")} onClick={this.switchViewMode}></a>
</div> </div>
<div className="common-toolbar"> <div className="common-toolbar">
<Search onSearchedClick={this.props.onSearchedClick} {isPro && <Search onSearchedClick={this.props.onSearchedClick}
placeholder={gettext("Search files in this library")}/> placeholder={gettext("Search files in this wiki")}
/>
}
<Account /> <Account />
</div> </div>
</div> </div>
<div className="cur-view-main"> <div className="cur-view-main">
<div className="cur-view-path"> <div className="cur-view-path">
<div className="path-containter"> <div className="path-containter">
<a href={siteRoot + '#my-libs/'} className="normal">{gettext("Libraries")}</a> <a href={siteRoot + '#common/'} className="normal">{gettext("Libraries")}</a>
<span className="path-split">/</span> <span className="path-split">/</span>
<a href={siteRoot + 'wiki/lib/' + repoID + '/'} className="normal">{slug}</a> <a href={siteRoot + 'wiki/lib/' + repoID + '/'} className="normal">{slug}</a>
{pathElem} {pathElem}

View File

@@ -3,6 +3,9 @@ import TreeView from '../../components/tree-view/tree-view';
import { siteRoot, logoPath, mediaUrl, siteTitle, logoWidth, logoHeight } from '../../components/constance'; import { siteRoot, logoPath, mediaUrl, siteTitle, logoWidth, logoHeight } from '../../components/constance';
import NodeMenu from '../../components/menu-component/node-menu'; import NodeMenu from '../../components/menu-component/node-menu';
import MenuControl from '../../components/menu-component/node-menu-control'; import MenuControl from '../../components/menu-component/node-menu-control';
import Delete from '../../components/menu-component/menu-dialog/delete-dialog';
import Rename from '../../components/menu-component/menu-dialog/rename-dialog';
import CreateFlieFolder from '../../components/menu-component/menu-dialog/create-fileforder-dialog';
const gettext = window.gettext; const gettext = window.gettext;
@@ -19,7 +22,11 @@ class SidePanel extends Component {
top: 0 top: 0
}, },
isLoadFailed: false, isLoadFailed: false,
isMenuIconShow: false isMenuIconShow: false,
showDelete: false,
showAddFileFolder: false,
showRename: false,
isFile: false
} }
this.searchedPath = null; this.searchedPath = null;
} }
@@ -71,26 +78,52 @@ class SidePanel extends Component {
} }
onHideContextMenu = () => { onHideContextMenu = () => {
if (!this.state.isShowMenu) {
return;
}
this.setState({ this.setState({
isShowMenu: false, isShowMenu: false,
isNodeItemFrezee: false isNodeItemFrezee: false
}) })
} }
onAddFolderNode = (dirPath) => { toggleAddFileFolder = (flag) => {
this.props.onAddFolderNode(dirPath); let isFile = flag === true ? true : false;
this.setState({
showAddFileFolder: !this.state.showAddFileFolder,
isFile: isFile
});
this.onHideContextMenu();
}
toggleRename = () => {
this.setState({showRename: !this.state.showRename});
this.onHideContextMenu();
}
toggleDelete = () => {
this.setState({showDelete: !this.state.showDelete});
this.onHideContextMenu();
} }
onAddFolderNode = (dirPath) => {
this.setState({showAddFileFolder: !this.state.showAddFileFolder});
this.props.onAddFolderNode(dirPath);
}
onAddFileNode = (filePath) => { onAddFileNode = (filePath) => {
this.setState({showAddFileFolder: !this.state.showAddFileFolder});
this.props.onAddFileNode(filePath); this.props.onAddFileNode(filePath);
} }
onRenameNode = (newName) => { onRenameNode = (newName) => {
this.setState({showRename: !this.state.showRename})
let node = this.state.currentNode; let node = this.state.currentNode;
this.props.onRenameNode(node, newName) this.props.onRenameNode(node, newName)
} }
onDeleteNode = () => { onDeleteNode = () => {
this.setState({showDelete: !this.state.showDelete})
let node = this.state.currentNode; let node = this.state.currentNode;
this.props.onDeleteNode(node); this.props.onDeleteNode(node);
} }
@@ -109,6 +142,22 @@ class SidePanel extends Component {
document.removeEventListener('click', this.onHideContextMenu); document.removeEventListener('click', this.onHideContextMenu);
} }
addFolderCancel = () => {
this.setState({showAddFileFolder: !this.state.showAddFileFolder});
}
addFileCancel = () => {
this.setState({showAddFileFolder: !this.state.showAddFileFolder});
}
deleteCancel = () => {
this.setState({showDelete: !this.state.showDelete})
}
renameCancel = () => {
this.setState({showRename: !this.state.showRename})
}
render() { render() {
return ( return (
<div className={`wiki-side-panel ${this.props.closeSideBar ? "": "left-zero"}`}> <div className={`wiki-side-panel ${this.props.closeSideBar ? "": "left-zero"}`}>
@@ -135,7 +184,6 @@ class SidePanel extends Component {
<div className="wiki-pages-container"> <div className="wiki-pages-container">
{this.props.treeData && {this.props.treeData &&
<TreeView <TreeView
permission={this.props.permission}
currentFilePath={this.props.currentFilePath} currentFilePath={this.props.currentFilePath}
treeData={this.props.treeData} treeData={this.props.treeData}
currentNode={this.state.currentNode} currentNode={this.state.currentNode}
@@ -145,16 +193,39 @@ class SidePanel extends Component {
onDirCollapse={this.props.onDirCollapse} onDirCollapse={this.props.onDirCollapse}
/> />
} }
{this.state.isShowMenu &&
<NodeMenu <NodeMenu
isShowMenu={this.state.isShowMenu}
menuPosition={this.state.menuPosition} menuPosition={this.state.menuPosition}
currentNode={this.state.currentNode} currentNode={this.state.currentNode}
onHideContextMenu={this.onHideContextMenu} toggleAddFileFolder={this.toggleAddFileFolder}
onDeleteNode={this.onDeleteNode} toggleRename={this.toggleRename}
onAddFileNode={this.onAddFileNode} toggleDelete={this.toggleDelete}
onAddFolderNode={this.onAddFolderNode}
onRenameNode={this.onRenameNode}
/> />
}
{this.state.showDelete &&
<Delete
currentNode={this.state.currentNode}
handleSubmit={this.onDeleteNode}
toggleCancel={this.deleteCancel}
/>
}
{this.state.showAddFileFolder &&
<CreateFlieFolder
isFile={this.state.isFile}
currentNode={this.state.currentNode}
onAddFolder={this.onAddFolderNode}
addFolderCancel={this.addFolderCancel}
onAddFile={this.onAddFileNode}
addFileCancel={this.addFileCancel}
/>
}
{this.state.showRename &&
<Rename
currentNode={this.state.currentNode}
onRename={this.onRenameNode}
toggleCancel={this.renameCancel}
/>
}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -5,8 +5,8 @@ import SidePanel from './pages/repo-wiki-mode/side-panel';
import MainPanel from './pages/repo-wiki-mode/main-panel'; import MainPanel from './pages/repo-wiki-mode/main-panel';
import moment from 'moment'; import moment from 'moment';
import { slug, repoID, serviceUrl, initialFilePath } from './components/constance'; import { slug, repoID, serviceUrl, initialFilePath } from './components/constance';
import editorUtilities from './utils/editor-utilties'; import editorUtilities from './utils/editor-utilties';
import { seafileAPI } from './utils/editor-utilties'; import { seafileAPI } from './utils/editor-utilties';
import Node from './components/tree-view/node' import Node from './components/tree-view/node'
import Tree from './components/tree-view/tree' import Tree from './components/tree-view/tree'
import 'seafile-ui'; import 'seafile-ui';
@@ -47,6 +47,7 @@ class Wiki extends Component {
treeData.parseListToTree(files); treeData.parseListToTree(files);
let node = treeData.getNodeByPath(filePath); let node = treeData.getNodeByPath(filePath);
treeData.expandNode(node);
if (node.isDir()) { if (node.isDir()) {
this.exitViewFileState(treeData, node); this.exitViewFileState(treeData, node);
this.setState({isFileLoading: false}); this.setState({isFileLoading: false});
@@ -60,6 +61,7 @@ class Wiki extends Component {
lastModified: moment.unix(mtime).fromNow(), lastModified: moment.unix(mtime).fromNow(),
permission: permission, permission: permission,
filePath: filePath, filePath: filePath,
isFileLoading: false
}) })
seafileAPI.getFileDownloadLink(repoID, filePath).then((res) => { seafileAPI.getFileDownloadLink(repoID, filePath).then((res) => {
@@ -104,11 +106,10 @@ class Wiki extends Component {
content: res.data, content: res.data,
isFileLoading: false isFileLoading: false
}) })
}) });
}); })
}) })
let fileUrl = serviceUrl + '/wiki/lib/' + repoID + filePath; let fileUrl = serviceUrl + '/wiki/lib/' + repoID + filePath;
window.history.pushState({urlPath: fileUrl, filePath: filePath}, filePath, fileUrl); window.history.pushState({urlPath: fileUrl, filePath: filePath}, filePath, fileUrl);
} }
@@ -134,6 +135,9 @@ class Wiki extends Component {
if (this.isInternalMarkdownLink(url)) { if (this.isInternalMarkdownLink(url)) {
let path = this.getPathFromInternalMarkdownLink(url); let path = this.getPathFromInternalMarkdownLink(url);
this.initMainPanelData(path); this.initMainPanelData(path);
} else if (this.isInternalDirLink(url)) {
let path = this.getPathFromInternalDirLink(url);
this.initWikiData(path);
} else { } else {
window.location.href = url; window.location.href = url;
} }
@@ -151,17 +155,15 @@ class Wiki extends Component {
let tree = this.state.tree_data.clone(); let tree = this.state.tree_data.clone();
let node = tree.getNodeByPath(path); let node = tree.getNodeByPath(path);
tree.setNodeToActivated(node); tree.expandNode(node);
this.enterViewFileState(tree, node, node.path);
let path = node.path; //node is file
this.enterViewFileState(tree, node, path);
} }
} }
onMainNavBarClick = (nodePath) => { onMainNavBarClick = (nodePath) => {
let tree = this.state.tree_data.clone(); let tree = this.state.tree_data.clone();
let node = tree.getNodeByPath(nodePath); let node = tree.getNodeByPath(nodePath);
tree.setNodeToActivated(node); tree.expandNode(node);
this.exitViewFileState(tree, node); this.exitViewFileState(tree, node);
@@ -172,7 +174,7 @@ class Wiki extends Component {
onMainNodeClick = (node) => { onMainNodeClick = (node) => {
let tree = this.state.tree_data.clone(); let tree = this.state.tree_data.clone();
tree.setNodeToActivated(node); tree.expandNode(node);
if (node.isMarkdown()) { if (node.isMarkdown()) {
this.initMainPanelData(node.path); this.initMainPanelData(node.path);
this.enterViewFileState(tree, node, node.path); this.enterViewFileState(tree, node, node.path);
@@ -192,6 +194,13 @@ class Wiki extends Component {
this.enterViewFileState(tree, node, node.path); this.enterViewFileState(tree, node, node.path);
} else if(node instanceof Node && node.isDir()){ } else if(node instanceof Node && node.isDir()){
let tree = this.state.tree_data.clone(); let tree = this.state.tree_data.clone();
if (this.state.filePath === node.path) {
if (node.isExpanded) {
tree.collapseNode(node);
} else {
tree.expandNode(node);
}
}
this.exitViewFileState(tree, node); this.exitViewFileState(tree, node);
} else { } else {
const w=window.open('about:blank'); const w=window.open('about:blank');
@@ -232,7 +241,7 @@ class Wiki extends Component {
let parentNode = tree.getNodeByPath(parentPath); let parentNode = tree.getNodeByPath(parentPath);
tree.addNodeToParent(node, parentNode); tree.addNodeToParent(node, parentNode);
if (this.state.isViewFileState) { if (this.state.isViewFileState) {
tree.setNodeToActivated(node); tree.expandNode(node);
this.setState({ this.setState({
tree_data: tree, tree_data: tree,
changedNode: node changedNode: node
@@ -256,7 +265,7 @@ class Wiki extends Component {
let parentNode = tree.getNodeByPath(parentPath); let parentNode = tree.getNodeByPath(parentPath);
tree.addNodeToParent(node, parentNode); tree.addNodeToParent(node, parentNode);
if (this.state.isViewFileState) { if (this.state.isViewFileState) {
tree.setNodeToActivated(node); tree.expandNode(node);
this.setState({ this.setState({
tree_data: tree, tree_data: tree,
changedNode: node changedNode: node
@@ -272,15 +281,17 @@ class Wiki extends Component {
let filePath = node.path; let filePath = node.path;
if (node.isMarkdown()) { if (node.isMarkdown()) {
editorUtilities.renameFile(filePath, newName).then(res => { editorUtilities.renameFile(filePath, newName).then(res => {
let date = new Date().getTime()/1000; let cloneNode = node.clone();
tree.updateNodeParam(node, "name", newName); tree.updateNodeParam(node, "name", newName);
node.name = newName; node.name = newName;
let date = new Date().getTime()/1000;
tree.updateNodeParam(node, "last_update_time", moment.unix(date).fromNow()); tree.updateNodeParam(node, "last_update_time", moment.unix(date).fromNow());
node.last_update_time = moment.unix(date).fromNow(); node.last_update_time = moment.unix(date).fromNow();
if (this.state.isViewFileState) { if (this.state.isViewFileState) {
if (this.isModifyCurrentFile(node)) { if (this.isModifyCurrentFile(cloneNode)) {
tree.setNodeToActivated(node); tree.expandNode(node);
this.setState({ this.setState({
tree_data: tree, tree_data: tree,
changedNode: node changedNode: node
@@ -290,23 +301,29 @@ class Wiki extends Component {
this.setState({tree_data: tree}); this.setState({tree_data: tree});
} }
} else { } else {
this.setState({tree_data: tree}); let parentNode = tree.findNodeParentFromTree(node);
this.setState({
tree_data: tree,
changedNode: parentNode
});
} }
}) })
} else if (node.isDir()) { } else if (node.isDir()) {
editorUtilities.renameDir(filePath, newName).then(res => { editorUtilities.renameDir(filePath, newName).then(res => {
let currentFilePath = this.state.filePath;// the sequence is must right
let currentFilePath = this.state.filePath;
let currentFileNode = tree.getNodeByPath(currentFilePath); let currentFileNode = tree.getNodeByPath(currentFilePath);
let nodePath = node.path;
let isPathEqual = (node.path === currentFilePath);
let date = new Date().getTime()/1000;
tree.updateNodeParam(node, "name", newName); tree.updateNodeParam(node, "name", newName);
node.name = newName; // just synchronization node data && tree data; node.name = newName;
let date = new Date().getTime()/1000;
tree.updateNodeParam(node, "last_update_time", moment.unix(date).fromNow()); tree.updateNodeParam(node, "last_update_time", moment.unix(date).fromNow());
node.last_update_time = moment.unix(date).fromNow(); node.last_update_time = moment.unix(date).fromNow();
if (this.state.isViewFileState) { if (this.state.isViewFileState) {
if (this.isModifyContainsCurrentFile(node)) { if (currentFilePath.indexOf(nodePath) > -1) {
tree.setNodeToActivated(currentFileNode); tree.expandNode(currentFileNode);
this.setState({ this.setState({
tree_data: tree, tree_data: tree,
changedNode: currentFileNode changedNode: currentFileNode
@@ -316,8 +333,11 @@ class Wiki extends Component {
this.setState({tree_data: tree}); this.setState({tree_data: tree});
} }
} else { } else {
if (isPathEqual || node.path.indexOf(currentFilePath) > -1) { if (nodePath === currentFilePath) { // old node
tree.setNodeToActivated(currentFileNode); tree.expandNode(node);
this.exitViewFileState(tree, node);
} else if (node.path.indexOf(currentFilePath) > -1) { // new node
tree.expandNode(currentFileNode);
this.exitViewFileState(tree, currentFileNode); this.exitViewFileState(tree, currentFileNode);
} else { } else {
this.setState({tree_data: tree}); this.setState({tree_data: tree});
@@ -349,7 +369,7 @@ class Wiki extends Component {
if (this.state.isViewFileState) { if (this.state.isViewFileState) {
if (isCurrentFile) { if (isCurrentFile) {
let homeNode = this.getHomeNode(tree); let homeNode = this.getHomeNode(tree);
tree.setNodeToActivated(homeNode); tree.expandNode(homeNode);
this.setState({ this.setState({
tree_data: tree, tree_data: tree,
changedNode: homeNode changedNode: homeNode
@@ -451,6 +471,11 @@ class Wiki extends Component {
return re.test(url); return re.test(url);
} }
isInternalDirLink(url) {
var re = new RegExp(serviceUrl + '/#[a-z\-]*?/lib/' + repoID + '/.*');
return re.test(url);
}
getPathFromInternalMarkdownLink(url) { getPathFromInternalMarkdownLink(url) {
var re = new RegExp(serviceUrl + '/lib/' + repoID + '/file' + "(.*\.md)"); var re = new RegExp(serviceUrl + '/lib/' + repoID + '/file' + "(.*\.md)");
var array = re.exec(url); var array = re.exec(url);
@@ -458,6 +483,22 @@ class Wiki extends Component {
return path; return path;
} }
getPathFromInternalDirLink(url) {
var re = new RegExp(serviceUrl + '/#[a-z\-]*?/lib/' + repoID + "(/.*)");
var array = re.exec(url);
var path = decodeURIComponent(array[1]);
var dirPath = path.substring(1);
var re = new RegExp("(^/.*)");
if (re.test(dirPath)) {
path = dirPath;
} else {
path = '/' + dirPath
}
return path;
}
render() { render() {
return ( return (
<div id="main" className="wiki-main"> <div id="main" className="wiki-main">
@@ -466,7 +507,6 @@ class Wiki extends Component {
closeSideBar={this.state.closeSideBar} closeSideBar={this.state.closeSideBar}
onCloseSide ={this.onCloseSide} onCloseSide ={this.onCloseSide}
treeData={this.state.tree_data} treeData={this.state.tree_data}
permission={this.state.permission}
currentFilePath={this.state.filePath} currentFilePath={this.state.filePath}
changedNode={this.state.changedNode} changedNode={this.state.changedNode}
onAddFolderNode={this.onAddFolderNode} onAddFolderNode={this.onAddFolderNode}