1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-07-18 17:22:05 +00:00
seahub/frontend/src/repo-wiki-mode.js

889 lines
26 KiB
JavaScript
Raw Normal View History

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';
import { seafileAPI } from './utils/seafile-api';
2018-11-22 03:26:00 +00:00
import { Utils } from './utils/utils';
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';
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';
import './css/side-panel.css';
import './css/wiki.css';
2018-09-19 01:57:17 +00:00
import './css/toolbar.css';
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(),
closeSideBar: false,
2018-11-22 03:26:00 +00:00
currentNode: null,
isDirentListLoading: true,
isViewFile: false,
direntList: [],
isFileLoading: true,
content: '',
lastModified: '',
2018-11-22 03:26:00 +00:00
latestContributor: '',
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: '',
};
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;
}
}
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-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
};
});
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});
} else {
2018-11-22 03:26:00 +00:00
this.setState({treeData: treeData});
}
2018-11-22 03:26:00 +00:00
}).catch(() => {
/* eslint-disable */
2018-09-19 01:57:17 +00:00
console.log('failed to load files');
/* eslint-enable */
2018-11-22 03:26:00 +00:00
this.setState({isLoadFailed: true});
2018-09-19 01:57:17 +00:00
});
}
2018-11-22 03:26:00 +00:00
showFile = (filePath) => {
this.setState({
path: filePath,
isViewFile: true
});
2018-11-22 03:26:00 +00:00
this.setState({isFileLoading: true});
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;
seafileAPI.getFileDownloadLink(repoID, filePath).then((res) => {
2018-11-22 03:26:00 +00:00
seafileAPI.getFileContent(res.data).then((res) => {
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-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-11-22 03:26:00 +00:00
showDir = (path) => {
this.loadDirentList(path);
this.setState({
path: path,
isViewFile: false
});
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-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});
}
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-11-22 03:26:00 +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;
}
}
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();
let node = tree.getNodeByPath(nodePath);
2018-09-12 06:15:27 +00:00
tree.expandNode(node);
2018-11-22 03:26:00 +00:00
this.setState({treeData: tree, currentNode: node});
this.showDir(node.path);
}
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
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);
} 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);
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-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-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-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-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-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-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-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);
}
} 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;
w.location.href = url;
}
}
2018-11-22 03:26:00 +00:00
onTreeDirCollapse = (node) => {
let tree = this.state.treeData.clone();
let findNode = tree.getNodeByPath(node.path);
findNode.isExpanded = !findNode.isExpanded;
2018-11-22 03:26:00 +00:00
this.setState({treeData: tree});
}
2018-11-22 03:26:00 +00:00
onSideNavMenuClick = () => {
this.setState({
closeSideBar: !this.state.closeSideBar,
2018-09-19 01:57:17 +00:00
});
}
onCloseSide = () => {
this.setState({
closeSideBar: !this.state.closeSideBar,
2018-09-19 01:57:17 +00:00
});
}
2018-11-22 03:26:00 +00:00
onDeleteTreeNode = (node) => {
this.deleteItem(node.path, node.isDir());
}
2018-11-22 03:26:00 +00:00
onRenameTreeNode = (node, newName) => {
this.renameItem(node.path, node.isDir(), newName);
}
2018-11-22 03:26:00 +00:00
addNodeToTree = (name, parentPath, type) => {
let tree = this.state.treeData.clone();
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-11-22 03:26:00 +00:00
deleteTreeNode = (node) => {
let tree = this.state.treeData.clone();
tree.deleteNode(node);
this.setState({treeData: tree});
}
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);
} else {
2018-11-22 03:26:00 +00:00
tree.deleteNodeByPath(nodePath);
}
2018-11-22 03:26:00 +00:00
this.setState({treeData: tree});
}
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-11-22 03:26:00 +00:00
createTreeNode(name, type) {
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: []
});
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-11-22 03:26:00 +00:00
return dirent;
}
isMarkdownFile(filePath) {
2018-09-19 01:57:17 +00:00
let index = filePath.lastIndexOf('.');
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') {
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$');
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);
}
getPathFromInternalMarkdownLink(url) {
2018-12-12 02:34:58 +00:00
var re = new RegExp(serviceUrl + '/wiki/lib/' + repoID + '/file' + '(.*\.md)');
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';
}
render() {
2018-12-14 08:49:55 +00:00
let { libNeedDecrypt } = this.state;
if (libNeedDecrypt) {
return (
<ModalPortal>
<LibDecryptDialog repoID={repoID}
onLibDecryptDialog={this.onLibDecryptDialog}
/>
</ModalPortal>
)
}
return (
<div id="main" className="wiki-main">
<SidePanel
2018-11-22 03:26:00 +00:00
onNodeClick={this.onTreeNodeClick}
onDirCollapse={this.onTreeDirCollapse}
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}
/>
<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}
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}
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}
/>
</div>
2018-09-29 07:47:53 +00:00
);
}
}
ReactDOM.render (
<Wiki />,
document.getElementById('wrapper')
);