Content server: When clicking on author names in the book details page perform the same action as clicking it in the calibre program's book details panel

This commit is contained in:
Kovid Goyal 2025-02-08 12:32:52 +05:30
parent ae15a85e73
commit 0efd8c7b6d
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 61 additions and 10 deletions

View File

@ -15,10 +15,11 @@ from calibre import as_unicode
from calibre.constants import in_develop_mode
from calibre.customize.ui import available_input_formats
from calibre.db.view import sanitize_sort_field_name
from calibre.ebooks.metadata.book.render import resolve_default_author_link
from calibre.srv.ajax import search_result
from calibre.srv.errors import BookNotFound, HTTPBadRequest, HTTPForbidden, HTTPNotFound, HTTPRedirect
from calibre.srv.errors import BookNotFound, HTTPBadRequest, HTTPForbidden, HTTPNotFound, HTTPRedirect, HTTPTempRedirect
from calibre.srv.last_read import last_read_cache
from calibre.srv.metadata import book_as_json, categories_as_json, categories_settings, icon_map
from calibre.srv.metadata import book_as_json, categories_as_json, categories_settings, get_gpref, icon_map, web_search_link
from calibre.srv.routes import endpoint, json
from calibre.srv.utils import get_library_data, get_use_roman
from calibre.utils.config import prefs, tweaks
@ -172,6 +173,7 @@ def basic_interface_data(ctx, rd):
'default_book_list_mode': rd.opts.book_list_mode,
'donate_link': localize_website_link('https://calibre-ebook.com/donate'),
'lang_code_for_user_manual': lang_code_for_user_manual(),
'default_author_link': resolve_default_author_link(get_gpref('default_author_link')),
}
ans['library_map'], ans['default_library_id'] = ctx.library_info(rd)
if ans['username']:
@ -419,6 +421,29 @@ def book_metadata(ctx, rd, book_id):
return data
@endpoint('/web-search/{book_id}/{field}/{item_val}', postprocess=json)
def web_search(ctx, rd, book_id, field, item_val):
'''
Redirect to a web search URL for the specified item.
Optional: ?library_id=<default library>
'''
db, library_id = get_library_data(ctx, rd)[:2]
try:
book_id = int(book_id)
except Exception:
raise HTTPNotFound(f'Book with id {book_id!r} does not exist')
if db is None:
raise HTTPNotFound(f'Library {library_id!r} not found')
with db.safe_read_lock:
if not ctx.has_id(rd, db, book_id):
raise BookNotFound(book_id, db)
mi = db.get_metadata(book_id, get_cover=False)
url, tooltip = web_search_link(db, book_id, field, item_val)
if url:
raise HTTPTempRedirect(url)
raise HTTPNotFound(f'No web search URL for {field} {item_val}')
@endpoint('/interface-data/tag-browser')
def tag_browser(ctx, rd):
'''

View File

@ -32,6 +32,12 @@ class HTTPRedirect(HTTPSimpleResponse):
HTTPSimpleResponse.__init__(self, http_code, http_message, close_connection, location)
class HTTPTempRedirect(HTTPSimpleResponse):
def __init__(self, location, http_code=http_client.TEMPORARY_REDIRECT, http_message='', close_connection=False):
HTTPSimpleResponse.__init__(self, http_code, http_message, close_connection, location)
class HTTPNotFound(HTTPSimpleResponse):
def __init__(self, http_message='', close_connection=False):

View File

@ -12,7 +12,7 @@ from book_list.item_list import create_item, create_item_list, create_side_actio
from book_list.library_data import (
all_libraries, book_after, book_metadata, cover_url, current_library_id,
current_virtual_library, download_url, library_data, load_status,
set_book_metadata, download_data_file_url
set_book_metadata, download_data_file_url, web_search_url
)
from book_list.router import back, home, open_book, report_a_load_failure, show_note, open_book_url_in_library, search_url_in_library
from book_list.theme import (
@ -286,18 +286,33 @@ def render_metadata(mi, table, book_id, iframe_css): # {{{
v += ''
parent = table.lastChild.lastChild
if is_searchable:
websearch_link = False
if field is 'authors':
websearch_link = bool(interface_data.default_author_link) and interface_data.default_author_link is not 'search-calibre'
text_rep = search_text or v
parent.appendChild(E.a(
v,
title=_('Click to see books with {0}: {1}').format(name, text_rep), class_='blue-link',
href=href_for_search(is_searchable, text_rep, use_quotes=use_quotes)
))
target = '_self'
if websearch_link and jstype(v) is not 'string':
websearch_link = False
calibre_search_url = href_for_search(is_searchable, text_rep, use_quotes=use_quotes)
calibre_search_tooltip = _('Click to see books with {0}: {1}').format(name, text_rep)
if websearch_link:
url = web_search_url(book_id, field, v)
target = '_blank'
tooltip = _('Click to browse for {} on the web').format(text_rep)
else:
url = calibre_search_url
tooltip = calibre_search_tooltip
parent.appendChild(E.a(v, target=target, title=tooltip, class_='blue-link', href=url))
if link_maps[field] and link_maps[field][text_rep]:
url = link_maps[field][text_rep]
if url.startswith('https://') or url.startswith('http://'):
parent.appendChild(document.createTextNode(' '))
parent.appendChild(E.a(
svgicon('external-link'), title=_('Click to open') + ': ' + url, href=url, target='_new', class_='blue-link'))
svgicon('external-link'), title=_('Click to open') + ': ' + url, href=url, target='_blank', class_='blue-link'))
if websearch_link:
parent.appendChild(document.createTextNode(' '))
parent.appendChild(E.a(
svgicon('search'), title=calibre_search_tooltip, href=calibre_search_url, class_='blue-link'))
else:
if v.appendChild:
parent.appendChild(v)

View File

@ -99,7 +99,7 @@ def create_item(book_id, metadata, create_image, show_book_details, href):
ival = fmt_sidx(ival, use_roman=interface_data.use_roman_numerals_for_series_number)
extra_data.appendChild(safe_set_inner_html(E.span(), _('{0} of <i>{1}</i>').format(ival, metadata.series)))
right = E.div(
class_='details-list-right',
class_='details-list-right',
E.div(style='display:flex; justify-content: space-between; overflow: hidden',
E.div(
E.b(metadata.title or _('Unknown')), E.br(), authors,

View File

@ -233,6 +233,10 @@ def download_data_file_url(book_id, relpath, content_disposition):
return ans
def web_search_url(book_id, field, item_val):
return absolute_path(f'web-search/{book_id}/{encodeURIComponent(field)}/{encodeURIComponent(item_val)}?library_id={encodeURIComponent(current_library_id())}')
def book_metadata(book_id):
return library_data.metadata[book_id]

View File

@ -313,6 +313,7 @@ default_interface_data = {
'library_map': None,
'search_the_net_urls': [],
'donate_link': 'https://calibre-ebook.com/donate',
'default_author_link': '',
'icon_map': {},
'icon_path': '',
'custom_list_template': None,