Start for on detailed book list

This commit is contained in:
Kovid Goyal 2017-04-27 10:19:27 +05:30
parent fe0a63e3ef
commit de3d570c52
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 98 additions and 7 deletions

View File

@ -1,5 +1,3 @@
Add a couple more book list visualizations
Rewrite calibredb to connect to running server
Prevent standalone and embedded servers from running simultaneously
Prevent more than a single instance of the standalone server from running

View File

@ -11,6 +11,7 @@ COVER_GRID_CLASS = 'book-list-cover-grid'
THUMBNAIL_MAX_WIDTH = 300
THUMBNAIL_MAX_HEIGHT = 400
BORDER_RADIUS = 10
DESCRIPTION = _('A grid of book covers')
def cover_grid_css():
sel = '.' + COVER_GRID_CLASS

View File

@ -0,0 +1,54 @@
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
from __python__ import bound_methods, hash_literals
from dom import clear, set_css, build_rule
from elementmaker import E
from gettext import gettext as _
DETAILS_LIST_CLASS = 'book-list-details-list'
DESCRIPTION = _('A list with thumbnails and some book details')
THUMBNAIL_MAX_WIDTH = 90
THUMBNAIL_MAX_HEIGHT = 120
BORDER_RADIUS = 5
def details_list_css():
ans = ''
sel = '.' + DETAILS_LIST_CLASS
ans += build_rule(sel + ' img', border_radius=BORDER_RADIUS+'px')
return ans
def init(container):
clear(container)
container.appendChild(E.div(class_=DETAILS_LIST_CLASS))
def on_img_load(img, load_type):
div = img.parentNode
if not div:
return
if load_type is not 'load':
clear(div)
div.appendChild(E.div(
E.h2(img.dataset.title, style='text-align:center; font-size:larger; font-weight: bold'),
E.div(_('by'), style='text-align: center'),
E.h2(img.dataset.authors, style='text-align:center; font-size:larger; font-weight: bold')
))
set_css(div, border='dashed 1px currentColor', border_radius=BORDER_RADIUS+'px')
def create_item(book_id, metadata, create_image, show_book_details):
authors = metadata.authors.join(' & ')
img = create_image(book_id, THUMBNAIL_MAX_WIDTH, THUMBNAIL_MAX_HEIGHT, on_img_load)
img.setAttribute('alt', _('{} by {}').format(metadata.title, authors))
img.dataset.title, img.dataset.authors = metadata.title, authors
img_div = E.div(img)
ans = E.div(img_div, style=f'height:{THUMBNAIL_MAX_HEIGHT}px')
return ans
def append_item(container, item):
container.lastChild.appendChild(item)

View File

@ -8,8 +8,13 @@ from gettext import gettext as _
from ajax import ajax_send
from book_list.cover_grid import (
append_item as cover_grid_append_item, cover_grid_css,
create_item as create_cover_grid_item, init as init_cover_grid
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
)
from book_list.details_list import (
DESCRIPTION as DETAILS_LIST_DESCRIPTION, append_item as details_list_append_item,
create_item as create_details_list_item, details_list_css,
init as init_details_list
)
from book_list.globals import get_session_data
from book_list.item_list import create_item, create_item_list
@ -31,13 +36,14 @@ from utils import conditional_timeout
from widgets import create_button, create_spinner
CLASS_NAME = 'book-list-container'
ALLOWED_MODES = {'cover_grid'}
ALLOWED_MODES = {'cover_grid', 'details_list'}
DEFAULT_MODE = 'cover_grid'
add_extra_css(def():
sel = '.' + CLASS_NAME + ' '
ans = build_rule(sel + '[data-component="top_message"]', margin='1ex 1em')
ans += cover_grid_css.call()
ans += cover_grid_css()
ans += details_list_css()
return ans
)
@ -94,6 +100,10 @@ def apply_view_mode(mode=DEFAULT_MODE):
book_list_data.render_book = create_cover_grid_item
book_list_data.init_grid = init_cover_grid
book_list_data.append_item = cover_grid_append_item
elif mode is 'details_list':
book_list_data.render_book = create_details_list_item
book_list_data.init_grid = init_details_list
book_list_data.append_item = details_list_append_item
clear_grid()
render_ids()
@ -319,13 +329,40 @@ def show_vl(vl_name, replace):
# }}}
# Modes {{{
def create_mode_panel(container_id):
if not library_data.sortable_fields:
show_panel('book_list', replace=True)
return
container = document.getElementById(container_id)
create_top_bar(container, title=_('Choose book list mode…'), action=back, icon='close')
items = []
current_mode = get_session_data().get('view_mode')
def ci(title, desc, name):
ic = 'check' if name is current_mode else None
items.push(create_item(title, subtitle=desc, icon=ic, action=def():
if name is not current_mode:
get_session_data().set('view_mode', name)
back()
))
ci(_('Cover grid'), COVER_GRID_DESCRIPTION, 'cover_grid')
ci(_('Detailed list'), DETAILS_LIST_DESCRIPTION, 'details_list')
container.appendChild(E.div())
create_item_list(container.lastChild, items, _('Choose a display mode for the list of books from below'))
# }}}
# More actions {{{
def create_more_actions_panel(container_id):
container = document.getElementById(container_id)
create_top_bar(container, title=_('Sort books by…'), action=back, icon='close')
items = [
create_item(_('Book list mode'), subtitle=_('Change how the list of books is displayed')),
create_item(_('Book list mode'), subtitle=_('Change how the list of books is displayed'), action=def():
show_panel('book_list^choose_mode', replace=True)
),
create_item(_('A random book'), subtitle=_('Choose a random book from the library'), action=def():
query = {'book_id':'0'}
show_panel('book_details', query=query, replace=True)
@ -345,5 +382,6 @@ set_panel_handler('book_list', init)
set_panel_handler('book_list^sort', create_sort_panel)
set_panel_handler('book_list^vl', create_vl_panel)
set_panel_handler('book_list^search', init_search_panel)
set_panel_handler('book_list^choose_mode', create_mode_panel)
set_panel_handler('book_list^search^prefs', tb_config_panel_handler())
set_panel_handler('book_list^more_actions', create_more_actions_panel)