2018-09-12 02:32:31 +00:00
|
|
|
import React, { Component } from 'react';
|
|
|
|
import ReactDOM from 'react-dom';
|
|
|
|
import moment from 'moment';
|
2018-12-12 02:34:58 +00:00
|
|
|
import { gettext, repoID, siteRoot, initialPath, isDir, serviceUrl } from './utils/constants';
|
2018-09-18 02:11:37 +00:00
|
|
|
import { seafileAPI } from './utils/seafile-api';
|
2018-11-22 03:26:00 +00:00
|
|
|
import { Utils } from './utils/utils';
|
2018-10-25 05:36:06 +00:00
|
|
|
import SidePanel from './pages/repo-wiki-mode/side-panel';
|
|
|
|
import MainPanel from './pages/repo-wiki-mode/main-panel';
|
2018-09-19 01:57:17 +00:00
|
|
|
import Node from './components/tree-view/node';
|
|
|
|
import Tree from './components/tree-view/tree';
|
2018-12-07 06:58:37 +00:00
|
|
|
import toaster from './components/toast';
|
2018-12-14 08:49:55 +00:00
|
|
|
import LibDecryptDialog from './components/dialog/lib-decrypt-dialog';
|
|
|
|
import ModalPortal from './components/modal-portal';
|
2018-11-22 03:26:00 +00:00
|
|
|
import Dirent from './models/dirent';
|
|
|
|
import FileTag from './models/file-tag';
|
2018-09-12 02:32:31 +00:00
|
|
|
import './assets/css/fa-solid.css';
|
|
|
|
import './assets/css/fa-regular.css';
|
|
|
|
import './assets/css/fontawesome.css';
|
2018-09-21 06:16:15 +00:00
|
|
|
import './css/layout.css';
|
2018-09-12 02:32:31 +00:00
|
|
|
import './css/side-panel.css';
|
|
|
|
import './css/wiki.css';
|
2018-09-19 01:57:17 +00:00
|
|
|
import './css/toolbar.css';
|
2018-09-12 02:32:31 +00:00
|
|
|
import './css/search.css';
|
|
|
|
|
|
|
|
class Wiki extends Component {
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state = {
|
2018-11-22 03:26:00 +00:00
|
|
|
path: '',
|
|
|
|
pathExist: true,
|
|
|
|
treeData: new Tree(),
|
2018-09-12 02:32:31 +00:00
|
|
|
closeSideBar: false,
|
2018-11-22 03:26:00 +00:00
|
|
|
currentNode: null,
|
|
|
|
isDirentListLoading: true,
|
|
|
|
isViewFile: false,
|
|
|
|
direntList: [],
|
|
|
|
isFileLoading: true,
|
|
|
|
content: '',
|
2018-09-12 02:32:31 +00:00
|
|
|
lastModified: '',
|
2018-11-22 03:26:00 +00:00
|
|
|
latestContributor: '',
|
2018-09-12 02:32:31 +00:00
|
|
|
permission: '',
|
2018-11-23 12:19:42 +00:00
|
|
|
isDirentSelected: false,
|
|
|
|
isAllDirentSelected: false,
|
|
|
|
selectedDirentList: [],
|
2018-12-12 02:34:58 +00:00
|
|
|
libNeedDecrypt: false,
|
|
|
|
isDraft: false,
|
|
|
|
hasDraft: false,
|
|
|
|
reviewStatus: '',
|
|
|
|
reviewID: '',
|
|
|
|
draftFilePath: '',
|
2018-12-12 13:42:23 +00:00
|
|
|
dirID: '',
|
2018-09-12 02:32:31 +00:00
|
|
|
};
|
|
|
|
window.onpopstate = this.onpopstate;
|
2018-12-06 06:10:36 +00:00
|
|
|
this.hash = '';
|
|
|
|
}
|
|
|
|
|
|
|
|
componentWillMount() {
|
|
|
|
const hash = window.location.hash;
|
|
|
|
if (hash.slice(0, 1) === '#') {
|
|
|
|
this.hash = hash;
|
|
|
|
}
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
2018-12-14 08:49:55 +00:00
|
|
|
seafileAPI.getRepoInfo(repoID).then(res => {
|
|
|
|
this.setState({
|
|
|
|
libNeedDecrypt: res.data.lib_need_decrypt,
|
|
|
|
});
|
2018-11-22 03:26:00 +00:00
|
|
|
|
2018-12-14 08:49:55 +00:00
|
|
|
if (!res.data.lib_need_decrypt) {
|
|
|
|
if (isDir === 'None') {
|
|
|
|
this.setState({pathExist: false});
|
|
|
|
} else if (isDir === 'True') {
|
|
|
|
this.showDir(initialPath);
|
|
|
|
} else if (isDir === 'False') {
|
|
|
|
this.showFile(initialPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.loadSidePanel(initialPath);
|
|
|
|
}
|
|
|
|
});
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
|
|
|
|
deleteItemAjaxCallback(path, isDir) {
|
|
|
|
let node = this.state.treeData.getNodeByPath(path);
|
|
|
|
this.deleteTreeNode(node);
|
|
|
|
this.deleteDirent(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
deleteItem(path, isDir) {
|
|
|
|
if (isDir) {
|
|
|
|
seafileAPI.deleteDir(repoID, path).then(() => {
|
|
|
|
this.deleteItemAjaxCallback(path, isDir);
|
|
|
|
}).catch(() => {
|
|
|
|
//todos;
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
seafileAPI.deleteFile(repoID, path).then(() => {
|
|
|
|
this.deleteItemAjaxCallback(path, isDir);
|
|
|
|
}).catch(() => {
|
|
|
|
//todos;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
renameItemAjaxCallback(path, isDir, newName) {
|
|
|
|
let node = this.state.treeData.getNodeByPath(path);
|
|
|
|
this.renameTreeNode(node, newName);
|
|
|
|
this.renameDirent(path, newName);
|
|
|
|
}
|
|
|
|
|
|
|
|
renameItem = (path, isDir, newName) => {
|
|
|
|
//validate task
|
|
|
|
if (isDir) {
|
|
|
|
seafileAPI.renameDir(repoID, path, newName).then(() => {
|
|
|
|
this.renameItemAjaxCallback(path, isDir, newName);
|
|
|
|
}).catch(() => {
|
|
|
|
//todos;
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
seafileAPI.renameFile(repoID, path, newName).then(() => {
|
|
|
|
this.renameItemAjaxCallback(path, isDir, newName);
|
|
|
|
}).catch(() => {
|
|
|
|
//todos;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
onAddFile = (filePath, isDraft) => {
|
|
|
|
//todo validate;
|
|
|
|
seafileAPI.createFile(repoID, filePath, isDraft).then(res => {
|
|
|
|
let name = Utils.getFileName(filePath);
|
|
|
|
let parentPath = Utils.getDirName(filePath);
|
|
|
|
|
|
|
|
this.addNodeToTree(name, parentPath, 'file');
|
|
|
|
if (parentPath === this.state.path && !this.state.isViewFile) {
|
|
|
|
this.addDirent(name, 'file');
|
|
|
|
}
|
|
|
|
}).catch(() => {
|
|
|
|
//todo;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
onAddFolder = (dirPath) => {
|
|
|
|
//validate task
|
|
|
|
seafileAPI.createDir(repoID, dirPath).then(() => {
|
|
|
|
let name = Utils.getFileName(dirPath);
|
|
|
|
let parentPath = Utils.getDirName(dirPath);
|
|
|
|
|
|
|
|
this.addNodeToTree(name, parentPath, 'dir');
|
|
|
|
if (parentPath === this.state.path && !this.state.isViewFile) {
|
|
|
|
this.addDirent(name, 'dir');
|
|
|
|
}
|
|
|
|
}).catch(() => {
|
|
|
|
//return error message
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-11-29 09:55:14 +00:00
|
|
|
onMoveItem = (destRepo, dirent, moveToDirentPath) => {
|
2018-11-22 03:26:00 +00:00
|
|
|
//just for view list state
|
2018-11-29 09:55:14 +00:00
|
|
|
let dirName = dirent.name
|
|
|
|
let direntPath = Utils.joinPath(this.state.path, dirName);
|
|
|
|
seafileAPI.moveDir(repoID, destRepo.repo_id,moveToDirentPath, this.state.path, dirName).then(() => {
|
2018-11-22 03:26:00 +00:00
|
|
|
|
2018-11-29 09:55:14 +00:00
|
|
|
this.moveTreeNode(direntPath, moveToDirentPath, destRepo);
|
2018-11-22 03:26:00 +00:00
|
|
|
this.moveDirent(direntPath);
|
|
|
|
|
|
|
|
let message = gettext('Successfully moved %(name)s.');
|
|
|
|
message = message.replace('%(name)s', dirName);
|
2018-12-07 06:58:37 +00:00
|
|
|
toaster.success(message);
|
2018-11-22 03:26:00 +00:00
|
|
|
}).catch(() => {
|
|
|
|
let message = gettext('Failed to move %(name)s');
|
|
|
|
message = message.replace('%(name)s', dirName);
|
2018-12-07 06:58:37 +00:00
|
|
|
toaster.danger(message);
|
2018-11-22 03:26:00 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-11-29 09:55:14 +00:00
|
|
|
onCopyItem = (destRepo, dirent, copyToDirentPath) => {
|
2018-11-22 03:26:00 +00:00
|
|
|
//just for view list state
|
2018-11-29 09:55:14 +00:00
|
|
|
let dirName = dirent.name;
|
|
|
|
let direntPath = Utils.joinPath(this.state.path, dirName);
|
|
|
|
seafileAPI.copyDir(repoID, destRepo.repo_id, copyToDirentPath, this.state.path, dirName).then(() => {
|
|
|
|
this.copyTreeNode(direntPath, copyToDirentPath, destRepo);
|
2018-11-22 03:26:00 +00:00
|
|
|
let message = gettext('Successfully copied %(name)s.');
|
|
|
|
message = message.replace('%(name)s', dirName);
|
2018-12-07 06:58:37 +00:00
|
|
|
toaster.success(message);
|
2018-11-22 03:26:00 +00:00
|
|
|
}).catch(() => {
|
|
|
|
let message = gettext('Failed to copy %(name)s');
|
|
|
|
message = message.replace('%(name)s', dirName);
|
2018-12-07 06:58:37 +00:00
|
|
|
toaster.danger(message);
|
2018-11-22 03:26:00 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
loadSidePanel = (filePath) => {
|
|
|
|
seafileAPI.listDir(repoID, '/',{recursive: true}).then(items => {
|
|
|
|
const files = items.data.map(item => {
|
|
|
|
return {
|
|
|
|
name: item.name,
|
|
|
|
type: item.type === 'dir' ? 'dir' : 'file',
|
|
|
|
isExpanded: item.type === 'dir' ? true : false,
|
|
|
|
parent_path: item.parent_dir,
|
|
|
|
last_update_time: item.mtime,
|
|
|
|
permission: item.permission,
|
|
|
|
size: item.size
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
2018-09-12 02:32:31 +00:00
|
|
|
var treeData = new Tree();
|
|
|
|
treeData.parseListToTree(files);
|
|
|
|
|
|
|
|
let node = treeData.getNodeByPath(filePath);
|
2018-11-22 03:26:00 +00:00
|
|
|
if (node) {
|
|
|
|
treeData.expandNode(node);
|
|
|
|
this.setState({treeData: treeData, currentNode: node});
|
2018-09-12 02:32:31 +00:00
|
|
|
} else {
|
2018-11-22 03:26:00 +00:00
|
|
|
this.setState({treeData: treeData});
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
2018-11-22 03:26:00 +00:00
|
|
|
}).catch(() => {
|
2018-09-29 10:32:53 +00:00
|
|
|
/* eslint-disable */
|
2018-09-19 01:57:17 +00:00
|
|
|
console.log('failed to load files');
|
2018-09-29 10:32:53 +00:00
|
|
|
/* eslint-enable */
|
2018-11-22 03:26:00 +00:00
|
|
|
this.setState({isLoadFailed: true});
|
2018-09-19 01:57:17 +00:00
|
|
|
});
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
showFile = (filePath) => {
|
|
|
|
this.setState({
|
|
|
|
path: filePath,
|
|
|
|
isViewFile: true
|
|
|
|
});
|
2018-09-12 02:32:31 +00:00
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
this.setState({isFileLoading: true});
|
2018-09-12 02:32:31 +00:00
|
|
|
seafileAPI.getFileInfo(repoID, filePath).then((res) => {
|
2018-12-12 02:34:58 +00:00
|
|
|
let { mtime, permission, last_modifier_name, is_draft, has_draft,
|
|
|
|
review_status, review_id, draft_file_path } = res.data;
|
2018-09-12 02:32:31 +00:00
|
|
|
seafileAPI.getFileDownloadLink(repoID, filePath).then((res) => {
|
2018-11-22 03:26:00 +00:00
|
|
|
seafileAPI.getFileContent(res.data).then((res) => {
|
2018-09-12 02:32:31 +00:00
|
|
|
this.setState({
|
|
|
|
content: res.data,
|
2018-11-22 03:26:00 +00:00
|
|
|
permission: permission,
|
|
|
|
latestContributor: last_modifier_name,
|
|
|
|
lastModified: moment.unix(mtime).fromNow(),
|
|
|
|
isFileLoading: false,
|
2018-12-12 02:34:58 +00:00
|
|
|
isDraft: is_draft,
|
|
|
|
hasDraft: has_draft,
|
|
|
|
reviewStatus: review_status,
|
|
|
|
reviewID: review_id,
|
|
|
|
draftFilePath: draft_file_path
|
2018-09-19 01:57:17 +00:00
|
|
|
});
|
2018-09-12 06:15:27 +00:00
|
|
|
});
|
2018-09-19 01:57:17 +00:00
|
|
|
});
|
|
|
|
});
|
2018-09-12 02:32:31 +00:00
|
|
|
|
2018-11-29 09:55:14 +00:00
|
|
|
let fileUrl = siteRoot + 'wiki/lib/' + repoID + filePath;
|
2018-11-22 03:26:00 +00:00
|
|
|
window.history.pushState({url: fileUrl, path: filePath}, filePath, fileUrl);
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
showDir = (path) => {
|
|
|
|
this.loadDirentList(path);
|
|
|
|
this.setState({
|
|
|
|
path: path,
|
|
|
|
isViewFile: false
|
|
|
|
});
|
2018-09-12 02:32:31 +00:00
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
// update location url
|
2018-11-29 09:55:14 +00:00
|
|
|
let url = siteRoot + 'wiki/lib/' + repoID + path;
|
2018-11-22 03:26:00 +00:00
|
|
|
window.history.pushState({ url: url, path: path}, path, url);
|
|
|
|
}
|
2018-09-12 02:32:31 +00:00
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
loadDirentList = (filePath) => {
|
|
|
|
this.setState({isDirentListLoading: true});
|
|
|
|
seafileAPI.listDir(repoID, filePath).then(res => {
|
|
|
|
let direntList = [];
|
2018-12-13 03:15:20 +00:00
|
|
|
res.data.forEach(item => {
|
2018-11-22 03:26:00 +00:00
|
|
|
let dirent = new Dirent(item);
|
|
|
|
direntList.push(dirent);
|
|
|
|
});
|
|
|
|
this.setState({
|
|
|
|
direntList: direntList,
|
|
|
|
isDirentListLoading: false,
|
2018-12-13 03:15:20 +00:00
|
|
|
dirID: res.headers.oid,
|
2018-11-22 03:26:00 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-12-12 02:34:58 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
updateDirent = (dirent, paramKey, paramValue) => {
|
|
|
|
let newDirentList = this.state.direntList.map(item => {
|
|
|
|
if (item.name === dirent.name) {
|
|
|
|
item[paramKey] = paramValue;
|
|
|
|
}
|
|
|
|
return item;
|
|
|
|
});
|
2018-11-23 12:19:42 +00:00
|
|
|
this.setState({direntList: newDirentList});
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
onpopstate = (event) => {
|
2018-11-22 03:26:00 +00:00
|
|
|
if (event.state && event.state.path) {
|
|
|
|
let path = event.state.path;
|
2018-10-13 09:07:54 +00:00
|
|
|
if (this.isMarkdownFile(path)) {
|
2018-11-22 03:26:00 +00:00
|
|
|
this.showFile(path);
|
2018-10-13 09:07:54 +00:00
|
|
|
} else {
|
2018-11-22 03:26:00 +00:00
|
|
|
let currentNode = this.state.treeData.getNodeByPath(path);
|
|
|
|
this.showDir(currentNode.path);
|
2018-10-13 09:07:54 +00:00
|
|
|
}
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
}
|
2018-11-22 03:26:00 +00:00
|
|
|
|
2018-09-18 02:11:37 +00:00
|
|
|
onSearchedClick = (item) => {
|
2018-12-13 12:42:51 +00:00
|
|
|
if (item.is_dir) {
|
|
|
|
let path = item.path.slice(0, item.path.length - 1);
|
|
|
|
if (this.state.currentFilePath !== path) {
|
|
|
|
let tree = this.state.treeData.clone();
|
|
|
|
let node = tree.getNodeByPath(path);
|
|
|
|
tree.expandNode(node);
|
|
|
|
this.showDir(node.path);
|
|
|
|
}
|
|
|
|
} else if (Utils.isMarkdownFile(item.path)) {
|
|
|
|
let path = item.path;
|
|
|
|
if (this.state.currentFilePath !== path) {
|
|
|
|
let tree = this.state.treeData.clone();
|
|
|
|
let node = tree.getNodeByPath(path);
|
|
|
|
tree.expandNode(node);
|
|
|
|
this.showFile(node.path);
|
|
|
|
}
|
|
|
|
} else {
|
2018-12-14 13:52:54 +00:00
|
|
|
let url = siteRoot + 'lib/' + item.repo_id + '/file' + Utils.encodePath(item.path);
|
2018-12-13 12:42:51 +00:00
|
|
|
let newWindow = window.open('about:blank');
|
|
|
|
newWindow.location.href = url;
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
onMainNavBarClick = (nodePath) => {
|
2018-11-22 03:26:00 +00:00
|
|
|
//just for dir
|
2018-11-23 12:19:42 +00:00
|
|
|
this.resetSelected();
|
2018-11-22 03:26:00 +00:00
|
|
|
let tree = this.state.treeData.clone();
|
2018-09-12 02:32:31 +00:00
|
|
|
let node = tree.getNodeByPath(nodePath);
|
2018-09-12 06:15:27 +00:00
|
|
|
tree.expandNode(node);
|
2018-09-12 02:32:31 +00:00
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
this.setState({treeData: tree, currentNode: node});
|
|
|
|
this.showDir(node.path);
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
2018-11-29 09:55:14 +00:00
|
|
|
onDirentClick = (dirent) => {
|
2018-11-23 12:19:42 +00:00
|
|
|
this.resetSelected();
|
2018-11-29 09:55:14 +00:00
|
|
|
let direntPath = Utils.joinPath(this.state.path, dirent.name);
|
2018-11-22 03:26:00 +00:00
|
|
|
let tree = this.state.treeData.clone();
|
2018-10-13 09:07:54 +00:00
|
|
|
let node = tree.getNodeByPath(direntPath);
|
|
|
|
let parentNode = tree.findNodeParentFromTree(node);
|
|
|
|
tree.expandNode(parentNode);
|
2018-11-22 03:26:00 +00:00
|
|
|
|
2018-09-12 02:32:31 +00:00
|
|
|
if (node.isMarkdown()) {
|
2018-11-22 03:26:00 +00:00
|
|
|
this.setState({treeData: tree}); // tree
|
|
|
|
this.showFile(direntPath);
|
|
|
|
} else if (node.isDir()) {
|
|
|
|
this.setState({treeData: tree, currentNode: node}); //tree
|
|
|
|
this.showDir(node.path);
|
2018-09-12 02:32:31 +00:00
|
|
|
} else {
|
|
|
|
const w=window.open('about:blank');
|
2018-12-14 13:52:54 +00:00
|
|
|
const url = siteRoot + 'lib/' + repoID + '/file' + Utils.encodePath(node.path);
|
2018-09-12 02:32:31 +00:00
|
|
|
w.location.href = url;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-23 12:19:42 +00:00
|
|
|
onDirentSelected = (dirent) => {
|
|
|
|
let direntList = this.state.direntList.map(item => {
|
|
|
|
if (item.name === dirent.name) {
|
|
|
|
item.isSelected = !item.isSelected;
|
|
|
|
}
|
|
|
|
return item;
|
|
|
|
});
|
|
|
|
let selectedDirentList = direntList.filter(item => {
|
|
|
|
return item.isSelected;
|
|
|
|
});
|
|
|
|
|
|
|
|
if (selectedDirentList.length) {
|
|
|
|
this.setState({isDirentSelected: true});
|
|
|
|
if (selectedDirentList.length === direntList.length) {
|
|
|
|
this.setState({
|
|
|
|
isAllDirentSelected: true,
|
|
|
|
direntList: direntList,
|
|
|
|
selectedDirentList: selectedDirentList,
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this.setState({
|
|
|
|
isAllDirentSelected: false,
|
|
|
|
direntList: direntList,
|
|
|
|
selectedDirentList: selectedDirentList
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
this.setState({
|
|
|
|
isDirentSelected: false,
|
|
|
|
isAllDirentSelected: false,
|
|
|
|
direntList: direntList,
|
|
|
|
selectedDirentList: []
|
2018-11-27 06:47:19 +00:00
|
|
|
});
|
2018-11-23 12:19:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
onAllDirentSelected = () => {
|
|
|
|
if (this.state.isAllDirentSelected) {
|
|
|
|
let direntList = this.state.direntList.map(item => {
|
|
|
|
item.isSelected = false;
|
|
|
|
return item;
|
|
|
|
});
|
|
|
|
this.setState({
|
|
|
|
isDirentSelected: false,
|
|
|
|
isAllDirentSelected: false,
|
|
|
|
direntList: direntList,
|
|
|
|
selectedDirentList: [],
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
let direntList = this.state.direntList.map(item => {
|
|
|
|
item.isSelected = true;
|
|
|
|
return item;
|
|
|
|
});
|
|
|
|
this.setState({
|
|
|
|
isDirentSelected: true,
|
|
|
|
isAllDirentSelected: true,
|
|
|
|
direntList: direntList,
|
|
|
|
selectedDirentList: direntList,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
onMainPanelItemRename = (dirent, newName) => {
|
|
|
|
let path = Utils.joinPath(this.state.path, dirent.name);
|
|
|
|
this.renameItem(path, dirent.isDir(), newName);
|
2018-10-13 09:07:54 +00:00
|
|
|
}
|
2018-11-22 03:26:00 +00:00
|
|
|
|
|
|
|
onMainPanelItemDelete = (dirent) => {
|
|
|
|
let path = Utils.joinPath(this.state.path, dirent.name);
|
|
|
|
this.deleteItem(path, dirent.isDir());
|
2018-10-25 05:36:06 +00:00
|
|
|
}
|
2018-10-13 09:07:54 +00:00
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
renameDirent = (direntPath, newName) => {
|
|
|
|
let parentPath = Utils.getDirName(direntPath);
|
|
|
|
let newDirentPath = Utils.joinPath(parentPath, newName);
|
|
|
|
if (direntPath === this.state.path) {
|
|
|
|
// the renamed item is current viewed item
|
|
|
|
// example: direntPath = /A/B/C, state.path = /A/B/C
|
|
|
|
this.setState({ path: newDirentPath });
|
|
|
|
} else if (Utils.isChildPath(direntPath, this.state.path)) {
|
|
|
|
// example: direntPath = /A/B/C/D, state.path = /A/B/C
|
|
|
|
let oldName = Utils.getFileName(direntPath);
|
|
|
|
let direntList = this.state.direntList.map(item => {
|
|
|
|
if (item.name === oldName) {
|
|
|
|
item.name = newName;
|
|
|
|
}
|
|
|
|
return item;
|
|
|
|
});
|
|
|
|
this.setState({ direntList: direntList });
|
|
|
|
} else if (Utils.isAncestorPath(direntPath, this.state.path)) {
|
|
|
|
// example: direntPath = /A/B, state.path = /A/B/C
|
|
|
|
let newPath = Utils.renameAncestorPath(this.state.path, direntPath, newDirentPath);
|
|
|
|
this.setState({ path: newPath });
|
|
|
|
}
|
|
|
|
}
|
2018-10-25 05:36:06 +00:00
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
deleteDirent(direntPath) {
|
|
|
|
if (direntPath === this.state.path) {
|
|
|
|
// The deleted item is current item
|
|
|
|
let parentPath = Utils.getDirName(direntPath);
|
|
|
|
this.showDir(parentPath);
|
|
|
|
} else if (Utils.isChildPath(direntPath, this.state.path)) {
|
|
|
|
// The deleted item is inside current path
|
|
|
|
let name = Utils.getFileName(direntPath);
|
|
|
|
let direntList = this.state.direntList.filter(item => {
|
|
|
|
return item.name !== name;
|
|
|
|
});
|
|
|
|
this.setState({ direntList: direntList });
|
|
|
|
} else if (Utils.isAncestorPath(direntPath, this.state.path)) {
|
|
|
|
// the deleted item is ancester of the current item
|
|
|
|
let parentPath = Utils.getDirName(direntPath);
|
|
|
|
this.showDir(parentPath);
|
|
|
|
}
|
|
|
|
// else do nothing
|
2018-10-25 05:36:06 +00:00
|
|
|
}
|
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
addDirent = (name, type) => {
|
|
|
|
let item = this.createDirent(name, type);
|
|
|
|
let direntList = this.state.direntList;
|
|
|
|
if (type === 'dir') {
|
|
|
|
direntList.unshift(item);
|
|
|
|
} else {
|
|
|
|
direntList.push(item);
|
|
|
|
}
|
|
|
|
this.setState({direntList: direntList});
|
|
|
|
}
|
|
|
|
|
|
|
|
moveDirent = (filePath) => {
|
|
|
|
let name = filePath.slice(filePath.lastIndexOf('/') + 1);
|
|
|
|
let direntList = this.state.direntList.filter(item => {
|
|
|
|
return item.name !== name;
|
2018-10-25 05:36:06 +00:00
|
|
|
});
|
2018-11-22 03:26:00 +00:00
|
|
|
this.setState({direntList: direntList});
|
|
|
|
}
|
|
|
|
|
2018-11-23 12:19:42 +00:00
|
|
|
onMoveItems = (destRepo, destDirentPath) => {
|
|
|
|
let direntPaths = this.getSelectedDirentPaths();
|
|
|
|
let dirNames = this.getSelectedDirentNames();
|
|
|
|
|
|
|
|
seafileAPI.moveDir(repoID, destRepo.repo_id, destDirentPath, this.state.path, dirNames).then(() => {
|
|
|
|
direntPaths.forEach(direntPath => {
|
|
|
|
this.moveTreeNode(direntPath, destDirentPath, destRepo);
|
|
|
|
this.moveDirent(direntPath);
|
|
|
|
});
|
|
|
|
let message = gettext('Successfully moved %(name)s.');
|
|
|
|
message = message.replace('%(name)s', dirNames);
|
2018-12-07 06:58:37 +00:00
|
|
|
toaster.success(message);
|
2018-11-23 12:19:42 +00:00
|
|
|
}).catch(() => {
|
|
|
|
let message = gettext('Failed to move %(name)s');
|
|
|
|
message = message.replace('%(name)s', dirNames);
|
2018-12-07 06:58:37 +00:00
|
|
|
toaster.danger(message);
|
2018-11-27 06:47:19 +00:00
|
|
|
});
|
2018-11-23 12:19:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
onCopyItems = (destRepo, destDirentPath) => {
|
|
|
|
let direntPaths = this.getSelectedDirentPaths();
|
|
|
|
let dirNames = this.getSelectedDirentNames();
|
|
|
|
|
|
|
|
seafileAPI.copyDir(repoID, destRepo.repo_id, destDirentPath, this.state.path, dirNames).then(() => {
|
|
|
|
direntPaths.forEach(direntPath => {
|
|
|
|
this.copyTreeNode(direntPath, destDirentPath, destRepo);
|
|
|
|
});
|
|
|
|
let message = gettext('Successfully copied %(name)s.');
|
|
|
|
message = message.replace('%(name)s', dirNames);
|
2018-12-07 06:58:37 +00:00
|
|
|
toaster.success(message);
|
2018-11-23 12:19:42 +00:00
|
|
|
}).catch(() => {
|
|
|
|
let message = gettext('Failed to copy %(name)s');
|
|
|
|
message = message.replace('%(name)s', dirNames);
|
2018-12-07 06:58:37 +00:00
|
|
|
toaster.danger(message);
|
2018-11-27 06:47:19 +00:00
|
|
|
});
|
2018-11-23 12:19:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
onDeleteItems = () => {
|
|
|
|
let direntPaths = this.getSelectedDirentPaths();
|
|
|
|
let dirNames = this.getSelectedDirentNames();
|
|
|
|
|
|
|
|
seafileAPI.deleteMutipleDirents(repoID, this.state.path, dirNames).then(res => {
|
|
|
|
direntPaths.forEach(direntPath => {
|
|
|
|
let node = this.state.treeData.getNodeByPath(direntPath);
|
|
|
|
this.deleteTreeNode(node);
|
|
|
|
this.deleteDirent(direntPath);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
onFileTagChanged = (dirent, direntPath) => {
|
|
|
|
seafileAPI.listFileTags(repoID, direntPath).then(res => {
|
|
|
|
let fileTags = res.data.file_tags.map(item => {
|
|
|
|
return new FileTag(item);
|
2018-11-23 12:19:42 +00:00
|
|
|
});
|
2018-11-22 03:26:00 +00:00
|
|
|
this.updateDirent(dirent, 'file_tags', fileTags);
|
2018-11-23 12:19:42 +00:00
|
|
|
});
|
2018-10-13 09:07:54 +00:00
|
|
|
}
|
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
onTreeNodeClick = (node) => {
|
2018-11-23 12:19:42 +00:00
|
|
|
this.resetSelected();
|
2018-11-22 03:26:00 +00:00
|
|
|
if (!this.state.pathExist) {
|
|
|
|
this.setState({pathExist: true});
|
|
|
|
}
|
|
|
|
if (node instanceof Node && node.isMarkdown()) {
|
|
|
|
let tree = this.state.treeData.clone();
|
|
|
|
this.setState({treeData: tree});
|
2018-11-23 12:19:42 +00:00
|
|
|
if (node.path !== this.state.path) {
|
2018-11-22 03:26:00 +00:00
|
|
|
this.showFile(node.path);
|
|
|
|
}
|
|
|
|
} else if (node instanceof Node && node.isDir()) {
|
|
|
|
let tree = this.state.treeData.clone();
|
2018-11-23 12:19:42 +00:00
|
|
|
if (this.state.path === node.path) {
|
2018-09-12 06:15:27 +00:00
|
|
|
if (node.isExpanded) {
|
|
|
|
tree.collapseNode(node);
|
|
|
|
} else {
|
|
|
|
tree.expandNode(node);
|
|
|
|
}
|
|
|
|
}
|
2018-11-22 03:26:00 +00:00
|
|
|
this.setState({treeData: tree});
|
2018-11-23 12:19:42 +00:00
|
|
|
if (node.path !== this.state.path) {
|
2018-11-22 03:26:00 +00:00
|
|
|
this.showDir(node.path);
|
|
|
|
}
|
2018-09-12 02:32:31 +00:00
|
|
|
} else {
|
2018-11-22 03:26:00 +00:00
|
|
|
const w = window.open('about:blank');
|
2018-11-29 09:55:14 +00:00
|
|
|
const url = siteRoot + 'lib/' + repoID + '/file' + node.path;
|
2018-09-12 02:32:31 +00:00
|
|
|
w.location.href = url;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
onTreeDirCollapse = (node) => {
|
|
|
|
let tree = this.state.treeData.clone();
|
2018-09-12 02:32:31 +00:00
|
|
|
let findNode = tree.getNodeByPath(node.path);
|
|
|
|
findNode.isExpanded = !findNode.isExpanded;
|
2018-11-22 03:26:00 +00:00
|
|
|
this.setState({treeData: tree});
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
onSideNavMenuClick = () => {
|
2018-09-12 02:32:31 +00:00
|
|
|
this.setState({
|
|
|
|
closeSideBar: !this.state.closeSideBar,
|
2018-09-19 01:57:17 +00:00
|
|
|
});
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
onCloseSide = () => {
|
|
|
|
this.setState({
|
|
|
|
closeSideBar: !this.state.closeSideBar,
|
2018-09-19 01:57:17 +00:00
|
|
|
});
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
onDeleteTreeNode = (node) => {
|
|
|
|
this.deleteItem(node.path, node.isDir());
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
onRenameTreeNode = (node, newName) => {
|
|
|
|
this.renameItem(node.path, node.isDir(), newName);
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
addNodeToTree = (name, parentPath, type) => {
|
|
|
|
let tree = this.state.treeData.clone();
|
2018-09-12 02:32:31 +00:00
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
let node = this.createTreeNode(name, type);
|
|
|
|
let parentNode = tree.getNodeByPath(parentPath);
|
|
|
|
|
|
|
|
tree.addNodeToParent(node, parentNode);
|
|
|
|
this.setState({treeData: tree});
|
2018-10-13 09:07:54 +00:00
|
|
|
}
|
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
renameTreeNode = (node, newName) => {
|
|
|
|
let tree = this.state.treeData.clone();
|
|
|
|
tree.updateNodeParam(node, 'name', newName);
|
|
|
|
this.setState({treeData: tree});
|
|
|
|
}
|
2018-09-12 02:32:31 +00:00
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
deleteTreeNode = (node) => {
|
|
|
|
let tree = this.state.treeData.clone();
|
|
|
|
tree.deleteNode(node);
|
|
|
|
this.setState({treeData: tree});
|
|
|
|
}
|
2018-09-12 02:32:31 +00:00
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
moveTreeNode = (nodePath, moveToPath, moveToRepo) => {
|
|
|
|
let tree = this.state.treeData.clone();
|
2018-10-13 09:07:54 +00:00
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
if (repoID === moveToRepo.repo_id) {
|
|
|
|
tree.moveNodeByPath(nodePath, moveToPath, true);
|
2018-09-12 02:32:31 +00:00
|
|
|
} else {
|
2018-11-22 03:26:00 +00:00
|
|
|
tree.deleteNodeByPath(nodePath);
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
this.setState({treeData: tree});
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
2018-11-27 06:47:19 +00:00
|
|
|
copyTreeNode = (nodePath, copyToPath, destRepo) => {
|
|
|
|
if (repoID !== destRepo.repo_id) {
|
|
|
|
return;
|
|
|
|
}
|
2018-11-22 03:26:00 +00:00
|
|
|
let tree = this.state.treeData.clone();
|
|
|
|
tree.moveNodeByPath(nodePath, copyToPath, false);
|
|
|
|
this.setState({treeData: tree});
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
createTreeNode(name, type) {
|
2018-09-12 02:32:31 +00:00
|
|
|
let date = new Date().getTime()/1000;
|
|
|
|
let node = new Node({
|
2018-09-19 01:57:17 +00:00
|
|
|
name : name,
|
2018-11-22 03:26:00 +00:00
|
|
|
type: type,
|
2018-09-19 01:57:17 +00:00
|
|
|
size: '0',
|
|
|
|
last_update_time: moment.unix(date).fromNow(),
|
2018-11-22 03:26:00 +00:00
|
|
|
isExpanded: false,
|
2018-09-19 01:57:17 +00:00
|
|
|
children: []
|
2018-09-12 02:32:31 +00:00
|
|
|
});
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2018-11-22 03:26:00 +00:00
|
|
|
createDirent(name, type) {
|
|
|
|
let data = new Date().getTime()/1000;
|
|
|
|
let dirent = null;
|
|
|
|
if (type === 'dir') {
|
|
|
|
dirent = new Dirent({
|
|
|
|
id: '000000000000000000',
|
|
|
|
name: name,
|
|
|
|
type: type,
|
|
|
|
mtime: data,
|
|
|
|
permission: 'rw',
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
dirent = new Dirent({
|
|
|
|
id: '000000000000000000',
|
|
|
|
name: name,
|
|
|
|
type: type,
|
|
|
|
mtime: data,
|
|
|
|
permission: 'rw',
|
|
|
|
size: 0,
|
|
|
|
starred: false,
|
|
|
|
is_locked: false,
|
|
|
|
lock_time: '',
|
|
|
|
lock_owner: null,
|
|
|
|
locked_by_me: false,
|
|
|
|
modifier_name: '',
|
|
|
|
modifier_email: '',
|
|
|
|
modifier_contact_email: '',
|
|
|
|
file_tags: []
|
|
|
|
});
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
2018-11-22 03:26:00 +00:00
|
|
|
return dirent;
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
isMarkdownFile(filePath) {
|
2018-09-19 01:57:17 +00:00
|
|
|
let index = filePath.lastIndexOf('.');
|
2018-09-12 02:32:31 +00:00
|
|
|
if (index === -1) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
let type = filePath.substring(index).toLowerCase();
|
2018-09-19 01:57:17 +00:00
|
|
|
if (type === '.md' || type === '.markdown') {
|
2018-09-12 02:32:31 +00:00
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
isInternalMarkdownLink(url) {
|
2018-12-12 02:34:58 +00:00
|
|
|
var re = new RegExp(serviceUrl + '/wiki/lib/' + repoID + '/file' + '.*\.md$');
|
2018-09-12 02:32:31 +00:00
|
|
|
return re.test(url);
|
|
|
|
}
|
|
|
|
|
2018-09-12 06:15:27 +00:00
|
|
|
isInternalDirLink(url) {
|
2018-12-12 02:34:58 +00:00
|
|
|
var re = new RegExp(serviceUrl + '/wiki/lib/' + repoID + '/.*');
|
2018-09-12 06:15:27 +00:00
|
|
|
return re.test(url);
|
|
|
|
}
|
|
|
|
|
2018-09-12 02:32:31 +00:00
|
|
|
getPathFromInternalMarkdownLink(url) {
|
2018-12-12 02:34:58 +00:00
|
|
|
var re = new RegExp(serviceUrl + '/wiki/lib/' + repoID + '/file' + '(.*\.md)');
|
2018-09-12 02:32:31 +00:00
|
|
|
var array = re.exec(url);
|
|
|
|
var path = decodeURIComponent(array[1]);
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2018-09-12 06:15:27 +00:00
|
|
|
getPathFromInternalDirLink(url) {
|
2018-12-12 02:34:58 +00:00
|
|
|
var re = new RegExp(serviceUrl + '/wiki/lib/' + repoID + '(/.*)');
|
2018-09-12 06:15:27 +00:00
|
|
|
var array = re.exec(url);
|
|
|
|
var path = decodeURIComponent(array[1]);
|
|
|
|
|
|
|
|
var dirPath = path.substring(1);
|
2018-09-19 01:57:17 +00:00
|
|
|
re = new RegExp('(^/.*)');
|
2018-09-12 06:15:27 +00:00
|
|
|
if (re.test(dirPath)) {
|
|
|
|
path = dirPath;
|
|
|
|
} else {
|
2018-09-19 01:57:17 +00:00
|
|
|
path = '/' + dirPath;
|
2018-09-12 06:15:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2018-11-23 12:19:42 +00:00
|
|
|
getSelectedDirentPaths = () => {
|
|
|
|
let paths = [];
|
|
|
|
this.state.selectedDirentList.forEach(selectedDirent => {
|
|
|
|
paths.push(Utils.joinPath(this.state.path, selectedDirent.name));
|
|
|
|
});
|
|
|
|
return paths;
|
|
|
|
}
|
|
|
|
|
|
|
|
getSelectedDirentNames = () => {
|
|
|
|
let names = [];
|
|
|
|
this.state.selectedDirentList.forEach(selectedDirent => {
|
|
|
|
names.push(selectedDirent.name);
|
|
|
|
});
|
|
|
|
return names;
|
|
|
|
}
|
|
|
|
|
|
|
|
resetSelected = () => {
|
|
|
|
this.setState({
|
|
|
|
isDirentSelected: false,
|
|
|
|
isAllDirentSelected: false,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-12-14 08:49:55 +00:00
|
|
|
onLibDecryptDialog = () => {
|
|
|
|
this.setState({
|
|
|
|
libNeedDecrypt: false,
|
|
|
|
})
|
|
|
|
|
|
|
|
if (isDir === 'None') {
|
|
|
|
this.setState({pathExist: false});
|
|
|
|
} else if (isDir === 'True') {
|
|
|
|
this.showDir(initialPath);
|
|
|
|
} else if (isDir === 'False') {
|
|
|
|
this.showFile(initialPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.loadSidePanel(initialPath);
|
|
|
|
}
|
|
|
|
|
2018-12-12 02:34:58 +00:00
|
|
|
goReviewPage = () => {
|
|
|
|
window.location.href = siteRoot + 'drafts/review/' + this.state.reviewID;
|
|
|
|
}
|
|
|
|
|
|
|
|
goDraftPage = () => {
|
|
|
|
window.location.href = siteRoot + 'lib/' + repoID + '/file' + this.state.draftFilePath + '?mode=edit';
|
|
|
|
}
|
|
|
|
|
2018-09-12 02:32:31 +00:00
|
|
|
render() {
|
2018-12-14 08:49:55 +00:00
|
|
|
let { libNeedDecrypt } = this.state;
|
|
|
|
if (libNeedDecrypt) {
|
|
|
|
return (
|
|
|
|
<ModalPortal>
|
|
|
|
<LibDecryptDialog repoID={repoID}
|
|
|
|
onLibDecryptDialog={this.onLibDecryptDialog}
|
|
|
|
/>
|
|
|
|
</ModalPortal>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2018-09-12 02:32:31 +00:00
|
|
|
return (
|
|
|
|
<div id="main" className="wiki-main">
|
|
|
|
<SidePanel
|
2018-11-22 03:26:00 +00:00
|
|
|
onNodeClick={this.onTreeNodeClick}
|
|
|
|
onDirCollapse={this.onTreeDirCollapse}
|
2018-09-12 02:32:31 +00:00
|
|
|
closeSideBar={this.state.closeSideBar}
|
|
|
|
onCloseSide ={this.onCloseSide}
|
2018-11-22 03:26:00 +00:00
|
|
|
treeData={this.state.treeData}
|
|
|
|
currentPath={this.state.path}
|
|
|
|
currentNode={this.state.currentNode}
|
|
|
|
onAddFolderNode={this.onAddFolder}
|
|
|
|
onAddFileNode={this.onAddFile}
|
|
|
|
onRenameNode={this.onRenameTreeNode}
|
|
|
|
onDeleteNode={this.onDeleteTreeNode}
|
2018-09-12 02:32:31 +00:00
|
|
|
/>
|
|
|
|
<MainPanel
|
2018-12-12 13:42:23 +00:00
|
|
|
dirID={this.state.dirID}
|
2018-11-22 03:26:00 +00:00
|
|
|
path={this.state.path}
|
|
|
|
isViewFile={this.state.isViewFile}
|
|
|
|
pathExist={this.state.pathExist}
|
|
|
|
isDirentListLoading={this.state.isDirentListLoading}
|
|
|
|
isFileLoading={this.state.isFileLoading}
|
|
|
|
permission={this.state.permission}
|
2018-09-12 02:32:31 +00:00
|
|
|
content={this.state.content}
|
|
|
|
lastModified={this.state.lastModified}
|
2018-11-22 03:26:00 +00:00
|
|
|
latestContributor={this.state.latestContributor}
|
|
|
|
direntList={this.state.direntList}
|
2018-11-23 12:19:42 +00:00
|
|
|
selectedDirentList={this.state.selectedDirentList}
|
2018-11-22 03:26:00 +00:00
|
|
|
updateDirent={this.updateDirent}
|
|
|
|
onSideNavMenuClick={this.onSideNavMenuClick}
|
2018-09-12 02:32:31 +00:00
|
|
|
onSearchedClick={this.onSearchedClick}
|
|
|
|
onMainNavBarClick={this.onMainNavBarClick}
|
2018-11-22 03:26:00 +00:00
|
|
|
onItemClick={this.onDirentClick}
|
2018-11-23 12:19:42 +00:00
|
|
|
onItemSelected={this.onDirentSelected}
|
2018-11-22 03:26:00 +00:00
|
|
|
onItemDelete={this.onMainPanelItemDelete}
|
|
|
|
onItemRename={this.onMainPanelItemRename}
|
2018-12-12 02:34:58 +00:00
|
|
|
onLinkClick={this.onLinkClick}
|
2018-11-22 03:26:00 +00:00
|
|
|
onItemMove={this.onMoveItem}
|
|
|
|
onItemCopy={this.onCopyItem}
|
|
|
|
onAddFile={this.onAddFile}
|
|
|
|
onAddFolder={this.onAddFolder}
|
|
|
|
onFileTagChanged={this.onFileTagChanged}
|
2018-11-23 12:19:42 +00:00
|
|
|
isDirentSelected={this.state.isDirentSelected}
|
|
|
|
isAllDirentSelected={this.state.isAllDirentSelected}
|
|
|
|
onAllDirentSelected={this.onAllDirentSelected}
|
|
|
|
onItemsMove={this.onMoveItems}
|
|
|
|
onItemsCopy={this.onCopyItems}
|
|
|
|
onItemsDelete={this.onDeleteItems}
|
2018-12-06 06:10:36 +00:00
|
|
|
hash={this.hash}
|
2018-12-12 02:34:58 +00:00
|
|
|
isDraft={this.state.isDraft}
|
|
|
|
hasDraft={this.state.hasDraft}
|
|
|
|
reviewStatus={this.state.reviewStatus}
|
2018-12-16 12:45:26 +00:00
|
|
|
reviewID={this.state.reviewID}
|
2018-12-12 02:34:58 +00:00
|
|
|
goDraftPage={this.goDraftPage}
|
|
|
|
goReviewPage={this.goReviewPage}
|
2018-09-12 02:32:31 +00:00
|
|
|
/>
|
|
|
|
</div>
|
2018-09-29 07:47:53 +00:00
|
|
|
);
|
2018-09-12 02:32:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ReactDOM.render (
|
|
|
|
<Wiki />,
|
|
|
|
document.getElementById('wrapper')
|
2018-09-29 10:32:53 +00:00
|
|
|
);
|