mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-02 07:27:04 +00:00
View repo content in list mode (#2579)
This commit is contained in:
@@ -124,7 +124,7 @@ class CopyDirent extends React.Component {
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.onItemCopy(repo, direntPath, selectedPath);
|
||||
this.props.onItemCopy(repo, this.props.dirent, selectedPath);
|
||||
this.toggle();
|
||||
}
|
||||
|
||||
|
@@ -124,7 +124,7 @@ class MoveDirent extends React.Component {
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.onItemMove(repo, direntPath, selectedPath);
|
||||
this.props.onItemMove(repo, this.props.dirent, selectedPath);
|
||||
this.toggle();
|
||||
}
|
||||
|
||||
|
208
frontend/src/components/dir-view/dir-panel.js
Normal file
208
frontend/src/components/dir-view/dir-panel.js
Normal file
@@ -0,0 +1,208 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import cookie from 'react-cookies';
|
||||
import { gettext, siteRoot } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import CommonToolbar from '../toolbar/common-toolbar';
|
||||
import ViewModeToolbar from '../toolbar/view-mode-toolbar';
|
||||
import DirOperationToolBar from '../toolbar/dir-operation-toolbar';
|
||||
import MutipleDirOperationToolbar from '../toolbar/mutilple-dir-operation-toolbar';
|
||||
import CurDirPath from '../cur-dir-path';
|
||||
import DirentListView from '../dirent-list-view/dirent-list-view';
|
||||
import DirentDetail from '../dirent-detail/dirent-details';
|
||||
import FileUploader from '../file-uploader/file-uploader';
|
||||
|
||||
const propTypes = {
|
||||
currentRepo: PropTypes.object,
|
||||
path: PropTypes.string.isRequired,
|
||||
repoID: PropTypes.string.isRequired,
|
||||
repoName: PropTypes.string.isRequired,
|
||||
pathExist: PropTypes.bool.isRequired,
|
||||
permission: PropTypes.bool.isRequired,
|
||||
isDirentListLoading: PropTypes.bool.isRequired,
|
||||
isDirentSelected: PropTypes.bool.isRequired,
|
||||
isAllDirentSelected: PropTypes.bool.isRequired,
|
||||
direntList: PropTypes.array.isRequired,
|
||||
selectedDirentList: PropTypes.array.isRequired,
|
||||
onItemClick: PropTypes.func.isRequired,
|
||||
onAddFile: PropTypes.func.isRequired,
|
||||
onAddFolder: PropTypes.func.isRequired,
|
||||
onItemMove: PropTypes.func.isRequired,
|
||||
onItemCopy: PropTypes.func.isRequired,
|
||||
onItemRename: PropTypes.func.isRequired,
|
||||
onItemDelete: PropTypes.func.isRequired,
|
||||
onItemSelected: PropTypes.func.isRequired,
|
||||
onItemsCopy: PropTypes.func.isRequired,
|
||||
onItemsMove: PropTypes.func.isRequired,
|
||||
onItemsDelete: PropTypes.func.isRequired,
|
||||
onAllItemSelected: PropTypes.func.isRequired,
|
||||
onFileTagChanged: PropTypes.func.isRequired,
|
||||
onMenuClick: PropTypes.func.isRequired,
|
||||
onPathClick: PropTypes.func.isRequired,
|
||||
updateDirent: PropTypes.func.isRequired,
|
||||
onSearchedClick: PropTypes.func.isRequired,
|
||||
onFileUploadSuccess: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class DirPanel extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
currentDirent: null,
|
||||
currentMode: 'list',
|
||||
isDirentDetailShow: false,
|
||||
isRepoOwner: true,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
let currentRepo = this.props.currentRepo;
|
||||
if (currentRepo) {
|
||||
seafileAPI.getAccountInfo().then(res => {
|
||||
let user_email = res.data.email;
|
||||
let isRepoOwner = currentRepo.owner_email === user_email;
|
||||
this.setState({isRepoOwner: isRepoOwner});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onItemDetails = (dirent) => {
|
||||
this.setState({
|
||||
currentDirent: dirent,
|
||||
isDirentDetailShow: true,
|
||||
});
|
||||
}
|
||||
|
||||
onItemDetailsClose = () => {
|
||||
this.setState({isDirentDetailShow: false});
|
||||
}
|
||||
|
||||
onUploadFile = (e) => {
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
this.uploader.onFileUpload();
|
||||
}
|
||||
|
||||
onUploadFolder = (e) => {
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
this.uploader.onFolderUpload();
|
||||
}
|
||||
|
||||
switchViewMode = (mode) => {
|
||||
let { path, repoID } = this.props;
|
||||
if (mode === this.state.currentMode) {
|
||||
return;
|
||||
}
|
||||
if (mode === 'wiki') {
|
||||
var url = siteRoot + 'wiki/lib/' + repoID + path;
|
||||
window.location = url;
|
||||
}
|
||||
cookie.save('view_mode', mode, { path: '/' });
|
||||
|
||||
this.setState({currentMode: mode});
|
||||
}
|
||||
|
||||
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-north">
|
||||
<div className="cur-view-toolbar border-left-show">
|
||||
<span className="sf2-icon-menu hidden-md-up d-md-none side-nav-toggle" title={gettext('Side Nav Menu')} onClick={this.props.onMenuClick}></span>
|
||||
<div className="dir-operation">
|
||||
{this.props.isDirentSelected ?
|
||||
<MutipleDirOperationToolbar
|
||||
path={this.props.path}
|
||||
repoID={this.props.repoID}
|
||||
selectedDirentList={this.props.selectedDirentList}
|
||||
onItemsMove={this.props.onItemsMove}
|
||||
onItemsCopy={this.props.onItemsCopy}
|
||||
onItemsDelete={this.props.onItemsDelete}
|
||||
/> :
|
||||
<DirOperationToolBar
|
||||
path={this.props.path}
|
||||
repoID={this.props.repoID}
|
||||
onAddFile={this.props.onAddFile}
|
||||
onAddFolder={this.props.onAddFolder}
|
||||
onUploadFile={this.onUploadFile}
|
||||
onUploadFolder={this.onUploadFolder}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
<ViewModeToolbar
|
||||
currentMode={this.state.currentMode}
|
||||
switchViewMode={this.switchViewMode}
|
||||
/>
|
||||
</div>
|
||||
<CommonToolbar
|
||||
repoID={this.props.repoID}
|
||||
onSearchedClick={this.props.onSearchedClick}
|
||||
searchPlaceholder={'Search files in this library'}
|
||||
/>
|
||||
</div>
|
||||
<div className="main-panel-center flex-direction-row">
|
||||
<div className="cur-view-container">
|
||||
<div className="cur-view-path">
|
||||
<CurDirPath
|
||||
repoID={this.props.repoID}
|
||||
repoName={this.props.repoName}
|
||||
currentPath={this.props.path}
|
||||
permission={this.props.permission}
|
||||
onPathClick={this.props.onPathClick}
|
||||
/>
|
||||
</div>
|
||||
<div className="cur-view-content">
|
||||
{!this.props.pathExist ?
|
||||
ErrMessage :
|
||||
<Fragment>
|
||||
<DirentListView
|
||||
path={this.props.path}
|
||||
repoID={this.props.repoID}
|
||||
direntList={this.props.direntList}
|
||||
currentRepo={this.props.currentRepo}
|
||||
isDirentListLoading={this.props.isDirentListLoading}
|
||||
isAllItemSelected={this.props.isAllDirentSelected}
|
||||
isRepoOwner={this.state.isRepoOwner}
|
||||
onItemDetails={this.onItemDetails}
|
||||
onItemMove={this.props.onItemMove}
|
||||
onItemCopy={this.props.onItemCopy}
|
||||
onItemClick={this.props.onItemClick}
|
||||
onItemDelete={this.props.onItemDelete}
|
||||
onItemRename={this.props.onItemRename}
|
||||
onItemSelected={this.props.onItemSelected}
|
||||
onAllItemSelected={this.props.onAllItemSelected}
|
||||
updateDirent={this.props.updateDirent}
|
||||
/>
|
||||
<FileUploader
|
||||
dragAndDrop={true}
|
||||
ref={uploader => this.uploader = uploader}
|
||||
path={this.props.path}
|
||||
repoID={this.props.repoID}
|
||||
direntList={this.props.direntList}
|
||||
onFileUploadSuccess={this.props.onFileUploadSuccess}
|
||||
/>
|
||||
</Fragment>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
{this.state.isDirentDetailShow && (
|
||||
<div className="cur-view-detail">
|
||||
<DirentDetail
|
||||
path={this.props.path}
|
||||
repoID={this.props.repoID}
|
||||
dirent={this.state.currentDirent}
|
||||
onFileTagChanged={this.props.onFileTagChanged}
|
||||
onItemDetailsClose={this.onItemDetailsClose}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DirPanel.propTypes = propTypes;
|
||||
|
||||
export default DirPanel;
|
465
frontend/src/components/dir-view/dir-view.js
Normal file
465
frontend/src/components/dir-view/dir-view.js
Normal file
@@ -0,0 +1,465 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { siteRoot } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import Toast from '../toast';
|
||||
import DirPanel from './dir-panel';
|
||||
import Dirent from '../../models/dirent';
|
||||
import FileTag from '../../models/file-tag';
|
||||
import Repo from '../../models/repo';
|
||||
|
||||
const propTypes = {
|
||||
onMenuClick: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class DirView extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
path: '/',
|
||||
pathExit: true,
|
||||
repoName: '',
|
||||
repoID: '',
|
||||
permission: true,
|
||||
isDirentSelected: false,
|
||||
isAllDirentSelected: false,
|
||||
isDirentListLoading: true,
|
||||
currentRepo: null,
|
||||
direntList: [],
|
||||
selectedDirentList: [],
|
||||
};
|
||||
window.onpopstate = this.onpopstate;
|
||||
}
|
||||
|
||||
onpopstate = (event) => {
|
||||
if (event.state && event.state.path) {
|
||||
this.updateDirentList(event.state.path);
|
||||
this.setState({path: event.state.path});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
let repoID = this.props.repoID;
|
||||
let index = location.href.indexOf(repoID) + repoID.length;
|
||||
let path = decodeURIComponent(location.href.slice(index));
|
||||
seafileAPI.getRepoInfo(repoID).then(res => {
|
||||
let repo = new Repo(res.data);
|
||||
this.setState({
|
||||
repoID: repo.repo_id,
|
||||
repoName: repo.repo_name,
|
||||
permission: repo.permission === 'rw',
|
||||
currentRepo: repo,
|
||||
});
|
||||
this.updateDirentList(path);
|
||||
this.setState({path: path});
|
||||
});
|
||||
}
|
||||
|
||||
updateDirentList = (filePath) => {
|
||||
let repoID = this.state.repoID;
|
||||
this.setState({isDirentListLoading: true});
|
||||
seafileAPI.listDir(repoID, filePath).then(res => {
|
||||
let direntList = res.data.map(item => {
|
||||
return new Dirent(item);
|
||||
});
|
||||
this.setState({
|
||||
isDirentListLoading: false,
|
||||
direntList: direntList,
|
||||
});
|
||||
}).catch(() => {
|
||||
this.setState({pathExist: false});
|
||||
});
|
||||
}
|
||||
|
||||
onItemClick = (dirent) => {
|
||||
this.resetSelected();
|
||||
let direntPath = Utils.joinPath(this.state.path, dirent.name);
|
||||
if (dirent.isDir()) {
|
||||
this.updateDirentList(direntPath);
|
||||
this.setState({path: direntPath});
|
||||
|
||||
let fileUrl = siteRoot + 'librarys/' + this.state.repoID + direntPath;
|
||||
window.history.pushState({url: fileUrl, path: direntPath}, direntPath, fileUrl);
|
||||
} else {
|
||||
const w=window.open('about:blank');
|
||||
const url = siteRoot + 'lib/' + this.state.repoID + '/file' + direntPath;
|
||||
w.location.href = url;
|
||||
}
|
||||
}
|
||||
|
||||
onAddFolder = (dirPath) => {
|
||||
let repoID = this.state.repoID;
|
||||
seafileAPI.createDir(repoID, dirPath).then(() => {
|
||||
let name = Utils.getFileName(dirPath);
|
||||
let dirent = this.createDirent(name, 'dir');
|
||||
let direntList = this.addItem(dirent, 'dir');
|
||||
this.setState({direntList: direntList});
|
||||
});
|
||||
}
|
||||
|
||||
onAddFile = (filePath, isDraft) => {
|
||||
let repoID = this.state.repoID;
|
||||
seafileAPI.createDir(repoID, filePath).then(() => {
|
||||
let name = Utils.getFileName(filePath);
|
||||
let dirent = this.createDirent(name, 'file');
|
||||
let direntList = this.addItem(dirent, 'file');
|
||||
this.setState({direntList: direntList});
|
||||
});
|
||||
}
|
||||
|
||||
onItemDelete = (dirent) => {
|
||||
let repoID = this.state.repoID;
|
||||
let direntPath = Utils.joinPath(this.state.path, dirent.name);
|
||||
if (dirent.isDir()) {
|
||||
seafileAPI.deleteDir(repoID, direntPath).then(() => {
|
||||
let direntList = this.deleteItem(dirent);
|
||||
this.setState({direntList: direntList});
|
||||
}).catch(() => {
|
||||
// todo
|
||||
})
|
||||
} else {
|
||||
seafileAPI.deleteFile(repoID, direntPath).then(() => {
|
||||
let direntList = this.deleteItem(dirent);
|
||||
this.setState({direntList: direntList});
|
||||
}).catch(() => {
|
||||
// todo
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
onItemRename = (dirent, newName) => {
|
||||
let repoID = this.state.repoID;
|
||||
let direntPath = Utils.joinPath(this.state.path, dirent.name);
|
||||
if (dirent.isDir()) {
|
||||
seafileAPI.renameDir(repoID, direntPath, newName).then(() => {
|
||||
let direntList = this.renameItem(dirent, newName);
|
||||
this.setState({direntList: direntList});
|
||||
}).catch(() => {
|
||||
//todo
|
||||
});
|
||||
} else {
|
||||
seafileAPI.renameFile(repoID, direntPath, newName).then(() => {
|
||||
let direntList = this.renameItem(dirent, newName);
|
||||
this.setState({direntList: direntList});
|
||||
}).catch(() => {
|
||||
//todo
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onItemMove = (destRepo, dirent, moveToDirentPath) => {
|
||||
let dirName = dirent.name;
|
||||
let repoID = this.state.repoID;
|
||||
seafileAPI.moveDir(repoID, destRepo.repo_id, moveToDirentPath, this.state.path, dirName).then(() => {
|
||||
|
||||
let direntList = this.deleteItem(dirent);
|
||||
this.setState(direntList);
|
||||
|
||||
let message = gettext('Successfully moved %(name)s.');
|
||||
message = message.replace('%(name)s', dirName);
|
||||
Toast.success(message);
|
||||
}).catch(() => {
|
||||
let message = gettext('Failed to move %(name)s');
|
||||
message = message.replace('%(name)s', dirName);
|
||||
Toast.error(message);
|
||||
});
|
||||
}
|
||||
|
||||
onItemCopy = (destRepo, dirent, copyToDirentPath) => {
|
||||
let dirName = dirent.name;
|
||||
let repoID = this.state.repoID;
|
||||
seafileAPI.copyDir(repoID, destRepo.repo_id, copyToDirentPath, this.state.path, dirName).then(() => {
|
||||
let message = gettext('Successfully copied %(name)s.');
|
||||
message = message.replace('%(name)s', dirName);
|
||||
Toast.success(message);
|
||||
}).catch(() => {
|
||||
let message = gettext('Failed to copy %(name)s');
|
||||
message = message.replace('%(name)s', dirName);
|
||||
Toast.error(message);
|
||||
});
|
||||
}
|
||||
|
||||
onItemSelected = (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: []
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onItemsMove = (destRepo, destDirentPath) => {
|
||||
let dirNames = this.getSelectedDirentNames();
|
||||
let repoID = this.state.repoID;
|
||||
seafileAPI.moveDir(repoID, destRepo.repo_id, destDirentPath, this.state.path, dirNames).then(() => {
|
||||
let direntList = this.deleteItems(dirNames);
|
||||
this.setState({direntList: direntList});
|
||||
let message = gettext('Successfully moved %(name)s.');
|
||||
message = message.replace('%(name)s', dirNames);
|
||||
Toast.success(message);
|
||||
}).catch(() => {
|
||||
let message = gettext('Failed to move %(name)s');
|
||||
message = message.replace('%(name)s', dirNames);
|
||||
Toast.error(message);
|
||||
});
|
||||
}
|
||||
|
||||
onItemsCopy = (destRepo, destDirentPath) => {
|
||||
let dirNames = this.getSelectedDirentNames();
|
||||
let repoID = this.state.repoID;
|
||||
seafileAPI.copyDir(repoID, destRepo.repo_id, destDirentPath, this.state.path, dirNames).then(() => {
|
||||
let message = gettext('Successfully copied %(name)s.');
|
||||
message = message.replace('%(name)s', dirNames);
|
||||
Toast.success(message);
|
||||
}).catch(() => {
|
||||
let message = gettext('Failed to copy %(name)s');
|
||||
message = message.replace('%(name)s', dirNames);
|
||||
Toast.error(message);
|
||||
});
|
||||
}
|
||||
|
||||
onItemsDelete = () => {
|
||||
let dirNames = this.getSelectedDirentNames();
|
||||
let repoID = this.state.repoID;
|
||||
seafileAPI.deleteMutipleDirents(repoID, this.state.path, dirNames).then(res => {
|
||||
let direntList = this.deleteItems(dirNames);
|
||||
this.setState({direntList: direntList});
|
||||
});
|
||||
}
|
||||
|
||||
onAllItemSelected = () => {
|
||||
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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onFileTagChanged = (dirent, direntPath) => {
|
||||
let repoID = this.state.repoID;
|
||||
seafileAPI.listFileTags(repoID, direntPath).then(res => {
|
||||
let fileTags = res.data.file_tags.map(item => {
|
||||
return new FileTag(item);
|
||||
});
|
||||
this.updateDirent(dirent, 'file_tags', fileTags);
|
||||
});
|
||||
}
|
||||
|
||||
onMenuClick = () => {
|
||||
this.props.onMenuClick();
|
||||
}
|
||||
|
||||
onPathClick = (path) => {
|
||||
this.updateDirentList(path);
|
||||
this.setState({path: path});
|
||||
|
||||
let fileUrl = siteRoot + 'librarys/' + this.state.repoID + path;
|
||||
window.history.pushState({url: fileUrl, path: path}, path, fileUrl);
|
||||
}
|
||||
|
||||
updateDirent = (dirent, paramKey, paramValue) => {
|
||||
let newDirentList = this.state.direntList.map(item => {
|
||||
if (item.name === dirent.name) {
|
||||
item[paramKey] = paramValue;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
this.setState({direntList: newDirentList});
|
||||
}
|
||||
|
||||
onFileUploadSuccess = () => {
|
||||
// todo update upload file to direntList
|
||||
}
|
||||
|
||||
onSearchedClick = () => {
|
||||
// todo
|
||||
}
|
||||
|
||||
resetSelected = () => {
|
||||
this.setState({isDirentSelected: false, isAllDirentSelected: false});
|
||||
}
|
||||
|
||||
addItem = (dirent, type) => {
|
||||
let direntList = this.state.direntList.map(item => {return item}); //clone
|
||||
if (type === 'dir') {
|
||||
direntList.unshift(dirent);
|
||||
return direntList;
|
||||
}
|
||||
direntList.push(dirent);
|
||||
return direntList;
|
||||
}
|
||||
|
||||
deleteItem = (dirent) => {
|
||||
return this.state.direntList.filter(item => {
|
||||
return item.name !== dirent.name;
|
||||
});
|
||||
}
|
||||
|
||||
renameItem = (dirent, newName) => {
|
||||
return this.state.direntList.map(item => {
|
||||
if (item.name === dirent.name) {
|
||||
item.name = newName;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
}
|
||||
|
||||
deleteItems = (dirNames) => {
|
||||
let direntList = this.state.direntList.map(item => {return item}); //clone
|
||||
while (dirNames.length) {
|
||||
for (let i = 0; i < direntList.length; i++) {
|
||||
if (direntList[i].name === dirNames[0]) {
|
||||
direntList.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
dirNames.shift();
|
||||
}
|
||||
return direntList;
|
||||
}
|
||||
|
||||
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: []
|
||||
});
|
||||
}
|
||||
return dirent;
|
||||
}
|
||||
|
||||
getSelectedDirentNames = () => {
|
||||
let names = [];
|
||||
this.state.selectedDirentList.forEach(selectedDirent => {
|
||||
names.push(selectedDirent.name);
|
||||
});
|
||||
return names;
|
||||
}
|
||||
|
||||
isMarkdownFile(filePath) {
|
||||
let index = filePath.lastIndexOf('.');
|
||||
if (index === -1) {
|
||||
return false;
|
||||
} else {
|
||||
let type = filePath.substring(index).toLowerCase();
|
||||
if (type === '.md' || type === '.markdown') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<DirPanel
|
||||
currentRepo={this.state.currentRepo}
|
||||
path={this.state.path}
|
||||
pathExist={this.state.pathExit}
|
||||
repoID={this.state.repoID}
|
||||
repoName={this.state.repoName}
|
||||
permission={this.state.permission}
|
||||
isDirentListLoading={this.state.isDirentListLoading}
|
||||
isDirentSelected={this.state.isDirentSelected}
|
||||
isAllDirentSelected={this.state.isAllDirentSelected}
|
||||
direntList={this.state.direntList}
|
||||
selectedDirentList={this.state.direntList}
|
||||
onItemClick={this.onItemClick}
|
||||
onAddFile={this.onAddFile}
|
||||
onAddFolder={this.onAddFolder}
|
||||
onItemMove={this.onItemMove}
|
||||
onItemCopy={this.onItemCopy}
|
||||
onItemRename={this.onItemRename}
|
||||
onItemDelete={this.onItemDelete}
|
||||
onItemSelected={this.onItemSelected}
|
||||
onItemsMove={this.onItemsMove}
|
||||
onItemsCopy={this.onItemsCopy}
|
||||
onItemsDelete={this.onItemsDelete}
|
||||
onAllItemSelected={this.onAllItemSelected}
|
||||
onFileTagChanged={this.onFileTagChanged}
|
||||
onMenuClick={this.onMenuClick}
|
||||
onPathClick={this.onPathClick}
|
||||
updateDirent={this.updateDirent}
|
||||
switchViewMode={this.switchViewMode}
|
||||
onSearchedClick={this.onSearchedClick}
|
||||
onFileUploadSuccess={this.onFileUploadSuccess}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DirView.propTypes = propTypes;
|
||||
|
||||
export default DirView;
|
@@ -11,7 +11,7 @@ const propTypes = {
|
||||
dirent: PropTypes.object.isRequired,
|
||||
direntType: PropTypes.string.isRequired,
|
||||
direntDetail: PropTypes.object.isRequired,
|
||||
direntPath: PropTypes.string.isRequired,
|
||||
path: PropTypes.string.isRequired,
|
||||
fileTagList: PropTypes.array.isRequired,
|
||||
onFileTagChanged: PropTypes.func.isRequired,
|
||||
};
|
||||
@@ -26,7 +26,8 @@ class DetailListView extends React.Component {
|
||||
}
|
||||
|
||||
getDirentPostion = () => {
|
||||
let { repo, direntPath } = this.props;
|
||||
let { repo } = this.props;
|
||||
let direntPath = this.getDirentPath();
|
||||
let position = repo.repo_name;
|
||||
if (direntPath !== '/') {
|
||||
let index = direntPath.lastIndexOf('/');
|
||||
@@ -43,12 +44,19 @@ class DetailListView extends React.Component {
|
||||
}
|
||||
|
||||
onFileTagChanged = () => {
|
||||
this.props.onFileTagChanged(this.props.dirent, this.props.direntPath);
|
||||
let direntPath = this.getDirentPath();
|
||||
this.props.onFileTagChanged(this.props.dirent, direntPath);
|
||||
}
|
||||
|
||||
getDirentPath = () => {
|
||||
let { dirent, path } = this.props;
|
||||
return Utils.joinPath(path, dirent.name);
|
||||
}
|
||||
|
||||
render() {
|
||||
let { direntType, direntDetail, fileTagList } = this.props;
|
||||
let position = this.getDirentPostion();
|
||||
let direntPath = this.getDirentPath();
|
||||
if (direntType === 'dir') {
|
||||
return (
|
||||
<table>
|
||||
@@ -93,7 +101,7 @@ class DetailListView extends React.Component {
|
||||
<EditFileTagDialog
|
||||
repoID={this.props.repoID}
|
||||
fileTagList={fileTagList}
|
||||
filePath={this.props.direntPath}
|
||||
filePath={direntPath}
|
||||
toggleCancel={this.onEditFileTagToggle}
|
||||
onFileTagChanged={this.onFileTagChanged}
|
||||
/>
|
||||
|
@@ -1,5 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import { siteRoot } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import DetailListView from './detail-list-view';
|
||||
import Repo from '../../models/repo';
|
||||
@@ -8,9 +10,8 @@ import '../../css/dirent-detail.css';
|
||||
|
||||
const propTypes = {
|
||||
repoID: PropTypes.string.isRequired,
|
||||
serviceUrl: PropTypes.string.isRequired,
|
||||
dirent: PropTypes.object.isRequired,
|
||||
direntPath: PropTypes.string.isRequired,
|
||||
path: PropTypes.string.isRequired,
|
||||
onItemDetailsClose: PropTypes.func.isRequired,
|
||||
onFileTagChanged: PropTypes.func.isRequired,
|
||||
};
|
||||
@@ -28,7 +29,8 @@ class DirentDetail extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
let { dirent, direntPath, repoID } = this.props;
|
||||
let { dirent, path, repoID } = this.props;
|
||||
let direntPath = Utils.joinPath(path, dirent.name);
|
||||
seafileAPI.getRepoInfo(repoID).then(res => {
|
||||
let repo = new Repo(res.data);
|
||||
this.setState({repo: repo});
|
||||
@@ -37,7 +39,9 @@ class DirentDetail extends React.Component {
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.updateDetailView(nextProps.dirent, nextProps.direntPath);
|
||||
let { dirent, path } = nextProps;
|
||||
let direntPath = Utils.joinPath(path, dirent.name);
|
||||
this.updateDetailView(dirent, direntPath);
|
||||
}
|
||||
|
||||
updateDetailView = (dirent, direntPath) => {
|
||||
@@ -68,27 +72,27 @@ class DirentDetail extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
let { dirent, serviceUrl } = this.props;
|
||||
let { dirent } = this.props;
|
||||
return (
|
||||
<div className="detail-container">
|
||||
<div className="detail-header">
|
||||
<div className="detail-control sf2-icon-x1" onClick={this.props.onItemDetailsClose}></div>
|
||||
<div className="detail-title dirent-title">
|
||||
<img src={dirent.type === 'dir' ? serviceUrl + '/media/img/folder-192.png' : serviceUrl + '/media/img/file/192/txt.png'} alt="icon"></img>
|
||||
<img src={dirent.type === 'dir' ? siteRoot + 'media/img/folder-192.png' : siteRoot + 'media/img/file/192/txt.png'} alt="icon"></img>
|
||||
<span className="name">{dirent.name}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="detail-body dirent-info">
|
||||
<div className="img">
|
||||
<img src={dirent.type === 'dir' ? serviceUrl + '/media/img/folder-192.png' : serviceUrl + '/media/img/file/192/txt.png'} alt="icon"></img>
|
||||
<img src={dirent.type === 'dir' ? siteRoot + 'media/img/folder-192.png' : siteRoot + 'media/img/file/192/txt.png'} alt="icon"></img>
|
||||
</div>
|
||||
{this.state.direntDetail &&
|
||||
<div className="dirent-table-container">
|
||||
<DetailListView
|
||||
repo={this.state.repo}
|
||||
path={this.props.path}
|
||||
repoID={this.props.repoID}
|
||||
dirent={this.props.dirent}
|
||||
direntPath={this.props.direntPath}
|
||||
direntType={this.state.direntType}
|
||||
direntDetail={this.state.direntDetail}
|
||||
fileTagList={this.state.fileTagList}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import { gettext, siteRoot } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import URLDecorator from '../../utils/url-decorator';
|
||||
import Toast from '../toast';
|
||||
@@ -14,7 +14,6 @@ import CopyDirentDialog from '../dialog/copy-dirent-dialog';
|
||||
const propTypes = {
|
||||
path: PropTypes.string.isRequired,
|
||||
repoID: PropTypes.string.isRequired,
|
||||
serviceUrl: PropTypes.string.isRequired,
|
||||
isItemFreezed: PropTypes.bool.isRequired,
|
||||
dirent: PropTypes.object.isRequired,
|
||||
onItemClick: PropTypes.func.isRequired,
|
||||
@@ -139,8 +138,7 @@ class DirentListItem extends React.Component {
|
||||
}
|
||||
|
||||
onItemClick = () => {
|
||||
let direntPath = this.getDirentPath(this.props.dirent);
|
||||
this.props.onItemClick(direntPath);
|
||||
this.props.onItemClick(this.props.dirent);
|
||||
}
|
||||
|
||||
onItemDelete = (e) => {
|
||||
@@ -244,8 +242,7 @@ class DirentListItem extends React.Component {
|
||||
}
|
||||
|
||||
onDetailsItem = () => {
|
||||
let direntPath = this.getDirentPath(this.props.dirent);
|
||||
this.props.onItemDetails(this.props.dirent, direntPath);
|
||||
this.props.onItemDetails(this.props.dirent);
|
||||
this.onItemMenuHide();
|
||||
}
|
||||
|
||||
@@ -368,7 +365,7 @@ class DirentListItem extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
let { dirent, serviceUrl } = this.props;
|
||||
let { dirent } = this.props;
|
||||
return (
|
||||
<Fragment>
|
||||
<tr className={this.state.highlight ? 'tr-highlight' : ''} onMouseEnter={this.onMouseEnter} onMouseOver={this.onMouseOver} onMouseLeave={this.onMouseLeave}>
|
||||
@@ -381,8 +378,8 @@ class DirentListItem extends React.Component {
|
||||
</td>
|
||||
<td className="icon">
|
||||
<div className="dir-icon">
|
||||
<img src={dirent.type === 'dir' ? serviceUrl + '/media/img/folder-192.png' : serviceUrl + '/media/img/file/192/txt.png'} alt={gettext('file icon')}></img>
|
||||
{dirent.is_locked && <img className="locked" src={serviceUrl + '/media/img/file-locked-32.png'} alt={gettext('locked')}></img>}
|
||||
<img src={dirent.type === 'dir' ? siteRoot + 'media/img/folder-192.png' : siteRoot + 'media/img/file/192/txt.png'} alt={gettext('file icon')}></img>
|
||||
{dirent.is_locked && <img className="locked" src={siteRoot + 'media/img/file-locked-32.png'} alt={gettext('locked')}></img>}
|
||||
</div>
|
||||
</td>
|
||||
<td className="name a-simulate">
|
||||
|
@@ -7,7 +7,6 @@ import DirentListItem from './dirent-list-item';
|
||||
const propTypes = {
|
||||
path: PropTypes.string.isRequired,
|
||||
repoID: PropTypes.string.isRequired,
|
||||
serviceUrl: PropTypes.string.isRequired,
|
||||
isRepoOwner: PropTypes.bool,
|
||||
currentRepo: PropTypes.object,
|
||||
isAllItemSelected: PropTypes.bool.isRequired,
|
||||
@@ -45,8 +44,8 @@ class DirentListView extends React.Component {
|
||||
this.onFreezedItem();
|
||||
}
|
||||
|
||||
onItemDetails = (dirent, direntPath) => {
|
||||
this.props.onItemDetails(dirent, direntPath);
|
||||
onItemDetails = (dirent) => {
|
||||
this.props.onItemDetails(dirent);
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -81,7 +80,6 @@ class DirentListView extends React.Component {
|
||||
dirent={dirent}
|
||||
path={this.props.path}
|
||||
repoID={this.props.repoID}
|
||||
serviceUrl={this.props.serviceUrl}
|
||||
currentRepo={this.props.currentRepo}
|
||||
isRepoOwner={this.props.isRepoOwner}
|
||||
onItemClick={this.props.onItemClick}
|
||||
|
@@ -26,7 +26,7 @@ const propTypes = {
|
||||
fileTypeErrorCallback: PropTypes.func,
|
||||
dragAndDrop: PropTypes.bool.isRequired,
|
||||
path: PropTypes.string.isRequired,
|
||||
onFileSuccess: PropTypes.func.isRequired,
|
||||
onFileUploadSuccess: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class FileUploader extends React.Component {
|
||||
@@ -97,7 +97,7 @@ class FileUploader extends React.Component {
|
||||
this.resumable.on('fileAdded', this.onFileAdded);
|
||||
this.resumable.on('filesAddedComplete', this.filesAddedComplete);
|
||||
this.resumable.on('fileProgress', this.onFileProgress);
|
||||
this.resumable.on('fileSuccess', this.onFileSuccess);
|
||||
this.resumable.on('fileSuccess', this.onFileUploadSuccess);
|
||||
this.resumable.on('progress', this.onProgress);
|
||||
this.resumable.on('complete', this.onComplete);
|
||||
this.resumable.on('pause', this.onPause);
|
||||
@@ -205,7 +205,7 @@ class FileUploader extends React.Component {
|
||||
this.setState({uploadFileList: uploadFileList});
|
||||
}
|
||||
|
||||
onFileSuccess = (file) => {
|
||||
onFileUploadSuccess = (file) => {
|
||||
// todos, update uploadList or updateList;
|
||||
}
|
||||
|
||||
|
@@ -179,7 +179,7 @@ class Search extends Component {
|
||||
for (let key in queryData) {
|
||||
params += key + '=' + queryData[key] + '&';
|
||||
}
|
||||
window.location = siteRoot + '/search/?' + params.slice(0, params.length - 1);
|
||||
window.location = siteRoot + 'search/?' + params.slice(0, params.length - 1);
|
||||
}
|
||||
|
||||
renderSearchResult() {
|
||||
|
@@ -1,17 +1,16 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import { gettext, siteRoot } from '../../utils/constants';
|
||||
import ModalPortal from '../modal-portal';
|
||||
import CreateFolder from '../../components/dialog/create-folder-dialog';
|
||||
import CreateFile from '../../components/dialog/create-file-dialog';
|
||||
|
||||
const propTypes = {
|
||||
isViewFile: PropTypes.bool,
|
||||
isViewFile: PropTypes.bool, // just for view file,
|
||||
permission: PropTypes.string, //just for view file, and premission is file permission
|
||||
path: PropTypes.string.isRequired,
|
||||
repoID: PropTypes.string.isRequired,
|
||||
serviceUrl: PropTypes.string.isRequired,
|
||||
permission: PropTypes.string.isRequired,
|
||||
onAddFile: PropTypes.func.isRequired,
|
||||
onAddFolder: PropTypes.func.isRequired,
|
||||
onUploadFile: PropTypes.func.isRequired,
|
||||
@@ -58,8 +57,8 @@ class DirOperationToolbar extends React.Component {
|
||||
|
||||
onEditClick = (e) => {
|
||||
e.preventDefault();
|
||||
let { path, repoID, serviceUrl } = this.props;
|
||||
window.location.href= serviceUrl + '/lib/' + repoID + '/file' + path + '?mode=edit';
|
||||
let { path, repoID } = this.props;
|
||||
window.location.href= siteRoot + 'lib/' + repoID + '/file' + path + '?mode=edit';
|
||||
}
|
||||
|
||||
onUploadClick = (e) => {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { serviceUrl } from '../../utils/constants';
|
||||
import { siteRoot } from '../../utils/constants';
|
||||
|
||||
const propTypes = {
|
||||
node: PropTypes.object.isRequired,
|
||||
@@ -35,7 +35,7 @@ class TreeDirList extends React.Component {
|
||||
return (
|
||||
<tr className={this.state.highlight ? 'tr-highlight' : ''} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
|
||||
<td className="icon">
|
||||
<img src={node.type === 'dir' ? serviceUrl + '/media/img/folder-192.png' : serviceUrl + '/media/img/file/192/txt.png'} alt='icon'></img>
|
||||
<img src={node.type === 'dir' ? siteRoot + 'media/img/folder-192.png' : siteRoot + 'media/img/file/192/txt.png'} alt='icon'></img>
|
||||
</td>
|
||||
<td className="name a-simulate" onClick={this.onMainNodeClick}>{node.name}</td>
|
||||
<td>{node.size}</td>
|
||||
|
@@ -65,6 +65,9 @@ class Node {
|
||||
}
|
||||
|
||||
isMarkdown() {
|
||||
if (this.isDir()) {
|
||||
return false;
|
||||
}
|
||||
let index = this.name.lastIndexOf('.');
|
||||
if (index == -1) {
|
||||
return false;
|
||||
|
@@ -121,6 +121,7 @@
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.header {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import React, { Component } from 'react';
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { gettext, siteRoot } from '../../utils/constants';
|
||||
@@ -17,7 +17,7 @@ class FileActivitiesContent extends Component {
|
||||
return <p className="error text-center">{error_msg}</p>;
|
||||
} else {
|
||||
return (
|
||||
<div className="activity-table-container">
|
||||
<Fragment>
|
||||
<table className="table table-hover table-vcenter">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -32,7 +32,7 @@ class FileActivitiesContent extends Component {
|
||||
</table>
|
||||
{has_more ? <span className="loading-icon loading-tip"></span> : ''}
|
||||
{error_msg ? <p className="error text-center">{error_msg}</p> : ''}
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import cookie from 'react-cookies';
|
||||
import { gettext, repoID, serviceUrl, slug, permission } from '../../utils/constants';
|
||||
import { gettext, repoID, siteRoot, slug, permission } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import Repo from '../../models/repo';
|
||||
@@ -81,7 +81,7 @@ class MainPanel extends Component {
|
||||
switchViewMode = (mode) => {
|
||||
cookie.save('view_mode', mode, { path: '/' });
|
||||
let dirPath = this.props.isViewFile ? Utils.getDirName(this.props.path) : this.props.path;
|
||||
window.location.href = serviceUrl + '/#common/lib/' + repoID + dirPath;
|
||||
window.location.href = siteRoot + '#common/lib/' + repoID + dirPath;
|
||||
}
|
||||
|
||||
onSideNavMenuClick = () => {
|
||||
@@ -92,10 +92,9 @@ class MainPanel extends Component {
|
||||
this.props.onMainNavBarClick(path);
|
||||
}
|
||||
|
||||
onItemDetails = (dirent, direntPath) => {
|
||||
onItemDetails = (dirent) => {
|
||||
this.setState({
|
||||
currentDirent: dirent,
|
||||
direntPath: direntPath,
|
||||
isDirentDetailShow: true,
|
||||
});
|
||||
}
|
||||
@@ -118,14 +117,16 @@ class MainPanel extends Component {
|
||||
this.uploader.onFolderUpload();
|
||||
}
|
||||
|
||||
onFileSuccess = (file) => {
|
||||
onFileUploadSuccess = (file) => {
|
||||
// todo
|
||||
}
|
||||
|
||||
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">
|
||||
<div className="main-panel-north">
|
||||
<div className="cur-view-toolbar border-left-show">
|
||||
<span className="sf2-icon-menu hidden-md-up d-md-none side-nav-toggle" title={gettext('Side Nav Menu')} onClick={this.onSideNavMenuClick}></span>
|
||||
<div className="dir-operation">
|
||||
@@ -141,7 +142,6 @@ class MainPanel extends Component {
|
||||
<DirOperationToolBar
|
||||
path={this.props.path}
|
||||
repoID={repoID}
|
||||
serviceUrl={serviceUrl}
|
||||
permission={this.props.permission}
|
||||
isViewFile={this.props.isViewFile}
|
||||
onAddFile={this.props.onAddFile}
|
||||
@@ -167,8 +167,8 @@ class MainPanel extends Component {
|
||||
/>
|
||||
</div>
|
||||
<div className="cur-view-content">
|
||||
{ !this.props.pathExist ?
|
||||
<div className="message empty-tip err-message"><h2>{gettext('Folder does not exist.')}</h2></div> :
|
||||
{!this.props.pathExist ?
|
||||
ErrMessage :
|
||||
<Fragment>
|
||||
{ this.props.isViewFile ?
|
||||
<MarkdownViewer
|
||||
@@ -182,7 +182,6 @@ class MainPanel extends Component {
|
||||
<DirentListView
|
||||
path={this.props.path}
|
||||
repoID={repoID}
|
||||
serviceUrl={serviceUrl}
|
||||
direntList={this.props.direntList}
|
||||
onItemClick={this.props.onItemClick}
|
||||
onItemDelete={this.props.onItemDelete}
|
||||
@@ -203,7 +202,7 @@ class MainPanel extends Component {
|
||||
dragAndDrop={true}
|
||||
path={this.props.path}
|
||||
repoID={repoID}
|
||||
onFileSuccess={this.onFileSuccess}
|
||||
onFileUploadSuccess={this.onFileUploadSuccess}
|
||||
direntList={this.props.direntList}
|
||||
/>
|
||||
</Fragment>
|
||||
@@ -212,18 +211,18 @@ class MainPanel extends Component {
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
{ this.state.isDirentDetailShow &&
|
||||
{this.state.isDirentDetailShow && (
|
||||
<div className="cur-view-detail">
|
||||
<DirentDetail
|
||||
repoID={repoID}
|
||||
serviceUrl={serviceUrl}
|
||||
path={this.props.path}
|
||||
dirent={this.state.currentDirent}
|
||||
direntPath={this.state.direntPath}
|
||||
onItemDetailsClose={this.onItemDetailsClose}
|
||||
onFileTagChanged={this.onFileTagChanged}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext, repoID, serviceUrl, slug, siteRoot } from '../../utils/constants';
|
||||
import { gettext, repoID, slug, siteRoot } from '../../utils/constants';
|
||||
import CommonToolbar from '../../components/toolbar/common-toolbar';
|
||||
import MarkdownViewer from '../../components/markdown-viewer';
|
||||
import TreeDirView from '../../components/tree-dir-view/tree-dir-view';
|
||||
@@ -39,7 +39,7 @@ class MainPanel extends Component {
|
||||
onEditClick = (e) => {
|
||||
// const w=window.open('about:blank')
|
||||
e.preventDefault();
|
||||
window.location.href= serviceUrl + '/lib/' + repoID + '/file' + this.props.filePath + '?mode=edit';
|
||||
window.location.href= siteRoot + 'lib/' + repoID + '/file' + this.props.filePath + '?mode=edit';
|
||||
}
|
||||
|
||||
onMainNavBarClick = (e) => {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import moment from 'moment';
|
||||
import { gettext, repoID, serviceUrl, initialPath, isDir } from './utils/constants';
|
||||
import { gettext, repoID, siteRoot, initialPath, isDir } from './utils/constants';
|
||||
import { seafileAPI } from './utils/seafile-api';
|
||||
import { Utils } from './utils/utils';
|
||||
import SidePanel from './pages/repo-wiki-mode/side-panel';
|
||||
@@ -133,14 +133,13 @@ class Wiki extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
onMoveItem = (repo, direntPath, moveToDirentPath) => {
|
||||
onMoveItem = (destRepo, dirent, moveToDirentPath) => {
|
||||
//just for view list state
|
||||
let index = direntPath.lastIndexOf('/');
|
||||
let dirPath = direntPath.slice(0, index + 1);
|
||||
let dirName = direntPath.slice(index + 1);
|
||||
seafileAPI.moveDir(repoID, repo.repo_id,moveToDirentPath, dirPath, dirName).then(() => {
|
||||
let dirName = dirent.name
|
||||
let direntPath = Utils.joinPath(this.state.path, dirName);
|
||||
seafileAPI.moveDir(repoID, destRepo.repo_id,moveToDirentPath, this.state.path, dirName).then(() => {
|
||||
|
||||
this.moveTreeNode(direntPath, moveToDirentPath, repo);
|
||||
this.moveTreeNode(direntPath, moveToDirentPath, destRepo);
|
||||
this.moveDirent(direntPath);
|
||||
|
||||
let message = gettext('Successfully moved %(name)s.');
|
||||
@@ -153,13 +152,12 @@ class Wiki extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
onCopyItem = (repo, direntPath, copyToDirentPath) => {
|
||||
onCopyItem = (destRepo, dirent, copyToDirentPath) => {
|
||||
//just for view list state
|
||||
let index = direntPath.lastIndexOf('/');
|
||||
let dirPath = direntPath.slice(0, index + 1);
|
||||
let dirName = direntPath.slice(index + 1);
|
||||
seafileAPI.copyDir(repoID, repo.repo_id, copyToDirentPath, dirPath, dirName).then(() => {
|
||||
this.copyTreeNode(direntPath, copyToDirentPath, repo);
|
||||
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);
|
||||
let message = gettext('Successfully copied %(name)s.');
|
||||
message = message.replace('%(name)s', dirName);
|
||||
Toast.success(message);
|
||||
@@ -224,7 +222,7 @@ class Wiki extends Component {
|
||||
});
|
||||
});
|
||||
|
||||
let fileUrl = serviceUrl + '/wiki/lib/' + repoID + filePath;
|
||||
let fileUrl = siteRoot + 'wiki/lib/' + repoID + filePath;
|
||||
window.history.pushState({url: fileUrl, path: filePath}, filePath, fileUrl);
|
||||
}
|
||||
|
||||
@@ -236,7 +234,7 @@ class Wiki extends Component {
|
||||
});
|
||||
|
||||
// update location url
|
||||
let url = serviceUrl + '/wiki/lib/' + repoID + path;
|
||||
let url = siteRoot + 'wiki/lib/' + repoID + path;
|
||||
window.history.pushState({ url: url, path: path}, path, url);
|
||||
}
|
||||
|
||||
@@ -312,8 +310,9 @@ class Wiki extends Component {
|
||||
this.showDir(node.path);
|
||||
}
|
||||
|
||||
onDirentClick = (direntPath) => {
|
||||
onDirentClick = (dirent) => {
|
||||
this.resetSelected();
|
||||
let direntPath = Utils.joinPath(this.state.path, dirent.name);
|
||||
let tree = this.state.treeData.clone();
|
||||
let node = tree.getNodeByPath(direntPath);
|
||||
let parentNode = tree.findNodeParentFromTree(node);
|
||||
@@ -327,7 +326,7 @@ class Wiki extends Component {
|
||||
this.showDir(node.path);
|
||||
} else {
|
||||
const w=window.open('about:blank');
|
||||
const url = serviceUrl + '/lib/' + repoID + '/file' + node.path;
|
||||
const url = siteRoot + 'lib/' + repoID + '/file' + node.path;
|
||||
w.location.href = url;
|
||||
}
|
||||
}
|
||||
@@ -552,7 +551,7 @@ class Wiki extends Component {
|
||||
}
|
||||
} else {
|
||||
const w = window.open('about:blank');
|
||||
const url = serviceUrl + '/lib/' + repoID + '/file' + node.path;
|
||||
const url = siteRoot + 'lib/' + repoID + '/file' + node.path;
|
||||
w.location.href = url;
|
||||
}
|
||||
}
|
||||
@@ -688,24 +687,24 @@ class Wiki extends Component {
|
||||
}
|
||||
|
||||
isInternalMarkdownLink(url) {
|
||||
var re = new RegExp(serviceUrl + '/lib/' + repoID + '/file' + '.*\.md$');
|
||||
var re = new RegExp(siteRoot + 'lib/' + repoID + '/file' + '.*\.md$');
|
||||
return re.test(url);
|
||||
}
|
||||
|
||||
isInternalDirLink(url) {
|
||||
var re = new RegExp(serviceUrl + '/#[a-z\-]*?/lib/' + repoID + '/.*');
|
||||
var re = new RegExp(siteRoot + '#[a-z\-]*?/lib/' + repoID + '/.*');
|
||||
return re.test(url);
|
||||
}
|
||||
|
||||
getPathFromInternalMarkdownLink(url) {
|
||||
var re = new RegExp(serviceUrl + '/lib/' + repoID + '/file' + '(.*\.md)');
|
||||
var re = new RegExp(siteRoot + 'lib/' + repoID + '/file' + '(.*\.md)');
|
||||
var array = re.exec(url);
|
||||
var path = decodeURIComponent(array[1]);
|
||||
return path;
|
||||
}
|
||||
|
||||
getPathFromInternalDirLink(url) {
|
||||
var re = new RegExp(serviceUrl + '/#[a-z\-]*?/lib/' + repoID + '(/.*)');
|
||||
var re = new RegExp(siteRoot + '#[a-z\-]*?/lib/' + repoID + '(/.*)');
|
||||
var array = re.exec(url);
|
||||
var path = decodeURIComponent(array[1]);
|
||||
|
||||
|
@@ -23,16 +23,12 @@ export const folderPermEnabled = window.app.pageOptions.folderPermEnabled === 'T
|
||||
export const enableUploadFolder = window.app.pageOptions.enableUploadFolder === 'True';
|
||||
export const enableResumableFileUpload = window.app.pageOptions.enableResumableFileUpload === 'True';
|
||||
|
||||
//main-page
|
||||
export const mainServiceUrl = window.main ? window.main.pageOptions.serviceUrl : '';
|
||||
// wiki
|
||||
export const slug = window.wiki ? window.wiki.config.slug : '';
|
||||
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;
|
||||
|
@@ -3,7 +3,7 @@ import ReactDOM from 'react-dom';
|
||||
import SidePanel from './pages/wiki/side-panel';
|
||||
import MainPanel from './pages/wiki/main-panel';
|
||||
import moment from 'moment';
|
||||
import { slug, repoID, serviceUrl, initialFilePath } from './utils/constants';
|
||||
import { slug, repoID, siteRoot, initialFilePath } from './utils/constants';
|
||||
import editorUtilities from './utils/editor-utilties';
|
||||
import Node from './components/tree-view/node';
|
||||
import Tree from './components/tree-view/tree';
|
||||
@@ -65,7 +65,7 @@ class Wiki extends Component {
|
||||
});
|
||||
});
|
||||
const hash = window.location.hash;
|
||||
let fileUrl = serviceUrl + '/wikis/' + slug + filePath + hash;
|
||||
let fileUrl = siteRoot + 'wikis/' + slug + filePath + hash;
|
||||
window.history.pushState({urlPath: fileUrl, filePath: filePath}, filePath, fileUrl);
|
||||
}
|
||||
}, () => {
|
||||
@@ -90,7 +90,7 @@ class Wiki extends Component {
|
||||
});
|
||||
|
||||
const hash = window.location.hash;
|
||||
let fileUrl = serviceUrl + '/wikis/' + slug + filePath + hash;
|
||||
let fileUrl = siteRoot + 'wikis/' + slug + filePath + hash;
|
||||
window.history.pushState({urlPath: fileUrl, filePath: filePath}, filePath, fileUrl);
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ class Wiki extends Component {
|
||||
this.exitViewFileState(tree, node);
|
||||
|
||||
// update location url
|
||||
let fileUrl = serviceUrl + '/wikis/' + slug + node.path;
|
||||
let fileUrl = siteRoot + 'wikis/' + slug + node.path;
|
||||
window.history.pushState({urlPath: fileUrl, filePath: node.path},node.path, fileUrl);
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ class Wiki extends Component {
|
||||
this.exitViewFileState(tree, node);
|
||||
} else {
|
||||
const w=window.open('about:blank');
|
||||
const url = serviceUrl + '/lib/' + repoID + '/file' + node.path;
|
||||
const url = siteRoot + 'lib/' + repoID + '/file' + node.path;
|
||||
w.location.href = url;
|
||||
}
|
||||
}
|
||||
@@ -169,7 +169,7 @@ class Wiki extends Component {
|
||||
this.exitViewFileState(tree, node);
|
||||
} else {
|
||||
const w=window.open('about:blank');
|
||||
const url = serviceUrl + '/lib/' + repoID + '/file' + node.path;
|
||||
const url = siteRoot + 'lib/' + repoID + '/file' + node.path;
|
||||
w.location.href = url;
|
||||
}
|
||||
}
|
||||
@@ -371,7 +371,7 @@ class Wiki extends Component {
|
||||
filePath: newNode.path,
|
||||
isViewFileState: false
|
||||
});
|
||||
let fileUrl = serviceUrl + '/wikis/' + slug + newNode.path;
|
||||
let fileUrl = siteRoot + 'wikis/' + slug + newNode.path;
|
||||
window.history.pushState({urlPath: fileUrl, filePath: newNode.path}, newNode.path, fileUrl);
|
||||
}
|
||||
|
||||
@@ -431,24 +431,24 @@ class Wiki extends Component {
|
||||
}
|
||||
|
||||
isInternalMarkdownLink(url) {
|
||||
var re = new RegExp(serviceUrl + '/lib/' + repoID + '/file' + '.*\.md$');
|
||||
var re = new RegExp(siteRoot + 'lib/' + repoID + '/file' + '.*\.md$');
|
||||
return re.test(url);
|
||||
}
|
||||
|
||||
isInternalDirLink(url) {
|
||||
var re = new RegExp(serviceUrl + '/#[a-z\-]*?/lib/' + repoID + '/.*');
|
||||
var re = new RegExp(siteRoot + '#[a-z\-]*?/lib/' + repoID + '/.*');
|
||||
return re.test(url);
|
||||
}
|
||||
|
||||
getPathFromInternalMarkdownLink(url) {
|
||||
var re = new RegExp(serviceUrl + '/lib/' + repoID + '/file' + '(.*\.md)');
|
||||
var re = new RegExp(siteRoot + 'lib/' + repoID + '/file' + '(.*\.md)');
|
||||
var array = re.exec(url);
|
||||
var path = decodeURIComponent(array[1]);
|
||||
return path;
|
||||
}
|
||||
|
||||
getPathFromInternalDirLink(url) {
|
||||
var re = new RegExp(serviceUrl + '/#[a-z\-]*?/lib/' + repoID + '(/.*)');
|
||||
var re = new RegExp(siteRoot + '#[a-z\-]*?/lib/' + repoID + '(/.*)');
|
||||
var array = re.exec(url);
|
||||
var path = decodeURIComponent(array[1]);
|
||||
|
||||
|
@@ -1017,14 +1017,6 @@ table .menu-toggle {
|
||||
|
||||
/* end file-tag */
|
||||
|
||||
/* begin activity page */
|
||||
.activity-table-container {
|
||||
flex: 1;
|
||||
padding: 10px 16px 20px;
|
||||
overflow: auto;
|
||||
}
|
||||
/* end activity page */
|
||||
|
||||
.dirent-item.tag-list {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@@ -1212,6 +1212,4 @@ def choose_register(request):
|
||||
|
||||
@login_required
|
||||
def react_fake_view(request):
|
||||
return render(request, "react_app.html", {
|
||||
"service_url": get_service_url().rstrip('/')
|
||||
})
|
||||
return render(request, "react_app.html")
|
||||
|
@@ -76,7 +76,6 @@ def slug(request, slug, file_path="home.md"):
|
||||
"repo_id": wiki.repo_id,
|
||||
"search_repo_id": wiki.repo_id,
|
||||
"search_wiki": True,
|
||||
"service_url": get_service_url().rstrip('/')
|
||||
})
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user