1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-01 15:09:14 +00:00

Upload improve (#2753)

This commit is contained in:
杨顺强
2019-01-05 11:43:33 +08:00
committed by Daniel Pan
parent b04c0ab5d1
commit 6dbd69c436
6 changed files with 198 additions and 60 deletions

View File

@@ -12,10 +12,21 @@ const propTypes = {
class UploadRemindDialog extends React.Component { class UploadRemindDialog extends React.Component {
toggle = () => { toggle = (e) => {
e.nativeEvent.stopImmediatePropagation();
this.props.cancelFileUpload(); this.props.cancelFileUpload();
} }
replaceRepetitionFile = (e) => {
e.nativeEvent.stopImmediatePropagation();
this.props.replaceRepetitionFile();
}
uploadFile = (e) => {
e.nativeEvent.stopImmediatePropagation();
this.props.uploadFile();
}
render() { render() {
let title = gettext('Replace file {filename}?'); let title = gettext('Replace file {filename}?');
@@ -28,8 +39,8 @@ class UploadRemindDialog extends React.Component {
<p>{gettext('Replacing it will overwrite its content.')}</p> <p>{gettext('Replacing it will overwrite its content.')}</p>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button outline color="primary" onClick={this.props.replaceRepetitionFile}>{gettext('Replace')}</Button> <Button outline color="primary" onClick={this.replaceRepetitionFile}>{gettext('Replace')}</Button>
<Button outline color="info" onClick={this.props.uploadFile}>{gettext("Don't replace")}</Button> <Button outline color="info" onClick={this.uploadFile}>{gettext("Don't replace")}</Button>
<Button outline color="danger" onClick={this.toggle}>{gettext('Cancel')}</Button> <Button outline color="danger" onClick={this.toggle}>{gettext('Cancel')}</Button>
</ModalFooter> </ModalFooter>
</Modal> </Modal>

View File

@@ -1,5 +1,6 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import moment from 'moment';
import { siteRoot } from '../../utils/constants'; import { siteRoot } 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';
@@ -421,8 +422,29 @@ class DirView extends React.Component {
this.setState({direntList: newDirentList}); this.setState({direntList: newDirentList});
} }
onFileUploadSuccess = () => { onFileUploadSuccess = (direntObject) => {
// todo update upload file to direntList let isExist = this.state.direntList.some(item => {
return item.name === direntObject.name && item.type === direntObject.type;
});
if (isExist) {
let direntList = this.state.direntList;
for (let i = 0; i < direntList.length; i++) {
let dirent = direntList[i];
if (dirent.name === direntObject.name && dirent.type === direntObject.type) {
let mtime = moment.unix(direntObject.mtime).fromNow();
this.updateDirent(dirent, 'mtime', mtime); // todo file size is need update too, api is not return;
break;
}
}
} else {
direntObject.permission = 'rw';
let dirent = new Dirent(direntObject);
if (direntObject.type === 'dir') {
this.setState({direntList: [dirent, ...this.state.direntList]});
} else {
this.setState({direntList: [...this.state.direntList, dirent]});
}
}
} }
onSearchedClick = (selectedItem) => { onSearchedClick = (selectedItem) => {

View File

@@ -1,4 +1,4 @@
import React from 'react'; import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Resumablejs from '@seafile/resumablejs'; import Resumablejs from '@seafile/resumablejs';
import MD5 from 'MD5'; import MD5 from 'MD5';
@@ -40,6 +40,8 @@ class FileUploader extends React.Component {
isUploadRemindDialogShow: false, isUploadRemindDialogShow: false,
currentResumableFile: null, currentResumableFile: null,
}; };
this.uploadedFolders = [];
} }
componentDidMount() { componentDidMount() {
@@ -174,14 +176,13 @@ class FileUploader extends React.Component {
// single file uploading can check repetition, because custom dialog conn't prevent program execution; // single file uploading can check repetition, because custom dialog conn't prevent program execution;
} }
setUploadFileList = (files) => { setUploadFileList = () => {
let uploadFileList = files.map(resumableFile => { let uploadFileList = this.resumable.files.map(resumableFile => {
return this.buildCustomFileObj(resumableFile); return this.buildCustomFileObj(resumableFile);
}); });
this.setState({ this.setState({
isUploadRemindDialogShow: false,
isUploadProgressDialogShow: true, isUploadProgressDialogShow: true,
uploadFileList: uploadFileList uploadFileList: uploadFileList,
}); });
} }
@@ -204,27 +205,90 @@ class FileUploader extends React.Component {
this.setState({uploadFileList: uploadFileList}); this.setState({uploadFileList: uploadFileList});
} }
onProgress = () => {
let progress = Math.round(this.resumable.progress() * 100);
this.setState({totalProgress: progress});
}
onFileUploadSuccess = (file) => { onFileUploadSuccess = (resumableFile, message) => {
// todos, update uploadList or updateList; let formData = resumableFile.formData;
let currentTime = new Date().getTime()/1000;
message = formData.replace ? message : JSON.parse(message)[0];
if (formData.relative_path) { // upload folder
let relative_path = formData.relative_path;
let dir_name = relative_path.slice(0, relative_path.indexOf('/'));
let dirent = {
id: message.id,
name: dir_name,
type: 'dir',
mtime: currentTime,
};
// update folders cache
let isExist = this.uploadedFolders.some(item => {return item.name === dirent.name;});
if (!isExist) {
this.uploadedFolders.push(dirent);
this.props.onFileUploadSuccess(dirent);
}
// update uploadFileList
let uploadFileList = this.state.uploadFileList.map(item => {
if (item.resumableFile.uniqueIdentifier === resumableFile.uniqueIdentifier) {
item.resumableFile.fileName = message.name;
item.resumableFile.relativePath = relative_path + message.name;
}
return item;
});
this.setState({uploadFileList: uploadFileList});
return;
}
if (formData.replace) { // upload file -- replace exist file
let fileName = resumableFile.fileName;
let dirent = {
id: message,
name: fileName,
type: 'file',
mtime: currentTime
};
this.props.onFileUploadSuccess(dirent); // this contance: just one file
return;
}
// upload file -- add files
let dirent = {
id: message.id,
type: 'file',
name: message.name,
size: message.size,
mtime: currentTime,
};
this.props.onFileUploadSuccess(dirent); // this contance: no repetition file
let uploadFileList = this.state.uploadFileList.map(item => {
if (item.resumableFile.uniqueIdentifier === resumableFile.uniqueIdentifier) {
item.resumableFile.fileName = message.name;
item.resumableFile.relativePath = message.name;
}
return item;
});
this.setState({uploadFileList: uploadFileList});
} }
onFileError = (file) => { onFileError = (file) => {
} }
onProgress = () => {
let progress = Math.round(this.resumable.progress() * 100);
this.setState({totalProgress: progress});
}
onComplete = () => { onComplete = () => {
this.uploadedFolders = [];
} }
onPause = () => [ onPause = () => {
] }
onError = () => { onError = () => {
@@ -243,6 +307,9 @@ class FileUploader extends React.Component {
} }
setHeaders = (resumableFile, resumable) => { setHeaders = (resumableFile, resumable) => {
if (resumableFile.formData.replace) {
return [];
}
let offset = resumable.offset; let offset = resumable.offset;
let chunkSize = resumable.getOpt('chunkSize'); let chunkSize = resumable.getOpt('chunkSize');
let fileSize = resumableFile.size; let fileSize = resumableFile.size;
@@ -328,21 +395,29 @@ class FileUploader extends React.Component {
} }
replaceRepetitionFile = () => { replaceRepetitionFile = () => {
let resumableFile = this.resumable.files[this.resumable.files.length - 1]; let { repoID, path } = this.props;
resumableFile.formData['replace'] = 1; seafileAPI.getUpdateLink(repoID, path).then(res => {
this.resumable.opts.target = res.data;
// this.setState({isUploadRemindDialogShow: false}); let resumableFile = this.resumable.files[this.resumable.files.length - 1];
resumableFile.formData['replace'] = 1;
this.setUploadFileList(this.resumable.files); resumableFile.formData['target_file'] = resumableFile.formData.parent_dir + resumableFile.fileName;
this.setState({isUploadRemindDialogShow: false});
this.resumable.upload(); this.setUploadFileList(this.resumable.files);
this.resumable.upload();
});
} }
uploadFile = () => { uploadFile = () => {
// this.setState({isUploadRemindDialogShow: false}); let resumableFile = this.resumable.files[this.resumable.files.length - 1];
let fileObject = this.buildCustomFileObj(resumableFile);
this.setUploadFileList(this.resumable.files); this.setState({
this.resumable.upload(); isUploadRemindDialogShow: false,
isUploadProgressDialogShow: true,
uploadFileList: [...this.state.uploadFileList, fileObject]
}, () => {
this.resumable.upload();
});
} }
cancelFileUpload = () => { cancelFileUpload = () => {
@@ -352,30 +427,32 @@ class FileUploader extends React.Component {
render() { render() {
return ( return (
<div className="file-uploader-container"> <Fragment>
<div className="file-uploader"> <div className="file-uploader-container">
<input className="upload-input" type="file" ref={node => this.uploadInput = node} onClick={this.onClick}/> <div className="file-uploader">
<input className="upload-input" type="file" ref={node => this.uploadInput = node} onClick={this.onClick}/>
</div>
</div> </div>
{ {
this.state.isUploadProgressDialogShow && this.state.isUploadRemindDialogShow &&
<UploadProgressDialog <UploadRemindDialog
uploadFileList={this.state.uploadFileList} currentResumableFile={this.state.currentResumableFile}
totalProgress={this.state.totalProgress} replaceRepetitionFile={this.replaceRepetitionFile}
onMinimizeUploadDialog={this.onMinimizeUploadDialog} uploadFile={this.uploadFile}
onCloseUploadDialog={this.onCloseUploadDialog} cancelFileUpload={this.cancelFileUpload}
onUploadCancel={this.onUploadCancel} />
/> }
} {
{ this.state.isUploadProgressDialogShow &&
this.state.isUploadRemindDialogShow && <UploadProgressDialog
<UploadRemindDialog uploadFileList={this.state.uploadFileList}
currentResumableFile={this.state.currentResumableFile} totalProgress={this.state.totalProgress}
replaceRepetitionFile={this.replaceRepetitionFile} onMinimizeUploadDialog={this.onMinimizeUploadDialog}
uploadFile={this.uploadFile} onCloseUploadDialog={this.onCloseUploadDialog}
cancelFileUpload={this.cancelFileUpload} onUploadCancel={this.onUploadCancel}
/> />
} }
</div> </Fragment>
); );
} }
} }

View File

@@ -13,8 +13,8 @@ class Dirent {
this.isSelected = false; // is check or not this.isSelected = false; // is check or not
if (json.type === 'file') { if (json.type === 'file') {
this.size = Utils.bytesToSize(json.size); this.size = Utils.bytesToSize(json.size);
this.starred = json.starred; this.starred = json.starred || false;
this.is_locked = json.is_locked; this.is_locked = json.is_locked || false;
this.lock_time = moment.unix(json.lock_time).fromNow(); this.lock_time = moment.unix(json.lock_time).fromNow();
this.lock_owner= json.lock_owner; this.lock_owner= json.lock_owner;
this.locked_by_me = json.locked_by_me; this.locked_by_me = json.locked_by_me;

View File

@@ -53,6 +53,7 @@ const propTypes = {
onItemsCopy: PropTypes.func.isRequired, onItemsCopy: PropTypes.func.isRequired,
onItemsDelete: PropTypes.func.isRequired, onItemsDelete: PropTypes.func.isRequired,
onLinkClick: PropTypes.func.isRequired, onLinkClick: PropTypes.func.isRequired,
onFileUploadSuccess: PropTypes.func.isRequired,
isDraft: PropTypes.bool, isDraft: PropTypes.bool,
hasDraft: PropTypes.bool, hasDraft: PropTypes.bool,
reviewStatus: PropTypes.any, reviewStatus: PropTypes.any,
@@ -146,8 +147,8 @@ class MainPanel extends Component {
this.uploader.onFolderUpload(); this.uploader.onFolderUpload();
} }
onFileUploadSuccess = (file) => { onFileUploadSuccess = (direntObject) => {
// todo this.props.onFileUploadSuccess(direntObject);
} }
handlePageScroll = () => { handlePageScroll = () => {
@@ -291,8 +292,8 @@ class MainPanel extends Component {
dragAndDrop={true} dragAndDrop={true}
path={this.props.path} path={this.props.path}
repoID={repoID} repoID={repoID}
onFileUploadSuccess={this.onFileUploadSuccess}
direntList={this.props.direntList} direntList={this.props.direntList}
onFileUploadSuccess={this.onFileUploadSuccess}
/> />
</Fragment> </Fragment>
} }

View File

@@ -556,6 +556,32 @@ class Wiki extends Component {
this.setState({direntList: direntList}); this.setState({direntList: direntList});
} }
onFileUploadSuccess = (direntObject) => {
let isExist = this.state.direntList.some(item => {
return item.name === direntObject.name && item.type === direntObject.type;
});
if (isExist) {
let direntList = this.state.direntList;
for (let i = 0; i < direntList.length; i++) {
let dirent = direntList[i];
if (dirent.name === direntObject.name && dirent.type === direntObject.type) {
let mtime = moment.unix(direntObject.mtime).fromNow();
this.updateDirent(dirent, 'mtime', mtime); // todo file size is need update too, api is not return;
break;
}
}
} else {
direntObject.permission = 'rw';
let dirent = new Dirent(direntObject);
this.addNodeToTree(dirent.name, this.state.path, dirent.type);
if (direntObject.type === 'dir') {
this.setState({direntList: [dirent, ...this.state.direntList]});
} else {
this.setState({direntList: [...this.state.direntList, dirent]});
}
}
}
onMoveItems = (destRepo, destDirentPath) => { onMoveItems = (destRepo, destDirentPath) => {
let direntPaths = this.getSelectedDirentPaths(); let direntPaths = this.getSelectedDirentPaths();
let dirNames = this.getSelectedDirentNames(); let dirNames = this.getSelectedDirentNames();
@@ -937,6 +963,7 @@ class Wiki extends Component {
onItemsMove={this.onMoveItems} onItemsMove={this.onMoveItems}
onItemsCopy={this.onCopyItems} onItemsCopy={this.onCopyItems}
onItemsDelete={this.onDeleteItems} onItemsDelete={this.onDeleteItems}
onFileUploadSuccess={this.onFileUploadSuccess}
hash={this.hash} hash={this.hash}
isDraft={this.state.isDraft} isDraft={this.state.isDraft}
hasDraft={this.state.hasDraft} hasDraft={this.state.hasDraft}