1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-16 15:19:06 +00:00

Wiki module improve (#2901)

This commit is contained in:
杨顺强
2019-01-29 11:03:43 +08:00
committed by Daniel Pan
parent d9a2f6ded9
commit 3c2b89dc22
7 changed files with 155 additions and 31 deletions

View File

@@ -641,7 +641,7 @@
},
"axios": {
"version": "0.18.0",
"resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
"integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=",
"requires": {
"follow-redirects": "^1.3.0",
@@ -5282,7 +5282,7 @@
},
"git-up": {
"version": "1.2.1",
"resolved": "http://registry.npmjs.org/git-up/-/git-up-1.2.1.tgz",
"resolved": "https://registry.npmjs.org/git-up/-/git-up-1.2.1.tgz",
"integrity": "sha1-JkSAoAax2EJhrB/gmjpRacV+oZ0=",
"requires": {
"is-ssh": "^1.0.0",
@@ -5291,7 +5291,7 @@
},
"git-url-parse": {
"version": "5.0.1",
"resolved": "http://registry.npmjs.org/git-url-parse/-/git-url-parse-5.0.1.tgz",
"resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-5.0.1.tgz",
"integrity": "sha1-/j15xnRq4FBIz6UIyB553du6OEM=",
"requires": {
"git-up": "^1.0.0"
@@ -7844,7 +7844,7 @@
},
"node-status-codes": {
"version": "1.0.0",
"resolved": "http://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz",
"integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8="
},
"noop6": {
@@ -8151,7 +8151,7 @@
},
"package.json": {
"version": "2.0.1",
"resolved": "http://registry.npmjs.org/package.json/-/package.json-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/package.json/-/package.json-2.0.1.tgz",
"integrity": "sha1-+IYFnSpJ7QduZIg2ldc7K0bSHW0=",
"requires": {
"git-package-json": "^1.4.0",
@@ -8161,7 +8161,7 @@
"dependencies": {
"got": {
"version": "5.7.1",
"resolved": "http://registry.npmjs.org/got/-/got-5.7.1.tgz",
"resolved": "https://registry.npmjs.org/got/-/got-5.7.1.tgz",
"integrity": "sha1-X4FjWmHkplifGAVp6k44FoClHzU=",
"requires": {
"create-error-class": "^3.0.1",
@@ -8183,7 +8183,7 @@
},
"package-json": {
"version": "2.4.0",
"resolved": "http://registry.npmjs.org/package-json/-/package-json-2.4.0.tgz",
"resolved": "https://registry.npmjs.org/package-json/-/package-json-2.4.0.tgz",
"integrity": "sha1-DRW9Z9HLvduyyiIv8u24a8sxqLs=",
"requires": {
"got": "^5.0.0",

View File

@@ -1,17 +1,114 @@
import React from 'react';
import PropTypes from 'prop-types';
import MarkdownViewer from '@seafile/seafile-editor/dist/viewer/markdown-viewer';
import { repoID, slug, serviceURL, isPublicWiki } from '../utils/constants';
import { Utils } from '../utils/utils';
const viewerPropTypes = {
indexContent: PropTypes.string.isRequired,
onLinkClick: PropTypes.func.isRequired,
};
const contentClass = 'wiki-page-content';
class IndexContentViewer extends React.Component {
constructor(props) {
super(props);
this.links = [];
}
componentDidMount() {
// Bind event when first loaded
this.links = document.querySelectorAll(`.${contentClass} a`);
this.links.forEach(link => {
link.addEventListener('click', this.onLinkClick);
});
}
componentWillReceiveProps() {
// Unbound event when updating
this.links.forEach(link => {
link.removeEventListener('click', this.onLinkClick);
});
}
componentDidUpdate() {
// Update completed, rebind event
this.links = document.querySelectorAll(`.${contentClass} a`);
this.links.forEach(link => {
link.addEventListener('click', this.onLinkClick);
});
}
componentWillUnmount() {
// Rebinding events when the component is destroyed
this.links.forEach(link => {
link.removeEventListener('click', this.onLinkClick);
});
}
onLinkClick = (event) => {
event.preventDefault();
this.props.onLinkClick(event);
event.preventDefault();
event.stopPropagation();
let link = '';
if (event.target.tagName !== 'A') {
let target = event.target.parentNode;
while (target.tagName !== 'A') {
target = target.parentNode;
}
link = target.href;
} else {
link = event.target.href;
}
this.props.onLinkClick(link);
}
changeInlineNode = (item) => {
if (item.object == 'inline') {
let url;
// change image url
if (item.type == 'image' && isPublicWiki) {
url = item.data.src;
const re = new RegExp(serviceURL + '/lib/' + repoID +'/file.*raw=1');
// different repo
if (!re.test(url)) {
return;
}
// get image path
let index = url.indexOf('/file');
let index2 = url.indexOf('?');
const imagePath = url.substring(index + 5, index2);
// replace url
item.data.src = serviceURL + '/view-image-via-public-wiki/?slug=' + slug + '&path=' + imagePath;
}
else if (item.type == 'link') {
url = item.data.href;
// change file url
if (Utils.isInternalMarkdownLink(url, repoID)) {
let path = Utils.getPathFromInternalMarkdownLink(url, repoID);
// replace url
item.data.href = serviceURL + '/wikis/' + slug + path;
}
// change dir url
else if (Utils.isInternalDirLink(url, repoID)) {
let path = Utils.getPathFromInternalDirLink(url, repoID, slug);
// replace url
item.data.href = serviceURL + '/wikis/' + slug + path;
}
}
}
return item;
}
modifyValueBeforeRender = (value) => {
let nodes = value.document.nodes;
let newNodes = Utils.changeMarkdownNodes(nodes, this.changeInlineNode);
value.document.nodes = newNodes;
return value;
}
onContentRendered = () => {
@@ -20,10 +117,11 @@ class IndexContentViewer extends React.Component {
render() {
return (
<div className="markdown-content">
<div className={contentClass}>
<MarkdownViewer
markdownContent={this.props.indexContent}
onContentRendered={this.props.onContentRendered}
modifyValueBeforeRender={this.modifyValueBeforeRender}
/>
</div>
);

View File

@@ -56,7 +56,7 @@ class WikiDirListItem extends React.Component {
<a href={href} onClick={this.onDirentClick}>{dirent.name}</a>
</td>
<td>{dirent.size}</td>
<td title={dirent.last_update_time}>{dirent.last_update_time}</td>
<td title={dirent.mtime_relative}>{dirent.mtime_relative}</td>
</tr>
);
}

View File

@@ -31,7 +31,8 @@ class MainPanel extends Component {
onEditClick = (e) => {
e.preventDefault();
window.location.href= siteRoot + 'lib/' + repoID + '/file' + this.props.filePath + '?mode=edit';
let url = siteRoot + 'lib/' + repoID + '/file' + this.props.path + '?mode=edit';
window.open(url);
}
onMainNavBarClick = (e) => {
@@ -69,6 +70,7 @@ class MainPanel extends Component {
render() {
const errMessage = (<div className="message empty-tip err-message"><h2>{gettext('Folder does not exist.')}</h2></div>);
return (
<div className="main-panel wiki-main-panel o-hidden">
<div className="main-panel-top panel-top">
@@ -102,8 +104,9 @@ class MainPanel extends Component {
</div>
</div>
<div className="cur-view-content">
{this.props.isDataLoading && <Loading />}
{(!this.props.isDataLoading && this.props.isViewFile) && (
{!this.props.pathExist && errMessage}
{this.props.pathExist && this.props.isDataLoading && <Loading />}
{(this.props.pathExist && !this.props.isDataLoading && this.props.isViewFile) && (
<WikiMarkdownViewer
markdownContent={this.props.content}
isFileLoading={this.props.isDataLoading}

View File

@@ -1,6 +1,6 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { gettext, siteRoot, repoID } from '../../utils/constants';
import { gettext, siteRoot, repoID, slug } from '../../utils/constants';
import Logo from '../../components/logo';
import Loading from '../../components/loading';
import TreeView from '../../components/tree-view/tree-view';
@@ -27,21 +27,11 @@ class SidePanel extends Component {
this.isNodeMenuShow = false;
}
onEditClick = (e) => {
e.preventDefault();
let indexNode = this.props.indexNode
window.location.href= siteRoot + 'lib/' + repoID + '/file' + indexNode.path + '?mode=edit';
}
renderIndexView = () => {
let indexNode = this.props.indexNode;
return (
<Fragment>
<h3 className="wiki-pages-heading">
{gettext('Contents')}
{indexNode.object.permission === 'rw' &&
<button className="btn btn-secondary operation-item index-edit" title="Edit Index" onClick={this.onEditClick}>{gettext('Edit')}</button>
}
</h3>
<div className="wiki-pages-container">
<IndexContentViewer
@@ -83,6 +73,7 @@ class SidePanel extends Component {
{this.props.isTreeDataLoading && <Loading /> }
{!this.props.isTreeDataLoading && this.props.indexNode && this.renderIndexView() }
{!this.props.isTreeDataLoading && !this.props.indexNode && this.renderTreeView() }
<div className="text-left p-2"><a href={siteRoot + 'library/' + repoID + "/" + slug} className="text-dark text-decoration-underline">{gettext('Go to Library')}</a></div>
</div>
</div>
);

View File

@@ -50,11 +50,17 @@ class Wiki extends Component {
this.loadWikiData(initialPath);
}
loadWikiData = () => {
loadWikiData = (initialPath) => {
this.loadSidePanel(initialPath);
if (isDir === 'None') {
this.setState({pathExist: false});
if (initialPath === '/home.md') {
this.showDir('/');
} else {
this.setState({pathExist: false});
let fileUrl = siteRoot + 'wikis/' + slug + initialPath;
window.history.pushState({url: fileUrl, path: initialPath}, initialPath, fileUrl);
}
} else if (isDir === 'True') {
this.showDir(initialPath);
} else if (isDir === 'False') {
@@ -66,9 +72,10 @@ class Wiki extends Component {
if (initialPath === this.homePath || isDir === 'None') {
seafileAPI.listDir(repoID, '/').then(res => {
let tree = this.state.treeData;
this.addResponseListToNode(res.data.dirent_list, tree.root);
this.addFirstResponseListToNode(res.data.dirent_list, tree.root);
let indexNode = tree.getNodeByPath(this.indexPath);
if (indexNode) {
let homeNode = tree.getNodeByPath(this.homePath);
if (homeNode && indexNode) {
seafileAPI.getFileDownloadLink(repoID, indexNode.path).then(res => {
seafileAPI.getFileContent(res.data).then(res => {
this.setState({
@@ -202,10 +209,10 @@ class Wiki extends Component {
const url = link;
if (Utils.isWikiInternalMarkdownLink(url, slug)) {
let path = Utils.getPathFromWikiInternalMarkdownLink(url, slug);
this.initMainPanelData(path);
this.showFile(path);
} else if (Utils.isWikiInternalDirLink(url, slug)) {
let path = Utils.getPathFromWikiInternalDirLink(url, slug);
this.initWikiData(path);
this.showDir(path);
} else {
window.location.href = url;
}
@@ -364,6 +371,27 @@ class Wiki extends Component {
}
}
addFirstResponseListToNode = (list, node) => {
node.isLoaded = true;
node.isExpanded = true;
let direntList = list.map(item => {
return new Dirent(item);
});
direntList = direntList.filter(item => {
if (item.type === 'dir') {
let name = item.name.toLowerCase();
return name !== 'drafts' && name !== 'images' && name !== 'downloads';
}
return true;
});
direntList = Utils.sortDirents(direntList, 'name', 'asc');
let nodeList = direntList.map(object => {
return new TreeNode({object});
});
node.addChildren(nodeList);
}
addResponseListToNode = (list, node) => {
node.isLoaded = true;
node.isExpanded = true;

View File

@@ -149,6 +149,10 @@ ul,ol,li {
cursor: pointer;
}
.text-decoration-underline {
text-decoration: underline !important;
}
.sf-dropdown-toggle {
margin-left: 0.5rem;
vertical-align: middle;