From 497ddeee6dcdb7a6a7ed6601e3916f84592a5b3c Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 14 Jun 2017 12:47:37 +0200 Subject: [PATCH 1/5] Upload files with drag&drop in the drive --- www/common/common-file.js | 17 ++++++---- www/common/cryptpad-common.js | 19 +++++------ www/common/toolbar2.js | 4 +++ www/drive/main.js | 59 +++++++++++++++++++++++++++++++++-- www/file/file.css | 39 ----------------------- www/file/file.less | 35 --------------------- www/slide/main.js | 5 --- 7 files changed, 81 insertions(+), 97 deletions(-) diff --git a/www/common/common-file.js b/www/common/common-file.js index b6c59e581..bb345565d 100644 --- a/www/common/common-file.js +++ b/www/common/common-file.js @@ -238,7 +238,13 @@ define([ reader.readAsArrayBuffer(file); }; - var createAreaHandlers = File.createDropArea = function ($area, $hoverArea, todo) { + var onFileDrop = File.onFileDrop = function (file, e) { + Array.prototype.slice.call(file).forEach(function (d) { + handleFile(d, e); + }); + }; + + var createAreaHandlers = File.createDropArea = function ($area, $hoverArea) { var counter = 0; if (!$hoverArea) { $hoverArea = $area; } $hoverArea @@ -267,15 +273,14 @@ define([ var dropped = e.originalEvent.dataTransfer.files; counter = 0; $hoverArea.removeClass('hovering'); - - Array.prototype.slice.call(dropped).forEach(function (d) { - todo(d, e); - }); + onFileDrop(dropped, e); }); }; var createUploader = function ($area, $hover, $body) { - createAreaHandlers($area, null, handleFile); + if (!config.noHandlers) { + createAreaHandlers($area, null); + } createTableContainer($body); }; diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index 7d2885d15..b1406a4f2 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -586,25 +586,26 @@ define([ return pad; }); + if (updateWeaker.length > 0) { + updateWeaker.forEach(function (obj) { + // If we have a stronger url, and if all the occurences of the weaker were + // in the trash, add remove them from the trash and add the stronger in root + getStore().restoreHref(obj.n); + }); + } if (!contains && href) { var data = makePad(href, name); getStore().pushData(data, function (e, id) { if (e) { if (e === 'E_OVER_LIMIT') { common.alert(Messages.pinLimitNotPinned, null, true); - return; } - else { return void cb(e); } + return void cb(e); } getStore().addPad(id, common.initialPath); + cb(err, recent); }); - } - if (updateWeaker.length > 0) { - updateWeaker.forEach(function (obj) { - // If we have a stronger url, and if all the occurences of the weaker were - // in the trash, add remove them from the trash and add the stronger in root - getStore().restoreHref(obj.n); - }); + return; } cb(err, recent); }); diff --git a/www/common/toolbar2.js b/www/common/toolbar2.js index 39bfc49e8..b96d072ac 100644 --- a/www/common/toolbar2.js +++ b/www/common/toolbar2.js @@ -96,6 +96,10 @@ define([ } else { styleToolbar($container); } + $container.on('drop dragover', function (e) { + e.preventDefault(); + e.stopPropagation(); + }); return $toolbar; }; diff --git a/www/drive/main.js b/www/drive/main.js index bcba56df6..1837f6700 100644 --- a/www/drive/main.js +++ b/www/drive/main.js @@ -205,6 +205,17 @@ define([ var $trashTreeContextMenu = $iframe.find("#trashTreeContextMenu"); var $trashContextMenu = $iframe.find("#trashContextMenu"); + $tree.on('drop dragover', function (e) { + e.preventDefault(); + e.stopPropagation(); + }); + $driveToolbar.on('drop dragover', function (e) { + e.preventDefault(); + e.stopPropagation(); + }); + + + // TOOLBAR /* add a "change username" button */ @@ -1012,13 +1023,30 @@ define([ ev.dataTransfer.setData("text", stringify(data)); }; + var onFileDrop = APP.onFileDrop = function (file, e) { + APP.FM.onFileDrop(file, e); + }; + var findDropPath = function (target) { + var $target = $(target); + var $el = findDataHolder($target); + var newPath = $el.data('path'); + if ((!newPath || filesOp.isFile(filesOp.find(newPath))) + && $target.parents('#content')) { + newPath = currentPath; + } + return newPath; + }; var onDrop = function (ev) { ev.preventDefault(); $iframe.find('.droppable').removeClass('droppable'); var data = ev.dataTransfer.getData("text"); + + // Don't the the normal drop handler for file upload + var fileDrop = ev.dataTransfer.files; + if (fileDrop) { return void onFileDrop(fileDrop, ev); } + var oldPaths = JSON.parse(data).path; if (!oldPaths) { return; } - // Dropped elements can be moved from the same file manager or imported from another one. // A moved element should be removed from its previous location var movedPaths = []; @@ -1032,8 +1060,7 @@ define([ } }); - var $el = findDataHolder($(ev.target)); - var newPath = $el.data('path'); + var newPath = findDropPath(ev.target); if (!newPath) { return; } if (movedPaths && movedPaths.length) { moveElements(movedPaths, newPath, null, refresh); @@ -1069,6 +1096,8 @@ define([ e.preventDefault(); }); $element.on('drop', function (e) { + e.preventDefault(); + e.stopPropagation(); onDrop(e.originalEvent); }); $element.on('dragenter', function (e) { @@ -1087,6 +1116,7 @@ define([ } }); }; + addDragAndDropHandlers($content, null, true, true); // In list mode, display metadata from the filesData object // _WORKGROUP_ : Do not display title, atime and ctime columns since we don't have files data @@ -2559,6 +2589,29 @@ define([ if (typeof(cb) === "function") { cb(); } }; + var fmConfig = { + noHandlers: true, + onUploaded: function (ev, data) { + try { + // Get the folder path + var newPath = findDropPath(ev.target); + if (!newPath) { return void refresh(); } + var href = data.url; + // Get the current file location in ROOT + var id = filesOp.getIdFromHref(href); + var paths = filesOp.findFile(id); + if (paths.length !== 1) { return; } + // Try to move and refresh + moveElements([paths[0]], newPath, true); + refresh(); + } catch (e) { + console.error(e); + refresh(); + } + } + }; + APP.FM = Cryptpad.createFileManager(fmConfig); + createReadme(proxy, function () { refresh(); APP.userList.onChange(); diff --git a/www/file/file.css b/www/file/file.css index eade31db1..27cd125e1 100644 --- a/www/file/file.css +++ b/www/file/file.css @@ -77,42 +77,3 @@ body { z-index: 10000; display: block; } -#uploadStatus { - display: none; - width: 80vw; - margin-top: 50px; - margin-left: 10vw; - border: 1px solid black; - border-collapse: collapse; -} -#uploadStatus tr:nth-child(1) { - background-color: #ccc; - border: 1px solid #999; -} -#uploadStatus tr:nth-child(1) td { - text-align: center; -} -#uploadStatus td { - border-left: 1px solid #BBB; - border-right: 1px solid #BBB; - padding: 0 10px; -} -#uploadStatus .upProgress { - width: 200px; - position: relative; - text-align: center; -} -#uploadStatus .progressContainer { - position: absolute; - width: 0px; - left: 5px; - top: 1px; - bottom: 1px; - background-color: rgba(0, 0, 255, 0.3); -} -#uploadStatus .upCancel { - text-align: center; -} -#uploadStatus .fa.cancel { - color: #ff0073; -} diff --git a/www/file/file.less b/www/file/file.less index 2347889f7..fe7a37ebb 100644 --- a/www/file/file.less +++ b/www/file/file.less @@ -87,38 +87,3 @@ html, body { display: block; } -#uploadStatus { - display: none; - width: 80vw; - margin-top: 50px; - margin-left: 10vw; - border: 1px solid black; - border-collapse: collapse; - tr:nth-child(1) { - background-color: #ccc; - border: 1px solid #999; - td { text-align: center; } - } - td { - border-left: 1px solid #BBB; - border-right: 1px solid #BBB; - padding: 0 10px; - } - .upProgress { - width: 200px; - position: relative; - text-align: center; - } - .progressContainer { - position: absolute; - width: 0px; - left: 5px; - top: 1px; bottom: 1px; - background-color: rgba(0,0,255,0.3); - } - .upCancel { text-align: center; } - .fa.cancel { - color: rgb(255, 0, 115); - } -} - diff --git a/www/slide/main.js b/www/slide/main.js index f1870eead..8a4522f30 100644 --- a/www/slide/main.js +++ b/www/slide/main.js @@ -511,11 +511,6 @@ define([ if (readOnly) { return; } UserList.getLastName(toolbar.$userNameButton, isNew); - - /*editor.on('dragover', function (e) { - //console.log(editor.coordsChar()); - console.log(e); - });*/ var fmConfig = { dropArea: $iframe.find('.CodeMirror'), body: $iframe.find('body'), From e51f678bb914370574207a55c6c8a92bb1246bbf Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 14 Jun 2017 12:50:44 +0200 Subject: [PATCH 2/5] Don't display the popup whne moving a file to the trash --- www/drive/main.js | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/www/drive/main.js b/www/drive/main.js index 1837f6700..0a460a703 100644 --- a/www/drive/main.js +++ b/www/drive/main.js @@ -965,23 +965,7 @@ define([ if (filesOp.isPathIn(newPath, [TRASH]) && paths.length && paths[0][0] === TRASH) { return; } - // "force" is currently unused but may be configurable by user - if (newPath[0] !== TRASH || force) { - andThen(); - return; - } - var msg = Messages._getKey('fm_removeSeveralDialog', [paths.length]); - if (paths.length === 1) { - var path = paths[0].slice(); - var el = filesOp.find(path); - var name = filesOp.isFile(el) ? getElementName(path) : path.pop(); - msg = Messages._getKey('fm_removeDialog', [name]); - } - Cryptpad.confirm(msg, function (res) { - $(ifrw).focus(); - if (!res) { return; } - andThen(); - }); + andThen(); }; // Drag & drop: // The data transferred is a stringified JSON containing the path of the dragged element From 5b523be1715fc7fd8892ecbf9a932a20607a2989 Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 14 Jun 2017 12:55:41 +0200 Subject: [PATCH 3/5] Fix drag&drop for pads in the drive --- www/drive/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/drive/main.js b/www/drive/main.js index 0a460a703..3d9c04ad3 100644 --- a/www/drive/main.js +++ b/www/drive/main.js @@ -1027,7 +1027,7 @@ define([ // Don't the the normal drop handler for file upload var fileDrop = ev.dataTransfer.files; - if (fileDrop) { return void onFileDrop(fileDrop, ev); } + if (fileDrop.length) { return void onFileDrop(fileDrop, ev); } var oldPaths = JSON.parse(data).path; if (!oldPaths) { return; } From 7e0a2abc2c459a6f173bf04eb915381477f86691 Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 14 Jun 2017 13:03:10 +0200 Subject: [PATCH 4/5] Fix the file name when restoring an element from the trash --- www/drive/main.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/www/drive/main.js b/www/drive/main.js index 3d9c04ad3..b93086262 100644 --- a/www/drive/main.js +++ b/www/drive/main.js @@ -2389,8 +2389,7 @@ define([ var name = paths[0].path[paths[0].path.length - 1]; if ($(this).hasClass("remove")) { if (paths.length === 1) { - if (path.length === 4) { name = path[1]; } - Cryptpad.confirm(Messages._getKey("fm_removePermanentlyDialog", [name]), function(res) { + Cryptpad.confirm(Messages.fm_removePermanentlyDialog, function(res) { if (!res) { return; } filesOp.delete([path], refresh); }); @@ -2406,7 +2405,14 @@ define([ } else if ($(this).hasClass("restore")) { if (paths.length !== 1) { return; } - if (path.length === 4) { name = path[1]; } + if (path.length === 4) { + var el = filesOp.find(path); + if (filesOp.isFile(el)) { + name = filesOp.getTitle(el); + } else { + name = path[1]; + } + } Cryptpad.confirm(Messages._getKey("fm_restoreDialog", [name]), function(res) { if (!res) { return; } filesOp.restore(path, refresh); From a98353af6c299c352c5112f270e6e52909b0ff6e Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 14 Jun 2017 15:55:03 +0200 Subject: [PATCH 5/5] Add a button to upload a file in the drive --- customize.dist/translations/messages.fr.js | 2 ++ customize.dist/translations/messages.js | 2 ++ www/common/common-file.js | 1 - www/drive/main.js | 27 +++++++++++++++++++++- 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/customize.dist/translations/messages.fr.js b/customize.dist/translations/messages.fr.js index 41423fe57..4c5ba9fc9 100644 --- a/customize.dist/translations/messages.fr.js +++ b/customize.dist/translations/messages.fr.js @@ -107,6 +107,8 @@ define(function () { out.newButton = 'Nouveau'; out.newButtonTitle = 'Créer un nouveau pad'; + out.uploadButton = 'Upload'; + out.uploadButtonTitle = 'Uploader un nouveau fichier dans le dossier actuel'; out.saveTemplateButton = "Sauver en tant que modèle"; out.saveTemplatePrompt = "Choisir un titre pour ce modèle"; diff --git a/customize.dist/translations/messages.js b/customize.dist/translations/messages.js index c549a6009..ceade6204 100644 --- a/customize.dist/translations/messages.js +++ b/customize.dist/translations/messages.js @@ -109,6 +109,8 @@ define(function () { out.newButton = 'New'; out.newButtonTitle = 'Create a new pad'; + out.uploadButton = 'Upload'; + out.uploadButtonTitle = 'Upload a new file to the current folder'; out.saveTemplateButton = "Save as template"; out.saveTemplatePrompt = "Choose a title for the template"; diff --git a/www/common/common-file.js b/www/common/common-file.js index bb345565d..43d7cff2a 100644 --- a/www/common/common-file.js +++ b/www/common/common-file.js @@ -223,7 +223,6 @@ define([ }; var handleFile = File.handleFile = function (file, e) { - console.log(file); var reader = new FileReader(); reader.onloadend = function () { queue.push({ diff --git a/www/drive/main.js b/www/drive/main.js index b93086262..0d1f6c0e3 100644 --- a/www/drive/main.js +++ b/www/drive/main.js @@ -1441,6 +1441,30 @@ define([ return $block; }; + var createUploadButton = function () { + var inTrash = filesOp.isPathIn(currentPath, [TRASH]); + var $icon = $('', { + 'class': 'fa fa-upload' + }); + var $input = $('', { + 'type': 'file', + 'style': 'display: none;' + }).on('change', function (e) { + var file = e.target.files[0]; + var ev = { + target: $content[0] + }; + APP.FM.handleFile(file, ev); + }); + var $button = $('