CS: Implement switching of libraries

This commit is contained in:
Kovid Goyal 2016-02-18 18:16:12 +05:30
parent b44c770bfd
commit d83dc3fb94
7 changed files with 77 additions and 10 deletions

View File

@ -6,7 +6,7 @@
<meta name="robots" content="noindex">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="favicon.png">
<script>window.calibre_entry_point = 'ENTRY_POINT';</script>
<script>window.calibre_entry_point = 'ENTRY_POINT'; window.calibre_default_library = DEFAULT_LIBRARY;</script>
<script type="text/javascript" src="static/main.js"></script>
<link rel="stylesheet" href="static/reset.css"></link>
<link rel="stylesheet" href="static/font-awesome/fa.css"></link>

View File

@ -7,7 +7,7 @@ from __future__ import (unicode_literals, division, absolute_import,
import re, hashlib, random, os
from functools import partial
from threading import Lock
from json import load as load_json_file
from json import load as load_json_file, dumps as json_dumps
from calibre import prepare_string_for_xml, as_unicode
from calibre.constants import config_dir
@ -53,9 +53,13 @@ def get_html(name, auto_reload_port, **replacements):
@endpoint('', auth_required=False)
def index(ctx, rd):
default_library = ctx.library_map[1]
return rd.generate_static_output('/', partial(
get_html, 'content-server/index.html', getattr(rd.opts, 'auto_reload_port', 0),
ENTRY_POINT='book list', LOADING_MSG=prepare_string_for_xml(_('Loading library, please wait'))))
ENTRY_POINT='book list',
LOADING_MSG=prepare_string_for_xml(_('Loading library, please wait')),
DEFAULT_LIBRARY=json_dumps(default_library)
))
def get_library_data(ctx, query):
library_id = query.get('library_id')

View File

@ -77,7 +77,7 @@ class Boss:
sval = ''
for field, order in zip(str.split(data.search_result.sort, ','), str.split(data.search_result.sort_order, ',')):
sval += field + '.' + order + ','
get_session_data().set('sort', str.rstrip(sval, ','))
get_session_data().set_library_option(self.interface_data.library_id, 'sort', str.rstrip(sval, ','))
self.interface_data.metadata = data.metadata
self.interface_data.search_result = data.search_result
self.ui.refresh_books_view()

View File

@ -1,7 +1,7 @@
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
from book_list.globals import get_boss
from book_list.globals import get_boss, get_session_data
from book_list.search import SearchPanel
from book_list.top_bar import TopBar
from book_list.views import BooksView
@ -10,6 +10,7 @@ from book_list.prefs import PrefsPanel
from book_list.book_details import BookDetailsPanel
from gettext import gettext as _
from utils import debounce
from modals import error_dialog, ajax_progress_dialog
class BarState:
@ -70,6 +71,17 @@ def create_book_view_top_bar_state(books_view):
def random_book():
get_boss().ui.replace_panel('book-details', extra_query_data={'book-id':'0'})
def change_library_actions():
boss = get_boss()
interface_data = boss.interface_data
ans = []
ans.subtitle = _('Currently showing the library: ') + interface_data.library_map[interface_data.library_id]
for lid in sorted(interface_data.library_map):
if lid != interface_data.library_id:
library_name = interface_data.library_map[lid]
ans.append({'title':library_name, 'action':boss.ui.change_library.bind(boss.ui, lid)})
return ans
class UI:
ROOT_PANEL = 'books'
@ -86,10 +98,18 @@ class UI:
self.current_panel = self.ROOT_PANEL
window.addEventListener('resize', debounce(self.on_resize.bind(self), 250))
self.panel_map['more-actions-menu'] = UIState(ClosePanelBar(_('More actions')), panel_data=[
num_of_libraries = len(interface_data.library_map)
actions = [
create_item(_('Book List Mode'), replace_panel_action('booklist-mode-menu'), _('Change how the list of books is displayed')),
create_item(_('A Random Book'), random_book, _('Choose a random book from your library')),
])
]
if num_of_libraries > 1:
actions.push(
create_item(_('Change Library'), replace_panel_action('booklist-change-library'), _('Choose a different library to display'))
)
self.panel_map['booklist-change-library'] = UIState(ClosePanelBar(_('Change Library')), panel_data=change_library_actions)
self.panel_map['more-actions-menu'] = UIState(ClosePanelBar(_('More actions')), panel_data=actions)
self.panel_map['booklist-mode-menu'] = UIState(ClosePanelBar(_('Book List Mode')), panel_data=[])
@ -164,3 +184,25 @@ class UI:
self.books_view.refresh()
if self.current_panel == self.ROOT_PANEL:
self.top_bar.refresh_left()
def change_library(self, library_id):
data = {'search':'', 'sort':get_session_data().get_library_option(library_id, 'sort'), 'library_id':library_id}
ajax_progress_dialog('interface-data/get-books', self.library_changed.bind(self), _(
'Fetching data from server, please wait') + '…', query=data, extra_data_for_callback={'library_id':library_id})
def library_changed(self, end_type, xhr, ev):
if end_type == 'load':
boss = get_boss()
boss.interface_data.library_id = xhr.extra_data_for_callback.library_id
try:
data = JSON.parse(xhr.responseText)
boss.change_books(data)
except Exception as err:
return error_dialog(_('Could not change library'), err + '', details=err.stack)
self.show_panel(self.ROOT_PANEL)
window.scrollTo(0, 0)
elif end_type != 'abort':
msg = xhr.error_html
error_dialog(_('Could not change library'), msg)

View File

@ -240,7 +240,7 @@ class BooksView:
self.abort_get_more_books()
query = query or ''
sd = get_session_data()
data = {'search':query, 'sort':sd.get('sort'), 'library_id':self.interface_data.library_id}
data = {'search':query, 'sort':sd.get_library_option(self.interface_data.library_id, 'sort'), 'library_id':self.interface_data.library_id}
ajax_progress_dialog('interface-data/get-books', self.search_change_completed.bind(self), _(
'Fetching data from server, please wait') + '…', query=data, extra_data_for_callback={'push_state':push_state, 'panel_to_show': panel_to_show})

View File

@ -128,6 +128,14 @@ class UserSessionData(SessionData):
defval = defaults[key]
return SessionData.get(self, (self.prefix + key), defval)
def get_library_option(self, library_id, key, defval):
if not library_id:
return self.get(key, defval)
lkey = key + '-||-' + library_id
if defval is undefined:
defval = defaults[key]
return self.get(lkey, defval)
def set(self, key, value):
if self.echo_changes and self.has_user:
self.changes[key] = value
@ -137,6 +145,11 @@ class UserSessionData(SessionData):
self.push_timer_id = setTimeout(self.push_to_server.bind(self), 1000)
return SessionData.set(self, (self.prefix + key), value)
def set_library_option(self, library_id, key, value):
if library_id:
key = key + '-||-' + library_id
return self.set(key, value)
def push_to_server(self):
if self.has_changes:
ajax_send('interface-data/set-session-data', self.changes, def(end_type, xhr, ev):

View File

@ -33,14 +33,22 @@ def on_library_load_progress(loaded, total):
def load_book_list():
temp = UserSessionData(None, {}) # So that settings for anonymous users are preserved
query = {k:temp.get(k) for k in str.split('library_id sort')}
query = {}
default_lib = window.calibre_default_library
v'delete window.calibre_default_library'
query.sort = temp.get_library_option(default_lib, 'sort')
library_id = temp.get('library_id')
if library_id:
query.library_id = library_id
url_query = parse_url_params()
for key in url_query:
query[key] = url_query[key]
ajax('interface-data/init', on_library_loaded, on_library_load_progress, query=query).send()
def on_load():
if window.calibre_entry_point == 'book list':
ep = window.calibre_entry_point
v'delete window.calibre_entry_point'
if ep == 'book list':
print('calibre loaded at:', Date().toString())
load_book_list()