2018-05-02 06:09:58 +00:00
|
|
|
import React from 'react';
|
2018-07-27 03:48:21 +00:00
|
|
|
import SeafileEditor from '@seafile/seafile-editor';
|
2018-05-02 06:09:58 +00:00
|
|
|
import 'whatwg-fetch';
|
2018-07-27 03:48:21 +00:00
|
|
|
import { SeafileAPI } from 'seafile-js';
|
2018-12-19 08:07:56 +00:00
|
|
|
import { Utils } from './utils/utils';
|
2018-08-06 10:29:12 +00:00
|
|
|
import cookie from 'react-cookies';
|
2018-05-02 06:09:58 +00:00
|
|
|
let repoID = window.app.pageOptions.repoID;
|
2018-12-19 08:07:56 +00:00
|
|
|
let repoName = window.app.pageOptions.repoName;
|
2018-05-02 06:09:58 +00:00
|
|
|
let filePath = window.app.pageOptions.filePath;
|
|
|
|
let fileName = window.app.pageOptions.fileName;
|
|
|
|
let siteRoot = window.app.config.siteRoot;
|
|
|
|
let domain = window.app.pageOptions.domain;
|
|
|
|
let protocol = window.app.pageOptions.protocol;
|
2018-08-06 10:29:12 +00:00
|
|
|
let mode = window.app.pageOptions.mode;
|
2018-10-15 07:51:29 +00:00
|
|
|
let draftID = window.app.pageOptions.draftID;
|
2018-10-30 03:07:01 +00:00
|
|
|
let reviewID = window.app.pageOptions.reviewID;
|
2018-12-05 09:11:11 +00:00
|
|
|
let reviewStatus = window.app.pageOptions.reviewStatus;
|
2018-10-30 03:07:01 +00:00
|
|
|
let isDraft = window.app.pageOptions.isDraft;
|
2018-11-01 09:52:59 +00:00
|
|
|
let hasDraft = window.app.pageOptions.hasDraft;
|
|
|
|
let draftFilePath = window.app.pageOptions.draftFilePath;
|
2018-12-19 03:15:18 +00:00
|
|
|
let shareLinkExpireDaysMin = window.app.pageOptions.shareLinkExpireDaysMin;
|
|
|
|
let shareLinkExpireDaysMax = window.app.pageOptions.shareLinkExpireDaysMax;
|
2018-10-30 03:07:01 +00:00
|
|
|
let userName = window.app.userInfo.username;
|
2018-05-02 06:09:58 +00:00
|
|
|
let dirPath = '/';
|
|
|
|
|
2018-07-27 03:48:21 +00:00
|
|
|
const serviceUrl = window.app.config.serviceUrl;
|
|
|
|
const seafileCollabServer = window.app.config.seafileCollabServer;
|
|
|
|
const userInfo = window.app.userInfo;
|
|
|
|
// init seafileAPI
|
|
|
|
let seafileAPI = new SeafileAPI();
|
2018-09-01 03:42:25 +00:00
|
|
|
let xcsrfHeaders = cookie.load('sfcsrftoken');
|
2018-08-06 10:29:12 +00:00
|
|
|
seafileAPI.initForSeahubUsage({ siteRoot, xcsrfHeaders });
|
2018-05-02 06:09:58 +00:00
|
|
|
|
|
|
|
function getImageFileNameWithTimestamp() {
|
|
|
|
var d = Date.now();
|
2018-09-29 10:32:53 +00:00
|
|
|
return 'image-' + d.toString() + '.png';
|
2018-05-02 06:09:58 +00:00
|
|
|
}
|
|
|
|
|
2018-10-15 07:51:29 +00:00
|
|
|
|
2018-05-02 06:09:58 +00:00
|
|
|
class EditorUtilities {
|
2018-07-27 03:48:21 +00:00
|
|
|
|
|
|
|
constructor () {
|
|
|
|
this.repoID = repoID;
|
|
|
|
this.filePath = filePath;
|
|
|
|
this.serviceUrl = serviceUrl;
|
|
|
|
}
|
|
|
|
|
2018-05-02 06:09:58 +00:00
|
|
|
saveContent(content) {
|
2018-07-27 03:48:21 +00:00
|
|
|
return (
|
|
|
|
seafileAPI.getUpdateLink(repoID, dirPath).then((res) => {
|
|
|
|
const uploadLink = res.data;
|
2018-09-29 10:32:53 +00:00
|
|
|
return seafileAPI.updateFile(uploadLink, filePath, fileName, content);
|
2018-05-02 06:09:58 +00:00
|
|
|
})
|
2018-09-29 10:32:53 +00:00
|
|
|
);
|
2018-07-27 03:48:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unStarFile () {
|
|
|
|
return (
|
|
|
|
seafileAPI.unStarFile(repoID, this.filePath)
|
2018-09-29 10:32:53 +00:00
|
|
|
);
|
2018-05-02 06:09:58 +00:00
|
|
|
}
|
|
|
|
|
2018-07-27 03:48:21 +00:00
|
|
|
starFile() {
|
|
|
|
return (
|
|
|
|
seafileAPI.starFile(this.repoID, this.filePath)
|
2018-09-29 10:32:53 +00:00
|
|
|
);
|
2018-07-27 03:48:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
getParentDectionaryUrl() {
|
|
|
|
let parentPath = this.filePath.substring(0, this.filePath.lastIndexOf('/'));
|
2018-12-19 08:07:56 +00:00
|
|
|
let libName = encodeURIComponent(repoName);
|
|
|
|
let path = Utils.encodePath(parentPath);
|
|
|
|
return this.serviceUrl + '/library/' + this.repoID + '/' + libName + path + '/';
|
2018-07-27 03:48:21 +00:00
|
|
|
}
|
|
|
|
|
2018-05-02 06:09:58 +00:00
|
|
|
_getImageURL(fileName) {
|
|
|
|
const url = `${protocol}://${domain}${siteRoot}lib/${repoID}/file/images/${fileName}?raw=1`;
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
|
|
|
uploadImage = (imageFile) => {
|
2018-07-27 03:48:21 +00:00
|
|
|
return (
|
|
|
|
seafileAPI.getUploadLink(repoID, dirPath).then((res) => {
|
|
|
|
let uploadLinkComponent = res.data;
|
2018-09-29 10:32:53 +00:00
|
|
|
const uploadLink = uploadLinkComponent + '?ret-json=1';
|
2018-05-02 06:09:58 +00:00
|
|
|
const name = getImageFileNameWithTimestamp();
|
|
|
|
const blob = imageFile.slice(0, -1, 'image/png');
|
|
|
|
const newFile = new File([blob], name, {type: 'image/png'});
|
|
|
|
const formData = new FormData();
|
2018-09-29 10:32:53 +00:00
|
|
|
formData.append('parent_dir', '/');
|
|
|
|
formData.append('relative_path', 'images');
|
|
|
|
formData.append('file', newFile);
|
|
|
|
return {uploadLink, formData};
|
2018-07-27 03:48:21 +00:00
|
|
|
}).then(({ uploadLink, formData}) => {
|
2018-09-29 10:32:53 +00:00
|
|
|
return seafileAPI.uploadImage(uploadLink, formData);
|
2018-07-27 03:48:21 +00:00
|
|
|
}).then ((res) => {
|
|
|
|
let resArr = res.data[0];
|
|
|
|
let filename = resArr.name;
|
2018-05-02 06:09:58 +00:00
|
|
|
return this._getImageURL(filename);
|
2018-07-27 03:48:21 +00:00
|
|
|
})
|
2018-09-29 10:32:53 +00:00
|
|
|
);
|
2018-07-27 03:48:21 +00:00
|
|
|
}
|
2018-05-02 06:09:58 +00:00
|
|
|
|
2018-11-05 14:03:13 +00:00
|
|
|
uploadLocalImage = (imageFile) => {
|
|
|
|
return (
|
|
|
|
seafileAPI.getUploadLink(repoID, dirPath).then((res) => {
|
|
|
|
const uploadLink = res.data + '?ret-json=1';
|
|
|
|
const newFile = new File([imageFile], imageFile.name, {type: imageFile.type});
|
|
|
|
const formData = new FormData();
|
|
|
|
formData.append('parent_dir', '/');
|
|
|
|
formData.append('relative_path', 'images');
|
|
|
|
formData.append('file', newFile);
|
|
|
|
return seafileAPI.uploadImage(uploadLink, formData);
|
|
|
|
}).then ((res) => {
|
|
|
|
return this._getImageURL(res.data[0].name);
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-05-02 06:09:58 +00:00
|
|
|
getFileURL(fileNode) {
|
|
|
|
var url;
|
2018-08-28 03:34:03 +00:00
|
|
|
if (fileNode.type === 'file') {
|
|
|
|
if (fileNode.isImage()) {
|
2018-09-29 10:32:53 +00:00
|
|
|
url = serviceUrl + '/lib/' + repoID + '/file' + encodeURIComponent(fileNode.path()) + '?raw=1';
|
2018-08-28 03:34:03 +00:00
|
|
|
} else {
|
2018-12-12 02:34:58 +00:00
|
|
|
url = serviceUrl + '/wiki/lib/' + repoID + '/file' + encodeURIComponent(fileNode.path());
|
2018-08-28 03:34:03 +00:00
|
|
|
}
|
2018-05-02 06:09:58 +00:00
|
|
|
} else {
|
2018-12-12 02:34:58 +00:00
|
|
|
url = serviceUrl + '/wiki/lib/' + repoID + encodeURIComponent(fileNode.path());
|
2018-05-02 06:09:58 +00:00
|
|
|
}
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
|
|
|
isInternalFileLink(url) {
|
2018-12-12 02:34:58 +00:00
|
|
|
var re = new RegExp(this.serviceUrl + '/wiki/lib/[0-9a-f-]{36}/file.*');
|
2018-05-02 06:09:58 +00:00
|
|
|
return re.test(url);
|
|
|
|
}
|
|
|
|
|
2018-08-28 03:34:03 +00:00
|
|
|
|
|
|
|
isInternalDirLink(url) {
|
2018-12-12 02:34:58 +00:00
|
|
|
var re = new RegExp(serviceUrl + '/wiki/lib/' + '[0-9a-f\-]{36}.*');
|
2018-08-28 03:34:03 +00:00
|
|
|
return re.test(url);
|
|
|
|
}
|
|
|
|
|
2018-05-02 06:09:58 +00:00
|
|
|
getFiles() {
|
2018-07-27 03:48:21 +00:00
|
|
|
return seafileAPI.listDir(repoID, dirPath, { recursive: true} ).then((response) => {
|
|
|
|
var files = response.data.map((item) => {
|
|
|
|
return {
|
|
|
|
name: item.name,
|
|
|
|
type: item.type === 'dir' ? 'dir' : 'file',
|
|
|
|
parent_path: item.parent_dir
|
2018-09-29 10:32:53 +00:00
|
|
|
};
|
|
|
|
});
|
2018-07-27 03:48:21 +00:00
|
|
|
return files;
|
2018-09-29 10:32:53 +00:00
|
|
|
});
|
2018-05-02 06:09:58 +00:00
|
|
|
}
|
2018-08-06 10:29:12 +00:00
|
|
|
|
|
|
|
getFileHistory() {
|
|
|
|
return (
|
|
|
|
seafileAPI.getFileHistory(repoID, filePath)
|
2018-09-29 10:32:53 +00:00
|
|
|
);
|
2018-08-06 10:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
getFileInfo() {
|
|
|
|
return (
|
|
|
|
seafileAPI.getFileInfo(repoID, filePath)
|
2018-09-29 10:32:53 +00:00
|
|
|
);
|
2018-08-06 10:29:12 +00:00
|
|
|
}
|
2018-08-22 10:07:32 +00:00
|
|
|
|
2018-12-28 06:25:25 +00:00
|
|
|
getRepoInfo(newRepoID) {
|
|
|
|
return (
|
|
|
|
seafileAPI.getRepoInfo(newRepoID)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-08-22 10:07:32 +00:00
|
|
|
getInternalLink() {
|
2018-09-29 10:32:53 +00:00
|
|
|
return seafileAPI.getInternalLink(repoID, filePath);
|
2018-08-22 10:07:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
getShareLink() {
|
|
|
|
return seafileAPI.getShareLink(repoID, filePath);
|
|
|
|
}
|
|
|
|
|
2018-12-19 02:17:07 +00:00
|
|
|
createShareLink (repoID, filePath, userPassword, userValidDays, permissions) {
|
|
|
|
return seafileAPI.createShareLink(repoID, filePath, userPassword, userValidDays, permissions);
|
2018-08-22 10:07:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
deleteShareLink(token){
|
2018-09-29 10:32:53 +00:00
|
|
|
return seafileAPI.deleteShareLink(token);
|
2018-08-22 10:07:32 +00:00
|
|
|
}
|
|
|
|
|
2018-09-19 02:47:56 +00:00
|
|
|
getDraftKey() {
|
2018-09-29 10:32:53 +00:00
|
|
|
return (repoID + filePath);
|
|
|
|
}
|
2018-09-27 04:01:56 +00:00
|
|
|
|
|
|
|
getFileContent(url) {
|
|
|
|
return seafileAPI.getFileContent(url);
|
|
|
|
}
|
|
|
|
|
|
|
|
listFileHistoryRecords(page, perPage) {
|
|
|
|
return (
|
|
|
|
seafileAPI.listFileHistoryRecords(repoID, filePath, page, perPage)
|
2018-09-29 10:32:53 +00:00
|
|
|
);
|
2018-09-27 04:01:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
getFileHistoryVersion(commitID) {
|
|
|
|
return seafileAPI.getFileRevision(repoID, commitID, filePath);
|
|
|
|
}
|
2018-10-15 07:51:29 +00:00
|
|
|
|
|
|
|
createDraftReview() {
|
2018-10-16 10:19:51 +00:00
|
|
|
return seafileAPI.createDraftReview(draftID).then(res => {
|
|
|
|
let url = serviceUrl + '/drafts/review/' + res.data.id;
|
|
|
|
return url;
|
|
|
|
});
|
2018-10-15 07:51:29 +00:00
|
|
|
}
|
2018-10-30 03:07:01 +00:00
|
|
|
|
|
|
|
goReviewPage() {
|
2018-11-22 09:00:23 +00:00
|
|
|
window.location.href = serviceUrl + '/drafts/review/' + reviewID;
|
2018-10-30 03:07:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
getCommentsNumber() {
|
2018-10-30 03:51:22 +00:00
|
|
|
return seafileAPI.getCommentsNumber(this.repoID, dirPath);
|
2018-10-30 03:07:01 +00:00
|
|
|
}
|
|
|
|
|
2018-11-16 09:57:35 +00:00
|
|
|
postComment(comment, detail) {
|
|
|
|
return seafileAPI.postComment(this.repoID, this.filePath, comment, detail);
|
2018-10-30 03:07:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
listComments() {
|
|
|
|
return seafileAPI.listComments(this.repoID, this.filePath);
|
|
|
|
}
|
|
|
|
|
|
|
|
updateComment(commentID, resolved, detail) {
|
|
|
|
return seafileAPI.updateComment(this.repoID, commentID, resolved, detail);
|
|
|
|
}
|
|
|
|
|
|
|
|
deleteComment(commentID) {
|
|
|
|
return seafileAPI.deleteComment(this.repoID, commentID);
|
|
|
|
}
|
|
|
|
|
|
|
|
getUserAvatar(size) {
|
|
|
|
return seafileAPI.getUserAvatar(userName, size);
|
|
|
|
}
|
2018-11-01 09:52:59 +00:00
|
|
|
|
|
|
|
goDraftPage() {
|
2018-11-22 09:00:23 +00:00
|
|
|
window.location.href = serviceUrl + '/lib/' + repoID + '/file' + draftFilePath + '?mode=edit';
|
2018-11-01 09:52:59 +00:00
|
|
|
}
|
2018-11-02 03:03:10 +00:00
|
|
|
|
|
|
|
createDraftFile() {
|
|
|
|
return seafileAPI.createDraft(repoID, filePath).then(res => {
|
2018-11-22 09:00:23 +00:00
|
|
|
window.location.href = serviceUrl + '/lib/' + res.data.origin_repo_id + '/file' + res.data.draft_file_path + '?mode=edit';
|
|
|
|
});
|
2018-11-02 03:03:10 +00:00
|
|
|
}
|
2018-05-02 06:09:58 +00:00
|
|
|
|
2018-11-09 10:03:10 +00:00
|
|
|
createFileReview() {
|
|
|
|
return seafileAPI.createFileReview(repoID, filePath).then(res => {
|
|
|
|
window.location.href = serviceUrl + '/drafts/review/' + res.data.id;
|
2018-11-22 09:00:23 +00:00
|
|
|
});
|
2018-11-09 10:03:10 +00:00
|
|
|
}
|
|
|
|
}
|
2018-05-02 06:09:58 +00:00
|
|
|
|
|
|
|
const editorUtilities = new EditorUtilities();
|
|
|
|
|
2018-09-21 06:16:15 +00:00
|
|
|
class MarkdownEditor extends React.Component {
|
2018-05-02 06:09:58 +00:00
|
|
|
constructor(props) {
|
2018-09-29 10:32:53 +00:00
|
|
|
super(props);
|
|
|
|
this.state = {
|
|
|
|
markdownContent: '',
|
|
|
|
loading: true,
|
|
|
|
mode: 'editor',
|
|
|
|
fileInfo: {
|
|
|
|
repoID: repoID,
|
|
|
|
name: fileName,
|
|
|
|
path: filePath,
|
|
|
|
mtime: null,
|
|
|
|
size: 0,
|
|
|
|
starred: false,
|
|
|
|
permission: '',
|
|
|
|
lastModifier: '',
|
|
|
|
},
|
|
|
|
collabServer: seafileCollabServer ? seafileCollabServer : null,
|
2018-12-28 06:25:25 +00:00
|
|
|
relatedFiles: [],
|
2018-09-29 10:32:53 +00:00
|
|
|
};
|
|
|
|
}
|
2018-05-02 06:09:58 +00:00
|
|
|
|
|
|
|
componentDidMount() {
|
2018-07-27 03:48:21 +00:00
|
|
|
|
|
|
|
seafileAPI.getFileInfo(repoID, filePath).then((res) => {
|
2018-08-06 10:29:12 +00:00
|
|
|
let { mtime, size, starred, permission, last_modifier_name } = res.data;
|
2018-09-29 10:32:53 +00:00
|
|
|
let lastModifier = last_modifier_name;
|
2018-08-06 10:29:12 +00:00
|
|
|
|
2018-07-27 03:48:21 +00:00
|
|
|
this.setState((prevState, props) => ({
|
|
|
|
fileInfo: {
|
|
|
|
...prevState.fileInfo,
|
|
|
|
mtime,
|
|
|
|
size,
|
2018-08-06 10:29:12 +00:00
|
|
|
starred,
|
|
|
|
permission,
|
|
|
|
lastModifier
|
2018-07-27 03:48:21 +00:00
|
|
|
}
|
|
|
|
}));
|
|
|
|
|
|
|
|
seafileAPI.getFileDownloadLink(repoID, filePath).then((res) => {
|
|
|
|
const downLoadUrl = res.data;
|
|
|
|
seafileAPI.getFileContent(downLoadUrl).then((res) => {
|
|
|
|
this.setState({
|
|
|
|
markdownContent: res.data,
|
|
|
|
loading: false
|
2018-09-29 10:32:53 +00:00
|
|
|
});
|
|
|
|
});
|
2018-07-27 03:48:21 +00:00
|
|
|
});
|
2018-09-29 10:32:53 +00:00
|
|
|
});
|
2018-12-28 06:25:25 +00:00
|
|
|
|
|
|
|
seafileAPI.listRelatedFiles(repoID, filePath).then(res => {
|
|
|
|
this.setState({
|
|
|
|
relatedFiles: res.data.related_files
|
|
|
|
})
|
|
|
|
});
|
2018-05-02 06:09:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
if (this.state.loading) {
|
|
|
|
return (
|
|
|
|
<div className="empty-loading-page">
|
|
|
|
<div className="lds-ripple page-centered"><div></div><div></div></div>
|
|
|
|
</div>
|
2018-09-29 10:32:53 +00:00
|
|
|
);
|
|
|
|
} else if (this.state.mode === 'editor') {
|
2018-05-02 06:09:58 +00:00
|
|
|
return (
|
|
|
|
<SeafileEditor
|
2018-07-27 03:48:21 +00:00
|
|
|
fileInfo={this.state.fileInfo}
|
2018-05-02 06:09:58 +00:00
|
|
|
markdownContent={this.state.markdownContent}
|
|
|
|
editorUtilities={editorUtilities}
|
2018-07-27 03:48:21 +00:00
|
|
|
userInfo={this.state.collabServer ? userInfo : null}
|
|
|
|
collabServer={this.state.collabServer}
|
2018-09-29 10:32:53 +00:00
|
|
|
showFileHistory={true}
|
2018-08-06 10:29:12 +00:00
|
|
|
mode={mode}
|
2018-10-15 07:51:29 +00:00
|
|
|
draftID={draftID}
|
2018-10-30 03:07:01 +00:00
|
|
|
reviewID={reviewID}
|
2018-12-05 09:11:11 +00:00
|
|
|
reviewStatus={reviewStatus}
|
2018-10-30 03:07:01 +00:00
|
|
|
isDraft={isDraft}
|
2018-11-01 09:52:59 +00:00
|
|
|
hasDraft={hasDraft}
|
2018-12-19 03:15:18 +00:00
|
|
|
shareLinkExpireDaysMin={shareLinkExpireDaysMin}
|
|
|
|
shareLinkExpireDaysMax={shareLinkExpireDaysMax}
|
2018-12-28 06:25:25 +00:00
|
|
|
relatedFiles={this.state.relatedFiles}
|
2018-12-29 02:38:39 +00:00
|
|
|
siteRoot={siteRoot}
|
2018-05-02 06:09:58 +00:00
|
|
|
/>
|
|
|
|
);
|
2018-06-07 07:01:41 +00:00
|
|
|
}
|
2018-05-02 06:09:58 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-29 10:32:53 +00:00
|
|
|
|
2018-09-21 06:16:15 +00:00
|
|
|
export default MarkdownEditor;
|