From e1927d5bee11b561a293a9488bd27d90c2c043e6 Mon Sep 17 00:00:00 2001 From: Jörn Friedrich Dreyer Date: Mon, 12 Aug 2013 12:33:22 +0200 Subject: fix whitespace, check selected files before starting upload --- apps/files/css/files.css | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'apps/files/css/files.css') diff --git a/apps/files/css/files.css b/apps/files/css/files.css index 86fb0dc6046..acee8471aff 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -189,3 +189,44 @@ table.dragshadow td.size { text-align: center; margin-left: -200px; } + +.oc-dialog .fileexists .original .icon { + width: 64px; + height: 64px; + margin: 5px 5px 5px 0px; + background-repeat: no-repeat; + background-size: 64px 64px; + float: left; +} + +.oc-dialog .fileexists .replacement { + margin-top: 20px; +} + +.oc-dialog .fileexists .replacement .icon { + width: 64px; + height: 64px; + margin: 5px 5px 5px 0px; + background-repeat: no-repeat; + background-size: 64px 64px; + float: left; + clear: both; +} + +.oc-dialog .fileexists label[for="new-name"] { + margin-top: 20px; + display: block; +} +.oc-dialog .fileexists h3 { + font-weight: bold; +} + + +.oc-dialog .oc-dialog-buttonrow { + width:100%; + text-align:right; +} + +.oc-dialog .oc-dialog-buttonrow .cancel { + float:left; +} \ No newline at end of file -- cgit v1.2.3 From f94e6036980644bdd6312e75a8973f2633cf5ff2 Mon Sep 17 00:00:00 2001 From: Jörn Friedrich Dreyer Date: Fri, 16 Aug 2013 11:40:55 +0200 Subject: progress fixes --- apps/files/ajax/upload.php | 9 +- apps/files/css/files.css | 23 +++- apps/files/js/file-upload.js | 263 ++++++++++++++++++++++++++------------- apps/files/js/fileactions.js | 2 +- apps/files/js/filelist.js | 265 ++++++++++++++++++++++++---------------- apps/files/js/files.js | 29 +---- apps/files_sharing/js/public.js | 7 +- core/js/oc-dialogs.js | 215 ++++++++++++++++++-------------- 8 files changed, 503 insertions(+), 310 deletions(-) (limited to 'apps/files/css/files.css') diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php index 8d183bd1f9c..619b5f6a04b 100644 --- a/apps/files/ajax/upload.php +++ b/apps/files/ajax/upload.php @@ -99,8 +99,8 @@ if (strpos($dir, '..') === false) { $fileCount = count($files['name']); for ($i = 0; $i < $fileCount; $i++) { // $path needs to be normalized - this failed within drag'n'drop upload to a sub-folder - if (isset($_POST['new_name'])) { - $newName = $_POST['new_name']; + if (isset($_POST['newname'])) { + $newName = $_POST['newname']; } else { $newName = $files['name'][$i]; } @@ -109,11 +109,12 @@ if (strpos($dir, '..') === false) { } else { $replace = false; } - $target = \OC\Files\Filesystem::normalizePath(stripslashes($dir).$newName); + $target = \OC\Files\Filesystem::normalizePath(stripslashes($dir).'/'.$newName); if ( ! $replace && \OC\Files\Filesystem::file_exists($target)) { $meta = \OC\Files\Filesystem::getFileInfo($target); $result[] = array('status' => 'existserror', - 'mime' => $meta['mimetype'], + 'type' => $meta['mimetype'], + 'mtime' => $meta['mtime'], 'size' => $meta['size'], 'id' => $meta['fileid'], 'name' => basename($target), diff --git a/apps/files/css/files.css b/apps/files/css/files.css index acee8471aff..0ff25a24d76 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -190,6 +190,9 @@ table.dragshadow td.size { margin-left: -200px; } +.oc-dialog .fileexists table { + width: 100%; +} .oc-dialog .fileexists .original .icon { width: 64px; height: 64px; @@ -201,6 +204,7 @@ table.dragshadow td.size { .oc-dialog .fileexists .replacement { margin-top: 20px; + margin-bottom: 20px; } .oc-dialog .fileexists .replacement .icon { @@ -213,10 +217,23 @@ table.dragshadow td.size { clear: both; } -.oc-dialog .fileexists label[for="new-name"] { - margin-top: 20px; - display: block; +.oc-dialog .fileexists .toggle { + background-image: url('%webroot%/core/img/actions/triangle-e.png'); + width: 16px; + height: 16px; +} +.oc-dialog .fileexists #allfileslabel { + float:right; } +.oc-dialog .fileexists #allfiles { + vertical-align: bottom; + position: relative; + top: -3px; +} +.oc-dialog .fileexists #allfiles + span{ + vertical-align: bottom; +} + .oc-dialog .fileexists h3 { font-weight: bold; } diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index bd9757b5ffc..f8899cb07e6 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -1,4 +1,30 @@ /** + * 1. tracking which file to upload next -> upload queue with data elements added whenever add is called + * 2. tracking progress for each folder individually -> track progress in a progress[dirname] object + * - every new selection increases the total size and number of files for a directory + * - add increases, successful done decreases, skip decreases, cancel decreases + * 3. track selections -> the general skip / overwrite decision is selection based and can change + * - server might send already exists error -> show dialog & remember decision for selection again + * - server sends error, how do we find collection? + * 4. track jqXHR object to prevent browser from navigationg away -> track in a uploads[dirname][filename] object [x] + * + * selections can progress in parrallel but each selection progresses sequentially + * + * -> store everything in context? + * context.folder + * context.element? + * context.progressui? + * context.jqXHR + * context.selection + * context.selection.onExistsAction? + * + * context available in what events? + * build in drop() add dir + * latest in add() add file? add selection! + * progress? -> update progress? + * onsubmit -> context.jqXHR? + * fail() -> + * done() * * when versioning app is active -> always overwrite * @@ -22,24 +48,74 @@ * dialoge: * -> skip, replace, choose (or abort) () * -> choose left or right (with skip) (when only one file in list also show rename option and remember for all option) + * + * progress always based on filesize + * number of files as text, bytes as bar + * */ -OC.upload = { + +//TODO clean uploads when all progress has completed +OC.Upload = { + /** + * map to lookup the selections for a given directory. + * @type Array + */ + _selections: {}, + /* + * queue which progress tracker to use for the next upload + * @type Array + */ + _queue: [], + queueUpload:function(data) { + // add to queue + this._queue.push(data); //remember what to upload next + if ( ! this.isProcessing() ) { + this.startUpload(); + } + }, + getSelection:function(originalFiles) { + if (!originalFiles.selectionKey) { + originalFiles.selectionKey = 'selection-' + $.assocArraySize(this._selections); + this._selections[originalFiles.selectionKey] = { + selectionKey:originalFiles.selectionKey, + files:{}, + totalBytes:0, + loadedBytes:0, + currentFile:0, + uploads:{}, + checked:false + }; + } + return this._selections[originalFiles.selectionKey]; + }, + cancelUpload:function(dir, filename) { + var deleted = false; + jQuery.each(this._selections, function(i, selection) { + if (selection.dir === dir && selection.uploads[filename]) { + delete selection.uploads[filename]; + deleted = true; + return false; // end searching through selections + } + }); + return deleted; + }, + cancelUploads:function() { + jQuery.each(this._selections,function(i,selection){ + jQuery.each(selection.uploads, function (j, jqXHR) { + delete jqXHR; + }); + }); + this._queue = []; + this._isProcessing = false; + }, _isProcessing:false, isProcessing:function(){ return this._isProcessing; }, - _uploadQueue:[], - addUpload:function(data){ - this._uploadQueue.push(data); - - if ( ! OC.upload.isProcessing() ) { - OC.upload.startUpload(); - } - }, startUpload:function(){ - if (this._uploadQueue.length > 0) { + if (this._queue.length > 0) { this._isProcessing = true; this.nextUpload(); return true; @@ -48,32 +124,50 @@ OC.upload = { } }, nextUpload:function(){ - if (this._uploadQueue.length > 0) { - var data = this._uploadQueue.pop(); - var jqXHR = data.submit(); - - // remember jqXHR to show warning to user when he navigates away but an upload is still in progress - if (typeof data.context !== 'undefined' && data.context.data('type') === 'dir') { - var dirName = data.context.data('file'); - if(typeof uploadingFiles[dirName] === 'undefined') { - uploadingFiles[dirName] = {}; - } - uploadingFiles[dirName][data.files[0].name] = jqXHR; - } else { - uploadingFiles[data.files[0].name] = jqXHR; - } + if (this._queue.length > 0) { + var data = this._queue.pop(); + var selection = this.getSelection(data.originalFiles); + selection.uploads[data.files[0]] = data.submit(); + } else { //queue is empty, we are done this._isProcessing = false; + //TODO free data } + }, + progressBytes: function() { + var total = 0; + var loaded = 0; + jQuery.each(this._selections, function (i, selection) { + total += selection.totalBytes; + loaded += selection.loadedBytes; + }); + return (loaded/total)*100; + }, + loadedBytes: function() { + var loaded = 0; + jQuery.each(this._selections, function (i, selection) { + loaded += selection.loadedBytes; + }); + return loaded; + }, + totalBytes: function() { + var total = 0; + jQuery.each(this._selections, function (i, selection) { + total += selection.totalBytes; + }); + return total; + }, + handleExists:function(data) { + }, onCancel:function(data){ //TODO cancel all uploads - Files.cancelUploads(); - this._uploadQueue = []; - this._isProcessing = false; + OC.Upload.cancelUploads(); }, onSkip:function(data){ + var selection = this.getSelection(data.originalFiles); + selection.loadedBytes += data.loaded; this.nextUpload(); }, onReplace:function(data){ @@ -83,8 +177,14 @@ OC.upload = { }, onRename:function(data, newName){ //TODO rename file in filelist, stop spinner - data.data.append('new_name', newName); + data.data.append('newname', newName); data.submit(); + }, + setAction:function(data, action) { + + }, + setDefaultAction:function(action) { + } }; @@ -92,15 +192,23 @@ $(document).ready(function() { var file_upload_param = { dropZone: $('#content'), // restrict dropZone to content div + //singleFileUploads is on by default, so the data.files array will always have length 1 add: function(e, data) { var that = $(this); - - if (typeof data.originalFiles.checked === 'undefined') { + + // lookup selection for dir + var selection = OC.Upload.getSelection(data.originalFiles); + + if (!selection.dir) { + selection.dir = $('#dir').val(); + } + + if ( ! selection.checked ) { - var totalSize = 0; + selection.totalBytes = 0; $.each(data.originalFiles, function(i, file) { - totalSize += file.size; + selection.totalBytes += file.size; if (file.type === '' && file.size === 4096) { data.textStatus = 'dirorzero'; @@ -111,11 +219,10 @@ $(document).ready(function() { } }); - if (totalSize > $('#max_upload').val()) { + if (selection.totalBytes > $('#max_upload').val()) { data.textStatus = 'notenoughspace'; data.errorThrown = t('files', 'Not enough space available'); } - if (data.errorThrown) { //don't upload anything var fu = that.data('blueimp-fileupload') || that.data('fileupload'); @@ -123,9 +230,22 @@ $(document).ready(function() { return false; } - data.originalFiles.checked = true; // this will skip the checks on subsequent adds + //TODO refactor away: + //show cancel button + if($('html.lte9').length === 0 && data.dataType !== 'iframe') { + $('#uploadprogresswrapper input.stop').show(); + } } + //all subsequent add calls for this selection can be ignored + //allow navigating to the selection from a context + //context.selection = data.originalFiles.selection; + + //allow navigating to contexts / files of a selection + selection.files[data.files[0].name] = data; + + OC.Upload.queueUpload(data); + //TODO check filename already exists /* if ($('tr[data-file="'+data.files[0].name+'"][data-id]').length > 0) { @@ -140,14 +260,6 @@ $(document).ready(function() { } */ - //add files to queue - OC.upload.addUpload(data); - - //TODO refactor away: - //show cancel button - if($('html.lte9').length === 0 && data.dataType !== 'iframe') { - $('#uploadprogresswrapper input.stop').show(); - } return true; }, /** @@ -176,7 +288,8 @@ $(document).ready(function() { $('#notification').fadeOut(); }, 5000); } - delete uploadingFiles[data.files[0].name]; + var selection = OC.Upload.getSelection(data.originalFiles); + delete selection.uploads[data.files[0]]; }, progress: function(e, data) { // TODO: show nice progress bar in file row @@ -186,7 +299,8 @@ $(document).ready(function() { if($('html.lte9').length > 0) { return; } - var progress = (data.loaded/data.total)*100; + //var progress = (data.loaded/data.total)*100; + var progress = OC.Upload.progressBytes(); $('#uploadprogressbar').progressbar('value', progress); }, /** @@ -204,27 +318,22 @@ $(document).ready(function() { response = data.result[0].body.innerText; } var result=$.parseJSON(response); + var selection = OC.Upload.getSelection(data.originalFiles); - if(typeof result[0] !== 'undefined' && result[0].status === 'success') { - OC.upload.nextUpload(); + if(typeof result[0] !== 'undefined' + && result[0].status === 'success' + ) { + selection.loadedBytes+=data.loaded; + OC.Upload.nextUpload(); } else { if (result[0].status === 'existserror') { - //TODO open dialog and retry with other name? - // get jqXHR reference - if (typeof data.context !== 'undefined' && data.context.data('type') === 'dir') { - var dirName = data.context.data('file'); - var jqXHR = uploadingFiles[dirName][filename]; - } else { - var jqXHR = uploadingFiles[filename]; - } - //filenames can only be changed on the server side - //TODO show "file already exists" dialog - //options: abort | skip | replace / rename - //TODO reset all-files flag? when done with selection? + //show "file already exists" dialog var original = result[0]; var replacement = data.files[0]; - OC.dialogs.fileexists(data, original, replacement, OC.upload); + var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); + OC.dialogs.fileexists(data, original, replacement, OC.Upload, fu); } else { + delete selection.uploads[data.files[0]]; data.textStatus = 'servererror'; data.errorThrown = t('files', result.data.message); var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); @@ -232,19 +341,6 @@ $(document).ready(function() { } } - var filename = result[0].originalname; - - // delete jqXHR reference - if (typeof data.context !== 'undefined' && data.context.data('type') === 'dir') { - var dirName = data.context.data('file'); - delete uploadingFiles[dirName][filename]; - if ($.assocArraySize(uploadingFiles[dirName]) === 0) { - delete uploadingFiles[dirName]; - } - } else { - delete uploadingFiles[filename]; - } - }, /** * called after last upload @@ -252,17 +348,20 @@ $(document).ready(function() { * @param data */ stop: function(e, data) { - if(data.dataType !== 'iframe') { - $('#uploadprogresswrapper input.stop').hide(); - } + if(OC.Upload.progressBytes()>=100) { - //IE < 10 does not fire the necessary events for the progress bar. - if($('html.lte9').length > 0) { - return; - } + if(data.dataType !== 'iframe') { + $('#uploadprogresswrapper input.stop').hide(); + } - $('#uploadprogressbar').progressbar('value', 100); - $('#uploadprogressbar').fadeOut(); + //IE < 10 does not fire the necessary events for the progress bar. + if($('html.lte9').length > 0) { + return; + } + + $('#uploadprogressbar').progressbar('value', 100); + $('#uploadprogressbar').fadeOut(); + } } }; diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js index aa66a57a7b5..277abcfdb15 100644 --- a/apps/files/js/fileactions.js +++ b/apps/files/js/fileactions.js @@ -174,7 +174,7 @@ $(document).ready(function () { FileActions.register('all', 'Delete', OC.PERMISSION_DELETE, function () { return OC.imagePath('core', 'actions/delete'); }, function (filename) { - if (Files.cancelUpload(filename)) { + if (OC.Upload.cancelUpload($('#dir').val(), filename)) { if (filename.substr) { filename = [filename]; } diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index f4863837ce7..335f81e04b9 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -407,151 +407,212 @@ $(document).ready(function(){ // handle upload events var file_upload_start = $('#file_upload_start'); + file_upload_start.on('fileuploaddrop', function(e, data) { - // only handle drop to dir if fileList exists - if ($('#fileList').length > 0) { - var dropTarget = $(e.originalEvent.target).closest('tr'); - if(dropTarget && dropTarget.data('type') === 'dir') { // drag&drop upload to folder - data.context = dropTarget; - var dirName = dropTarget.data('file'); - // update folder in form - data.formData = function(form) { - var formArray = form.serializeArray(); - // array index 0 contains the max files size - // array index 1 contains the request token - // array index 2 contains the directory - var parentDir = formArray[2]['value']; - if (parentDir === '/') { - formArray[2]['value'] += dirName; - } else { - formArray[2]['value'] += '/'+dirName; - } - return formArray; - }; + console.log('fileuploaddrop ' +OC.Upload.loadedBytes()+' / '+OC.Upload.totalBytes()); + + var dropTarget = $(e.originalEvent.target).closest('tr'); + if(dropTarget && dropTarget.data('type') === 'dir') { // drag&drop upload to folder + + // lookup selection for dir + var selection = OC.Upload.getSelection(data.files); + + // remember drop target + selection.dropTarget = dropTarget; + + selection.dir = dropTarget.data('file'); + if (selection.dir !== '/') { + if ($('#dir').val() === '/') { + selection.dir = '/' + selection.dir; + } else { + selection.dir = $('#dir').val() + '/' + selection.dir; + } } - } + + // update folder in form + data.formData = function(form) { + var formArray = form.serializeArray(); + // array index 0 contains the max files size + // array index 1 contains the request token + // array index 2 contains the directory + var parentDir = formArray[2]['value']; + if (parentDir === '/') { + formArray[2]['value'] += selection.dir; + } else { + formArray[2]['value'] += '/' + selection.dir; + } + + return formArray; + }; + } + }); file_upload_start.on('fileuploadadd', function(e, data) { - // only add to fileList if it exists - if ($('#fileList').length > 0) { + console.log('fileuploadadd ' +OC.Upload.loadedBytes()+' / '+OC.Upload.totalBytes()); + + // lookup selection for dir + var selection = OC.Upload.getSelection(data.originalFiles); + + if(FileList.deleteFiles && FileList.deleteFiles.indexOf(data.files[0].name)!==-1){//finish delete if we are uploading a deleted file + FileList.finishDelete(null, true); //delete file before continuing + } + + // add ui visualization to existing folder + if(selection.dropTarget && selection.dropTarget.data('type') === 'dir') { + // add to existing folder + var dirName = selection.dropTarget.data('file'); + + // set dir context + data.context = $('tr').filterAttr('data-type', 'dir').filterAttr('data-file', dirName); - if(FileList.deleteFiles && FileList.deleteFiles.indexOf(data.files[0].name)!==-1){//finish delete if we are uploading a deleted file - FileList.finishDelete(null, true); //delete file before continuing + // update upload counter ui + var uploadtext = data.context.find('.uploadtext'); + var currentUploads = parseInt(uploadtext.attr('currentUploads')); + currentUploads += 1; + uploadtext.attr('currentUploads', currentUploads); + + if(currentUploads === 1) { + var img = OC.imagePath('core', 'loading.gif'); + data.context.find('td.filename').attr('style','background-image:url('+img+')'); + uploadtext.text(t('files', '1 file uploading')); + uploadtext.show(); + } else { + uploadtext.text(currentUploads + ' ' + t('files', 'files uploading')); } + } + + }); + file_upload_start.on('fileuploaddone', function(e, data) { + console.log('fileuploaddone ' +OC.Upload.loadedBytes()+' / '+OC.Upload.totalBytes()); + + var response; + if (typeof data.result === 'string') { + response = data.result; + } else { + // fetch response from iframe + response = data.result[0].body.innerText; + } + var result=$.parseJSON(response); - // add ui visualization to existing folder - var dropTarget = $(e.originalEvent.target).closest('tr'); - if(dropTarget && dropTarget.data('type') === 'dir') { - // add to existing folder - var dirName = dropTarget.data('file'); + if(typeof result[0] !== 'undefined' && result[0].status === 'success') { + var file = result[0]; - // set dir context - data.context = $('tr').filterAttr('data-type', 'dir').filterAttr('data-file', dirName); + if (data.context && data.context.data('type') === 'dir') { // update upload counter ui var uploadtext = data.context.find('.uploadtext'); var currentUploads = parseInt(uploadtext.attr('currentUploads')); - currentUploads += 1; + currentUploads -= 1; uploadtext.attr('currentUploads', currentUploads); - if(currentUploads === 1) { - var img = OC.imagePath('core', 'loading.gif'); + if(currentUploads === 0) { + var img = OC.imagePath('core', 'filetypes/folder.png'); data.context.find('td.filename').attr('style','background-image:url('+img+')'); - uploadtext.text(t('files', '1 file uploading')); - uploadtext.show(); + uploadtext.text(''); + uploadtext.hide(); } else { uploadtext.text(currentUploads + ' ' + t('files', 'files uploading')); } - } - } - }); - file_upload_start.on('fileuploaddone', function(e, data) { - // only update the fileList if it exists - if ($('#fileList').length > 0) { - var response; - if (typeof data.result === 'string') { - response = data.result; + + // update folder size + var size = parseInt(data.context.data('size')); + size += parseInt(file.size); + data.context.attr('data-size', size); + data.context.find('td.filesize').text(humanFileSize(size)); + } else { - // fetch response from iframe - response = data.result[0].body.innerText; - } - var result=$.parseJSON(response); - - if(typeof result[0] !== 'undefined' && result[0].status === 'success') { - var file = result[0]; - - if (data.context && data.context.data('type') === 'dir') { - - // update upload counter ui - var uploadtext = data.context.find('.uploadtext'); - var currentUploads = parseInt(uploadtext.attr('currentUploads')); - currentUploads -= 1; - uploadtext.attr('currentUploads', currentUploads); - if(currentUploads === 0) { - var img = OC.imagePath('core', 'filetypes/folder.png'); - data.context.find('td.filename').attr('style','background-image:url('+img+')'); - uploadtext.text(''); - uploadtext.hide(); - } else { - uploadtext.text(currentUploads + ' ' + t('files', 'files uploading')); - } - // update folder size - var size = parseInt(data.context.data('size')); - size += parseInt(file.size) ; - data.context.attr('data-size', size); - data.context.find('td.filesize').text(humanFileSize(size)); + // add as stand-alone row to filelist + var size=t('files','Pending'); + if (data.files[0].size>=0){ + size=data.files[0].size; + } + var date=new Date(); + var param = {}; + if ($('#publicUploadRequestToken').length) { + param.download_url = document.location.href + '&download&path=/' + $('#dir').val() + '/' + file.name; + } + //should the file exist in the list remove it + FileList.remove(file.name); + + // create new file context + data.context = FileList.addFile(file.name, file.size, date, false, false, param); - } else { - - // add as stand-alone row to filelist - var uniqueName = getUniqueName(data.files[0].name); - var size=t('files','Pending'); - if (data.files[0].size>=0){ - size=data.files[0].size; - } - var date=new Date(); - var param = {}; - if ($('#publicUploadRequestToken').length) { - param.download_url = document.location.href + '&download&path=/' + $('#dir').val() + '/' + uniqueName; - } - - //should the file exist in the list remove it - FileList.remove(file.name); + // update file data + data.context.attr('data-mime',file.mime).attr('data-id',file.id); - // create new file context - data.context = FileList.addFile(file.name, file.size, date, false, false, param); - - // update file data - data.context.attr('data-mime',file.mime).attr('data-id',file.id); - - getMimeIcon(file.mime, function(path){ - data.context.find('td.filename').attr('style','background-image:url('+path+')'); - }); - } + getMimeIcon(file.mime, function(path){ + data.context.find('td.filename').attr('style','background-image:url('+path+')'); + }); } } }); + + file_upload_start.on('fileuploadalways', function(e, data) { + console.log('fileuploadalways ' +OC.Upload.loadedBytes()+' / '+OC.Upload.totalBytes()); + }); + file_upload_start.on('fileuploadsend', function(e, data) { + console.log('fileuploadsend ' +OC.Upload.loadedBytes()+' / '+OC.Upload.totalBytes()); + + // TODOD add vis + //data.context.element = + }); + file_upload_start.on('fileuploadprogress', function(e, data) { + console.log('fileuploadprogress ' +OC.Upload.loadedBytes()+' / '+OC.Upload.totalBytes()); + }); + file_upload_start.on('fileuploadprogressall', function(e, data) { + console.log('fileuploadprogressall ' +OC.Upload.loadedBytes()+' / '+OC.Upload.totalBytes()); + }); + file_upload_start.on('fileuploadstop', function(e, data) { + console.log('fileuploadstop ' +OC.Upload.loadedBytes()+' / '+OC.Upload.totalBytes()); + }); + file_upload_start.on('fileuploadfail', function(e, data) { + console.log('fileuploadfail ' +OC.Upload.loadedBytes()+' / '+OC.Upload.totalBytes()); + }); + /* file_upload_start.on('fileuploadfail', function(e, data) { - // only update the fileList if it exists + console.log('fileuploadfail'+((data.files&&data.files.length>0)?' '+data.files[0].name:'')); + + // if we are uploading to a subdirectory + if (data.context && data.context.data('type') === 'dir') { + + // update upload counter ui + var uploadtext = data.context.find('.uploadtext'); + var currentUploads = parseInt(uploadtext.attr('currentUploads')); + currentUploads -= 1; + uploadtext.attr('currentUploads', currentUploads); + if(currentUploads === 0) { + var img = OC.imagePath('core', 'filetypes/folder.png'); + data.context.find('td.filename').attr('style','background-image:url('+img+')'); + uploadtext.text(''); + uploadtext.hide(); + } else { + uploadtext.text(currentUploads + ' ' + t('files', 'files uploading')); + } + + } + // cleanup files, error notification has been shown by fileupload code var tr = data.context; if (typeof tr === 'undefined') { tr = $('tr').filterAttr('data-file', data.files[0].name); } if (tr.attr('data-type') === 'dir') { + //cleanup uploading to a dir var uploadtext = tr.find('.uploadtext'); var img = OC.imagePath('core', 'filetypes/folder.png'); tr.find('td.filename').attr('style','background-image:url('+img+')'); uploadtext.text(''); uploadtext.hide(); //TODO really hide already + } else { + //TODO add row when sending file //remove file tr.fadeOut(); tr.remove(); } }); - +*/ $('#notification').hide(); $('#notification').on('click', '.undo', function(){ if (FileList.deleteFiles) { diff --git a/apps/files/js/files.js b/apps/files/js/files.js index 3fad3fae7d3..a907aeab1fc 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -1,31 +1,5 @@ var uploadingFiles = {}; Files={ - cancelUpload:function(filename) { - if(uploadingFiles[filename]) { - uploadingFiles[filename].abort(); - delete uploadingFiles[filename]; - return true; - } - return false; - }, - cancelUploads:function() { - $.each(uploadingFiles,function(index,file) { - if(typeof file['abort'] === 'function') { - file.abort(); - var filename = $('tr').filterAttr('data-file',index); - filename.hide(); - filename.find('input[type="checkbox"]').removeAttr('checked'); - filename.removeClass('selected'); - } else { - $.each(file,function(i,f) { - f.abort(); - delete file[i]; - }); - } - delete uploadingFiles[index]; - }); - procesSelection(); - }, updateMaxUploadFilesize:function(response) { if(response == undefined) { return; @@ -117,7 +91,8 @@ $(document).ready(function() { // Trigger cancelling of file upload $('#uploadprogresswrapper .stop').on('click', function() { - Files.cancelUploads(); + OC.Upload.cancelUploads(); + procesSelection(); }); // Show trash bin diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js index 294223aa094..a20b4ae636f 100644 --- a/apps/files_sharing/js/public.js +++ b/apps/files_sharing/js/public.js @@ -62,7 +62,10 @@ $(document).ready(function() { // Add Uploadprogress Wrapper to controls bar $('#controls').append($('#additional_controls div#uploadprogresswrapper')); - // Cancel upload trigger - $('#cancel_upload_button').click(Files.cancelUploads); + // Cancel upload trigger + $('#cancel_upload_button').click(function() { + OC.Upload.cancelUploads(); + procesSelection(); + }); }); diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js index 88a3f6628cb..ea03ef21455 100644 --- a/core/js/oc-dialogs.js +++ b/core/js/oc-dialogs.js @@ -207,105 +207,142 @@ var OCdialogs = { * @param {object} controller a controller with onCancel, onSkip, onReplace and onRename methods */ fileexists:function(data, original, replacement, controller) { - if (typeof controller !== 'object') { - controller = {}; - } - var self = this; - $.when(this._getFileExistsTemplate()).then(function($tmpl) { - var dialog_name = 'oc-dialog-fileexists-' + OCdialogs.dialogs_counter + '-content'; - var dialog_id = '#' + dialog_name; - var title = t('files','Replace »{filename}«?',{filename: original.name}); - var $dlg = $tmpl.octemplate({ - dialog_name: dialog_name, - title: title, - type: 'fileexists', - - why: t('files','Another file with the same name already exists in "{dir}".',{dir:'somedir'}), - what: t('files','Replacing it will overwrite it\'s contents.'), - original_heading: t('files','Original file'), - original_size: t('files','Size: {size}',{size: original.size}), - original_mtime: t('files','Last changed: {mtime}',{mtime: original.mtime}), + var selection = controller.getSelection(data.originalFiles); + if (selection.defaultAction) { + controller[selection.defaultAction](data); + } else { + $.when(this._getFileExistsTemplate()).then(function($tmpl) { + var dialog_name = 'oc-dialog-fileexists-' + OCdialogs.dialogs_counter + '-content'; + var dialog_id = '#' + dialog_name; + var title = t('files','Replace »{filename}«?',{filename: original.name}); + var original_size= t('files','Size: {size}',{size: original.size}); + var original_mtime = t('files','Last changed: {mtime}',{mtime: original.mtime}); + var replacement_size= t('files','Size: {size}',{size: replacement.size}); + var replacement_mtime = t('files','Last changed: {mtime}',{mtime: replacement.mtime}); + var $dlg = $tmpl.octemplate({ + dialog_name: dialog_name, + title: title, + type: 'fileexists', - replacement_heading: t('files','Replace with'), - replacement_size: t('files','Size: {size}',{size: replacement.size}), - replacement_mtime: t('files','Last changed: {mtime}',{mtime: replacement.mtime}), + why: t('files','Another file with the same name already exists in "{dir}".',{dir:'somedir'}), + what: t('files','Replacing it will overwrite it\'s contents.'), + original_heading: t('files','Original file'), + original_size: original_size, + original_mtime: original_mtime, - new_name_label: t('files','Choose a new name for the target.'), - all_files_label: t('files','Use this action for all files.') - }); - $('body').append($dlg); - - $(dialog_id + ' .original .icon').css('background-image','url('+OC.imagePath('core', 'filetypes/file.png')+')'); - $(dialog_id + ' .replacement .icon').css('background-image','url('+OC.imagePath('core', 'filetypes/file.png')+')'); - $(dialog_id + ' #new-name').val(original.name); - - - $(dialog_id + ' #new-name').on('keyup', function(e){ - if ($(dialog_id + ' #new-name').val() === original.name) { - - $(dialog_id + ' + div .rename').removeClass('primary').hide(); - $(dialog_id + ' + div .replace').addClass('primary').show(); - } else { - $(dialog_id + ' + div .rename').addClass('primary').show(); - $(dialog_id + ' + div .replace').removeClass('primary').hide(); - } - }); + replacement_heading: t('files','Replace with'), + replacement_size: replacement_size, + replacement_mtime: replacement_mtime, - buttonlist = [{ - text: t('core', 'Cancel'), - classes: 'cancel', - click: function(){ - if ( typeof controller.onCancel !== 'undefined') { - controller.onCancel(data); - } - $(dialog_id).ocdialog('close'); + new_name_label: t('files','Choose a new name for the target.'), + all_files_label: t('files','Use this action for all files.') + }); + $('body').append($dlg); + + getMimeIcon(original.type,function(path){ + $(dialog_id + ' .original .icon').css('background-image','url('+path+')'); + }); + getMimeIcon(replacement.type,function(path){ + $(dialog_id + ' .replacement .icon').css('background-image','url('+path+')'); + }); + $(dialog_id + ' #newname').val(original.name); + + + $(dialog_id + ' #newname').on('keyup', function(e){ + if ($(dialog_id + ' #newname').val() === original.name) { + $(dialog_id + ' + div .rename').removeClass('primary').hide(); + $(dialog_id + ' + div .replace').addClass('primary').show(); + } else { + $(dialog_id + ' + div .rename').addClass('primary').show(); + $(dialog_id + ' + div .replace').removeClass('primary').hide(); } - }, - { - text: t('core', 'Skip'), - classes: 'skip', - click: function(){ - if ( typeof controller.onSkip !== 'undefined') { - controller.onSkip(data); + }); + + buttonlist = [{ + text: t('core', 'Cancel'), + classes: 'cancel', + click: function(){ + if ( typeof controller.onCancel !== 'undefined') { + controller.onCancel(data); + } + $(dialog_id).ocdialog('close'); } - $(dialog_id).ocdialog('close'); - } - }, - { - text: t('core', 'Replace'), - classes: 'replace', - click: function(){ - if ( typeof controller.onReplace !== 'undefined') { - controller.onReplace(data); + }, + { + text: t('core', 'Skip'), + classes: 'skip', + click: function(){ + if ( typeof controller.onSkip !== 'undefined') { + if($(dialog_id + ' #allfiles').prop('checked')){ + selection.defaultAction = 'onSkip'; + /*selection.defaultAction = function(){ + controller.onSkip(data); + };*/ + } + controller.onSkip(data); + } + // trigger fileupload done with status skip + //data.result[0].status = 'skip'; + //fileupload._trigger('done', data.e, data); + $(dialog_id).ocdialog('close'); } - $(dialog_id).ocdialog('close'); }, - defaultButton: true - }, - { - text: t('core', 'Rename'), - classes: 'rename', - click: function(){ - if ( typeof controller.onRename !== 'undefined') { - controller.onRename(data, $(dialog_id + ' #new-name').val()); + { + text: t('core', 'Replace'), + classes: 'replace', + click: function(){ + if ( typeof controller.onReplace !== 'undefined') { + if($(dialog_id + ' #allfiles').prop('checked')){ + selection.defaultAction = 'onReplace'; + /*selection.defaultAction = function(){ + controller.onReplace(data); + };*/ + } + controller.onReplace(data); + } + $(dialog_id).ocdialog('close'); + }, + defaultButton: true + }, + { + text: t('core', 'Rename'), + classes: 'rename', + click: function(){ + if ( typeof controller.onRename !== 'undefined') { + //TODO use autorename when repeat is checked + controller.onRename(data, $(dialog_id + ' #newname').val()); + } + $(dialog_id).ocdialog('close'); } - $(dialog_id).ocdialog('close'); - } - }]; + }]; - $(dialog_id).ocdialog({ - closeOnEscape: true, - modal: true, - buttons: buttonlist, - closeButton: null + $(dialog_id).ocdialog({ + width: 500, + closeOnEscape: true, + modal: true, + buttons: buttonlist, + closeButton: null + }); + OCdialogs.dialogs_counter++; + + $(dialog_id + ' + div .rename').hide(); + $(dialog_id + ' #newname').hide(); + + $(dialog_id + ' #newnamecb').on('change', function(){ + if ($(dialog_id + ' #newnamecb').prop('checked')) { + $(dialog_id + ' #newname').fadeIn(); + } else { + $(dialog_id + ' #newname').fadeOut(); + $(dialog_id + ' #newname').val(original.name); + } + }); + + + }) + .fail(function() { + alert(t('core', 'Error loading file exists template')); }); - OCdialogs.dialogs_counter++; - - $(dialog_id + ' + div .rename').hide(); - }) - .fail(function() { - alert(t('core', 'Error loading file exists template')); - }); + } }, _getFilePickerTemplate: function() { var defer = $.Deferred(); -- cgit v1.2.3 From 7c9d9992432839f2265b8f6b0f43ed15bfca9ff1 Mon Sep 17 00:00:00 2001 From: Jörn Friedrich Dreyer Date: Thu, 22 Aug 2013 14:29:00 +0200 Subject: reduced complexity, added listing conflicts to dialog --- apps/files/ajax/upload.php | 1 + apps/files/css/files.css | 53 +++++--- apps/files/js/file-upload.js | 226 +++++++++++++++++++++++--------- core/js/oc-dialogs.js | 305 +++++++++++++++++++++++++++---------------- 4 files changed, 390 insertions(+), 195 deletions(-) (limited to 'apps/files/css/files.css') diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php index 619b5f6a04b..218482cb41d 100644 --- a/apps/files/ajax/upload.php +++ b/apps/files/ajax/upload.php @@ -131,6 +131,7 @@ if (strpos($dir, '..') === false) { $result[] = array('status' => 'success', 'mime' => $meta['mimetype'], + 'mtime' => $meta['mtime'], 'size' => $meta['size'], 'id' => $meta['fileid'], 'name' => basename($target), diff --git a/apps/files/css/files.css b/apps/files/css/files.css index 0ff25a24d76..dcd6aeadf82 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -193,28 +193,54 @@ table.dragshadow td.size { .oc-dialog .fileexists table { width: 100%; } -.oc-dialog .fileexists .original .icon { +.oc-dialog .fileexists th { + padding-left: 0; + padding-right: 0; +} +.oc-dialog .fileexists th input[type='checkbox'] { + margin-right: 3px; +} +.oc-dialog .fileexists th:first-child { + width: 235px; +} +.oc-dialog .fileexists th label { + font-weight: normal; + color:black; +} +.oc-dialog .fileexists th .count { + margin-left: 3px; +} +.oc-dialog .fileexists .conflict { + width: 100%; + height: 85px; +} +.oc-dialog .fileexists .conflict .filename { + color:#777; + word-break: break-all; +} +.oc-dialog .fileexists .icon { width: 64px; height: 64px; - margin: 5px 5px 5px 0px; + margin: 0px 5px 5px 5px; background-repeat: no-repeat; background-size: 64px 64px; float: left; } .oc-dialog .fileexists .replacement { - margin-top: 20px; - margin-bottom: 20px; + float: left; + width: 235px; } - -.oc-dialog .fileexists .replacement .icon { - width: 64px; - height: 64px; - margin: 5px 5px 5px 0px; - background-repeat: no-repeat; - background-size: 64px 64px; +.oc-dialog .fileexists .original { + float: left; + width: 235px; +} +.oc-dialog .fileexists .conflict-wrapper { + overflow-y:scroll; + max-height: 225px; +} +.oc-dialog .fileexists .conflict-wrapper input[type='checkbox'] { float: left; - clear: both; } .oc-dialog .fileexists .toggle { @@ -234,9 +260,6 @@ table.dragshadow td.size { vertical-align: bottom; } -.oc-dialog .fileexists h3 { - font-weight: bold; -} .oc-dialog .oc-dialog-buttonrow { diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index c620942170c..ec8c97ff457 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -1,4 +1,43 @@ /** + * + * and yet another idea how to handle file uploads: + * let the jquery fileupload thing handle as much as possible + * + * use singlefileupload + * on first add of every selection + * - check all files of originalFiles array with files in dir + * - on conflict show dialog + * - skip all -> remember as default action + * - replace all -> remember as default action + * - choose -> show choose dialog + * - mark files to keep + * - when only existing -> remember as single skip action + * - when only new -> remember as single replace action + * - when both -> remember as single autorename action + * - start uploading selection + * + * on send + * - if single action or default action + * - when skip -> abort upload + * ..- when replace -> add replace=true parameter + * ..- when rename -> add newName=filename parameter + * ..- when autorename -> add autorename=true parameter + * + * on fail + * - if server sent existserror + * - show dialog + * - on skip single -> abort single upload + * - on skip always -> remember as default action + * - on replace single -> replace single upload + * - on replace always -> remember as default action + * - on rename single -> rename single upload, propose autorename - when changed disable remember always checkbox + * - on rename always -> remember autorename as default action + * - resubmit data + * + * on uplad done + * - if last upload -> unset default action + * + * ------------------------------------------------------------- * * use put t ocacnel upload before it starts? use chunked uploads? * @@ -202,11 +241,11 @@ OC.Upload = { data.submit(); }, logStatus:function(caption, e, data) { - console.log(caption+' ' +OC.Upload.loadedBytes()+' / '+OC.Upload.totalBytes()); - if (data) { - console.log(data); - } - console.log(e); + console.log(caption); + console.log(data); + }, + checkExistingFiles: function (selection, callbacks){ + callbacks.onNoConflicts(selection); } }; @@ -214,44 +253,110 @@ $(document).ready(function() { var file_upload_param = { dropZone: $('#content'), // restrict dropZone to content div + autoUpload: false, + sequentialUploads: true, //singleFileUploads is on by default, so the data.files array will always have length 1 + /** + * on first add of every selection + * - check all files of originalFiles array with files in dir + * - on conflict show dialog + * - skip all -> remember as single skip action for all conflicting files + * - replace all -> remember as single replace action for all conflicting files + * - choose -> show choose dialog + * - mark files to keep + * - when only existing -> remember as single skip action + * - when only new -> remember as single replace action + * - when both -> remember as single autorename action + * - start uploading selection + * @param {type} e + * @param {type} data + * @returns {Boolean} + */ add: function(e, data) { OC.Upload.logStatus('add', e, data); var that = $(this); - // lookup selection for dir - var selection = OC.Upload.getSelection(data.originalFiles); + // we need to collect all data upload objects before starting the upload so we can check their existence + // and set individual conflict actions. unfortunately there is only one variable that we can use to identify + // the selection a data upload is part of, so we have to collect them in data.originalFiles + // turning singleFileUploads off is not an option because we want to gracefully handle server errors like + // already exists - if (!selection.dir) { - selection.dir = $('#dir').val(); + // create a container where we can store the data objects + if ( ! data.originalFiles.selection ) { + // initialize selection and remember number of files to upload + data.originalFiles.selection = { + uploads: [], + filesToUpload: data.originalFiles.length, + totalBytes: 0 + }; } + var selection = data.originalFiles.selection; - if ( ! selection.checked ) { + // add uploads + if ( selection.uploads.length < selection.filesToUpload ){ + // remember upload + selection.uploads.push(data); + } + + //examine file + var file = data.files[0]; + + if (file.type === '' && file.size === 4096) { + data.textStatus = 'dirorzero'; + data.errorThrown = t('files', 'Unable to upload {filename} as it is a directory or has 0 bytes', + {filename: file.name} + ); + } + + // add size + selection.totalBytes += file.size; + + //check max upload size + if (selection.totalBytes > $('#max_upload').val()) { + data.textStatus = 'notenoughspace'; + data.errorThrown = t('files', 'Not enough space available'); + } + + // end upload for whole selection on error + if (data.errorThrown) { + // trigger fileupload fail + var fu = that.data('blueimp-fileupload') || that.data('fileupload'); + fu._trigger('fail', e, data); + return false; //don't upload anything + } + + // check existing files whan all is collected + if ( selection.uploads.length >= selection.filesToUpload ) { - selection.totalBytes = 0; - $.each(data.originalFiles, function(i, file) { - selection.totalBytes += file.size; + //remove our selection hack: + delete data.originalFiles.selection; - if (file.type === '' && file.size === 4096) { - data.textStatus = 'dirorzero'; - data.errorThrown = t('files', 'Unable to upload {filename} as it is a directory or has 0 bytes', - {filename: file.name} - ); - return false; + var callbacks = { + + onNoConflicts: function (selection) { + $.each(selection.uploads, function(i, upload) { + upload.submit(); + }); + }, + onSkipConflicts: function (selection) { + //TODO mark conflicting files as toskip + }, + onReplaceConflicts: function (selection) { + //TODO mark conflicting files as toreplace + }, + onChooseConflicts: function (selection) { + //TODO mark conflicting files as chosen + }, + onCancel: function (selection) { + $.each(selection.uploads, function(i, upload) { + upload.abort(); + }); } - }); + }; - if (selection.totalBytes > $('#max_upload').val()) { - data.textStatus = 'notenoughspace'; - data.errorThrown = t('files', 'Not enough space available'); - } - if (data.errorThrown) { - //don't upload anything - var fu = that.data('blueimp-fileupload') || that.data('fileupload'); - fu._trigger('fail', e, data); - return false; - } + OC.Upload.checkExistingFiles(selection, callbacks); //TODO refactor away: //show cancel button @@ -259,15 +364,8 @@ $(document).ready(function() { $('#uploadprogresswrapper input.stop').show(); } } + - //all subsequent add calls for this selection can be ignored - //allow navigating to the selection from a context - //context.selection = data.originalFiles.selection; - - //allow navigating to contexts / files of a selection - selection.files[data.files[0].name] = data; - - OC.Upload.queueUpload(data); //TODO check filename already exists /* @@ -283,7 +381,7 @@ $(document).ready(function() { } */ - return true; + return true; // continue adding files }, /** * called after the first add, does NOT have the data param @@ -314,8 +412,8 @@ $(document).ready(function() { $('#notification').fadeOut(); }, 5000); } - var selection = OC.Upload.getSelection(data.originalFiles); - OC.Upload.deleteSelectionUpload(selection, data.files[0].name); + //var selection = OC.Upload.getSelection(data.originalFiles); + //OC.Upload.deleteSelectionUpload(selection, data.files[0].name); //if user pressed cancel hide upload progress bar and cancel button if (data.errorThrown === 'abort') { @@ -339,8 +437,8 @@ $(document).ready(function() { if($('html.lte9').length > 0) { return; } - //var progress = (data.loaded/data.total)*100; - var progress = OC.Upload.progressBytes(); + var progress = (data.loaded/data.total)*100; + //var progress = OC.Upload.progressBytes(); $('#uploadprogressbar').progressbar('value', progress); }, /** @@ -359,15 +457,15 @@ $(document).ready(function() { response = data.result[0].body.innerText; } var result=$.parseJSON(response); - var selection = OC.Upload.getSelection(data.originalFiles); + //var selection = OC.Upload.getSelection(data.originalFiles); if(typeof result[0] !== 'undefined' && result[0].status === 'success' ) { - if (selection) { - selection.loadedBytes+=data.loaded; - } - OC.Upload.nextUpload(); + //if (selection) { + // selection.loadedBytes+=data.loaded; + //} + //OC.Upload.nextUpload(); } else { if (result[0].status === 'existserror') { //show "file already exists" dialog @@ -385,10 +483,10 @@ $(document).ready(function() { } //if user pressed cancel hide upload chrome - if (! OC.Upload.isProcessing()) { - $('#uploadprogresswrapper input.stop').fadeOut(); - $('#uploadprogressbar').fadeOut(); - } + //if (! OC.Upload.isProcessing()) { + // $('#uploadprogresswrapper input.stop').fadeOut(); + // $('#uploadprogressbar').fadeOut(); + //} }, /** @@ -398,27 +496,27 @@ $(document).ready(function() { */ stop: function(e, data) { OC.Upload.logStatus('stop', e, data); - if(OC.Upload.progressBytes()>=100) { //only hide controls when all selections have ended uploading + //if(OC.Upload.progressBytes()>=100) { //only hide controls when all selections have ended uploading - OC.Upload.cancelUploads(); //cleanup + //OC.Upload.cancelUploads(); //cleanup - if(data.dataType !== 'iframe') { - $('#uploadprogresswrapper input.stop').hide(); - } + // if(data.dataType !== 'iframe') { + // $('#uploadprogresswrapper input.stop').hide(); + // } //IE < 10 does not fire the necessary events for the progress bar. if($('html.lte9').length > 0) { return; } - $('#uploadprogressbar').progressbar('value', 100); - $('#uploadprogressbar').fadeOut(); - } + // $('#uploadprogressbar').progressbar('value', 100); + // $('#uploadprogressbar').fadeOut(); + //} //if user pressed cancel hide upload chrome - if (! OC.Upload.isProcessing()) { - $('#uploadprogresswrapper input.stop').fadeOut(); - $('#uploadprogressbar').fadeOut(); - } + //if (! OC.Upload.isProcessing()) { + // $('#uploadprogresswrapper input.stop').fadeOut(); + // $('#uploadprogressbar').fadeOut(); + //} } }; diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js index ea03ef21455..a101cce9d1f 100644 --- a/core/js/oc-dialogs.js +++ b/core/js/oc-dialogs.js @@ -200,148 +200,221 @@ var OCdialogs = { alert(t('core', 'Error loading message template')); }); }, + _fileexistsshown: false, /** * Displays file exists dialog - * @param {object} original a file with name, size and mtime - * @param {object} replacement a file with name, size and mtime - * @param {object} controller a controller with onCancel, onSkip, onReplace and onRename methods + * @param {object} data upload object + * @param {object} original file with name, size and mtime + * @param {object} replacement file with name, size and mtime + * @param {object} controller with onCancel, onSkip, onReplace and onRename methods */ fileexists:function(data, original, replacement, controller) { + var self = this; var selection = controller.getSelection(data.originalFiles); if (selection.defaultAction) { controller[selection.defaultAction](data); } else { - $.when(this._getFileExistsTemplate()).then(function($tmpl) { - var dialog_name = 'oc-dialog-fileexists-' + OCdialogs.dialogs_counter + '-content'; - var dialog_id = '#' + dialog_name; - var title = t('files','Replace »{filename}«?',{filename: original.name}); - var original_size= t('files','Size: {size}',{size: original.size}); - var original_mtime = t('files','Last changed: {mtime}',{mtime: original.mtime}); - var replacement_size= t('files','Size: {size}',{size: replacement.size}); - var replacement_mtime = t('files','Last changed: {mtime}',{mtime: replacement.mtime}); - var $dlg = $tmpl.octemplate({ - dialog_name: dialog_name, - title: title, - type: 'fileexists', - - why: t('files','Another file with the same name already exists in "{dir}".',{dir:'somedir'}), - what: t('files','Replacing it will overwrite it\'s contents.'), - original_heading: t('files','Original file'), - original_size: original_size, - original_mtime: original_mtime, - - replacement_heading: t('files','Replace with'), - replacement_size: replacement_size, - replacement_mtime: replacement_mtime, - - new_name_label: t('files','Choose a new name for the target.'), - all_files_label: t('files','Use this action for all files.') - }); - $('body').append($dlg); - + var dialog_name = 'oc-dialog-fileexists-content'; + var dialog_id = '#' + dialog_name; + if (this._fileexistsshown) { + // add row + var conflict = $(dialog_id+ ' .conflict').last().clone(); + conflict.find('.name').text(original.name); + conflict.find('.original .size').text(humanFileSize(original.size)); + conflict.find('.original .mtime').text(formatDate(original.mtime*1000)); + conflict.find('.replacement .size').text(humanFileSize(replacement.size)); + conflict.find('.replacement .mtime').text(formatDate(replacement.lastModifiedDate)); getMimeIcon(original.type,function(path){ - $(dialog_id + ' .original .icon').css('background-image','url('+path+')'); + conflict.find('.original .icon').css('background-image','url('+path+')'); }); getMimeIcon(replacement.type,function(path){ - $(dialog_id + ' .replacement .icon').css('background-image','url('+path+')'); + conflict.find('.replacement .icon').css('background-image','url('+path+')'); }); - $(dialog_id + ' #newname').val(original.name); + $(dialog_id+' .conflict').last().after(conflict); + $(dialog_id).parent().children('.oc-dialog-title').text(t('files','{count} file conflicts',{count:$(dialog_id+ ' .conflict').length})); + + //set more recent mtime bold + if (replacement.lastModifiedDate.getTime() > original.mtime*1000) { + conflict.find('.replacement .mtime').css('font-weight', 'bold'); + } else if (replacement.lastModifiedDate.getTime() < original.mtime*1000) { + conflict.find('.original .mtime').css('font-weight', 'bold'); + } else { + //TODO add to same mtime colletion? + } + + // set bigger size bold + if (replacement.size > original.size) { + conflict.find('.replacement .size').css('font-weight','bold'); + } else if (replacement.size < original.size) { + conflict.find('.original .size').css('font-weight','bold'); + } else { + //TODO add to same size colletion? + } + + //add checkbox toggling actions + conflict.find('.replacement,.original').on('click', function(){ + var checkbox = $(this).find('input[type="checkbox"]'); + checkbox.prop('checkbox', !checkbox.prop('checkbox')); + }).find('input[type="checkbox"]').prop('checkbox',false); + + //TODO show skip action for files with same size and mtime + + $(window).trigger('resize'); + } else { + //create dialog + this._fileexistsshown = true; + $.when(this._getFileExistsTemplate()).then(function($tmpl) { + var title = t('files','One file conflict'); + var original_size = humanFileSize(original.size); + var original_mtime = formatDate(original.mtime*1000); + var replacement_size= humanFileSize(replacement.size); + var replacement_mtime = formatDate(replacement.lastModifiedDate); + var $dlg = $tmpl.octemplate({ + dialog_name: dialog_name, + title: title, + type: 'fileexists', + why: t('files','Which files do you want to keep?'), + what: t('files','If you select both versions, the copied file will have a number added to its name.'), + filename: original.name, + + original_size: original_size, + original_mtime: original_mtime, - $(dialog_id + ' #newname').on('keyup', function(e){ - if ($(dialog_id + ' #newname').val() === original.name) { - $(dialog_id + ' + div .rename').removeClass('primary').hide(); - $(dialog_id + ' + div .replace').addClass('primary').show(); - } else { - $(dialog_id + ' + div .rename').addClass('primary').show(); - $(dialog_id + ' + div .replace').removeClass('primary').hide(); - } - }); + replacement_size: replacement_size, + replacement_mtime: replacement_mtime + }); + $('body').append($dlg); - buttonlist = [{ - text: t('core', 'Cancel'), - classes: 'cancel', - click: function(){ - if ( typeof controller.onCancel !== 'undefined') { - controller.onCancel(data); - } - $(dialog_id).ocdialog('close'); - } - }, - { - text: t('core', 'Skip'), - classes: 'skip', - click: function(){ - if ( typeof controller.onSkip !== 'undefined') { - if($(dialog_id + ' #allfiles').prop('checked')){ - selection.defaultAction = 'onSkip'; - /*selection.defaultAction = function(){ - controller.onSkip(data); - };*/ - } - controller.onSkip(data); - } - // trigger fileupload done with status skip - //data.result[0].status = 'skip'; - //fileupload._trigger('done', data.e, data); - $(dialog_id).ocdialog('close'); + getMimeIcon(original.type,function(path){ + $(dialog_id + ' .original .icon').css('background-image','url('+path+')'); + }); + getMimeIcon(replacement.type,function(path){ + $(dialog_id + ' .replacement .icon').css('background-image','url('+path+')'); + }); + $(dialog_id + ' #newname').val(original.name); + + $(dialog_id + ' #newname').on('keyup', function(e){ + if ($(dialog_id + ' #newname').val() === original.name) { + $(dialog_id + ' + div .rename').removeClass('primary').hide(); + $(dialog_id + ' + div .replace').addClass('primary').show(); + } else { + $(dialog_id + ' + div .rename').addClass('primary').show(); + $(dialog_id + ' + div .replace').removeClass('primary').hide(); } - }, - { - text: t('core', 'Replace'), - classes: 'replace', - click: function(){ - if ( typeof controller.onReplace !== 'undefined') { - if($(dialog_id + ' #allfiles').prop('checked')){ - selection.defaultAction = 'onReplace'; - /*selection.defaultAction = function(){ - controller.onReplace(data); - };*/ + }); + + buttonlist = [{ + text: t('core', 'Cancel'), + classes: 'cancel', + click: function(){ + self._fileexistsshown = false; + if ( typeof controller.onCancel !== 'undefined') { + controller.onCancel(data); } - controller.onReplace(data); + $(dialog_id).ocdialog('close'); } - $(dialog_id).ocdialog('close'); }, - defaultButton: true - }, - { - text: t('core', 'Rename'), - classes: 'rename', - click: function(){ - if ( typeof controller.onRename !== 'undefined') { - //TODO use autorename when repeat is checked - controller.onRename(data, $(dialog_id + ' #newname').val()); + { + text: t('core', 'Continue'), + classes: 'continue', + click: function(){ + self._fileexistsshown = false; + if ( typeof controller.onRename !== 'undefined') { + //TODO use autorename when repeat is checked + controller.onRename(data, $(dialog_id + ' #newname').val()); + } + $(dialog_id).ocdialog('close'); } - $(dialog_id).ocdialog('close'); + }]; + + $(dialog_id).ocdialog({ + width: 500, + closeOnEscape: true, + modal: true, + buttons: buttonlist, + closeButton: null + }); + + $(dialog_id + ' + div .rename').hide(); + $(dialog_id + ' #newname').hide(); + + $(dialog_id + ' #newnamecb').on('change', function(){ + if ($(dialog_id + ' #newnamecb').prop('checked')) { + $(dialog_id + ' #newname').fadeIn(); + } else { + $(dialog_id + ' #newname').fadeOut(); + $(dialog_id + ' #newname').val(original.name); } - }]; + }); + $(dialog_id).css('height','auto'); - $(dialog_id).ocdialog({ - width: 500, - closeOnEscape: true, - modal: true, - buttons: buttonlist, - closeButton: null - }); - OCdialogs.dialogs_counter++; + var conflict = $(dialog_id + ' .conflict').last(); + //set more recent mtime bold + if (replacement.lastModifiedDate.getTime() > original.mtime*1000) { + conflict.find('.replacement .mtime').css('font-weight','bold'); + } else if (replacement.lastModifiedDate.getTime() < original.mtime*1000) { + conflict.find('.original .mtime').css('font-weight','bold'); + } else { + //TODO add to same mtime colletion? + } - $(dialog_id + ' + div .rename').hide(); - $(dialog_id + ' #newname').hide(); - - $(dialog_id + ' #newnamecb').on('change', function(){ - if ($(dialog_id + ' #newnamecb').prop('checked')) { - $(dialog_id + ' #newname').fadeIn(); + // set bigger size bold + if (replacement.size > original.size) { + conflict.find('.replacement .size').css('font-weight','bold'); + } else if (replacement.size < original.size) { + conflict.find('.original .size').css('font-weight','bold'); } else { - $(dialog_id + ' #newname').fadeOut(); - $(dialog_id + ' #newname').val(original.name); + //TODO add to same size colletion? } - }); - - }) - .fail(function() { - alert(t('core', 'Error loading file exists template')); - }); + //add checkbox toggling actions + //add checkbox toggling actions + $(dialog_id).find('.allnewfiles').on('click', function(){ + var checkboxes = $(dialog_id).find('.replacement input[type="checkbox"]'); + checkboxes.prop('checked', $(this).prop('checked')); + }); + $(dialog_id).find('.allexistingfiles').on('click', function(){ + var checkboxes = $(dialog_id).find('.original input[type="checkbox"]'); + checkboxes.prop('checked', $(this).prop('checked')); + }); + conflict.find('.replacement,.original').on('click', function(){ + var checkbox = $(this).find('input[type="checkbox"]'); + checkbox.prop('checked', !checkbox.prop('checked')); + }); + + //update counters + $(dialog_id).on('click', '.replacement,.allnewfiles', function(){ + var count = $(dialog_id).find('.replacement input[type="checkbox"]:checked').length; + if (count === $(dialog_id+ ' .conflict').length) { + $(dialog_id).find('.allnewfiles').prop('checked', true); + $(dialog_id).find('.allnewfiles + .count').text(t('files','(all selected)')); + } else if (count > 0) { + $(dialog_id).find('.allnewfiles').prop('checked', false); + $(dialog_id).find('.allnewfiles + .count').text(t('files','({count} selected)',{count:count})); + } else { + $(dialog_id).find('.allnewfiles').prop('checked', false); + $(dialog_id).find('.allnewfiles + .count').text(''); + } + }); + $(dialog_id).on('click', '.original,.allexistingfiles', function(){ + var count = $(dialog_id).find('.original input[type="checkbox"]:checked').length; + if (count === $(dialog_id+ ' .conflict').length) { + $(dialog_id).find('.allexistingfiles').prop('checked', true); + $(dialog_id).find('.allexistingfiles + .count').text(t('files','(all selected)')); + } else if (count > 0) { + $(dialog_id).find('.allexistingfiles').prop('checked', false); + $(dialog_id).find('.allexistingfiles + .count').text(t('files','({count} selected)',{count:count})); + } else { + $(dialog_id).find('.allexistingfiles').prop('checked', false); + $(dialog_id).find('.allexistingfiles + .count').text(''); + } + }); + }) + .fail(function() { + alert(t('core', 'Error loading file exists template')); + }); + } } }, _getFilePickerTemplate: function() { -- cgit v1.2.3 From 49fd7e9f1e037266304053c7337c714339d82553 Mon Sep 17 00:00:00 2001 From: Jörn Friedrich Dreyer Date: Wed, 4 Sep 2013 15:24:25 +0200 Subject: refactor dialog creation --- apps/files/css/files.css | 7 +- apps/files/js/filelist.js | 12 ++-- apps/files/templates/fileexists.html | 26 +++++++ core/js/oc-dialogs.js | 134 ++++++++++++----------------------- 4 files changed, 84 insertions(+), 95 deletions(-) create mode 100644 apps/files/templates/fileexists.html (limited to 'apps/files/css/files.css') diff --git a/apps/files/css/files.css b/apps/files/css/files.css index 141f4557bed..cc556f8321a 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -356,6 +356,9 @@ table.dragshadow td.size { width: 100%; height: 85px; } +.oc-dialog .fileexists .conflict.template { + display: none; +} .oc-dialog .fileexists .conflict .filename { color:#777; word-break: break-all; @@ -377,11 +380,11 @@ table.dragshadow td.size { float: left; width: 235px; } -.oc-dialog .fileexists .conflict-wrapper { +.oc-dialog .fileexists .conflicts { overflow-y:scroll; max-height: 225px; } -.oc-dialog .fileexists .conflict-wrapper input[type='checkbox'] { +.oc-dialog .fileexists .conflict input[type='checkbox'] { float: left; } diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 77ae039f807..31e2a8300e2 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -579,13 +579,14 @@ $(document).ready(function(){ currentUploads += 1; uploadtext.attr('currentUploads', currentUploads); + var translatedText = n('files', 'Uploading %n file', 'Uploading %n files', currentUploads); if(currentUploads === 1) { var img = OC.imagePath('core', 'loading.gif'); data.context.find('td.filename').attr('style','background-image:url('+img+')'); - uploadtext.text(t('files', '1 file uploading')); + uploadtext.text(translatedText); uploadtext.show(); } else { - uploadtext.text(currentUploads + ' ' + t('files', 'files uploading')); + uploadtext.text(translatedText); } } @@ -634,7 +635,7 @@ $(document).ready(function(){ } else { // add as stand-alone row to filelist - var size=t('files','Pending'); + var size=t('files', 'Pending'); if (data.files[0].size>=0){ size=data.files[0].size; } @@ -652,8 +653,9 @@ $(document).ready(function(){ // update file data data.context.attr('data-mime',file.mime).attr('data-id',file.id); - getMimeIcon(file.mime, function(path){ - data.context.find('td.filename').attr('style','background-image:url('+path+')'); + var path = getPathForPreview(file.name); + lazyLoadPreview(path, file.mime, function(previewpath){ + data.context.find('td.filename').attr('style','background-image:url('+previewpath+')'); }); } } diff --git a/apps/files/templates/fileexists.html b/apps/files/templates/fileexists.html new file mode 100644 index 00000000000..a5b2fb76908 --- /dev/null +++ b/apps/files/templates/fileexists.html @@ -0,0 +1,26 @@ +
+ {why}
+ {what}
+
+ + + +
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+
+
diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js index b949fc74d14..5ed24417264 100644 --- a/core/js/oc-dialogs.js +++ b/core/js/oc-dialogs.js @@ -220,28 +220,24 @@ var OCdialogs = { */ fileexists:function(data, original, replacement, controller) { var self = this; - var selection = controller.getSelection(data.originalFiles); - if (selection.defaultAction) { - controller[selection.defaultAction](data); - } else { - var dialog_name = 'oc-dialog-fileexists-content'; - var dialog_id = '#' + dialog_name; - if (this._fileexistsshown) { - // add row - var conflict = $(dialog_id+ ' .conflict').last().clone(); - conflict.find('.name').text(original.name); + var addConflict = function(conflicts, original, replacement) { + + var conflict = conflicts.find('.conflict.template').clone(); + + conflict.find('.filename').text(original.name); conflict.find('.original .size').text(humanFileSize(original.size)); conflict.find('.original .mtime').text(formatDate(original.mtime*1000)); conflict.find('.replacement .size').text(humanFileSize(replacement.size)); conflict.find('.replacement .mtime').text(formatDate(replacement.lastModifiedDate)); - getMimeIcon(original.type,function(path){ - conflict.find('.original .icon').css('background-image','url('+path+')'); + var path = getPathForPreview(original.name); + lazyLoadPreview(path, original.type, function(previewpath){ + conflict.find('.original .icon').css('background-image','url('+previewpath+')'); }); getMimeIcon(replacement.type,function(path){ conflict.find('.replacement .icon').css('background-image','url('+path+')'); }); - $(dialog_id+' .conflict').last().after(conflict); - $(dialog_id).parent().children('.oc-dialog-title').text(t('files','{count} file conflicts',{count:$(dialog_id+ ' .conflict').length})); + conflict.removeClass('template'); + conflicts.append(conflict); //set more recent mtime bold if (replacement.lastModifiedDate.getTime() > original.mtime*1000) { @@ -249,16 +245,16 @@ var OCdialogs = { } else if (replacement.lastModifiedDate.getTime() < original.mtime*1000) { conflict.find('.original .mtime').css('font-weight', 'bold'); } else { - //TODO add to same mtime colletion? + //TODO add to same mtime collection? } // set bigger size bold if (replacement.size > original.size) { - conflict.find('.replacement .size').css('font-weight','bold'); + conflict.find('.replacement .size').css('font-weight', 'bold'); } else if (replacement.size < original.size) { - conflict.find('.original .size').css('font-weight','bold'); + conflict.find('.original .size').css('font-weight', 'bold'); } else { - //TODO add to same size colletion? + //TODO add to same size collection? } //add checkbox toggling actions @@ -269,50 +265,42 @@ var OCdialogs = { //TODO show skip action for files with same size and mtime + }; + var selection = controller.getSelection(data.originalFiles); + if (selection.defaultAction) { + controller[selection.defaultAction](data); + } else { + var dialog_name = 'oc-dialog-fileexists-content'; + var dialog_id = '#' + dialog_name; + if (this._fileexistsshown) { + // add conflict + + var conflicts = $(dialog_id+ ' .conflicts'); + addConflict(conflicts, original, replacement); + + var title = t('files','{count} file conflicts',{count:$(dialog_id+ ' .conflict:not(.template)').length}); + $(dialog_id).parent().children('.oc-dialog-title').text(title); + + //recalculate dimensions $(window).trigger('resize'); + } else { //create dialog this._fileexistsshown = true; $.when(this._getFileExistsTemplate()).then(function($tmpl) { var title = t('files','One file conflict'); - var original_size = humanFileSize(original.size); - var original_mtime = formatDate(original.mtime*1000); - var replacement_size= humanFileSize(replacement.size); - var replacement_mtime = formatDate(replacement.lastModifiedDate); var $dlg = $tmpl.octemplate({ dialog_name: dialog_name, title: title, type: 'fileexists', why: t('files','Which files do you want to keep?'), - what: t('files','If you select both versions, the copied file will have a number added to its name.'), - filename: original.name, - - original_size: original_size, - original_mtime: original_mtime, - - replacement_size: replacement_size, - replacement_mtime: replacement_mtime + what: t('files','If you select both versions, the copied file will have a number added to its name.') }); $('body').append($dlg); - getMimeIcon(original.type,function(path){ - $(dialog_id + ' .original .icon').css('background-image','url('+path+')'); - }); - getMimeIcon(replacement.type,function(path){ - $(dialog_id + ' .replacement .icon').css('background-image','url('+path+')'); - }); - $(dialog_id + ' #newname').val(original.name); - - $(dialog_id + ' #newname').on('keyup', function(e){ - if ($(dialog_id + ' #newname').val() === original.name) { - $(dialog_id + ' + div .rename').removeClass('primary').hide(); - $(dialog_id + ' + div .replace').addClass('primary').show(); - } else { - $(dialog_id + ' + div .rename').addClass('primary').show(); - $(dialog_id + ' + div .replace').removeClass('primary').hide(); - } - }); + var conflicts = $($dlg).find('.conflicts'); + addConflict(conflicts, original, replacement); buttonlist = [{ text: t('core', 'Cancel'), @@ -346,57 +334,27 @@ var OCdialogs = { closeButton: null }); - $(dialog_id + ' + div .rename').hide(); - $(dialog_id + ' #newname').hide(); - - $(dialog_id + ' #newnamecb').on('change', function(){ - if ($(dialog_id + ' #newnamecb').prop('checked')) { - $(dialog_id + ' #newname').fadeIn(); - } else { - $(dialog_id + ' #newname').fadeOut(); - $(dialog_id + ' #newname').val(original.name); - } - }); $(dialog_id).css('height','auto'); - var conflict = $(dialog_id + ' .conflict').last(); - //set more recent mtime bold - if (replacement.lastModifiedDate.getTime() > original.mtime*1000) { - conflict.find('.replacement .mtime').css('font-weight','bold'); - } else if (replacement.lastModifiedDate.getTime() < original.mtime*1000) { - conflict.find('.original .mtime').css('font-weight','bold'); - } else { - //TODO add to same mtime colletion? - } - - // set bigger size bold - if (replacement.size > original.size) { - conflict.find('.replacement .size').css('font-weight','bold'); - } else if (replacement.size < original.size) { - conflict.find('.original .size').css('font-weight','bold'); - } else { - //TODO add to same size colletion? - } - //add checkbox toggling actions - //add checkbox toggling actions - $(dialog_id).find('.allnewfiles').on('click', function(){ - var checkboxes = $(dialog_id).find('.replacement input[type="checkbox"]'); + $(dialog_id).find('.allnewfiles').on('click', function() { + var checkboxes = $(dialog_id).find('.conflict:not(.template) .replacement input[type="checkbox"]'); checkboxes.prop('checked', $(this).prop('checked')); }); - $(dialog_id).find('.allexistingfiles').on('click', function(){ - var checkboxes = $(dialog_id).find('.original input[type="checkbox"]'); + $(dialog_id).find('.allexistingfiles').on('click', function() { + var checkboxes = $(dialog_id).find('.conflict:not(.template) .original input[type="checkbox"]'); checkboxes.prop('checked', $(this).prop('checked')); }); - conflict.find('.replacement,.original').on('click', function(){ + + $(dialog_id).find('.conflicts').on('click', '.replacement,.original', function() { var checkbox = $(this).find('input[type="checkbox"]'); checkbox.prop('checked', !checkbox.prop('checked')); }); //update counters - $(dialog_id).on('click', '.replacement,.allnewfiles', function(){ - var count = $(dialog_id).find('.replacement input[type="checkbox"]:checked').length; - if (count === $(dialog_id+ ' .conflict').length) { + $(dialog_id).on('click', '.replacement,.allnewfiles', function() { + var count = $(dialog_id).find('.conflict:not(.template) .replacement input[type="checkbox"]:checked').length; + if (count === $(dialog_id+ ' .conflict:not(.template)').length) { $(dialog_id).find('.allnewfiles').prop('checked', true); $(dialog_id).find('.allnewfiles + .count').text(t('files','(all selected)')); } else if (count > 0) { @@ -408,8 +366,8 @@ var OCdialogs = { } }); $(dialog_id).on('click', '.original,.allexistingfiles', function(){ - var count = $(dialog_id).find('.original input[type="checkbox"]:checked').length; - if (count === $(dialog_id+ ' .conflict').length) { + var count = $(dialog_id).find('.conflict:not(.template) .original input[type="checkbox"]:checked').length; + if (count === $(dialog_id+ ' .conflict:not(.template)').length) { $(dialog_id).find('.allexistingfiles').prop('checked', true); $(dialog_id).find('.allexistingfiles + .count').text(t('files','(all selected)')); } else if (count > 0) { -- cgit v1.2.3 From ce035016460d8285d5511e67b389d494eb78c1ce Mon Sep 17 00:00:00 2001 From: Jörn Friedrich Dreyer Date: Fri, 6 Sep 2013 23:44:40 +0200 Subject: fine ie8 compatability --- apps/files/css/files.css | 4 ++++ apps/files/js/file-upload.js | 6 +++++- core/js/oc-dialogs.js | 16 ++++++++++------ 3 files changed, 19 insertions(+), 7 deletions(-) (limited to 'apps/files/css/files.css') diff --git a/apps/files/css/files.css b/apps/files/css/files.css index 65aa29052e6..ea9c99bb269 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -380,6 +380,10 @@ table.dragshadow td.size { float: left; width: 235px; } +html.lte9 .oc-dialog .fileexists .original { + float: left; + width: 225px; +} .oc-dialog .fileexists .conflicts { overflow-y:scroll; max-height: 225px; diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index 47d1188b511..ead397c569e 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -197,7 +197,11 @@ OC.Upload = { }, onAutorename:function(data){ this.logStatus('autorename', null, data); - data.data.append('resolution', 'autorename'); + if (data.data) { + data.data.append('resolution', 'autorename'); + } else { + data.formData.push({name:'resolution',value:'autorename'}); //hack for ie8 + } data.submit(); }, logStatus:function(caption, e, data) { diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js index bc460798350..82bf49fc3a7 100644 --- a/core/js/oc-dialogs.js +++ b/core/js/oc-dialogs.js @@ -229,8 +229,11 @@ var OCdialogs = { conflict.find('.filename').text(original.name); conflict.find('.original .size').text(humanFileSize(original.size)); conflict.find('.original .mtime').text(formatDate(original.mtime*1000)); - conflict.find('.replacement .size').text(humanFileSize(replacement.size)); - conflict.find('.replacement .mtime').text(formatDate(replacement.lastModifiedDate)); + // ie sucks + if (replacement.size && replacement.lastModifiedDate) { + conflict.find('.replacement .size').text(humanFileSize(replacement.size)); + conflict.find('.replacement .mtime').text(formatDate(replacement.lastModifiedDate)); + } var path = getPathForPreview(original.name); lazyLoadPreview(path, original.type, function(previewpath){ conflict.find('.original .icon').css('background-image','url('+previewpath+')'); @@ -242,18 +245,19 @@ var OCdialogs = { conflicts.append(conflict); //set more recent mtime bold - if (replacement.lastModifiedDate.getTime() > original.mtime*1000) { + // ie sucks + if (replacement.lastModifiedDate && replacement.lastModifiedDate.getTime() > original.mtime*1000) { conflict.find('.replacement .mtime').css('font-weight', 'bold'); - } else if (replacement.lastModifiedDate.getTime() < original.mtime*1000) { + } else if (replacement.lastModifiedDate && replacement.lastModifiedDate.getTime() < original.mtime*1000) { conflict.find('.original .mtime').css('font-weight', 'bold'); } else { //TODO add to same mtime collection? } // set bigger size bold - if (replacement.size > original.size) { + if (replacement.size && replacement.size > original.size) { conflict.find('.replacement .size').css('font-weight', 'bold'); - } else if (replacement.size < original.size) { + } else if (replacement.size && replacement.size < original.size) { conflict.find('.original .size').css('font-weight', 'bold'); } else { //TODO add to same size collection? -- cgit v1.2.3 From 2c9b3d32efa466b655a7f24c5022a42045ef482f Mon Sep 17 00:00:00 2001 From: Jörn Friedrich Dreyer Date: Tue, 10 Sep 2013 17:34:28 +0200 Subject: unify .original div to fix css in firefox, clear:left to fix filename wrapping in chrome, shrink width of columns and get rid of ie8 hack --- apps/files/css/files.css | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'apps/files/css/files.css') diff --git a/apps/files/css/files.css b/apps/files/css/files.css index e503674e0fc..06088b30fff 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -348,7 +348,7 @@ table.dragshadow td.size { margin-right: 3px; } .oc-dialog .fileexists th:first-child { - width: 235px; + width: 230px; } .oc-dialog .fileexists th label { font-weight: normal; @@ -367,6 +367,7 @@ table.dragshadow td.size { .oc-dialog .fileexists .conflict .filename { color:#777; word-break: break-all; + clear: left; } .oc-dialog .fileexists .icon { width: 64px; @@ -379,15 +380,11 @@ table.dragshadow td.size { .oc-dialog .fileexists .replacement { float: left; - width: 235px; + width: 230px; } .oc-dialog .fileexists .original { float: left; - width: 235px; -} -html.lte9 .oc-dialog .fileexists .original { - float: left; - width: 225px; + width: 230px; } .oc-dialog .fileexists .conflicts { overflow-y:scroll; -- cgit v1.2.3 From b40925ae1747ae44a52fb1f8dcf7645d022c6f13 Mon Sep 17 00:00:00 2001 From: Jörn Friedrich Dreyer Date: Wed, 31 Jul 2013 22:24:52 +0200 Subject: initial scrollto implementation: use places/folder icon, move link construction to JS, only show icon on hover, use 'searchresult' as css class name, add filter/unfilter methods, highlight searched files in current filelist only filter when correct FileList is present --- apps/files/css/files.css | 3 +++ apps/files/js/filelist.js | 41 ++++++++++++++++++++++++++++++++++----- apps/files/js/files.js | 5 +++++ core/js/js.js | 13 +++++++++++++ lib/search/provider/file.php | 3 ++- lib/search/result.php | 4 +++- search/css/results.css | 22 +++++++++++++++++++-- search/js/result.js | 38 ++++++++++++++++++++++++++++++------ search/templates/part.results.php | 3 ++- 9 files changed, 116 insertions(+), 16 deletions(-) (limited to 'apps/files/css/files.css') diff --git a/apps/files/css/files.css b/apps/files/css/files.css index 41d9808c56b..0acb3c5d829 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -76,6 +76,9 @@ #filestable tbody tr.selected { background-color: rgb(230,230,230); } +#filestable tbody tr.searchresult { + background-color: rgb(240,240,240); +} tbody a { color:#000; } span.extension, span.uploading, td.date { color:#999; } span.extension { text-transform:lowercase; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; filter:alpha(opacity=70); opacity:.7; -webkit-transition:opacity 300ms; -moz-transition:opacity 300ms; -o-transition:opacity 300ms; transition:opacity 300ms; } diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index b50d46c98d3..9a2d39c3652 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -643,6 +643,37 @@ var FileList={ if (FileList._maskTimeout){ window.clearTimeout(FileList._maskTimeout); } + }, + scrollTo:function(file) { + //scroll to and highlight preselected file + var scrolltorow = $('tr[data-file="'+file+'"]'); + if (scrolltorow.length > 0) { + scrolltorow.addClass('searchresult'); + $(window).scrollTop(scrolltorow.position().top); + //remove highlight when hovered over + scrolltorow.one('hover', function(){ + scrolltorow.removeClass('searchresult'); + }); + } + }, + filter:function(query){ + $('#fileList tr:not(.summary)').each(function(i,e){ + if ($(e).data('file').toLowerCase().indexOf(query.toLowerCase()) !== -1) { + $(e).addClass("searchresult"); + } else { + $(e).removeClass("searchresult"); + } + }); + //do not use scrollto to prevent removing searchresult css class + var first = $('#fileList tr.searchresult').first(); + if (first.length !== 0) { + $(window).scrollTop(first.position().top); + } + }, + unfilter:function(){ + $('#fileList tr.searchresult').each(function(i,e){ + $(e).removeClass("searchresult"); + }); } }; @@ -818,16 +849,16 @@ $(document).ready(function(){ FileList.replaceIsNewFile = null; } FileList.lastAction = null; - OC.Notification.hide(); + OC.Notification.hide(); }); $('#notification:first-child').on('click', '.replace', function() { - OC.Notification.hide(function() { - FileList.replace($('#notification > span').attr('data-oldName'), $('#notification > span').attr('data-newName'), $('#notification > span').attr('data-isNewFile')); - }); + OC.Notification.hide(function() { + FileList.replace($('#notification > span').attr('data-oldName'), $('#notification > span').attr('data-newName'), $('#notification > span').attr('data-isNewFile')); + }); }); $('#notification:first-child').on('click', '.suggest', function() { $('tr').filterAttr('data-file', $('#notification > span').attr('data-oldName')).show(); - OC.Notification.hide(); + OC.Notification.hide(); }); $('#notification:first-child').on('click', '.cancel', function() { if ($('#notification > span').attr('data-isNewFile')) { diff --git a/apps/files/js/files.js b/apps/files/js/files.js index c2418cfa751..a4fdf383339 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -384,6 +384,11 @@ $(document).ready(function() { } }); } + + //scroll to and highlight preselected file + if (getURLParameter('scrollto')) { + FileList.scrollTo(getURLParameter('scrollto')); + } }); function scanFiles(force, dir, users){ diff --git a/core/js/js.js b/core/js/js.js index c09f80369f9..c23cf9eebd9 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -723,11 +723,17 @@ $(document).ready(function(){ } }else if(event.keyCode===27){//esc OC.search.hide(); + if (FileList && typeof FileList.unfilter === 'function') { //TODO add hook system + FileList.unfilter(); + } }else{ var query=$('#searchbox').val(); if(OC.search.lastQuery!==query){ OC.search.lastQuery=query; OC.search.currentResult=-1; + if (FileList && typeof FileList.filter === 'function') { //TODO add hook system + FileList.filter(query); + } if(query.length>2){ OC.search(query); }else{ @@ -840,6 +846,13 @@ function formatDate(date){ return $.datepicker.formatDate(datepickerFormatDate, date)+' '+date.getHours()+':'+((date.getMinutes()<10)?'0':'')+date.getMinutes(); } +// taken from http://stackoverflow.com/questions/1403888/get-url-parameter-with-jquery +function getURLParameter(name) { + return decodeURI( + (RegExp(name + '=' + '(.+?)(&|$)').exec(location.search) || [, null])[1] + ); +} + /** * takes an absolute timestamp and return a string with a human-friendly relative date * @param int a Unix timestamp diff --git a/lib/search/provider/file.php b/lib/search/provider/file.php index 4d88c2a87f1..9bd50931517 100644 --- a/lib/search/provider/file.php +++ b/lib/search/provider/file.php @@ -10,6 +10,7 @@ class OC_Search_Provider_File extends OC_Search_Provider{ $mime = $fileData['mimetype']; $name = basename($path); + $container = dirname($path); $text = ''; $skip = false; if($mime=='httpd/unix-directory') { @@ -37,7 +38,7 @@ class OC_Search_Provider_File extends OC_Search_Provider{ } } if(!$skip) { - $results[] = new OC_Search_Result($name, $text, $link, $type); + $results[] = new OC_Search_Result($name, $text, $link, $type, $container); } } return $results; diff --git a/lib/search/result.php b/lib/search/result.php index 08beaea151c..42275c2df11 100644 --- a/lib/search/result.php +++ b/lib/search/result.php @@ -7,6 +7,7 @@ class OC_Search_Result{ public $text; public $link; public $type; + public $container; /** * create a new search result @@ -15,10 +16,11 @@ class OC_Search_Result{ * @param string $link link for the result * @param string $type the type of result as human readable string ('File', 'Music', etc) */ - public function __construct($name, $text, $link, $type) { + public function __construct($name, $text, $link, $type, $container) { $this->name=$name; $this->text=$text; $this->link=$link; $this->type=$type; + $this->container=$container; } } diff --git a/search/css/results.css b/search/css/results.css index 4ae7d67afb3..8a32b0b995d 100644 --- a/search/css/results.css +++ b/search/css/results.css @@ -14,7 +14,7 @@ position:fixed; right:0; text-overflow:ellipsis; - top:20px; + top:45px; width:380px; z-index:75; } @@ -43,10 +43,16 @@ } #searchresults td { - vertical-align:top; padding:0 .3em; + height: 32px; +} +#searchresults tr.template { + display: none; } +#searchresults td.result { + width:250px; +} #searchresults td.result div.text { padding-left:1em; white-space:nowrap; @@ -56,6 +62,18 @@ cursor:pointer; } +#searchresults td.container { + width:20px; +} + +#searchresults td.container img { + vertical-align: middle; + display:none; +} +#searchresults tr:hover td.container img { + display:inline; +} + #searchresults td.type { border-bottom:none; border-right:1px solid #aaa; diff --git a/search/js/result.js b/search/js/result.js index 78fa8efc8e9..78d9149f220 100644 --- a/search/js/result.js +++ b/search/js/result.js @@ -8,15 +8,23 @@ OC.search.catagorizeResults=function(results){ types[type].push(results[i]); } return types; -} +}; OC.search.hide=function(){ $('#searchresults').hide(); if($('#searchbox').val().length>2){ $('#searchbox').val(''); + if (FileList && typeof FileList.unfilter === 'function') { //TODO add hook system + FileList.unfilter(); + } }; -} + if ($('#searchbox').val().length === 0) { + if (FileList && typeof FileList.unfilter === 'function') { //TODO add hook system + FileList.unfilter(); + } + } +}; OC.search.showResults=function(results){ - if(results.length==0){ + if(results.length === 0){ return; } if(!OC.search.showResults.loaded){ @@ -30,6 +38,9 @@ OC.search.showResults=function(results){ }); $(document).click(function(event){ OC.search.hide(); + if (FileList && typeof FileList.unfilter === 'function') { //TODO add hook system + FileList.unfilter(); + } }); OC.search.lastResults=results; OC.search.showResults(results); @@ -46,12 +57,27 @@ OC.search.showResults=function(results){ var row=$('#searchresults tr.template').clone(); row.removeClass('template'); row.addClass('result'); - if (i == 0){ + if (i === 0){ row.children('td.type').text(name); } row.find('td.result a').attr('href',type[i].link); row.find('td.result div.name').text(type[i].name); row.find('td.result div.text').text(type[i].text); + if (type[i].container) { + var td = row.find('td.container'); + td.append(''); + td.find('img').attr('src',OC.imagePath('core','places/folder')); + var containerName = OC.basename(type[i].container); + if (containerName === '') { + containerName = '/'; + } + var containerLink = OC.linkTo('files','index.php') + +'?dir='+encodeURIComponent(type[i].container) + +'&scrollto='+encodeURIComponent(type[i].name); + row.find('td.container a') + .attr('href',containerLink) + .attr('title',t('core','Show in {folder}',{folder: containerName})); + } row.data('index',index); index++; if(OC.search.customResults[name]){//give plugins the ability to customize the entries in here @@ -62,7 +88,7 @@ OC.search.showResults=function(results){ } } } -} +}; OC.search.showResults.loaded=false; OC.search.renderCurrent=function(){ @@ -71,4 +97,4 @@ OC.search.renderCurrent=function(){ $('#searchresults tr.result').removeClass('current'); $(result).addClass('current'); } -} +}; diff --git a/search/templates/part.results.php b/search/templates/part.results.php index 9e39a1c2c8b..1469e3468d3 100644 --- a/search/templates/part.results.php +++ b/search/templates/part.results.php @@ -1,7 +1,7 @@
- + +
@@ -9,6 +9,7 @@
-- cgit v1.2.3 From 12ff268e607738b03125ec6b212708391496d7f5 Mon Sep 17 00:00:00 2001 From: Jörn Friedrich Dreyer Date: Wed, 18 Sep 2013 17:20:14 +0200 Subject: move upload dialog css to separate file --- apps/files/css/files.css | 85 ------------------------------ apps/files/css/upload.css | 119 ++++++++++++++++++++++++++++++++++++++++++ apps/files/index.php | 1 + apps/files_sharing/public.php | 1 + 4 files changed, 121 insertions(+), 85 deletions(-) create mode 100644 apps/files/css/upload.css (limited to 'apps/files/css/files.css') diff --git a/apps/files/css/files.css b/apps/files/css/files.css index ff593fc4d24..e15c2b540dc 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -357,88 +357,3 @@ table.dragshadow td.size { .mask.transparent{ opacity: 0; } - -.oc-dialog .fileexists table { - width: 100%; -} -.oc-dialog .fileexists th { - padding-left: 0; - padding-right: 0; -} -.oc-dialog .fileexists th input[type='checkbox'] { - margin-right: 3px; -} -.oc-dialog .fileexists th:first-child { - width: 230px; -} -.oc-dialog .fileexists th label { - font-weight: normal; - color:black; -} -.oc-dialog .fileexists th .count { - margin-left: 3px; -} -.oc-dialog .fileexists .conflict { - width: 100%; - height: 85px; -} -.oc-dialog .fileexists .conflict.template { - display: none; -} -.oc-dialog .fileexists .conflict .filename { - color:#777; - word-break: break-all; - clear: left; -} -.oc-dialog .fileexists .icon { - width: 64px; - height: 64px; - margin: 0px 5px 5px 5px; - background-repeat: no-repeat; - background-size: 64px 64px; - float: left; -} - -.oc-dialog .fileexists .replacement { - float: left; - width: 230px; -} -.oc-dialog .fileexists .original { - float: left; - width: 230px; -} -.oc-dialog .fileexists .conflicts { - overflow-y:scroll; - max-height: 225px; -} -.oc-dialog .fileexists .conflict input[type='checkbox'] { - float: left; -} - -.oc-dialog .fileexists .toggle { - background-image: url('%webroot%/core/img/actions/triangle-e.png'); - width: 16px; - height: 16px; -} -.oc-dialog .fileexists #allfileslabel { - float:right; -} -.oc-dialog .fileexists #allfiles { - vertical-align: bottom; - position: relative; - top: -3px; -} -.oc-dialog .fileexists #allfiles + span{ - vertical-align: bottom; -} - - - -.oc-dialog .oc-dialog-buttonrow { - width:100%; - text-align:right; -} - -.oc-dialog .oc-dialog-buttonrow .cancel { - float:left; -} diff --git a/apps/files/css/upload.css b/apps/files/css/upload.css new file mode 100644 index 00000000000..2d11e41ba88 --- /dev/null +++ b/apps/files/css/upload.css @@ -0,0 +1,119 @@ + +#upload { + height:27px; padding:0; margin-left:0.2em; overflow:hidden; + vertical-align: top; +} +#upload a { + position:relative; display:block; width:100%; height:27px; + cursor:pointer; z-index:10; + background-image:url('%webroot%/core/img/actions/upload.svg'); + background-repeat:no-repeat; + background-position:7px 6px; + opacity:0.65; +} +.file_upload_target { display:none; } +.file_upload_form { display:inline; float:left; margin:0; padding:0; cursor:pointer; overflow:visible; } +#file_upload_start { + float: left; + left:0; top:0; width:28px; height:27px; padding:0; + font-size:1em; + -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter:alpha(opacity=0); opacity:0; + z-index:20; position:relative; cursor:pointer; overflow:hidden; +} + +#uploadprogresswrapper { + display: inline-block; + vertical-align: top; + margin:0.3em; + height: 29px; +} +#uploadprogressbar { + position:relative; + float: left; + margin-left: 12px; + width: 130px; + height: 26px; + display:inline-block; +} +#uploadprogressbar + stop { + font-size: 13px; +} + +.oc-dialog .fileexists table { + width: 100%; +} +.oc-dialog .fileexists th { + padding-left: 0; + padding-right: 0; +} +.oc-dialog .fileexists th input[type='checkbox'] { + margin-right: 3px; +} +.oc-dialog .fileexists th:first-child { + width: 230px; +} +.oc-dialog .fileexists th label { + font-weight: normal; + color:black; +} +.oc-dialog .fileexists th .count { + margin-left: 3px; +} +.oc-dialog .fileexists .conflicts .template { + display: none; +} +.oc-dialog .fileexists .conflict { + width: 100%; + height: 85px; +} +.oc-dialog .fileexists .conflict .filename { + color:#777; + word-break: break-all; + clear: left; +} +.oc-dialog .fileexists .icon { + width: 64px; + height: 64px; + margin: 0px 5px 5px 5px; + background-repeat: no-repeat; + background-size: 64px 64px; + float: left; +} +.oc-dialog .fileexists .replacement { + float: left; + width: 230px; +} +.oc-dialog .fileexists .original { + float: left; + width: 230px; +} +.oc-dialog .fileexists .conflicts { + overflow-y:scroll; + max-height: 225px; +} +.oc-dialog .fileexists .conflict input[type='checkbox'] { + float: left; +} +.oc-dialog .fileexists .toggle { + background-image: url('%webroot%/core/img/actions/triangle-e.png'); + width: 16px; + height: 16px; +} +.oc-dialog .fileexists #allfileslabel { + float:right; +} +.oc-dialog .fileexists #allfiles { + vertical-align: bottom; + position: relative; + top: -3px; +} +.oc-dialog .fileexists #allfiles + span{ + vertical-align: bottom; +} +.oc-dialog .oc-dialog-buttonrow { + width:100%; + text-align:right; +} +.oc-dialog .oc-dialog-buttonrow .cancel { + float:left; +} diff --git a/apps/files/index.php b/apps/files/index.php index d46d8e32eef..9e54a706c01 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -26,6 +26,7 @@ OCP\User::checkLoggedIn(); // Load the files we need OCP\Util::addStyle('files', 'files'); +OCP\Util::addStyle('files', 'upload'); OCP\Util::addscript('files', 'file-upload'); OCP\Util::addscript('files', 'jquery.iframe-transport'); OCP\Util::addscript('files', 'jquery.fileupload'); diff --git a/apps/files_sharing/public.php b/apps/files_sharing/public.php index 6d3a07a9d0b..c997a7950c2 100644 --- a/apps/files_sharing/public.php +++ b/apps/files_sharing/public.php @@ -170,6 +170,7 @@ if (isset($path)) { $tmpl->assign('dir', $getPath); OCP\Util::addStyle('files', 'files'); + OCP\Util::addStyle('files', 'upload'); OCP\Util::addScript('files', 'files'); OCP\Util::addScript('files', 'filelist'); OCP\Util::addscript('files', 'keyboardshortcuts'); -- cgit v1.2.3