mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 18:24:30 -04:00
More work on adding books in the server UI
This commit is contained in:
parent
61ab18b81a
commit
d48c8e7a2b
@ -113,7 +113,7 @@ def ajax(path, on_complete, on_progress=None, bypass_cache=True, method='GET', q
|
|||||||
xhr.timeout = timeout * 1000 # IE requires timeout to be set after open
|
xhr.timeout = timeout * 1000 # IE requires timeout to be set after open
|
||||||
return xhr
|
return xhr
|
||||||
|
|
||||||
def ajax_send(path, data, on_complete, on_progress=None, query=None, timeout=30*1000, ok_code=200):
|
def ajax_send(path, data, on_complete, on_progress=None, query=None, timeout=None, ok_code=200):
|
||||||
# Unfortunately, browsers do not allow sending of data with HTTP GET, except
|
# Unfortunately, browsers do not allow sending of data with HTTP GET, except
|
||||||
# as query parameters, so we have to use POST
|
# as query parameters, so we have to use POST
|
||||||
xhr = ajax(path, on_complete, on_progress, False, 'POST', query, timeout, ok_code)
|
xhr = ajax(path, on_complete, on_progress, False, 'POST', query, timeout, ok_code)
|
||||||
@ -122,6 +122,19 @@ def ajax_send(path, data, on_complete, on_progress=None, query=None, timeout=30*
|
|||||||
return xhr
|
return xhr
|
||||||
|
|
||||||
|
|
||||||
|
def ajax_send_file(path, file, on_complete, on_progress, query=None, timeout=None, ok_code=200):
|
||||||
|
xhr = ajax(path, on_complete, on_progress, False, 'POST', query, timeout, ok_code)
|
||||||
|
if file.name:
|
||||||
|
xhr.setRequestHeader('Calibre-Filename', file.name)
|
||||||
|
if file.type:
|
||||||
|
xhr.overrideMimeType(file.type)
|
||||||
|
r = FileReader()
|
||||||
|
r.onload = def(evt):
|
||||||
|
xhr.send(evt.target.result)
|
||||||
|
r.readAsBinaryString(file)
|
||||||
|
return xhr
|
||||||
|
|
||||||
|
|
||||||
def console_print(*args):
|
def console_print(*args):
|
||||||
ρσ_print(*args) # noqa: undef
|
ρσ_print(*args) # noqa: undef
|
||||||
data = ' '.join(map(str, args)) + '\n'
|
data = ' '.join(map(str, args)) + '\n'
|
||||||
|
83
src/pyj/book_list/add.pyj
Normal file
83
src/pyj/book_list/add.pyj
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
# vim:fileencoding=utf-8
|
||||||
|
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
from __python__ import bound_methods, hash_literals
|
||||||
|
|
||||||
|
from gettext import gettext as _
|
||||||
|
|
||||||
|
from ajax import ajax_send_file
|
||||||
|
from book_list.router import back
|
||||||
|
from book_list.top_bar import create_top_bar
|
||||||
|
from dom import ensure_id
|
||||||
|
from file_uploads import (
|
||||||
|
update_status_widget, upload_files_widget, upload_status_widget
|
||||||
|
)
|
||||||
|
|
||||||
|
state = {
|
||||||
|
'in_progress': False,
|
||||||
|
'container_id': None,
|
||||||
|
'counter': 0,
|
||||||
|
'fake_send': False,
|
||||||
|
}
|
||||||
|
|
||||||
|
def on_close():
|
||||||
|
back()
|
||||||
|
|
||||||
|
|
||||||
|
def get_job_container(container_id, job_id):
|
||||||
|
container = document.getElementById(container_id)
|
||||||
|
if not container:
|
||||||
|
return
|
||||||
|
return container.querySelector(f'[data-job="{job_id}"]')
|
||||||
|
|
||||||
|
|
||||||
|
def on_progress(container_id, job_id):
|
||||||
|
container = get_job_container(container_id, job_id)
|
||||||
|
if container is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def on_complete(container_id, job_id):
|
||||||
|
container = get_job_container(container_id, job_id)
|
||||||
|
if container is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def fake_send(container_id, job_id):
|
||||||
|
container = get_job_container(container_id, job_id)
|
||||||
|
prev = parseInt(container.dataset.fake or '0')
|
||||||
|
container.dataset.fake = prev + 10
|
||||||
|
update_status_widget(container, container.dataset.fake, 100)
|
||||||
|
if parseInt(container.dataset.fake or '0') < 100:
|
||||||
|
setTimeout(fake_send.bind(None, container_id, job_id), 1000)
|
||||||
|
|
||||||
|
|
||||||
|
def files_chosen(container_id, files):
|
||||||
|
container = document.getElementById(container_id)
|
||||||
|
if not container:
|
||||||
|
return
|
||||||
|
for file in files:
|
||||||
|
state.counter += 1
|
||||||
|
job_id = state.counter
|
||||||
|
w = upload_status_widget(file.name, job_id)
|
||||||
|
container.appendChild(w)
|
||||||
|
w.style.borderBottom = 'solid 1px currentColor'
|
||||||
|
if state.fake_send:
|
||||||
|
setTimeout(fake_send.bind(None, container_id, job_id), 100)
|
||||||
|
else:
|
||||||
|
ajax_send_file('/add-book', file, on_complete.bind(None, container_id, job_id), on_progress.bind(None, container_id, job_id), query={'id': '' + job_id})
|
||||||
|
|
||||||
|
|
||||||
|
def add_books_panel(container_id):
|
||||||
|
container = document.getElementById(container_id)
|
||||||
|
create_top_bar(container, title=_('Add books'), action=on_close, icon='close')
|
||||||
|
state.in_progress = True
|
||||||
|
state.container_id = container_id
|
||||||
|
state.fake_send = False
|
||||||
|
return upload_files_widget(container, files_chosen)
|
||||||
|
|
||||||
|
|
||||||
|
def develop(container):
|
||||||
|
c = 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'}])
|
@ -7,6 +7,7 @@ from elementmaker import E
|
|||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
|
|
||||||
from ajax import ajax_send
|
from ajax import ajax_send
|
||||||
|
from book_list.add import add_books_panel
|
||||||
from book_list.cover_grid import (
|
from book_list.cover_grid import (
|
||||||
DESCRIPTION as COVER_GRID_DESCRIPTION, append_item as cover_grid_append_item,
|
DESCRIPTION as COVER_GRID_DESCRIPTION, append_item as cover_grid_append_item,
|
||||||
cover_grid_css, create_item as create_cover_grid_item, init as init_cover_grid
|
cover_grid_css, create_item as create_cover_grid_item, init as init_cover_grid
|
||||||
@ -35,7 +36,6 @@ from book_list.search import (
|
|||||||
from book_list.top_bar import add_button, create_top_bar
|
from book_list.top_bar import add_button, create_top_bar
|
||||||
from book_list.ui import query_as_href, set_panel_handler, show_panel
|
from book_list.ui import query_as_href, set_panel_handler, show_panel
|
||||||
from dom import add_extra_css, build_rule, clear, ensure_id, set_css
|
from dom import add_extra_css, build_rule, clear, ensure_id, set_css
|
||||||
from file_uploads import upload_files_widget
|
|
||||||
from modals import error_dialog
|
from modals import error_dialog
|
||||||
from session import get_interface_data
|
from session import get_interface_data
|
||||||
from utils import conditional_timeout, parse_url_params, safe_set_inner_html
|
from utils import conditional_timeout, parse_url_params, safe_set_inner_html
|
||||||
@ -452,8 +452,11 @@ def create_more_actions_panel(container_id):
|
|||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
# Adding books {{{
|
# Adding books {{{
|
||||||
def implement_me():
|
def add_books(container_id):
|
||||||
upload_files_widget()
|
if not library_data.sortable_fields:
|
||||||
|
show_panel('book_list', replace=True)
|
||||||
|
return
|
||||||
|
add_books_panel(container_id)
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ from __python__ import bound_methods, hash_literals
|
|||||||
from elementmaker import E
|
from elementmaker import E
|
||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
|
|
||||||
from utils import safe_set_inner_html
|
from utils import safe_set_inner_html, human_readable
|
||||||
|
|
||||||
|
|
||||||
def upload_files_widget(container, proceed, msg):
|
def upload_files_widget(container, proceed, msg):
|
||||||
@ -15,12 +15,13 @@ def upload_files_widget(container, proceed, msg):
|
|||||||
files = this.files
|
files = this.files
|
||||||
container = document.getElementById(container_id)
|
container = document.getElementById(container_id)
|
||||||
container.removeChild(container.lastChild)
|
container.removeChild(container.lastChild)
|
||||||
if callable(proceed):
|
if callable(proceed) and files.length:
|
||||||
proceed(container, files)
|
proceed(container_id, files)
|
||||||
|
|
||||||
msg = msg or _('Upload books by <a>selecting the book files</a> or drag and drop of the files here')
|
msg = msg or _('Upload books by <a>selecting the book files</a> or drag and drop of the files here')
|
||||||
c = E.div(E.span(), E.input(type='file', multiple=True, style='display:none', onchange=files_selected))
|
c = E.div(E.span(), E.input(type='file', multiple=True, style='display:none', onchange=files_selected))
|
||||||
c.style.minHeight = '40vh'
|
c.style.minHeight = '80vh'
|
||||||
|
c.style.padding = '1rem'
|
||||||
c.style.borderBottom = 'solid 1px currentColor'
|
c.style.borderBottom = 'solid 1px currentColor'
|
||||||
|
|
||||||
safe_set_inner_html(c.firstChild, msg)
|
safe_set_inner_html(c.firstChild, msg)
|
||||||
@ -47,9 +48,21 @@ def upload_files_widget(container, proceed, msg):
|
|||||||
return c
|
return c
|
||||||
|
|
||||||
|
|
||||||
|
def update_status_widget(w, sent, total):
|
||||||
|
if total:
|
||||||
|
p = w.getElementsByTagName('progress')[0]
|
||||||
|
p.setAttribute('value', '' + sent)
|
||||||
|
p.setAttribute('max', '' + total)
|
||||||
|
w.lastChild.textContent = _(' {percent:.0%} of {total}').format(percent=sent / total, total=human_readable(total))
|
||||||
|
|
||||||
|
|
||||||
|
def upload_status_widget(name, job_id):
|
||||||
|
ans = E.div(style='padding: 1rem 1ex;', data_job='' + job_id)
|
||||||
|
ans.appendChild(E.h3(E.b(name)))
|
||||||
|
ans.appendChild(E.progress())
|
||||||
|
ans.appendChild(E.span())
|
||||||
|
return ans
|
||||||
|
|
||||||
|
|
||||||
def start_send(container, files):
|
def start_send(container, files):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def develop(container):
|
|
||||||
upload_files_widget(container)
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user