Finish up adding books implementation

Still needs to add the new book to the existing book list, so that the
book list does not need to be refreshed to see the book.
This commit is contained in:
Kovid Goyal 2018-01-25 14:04:15 +05:30
parent b795ca81f1
commit 4fc76a6919
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 80 additions and 14 deletions

View File

@ -82,6 +82,7 @@ def cdb_add_book(ctx, rd, job_id, add_duplicates, filename, library_id):
add_duplicates = add_duplicates in ('y', '1') add_duplicates = add_duplicates in ('y', '1')
path = os.path.join(rd.tdir, sfilename) path = os.path.join(rd.tdir, sfilename)
rd.request_body_file.name = path rd.request_body_file.name = path
rd.request_body_file.seek(0)
mi = get_metadata(rd.request_body_file, stream_type=fmt, use_libprs_metadata=True) mi = get_metadata(rd.request_body_file, stream_type=fmt, use_libprs_metadata=True)
rd.request_body_file.seek(0) rd.request_body_file.seek(0)
ids, duplicates = db.add_books([(mi, {fmt: rd.request_body_file})], add_duplicates=add_duplicates) ids, duplicates = db.add_books([(mi, {fmt: rd.request_body_file})], add_duplicates=add_duplicates)

View File

@ -126,10 +126,7 @@ def ajax_send_file(path, file, on_complete, on_progress, timeout=None, ok_code=2
xhr = ajax(path, on_complete, on_progress, False, 'POST', timeout, ok_code) xhr = ajax(path, on_complete, on_progress, False, 'POST', timeout, ok_code)
if file.type: if file.type:
xhr.overrideMimeType(file.type) xhr.overrideMimeType(file.type)
r = FileReader() xhr.send(file)
r.onload = def(evt):
xhr.send(evt.target.result)
r.readAsBinaryString(file)
return xhr return xhr

View File

@ -2,25 +2,41 @@
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net> # License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
from __python__ import bound_methods, hash_literals from __python__ import bound_methods, hash_literals
from elementmaker import E
from gettext import gettext as _ from gettext import gettext as _
from ajax import ajax_send_file from ajax import ajax_send_file
from book_list.library_data import loaded_books_query from book_list.library_data import loaded_books_query
from book_list.router import back from book_list.router import back
from book_list.top_bar import create_top_bar from book_list.top_bar import create_top_bar
from dom import ensure_id from book_list.ui import query_as_href, show_panel
from dom import clear, ensure_id
from file_uploads import ( from file_uploads import (
update_status_widget, upload_files_widget, upload_status_widget update_status_widget, upload_files_widget, upload_status_widget
) )
from session import get_interface_data
from utils import safe_set_inner_html
from widgets import create_button
state = { state = {
'in_progress': False, 'in_progress': False,
'container_id': None, 'container_id': None,
'counter': 0, 'counter': 0,
'number': 0,
'fake_send': False, 'fake_send': False,
'transfers': v'[]',
} }
def cancel_in_progress():
for xhr in state.transfers:
xhr.abort()
state.transfers = v'[]'
state.in_progress = False
def on_close(): def on_close():
cancel_in_progress()
back() back()
@ -31,16 +47,66 @@ def get_job_container(container_id, job_id):
return container.querySelector(f'[data-job="{job_id}"]') return container.querySelector(f'[data-job="{job_id}"]')
def on_progress(container_id, job_id): def on_progress(container_id, job_id, loaded, total, xhr):
container = get_job_container(container_id, job_id) container = get_job_container(container_id, job_id)
if container is None: if container is None:
return return
if total:
update_status_widget(container, loaded, total)
def on_complete(container_id, job_id): def list_added_book(container, data):
container.appendChild(E.h3(E.b(data.title), E.span(' ' + _('by') + ' '), E.i(' & '.join(data.authors))))
container.appendChild(E.span(_('Added successfully') + ' '))
q = {'book_id': data.book_id + ''}
a = create_button(_('Open'), action=query_as_href(q, 'book_details'))
if state.number > 1:
a.setAttribute('target', '_blank')
else:
a.addEventListener('click', def(e):
e.preventDefault()
show_panel('book_details', {'book_id': data.book_id + ''}, True)
)
container.appendChild(a)
def list_duplicate_book(container, container_id, job_id, data, file):
container.appendChild(E.div(style="padding: 1rem 1ex", _('A book with the title "{0}" already exists in the library.').format(data.title)))
b = create_button(_('Add anyway'), action=def():
c = get_job_container(container_id, job_id)
clear(c)
w = upload_status_widget(file.name, job_id)
c.appendChild(w)
send_file(file, container_id, job_id, True)
)
container.appendChild(b)
def on_complete(container_id, job_id, end_type, xhr, ev):
idx = state.transfers.indexOf(xhr)
if idx > -1:
state.transfers.splice(idx, 1)
container = get_job_container(container_id, job_id) container = get_job_container(container_id, job_id)
if container is None: if container is None:
return return
clear(container)
if end_type is 'load':
data = JSON.parse(xhr.responseText)
if data.book_id:
list_added_book(container, data)
else:
list_duplicate_book(container, container_id, job_id, data, this)
elif end_type is 'abort':
return
else:
html = _('Failed to upload the file: {}').format(this.name) + '<br>'
if xhr.status is 403:
un = get_interface_data().username
if un:
html += _('You are not allowed to make changes to the library') + '<hr>'
else:
html += _('You must be logged in to make changes to the library') + '<hr>'
safe_set_inner_html(container, html + '<br>' + xhr.error_html)
def fake_send(container_id, job_id): def fake_send(container_id, job_id):
@ -55,17 +121,21 @@ def fake_send(container_id, job_id):
def send_file(file, container_id, job_id, add_duplicates): def send_file(file, container_id, job_id, add_duplicates):
lid = loaded_books_query().library_id lid = loaded_books_query().library_id
ad = 'y' if add_duplicates else 'n' ad = 'y' if add_duplicates else 'n'
return ajax_send_file( xhr = ajax_send_file(
f'/cdb/add-book/{job_id}/{ad}/{encodeURIComponent(file.name)}/{lid}', f'/cdb/add-book/{job_id}/{ad}/{encodeURIComponent(file.name)}/{lid}',
file, on_complete.bind(None, container_id, job_id), on_progress.bind(None, container_id, job_id)) file, on_complete.bind(file, container_id, job_id), on_progress.bind(None, container_id, job_id))
state.transfers.push(xhr)
return xhr
def files_chosen(container_id, files): def files_chosen(container_id, files):
container = document.getElementById(container_id) container = document.getElementById(container_id)
if not container: if not container:
return return
state.number = 0
for file in files: for file in files:
state.counter += 1 state.counter += 1
state.number += 1
job_id = state.counter job_id = state.counter
w = upload_status_widget(file.name, job_id) w = upload_status_widget(file.name, job_id)
container.appendChild(w) container.appendChild(w)
@ -79,6 +149,7 @@ def files_chosen(container_id, files):
def add_books_panel(container_id): def add_books_panel(container_id):
container = document.getElementById(container_id) container = document.getElementById(container_id)
create_top_bar(container, title=_('Add books'), action=on_close, icon='close') create_top_bar(container, title=_('Add books'), action=on_close, icon='close')
cancel_in_progress()
state.in_progress = True state.in_progress = True
state.container_id = container_id state.container_id = container_id
state.fake_send = False state.fake_send = False
@ -86,7 +157,4 @@ def add_books_panel(container_id):
def develop(container): def develop(container):
c = add_books_panel(ensure_id(container)) add_books_panel(ensure_id(container))
state.fake_send = True
container.removeChild(c)
files_chosen(container.id, [{'name': 'test1.epub', 'type': 'application/epub+zip'}, {'name': 'xxxx.yyy'}])

View File

@ -219,7 +219,7 @@ def simple_markup(html):
div.textContent = html div.textContent = html
html = div.innerHTML html = div.innerHTML
return html.replace(/\uffff(\/?[a-z1-6]+)\uffff/g, '<$1>') return html.replace(/\uffff(\/?[a-z1-6]+)\uffff/g, '<$1>')
simple_markup.allowed_tags = v"'a|b|i|br|h1|h2|h3|h4|h5|h6|div|em|strong|span'.split('|')" simple_markup.allowed_tags = v"'a|b|i|br|hr|h1|h2|h3|h4|h5|h6|div|em|strong|span'.split('|')"
def safe_set_inner_html(elem, html): def safe_set_inner_html(elem, html):