X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=frontend%2Fjs%2Fapp.js;h=9d7bacaa1cd4887420714d558972aea1aa7ba420;hb=7c36adbbc51c85c9073c72e75d6503b52c02561d;hp=d659b180c86a1c7b3972dc4d31254228af5718b2;hpb=13df9f95b03daec6f2ce4d5a5d2a62657e814d0d;p=perso%2FImmae%2FProjets%2FNodejs%2FSurfer.git diff --git a/frontend/js/app.js b/frontend/js/app.js index d659b18..9d7baca 100644 --- a/frontend/js/app.js +++ b/frontend/js/app.js @@ -1,11 +1,25 @@ (function () { 'use strict'; -function getProfile(accessToken, callback) { - callback = callback || function (error) { if (error) console.error(error); }; +// poor man's async +function asyncForEach(items, handler, callback) { + var cur = 0; + + if (items.length === 0) return callback(); + + (function iterator() { + handler(items[cur], function (error) { + if (error) return callback(error); + if (cur >= items.length-1) return callback(); + ++cur; + + iterator(); + }); + })(); +} +function getProfile(accessToken, callback) { superagent.get('/api/profile').query({ access_token: accessToken }).end(function (error, result) { - app.busy = false; app.ready = true; if (error && !error.response) return callback(error); @@ -18,7 +32,13 @@ function getProfile(accessToken, callback) { app.session.username = result.body.username; app.session.valid = true; - callback(); + superagent.get('/api/settings').query({ access_token: localStorage.accessToken }).end(function (error, result) { + if (error) console.error(error); + + app.folderListingEnabled = !!result.body.folderListingEnabled; + + callback(); + }); }); } @@ -107,57 +127,53 @@ function open(row, event, column) { window.open(encode(path)); } -function up() { - window.location.hash = sanitize(app.path.split('/').slice(0, -1).filter(function (p) { return !!p; }).join('/')); -} - function uploadFiles(files) { if (!files || !files.length) return; - app.uploadStatus = { - busy: true, - count: files.length, - done: 0, - percentDone: 0 - }; + app.uploadStatus.busy = true; + app.uploadStatus.count = files.length; + app.uploadStatus.done = 0; + app.uploadStatus.percentDone = 0; - function uploadFile(file) { - var path = encode(sanitize(app.path + '/' + file.name)); + asyncForEach(files, function (file, callback) { + // do not handle directories (file.type is empty in such a case) + if (file.type === '') return 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) { if (result && result.statusCode === 401) return logout(); - if (result && result.statusCode !== 201) console.error('Error uploading file: ', result.statusCode); - if (error) console.error(error); + 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); - if (app.uploadStatus.done >= app.uploadStatus.count) { - app.uploadStatus = { - busy: false, - count: 0, - done: 0, - percentDone: 100 - }; - - refresh(); - } + callback(); }); - } + }, function (error) { + if (error) console.error(error); - for(var i = 0; i < app.uploadStatus.count; ++i) { - uploadFile(files[i]); - } + app.uploadStatus.busy = false; + app.uploadStatus.count = 0; + app.uploadStatus.done = 0; + app.uploadStatus.percentDone = 100; + + refresh(); + }); } function dragOver(event) { + event.stopPropagation(); event.preventDefault(); + event.dataTransfer.dropEffect = 'copy'; } function drop(event) { + event.stopPropagation(); event.preventDefault(); uploadFiles(event.dataTransfer.files || []); } @@ -166,7 +182,7 @@ var app = new Vue({ el: '#app', data: { ready: false, - busy: true, + busy: false, uploadStatus: { busy: false, count: 0, @@ -181,19 +197,22 @@ var app = new Vue({ folderListingEnabled: false, loginData: { username: '', - password: '' + password: '', + busy: false }, entries: [] }, methods: { onLogin: function () { - app.busy = true; + var that = this; + + that.loginData.busy = true; - superagent.post('/api/login').send({ username: app.loginData.username, password: app.loginData.password }).end(function (error, result) { - app.busy = false; + superagent.post('/api/login').send({ username: that.loginData.username, password: that.loginData.password }).end(function (error, result) { + that.loginData.busy = false; - if (error) return console.error(error); - if (result.statusCode === 401) return console.error('Invalid credentials'); + if (error && !result) return that.$message.error(error.message); + if (result.statusCode === 401) return that.$message.error('Wrong username or password'); getProfile(result.body.accessToken, function (error) { if (error) return console.error(error); @@ -203,8 +222,12 @@ var app = new Vue({ }); }, onOptionsMenu: function (command) { + var that = this; + if (command === 'folderListing') { - console.log('Not implemented'); + superagent.put('/api/settings').send({ folderListingEnabled: this.folderListingEnabled }).query({ access_token: localStorage.accessToken }).end(function (error) { + if (error) console.error(error); + }); } else if (command === 'about') { this.$msgbox({ title: 'About Surfer', @@ -219,7 +242,7 @@ var app = new Vue({ superagent.post('/api/logout').query({ access_token: localStorage.accessToken }).end(function (error) { if (error) console.error(error); - app.session.valid = false; + that.session.valid = false; delete localStorage.accessToken; }); @@ -227,71 +250,84 @@ var app = new Vue({ }, onDownload: function (entry) { if (entry.isDirectory) return; - window.location.href = encode('/api/files/' + sanitize(app.path + '/' + entry.filePath)) + '?access_token=' + localStorage.accessToken; + window.location.href = encode('/api/files/' + sanitize(this.path + '/' + entry.filePath)) + '?access_token=' + localStorage.accessToken; }, onUpload: function () { - $(app.$refs.upload).on('change', function () { + var that = this; + $(this.$refs.upload).on('change', function () { // detach event handler - $(app.$refs.upload).off('change'); + $(that.$refs.upload).off('change'); + uploadFiles(that.$refs.upload.files || []); + }); - uploadFiles(app.$refs.upload.files || []); + // reset the form first to make the change handler retrigger even on the same file selected + 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 - app.$refs.upload.value = ''; - app.$refs.upload.click(); + this.$refs.uploadFolder.value = ''; + this.$refs.uploadFolder.click(); }, onDelete: function (entry) { + var that = this; + var title = 'Really delete ' + (entry.isDirectory ? 'folder ' : '') + entry.filePath; this.$confirm('', title, { confirmButtonText: 'Yes', cancelButtonText: 'No' }).then(function () { - var path = encode(sanitize(app.path + '/' + entry.filePath)); + var path = encode(sanitize(that.path + '/' + entry.filePath)); superagent.del('/api/files' + path).query({ access_token: localStorage.accessToken, recursive: true }).end(function (error, result) { if (result && result.statusCode === 401) return logout(); - if (result && result.statusCode !== 200) return console.error('Error deleting file: ', result.statusCode); - if (error) return console.error(error); + if (result && result.statusCode !== 200) return that.$message.error('Error deleting file: ' + result.statusCode); + if (error) return that.$message.error(error.message); refresh(); }); - }).catch(function () { - console.log('delete error:', arguments); - }); + }).catch(function () {}); }, onRename: function (entry) { + var that = this; + var title = 'Rename ' + entry.filePath; this.$prompt('', title, { confirmButtonText: 'Yes', cancelButtonText: 'No', inputPlaceholder: 'new filename', inputValue: entry.filePath }).then(function (data) { - var path = encode(sanitize(app.path + '/' + entry.filePath)); - var newFilePath = sanitize(app.path + '/' + data.value); + var path = encode(sanitize(that.path + '/' + entry.filePath)); + var newFilePath = sanitize(that.path + '/' + data.value); superagent.put('/api/files' + path).query({ access_token: localStorage.accessToken }).send({ newFilePath: newFilePath }).end(function (error, result) { if (result && result.statusCode === 401) return logout(); - if (result && result.statusCode !== 200) return console.error('Error renaming file: ', result.statusCode); - if (error) return console.error(error); + if (result && result.statusCode !== 200) return that.$message.error('Error renaming file: ' + result.statusCode); + if (error) return that.$message.error(error.message); refresh(); }); - }).catch(function () { - console.log('rename error:', arguments); - }); + }).catch(function () {}); }, onNewFolder: function () { + var that = this; + var title = 'Create New Folder'; this.$prompt('', title, { confirmButtonText: 'Yes', cancelButtonText: 'No', inputPlaceholder: 'new foldername' }).then(function (data) { - var path = encode(sanitize(app.path + '/' + data.value)); + var path = encode(sanitize(that.path + '/' + data.value)); superagent.post('/api/files' + path).query({ access_token: localStorage.accessToken, directory: true }).end(function (error, result) { if (result && result.statusCode === 401) return logout(); - if (result && result.statusCode === 403) return console.error('Name not allowed'); - if (result && result.statusCode === 409) return console.error('Directory already exists'); - if (result && result.statusCode !== 201) return console.error('Error creating directory: ', result.statusCode); - if (error) return console.error(error); + if (result && result.statusCode === 403) return that.$message.error('Folder name not allowed'); + if (result && result.statusCode === 409) return that.$message.error('Folder already exists'); + if (result && result.statusCode !== 201) return that.$message.error('Error creating folder: ' + result.statusCode); + if (error) return that.$message.error(error.message); refresh(); }); - }).catch(function () { - console.log('create folder error:', arguments); - }); + }).catch(function () {}); }, prettyDate: function (row, column, cellValue, index) { var date = new Date(cellValue), @@ -317,7 +353,9 @@ var app = new Vue({ return filesize(cellValue); }, loadDirectory: loadDirectory, - up: up, + onUp: function () { + window.location.hash = sanitize(this.path.split('/').slice(0, -1).filter(function (p) { return !!p; }).join('/')); + }, open: open, drop: drop, dragOver: dragOver