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 Rewrite calibredb to connect to running server
Prevent standalone and embedded servers from running simultaneously Prevent standalone and embedded servers from running simultaneously
Prevent more than a single instance of the standalone server from running 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_WIDTH = 300
THUMBNAIL_MAX_HEIGHT = 400 THUMBNAIL_MAX_HEIGHT = 400
BORDER_RADIUS = 10 BORDER_RADIUS = 10
DESCRIPTION = _('A grid of book covers')
def cover_grid_css(): def cover_grid_css():
sel = '.' + COVER_GRID_CLASS 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 ajax import ajax_send
from book_list.cover_grid import ( from book_list.cover_grid import (
append_item as cover_grid_append_item, cover_grid_css, DESCRIPTION as COVER_GRID_DESCRIPTION, append_item as cover_grid_append_item,
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
)
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.globals import get_session_data
from book_list.item_list import create_item, create_item_list 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 from widgets import create_button, create_spinner
CLASS_NAME = 'book-list-container' CLASS_NAME = 'book-list-container'
ALLOWED_MODES = {'cover_grid'} ALLOWED_MODES = {'cover_grid', 'details_list'}
DEFAULT_MODE = 'cover_grid' DEFAULT_MODE = 'cover_grid'
add_extra_css(def(): add_extra_css(def():
sel = '.' + CLASS_NAME + ' ' sel = '.' + CLASS_NAME + ' '
ans = build_rule(sel + '[data-component="top_message"]', margin='1ex 1em') 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 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.render_book = create_cover_grid_item
book_list_data.init_grid = init_cover_grid book_list_data.init_grid = init_cover_grid
book_list_data.append_item = cover_grid_append_item 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() clear_grid()
render_ids() 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 {{{ # More actions {{{
def create_more_actions_panel(container_id): def create_more_actions_panel(container_id):
container = document.getElementById(container_id) container = document.getElementById(container_id)
create_top_bar(container, title=_('Sort books by…'), action=back, icon='close') create_top_bar(container, title=_('Sort books by…'), action=back, icon='close')
items = [ 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(): create_item(_('A random book'), subtitle=_('Choose a random book from the library'), action=def():
query = {'book_id':'0'} query = {'book_id':'0'}
show_panel('book_details', query=query, replace=True) 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^sort', create_sort_panel)
set_panel_handler('book_list^vl', create_vl_panel) set_panel_handler('book_list^vl', create_vl_panel)
set_panel_handler('book_list^search', init_search_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^search^prefs', tb_config_panel_handler())
set_panel_handler('book_list^more_actions', create_more_actions_panel) set_panel_handler('book_list^more_actions', create_more_actions_panel)