diff --git a/frontend/src/components/dialog/upload-remind-dialog.js b/frontend/src/components/dialog/upload-remind-dialog.js index 774eeac541..4b561f7e1e 100644 --- a/frontend/src/components/dialog/upload-remind-dialog.js +++ b/frontend/src/components/dialog/upload-remind-dialog.js @@ -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 {

{gettext('Replacing it will overwrite its content.')}

- - + + diff --git a/frontend/src/components/dir-view/dir-view.js b/frontend/src/components/dir-view/dir-view.js index 4dcb7e632e..ad3d6e759d 100644 --- a/frontend/src/components/dir-view/dir-view.js +++ b/frontend/src/components/dir-view/dir-view.js @@ -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) => { diff --git a/frontend/src/components/file-uploader/file-uploader.js b/frontend/src/components/file-uploader/file-uploader.js index 1031d3d396..76364146c5 100644 --- a/frontend/src/components/file-uploader/file-uploader.js +++ b/frontend/src/components/file-uploader/file-uploader.js @@ -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, }); } @@ -204,27 +205,90 @@ class FileUploader extends React.Component { this.setState({uploadFileList: uploadFileList}); } + + onProgress = () => { + let progress = Math.round(this.resumable.progress() * 100); + this.setState({totalProgress: progress}); + } - onFileUploadSuccess = (file) => { - // todos, update uploadList or updateList; + 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 ( -
-
- this.uploadInput = node} onClick={this.onClick}/> + +
+
+ this.uploadInput = node} onClick={this.onClick}/> +
- { - this.state.isUploadProgressDialogShow && - - } - { - this.state.isUploadRemindDialogShow && - - } -
+ { + this.state.isUploadRemindDialogShow && + + } + { + this.state.isUploadProgressDialogShow && + + } + ); } } diff --git a/frontend/src/models/dirent.js b/frontend/src/models/dirent.js index 62766aadb1..d78a8fcf9c 100644 --- a/frontend/src/models/dirent.js +++ b/frontend/src/models/dirent.js @@ -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; diff --git a/frontend/src/pages/repo-wiki-mode/main-panel.js b/frontend/src/pages/repo-wiki-mode/main-panel.js index 0a159101c2..0a90ab48cb 100644 --- a/frontend/src/pages/repo-wiki-mode/main-panel.js +++ b/frontend/src/pages/repo-wiki-mode/main-panel.js @@ -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} /> } diff --git a/frontend/src/repo-wiki-mode.js b/frontend/src/repo-wiki-mode.js index 7ad1363758..1df02923e4 100644 --- a/frontend/src/repo-wiki-mode.js +++ b/frontend/src/repo-wiki-mode.js @@ -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}