mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Content server viewer: Allow editing metadata from the view metadata panel
Fixes #1890755
This commit is contained in:
parent
e304300fc6
commit
1867cadd5c
@ -15,6 +15,7 @@ from book_list.comments_editor import (
|
||||
create_comments_editor, focus_comments_editor, get_comments_html,
|
||||
set_comments_html
|
||||
)
|
||||
from book_list.globals import get_current_query
|
||||
from book_list.library_data import (
|
||||
book_metadata, cover_url, current_library_id, field_names_for, library_data,
|
||||
load_status, loaded_book_ids, set_book_metadata
|
||||
@ -937,8 +938,15 @@ def changes_submitted(container_id, book_id, end_type, xhr, ev):
|
||||
error_dialog(_('Could not update metadata for book'), _('Server returned an invalid response'), err.toString())
|
||||
return
|
||||
|
||||
for bid in dirtied:
|
||||
set_book_metadata(bid, dirtied[book_id])
|
||||
cq = get_current_query()
|
||||
if cq.from_read_book and window.opener:
|
||||
window.opener.postMessage(
|
||||
{'type': 'update_cached_book_metadata', 'library_id': cq.library_id, 'book_id': cq.book_id, 'metadata': dirtied[book_id], 'from_read_book': cq.from_read_book},
|
||||
document.location.protocol + '//' + document.location.host
|
||||
)
|
||||
else:
|
||||
for bid in dirtied:
|
||||
set_book_metadata(bid, dirtied[bid])
|
||||
on_close(container_id)
|
||||
|
||||
|
||||
@ -994,7 +1002,10 @@ def on_close(container_id):
|
||||
q = parse_url_params()
|
||||
show_book(container_id, int(q.book_id))
|
||||
return
|
||||
back()
|
||||
if get_current_query().from_read_book:
|
||||
window.close()
|
||||
else:
|
||||
back()
|
||||
|
||||
|
||||
def proceed_after_succesful_fetch_metadata(container_id, book_id):
|
||||
@ -1054,6 +1065,18 @@ def init(container_id):
|
||||
container.lastChild.focus()
|
||||
container.lastChild.appendChild(E.div(_('Loading books from the calibre library, please wait...'), style='margin: 1ex 1em'))
|
||||
conditional_timeout(container_id, 5, check_for_books_loaded)
|
||||
cq = get_current_query()
|
||||
if cq.from_read_book:
|
||||
window.opener.postMessage(
|
||||
{'type': 'edit_metadata_opened', 'library_id': cq.library_id, 'book_id': cq.book_id, 'from_read_book': cq.from_read_book},
|
||||
document.location.protocol + '//' + document.location.host
|
||||
)
|
||||
window.addEventListener('unload', def (ev):
|
||||
window.opener.postMessage(
|
||||
{'type': 'edit_metadata_closed', 'from_read_book': cq.from_read_book},
|
||||
document.location.protocol + '//' + document.location.host
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
set_panel_handler('edit_metadata', init)
|
||||
|
@ -297,6 +297,12 @@ class DB:
|
||||
book.last_read[unkey] = book.recent_date = now
|
||||
self.do_op(['books'], book, _('Failed to write to the books database'), op='put')
|
||||
|
||||
def update_metadata(self, book, new_metadata):
|
||||
if book.metadata:
|
||||
for key in Object.keys(new_metadata):
|
||||
book.metadata[key] = new_metadata[key]
|
||||
self.do_op(['books'], book, _('Failed to write to the books database'), op='put')
|
||||
|
||||
def update_annotations_data_from_key(self, library_id, book_id, fmt, new_data):
|
||||
unkey = username_key(get_interface_data().username)
|
||||
self.get_book(library_id, book_id, fmt, None, def(book):
|
||||
|
@ -4,12 +4,16 @@ from __python__ import bound_methods, hash_literals
|
||||
|
||||
from elementmaker import E
|
||||
from gettext import gettext as _
|
||||
from uuid import short_uuid
|
||||
|
||||
from book_list.book_details import CLASS_NAME as BD_CLASS_NAME, render_metadata
|
||||
from book_list.globals import get_session_data
|
||||
from book_list.library_data import sync_library_books
|
||||
from book_list.library_data import (
|
||||
current_library_id, set_book_metadata, sync_library_books
|
||||
)
|
||||
from book_list.router import home
|
||||
from book_list.theme import get_color
|
||||
from book_list.ui import query_as_href
|
||||
from dom import add_extra_css, build_rule, clear, set_css, svgicon, unique_id
|
||||
from modals import error_dialog
|
||||
from read_book.globals import runtime, ui_operations
|
||||
@ -665,10 +669,44 @@ class Overlay:
|
||||
|
||||
def show_metadata(self):
|
||||
self.hide_current_panel()
|
||||
from_read_book = short_uuid()
|
||||
|
||||
def show_metadata_overlay(mi, pathtoebook, overlay, container):
|
||||
container.appendChild(E.div(class_=BD_CLASS_NAME, style='padding: 1ex 1em'))
|
||||
def show_metadata_overlay(mi, pathtoebook, lname, book_id, overlay, container):
|
||||
container.appendChild(E.div(class_=BD_CLASS_NAME, style='padding: 1ex 1em', id=from_read_book))
|
||||
table = E.table(class_='metadata')
|
||||
|
||||
def handle_message(msg):
|
||||
data = msg.data
|
||||
if data.from_read_book is not from_read_book:
|
||||
return
|
||||
if data.type is 'edit_metadata_opened':
|
||||
if document.getElementById(from_read_book) and self.panels.length and self.panels[-1].from_read_book is from_read_book:
|
||||
self.hide_current_panel()
|
||||
return
|
||||
if data.type is 'edit_metadata_closed':
|
||||
ui_operations.stop_waiting_for_messages_from(this)
|
||||
return
|
||||
if data.type is 'update_cached_book_metadata' and data.metadata:
|
||||
if current_library_id() is data.library_id:
|
||||
mi = data.metadata
|
||||
book_id = int(data.book_id)
|
||||
set_book_metadata(book_id, mi)
|
||||
book = self.view.book
|
||||
if book and book.key[0] is data.library_id and book.key[1] is book_id:
|
||||
ui_operations.update_metadata(book, mi)
|
||||
|
||||
if not runtime.is_standalone_viewer and lname:
|
||||
|
||||
container.lastChild.appendChild(E.div(
|
||||
style='text-align: right',
|
||||
E.a(_('Edit metadata of book in library'), class_='blue-link', onclick=def():
|
||||
w = window.open(query_as_href({
|
||||
'from_read_book': from_read_book, 'library_id': lname, 'book_id': book_id + ''}, 'edit_metadata')
|
||||
, '_blank'
|
||||
)
|
||||
ui_operations.wait_for_messages_from(w, handle_message.bind(w))
|
||||
)
|
||||
))
|
||||
container.lastChild.appendChild(table)
|
||||
render_metadata(mi, table, None, f'html {{ font-size: {document.documentElement.style.fontSize} }}')
|
||||
for a in table.querySelectorAll('a[href]'):
|
||||
@ -680,7 +718,13 @@ class Overlay:
|
||||
style='margin-top: 1ex; padding-top: 1ex; border-top: solid 1px',
|
||||
_('Path: {}').format(pathtoebook)))
|
||||
|
||||
self.panels.push(SimpleOverlay(self, show_metadata_overlay.bind(None, self.view.book.metadata, self.view.book.manifest.pathtoebook), self.view.book.metadata.title))
|
||||
book = self.view.book
|
||||
key = book.key or v'[null, 0]'
|
||||
lname, book_id = key
|
||||
book_id = int(book_id or 0)
|
||||
panel = SimpleOverlay(self, show_metadata_overlay.bind(None, book.metadata, book.manifest.pathtoebook, lname, book_id), self.view.book.metadata.title)
|
||||
panel.from_read_book = from_read_book
|
||||
self.panels.push(panel)
|
||||
self.show_current_panel()
|
||||
|
||||
def show_ask_for_location(self):
|
||||
|
@ -53,7 +53,9 @@ class ReadUI:
|
||||
id=self.display_id, style='display:none',
|
||||
))
|
||||
self.view = View(container.lastChild)
|
||||
self.windows_to_listen_for_messages_from = []
|
||||
window.addEventListener('resize', debounce(self.on_resize.bind(self), 250))
|
||||
window.addEventListener('message', self.message_from_other_window.bind(self))
|
||||
self.db = get_db(self.db_initialized.bind(self), self.show_error.bind(self))
|
||||
ui_operations.get_file = self.db.get_file
|
||||
ui_operations.get_mathjax_files = self.db.get_mathjax_files
|
||||
@ -75,6 +77,9 @@ class ReadUI:
|
||||
ui_operations.toggle_full_screen = self.toggle_full_screen.bind(self)
|
||||
ui_operations.highlights_changed = self.highlights_changed.bind(self)
|
||||
ui_operations.annotations_synced = self.annotations_synced.bind(self)
|
||||
ui_operations.wait_for_messages_from = self.wait_for_messages_from.bind(self)
|
||||
ui_operations.stop_waiting_for_messages_from = self.stop_waiting_for_messages_from.bind(self)
|
||||
ui_operations.update_metadata = self.update_metadata.bind(self)
|
||||
ui_operations.open_url = def(url):
|
||||
window.open(url, '_blank')
|
||||
ui_operations.copy_selection = def(text):
|
||||
@ -534,3 +539,21 @@ class ReadUI:
|
||||
|
||||
def update_url_state(self, replace):
|
||||
push_state(self.url_data, replace=replace, mode=read_book_mode)
|
||||
|
||||
def update_metadata(self, book, metadata):
|
||||
self.db.update_metadata(book, metadata)
|
||||
|
||||
def wait_for_messages_from(self, w, callback):
|
||||
self.windows_to_listen_for_messages_from.push(v'[w, callback]')
|
||||
|
||||
def stop_waiting_for_messages_from(self, w):
|
||||
self.windows_to_listen_for_messages_from = [x for x in self.windows_to_listen_for_messages_from if x[0] is not w]
|
||||
|
||||
def message_from_other_window(self, msg):
|
||||
if not self.windows_to_listen_for_messages_from.length:
|
||||
return
|
||||
old = self.windows_to_listen_for_messages_from
|
||||
for x in old:
|
||||
w, callback = x
|
||||
if w is msg.source:
|
||||
callback(msg)
|
||||
|
Loading…
x
Reference in New Issue
Block a user