mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-02 23:48:47 +00:00
update wiki mode
This commit is contained in:
@@ -13,7 +13,18 @@ const viewerPropTypes = {
|
||||
activeTitleIndex: PropTypes.number
|
||||
};
|
||||
|
||||
const contentClass = 'markdown-content';
|
||||
|
||||
class MarkdownContentViewer extends React.Component {
|
||||
componentDidUpdate () {
|
||||
var links = document.querySelectorAll(`.${contentClass} a`);
|
||||
links.forEach((li) => {li.addEventListener('click', this.onLinkClick); });
|
||||
}
|
||||
|
||||
onLinkClick = (event) => {
|
||||
event.preventDefault();
|
||||
this.props.onLinkClick(event);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.isFileLoading) {
|
||||
|
@@ -2,6 +2,7 @@ import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import { gettext, siteRoot } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import ModalPortal from '../modal-portal';
|
||||
import CreateFolder from '../../components/dialog/create-folder-dialog';
|
||||
import CreateFile from '../../components/dialog/create-file-dialog';
|
||||
@@ -16,6 +17,11 @@ const propTypes = {
|
||||
onAddFolder: PropTypes.func.isRequired,
|
||||
onUploadFile: PropTypes.func.isRequired,
|
||||
onUploadFolder: PropTypes.func.isRequired,
|
||||
isDraft: PropTypes.bool,
|
||||
hasDraft: PropTypes.bool,
|
||||
reviewStatus: PropTypes.any,
|
||||
goDraftPage: PropTypes.func,
|
||||
goReviewPage: PropTypes.func,
|
||||
};
|
||||
|
||||
class DirOperationToolbar extends React.Component {
|
||||
@@ -63,6 +69,14 @@ class DirOperationToolbar extends React.Component {
|
||||
window.location.href= siteRoot + 'lib/' + repoID + '/file' + path + '?mode=edit';
|
||||
}
|
||||
|
||||
onNewDraft = (e) => {
|
||||
e.preventDefault();
|
||||
let { path, repoID } = this.props;
|
||||
seafileAPI.createDraft(repoID, path).then(res => {
|
||||
window.location.href = siteRoot + 'lib/' + res.data.origin_repo_id + '/file' + res.data.draft_file_path + '?mode=edit';
|
||||
});
|
||||
}
|
||||
|
||||
onUploadClick = (e) => {
|
||||
this.toggleOperationMenu(e);
|
||||
this.setState({
|
||||
@@ -115,14 +129,43 @@ class DirOperationToolbar extends React.Component {
|
||||
this.props.onAddFolder(dirPath);
|
||||
}
|
||||
|
||||
onViewReview = () => {
|
||||
this.props.goReviewPage();
|
||||
}
|
||||
|
||||
onViewDraft = () => {
|
||||
this.props.goDraftPage();
|
||||
}
|
||||
|
||||
render() {
|
||||
let dirName = this.props.path.replace('\/','');
|
||||
let isFile = this.props.isViewFile;
|
||||
let itemName;
|
||||
if (this.props.isViewFile) {
|
||||
itemName = Utils.getFileName(this.props.path)
|
||||
} else {
|
||||
itemName = this.props.path.replace('\/','');
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<div className="operation">
|
||||
{(this.props.isViewFile && this.props.permission === 'rw') && (
|
||||
<Fragment>
|
||||
<button className="btn btn-secondary operation-item" title={gettext('Edit File')} onClick={this.onEditClick}>{gettext('Edit')}</button>
|
||||
<button className="btn btn-secondary operation-item" title={gettext('Share')} onClick={this.onShareClick}>{gettext('Share')}</button>
|
||||
</Fragment>
|
||||
)}
|
||||
|
||||
{(this.props.isViewFile && this.props.permission !== 'None' && !this.props.isDraft && !this.props.hasDraft) && (
|
||||
<button className="btn btn-secondary operation-item" title={gettext('New Draft')} onClick={this.onNewDraft}>{gettext('New Draft')}</button>
|
||||
)}
|
||||
{(this.props.reviewStatus === 'open') &&
|
||||
<button className="btn btn-secondary operation-item" title={gettext('View Review')} onClick={this.onViewReview}>{gettext('View Review')}</button>
|
||||
}
|
||||
{(!this.props.isDraft && this.props.hasDraft) &&
|
||||
<button className="btn btn-secondary operation-item" title={gettext('View Draft')} onClick={this.onViewDraft}>{gettext('View Draft')}</button>
|
||||
}
|
||||
|
||||
{!this.props.isViewFile && (
|
||||
<Fragment>
|
||||
{Utils.isSupportUploadFolder() ?
|
||||
@@ -170,8 +213,8 @@ class DirOperationToolbar extends React.Component {
|
||||
{this.state.isShareDialogShow &&
|
||||
<ModalPortal>
|
||||
<ShareDialog
|
||||
isDir={true}
|
||||
itemName={dirName}
|
||||
isDir={!isFile}
|
||||
itemName={itemName}
|
||||
itemPath={this.props.path}
|
||||
repoID={this.props.repoID}
|
||||
toggleDialog={this.onShareClick}
|
||||
|
@@ -177,3 +177,7 @@ img[src=""] {
|
||||
.wiki-md-viewer-rendered-content.article h1 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.markdown-content a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@@ -117,22 +117,22 @@ class EditorUtilities {
|
||||
if (fileNode.isImage()) {
|
||||
url = serviceUrl + '/lib/' + repoID + '/file' + encodeURIComponent(fileNode.path()) + '?raw=1';
|
||||
} else {
|
||||
url = serviceUrl + '/lib/' + repoID + '/file' + encodeURIComponent(fileNode.path());
|
||||
url = serviceUrl + '/wiki/lib/' + repoID + '/file' + encodeURIComponent(fileNode.path());
|
||||
}
|
||||
} else {
|
||||
url = serviceUrl + '/#common/lib/' + repoID + encodeURIComponent(fileNode.path());
|
||||
url = serviceUrl + '/wiki/lib/' + repoID + encodeURIComponent(fileNode.path());
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
isInternalFileLink(url) {
|
||||
var re = new RegExp(this.serviceUrl + '/lib/[0-9a-f-]{36}/file.*');
|
||||
var re = new RegExp(this.serviceUrl + '/wiki/lib/[0-9a-f-]{36}/file.*');
|
||||
return re.test(url);
|
||||
}
|
||||
|
||||
|
||||
isInternalDirLink(url) {
|
||||
var re = new RegExp(serviceUrl + '/#[a-z\-]*?/lib/' + '[0-9a-f\-]{36}.*');
|
||||
var re = new RegExp(serviceUrl + '/wiki/lib/' + '[0-9a-f\-]{36}.*');
|
||||
return re.test(url);
|
||||
}
|
||||
|
||||
|
@@ -48,6 +48,12 @@ const propTypes = {
|
||||
onItemsMove: PropTypes.func.isRequired,
|
||||
onItemsCopy: PropTypes.func.isRequired,
|
||||
onItemsDelete: PropTypes.func.isRequired,
|
||||
onLinkClick: PropTypes.func.isRequired,
|
||||
isDraft: PropTypes.bool,
|
||||
hasDraft: PropTypes.bool,
|
||||
reviewStatus: PropTypes.any,
|
||||
goReviewPage: PropTypes.func,
|
||||
goDraftPage: PropTypes.func,
|
||||
};
|
||||
|
||||
class MainPanel extends Component {
|
||||
@@ -185,6 +191,11 @@ class MainPanel extends Component {
|
||||
<DirOperationToolBar
|
||||
path={this.props.path}
|
||||
repoID={repoID}
|
||||
isDraft={this.props.isDraft}
|
||||
hasDraft={this.props.hasDraft}
|
||||
reviewStatus={this.props.reviewStatus}
|
||||
goDraftPage={this.props.goDraftPage}
|
||||
goReviewPage={this.props.goReviewPage}
|
||||
permission={this.props.permission}
|
||||
isViewFile={this.props.isViewFile}
|
||||
onAddFile={this.props.onAddFile}
|
||||
@@ -224,6 +235,7 @@ class MainPanel extends Component {
|
||||
isFileLoading={this.props.isFileLoading}
|
||||
activeTitleIndex={this.state.activeTitleIndex}
|
||||
onContentRendered={this.onContentRendered}
|
||||
onLinkClick={this.props.onLinkClick}
|
||||
/> :
|
||||
<Fragment>
|
||||
<DirentListView
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import moment from 'moment';
|
||||
import { gettext, repoID, siteRoot, initialPath, isDir } from './utils/constants';
|
||||
import { gettext, repoID, siteRoot, initialPath, isDir, serviceUrl } from './utils/constants';
|
||||
import { seafileAPI } from './utils/seafile-api';
|
||||
import { Utils } from './utils/utils';
|
||||
import SidePanel from './pages/repo-wiki-mode/side-panel';
|
||||
@@ -42,7 +42,12 @@ class Wiki extends Component {
|
||||
isDirentSelected: false,
|
||||
isAllDirentSelected: false,
|
||||
selectedDirentList: [],
|
||||
libNeedDecrypt: false
|
||||
libNeedDecrypt: false,
|
||||
isDraft: false,
|
||||
hasDraft: false,
|
||||
reviewStatus: '',
|
||||
reviewID: '',
|
||||
draftFilePath: '',
|
||||
};
|
||||
window.onpopstate = this.onpopstate;
|
||||
this.hash = '';
|
||||
@@ -226,7 +231,8 @@ class Wiki extends Component {
|
||||
|
||||
this.setState({isFileLoading: true});
|
||||
seafileAPI.getFileInfo(repoID, filePath).then((res) => {
|
||||
let { mtime, permission, last_modifier_name } = res.data;
|
||||
let { mtime, permission, last_modifier_name, is_draft, has_draft,
|
||||
review_status, review_id, draft_file_path } = res.data;
|
||||
seafileAPI.getFileDownloadLink(repoID, filePath).then((res) => {
|
||||
seafileAPI.getFileContent(res.data).then((res) => {
|
||||
this.setState({
|
||||
@@ -235,6 +241,11 @@ class Wiki extends Component {
|
||||
latestContributor: last_modifier_name,
|
||||
lastModified: moment.unix(mtime).fromNow(),
|
||||
isFileLoading: false,
|
||||
isDraft: is_draft,
|
||||
hasDraft: has_draft,
|
||||
reviewStatus: review_status,
|
||||
reviewID: review_id,
|
||||
draftFilePath: draft_file_path
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -271,6 +282,18 @@ class Wiki extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
onLinkClick = (event) => {
|
||||
const url = event.path[2].href;
|
||||
if (this.isInternalMarkdownLink(url)) {
|
||||
let path = this.getPathFromInternalMarkdownLink(url);
|
||||
this.showFile(path);
|
||||
} else if (this.isInternalDirLink(url)) {
|
||||
let path = this.getPathFromInternalDirLink(url);
|
||||
this.showDir(path);
|
||||
}
|
||||
}
|
||||
|
||||
updateDirent = (dirent, paramKey, paramValue) => {
|
||||
let newDirentList = this.state.direntList.map(item => {
|
||||
if (item.name === dirent.name) {
|
||||
@@ -705,24 +728,24 @@ class Wiki extends Component {
|
||||
}
|
||||
|
||||
isInternalMarkdownLink(url) {
|
||||
var re = new RegExp(siteRoot + 'lib/' + repoID + '/file' + '.*\.md$');
|
||||
var re = new RegExp(serviceUrl + '/wiki/lib/' + repoID + '/file' + '.*\.md$');
|
||||
return re.test(url);
|
||||
}
|
||||
|
||||
isInternalDirLink(url) {
|
||||
var re = new RegExp(siteRoot + '#[a-z\-]*?/lib/' + repoID + '/.*');
|
||||
var re = new RegExp(serviceUrl + '/wiki/lib/' + repoID + '/.*');
|
||||
return re.test(url);
|
||||
}
|
||||
|
||||
getPathFromInternalMarkdownLink(url) {
|
||||
var re = new RegExp(siteRoot + 'lib/' + repoID + '/file' + '(.*\.md)');
|
||||
var re = new RegExp(serviceUrl + '/wiki/lib/' + repoID + '/file' + '(.*\.md)');
|
||||
var array = re.exec(url);
|
||||
var path = decodeURIComponent(array[1]);
|
||||
return path;
|
||||
}
|
||||
|
||||
getPathFromInternalDirLink(url) {
|
||||
var re = new RegExp(siteRoot + '#[a-z\-]*?/lib/' + repoID + '(/.*)');
|
||||
var re = new RegExp(serviceUrl + '/wiki/lib/' + repoID + '(/.*)');
|
||||
var array = re.exec(url);
|
||||
var path = decodeURIComponent(array[1]);
|
||||
|
||||
@@ -776,6 +799,14 @@ class Wiki extends Component {
|
||||
this.loadSidePanel(initialPath);
|
||||
}
|
||||
|
||||
goReviewPage = () => {
|
||||
window.location.href = siteRoot + 'drafts/review/' + this.state.reviewID;
|
||||
}
|
||||
|
||||
goDraftPage = () => {
|
||||
window.location.href = siteRoot + 'lib/' + repoID + '/file' + this.state.draftFilePath + '?mode=edit';
|
||||
}
|
||||
|
||||
render() {
|
||||
let { libNeedDecrypt } = this.state;
|
||||
if (libNeedDecrypt) {
|
||||
@@ -823,6 +854,7 @@ class Wiki extends Component {
|
||||
onItemSelected={this.onDirentSelected}
|
||||
onItemDelete={this.onMainPanelItemDelete}
|
||||
onItemRename={this.onMainPanelItemRename}
|
||||
onLinkClick={this.onLinkClick}
|
||||
onItemMove={this.onMoveItem}
|
||||
onItemCopy={this.onCopyItem}
|
||||
onAddFile={this.onAddFile}
|
||||
@@ -835,6 +867,11 @@ class Wiki extends Component {
|
||||
onItemsCopy={this.onCopyItems}
|
||||
onItemsDelete={this.onDeleteItems}
|
||||
hash={this.hash}
|
||||
isDraft={this.state.isDraft}
|
||||
hasDraft={this.state.hasDraft}
|
||||
reviewStatus={this.state.reviewStatus}
|
||||
goDraftPage={this.goDraftPage}
|
||||
goReviewPage={this.goReviewPage}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@@ -36,6 +36,7 @@ export const repoID = window.wiki ? window.wiki.config.repoId : '';
|
||||
export const initialPath = window.wiki ? window.wiki.config.initial_path : '';
|
||||
export const permission = window.wiki ? window.wiki.config.permission === 'True' : '';
|
||||
export const isDir = window.wiki ? window.wiki.config.isDir : '';
|
||||
export const serviceUrl = window.wiki ? window.wiki.config.serviceUrl : '';
|
||||
|
||||
// file history
|
||||
export const PER_PAGE = 25;
|
||||
|
Reference in New Issue
Block a user