Show conflict dialog before upload when possible

When uploading files, first check if the files exist in the current file
list. For the ones that do, show a conflict dialog.
For the rest, upload directly.

If the upload operation detects a conflict on the server side, it will
also continue populating the conflict dialog.

From now on, server side conflict can only occur if someone concurrently
uploaded a file into the same folder but the current user hasn't
refreshed the list yet.
This commit is contained in:
Vincent Petry 2015-09-28 17:50:11 +02:00
parent d68079f932
commit cc8efaa037
2 changed files with 64 additions and 22 deletions

View File

@ -18,7 +18,7 @@
* - TODO music upload button
*/
/* global Files, FileList, jQuery, oc_requesttoken, humanFileSize, getUniqueName */
/* global jQuery, oc_requesttoken, humanFileSize */
/**
* Function that will allow us to know if Ajax uploads are supported
@ -139,6 +139,9 @@ OC.Upload = {
if (data.data) {
data.data.append('resolution', 'replace');
} else {
if (!data.formData) {
data.formData = [];
}
data.formData.push({name:'resolution', value:'replace'}); //hack for ie8
}
data.submit();
@ -152,6 +155,9 @@ OC.Upload = {
if (data.data) {
data.data.append('resolution', 'autorename');
} else {
if (!data.formData) {
data.formData = [];
}
data.formData.push({name:'resolution', value:'autorename'}); //hack for ie8
}
data.submit();
@ -164,8 +170,9 @@ OC.Upload = {
}
},
/**
* TODO checks the list of existing files prior to uploading and shows a simple dialog to choose
* checks the list of existing files prior to uploading and shows a simple dialog to choose
* skip all, replace all or choose which files to keep
*
* @param {array} selection of files to upload
* @param {object} callbacks - object with several callback methods
* @param {function} callbacks.onNoConflicts
@ -175,14 +182,34 @@ OC.Upload = {
* @param {function} callbacks.onCancel
*/
checkExistingFiles: function (selection, callbacks) {
/*
$.each(selection.uploads, function(i, upload) {
var $row = OCA.Files.App.fileList.findFileEl(upload.files[0].name);
if ($row) {
// TODO check filelist before uploading and show dialog on conflicts, use callbacks
var fileList = OCA.Files.App.fileList;
var conflicts = [];
// only keep non-conflicting uploads
selection.uploads = _.filter(selection.uploads, function(upload) {
var fileInfo = fileList.findFile(upload.files[0].name);
if (fileInfo) {
conflicts.push([
// original
_.extend(fileInfo, {
directory: fileInfo.directory || fileInfo.path || fileList.getCurrentDirectory()
}),
// replacement (File object)
upload
]);
return false;
}
return true;
});
*/
if (conflicts.length) {
_.each(conflicts, function(conflictData) {
OC.dialogs.fileexists(conflictData[1], conflictData[0], conflictData[1].files[0], OC.Upload);
});
}
// upload non-conflicting files
// note: when reaching the server they might still meet conflicts
// if the folder was concurrently modified, these will get added
// to the already visible dialog, if applicable
callbacks.onNoConflicts(selection);
},
@ -368,18 +395,18 @@ OC.Upload = {
},
submit: function(e, data) {
OC.Upload.rememberUpload(data);
if ( ! data.formData ) {
var fileDirectory = '';
if(typeof data.files[0].relativePath !== 'undefined') {
fileDirectory = data.files[0].relativePath;
}
// noone set update parameters, we set the minimum
data.formData = {
requesttoken: oc_requesttoken,
dir: data.targetDir || FileList.getCurrentDirectory(),
file_directory: fileDirectory
};
if (!data.formData) {
data.formData = [];
}
var fileDirectory = '';
if(typeof data.files[0].relativePath !== 'undefined') {
fileDirectory = data.files[0].relativePath;
}
// FIXME: prevent re-adding the same
data.formData.push({name: 'requesttoken', value: oc_requesttoken});
data.formData.push({name: 'dir', value: data.targetDir || FileList.getCurrentDirectory()});
data.formData.push({name: 'file_directory', value: fileDirectory});
},
fail: function(e, data) {
OC.Upload.log('fail', e, data);

View File

@ -719,8 +719,23 @@
return true;
},
/**
* Returns the tr element for a given file name
* @param fileName file name
* Returns the file info for the given file name from the internal collection.
*
* @param {string} fileName file name
* @return {OCA.Files.FileInfo} file info or null if it was not found
*
* @since 8.2
*/
findFile: function(fileName) {
return _.find(this.files, function(aFile) {
return (aFile.name === fileName);
}) || null;
},
/**
* Returns the tr element for a given file name, but only if it was already rendered.
*
* @param {string} fileName file name
* @return {Object} jQuery object of the matching row
*/
findFileEl: function(fileName){
// use filterAttr to avoid escaping issues
@ -1877,7 +1892,7 @@
* @return {bool} true if the file exists in the list, false otherwise
*/
inList:function(file) {
return this.findFileEl(file).length;
return this.findFile(file);
},
/**