support drag and drop

This commit is contained in:
j 2015-06-06 19:54:44 +02:00
parent 2cbcc9e7dd
commit 25c24d6f20
4 changed files with 121 additions and 2 deletions

View file

@ -8,11 +8,23 @@ import os
from urllib.request import quote from urllib.request import quote
import zipfile import zipfile
from .models import Item import ox
from .models import Item, File
from user.models import List
from .scan import add_file
import db import db
import settings import settings
import tornado.web import tornado.web
import tornado.gen
import tornado.concurrent
from oxtornado import json_dumps, json_response
from media import get_id
import logging
logger = logging.getLogger('item.handlers')
class OMLHandler(tornado.web.RequestHandler): class OMLHandler(tornado.web.RequestHandler):
@ -126,3 +138,60 @@ class ReaderHandler(OMLHandler):
item.update_sort() item.update_sort()
item.save() item.save()
return serve_static(self, os.path.join(settings.static_path, html), 'text/html') return serve_static(self, os.path.join(settings.static_path, html), 'text/html')
class UploadHandler(tornado.web.RequestHandler):
def initialize(self, context=None):
self._context = context
def get(self):
self.write('use POST')
@tornado.web.asynchronous
@tornado.gen.coroutine
def post(self):
if 'origin' in self.request.headers and self.request.host not in self.request.headers['origin']:
logger.debug('reject cross site attempt to access api %s', self.request)
self.set_status(403)
self.write('')
return
def save_files(context, request, callback):
listname = request.arguments.get('list', None)
if listname:
listname = listname[0]
if isinstance(listname, bytes):
listname = listname.decode('utf-8')
with context():
prefs = settings.preferences
ids = []
for upload in request.files.get('files', []):
filename = upload.filename
id = get_id(data=upload.body)
ids.append(id)
file = File.get(id)
if not file:
prefix_books = os.path.join(os.path.expanduser(prefs['libraryPath']), 'Books/')
prefix_imported = os.path.join(prefix_books, 'Imported/')
ox.makedirs(prefix_imported)
import_name = os.path.join(prefix_imported, filename)
n = 1
while os.path.exists(import_name):
n += 1
name, extension = filename.rsplit('.', 1)
import_name = os.path.join(prefix_imported, '%s [%d].%s' % (name, n, extension))
with open(import_name, 'wb') as fd:
fd.write(upload.body)
file = add_file(id, import_name, prefix_books)
if listname and ids:
l = List.get(settings.USER_ID, listname)
if l:
l.add_items(ids)
response = json_response({'ids': ids})
callback(response)
response = yield tornado.gen.Task(save_files, self._context, self.request)
if not 'status' in response:
response = json_response(response)
response = json_dumps(response)
self.set_header('Content-Type', 'application/json')
self.write(response)

View file

@ -13,7 +13,7 @@ from tornado.web import StaticFileHandler, Application
from cache import Cache from cache import Cache
from item.handlers import EpubHandler, ReaderHandler, FileHandler from item.handlers import EpubHandler, ReaderHandler, FileHandler
from item.handlers import OMLHandler from item.handlers import OMLHandler, UploadHandler
from item.icons import IconHandler from item.icons import IconHandler
import db import db
import node.server import node.server
@ -74,6 +74,7 @@ def run():
'attachment': True 'attachment': True
}), }),
(r'/(.*)/(cover|preview)(\d*).jpg', IconHandler), (r'/(.*)/(cover|preview)(\d*).jpg', IconHandler),
(r'/api/upload/', UploadHandler, dict(context=db.session)),
(r'/api/', oxtornado.ApiHandler, dict(context=db.session)), (r'/api/', oxtornado.ApiHandler, dict(context=db.session)),
(r'/ws', websocket.Handler), (r'/ws', websocket.Handler),
(r"(.*)", MainHandler), (r"(.*)", MainHandler),

View file

@ -93,6 +93,25 @@
Ox.$window.on({ Ox.$window.on({
resize: oml.resizeWindow resize: oml.resizeWindow
}); });
Ox.$document.on({
dragenter: function(event) {
event.preventDefault();
},
dragover: function(event) {
event.preventDefault();
},
drop: function(event) {
if (event.originalEvent.dataTransfer.files) {
event.preventDefault();
oml.upload(event.originalEvent.dataTransfer.files, function(response) {
setTimeout(function() {
oml.UI.set({listSelection: response.data.ids});
oml.reloadList();
}, 50);
});
}
}
});
oml.$ui.appPanel = oml.ui.appPanel().appendTo(Ox.$body); oml.$ui.appPanel = oml.ui.appPanel().appendTo(Ox.$body);
oml.$ui.loadingIcon.updateElement(Ox.Request.requests()); oml.$ui.loadingIcon.updateElement(Ox.Request.requests());
Ox.Request.bindEvent({ Ox.Request.bindEvent({

View file

@ -999,3 +999,33 @@ oml.updateDebugMenu = function() {
}); });
oml.user.ui.showDebugMenu ? menu.show() : menu.hide(); oml.user.ui.showDebugMenu ? menu.show() : menu.hide();
}; };
oml.supportedExtensions = ['pdf', 'epub', 'cbr', 'cbz'];
oml.upload = function(files, callback) {
var request = new XMLHttpRequest(),
url = '/api/upload/';
request.onreadystatechange = function() {
if (request.readyState == 4) {
if (request.status == 200) {
callback(JSON.parse(request.responseText), null);
} else {
callback(null, {
code: request.status,
text: request.statusText
});
}
}
};
var formData = new FormData();
for (var i=0; i < files.length; i++) {
var extension = Ox.last(files[i].name.split('.'));
if (Ox.contains(oml.supportedExtensions, extension)) {
formData.append('files', files[i]);
}
}
if (oml.user.ui._list[0] == ':' && oml.user.ui._list.length > 1) {
formData.append('list', oml.user.ui._list.slice(1));
}
request.open('post', url, true);
request.send(formData);
};