support drag and drop
This commit is contained in:
parent
2cbcc9e7dd
commit
25c24d6f20
4 changed files with 121 additions and 2 deletions
|
@ -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)
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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({
|
||||||
|
|
|
@ -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);
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in a new issue