mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-02 15:38:15 +00:00
abstract dir-operation-toolbar and view-mode-toolbar (#2569)
This commit is contained in:
@@ -7,6 +7,7 @@ import EditFileTagDialog from '../dialog/edit-filetag-dialog';
|
|||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
repo: PropTypes.object.isRequired,
|
repo: PropTypes.object.isRequired,
|
||||||
|
dirent: PropTypes.object.isRequired,
|
||||||
direntType: PropTypes.string.isRequired,
|
direntType: PropTypes.string.isRequired,
|
||||||
direntDetail: PropTypes.object.isRequired,
|
direntDetail: PropTypes.object.isRequired,
|
||||||
direntPath: PropTypes.string.isRequired,
|
direntPath: PropTypes.string.isRequired,
|
||||||
|
@@ -126,11 +126,11 @@ class DirentListItem extends React.Component {
|
|||||||
let filePath = this.getDirentPath(dirent);
|
let filePath = this.getDirentPath(dirent);
|
||||||
if (dirent.starred) {
|
if (dirent.starred) {
|
||||||
seafileAPI.unStarFile(repoID, filePath).then(() => {
|
seafileAPI.unStarFile(repoID, filePath).then(() => {
|
||||||
this.props.updateDirent(this.props.dirent, "starred", false);
|
this.props.updateDirent(this.props.dirent, 'starred', false);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
seafileAPI.starFile(repoID, filePath).then(() => {
|
seafileAPI.starFile(repoID, filePath).then(() => {
|
||||||
this.props.updateDirent(this.props.dirent, "starred", true);
|
this.props.updateDirent(this.props.dirent, 'starred', true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,7 +210,7 @@ class DirentListItem extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (newName.indexOf('/') > -1) {
|
if (newName.indexOf('/') > -1) {
|
||||||
let errMessage = 'Name should not include "/".';
|
let errMessage = 'Name should not include ' + '\'/\'' + '.';
|
||||||
Toast.error(gettext(errMessage));
|
Toast.error(gettext(errMessage));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -249,8 +249,8 @@ class DirentListItem extends React.Component {
|
|||||||
onLockItem = () => {
|
onLockItem = () => {
|
||||||
let filePath = this.getDirentPath(this.props.dirent);
|
let filePath = this.getDirentPath(this.props.dirent);
|
||||||
seafileAPI.lockfile(repoID, filePath).then(() => {
|
seafileAPI.lockfile(repoID, filePath).then(() => {
|
||||||
this.props.updateDirent(this.props.dirent, "is_locked", true);
|
this.props.updateDirent(this.props.dirent, 'is_locked', true);
|
||||||
this.props.updateDirent(this.props.dirent, "locked_by_me", true);
|
this.props.updateDirent(this.props.dirent, 'locked_by_me', true);
|
||||||
});
|
});
|
||||||
this.onItemMenuHide();
|
this.onItemMenuHide();
|
||||||
}
|
}
|
||||||
@@ -258,8 +258,8 @@ class DirentListItem extends React.Component {
|
|||||||
onUnlockItem = () => {
|
onUnlockItem = () => {
|
||||||
let filePath = this.getDirentPath(this.props.dirent);
|
let filePath = this.getDirentPath(this.props.dirent);
|
||||||
seafileAPI.unlockfile(repoID, filePath).then(() => {
|
seafileAPI.unlockfile(repoID, filePath).then(() => {
|
||||||
this.props.updateDirent(this.props.dirent, "is_locked", false);
|
this.props.updateDirent(this.props.dirent, 'is_locked', false);
|
||||||
this.props.updateDirent(this.props.dirent, "locked_by_me", false);
|
this.props.updateDirent(this.props.dirent, 'locked_by_me', false);
|
||||||
});
|
});
|
||||||
this.onItemMenuHide();
|
this.onItemMenuHide();
|
||||||
}
|
}
|
||||||
|
@@ -48,7 +48,7 @@ class UploadProgressDialog extends React.Component {
|
|||||||
{totalProgress === 100 ? uploadedOptions : uploadingOptions}
|
{totalProgress === 100 ? uploadedOptions : uploadingOptions}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="uploader-list-content table-container">
|
<div className="uploader-list-content">
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
{
|
{
|
||||||
|
@@ -2,7 +2,7 @@ import React, { Fragment } from 'react';
|
|||||||
import GeneralToolBar from './toolbar/general-toolbar';
|
import GeneralToolBar from './toolbar/general-toolbar';
|
||||||
|
|
||||||
const MainContentWrapper = (WrapperedComponent) => {
|
const MainContentWrapper = (WrapperedComponent) => {
|
||||||
return class extends React.Component {
|
return class Wrapper extends React.Component {
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@@ -1,15 +1,166 @@
|
|||||||
import React from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { Utils } from '../../utils/utils';
|
||||||
|
import { gettext, serviceUrl } 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 = {
|
const propTypes = {
|
||||||
|
isViewFile: PropTypes.bool,
|
||||||
|
path: PropTypes.string.isRequired,
|
||||||
|
repoID: PropTypes.string.isRequired,
|
||||||
|
permission: PropTypes.string.isRequired,
|
||||||
|
onAddFile: PropTypes.func.isRequired,
|
||||||
|
onAddFolder: PropTypes.func.isRequired,
|
||||||
|
onUploadFile: PropTypes.func.isRequired,
|
||||||
|
onUploadFolder: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
class DirOperationToolbar extends React.Component {
|
class DirOperationToolbar extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
fileType: '.md',
|
||||||
|
isCreateFileDialogShow: false,
|
||||||
|
isCreateFolderDialogShow: false,
|
||||||
|
isUploadMenuShow: false,
|
||||||
|
isCreateMenuShow: false,
|
||||||
|
operationMenuStyle: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
document.addEventListener('click', this.hideOperationMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
document.removeEventListener('click', this.hideOperationMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
hideOperationMenu = () => {
|
||||||
|
this.setState({
|
||||||
|
isUploadMenuShow: false,
|
||||||
|
isCreateMenuShow: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleOperationMenu = (e) => {
|
||||||
|
e.nativeEvent.stopImmediatePropagation();
|
||||||
|
let targetRect = e.target.getClientRects()[0];
|
||||||
|
let left = targetRect.x;
|
||||||
|
let top = targetRect.y + targetRect.height;
|
||||||
|
let style = {position: 'fixed', display: 'block', left: left, top: top};
|
||||||
|
this.setState({operationMenuStyle: style});
|
||||||
|
}
|
||||||
|
|
||||||
|
onEditClick = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
let { path, repoID} = this.props;
|
||||||
|
window.location.href= serviceUrl + '/lib/' + repoID + '/file' + path + '?mode=edit';
|
||||||
|
}
|
||||||
|
|
||||||
|
onUploadClick = (e) => {
|
||||||
|
this.toggleOperationMenu(e);
|
||||||
|
this.setState({
|
||||||
|
isUploadMenuShow: true,
|
||||||
|
isCreateMenuShow: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onCreateClick = (e) => {
|
||||||
|
this.toggleOperationMenu(e);
|
||||||
|
this.setState({
|
||||||
|
isCreateMenuShow: true,
|
||||||
|
isUploadMenuShow: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onShareClick = (e) => {
|
||||||
|
//todos;
|
||||||
|
}
|
||||||
|
|
||||||
|
onCreateFolderToggle = () => {
|
||||||
|
this.setState({isCreateFolderDialogShow: !this.state.isCreateFolderDialogShow});
|
||||||
|
}
|
||||||
|
|
||||||
|
onCreateFileToggle = () => {
|
||||||
|
this.setState({
|
||||||
|
isCreateFileDialogShow: !this.state.isCreateFileDialogShow,
|
||||||
|
fileType: '',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onCreateMarkdownToggle = () => {
|
||||||
|
this.setState({
|
||||||
|
isCreateFileDialogShow: !this.state.isCreateFileDialogShow,
|
||||||
|
fileType: '.md'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onAddFile = (filePath, isDraft) => {
|
||||||
|
this.setState({isCreateFileDialogShow: false});
|
||||||
|
this.props.onAddFile(filePath, isDraft);
|
||||||
|
}
|
||||||
|
|
||||||
|
onAddFolder = (dirPath) => {
|
||||||
|
this.setState({isCreateFolderDialogShow: false});
|
||||||
|
this.props.onAddFolder(dirPath);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div></div>
|
<Fragment>
|
||||||
|
<div className="operation">
|
||||||
|
{(this.props.isViewFile && this.props.permission === 'rw') && (
|
||||||
|
<button className="btn btn-secondary operation-item" title={gettext('Edit File')} onClick={this.onEditClick}>{gettext('Edit')}</button>
|
||||||
|
)}
|
||||||
|
{!this.props.isViewFile && (
|
||||||
|
<Fragment>
|
||||||
|
{Utils.isSupportUploadFolder() ?
|
||||||
|
<button className="btn btn-secondary operation-item" title={gettext('Upload')} onClick={this.onUploadClick}>{gettext('Upload')}</button> :
|
||||||
|
<button className="btn btn-secondary operation-item" title={gettext('Upload')} onClick={this.uploadFile}>{gettext('Upload')}</button>
|
||||||
|
}
|
||||||
|
<button className="btn btn-secondary operation-item" title={gettext('New')} onClick={this.onCreateClick}>{gettext('New')}</button>
|
||||||
|
<button className="btn btn-secondary operation-item" title={gettext('Share')} onClick={this.onShareClick}>{gettext('Share')}</button>
|
||||||
|
</Fragment>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{this.state.isUploadMenuShow && (
|
||||||
|
<ul className="menu dropdown-menu" style={this.state.operationMenuStyle}>
|
||||||
|
<li className="dropdown-item" onClick={this.props.onUploadFile}>{gettext('File Upload')}</li>
|
||||||
|
<li className="dropdown-item" onClick={this.props.onUploadFolder}>{gettext('Folder Upload')}</li>
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
{this.state.isCreateMenuShow && (
|
||||||
|
<ul className="menu dropdown-menu" style={this.state.operationMenuStyle}>
|
||||||
|
<li className="dropdown-item" onClick={this.onCreateFolderToggle}>{gettext('New Folder')}</li>
|
||||||
|
<li className="dropdown-item" onClick={this.onCreateFileToggle}>{gettext('New File')}</li>
|
||||||
|
<li className="dropdown-divider"></li>
|
||||||
|
<li className="dropdown-item" onClick={this.onCreateMarkdownToggle}>{gettext('New Markdown File')}</li>
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
{this.state.isCreateFileDialogShow && (
|
||||||
|
<ModalPortal>
|
||||||
|
<CreateFile
|
||||||
|
parentPath={this.props.path}
|
||||||
|
fileType={this.state.fileType}
|
||||||
|
onAddFile={this.onAddFile}
|
||||||
|
addFileCancel={this.onCreateFileToggle}
|
||||||
|
/>
|
||||||
|
</ModalPortal>
|
||||||
|
)}
|
||||||
|
{this.state.isCreateFolderDialogShow && (
|
||||||
|
<ModalPortal>
|
||||||
|
<CreateFolder
|
||||||
|
parentPath={this.props.path}
|
||||||
|
onAddFolder={this.onAddFolder}
|
||||||
|
addFolderCancel={this.onCreateFolderToggle}
|
||||||
|
/>
|
||||||
|
</ModalPortal>
|
||||||
|
)}
|
||||||
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
import React, { Fragment } from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import CommonToolbar from './common-toolbar';
|
import CommonToolbar from './common-toolbar';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
|
searchPlaceholder: PropTypes.string,
|
||||||
onShowSidePanel: PropTypes.func.isRequired,
|
onShowSidePanel: PropTypes.func.isRequired,
|
||||||
onSearchedClick: PropTypes.func.isRequired,
|
onSearchedClick: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
35
frontend/src/components/toolbar/view-mode-toolbar.js
Normal file
35
frontend/src/components/toolbar/view-mode-toolbar.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { gettext } from '../../utils/constants';
|
||||||
|
|
||||||
|
const propTypes = {
|
||||||
|
currentMode: PropTypes.string.isRequired,
|
||||||
|
switchViewMode: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
class ViewModeToolbar extends React.Component {
|
||||||
|
|
||||||
|
switchViewMode = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
let id = e.target.id;
|
||||||
|
if (id === this.props.currentMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.props.switchViewMode(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let baseClass = 'btn btn-secondary btn-icon sf-view-mode-btn ';
|
||||||
|
return (
|
||||||
|
<div className="view-mode btn-group">
|
||||||
|
<button className={`${baseClass} sf2-icon-list-view ${this.props.currentMode === 'list' ? 'current-mode' : ''}`} id='list' title={gettext('List')} onClick={this.switchViewMode}></button>
|
||||||
|
<button className={`${baseClass} sf2-icon-grid-view ${this.props.currentMode === 'grid' ? 'current-mode' : ''}`} id='grid' title={gettext('Grid')} onClick={this.switchViewMode}></button>
|
||||||
|
<button className={`${baseClass} sf2-icon-two-columns ${this.props.currentMode === 'wiki' ? 'current-mode' : ''}`} id='wiki' title={gettext('wiki')} onClick={this.switchViewMode}></button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewModeToolbar.propTypes = propTypes;
|
||||||
|
|
||||||
|
export default ViewModeToolbar;
|
@@ -135,7 +135,7 @@ class TreeNodeView extends React.Component {
|
|||||||
|
|
||||||
renderMenuController() {
|
renderMenuController() {
|
||||||
if (permission) {
|
if (permission) {
|
||||||
let isShow = (this.props.node.path === this.props.currentFilePath);
|
let isShow = (this.props.node.path === this.props.currentPath);
|
||||||
return (
|
return (
|
||||||
<div className="right-icon">
|
<div className="right-icon">
|
||||||
<MenuControl
|
<MenuControl
|
||||||
@@ -180,7 +180,7 @@ class TreeNodeView extends React.Component {
|
|||||||
let node = this.props.node;
|
let node = this.props.node;
|
||||||
let { type, icon } = this.getNodeTypeAndIcon();
|
let { type, icon } = this.getNodeTypeAndIcon();
|
||||||
let hlClass = '';
|
let hlClass = '';
|
||||||
if (node.path === this.props.currentFilePath) {
|
if (node.path === this.props.currentPath) {
|
||||||
hlClass = 'tree-node-hight-light';
|
hlClass = 'tree-node-hight-light';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -42,5 +42,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.uploader-list-content {
|
.uploader-list-content {
|
||||||
|
padding: 0.625rem 1rem 1.25rem;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
@@ -24,7 +24,7 @@ class Dirent {
|
|||||||
if (json.file_tags) {
|
if (json.file_tags) {
|
||||||
file_tags = json.file_tags.map(item => {
|
file_tags = json.file_tags.map(item => {
|
||||||
return new FileTag(item);
|
return new FileTag(item);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
this.file_tags = file_tags;
|
this.file_tags = file_tags;
|
||||||
}
|
}
|
||||||
|
@@ -1,17 +1,18 @@
|
|||||||
import React, { Component, Fragment } from 'react';
|
import React, { Component, Fragment } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import cookie from 'react-cookies';
|
||||||
import { gettext, repoID, serviceUrl, slug } from '../../utils/constants';
|
import { gettext, repoID, serviceUrl, slug } from '../../utils/constants';
|
||||||
import { seafileAPI } from '../../utils/seafile-api';
|
import { seafileAPI } from '../../utils/seafile-api';
|
||||||
import { Utils } from '../../utils/utils';
|
import { Utils } from '../../utils/utils';
|
||||||
import Repo from '../../models/repo';
|
import Repo from '../../models/repo';
|
||||||
import CommonToolbar from '../../components/toolbar/common-toolbar';
|
import CommonToolbar from '../../components/toolbar/common-toolbar';
|
||||||
import MutipleDirentsOperationToolbar from '../../components/toolbar/mutilple-dir-operation-toolbar';
|
import ViewModeToolbar from '../../components/toolbar/view-mode-toolbar';
|
||||||
|
import DirOperationToolBar from '../../components/toolbar/dir-operation-toolbar';
|
||||||
|
import MutipleDirOperationToolbar from '../../components/toolbar/mutilple-dir-operation-toolbar';
|
||||||
import CurDirPath from '../../components/cur-dir-path';
|
import CurDirPath from '../../components/cur-dir-path';
|
||||||
import MarkdownViewer from '../../components/markdown-viewer';
|
import MarkdownViewer from '../../components/markdown-viewer';
|
||||||
import DirentListView from '../../components/dirent-list-view/dirent-list-view';
|
import DirentListView from '../../components/dirent-list-view/dirent-list-view';
|
||||||
import DirentDetail from '../../components/dirent-detail/dirent-details';
|
import DirentDetail from '../../components/dirent-detail/dirent-details';
|
||||||
import CreateFolder from '../../components/dialog/create-folder-dialog';
|
|
||||||
import CreateFile from '../../components/dialog/create-file-dialog';
|
|
||||||
import FileUploader from '../../components/file-uploader/file-uploader';
|
import FileUploader from '../../components/file-uploader/file-uploader';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
@@ -43,7 +44,6 @@ const propTypes = {
|
|||||||
onItemCopy: PropTypes.func.isRequired,
|
onItemCopy: PropTypes.func.isRequired,
|
||||||
onAddFile: PropTypes.func.isRequired,
|
onAddFile: PropTypes.func.isRequired,
|
||||||
onAddFolder: PropTypes.func.isRequired,
|
onAddFolder: PropTypes.func.isRequired,
|
||||||
switchViewMode: PropTypes.func.isRequired,
|
|
||||||
onFileTagChanged: PropTypes.func.isRequired,
|
onFileTagChanged: PropTypes.func.isRequired,
|
||||||
onItemsMove: PropTypes.func.isRequired,
|
onItemsMove: PropTypes.func.isRequired,
|
||||||
onItemsCopy: PropTypes.func.isRequired,
|
onItemsCopy: PropTypes.func.isRequired,
|
||||||
@@ -55,12 +55,7 @@ class MainPanel extends Component {
|
|||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
isWikiMode: true,
|
currentMode: 'wiki',
|
||||||
newMenuShow: false,
|
|
||||||
uploadMenuShow: false,
|
|
||||||
showFileDialog: false,
|
|
||||||
showFolderDialog: false,
|
|
||||||
createFileType: '',
|
|
||||||
isDirentDetailShow: false,
|
isDirentDetailShow: false,
|
||||||
currentDirent: null,
|
currentDirent: null,
|
||||||
direntPath: '',
|
direntPath: '',
|
||||||
@@ -81,20 +76,12 @@ class MainPanel extends Component {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
document.addEventListener('click', this.hideOperationMenu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
switchViewMode = (mode) => {
|
||||||
document.removeEventListener('click', this.hideOperationMenu);
|
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;
|
||||||
switchViewMode = (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
if (e.target.id === 'wiki') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.setState({isWikiMode: false});
|
|
||||||
this.props.switchViewMode(e.target.id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onSideNavMenuClick = () => {
|
onSideNavMenuClick = () => {
|
||||||
@@ -105,83 +92,6 @@ class MainPanel extends Component {
|
|||||||
this.props.onMainNavBarClick(path);
|
this.props.onMainNavBarClick(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
onEditClick = (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
window.location.href= serviceUrl + '/lib/' + repoID + '/file' + this.props.path + '?mode=edit';
|
|
||||||
}
|
|
||||||
|
|
||||||
onUploadClick = (e) => {
|
|
||||||
this.toggleOperationMenu(e);
|
|
||||||
this.setState({
|
|
||||||
newMenuShow: false,
|
|
||||||
uploadMenuShow: !this.state.uploadMenuShow,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onNewClick = (e) => {
|
|
||||||
this.toggleOperationMenu(e);
|
|
||||||
this.setState({
|
|
||||||
newMenuShow: !this.state.newMenuShow,
|
|
||||||
uploadMenuShow: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onShareClick = () => {
|
|
||||||
alert('share btn clicked');
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleOperationMenu = (e) => {
|
|
||||||
e.nativeEvent.stopImmediatePropagation();
|
|
||||||
let targetRect = e.target.getClientRects()[0];
|
|
||||||
let left = targetRect.x;
|
|
||||||
let top = targetRect.y + targetRect.height;
|
|
||||||
let style = {position: 'fixed', display: 'block', left: left, top: top};
|
|
||||||
this.setState({operationMenuStyle: style});
|
|
||||||
}
|
|
||||||
|
|
||||||
hideOperationMenu = () => {
|
|
||||||
this.setState({
|
|
||||||
uploadMenuShow: false,
|
|
||||||
newMenuShow: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
addFolder = () => {
|
|
||||||
this.setState({showFolderDialog: !this.showFolderDialog});
|
|
||||||
}
|
|
||||||
|
|
||||||
addFile = () => {
|
|
||||||
this.setState({
|
|
||||||
showFileDialog: !this.showFileDialog,
|
|
||||||
createFileType: '',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
addMarkdownFile = () => {
|
|
||||||
this.setState({
|
|
||||||
showFileDialog: !this.showFileDialog,
|
|
||||||
createFileType: '.md',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
addFolderCancel = () => {
|
|
||||||
this.setState({showFolderDialog: !this.state.showFolderDialog});
|
|
||||||
}
|
|
||||||
|
|
||||||
addFileCancel = () => {
|
|
||||||
this.setState({showFileDialog: !this.state.showFileDialog});
|
|
||||||
}
|
|
||||||
|
|
||||||
onAddFile = (filePath, isDraft) => {
|
|
||||||
this.setState({showFileDialog: !this.state.showFileDialog});
|
|
||||||
this.props.onAddFile(filePath, isDraft);
|
|
||||||
}
|
|
||||||
|
|
||||||
onAddFolder = (dirPath) => {
|
|
||||||
this.setState({showFolderDialog: !this.state.showFolderDialog});
|
|
||||||
this.props.onAddFolder(dirPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
onItemDetails = (dirent, direntPath) => {
|
onItemDetails = (dirent, direntPath) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
currentDirent: dirent,
|
currentDirent: dirent,
|
||||||
@@ -195,22 +105,21 @@ class MainPanel extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onFileTagChanged = (dirent, direntPath) => {
|
onFileTagChanged = (dirent, direntPath) => {
|
||||||
//todos;
|
|
||||||
this.props.onFileTagChanged(dirent, direntPath);
|
this.props.onFileTagChanged(dirent, direntPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadFile = (e) => {
|
onUploadFile = (e) => {
|
||||||
e.nativeEvent.stopImmediatePropagation();
|
e.nativeEvent.stopImmediatePropagation();
|
||||||
this.uploader.onFileUpload();
|
this.uploader.onFileUpload();
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadFolder = (e) => {
|
onUploadFolder = (e) => {
|
||||||
e.nativeEvent.stopImmediatePropagation();
|
e.nativeEvent.stopImmediatePropagation();
|
||||||
this.uploader.onFolderUpload();
|
this.uploader.onFolderUpload();
|
||||||
}
|
}
|
||||||
|
|
||||||
onFileSuccess = (file) => {
|
onFileSuccess = (file) => {
|
||||||
|
// todo
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -220,58 +129,28 @@ class MainPanel extends Component {
|
|||||||
<div className="cur-view-toolbar border-left-show">
|
<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>
|
<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">
|
<div className="dir-operation">
|
||||||
{this.props.isDirentSelected &&
|
{this.props.isDirentSelected ?
|
||||||
<MutipleDirentsOperationToolbar
|
<MutipleDirOperationToolbar
|
||||||
repoID={repoID}
|
repoID={repoID}
|
||||||
path={this.props.path}
|
path={this.props.path}
|
||||||
selectedDirentList={this.props.selectedDirentList}
|
selectedDirentList={this.props.selectedDirentList}
|
||||||
onItemsMove={this.props.onItemsMove}
|
onItemsMove={this.props.onItemsMove}
|
||||||
onItemsCopy={this.props.onItemsCopy}
|
onItemsCopy={this.props.onItemsCopy}
|
||||||
onItemsDelete={this.props.onItemsDelete}
|
onItemsDelete={this.props.onItemsDelete}
|
||||||
|
/> :
|
||||||
|
<DirOperationToolBar
|
||||||
|
repoID={repoID}
|
||||||
|
path={this.props.path}
|
||||||
|
permission={this.props.permission}
|
||||||
|
isViewFile={this.props.isViewFile}
|
||||||
|
onAddFile={this.props.onAddFile}
|
||||||
|
onAddFolder={this.props.onAddFolder}
|
||||||
|
onUploadFile={this.onUploadFile}
|
||||||
|
onUploadFolder={this.onUploadFolder}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
{!this.props.isDirentSelected &&
|
|
||||||
<div className="operation">
|
|
||||||
{
|
|
||||||
this.props.permission === 'rw' &&
|
|
||||||
<button className="btn btn-secondary operation-item" title={gettext('Edit File')} onClick={this.onEditClick}>{gettext('Edit')}</button>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
!this.props.isViewFile &&
|
|
||||||
<Fragment>
|
|
||||||
{
|
|
||||||
Utils.isSupportUploadFolder() ?
|
|
||||||
<button className="btn btn-secondary operation-item" title={gettext('Upload')} onClick={this.onUploadClick}>{gettext('Upload')}</button> :
|
|
||||||
<button className="btn btn-secondary operation-item" title={gettext('Upload')} onClick={this.uploadFile}>{gettext('Upload')}</button>
|
|
||||||
}
|
|
||||||
<button className="btn btn-secondary operation-item" title={gettext('New')} onClick={this.onNewClick}>{gettext('New')}</button>
|
|
||||||
<button className="btn btn-secondary operation-item" title={gettext('Share')} onClick={this.onShareClick}>{gettext('Share')}</button>
|
|
||||||
</Fragment>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
this.state.uploadMenuShow &&
|
|
||||||
<ul className="menu dropdown-menu" style={this.state.operationMenuStyle}>
|
|
||||||
<li className="dropdown-item" onClick={this.uploadFile}>{gettext('File Upload')}</li>
|
|
||||||
<li className="dropdown-item" onClick={this.uploadFolder}>{gettext('Folder Upload')}</li>
|
|
||||||
</ul>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
this.state.newMenuShow &&
|
|
||||||
<ul className="menu dropdown-menu" style={this.state.operationMenuStyle}>
|
|
||||||
<li className="dropdown-item" onClick={this.addFolder}>{gettext('New Folder')}</li>
|
|
||||||
<li className="dropdown-item" onClick={this.addFile}>{gettext('New File')}</li>
|
|
||||||
<li className="dropdown-divider"></li>
|
|
||||||
<li className="dropdown-item" onClick={this.addMarkdownFile}>{gettext('New Markdown File')}</li>
|
|
||||||
</ul>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div className="view-mode btn-group">
|
|
||||||
<button className="btn btn-secondary btn-icon sf-view-mode-btn sf2-icon-list-view" id='list' title={gettext('List')} onClick={this.switchViewMode}></button>
|
|
||||||
<button className="btn btn-secondary btn-icon sf-view-mode-btn sf2-icon-grid-view" id='grid' title={gettext('Grid')} onClick={this.switchViewMode}></button>
|
|
||||||
<button className={`btn btn-secondary btn-icon sf-view-mode-btn sf2-icon-two-columns ${this.state.isWikiMode ? 'current-mode' : ''}`} id='wiki' title={gettext('wiki')} onClick={this.switchViewMode}></button>
|
|
||||||
</div>
|
</div>
|
||||||
|
<ViewModeToolbar currentMode={this.state.currentMode} switchViewMode={this.switchViewMode}/>
|
||||||
</div>
|
</div>
|
||||||
<CommonToolbar onSearchedClick={this.props.onSearchedClick} searchPlaceholder={'Search files in this library'}/>
|
<CommonToolbar onSearchedClick={this.props.onSearchedClick} searchPlaceholder={'Search files in this library'}/>
|
||||||
</div>
|
</div>
|
||||||
@@ -334,21 +213,6 @@ class MainPanel extends Component {
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
{this.state.showFileDialog &&
|
|
||||||
<CreateFile
|
|
||||||
fileType={this.state.createFileType}
|
|
||||||
parentPath={this.props.path}
|
|
||||||
addFileCancel={this.addFileCancel}
|
|
||||||
onAddFile={this.onAddFile}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
{this.state.showFolderDialog &&
|
|
||||||
<CreateFolder
|
|
||||||
parentPath={this.props.path}
|
|
||||||
addFolderCancel={this.addFolderCancel}
|
|
||||||
onAddFolder={this.onAddFolder}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import cookie from 'react-cookies';
|
|
||||||
import { gettext, repoID, serviceUrl, initialPath, isDir } from './utils/constants';
|
import { gettext, repoID, serviceUrl, initialPath, isDir } from './utils/constants';
|
||||||
import { seafileAPI } from './utils/seafile-api';
|
import { seafileAPI } from './utils/seafile-api';
|
||||||
import { Utils } from './utils/utils';
|
import { Utils } from './utils/utils';
|
||||||
@@ -171,22 +170,6 @@ class Wiki extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
switchViewMode = (mode) => {
|
|
||||||
let dirPath;
|
|
||||||
let tree = this.state.treeData;
|
|
||||||
let node = tree.getNodeByPath(this.state.path);
|
|
||||||
if (node.isDir()) {
|
|
||||||
dirPath = this.state.path;
|
|
||||||
} else {
|
|
||||||
const index = this.state.path.lastIndexOf('/');
|
|
||||||
dirPath = this.state.path.substring(0, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
cookie.save('view_mode', mode, { path: '/' });
|
|
||||||
|
|
||||||
window.location.href = serviceUrl + '/#common/lib/' + repoID + dirPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
loadSidePanel = (filePath) => {
|
loadSidePanel = (filePath) => {
|
||||||
seafileAPI.listDir(repoID, '/',{recursive: true}).then(items => {
|
seafileAPI.listDir(repoID, '/',{recursive: true}).then(items => {
|
||||||
const files = items.data.map(item => {
|
const files = items.data.map(item => {
|
||||||
@@ -788,7 +771,6 @@ class Wiki extends Component {
|
|||||||
latestContributor={this.state.latestContributor}
|
latestContributor={this.state.latestContributor}
|
||||||
direntList={this.state.direntList}
|
direntList={this.state.direntList}
|
||||||
selectedDirentList={this.state.selectedDirentList}
|
selectedDirentList={this.state.selectedDirentList}
|
||||||
switchViewMode={this.switchViewMode}
|
|
||||||
updateDirent={this.updateDirent}
|
updateDirent={this.updateDirent}
|
||||||
onLinkClick={this.onLinkClick}
|
onLinkClick={this.onLinkClick}
|
||||||
onSideNavMenuClick={this.onSideNavMenuClick}
|
onSideNavMenuClick={this.onSideNavMenuClick}
|
||||||
|
@@ -23,13 +23,16 @@ export const folderPermEnabled = window.app.pageOptions.folderPermEnabled === 'T
|
|||||||
export const enableUploadFolder = window.app.pageOptions.enableUploadFolder === 'True';
|
export const enableUploadFolder = window.app.pageOptions.enableUploadFolder === 'True';
|
||||||
export const enableResumableFileUpload = window.app.pageOptions.enableResumableFileUpload === 'True';
|
export const enableResumableFileUpload = window.app.pageOptions.enableResumableFileUpload === 'True';
|
||||||
|
|
||||||
|
//main-page
|
||||||
|
export const mainServiceUrl = window.main ? window.main.pageOptions.serviceUrl : '';
|
||||||
// wiki
|
// wiki
|
||||||
export const slug = window.wiki ? window.wiki.config.slug : '';
|
export const slug = window.wiki ? window.wiki.config.slug : '';
|
||||||
export const repoID = window.wiki ? window.wiki.config.repoId : '';
|
export const repoID = window.wiki ? window.wiki.config.repoId : '';
|
||||||
export const serviceUrl = window.wiki ? window.wiki.config.serviceUrl : '';
|
|
||||||
export const initialPath = window.wiki ? window.wiki.config.initial_path : '';
|
export const initialPath = window.wiki ? window.wiki.config.initial_path : '';
|
||||||
export const permission = window.wiki ? window.wiki.config.permission === 'True' : '';
|
export const permission = window.wiki ? window.wiki.config.permission === 'True' : '';
|
||||||
export const isDir = window.wiki ? window.wiki.config.isDir : '';
|
export const isDir = window.wiki ? window.wiki.config.isDir : '';
|
||||||
|
export const serviceUrl = window.wiki ? window.wiki.config.serviceUrl : '';
|
||||||
|
|
||||||
|
|
||||||
// file history
|
// file history
|
||||||
export const PER_PAGE = 25;
|
export const PER_PAGE = 25;
|
||||||
|
@@ -118,7 +118,7 @@ def base(request):
|
|||||||
'is_pro': True if is_pro_version() else False,
|
'is_pro': True if is_pro_version() else False,
|
||||||
'enable_repo_wiki_mode': dj_settings.ENABLE_REPO_WIKI_MODE,
|
'enable_repo_wiki_mode': dj_settings.ENABLE_REPO_WIKI_MODE,
|
||||||
'enable_upload_folder': dj_settings.ENABLE_UPLOAD_FOLDER,
|
'enable_upload_folder': dj_settings.ENABLE_UPLOAD_FOLDER,
|
||||||
'enable_resumable_fileupload': dj_settings.ENABLE_RESUMABLE_FILEUPLOAD,
|
'enable_resumable_fileupload': dj_settings.ENABLE_RESUMABLE_FILEUPLOAD
|
||||||
}
|
}
|
||||||
|
|
||||||
if request.user.is_staff:
|
if request.user.is_staff:
|
||||||
|
@@ -2,5 +2,12 @@
|
|||||||
{% load render_bundle from webpack_loader %}
|
{% load render_bundle from webpack_loader %}
|
||||||
|
|
||||||
{% block extra_script %}
|
{% block extra_script %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
window.main = {
|
||||||
|
pageOptions: {
|
||||||
|
serviceUrl: "{{ service_url }}",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
{% render_bundle 'app' %}
|
{% render_bundle 'app' %}
|
||||||
{% endblock %}
|
{% endblock %}
|
@@ -10,9 +10,9 @@
|
|||||||
config: {
|
config: {
|
||||||
slug: "{{ wiki.slug }}",
|
slug: "{{ wiki.slug }}",
|
||||||
repoId: "{{ wiki.repo_id }}",
|
repoId: "{{ wiki.repo_id }}",
|
||||||
serviceUrl: "{{ service_url}}",
|
|
||||||
initial_file_path: "{{ file_path }}",
|
initial_file_path: "{{ file_path }}",
|
||||||
permission: "{{ user_can_write }}"
|
permission: "{{ user_can_write }}"
|
||||||
|
serviceUrl: "{{ service_url}}",
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@@ -43,7 +43,7 @@ from seahub.utils import render_permission_error, render_error, \
|
|||||||
get_user_repos, EMPTY_SHA1, gen_file_get_url, \
|
get_user_repos, EMPTY_SHA1, gen_file_get_url, \
|
||||||
new_merge_with_no_conflict, get_max_upload_file_size, \
|
new_merge_with_no_conflict, get_max_upload_file_size, \
|
||||||
is_pro_version, FILE_AUDIT_ENABLED, is_valid_dirent_name, \
|
is_pro_version, FILE_AUDIT_ENABLED, is_valid_dirent_name, \
|
||||||
is_windows_operating_system
|
is_windows_operating_system, get_service_url
|
||||||
from seahub.utils.star import get_dir_starred_files
|
from seahub.utils.star import get_dir_starred_files
|
||||||
from seahub.utils.repo import get_library_storages, parse_repo_perm
|
from seahub.utils.repo import get_library_storages, parse_repo_perm
|
||||||
from seahub.utils.file_op import check_file_lock
|
from seahub.utils.file_op import check_file_lock
|
||||||
@@ -1212,4 +1212,6 @@ def choose_register(request):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def react_fake_view(request):
|
def react_fake_view(request):
|
||||||
return render(request, "react_app.html")
|
return render(request, "react_app.html", {
|
||||||
|
"service_url": get_service_url().rstrip('/')
|
||||||
|
})
|
||||||
|
Reference in New Issue
Block a user