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) {
app.uploadStatus.busy = false;
app.uploadStatus.count = 0;
+ app.uploadStatus.size = 0;
app.uploadStatus.done = 0;
app.uploadStatus.percentDone = 100;
}
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({
busy: false,
count: 0,
done: 0,
- percentDone: 50
+ percentDone: 50,
+ uploadListCount: 0
},
path: '/',
pathParts: [],
var that = this;
$(this.$refs.upload).on('change', function () {
-
// detach event handler
$(that.$refs.upload).off('change');
-
uploadFiles(that.$refs.upload.files || []);
});
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;