Merge pull request #8104 from owncloud/lukepolo-master

Added the ability to Drag and Drop folders [chrome]
This commit is contained in:
Thomas Müller 2014-04-15 21:39:32 +02:00
commit 8bc7174bdc
6 changed files with 145 additions and 75 deletions

View File

@ -111,23 +111,33 @@ if ($maxUploadFileSize >= 0 and $totalSize > $maxUploadFileSize) {
} }
$result = array(); $result = array();
$directory = '';
if (strpos($dir, '..') === false) { if (strpos($dir, '..') === false) {
$fileCount = count($files['name']); $fileCount = count($files['name']);
for ($i = 0; $i < $fileCount; $i++) { for ($i = 0; $i < $fileCount; $i++) {
// Get the files directory
if(isset($_POST['file_directory']) === true) {
$directory = '/'.$_POST['file_directory'];
}
// $path needs to be normalized - this failed within drag'n'drop upload to a sub-folder // $path needs to be normalized - this failed within drag'n'drop upload to a sub-folder
if (isset($_POST['resolution']) && $_POST['resolution']==='autorename') { if (isset($_POST['resolution']) && $_POST['resolution']==='autorename') {
// append a number in brackets like 'filename (2).ext' // append a number in brackets like 'filename (2).ext'
$target = OCP\Files::buildNotExistingFileName(stripslashes($dir), $files['name'][$i]); $target = OCP\Files::buildNotExistingFileName(stripslashes($dir.$directory), $files['name'][$i]);
} else { } else {
$target = \OC\Files\Filesystem::normalizePath(stripslashes($dir).'/'.$files['name'][$i]); $target = \OC\Files\Filesystem::normalizePath(stripslashes($dir.$directory).'/'.$files['name'][$i]);
} }
if(empty($directory) === true)
{
$directory = \OC\Files\Filesystem::normalizePath(stripslashes($dir)); $directory = \OC\Files\Filesystem::normalizePath(stripslashes($dir));
if (isset($public_directory)) { if (isset($public_directory)) {
// If we are uploading from the public app, // If we are uploading from the public app,
// we want to send the relative path in the ajax request. // we want to send the relative path in the ajax request.
$directory = $public_directory; $directory = $public_directory;
} }
}
if ( ! \OC\Files\Filesystem::file_exists($target) if ( ! \OC\Files\Filesystem::file_exists($target)
|| (isset($_POST['resolution']) && $_POST['resolution']==='replace') || (isset($_POST['resolution']) && $_POST['resolution']==='replace')
@ -186,7 +196,6 @@ if (strpos($dir, '..') === false) {
if ($error === false) { if ($error === false) {
OCP\JSON::encodedPrint($result); OCP\JSON::encodedPrint($result);
exit();
} else { } else {
OCP\JSON::error(array(array('data' => array_merge(array('message' => $error, 'code' => $errorCode), $storageStats)))); OCP\JSON::error(array(array('data' => array_merge(array('message' => $error, 'code' => $errorCode), $storageStats))));
} }

View File

@ -242,12 +242,20 @@ OC.Upload = {
data.errorThrown = errorMessage; data.errorThrown = errorMessage;
} }
if (file.type === '' && file.size === 4096) { // in case folder drag and drop is not supported file will point to a directory
// http://stackoverflow.com/a/20448357
if (!file.type && file.size%4096 === 0 && file.size <= 102400) {
try {
reader = new FileReader();
reader.readAsBinaryString(f);
} catch (NS_ERROR_FILE_ACCESS_DENIED) {
//file is a directory
data.textStatus = 'dirorzero'; data.textStatus = 'dirorzero';
data.errorThrown = t('files', 'Unable to upload {filename} as it is a directory or has 0 bytes', data.errorThrown = t('files', 'Unable to upload {filename} as it is a directory or has 0 bytes',
{filename: file.name} {filename: file.name}
); );
} }
}
// add size // add size
selection.totalBytes += file.size; selection.totalBytes += file.size;
@ -326,10 +334,15 @@ OC.Upload = {
submit: function(e, data) { submit: function(e, data) {
OC.Upload.rememberUpload(data); OC.Upload.rememberUpload(data);
if ( ! data.formData ) { 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 // noone set update parameters, we set the minimum
data.formData = { data.formData = {
requesttoken: oc_requesttoken, requesttoken: oc_requesttoken,
dir: $('#dir').val() dir: $('#dir').val(),
file_directory: fileDirectory
}; };
} }
}, },
@ -683,3 +696,4 @@ $(document).ready(function() {
OC.Upload.init(); OC.Upload.init();
}); });

View File

@ -9,7 +9,7 @@
*/ */
/* global OC, t, n, FileList, FileActions, Files, BreadCrumb */ /* global OC, t, n, FileList, FileActions, Files, BreadCrumb */
/* global procesSelection, dragOptions */ /* global procesSelection, dragOptions, folderDropOptions */
window.FileList = { window.FileList = {
appName: t('files', 'Files'), appName: t('files', 'Files'),
isEmpty: true, isEmpty: true,
@ -212,7 +212,7 @@ window.FileList = {
linkUrl = Files.getDownloadUrl(name, FileList.getCurrentDirectory()); linkUrl = Files.getDownloadUrl(name, FileList.getCurrentDirectory());
} }
td.append('<input id="select-' + fileData.id + '" type="checkbox" /><label for="select-' + fileData.id + '"></label>'); td.append('<input id="select-' + fileData.id + '" type="checkbox" /><label for="select-' + fileData.id + '"></label>');
var link_elem = $('<a></a>').attr({ var linkElem = $('<a></a>').attr({
"class": "name", "class": "name",
"href": linkUrl "href": linkUrl
}); });
@ -228,19 +228,19 @@ window.FileList = {
basename = name; basename = name;
extension = false; extension = false;
} }
var name_span=$('<span></span>').addClass('nametext').text(basename); var nameSpan=$('<span></span>').addClass('nametext').text(basename);
link_elem.append(name_span); linkElem.append(nameSpan);
if (extension) { if (extension) {
name_span.append($('<span></span>').addClass('extension').text(extension)); nameSpan.append($('<span></span>').addClass('extension').text(extension));
} }
// dirs can show the number of uploaded files // dirs can show the number of uploaded files
if (type === 'dir') { if (type === 'dir') {
link_elem.append($('<span></span>').attr({ linkElem.append($('<span></span>').attr({
'class': 'uploadtext', 'class': 'uploadtext',
'currentUploads': 0 'currentUploads': 0
})); }));
} }
td.append(link_elem); td.append(linkElem);
tr.append(td); tr.append(td);
// size column // size column
@ -250,7 +250,7 @@ window.FileList = {
} else { } else {
simpleSize = t('files', 'Pending'); simpleSize = t('files', 'Pending');
} }
var lastModifiedTime = Math.round(mtime / 1000);
td = $('<td></td>').attr({ td = $('<td></td>').attr({
"class": "filesize", "class": "filesize",
"style": 'color:rgb(' + sizeColor + ',' + sizeColor + ',' + sizeColor + ')' "style": 'color:rgb(' + sizeColor + ',' + sizeColor + ',' + sizeColor + ')'
@ -437,8 +437,6 @@ window.FileList = {
}); });
}, },
reloadCallback: function(result) { reloadCallback: function(result) {
var $controls = $('#controls');
delete this._reloadCall; delete this._reloadCall;
this.hideMask(); this.hideMask();
@ -810,10 +808,9 @@ window.FileList = {
var info = t('files', '{dirs} and {files}', infoVars); var info = t('files', '{dirs} and {files}', infoVars);
// don't show the filesize column, if filesize is NaN (e.g. in trashbin) // don't show the filesize column, if filesize is NaN (e.g. in trashbin)
if (isNaN(summary.totalSize)) {
var fileSize = ''; var fileSize = '';
} else { if (!isNaN(summary.totalSize)) {
var fileSize = '<td class="filesize">'+humanFileSize(summary.totalSize)+'</td>'; fileSize = '<td class="filesize">'+humanFileSize(summary.totalSize)+'</td>';
} }
var $summary = $('<tr class="summary" data-file="undefined"><td><span class="info">'+info+'</span></td>'+fileSize+'<td></td></tr>'); var $summary = $('<tr class="summary" data-file="undefined"><td><span class="info">'+info+'</span></td>'+fileSize+'<td></td></tr>');
@ -899,7 +896,6 @@ window.FileList = {
} }
}, },
updateEmptyContent: function() { updateEmptyContent: function() {
var $fileList = $('#fileList');
var permissions = $('#permissions').val(); var permissions = $('#permissions').val();
var isCreatable = (permissions & OC.PERMISSION_CREATE) !== 0; var isCreatable = (permissions & OC.PERMISSION_CREATE) !== 0;
$('#emptycontent').toggleClass('hidden', !isCreatable || !FileList.isEmpty); $('#emptycontent').toggleClass('hidden', !isCreatable || !FileList.isEmpty);
@ -937,13 +933,13 @@ window.FileList = {
}, },
scrollTo:function(file) { scrollTo:function(file) {
//scroll to and highlight preselected file //scroll to and highlight preselected file
var $scrolltorow = FileList.findFileEl(file); var $scrollToRow = FileList.findFileEl(file);
if ($scrolltorow.exists()) { if ($scrollToRow.exists()) {
$scrolltorow.addClass('searchresult'); $scrollToRow.addClass('searchresult');
$(window).scrollTop($scrolltorow.position().top); $(window).scrollTop($scrollToRow.position().top);
//remove highlight when hovered over //remove highlight when hovered over
$scrolltorow.one('hover', function() { $scrollToRow.one('hover', function() {
$scrolltorow.removeClass('searchresult'); $scrollToRow.removeClass('searchresult');
}); });
} }
}, },
@ -979,9 +975,9 @@ $(document).ready(function() {
FileList.initialize(); FileList.initialize();
// handle upload events // handle upload events
var file_upload_start = $('#file_upload_start'); var fileUploadStart = $('#file_upload_start');
file_upload_start.on('fileuploaddrop', function(e, data) { fileUploadStart.on('fileuploaddrop', function(e, data) {
OC.Upload.log('filelist handle fileuploaddrop', e, data); OC.Upload.log('filelist handle fileuploaddrop', e, data);
var dropTarget = $(e.originalEvent.target).closest('tr, .crumb'); var dropTarget = $(e.originalEvent.target).closest('tr, .crumb');
@ -1008,7 +1004,8 @@ $(document).ready(function() {
data.formData = function(form) { data.formData = function(form) {
return [ return [
{name: 'dir', value: dir}, {name: 'dir', value: dir},
{name: 'requesttoken', value: oc_requesttoken} {name: 'requesttoken', value: oc_requesttoken},
{name: 'file_directory', value: data.files[0].relativePath}
]; ];
}; };
} else { } else {
@ -1019,7 +1016,7 @@ $(document).ready(function() {
} }
} }
}); });
file_upload_start.on('fileuploadadd', function(e, data) { fileUploadStart.on('fileuploadadd', function(e, data) {
OC.Upload.log('filelist handle fileuploadadd', e, data); OC.Upload.log('filelist handle fileuploadadd', e, data);
//finish delete if we are uploading a deleted file //finish delete if we are uploading a deleted file
@ -1032,19 +1029,19 @@ $(document).ready(function() {
// add to existing folder // add to existing folder
// update upload counter ui // update upload counter ui
var uploadtext = data.context.find('.uploadtext'); var uploadText = data.context.find('.uploadtext');
var currentUploads = parseInt(uploadtext.attr('currentUploads')); var currentUploads = parseInt(uploadText.attr('currentUploads'), 10);
currentUploads += 1; currentUploads += 1;
uploadtext.attr('currentUploads', currentUploads); uploadText.attr('currentUploads', currentUploads);
var translatedText = n('files', 'Uploading %n file', 'Uploading %n files', currentUploads); var translatedText = n('files', 'Uploading %n file', 'Uploading %n files', currentUploads);
if (currentUploads === 1) { if (currentUploads === 1) {
var img = OC.imagePath('core', 'loading.gif'); var img = OC.imagePath('core', 'loading.gif');
data.context.find('td.filename').attr('style','background-image:url('+img+')'); data.context.find('td.filename').attr('style','background-image:url('+img+')');
uploadtext.text(translatedText); uploadText.text(translatedText);
uploadtext.show(); uploadText.show();
} else { } else {
uploadtext.text(translatedText); uploadText.text(translatedText);
} }
} }
@ -1053,7 +1050,7 @@ $(document).ready(function() {
* when file upload done successfully add row to filelist * when file upload done successfully add row to filelist
* update counter when uploading to sub folder * update counter when uploading to sub folder
*/ */
file_upload_start.on('fileuploaddone', function(e, data) { fileUploadStart.on('fileuploaddone', function(e, data) {
OC.Upload.log('filelist handle fileuploaddone', e, data); OC.Upload.log('filelist handle fileuploaddone', e, data);
var response; var response;
@ -1067,38 +1064,69 @@ $(document).ready(function() {
if (typeof result[0] !== 'undefined' && result[0].status === 'success') { if (typeof result[0] !== 'undefined' && result[0].status === 'success') {
var file = result[0]; var file = result[0];
var size = 0;
if (data.context && data.context.data('type') === 'dir') { if (data.context && data.context.data('type') === 'dir') {
// update upload counter ui // update upload counter ui
var uploadtext = data.context.find('.uploadtext'); var uploadText = data.context.find('.uploadtext');
var currentUploads = parseInt(uploadtext.attr('currentUploads')); var currentUploads = parseInt(uploadText.attr('currentUploads'), 10);
currentUploads -= 1; currentUploads -= 1;
uploadtext.attr('currentUploads', currentUploads); uploadText.attr('currentUploads', currentUploads);
var translatedText = n('files', 'Uploading %n file', 'Uploading %n files', currentUploads); var translatedText = n('files', 'Uploading %n file', 'Uploading %n files', currentUploads);
if (currentUploads === 0) { if (currentUploads === 0) {
var img = OC.imagePath('core', 'filetypes/folder'); var img = OC.imagePath('core', 'filetypes/folder');
data.context.find('td.filename').attr('style','background-image:url('+img+')'); data.context.find('td.filename').attr('style','background-image:url('+img+')');
uploadtext.text(translatedText); uploadText.text(translatedText);
uploadtext.hide(); uploadText.hide();
} else { } else {
uploadtext.text(translatedText); uploadText.text(translatedText);
} }
// update folder size // update folder size
var size = parseInt(data.context.data('size')); size = parseInt(data.context.data('size'), 10);
size += parseInt(file.size); size += parseInt(file.size, 10);
data.context.attr('data-size', size); data.context.attr('data-size', size);
data.context.find('td.filesize').text(humanFileSize(size)); data.context.find('td.filesize').text(humanFileSize(size));
} else { } else {
// only append new file if uploaded into the current folder // only append new file if uploaded into the current folder
if (file.directory !== FileList.getCurrentDirectory()) { if (file.directory !== '/' && file.directory !== FileList.getCurrentDirectory()) {
var fileDirectory = file.directory.replace('/','').replace(/\/$/, "").split('/');
if (fileDirectory.length === 1) {
fileDirectory = fileDirectory[0];
// Get the directory
var fd = FileList.findFileEl(fileDirectory);
if (fd.length === 0) {
var dir = {
name: fileDirectory,
type: 'dir',
mimetype: 'httpd/unix-directory',
permissions: file.permissions,
size: 0,
id: file.parentId
};
FileList.add(dir, {insert: true});
}
} else {
fileDirectory = fileDirectory[0];
}
fileDirectory = FileList.findFileEl(fileDirectory);
// update folder size
size = parseInt(fileDirectory.attr('data-size'), 10);
size += parseInt(file.size, 10);
fileDirectory.attr('data-size', size);
fileDirectory.find('td.filesize').text(humanFileSize(size));
return; return;
} }
// add as stand-alone row to filelist // add as stand-alone row to filelist
var size=t('files', 'Pending'); size = t('files', 'Pending');
if (data.files[0].size>=0) { if (data.files[0].size>=0) {
size=data.files[0].size; size=data.files[0].size;
} }
@ -1110,37 +1138,40 @@ $(document).ready(function() {
} }
} }
}); });
file_upload_start.on('fileuploadstop', function(e, data) { fileUploadStart.on('fileuploadstop', function(e, data) {
OC.Upload.log('filelist handle fileuploadstop', e, data); OC.Upload.log('filelist handle fileuploadstop', e, data);
//if user pressed cancel hide upload chrome //if user pressed cancel hide upload chrome
if (data.errorThrown === 'abort') { if (data.errorThrown === 'abort') {
//cleanup uploading to a dir //cleanup uploading to a dir
var uploadtext = $('tr .uploadtext'); var uploadText = $('tr .uploadtext');
var img = OC.imagePath('core', 'filetypes/folder'); var img = OC.imagePath('core', 'filetypes/folder');
uploadtext.parents('td.filename').attr('style','background-image:url('+img+')'); uploadText.parents('td.filename').attr('style','background-image:url('+img+')');
uploadtext.fadeOut(); uploadText.fadeOut();
uploadtext.attr('currentUploads', 0); uploadText.attr('currentUploads', 0);
} }
}); });
file_upload_start.on('fileuploadfail', function(e, data) { fileUploadStart.on('fileuploadfail', function(e, data) {
OC.Upload.log('filelist handle fileuploadfail', e, data); OC.Upload.log('filelist handle fileuploadfail', e, data);
//if user pressed cancel hide upload chrome //if user pressed cancel hide upload chrome
if (data.errorThrown === 'abort') { if (data.errorThrown === 'abort') {
//cleanup uploading to a dir //cleanup uploading to a dir
var uploadtext = $('tr .uploadtext'); var uploadText = $('tr .uploadtext');
var img = OC.imagePath('core', 'filetypes/folder'); var img = OC.imagePath('core', 'filetypes/folder');
uploadtext.parents('td.filename').attr('style','background-image:url('+img+')'); uploadText.parents('td.filename').attr('style','background-image:url('+img+')');
uploadtext.fadeOut(); uploadText.fadeOut();
uploadtext.attr('currentUploads', 0); uploadText.attr('currentUploads', 0);
} }
}); });
$('#notification').hide(); $('#notification').hide();
$('#notification:first-child').on('click', '.replace', function() { $('#notification:first-child').on('click', '.replace', function() {
OC.Notification.hide(function() { OC.Notification.hide(function() {
FileList.replace($('#notification > span').attr('data-oldName'), $('#notification > span').attr('data-newName'), $('#notification > span').attr('data-isNewFile')); FileList.replace(
$('#notification > span').attr('data-oldName'),
$('#notification > span').attr('data-newName'),
$('#notification > span').attr('data-isNewFile'));
}); });
}); });
$('#notification:first-child').on('click', '.suggest', function() { $('#notification:first-child').on('click', '.suggest', function() {
@ -1170,8 +1201,7 @@ $(document).ready(function() {
function parseHashQuery() { function parseHashQuery() {
var hash = window.location.hash, var hash = window.location.hash,
pos = hash.indexOf('?'), pos = hash.indexOf('?');
query;
if (pos >= 0) { if (pos >= 0) {
return hash.substr(pos + 1); return hash.substr(pos + 1);
} }
@ -1180,8 +1210,7 @@ $(document).ready(function() {
function parseCurrentDirFromUrl() { function parseCurrentDirFromUrl() {
var query = parseHashQuery(), var query = parseHashQuery(),
params, params;
dir = '/';
// try and parse from URL hash first // try and parse from URL hash first
if (query) { if (query) {
params = OC.parseQueryString(decodeQuery(query)); params = OC.parseQueryString(decodeQuery(query));

View File

@ -73,13 +73,14 @@ class Helper
/** /**
* Formats the file info to be returned as JSON to the client. * Formats the file info to be returned as JSON to the client.
* *
* @param \OCP\Files\FileInfo file info * @param \OCP\Files\FileInfo $i
* @return array formatted file info * @return array formatted file info
*/ */
public static function formatFileInfo($i) { public static function formatFileInfo($i) {
$entry = array(); $entry = array();
$entry['id'] = $i['fileid']; $entry['id'] = $i['fileid'];
$entry['parentId'] = $i['parent'];
$entry['date'] = \OCP\Util::formatDate($i['mtime']); $entry['date'] = \OCP\Util::formatDate($i['mtime']);
$entry['mtime'] = $i['mtime'] * 1000; $entry['mtime'] = $i['mtime'] * 1000;
// only pick out the needed attributes // only pick out the needed attributes

View File

@ -62,11 +62,17 @@ $(document).ready(function() {
var file_upload_start = $('#file_upload_start'); var file_upload_start = $('#file_upload_start');
file_upload_start.on('fileuploadadd', function(e, data) { file_upload_start.on('fileuploadadd', function(e, data) {
var fileDirectory = '';
if(typeof data.files[0].relativePath !== 'undefined') {
fileDirectory = data.files[0].relativePath;
}
// Add custom data to the upload handler // Add custom data to the upload handler
data.formData = { data.formData = {
requesttoken: $('#publicUploadRequestToken').val(), requesttoken: $('#publicUploadRequestToken').val(),
dirToken: $('#dirToken').val(), dirToken: $('#dirToken').val(),
subdir: $('input#dir').val() subdir: $('input#dir').val(),
file_directory: fileDirectory
}; };
}); });

View File

@ -629,10 +629,21 @@ class View {
} }
public function fromTmpFile($tmpFile, $path) { public function fromTmpFile($tmpFile, $path) {
if (Filesystem::isValidPath($path)) { if (Filesystem::isValidPath($path)) {
// Get directory that the file is going into
$filePath = dirname($path);
// Create the directories if any
if (!$this->file_exists($filePath)) {
$this->mkdir($filePath);
}
if (!$tmpFile) { if (!$tmpFile) {
debug_print_backtrace(); debug_print_backtrace();
} }
$source = fopen($tmpFile, 'r'); $source = fopen($tmpFile, 'r');
if ($source) { if ($source) {
$this->file_put_contents($path, $source); $this->file_put_contents($path, $source);