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:
@@ -12,10 +12,21 @@ const propTypes = {
|
||||
|
||||
class UploadRemindDialog extends React.Component {
|
||||
|
||||
toggle = () => {
|
||||
toggle = (e) => {
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
this.props.cancelFileUpload();
|
||||
}
|
||||
|
||||
replaceRepetitionFile = (e) => {
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
this.props.replaceRepetitionFile();
|
||||
}
|
||||
|
||||
uploadFile = (e) => {
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
this.props.uploadFile();
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
let title = gettext('Replace file {filename}?');
|
||||
@@ -28,8 +39,8 @@ class UploadRemindDialog extends React.Component {
|
||||
<p>{gettext('Replacing it will overwrite its content.')}</p>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button outline color="primary" onClick={this.props.replaceRepetitionFile}>{gettext('Replace')}</Button>
|
||||
<Button outline color="info" onClick={this.props.uploadFile}>{gettext("Don't replace")}</Button>
|
||||
<Button outline color="primary" onClick={this.replaceRepetitionFile}>{gettext('Replace')}</Button>
|
||||
<Button outline color="info" onClick={this.uploadFile}>{gettext("Don't replace")}</Button>
|
||||
<Button outline color="danger" onClick={this.toggle}>{gettext('Cancel')}</Button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import moment from 'moment';
|
||||
import { siteRoot } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { Utils } from '../../utils/utils';
|
||||
@@ -421,8 +422,29 @@ class DirView extends React.Component {
|
||||
this.setState({direntList: newDirentList});
|
||||
}
|
||||
|
||||
onFileUploadSuccess = () => {
|
||||
// todo update upload file to 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);
|
||||
if (direntObject.type === 'dir') {
|
||||
this.setState({direntList: [dirent, ...this.state.direntList]});
|
||||
} else {
|
||||
this.setState({direntList: [...this.state.direntList, dirent]});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onSearchedClick = (selectedItem) => {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Resumablejs from '@seafile/resumablejs';
|
||||
import MD5 from 'MD5';
|
||||
@@ -40,6 +40,8 @@ class FileUploader extends React.Component {
|
||||
isUploadRemindDialogShow: false,
|
||||
currentResumableFile: null,
|
||||
};
|
||||
|
||||
this.uploadedFolders = [];
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -174,14 +176,13 @@ class FileUploader extends React.Component {
|
||||
// single file uploading can check repetition, because custom dialog conn't prevent program execution;
|
||||
}
|
||||
|
||||
setUploadFileList = (files) => {
|
||||
let uploadFileList = files.map(resumableFile => {
|
||||
setUploadFileList = () => {
|
||||
let uploadFileList = this.resumable.files.map(resumableFile => {
|
||||
return this.buildCustomFileObj(resumableFile);
|
||||
});
|
||||
this.setState({
|
||||
isUploadRemindDialogShow: false,
|
||||
isUploadProgressDialogShow: true,
|
||||
uploadFileList: uploadFileList
|
||||
uploadFileList: uploadFileList,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -205,26 +206,89 @@ class FileUploader extends React.Component {
|
||||
this.setState({uploadFileList: uploadFileList});
|
||||
}
|
||||
|
||||
onFileUploadSuccess = (file) => {
|
||||
// todos, update uploadList or updateList;
|
||||
onProgress = () => {
|
||||
let progress = Math.round(this.resumable.progress() * 100);
|
||||
this.setState({totalProgress: progress});
|
||||
}
|
||||
|
||||
onFileUploadSuccess = (resumableFile, message) => {
|
||||
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) => {
|
||||
|
||||
}
|
||||
|
||||
onProgress = () => {
|
||||
let progress = Math.round(this.resumable.progress() * 100);
|
||||
this.setState({totalProgress: progress});
|
||||
}
|
||||
|
||||
onComplete = () => {
|
||||
|
||||
this.uploadedFolders = [];
|
||||
}
|
||||
|
||||
onPause = () => [
|
||||
onPause = () => {
|
||||
|
||||
]
|
||||
}
|
||||
|
||||
onError = () => {
|
||||
|
||||
@@ -243,6 +307,9 @@ class FileUploader extends React.Component {
|
||||
}
|
||||
|
||||
setHeaders = (resumableFile, resumable) => {
|
||||
if (resumableFile.formData.replace) {
|
||||
return [];
|
||||
}
|
||||
let offset = resumable.offset;
|
||||
let chunkSize = resumable.getOpt('chunkSize');
|
||||
let fileSize = resumableFile.size;
|
||||
@@ -328,21 +395,29 @@ class FileUploader extends React.Component {
|
||||
}
|
||||
|
||||
replaceRepetitionFile = () => {
|
||||
let resumableFile = this.resumable.files[this.resumable.files.length - 1];
|
||||
resumableFile.formData['replace'] = 1;
|
||||
let { repoID, path } = this.props;
|
||||
seafileAPI.getUpdateLink(repoID, path).then(res => {
|
||||
this.resumable.opts.target = res.data;
|
||||
|
||||
// this.setState({isUploadRemindDialogShow: false});
|
||||
|
||||
this.setUploadFileList(this.resumable.files);
|
||||
|
||||
this.resumable.upload();
|
||||
let resumableFile = this.resumable.files[this.resumable.files.length - 1];
|
||||
resumableFile.formData['replace'] = 1;
|
||||
resumableFile.formData['target_file'] = resumableFile.formData.parent_dir + resumableFile.fileName;
|
||||
this.setState({isUploadRemindDialogShow: false});
|
||||
this.setUploadFileList(this.resumable.files);
|
||||
this.resumable.upload();
|
||||
});
|
||||
}
|
||||
|
||||
uploadFile = () => {
|
||||
// this.setState({isUploadRemindDialogShow: false});
|
||||
|
||||
this.setUploadFileList(this.resumable.files);
|
||||
this.resumable.upload();
|
||||
let resumableFile = this.resumable.files[this.resumable.files.length - 1];
|
||||
let fileObject = this.buildCustomFileObj(resumableFile);
|
||||
this.setState({
|
||||
isUploadRemindDialogShow: false,
|
||||
isUploadProgressDialogShow: true,
|
||||
uploadFileList: [...this.state.uploadFileList, fileObject]
|
||||
}, () => {
|
||||
this.resumable.upload();
|
||||
});
|
||||
}
|
||||
|
||||
cancelFileUpload = () => {
|
||||
@@ -352,30 +427,32 @@ class FileUploader extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="file-uploader-container">
|
||||
<div className="file-uploader">
|
||||
<input className="upload-input" type="file" ref={node => this.uploadInput = node} onClick={this.onClick}/>
|
||||
<Fragment>
|
||||
<div className="file-uploader-container">
|
||||
<div className="file-uploader">
|
||||
<input className="upload-input" type="file" ref={node => this.uploadInput = node} onClick={this.onClick}/>
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
this.state.isUploadProgressDialogShow &&
|
||||
<UploadProgressDialog
|
||||
uploadFileList={this.state.uploadFileList}
|
||||
totalProgress={this.state.totalProgress}
|
||||
onMinimizeUploadDialog={this.onMinimizeUploadDialog}
|
||||
onCloseUploadDialog={this.onCloseUploadDialog}
|
||||
onUploadCancel={this.onUploadCancel}
|
||||
/>
|
||||
}
|
||||
{
|
||||
this.state.isUploadRemindDialogShow &&
|
||||
<UploadRemindDialog
|
||||
currentResumableFile={this.state.currentResumableFile}
|
||||
replaceRepetitionFile={this.replaceRepetitionFile}
|
||||
uploadFile={this.uploadFile}
|
||||
cancelFileUpload={this.cancelFileUpload}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
{
|
||||
this.state.isUploadRemindDialogShow &&
|
||||
<UploadRemindDialog
|
||||
currentResumableFile={this.state.currentResumableFile}
|
||||
replaceRepetitionFile={this.replaceRepetitionFile}
|
||||
uploadFile={this.uploadFile}
|
||||
cancelFileUpload={this.cancelFileUpload}
|
||||
/>
|
||||
}
|
||||
{
|
||||
this.state.isUploadProgressDialogShow &&
|
||||
<UploadProgressDialog
|
||||
uploadFileList={this.state.uploadFileList}
|
||||
totalProgress={this.state.totalProgress}
|
||||
onMinimizeUploadDialog={this.onMinimizeUploadDialog}
|
||||
onCloseUploadDialog={this.onCloseUploadDialog}
|
||||
onUploadCancel={this.onUploadCancel}
|
||||
/>
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -13,8 +13,8 @@ class Dirent {
|
||||
this.isSelected = false; // is check or not
|
||||
if (json.type === 'file') {
|
||||
this.size = Utils.bytesToSize(json.size);
|
||||
this.starred = json.starred;
|
||||
this.is_locked = json.is_locked;
|
||||
this.starred = json.starred || false;
|
||||
this.is_locked = json.is_locked || false;
|
||||
this.lock_time = moment.unix(json.lock_time).fromNow();
|
||||
this.lock_owner= json.lock_owner;
|
||||
this.locked_by_me = json.locked_by_me;
|
||||
|
@@ -53,6 +53,7 @@ const propTypes = {
|
||||
onItemsCopy: PropTypes.func.isRequired,
|
||||
onItemsDelete: PropTypes.func.isRequired,
|
||||
onLinkClick: PropTypes.func.isRequired,
|
||||
onFileUploadSuccess: PropTypes.func.isRequired,
|
||||
isDraft: PropTypes.bool,
|
||||
hasDraft: PropTypes.bool,
|
||||
reviewStatus: PropTypes.any,
|
||||
@@ -146,8 +147,8 @@ class MainPanel extends Component {
|
||||
this.uploader.onFolderUpload();
|
||||
}
|
||||
|
||||
onFileUploadSuccess = (file) => {
|
||||
// todo
|
||||
onFileUploadSuccess = (direntObject) => {
|
||||
this.props.onFileUploadSuccess(direntObject);
|
||||
}
|
||||
|
||||
handlePageScroll = () => {
|
||||
@@ -291,8 +292,8 @@ class MainPanel extends Component {
|
||||
dragAndDrop={true}
|
||||
path={this.props.path}
|
||||
repoID={repoID}
|
||||
onFileUploadSuccess={this.onFileUploadSuccess}
|
||||
direntList={this.props.direntList}
|
||||
onFileUploadSuccess={this.onFileUploadSuccess}
|
||||
/>
|
||||
</Fragment>
|
||||
}
|
||||
|
@@ -556,6 +556,32 @@ class Wiki extends Component {
|
||||
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) => {
|
||||
let direntPaths = this.getSelectedDirentPaths();
|
||||
let dirNames = this.getSelectedDirentNames();
|
||||
@@ -937,6 +963,7 @@ class Wiki extends Component {
|
||||
onItemsMove={this.onMoveItems}
|
||||
onItemsCopy={this.onCopyItems}
|
||||
onItemsDelete={this.onDeleteItems}
|
||||
onFileUploadSuccess={this.onFileUploadSuccess}
|
||||
hash={this.hash}
|
||||
isDraft={this.state.isDraft}
|
||||
hasDraft={this.state.hasDraft}
|
||||
|
Reference in New Issue
Block a user