aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJohannes Zellner <johannes@cloudron.io>2018-05-18 22:29:34 +0200
committerJohannes Zellner <johannes@cloudron.io>2018-05-18 22:29:34 +0200
commit8370d9f06066dd808214b838551a29d24731bbd6 (patch)
treef93c7d910967b4b297e08f0b46b91c2120af9152
parent7c36adbbc51c85c9073c72e75d6503b52c02561d (diff)
downloadSurfer-8370d9f06066dd808214b838551a29d24731bbd6.tar.gz
Surfer-8370d9f06066dd808214b838551a29d24731bbd6.tar.zst
Surfer-8370d9f06066dd808214b838551a29d24731bbd6.zip
Support dropping a folder for upload
-rw-r--r--frontend/index.html5
-rw-r--r--frontend/js/app.js52
2 files changed, 51 insertions, 6 deletions
diff --git a/frontend/index.html b/frontend/index.html
index d2b526d..bb53ca4 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -101,7 +101,10 @@
101 101
102 </el-main> 102 </el-main>
103 <el-footer v-show="uploadStatus.busy"> 103 <el-footer v-show="uploadStatus.busy">
104 <el-row> 104 <el-row v-if="uploadStatus.uploadListCount">
105 <center><i class="el-icon-loading"></i> Fetching file information for upload <el-badge class="mark" :value="uploadStatus.uploadListCount"/></center>
106 </el-row>
107 <el-row v-else>
105 <el-col :span="4"> 108 <el-col :span="4">
106 Uploading files ({{ uploadStatus.done }} / {{ uploadStatus.count }}) 109 Uploading files ({{ uploadStatus.done }} / {{ uploadStatus.count }})
107 </el-col> 110 </el-col>
diff --git a/frontend/js/app.js b/frontend/js/app.js
index 9d7baca..df5043a 100644
--- a/frontend/js/app.js
+++ b/frontend/js/app.js
@@ -136,9 +136,6 @@ function uploadFiles(files) {
136 app.uploadStatus.percentDone = 0; 136 app.uploadStatus.percentDone = 0;
137 137
138 asyncForEach(files, function (file, callback) { 138 asyncForEach(files, function (file, callback) {
139 // do not handle directories (file.type is empty in such a case)
140 if (file.type === '') return callback();
141
142 var path = encode(sanitize(app.path + '/' + (file.webkitRelativePath || file.name))); 139 var path = encode(sanitize(app.path + '/' + (file.webkitRelativePath || file.name)));
143 140
144 var formData = new FormData(); 141 var formData = new FormData();
@@ -175,7 +172,51 @@ function dragOver(event) {
175function drop(event) { 172function drop(event) {
176 event.stopPropagation(); 173 event.stopPropagation();
177 event.preventDefault(); 174 event.preventDefault();
178 uploadFiles(event.dataTransfer.files || []); 175
176 if (!event.dataTransfer.items[0]) return;
177
178 // figure if a folder was dropped on a modern browser, in this case the first would have to be a directory
179 var folderItem;
180 try {
181 folderItem = event.dataTransfer.items[0].webkitGetAsEntry();
182 if (folderItem.isFile) return uploadFiles(event.dataTransfer.files);
183 } catch (e) {
184 return uploadFiles(event.dataTransfer.files);
185 }
186
187 // if we got here we have a folder drop and a modern browser
188 // now traverse the folder tree and create a file list
189 app.uploadStatus.busy = true;
190 app.uploadStatus.uploadListCount = 0;
191
192 var fileList = [];
193 function traverseFileTree(item, path, callback) {
194 if (item.isFile) {
195 // Get file
196 item.file(function (file) {
197 fileList.push(file);
198 ++app.uploadStatus.uploadListCount;
199 callback();
200 });
201 } else if (item.isDirectory) {
202 // Get folder contents
203 var dirReader = item.createReader();
204 dirReader.readEntries(function (entries) {
205 asyncForEach(entries, function (entry, callback) {
206 traverseFileTree(entry, path + item.name + '/', callback);
207 }, callback);
208 });
209 }
210 }
211
212 traverseFileTree(folderItem, '', function (error) {
213 app.uploadStatus.busy = false;
214 app.uploadStatus.uploadListCount = 0;
215
216 if (error) return console.error(error);
217
218 uploadFiles(fileList);
219 });
179} 220}
180 221
181var app = new Vue({ 222var app = new Vue({
@@ -187,7 +228,8 @@ var app = new Vue({
187 busy: false, 228 busy: false,
188 count: 0, 229 count: 0,
189 done: 0, 230 done: 0,
190 percentDone: 50 231 percentDone: 50,
232 uploadListCount: 0
191 }, 233 },
192 path: '/', 234 path: '/',
193 pathParts: [], 235 pathParts: [],