mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-02 15:38:15 +00:00
Optimized wiki code (#2566)
* optimized path component * abstract component * repair copy bug * move copy&move&download to list-item * add modal portal
This commit is contained in:
19
frontend/src/components/toolbar/dir-operation-toolbar.js
Normal file
19
frontend/src/components/toolbar/dir-operation-toolbar.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const propTypes = {
|
||||
|
||||
};
|
||||
|
||||
class DirOperationToolbar extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div></div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DirOperationToolbar.propTypes = propTypes;
|
||||
|
||||
export default DirOperationToolbar;
|
@@ -0,0 +1,132 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import URLDecorator from '../../utils/url-decorator';
|
||||
import ZipDownloadDialog from '../dialog/zip-download-dialog';
|
||||
import MoveDirentDialog from '../dialog/move-dirent-dialog';
|
||||
import CopyDirentDialog from '../dialog/copy-dirent-dialog';
|
||||
|
||||
const propTypes = {
|
||||
path: PropTypes.string.isRequired,
|
||||
repoID: PropTypes.string.isRequired,
|
||||
selectedDirentList: PropTypes.array.isRequired,
|
||||
onItemsMove: PropTypes.func.isRequired,
|
||||
onItemsCopy: PropTypes.func.isRequired,
|
||||
onItemsDelete: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class MutipleDirOperationToolbar extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
progress: 0,
|
||||
isProgressDialogShow: false,
|
||||
isMoveDialogShow: false,
|
||||
isCopyDialogShow: false,
|
||||
isMutipleOperation: true,
|
||||
};
|
||||
this.zipToken = null;
|
||||
}
|
||||
|
||||
onMoveToggle = () => {
|
||||
this.setState({isMoveDialogShow: !this.state.isMoveDialogShow});
|
||||
}
|
||||
|
||||
onCopyToggle = () => {
|
||||
this.setState({isCopyDialogShow: !this.state.isCopyDialogShow});
|
||||
}
|
||||
|
||||
onItemsDelete = () => {
|
||||
this.props.onItemsDelete();
|
||||
}
|
||||
|
||||
onItemsDownload = () => {
|
||||
let { path, repoID, selectedDirentList } = this.props;
|
||||
if (selectedDirentList.length) {
|
||||
if (selectedDirentList.length === 1 && !selectedDirentList[0].isDir()) {
|
||||
let direntPath = Utils.joinPath(path, selectedDirentList[0].name);
|
||||
let url = URLDecorator.getUrl({type: 'download_file_url', repoID: repoID, filePath: direntPath});
|
||||
location.href= url;
|
||||
return;
|
||||
}
|
||||
let selectedDirentNames = selectedDirentList.map(dirent => {
|
||||
return dirent.name;
|
||||
});
|
||||
this.setState({isProgressDialogShow: true, progress: 0});
|
||||
seafileAPI.zipDownload(repoID, path, selectedDirentNames).then(res => {
|
||||
this.zipToken = res.data['zip_token'];
|
||||
this.addDownloadAnimation();
|
||||
this.interval = setInterval(this.addDownloadAnimation, 1000);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
addDownloadAnimation = () => {
|
||||
let _this = this;
|
||||
let token = this.zipToken;
|
||||
seafileAPI.queryZipProgress(token).then(res => {
|
||||
let data = res.data;
|
||||
let progress = data.total === 0 ? 100 : (data.zipped / data.total * 100).toFixed(0);
|
||||
this.setState({progress: parseInt(progress)});
|
||||
|
||||
if (data['total'] === data['zipped']) {
|
||||
this.setState({
|
||||
progress: 100
|
||||
});
|
||||
clearInterval(this.interval);
|
||||
location.href = URLDecorator.getUrl({type: 'download_dir_zip_url', token: token});
|
||||
setTimeout(function() {
|
||||
_this.setState({isProgressDialogShow: false});
|
||||
}, 500);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
onCancelDownload = () => {
|
||||
seafileAPI.cancelZipTask(this.zipToken).then(() => {
|
||||
this.setState({isProgressDialogShow: false});
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Fragment>
|
||||
<div className="operation mutiple-dirents-operation">
|
||||
<button className="btn btn-secondary operation-item op-icon sf2-icon-move" title={gettext('Move')} onClick={this.onMoveToggle}></button>
|
||||
<button className="btn btn-secondary operation-item op-icon sf2-icon-copy" title={gettext('Copy')} onClick={this.onCopyToggle}></button>
|
||||
<button className="btn btn-secondary operation-item op-icon sf2-icon-delete" title={gettext('Delete')} onClick={this.props.onItemsDelete}></button>
|
||||
<button className="btn btn-secondary operation-item op-icon sf2-icon-download" title={gettext('Download')} onClick={this.onItemsDownload}></button>
|
||||
</div>
|
||||
{this.state.isMoveDialogShow &&
|
||||
<MoveDirentDialog
|
||||
path={this.props.path}
|
||||
isMutipleOperation={this.state.isMutipleOperation}
|
||||
selectedDirentList={this.props.selectedDirentList}
|
||||
onItemsMove={this.props.onItemsMove}
|
||||
onCancelMove={this.onMoveToggle}
|
||||
/>
|
||||
}
|
||||
{this.state.isCopyDialogShow &&
|
||||
<CopyDirentDialog
|
||||
path={this.props.path}
|
||||
selectedDirentList={this.props.selectedDirentList}
|
||||
isMutipleOperation={this.state.isMutipleOperation}
|
||||
onItemsCopy={this.props.onItemsCopy}
|
||||
onCancelCopy={this.onCopyToggle}
|
||||
/>
|
||||
}
|
||||
{this.state.isProgressDialogShow &&
|
||||
<ZipDownloadDialog progress={this.state.progress} onCancelDownload={this.onCancelDownload} />
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
MutipleDirOperationToolbar.propTypes = propTypes;
|
||||
|
||||
export default MutipleDirOperationToolbar;
|
@@ -1,105 +0,0 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { gettext, repoID, slug, permission, siteRoot } from '../../utils/constants';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import PropTypes from 'prop-types';
|
||||
import ListTagDialog from '../dialog/list-tag-dialog';
|
||||
import CreateTagDialog from '../dialog/create-tag-dialog';
|
||||
import UpdateTagDialog from '../dialog/update-tag-dialog';
|
||||
|
||||
const propTypes = {
|
||||
path: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
class PathToolbar extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
currentTag: null,
|
||||
isListRepoTagShow: false,
|
||||
isUpdateRepoTagShow: false,
|
||||
isCreateRepoTagShow: false,
|
||||
};
|
||||
}
|
||||
|
||||
onListRepoTagToggle = () => {
|
||||
this.setState({isListRepoTagShow: !this.state.isListRepoTagShow});
|
||||
}
|
||||
|
||||
onCreateRepoTagToggle = () => {
|
||||
this.setState({
|
||||
isCreateRepoTagShow: !this.state.isCreateRepoTagShow,
|
||||
isListRepoTagShow: !this.state.isListRepoTagShow,
|
||||
});
|
||||
}
|
||||
|
||||
onUpdateRepoTagToggle = (currentTag) => {
|
||||
this.setState({
|
||||
currentTag: currentTag,
|
||||
isListRepoTagShow: !this.state.isListRepoTagShow,
|
||||
isUpdateRepoTagShow: !this.state.isUpdateRepoTagShow,
|
||||
});
|
||||
}
|
||||
|
||||
isMarkdownFile(filePath) {
|
||||
let name = Utils.getFileName(filePath);
|
||||
return name.indexOf('.md') > -1 ? true : false;
|
||||
}
|
||||
|
||||
render() {
|
||||
let isFile = this.isMarkdownFile(this.props.path);
|
||||
let name = Utils.getFileName(this.props.path);
|
||||
let trashUrl = siteRoot + 'repo/recycle/' + repoID + '/?referer=' + encodeURIComponent(location.href);
|
||||
let historyUrl = siteRoot + 'repo/history/' + repoID + '/?referer=' + encodeURIComponent(location.href);
|
||||
if ( (name === slug || name === '') && !isFile && permission) {
|
||||
return (
|
||||
<Fragment>
|
||||
<ul className="path-toolbar">
|
||||
<li className="toolbar-item"><a className="op-link sf2-icon-tag" onClick={this.onListRepoTagToggle} title={gettext('Tags')} aria-label={gettext('Tags')}></a></li>
|
||||
<li className="toolbar-item"><a className="op-link sf2-icon-trash" href={trashUrl} title={gettext('Trash')} aria-label={gettext('Trash')}></a></li>
|
||||
<li className="toolbar-item"><a className="op-link sf2-icon-history" href={historyUrl} title={gettext('History')} aria-label={gettext('History')}></a></li>
|
||||
</ul>
|
||||
{
|
||||
this.state.isListRepoTagShow &&
|
||||
<ListTagDialog
|
||||
onListTagCancel={this.onListRepoTagToggle}
|
||||
onCreateRepoTag={this.onCreateRepoTagToggle}
|
||||
onUpdateRepoTag={this.onUpdateRepoTagToggle}
|
||||
/>
|
||||
}
|
||||
{
|
||||
this.state.isCreateRepoTagShow &&
|
||||
<CreateTagDialog
|
||||
toggleCancel={this.onCreateRepoTagToggle}
|
||||
/>
|
||||
}
|
||||
{
|
||||
this.state.isUpdateRepoTagShow &&
|
||||
<UpdateTagDialog
|
||||
currentTag={this.state.currentTag}
|
||||
toggleCancel={this.onUpdateRepoTagToggle}
|
||||
/>
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
} else if (!isFile && permission) {
|
||||
return (
|
||||
<ul className="path-toolbar">
|
||||
<li className="toolbar-item"><a className="op-link sf2-icon-trash" href={trashUrl} title={gettext('Trash')} aria-label={gettext('Trash')}></a></li>
|
||||
</ul>
|
||||
);
|
||||
} else if (permission) {
|
||||
historyUrl = siteRoot + 'repo/file_revisions/' + repoID + '/?p=' + Utils.encodePath(this.props.path) + '&referer=' + encodeURIComponent(location.href);
|
||||
return (
|
||||
<ul className="path-toolbar">
|
||||
<li className="toolbar-item"><a className="op-link sf2-icon-history" href={historyUrl} title={gettext('History')} aria-label={gettext('History')}></a></li>
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
PathToolbar.propTypes = propTypes;
|
||||
|
||||
export default PathToolbar;
|
Reference in New Issue
Block a user