mirror of
https://github.com/janeczku/calibre-web
synced 2024-12-25 17:40:31 +00:00
Fix for renaming uppercase/lowercase author, tag, series, publisher entries (fix for #2787)
Update epub.js
This commit is contained in:
commit
eff0750d77
22
cps/db.py
22
cps/db.py
@ -207,6 +207,9 @@ class Tags(Base):
|
|||||||
def get(self):
|
def get(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.name == other
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Tags('{0})>".format(self.name)
|
return "<Tags('{0})>".format(self.name)
|
||||||
|
|
||||||
@ -219,7 +222,7 @@ class Authors(Base):
|
|||||||
sort = Column(String(collation='NOCASE'))
|
sort = Column(String(collation='NOCASE'))
|
||||||
link = Column(String, nullable=False, default="")
|
link = Column(String, nullable=False, default="")
|
||||||
|
|
||||||
def __init__(self, name, sort, link):
|
def __init__(self, name, sort, link=""):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.sort = sort
|
self.sort = sort
|
||||||
self.link = link
|
self.link = link
|
||||||
@ -227,6 +230,9 @@ class Authors(Base):
|
|||||||
def get(self):
|
def get(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.name == other
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Authors('{0},{1}{2}')>".format(self.name, self.sort, self.link)
|
return "<Authors('{0},{1}{2}')>".format(self.name, self.sort, self.link)
|
||||||
|
|
||||||
@ -245,6 +251,9 @@ class Series(Base):
|
|||||||
def get(self):
|
def get(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.name == other
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Series('{0},{1}')>".format(self.name, self.sort)
|
return "<Series('{0},{1}')>".format(self.name, self.sort)
|
||||||
|
|
||||||
@ -261,6 +270,9 @@ class Ratings(Base):
|
|||||||
def get(self):
|
def get(self):
|
||||||
return self.rating
|
return self.rating
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.rating == other
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Ratings('{0}')>".format(self.rating)
|
return "<Ratings('{0}')>".format(self.rating)
|
||||||
|
|
||||||
@ -275,11 +287,14 @@ class Languages(Base):
|
|||||||
self.lang_code = lang_code
|
self.lang_code = lang_code
|
||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
if self.language_name:
|
if hasattr(self, "language_name"):
|
||||||
return self.language_name
|
return self.language_name
|
||||||
else:
|
else:
|
||||||
return self.lang_code
|
return self.lang_code
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.lang_code == other
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Languages('{0}')>".format(self.lang_code)
|
return "<Languages('{0}')>".format(self.lang_code)
|
||||||
|
|
||||||
@ -298,6 +313,9 @@ class Publishers(Base):
|
|||||||
def get(self):
|
def get(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.name == other
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Publishers('{0},{1}')>".format(self.name, self.sort)
|
return "<Publishers('{0},{1}')>".format(self.name, self.sort)
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ from flask_babel import get_locale
|
|||||||
from flask_login import current_user, login_required
|
from flask_login import current_user, login_required
|
||||||
from sqlalchemy.exc import OperationalError, IntegrityError, InterfaceError
|
from sqlalchemy.exc import OperationalError, IntegrityError, InterfaceError
|
||||||
from sqlalchemy.orm.exc import StaleDataError
|
from sqlalchemy.orm.exc import StaleDataError
|
||||||
|
from sqlalchemy.sql.expression import func
|
||||||
|
|
||||||
from . import constants, logger, isoLanguages, gdriveutils, uploader, helper, kobo_sync_status
|
from . import constants, logger, isoLanguages, gdriveutils, uploader, helper, kobo_sync_status
|
||||||
from . import config, ub, db, calibre_db
|
from . import config, ub, db, calibre_db
|
||||||
@ -470,7 +471,7 @@ def get_sorted_entry(field, bookid):
|
|||||||
if field == 'sort':
|
if field == 'sort':
|
||||||
return json.dumps({'sort': book.title})
|
return json.dumps({'sort': book.title})
|
||||||
if field == 'author_sort':
|
if field == 'author_sort':
|
||||||
return json.dumps({'author_sort': book.author})
|
return json.dumps({'authors': " & ".join([a.name for a in calibre_db.order_authors([book])])})
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
@ -1245,18 +1246,18 @@ def handle_title_on_edit(book, book_title):
|
|||||||
|
|
||||||
|
|
||||||
def handle_author_on_edit(book, author_name, update_stored=True):
|
def handle_author_on_edit(book, author_name, update_stored=True):
|
||||||
|
change = False
|
||||||
# handle author(s)
|
# handle author(s)
|
||||||
input_authors, renamed = prepare_authors(author_name)
|
input_authors, renamed = prepare_authors(author_name)
|
||||||
|
|
||||||
change = modify_database_object(input_authors, book.authors, db.Authors, calibre_db.session, 'author')
|
# change |= modify_database_object(input_authors, book.authors, db.Authors, calibre_db.session, 'author')
|
||||||
|
|
||||||
# Search for each author if author is in database, if not, author name and sorted author name is generated new
|
# Search for each author if author is in database, if not, author name and sorted author name is generated new
|
||||||
# everything then is assembled for sorted author field in database
|
# everything then is assembled for sorted author field in database
|
||||||
sort_authors_list = list()
|
sort_authors_list = list()
|
||||||
for inp in input_authors:
|
for inp in input_authors:
|
||||||
stored_author = calibre_db.session.query(db.Authors).filter(db.Authors.name == inp).first()
|
stored_author = calibre_db.session.query(db.Authors).filter(db.Authors.name == inp).first()
|
||||||
if not stored_author:
|
if not stored_author:
|
||||||
stored_author = helper.get_sorted_author(inp)
|
stored_author = helper.get_sorted_author(inp.replace('|', ','))
|
||||||
else:
|
else:
|
||||||
stored_author = stored_author.sort
|
stored_author = stored_author.sort
|
||||||
sort_authors_list.append(helper.get_sorted_author(stored_author))
|
sort_authors_list.append(helper.get_sorted_author(stored_author))
|
||||||
@ -1264,6 +1265,9 @@ def handle_author_on_edit(book, author_name, update_stored=True):
|
|||||||
if book.author_sort != sort_authors and update_stored:
|
if book.author_sort != sort_authors and update_stored:
|
||||||
book.author_sort = sort_authors
|
book.author_sort = sort_authors
|
||||||
change = True
|
change = True
|
||||||
|
|
||||||
|
change |= modify_database_object(input_authors, book.authors, db.Authors, calibre_db.session, 'author')
|
||||||
|
|
||||||
return input_authors, change, renamed
|
return input_authors, change, renamed
|
||||||
|
|
||||||
|
|
||||||
@ -1271,14 +1275,15 @@ def search_objects_remove(db_book_object, db_type, input_elements):
|
|||||||
del_elements = []
|
del_elements = []
|
||||||
for c_elements in db_book_object:
|
for c_elements in db_book_object:
|
||||||
found = False
|
found = False
|
||||||
if db_type == 'languages':
|
#if db_type == 'languages':
|
||||||
type_elements = c_elements.lang_code
|
# type_elements = c_elements.lang_code
|
||||||
elif db_type == 'custom':
|
if db_type == 'custom':
|
||||||
type_elements = c_elements.value
|
type_elements = c_elements.value
|
||||||
else:
|
else:
|
||||||
type_elements = c_elements.name
|
# type_elements = c_elements.name
|
||||||
|
type_elements = c_elements
|
||||||
for inp_element in input_elements:
|
for inp_element in input_elements:
|
||||||
if inp_element.lower() == type_elements.lower():
|
if type_elements == inp_element:
|
||||||
found = True
|
found = True
|
||||||
break
|
break
|
||||||
# if the element was not found in the new list, add it to remove list
|
# if the element was not found in the new list, add it to remove list
|
||||||
@ -1292,13 +1297,11 @@ def search_objects_add(db_book_object, db_type, input_elements):
|
|||||||
for inp_element in input_elements:
|
for inp_element in input_elements:
|
||||||
found = False
|
found = False
|
||||||
for c_elements in db_book_object:
|
for c_elements in db_book_object:
|
||||||
if db_type == 'languages':
|
if db_type == 'custom':
|
||||||
type_elements = c_elements.lang_code
|
|
||||||
elif db_type == 'custom':
|
|
||||||
type_elements = c_elements.value
|
type_elements = c_elements.value
|
||||||
else:
|
else:
|
||||||
type_elements = c_elements.name
|
type_elements = c_elements
|
||||||
if inp_element == type_elements:
|
if type_elements == inp_element:
|
||||||
found = True
|
found = True
|
||||||
break
|
break
|
||||||
if not found:
|
if not found:
|
||||||
@ -1314,6 +1317,7 @@ def remove_objects(db_book_object, db_session, del_elements):
|
|||||||
changed = True
|
changed = True
|
||||||
if len(del_element.books) == 0:
|
if len(del_element.books) == 0:
|
||||||
db_session.delete(del_element)
|
db_session.delete(del_element)
|
||||||
|
db_session.flush()
|
||||||
return changed
|
return changed
|
||||||
|
|
||||||
|
|
||||||
@ -1327,10 +1331,14 @@ def add_objects(db_book_object, db_object, db_session, db_type, add_elements):
|
|||||||
db_filter = db_object.name
|
db_filter = db_object.name
|
||||||
for add_element in add_elements:
|
for add_element in add_elements:
|
||||||
# check if an element with that name exists
|
# check if an element with that name exists
|
||||||
db_element = db_session.query(db_object).filter(db_filter == add_element).first()
|
changed = True
|
||||||
|
# db_session.query(db.Tags).filter((func.lower(db.Tags.name).ilike("GênOt"))).all()
|
||||||
|
db_element = db_session.query(db_object).filter((func.lower(db_filter).ilike(add_element))).first()
|
||||||
|
# db_element = db_session.query(db_object).filter(func.lower(db_filter) == add_element.lower()).first()
|
||||||
# if no element is found add it
|
# if no element is found add it
|
||||||
|
if db_element is None:
|
||||||
if db_type == 'author':
|
if db_type == 'author':
|
||||||
new_element = db_object(add_element, helper.get_sorted_author(add_element.replace('|', ',')), "")
|
new_element = db_object(add_element, helper.get_sorted_author(add_element.replace('|', ',')))
|
||||||
elif db_type == 'series':
|
elif db_type == 'series':
|
||||||
new_element = db_object(add_element, add_element)
|
new_element = db_object(add_element, add_element)
|
||||||
elif db_type == 'custom':
|
elif db_type == 'custom':
|
||||||
@ -1339,15 +1347,18 @@ def add_objects(db_book_object, db_object, db_session, db_type, add_elements):
|
|||||||
new_element = db_object(add_element, None)
|
new_element = db_object(add_element, None)
|
||||||
else: # db_type should be tag or language
|
else: # db_type should be tag or language
|
||||||
new_element = db_object(add_element)
|
new_element = db_object(add_element)
|
||||||
if db_element is None:
|
|
||||||
changed = True
|
|
||||||
db_session.add(new_element)
|
db_session.add(new_element)
|
||||||
db_book_object.append(new_element)
|
db_book_object.append(new_element)
|
||||||
|
else:
|
||||||
|
db_no_case = db_session.query(db_object).filter(db_filter == add_element).first()
|
||||||
|
if db_no_case:
|
||||||
|
# check for new case of element
|
||||||
|
db_element = create_objects_for_addition(db_element, add_element, db_type)
|
||||||
else:
|
else:
|
||||||
db_element = create_objects_for_addition(db_element, add_element, db_type)
|
db_element = create_objects_for_addition(db_element, add_element, db_type)
|
||||||
# add element to book
|
# add element to book
|
||||||
changed = True
|
|
||||||
db_book_object.append(db_element)
|
db_book_object.append(db_element)
|
||||||
|
|
||||||
return changed
|
return changed
|
||||||
|
|
||||||
|
|
||||||
@ -1382,13 +1393,24 @@ def modify_database_object(input_elements, db_book_object, db_object, db_session
|
|||||||
if not isinstance(input_elements, list):
|
if not isinstance(input_elements, list):
|
||||||
raise TypeError(str(input_elements) + " should be passed as a list")
|
raise TypeError(str(input_elements) + " should be passed as a list")
|
||||||
input_elements = [x for x in input_elements if x != '']
|
input_elements = [x for x in input_elements if x != '']
|
||||||
|
|
||||||
|
changed = False
|
||||||
|
# If elements are renamed (upper lower case), rename it
|
||||||
|
for rec_a, rec_b in zip(db_book_object, input_elements):
|
||||||
|
if db_type == "custom":
|
||||||
|
if rec_a.value.casefold() == rec_b.casefold() and rec_a.value != rec_b:
|
||||||
|
create_objects_for_addition(rec_a, rec_b, db_type)
|
||||||
|
else:
|
||||||
|
if rec_a.get().casefold() == rec_b.casefold() and rec_a.get() != rec_b:
|
||||||
|
create_objects_for_addition(rec_a, rec_b, db_type)
|
||||||
# we have all input element (authors, series, tags) names now
|
# we have all input element (authors, series, tags) names now
|
||||||
# 1. search for elements to remove
|
# 1. search for elements to remove
|
||||||
del_elements = search_objects_remove(db_book_object, db_type, input_elements)
|
del_elements = search_objects_remove(db_book_object, db_type, input_elements)
|
||||||
# 2. search for elements that need to be added
|
# 2. search for elements that need to be added
|
||||||
add_elements = search_objects_add(db_book_object, db_type, input_elements)
|
add_elements = search_objects_add(db_book_object, db_type, input_elements)
|
||||||
|
|
||||||
# if there are elements to remove, we remove them now
|
# if there are elements to remove, we remove them now
|
||||||
changed = remove_objects(db_book_object, db_session, del_elements)
|
changed |= remove_objects(db_book_object, db_session, del_elements)
|
||||||
# if there are elements to add, we add them now!
|
# if there are elements to add, we add them now!
|
||||||
if len(add_elements) > 0:
|
if len(add_elements) > 0:
|
||||||
changed |= add_objects(db_book_object, db_object, db_session, db_type, add_elements)
|
changed |= add_objects(db_book_object, db_object, db_session, db_type, add_elements)
|
||||||
|
2
cps/static/js/libs/epub.min.js
vendored
2
cps/static/js/libs/epub.min.js
vendored
File diff suppressed because one or more lines are too long
@ -61,7 +61,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="author_div" class="form-group">
|
<div id="author_div" class="form-group">
|
||||||
<label for="bookAuthor">{{_('Author')}}</label>
|
<label for="bookAuthor">{{_('Author')}}</label>
|
||||||
<input type="text" class="form-control typeahead" name="author_name" id="bookAuthor" value="{{' & '.join(authors)}}" autocomplete="off">
|
<input type="text" class="form-control typeahead" autocomplete="off" name="author_name" id="bookAuthor" value="{{' & '.join(authors)}}">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@ -85,11 +85,11 @@
|
|||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="tags">{{_('Tags')}}</label>
|
<label for="tags">{{_('Tags')}}</label>
|
||||||
<input type="text" class="form-control typeahead" name="tags" id="tags" value="{% for tag in book.tags %}{{tag.name.strip()}}{% if not loop.last %}, {% endif %}{% endfor %}">
|
<input type="text" class="form-control typeahead" autocomplete="off" name="tags" id="tags" value="{% for tag in book.tags %}{{tag.name.strip()}}{% if not loop.last %}, {% endif %}{% endfor %}">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="series">{{_('Series')}}</label>
|
<label for="series">{{_('Series')}}</label>
|
||||||
<input type="text" class="form-control typeahead" name="series" id="series" value="{% if book.series %}{{book.series[0].name}}{% endif %}">
|
<input type="text" class="form-control typeahead" autocomplete="off" name="series" id="series" value="{% if book.series %}{{book.series[0].name}}{% endif %}">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="series_index">{{_('Series ID')}}</label>
|
<label for="series_index">{{_('Series ID')}}</label>
|
||||||
@ -120,11 +120,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="publisher">{{_('Publisher')}}</label>
|
<label for="publisher">{{_('Publisher')}}</label>
|
||||||
<input type="text" class="form-control typeahead" name="publisher" id="publisher" value="{% if book.publishers|length > 0 %}{{book.publishers[0].name}}{% endif %}">
|
<input type="text" class="form-control typeahead" autocomplete="off" name="publisher" id="publisher" value="{% if book.publishers|length > 0 %}{{book.publishers[0].name}}{% endif %}">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="languages">{{_('Language')}}</label>
|
<label for="languages">{{_('Language')}}</label>
|
||||||
<input type="text" class="form-control typeahead" name="languages" id="languages" value="{% for language in book.languages %}{{language.language_name.strip()}}{% if not loop.last %}, {% endif %}{% endfor %}">
|
<input type="text" class="form-control typeahead" autocomplete="off" name="languages" id="languages" value="{% for language in book.languages %}{{language.language_name.strip()}}{% if not loop.last %}, {% endif %}{% endfor %}">
|
||||||
</div>
|
</div>
|
||||||
{% if cc|length > 0 %}
|
{% if cc|length > 0 %}
|
||||||
{% for c in cc %}
|
{% for c in cc %}
|
||||||
|
Loading…
Reference in New Issue
Block a user