X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=frontend%2Fjs%2Fapp.js;h=c1a63a9df6398760e3b1799569bcc033d54cbceb;hb=3760489ffc7596a13909907c60d1410d8161b89e;hp=4cb57e3b1b35163d1c72c04cd5e07e78d08d75ff;hpb=35355283872739fb9bd150cf42a40a1a23b1674d;p=perso%2FImmae%2FProjets%2FNodejs%2FSurfer.git diff --git a/frontend/js/app.js b/frontend/js/app.js index 4cb57e3..c1a63a9 100644 --- a/frontend/js/app.js +++ b/frontend/js/app.js @@ -132,23 +132,36 @@ function uploadFiles(files) { app.uploadStatus.busy = true; app.uploadStatus.count = files.length; + app.uploadStatus.size = 0; app.uploadStatus.done = 0; app.uploadStatus.percentDone = 0; + for (var i = 0; i < files.length; ++i) { + app.uploadStatus.size += files[i].size; + } + asyncForEach(files, function (file, callback) { var path = encode(sanitize(app.path + '/' + (file.webkitRelativePath || file.name))); var formData = new FormData(); formData.append('file', file); - superagent.post('/api/files' + path).query({ access_token: localStorage.accessToken }).send(formData).end(function (error, result) { + var finishedUploadSize = app.uploadStatus.done; + + superagent.post('/api/files' + path) + .query({ access_token: localStorage.accessToken }) + .send(formData) + .on('progress', function (event) { + // only handle upload events + if (!(event.target instanceof XMLHttpRequestUpload)) return; + + app.uploadStatus.done = finishedUploadSize + event.loaded; + app.uploadStatus.percentDone = Math.round(app.uploadStatus.done / app.uploadStatus.size * 100); + }).end(function (error, result) { if (result && result.statusCode === 401) return logout(); if (result && result.statusCode !== 201) return callback('Error uploading file: ', result.statusCode); if (error) return callback(error); - app.uploadStatus.done += 1; - app.uploadStatus.percentDone = Math.round(app.uploadStatus.done / app.uploadStatus.count * 100); - callback(); }); }, function (error) { @@ -156,6 +169,7 @@ function uploadFiles(files) { app.uploadStatus.busy = false; app.uploadStatus.count = 0; + app.uploadStatus.size = 0; app.uploadStatus.done = 0; app.uploadStatus.percentDone = 100; @@ -164,12 +178,59 @@ function uploadFiles(files) { } function dragOver(event) { + event.stopPropagation(); event.preventDefault(); + event.dataTransfer.dropEffect = 'copy'; } function drop(event) { + event.stopPropagation(); event.preventDefault(); - uploadFiles(event.dataTransfer.files || []); + + if (!event.dataTransfer.items[0]) return; + + // figure if a folder was dropped on a modern browser, in this case the first would have to be a directory + var folderItem; + try { + folderItem = event.dataTransfer.items[0].webkitGetAsEntry(); + if (folderItem.isFile) return uploadFiles(event.dataTransfer.files); + } catch (e) { + return uploadFiles(event.dataTransfer.files); + } + + // if we got here we have a folder drop and a modern browser + // now traverse the folder tree and create a file list + app.uploadStatus.busy = true; + app.uploadStatus.uploadListCount = 0; + + var fileList = []; + function traverseFileTree(item, path, callback) { + if (item.isFile) { + // Get file + item.file(function (file) { + fileList.push(file); + ++app.uploadStatus.uploadListCount; + callback(); + }); + } else if (item.isDirectory) { + // Get folder contents + var dirReader = item.createReader(); + dirReader.readEntries(function (entries) { + asyncForEach(entries, function (entry, callback) { + traverseFileTree(entry, path + item.name + '/', callback); + }, callback); + }); + } + } + + traverseFileTree(folderItem, '', function (error) { + app.uploadStatus.busy = false; + app.uploadStatus.uploadListCount = 0; + + if (error) return console.error(error); + + uploadFiles(fileList); + }); } var app = new Vue({ @@ -181,7 +242,8 @@ var app = new Vue({ busy: false, count: 0, done: 0, - percentDone: 50 + percentDone: 50, + uploadListCount: 0 }, path: '/', pathParts: [], @@ -250,10 +312,8 @@ var app = new Vue({ var that = this; $(this.$refs.upload).on('change', function () { - // detach event handler $(that.$refs.upload).off('change'); - uploadFiles(that.$refs.upload.files || []); }); @@ -261,6 +321,19 @@ var app = new Vue({ this.$refs.upload.value = ''; this.$refs.upload.click(); }, + onUploadFolder: function () { + var that = this; + + $(this.$refs.uploadFolder).on('change', function () { + // detach event handler + $(that.$refs.uploadFolder).off('change'); + uploadFiles(that.$refs.uploadFolder.files || []); + }); + + // reset the form first to make the change handler retrigger even on the same file selected + this.$refs.uploadFolder.value = ''; + this.$refs.uploadFolder.click(); + }, onDelete: function (entry) { var that = this;