Bugfix Publisher (upper/lower case, remove publisher, publisher visibility on new users)

404 messages on non existing categorys, languages, series
Updated Testresult
This commit is contained in:
Ozzieisaacs
2018-10-28 21:33:12 +01:00
15 changed files with 8419 additions and 8476 deletions
+25
View File
@@ -142,6 +142,17 @@ var languages = new Bloodhound({
}
});
var publishers = new Bloodhound({
name: "publisher",
datumTokenizer: function datumTokenizer(datum) {
return [datum.name];
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: getPath() + "/get_publishers_json?q=%QUERY"
}
});
function sourceSplit(query, cb, split, source) {
var bhAdapter = source.ttAdapter();
@@ -224,6 +235,20 @@ promiseLanguages.done(function() {
);
});
var promisePublishers = publishers.initialize();
promisePublishers.done(function() {
$("#publisher").typeahead(
{
highlight: true, minLength: 0,
hint: true
}, {
name: "publishers",
displayKey: "name",
source: publishers.ttAdapter()
}
);
});
$("#search").on("change input.typeahead:selected", function() {
var form = $("form").serialize();
$.getJSON( getPath() + "/get_matching_tags", form, function( data ) {
+1 -1
View File
@@ -101,7 +101,7 @@
</div>
<div class="form-group">
<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 %}" disabled>
<input type="text" class="form-control typeahead" name="publisher" id="publisher" value="{% if book.publishers|length > 0 %}{{book.publishers[0].name}}{% endif %}">
</div>
<div class="form-group">
<label for="languages">{{_('Language')}}</label>
+4
View File
@@ -143,6 +143,10 @@
<input type="checkbox" name="show_author" id="show_author" {% if content.show_author() %}checked{% endif %}>
<label for="show_author">{{_('Show author selection')}}</label>
</div>
<div class="form-group">
<input type="checkbox" name="show_publisher" id="show_publisher" {% if content.show_publisher() %}checked{% endif %}>
<label for="show_publisher">{{_('Show publisher selection')}}</label>
</div>
<div class="form-group">
<input type="checkbox" name="show_read_and_unread" id="show_read_and_unread" {% if content.show_read_and_unread() %}checked{% endif %}>
<label for="show_read_and_unread">{{_('Show read and unread')}}</label>
+7 -3
View File
@@ -120,13 +120,17 @@
</div>
{% endif %}
{% if entry.publishers|length > 0 %}
<div class="publishers">
<p>
<span>{{_('Publisher')}}:{% for publisher in entry.publishers %} {{publisher.name}}{% if not loop.last %},{% endif %}{% endfor %}</span>
</p>
<p>
<span>{{_('Publisher')}}:
<a href="{{url_for('publisher', book_id=entry.publishers[0].id ) }}">{{entry.publishers[0].name}}</a>
</span>
</p>
</div>
{% endif %}
{% if entry.pubdate[:10] != '0101-01-01' %}
<p>{{_('Publishing date')}}: {{entry.pubdate|formatdate}} </p>
{% endif %}
+3
View File
@@ -43,6 +43,9 @@
<author>
<name>{{entry.authors[0].name}}</name>
</author>
<publisher>
<name>{{entry.publishers[0].name}}</name>
</publisher>
<dcterms:language>{{entry.language}}</dcterms:language>
{% for tag in entry.tags %}
<category scheme="http://www.bisg.org/standards/bisac_subject/index.html"
+20 -13
View File
@@ -39,7 +39,7 @@
<updated>{{ current_time }}</updated>
<content type="text">{{_('Show Random Books')}}</content>
</entry>
{% if not current_user.is_anonymous %}
{% if not current_user.is_anonymous %}
<entry>
<title>{{_('Read Books')}}</title>
<link rel="subsection" href="{{url_for('feed_read_books')}}" type="application/atom+xml;profile=opds-catalog"/>
@@ -47,7 +47,7 @@
<updated>{{ current_time }}</updated>
<content type="text">{{_('Read Books')}}</content>
</entry>
{% endif %}
{% endif %}
<entry>
<title>{{_('Unread Books')}}</title>
<link rel="subsection" href="{{url_for('feed_unread_books')}}" type="application/atom+xml;profile=opds-catalog"/>
@@ -61,35 +61,42 @@
<id>{{url_for('feed_authorindex')}}</id>
<updated>{{ current_time }}</updated>
<content type="text">{{_('Books ordered by Author')}}</content>
</entry>
<entry>
</entry>
<entry>
<title>{{_('Publishers')}}</title>
<link rel="subsection" href="{{url_for('feed_publisherindex')}}" type="application/atom+xml;profile=opds-catalog"/>
<id>{{url_for('feed_publisherindex')}}</id>
<updated>{{ current_time }}</updated>
<content type="text">{{_('Books ordered by publisher')}}</content>
</entry>
<entry>
<title>{{_('Category list')}}</title>
<link rel="subsection" href="{{url_for('feed_categoryindex')}}" type="application/atom+xml;profile=opds-catalog"/>
<id>{{url_for('feed_categoryindex')}}</id>
<updated>{{ current_time }}</updated>
<content type="text">{{_('Books ordered by category')}}</content>
</entry>
<entry>
</entry>
<entry>
<title>{{_('Series list')}}</title>
<link rel="subsection" href="{{url_for('feed_seriesindex')}}" type="application/atom+xml;profile=opds-catalog"/>
<id>{{url_for('feed_seriesindex')}}</id>
<updated>{{ current_time }}</updated>
<content type="text">{{_('Books ordered by series')}}</content>
</entry>
<entry>
</entry>
<entry>
<title>{{_('Public Shelves')}}</title>
<link rel="subsection" href="{{url_for('feed_shelfindex', public="public")}}" type="application/atom+xml;profile=opds-catalog"/>
<id>{{url_for('feed_shelfindex', public="public")}}</id>
<updated>{{ current_time }}</updated>
<content type="text">{{_('Books organized in public shelfs, visible to everyone')}}</content>
</entry>
{% if not current_user.is_anonymous %}
<entry>
</entry>
{% if not current_user.is_anonymous %}
<entry>
<title>{{_('Your Shelves')}}</title>
<link rel="subsection" href="{{url_for('feed_shelfindex')}}" type="application/atom+xml;profile=opds-catalog"/>
<id>{{url_for('feed_shelfindex')}}</id>
<updated>{{ current_time }}</updated>
<content type="text">{{_("User's own shelfs, only visible to the current user himself")}}</content>
</entry>
{% endif %}
</entry>
{% endif %}
</feed>
+3
View File
@@ -159,6 +159,9 @@
{% if g.user.show_author() %}
<li id="nav_author" {% if page == 'author' %}class="active"{% endif %}><a href="{{url_for('author_list')}}"><span class="glyphicon glyphicon-user"></span>{{_('Authors')}}</a></li>
{%endif%}
{% if g.user.show_publisher() %}
<li id="nav_publisher" {% if page == 'publisher' %}class="active"{% endif %}><a href="{{url_for('publisher_list')}}"><span class="glyphicon glyphicon-text-size"></span>{{_('Publishers')}}</a></li>
{%endif%}
{% if g.user.filter_language() == 'all' and g.user.show_language() %}
<li id="nav_lang" {% if page == 'language' %}class="active"{% endif %}><a href="{{url_for('language_overview')}}"><span class="glyphicon glyphicon-flag"></span>{{_('Languages')}} </a></li>
{%endif%}
+4
View File
@@ -89,6 +89,10 @@
<input type="checkbox" name="show_author" id="show_author" {% if content.show_author() %}checked{% endif %}>
<label for="show_author">{{_('Show author selection')}}</label>
</div>
<div class="form-group">
<input type="checkbox" name="show_publisher" id="show_publisher" {% if content.show_publisher() %}checked{% endif %}>
<label for="show_publisher">{{_('Show publisher selection')}}</label>
</div>
<div class="form-group">
<input type="checkbox" name="show_read_and_unread" id="show_read_and_unread" {% if content.show_read_and_unread() %}checked{% endif %}>
<label for="show_read_and_unread">{{_('Show read and unread')}}</label>
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
+10 -2
View File
@@ -41,6 +41,7 @@ SIDEBAR_READ_AND_UNREAD = 256
SIDEBAR_RECENT = 512
SIDEBAR_SORTED = 1024
MATURE_CONTENT = 2048
SIDEBAR_PUBLISHER = 4096
DEFAULT_PASS = "admin123"
DEFAULT_PORT = int(os.environ.get("CALIBRE_PORT", 8083))
@@ -136,6 +137,9 @@ class UserBase:
def show_author(self):
return bool((self.sidebar_view is not None)and(self.sidebar_view & SIDEBAR_AUTHOR == SIDEBAR_AUTHOR))
def show_publisher(self):
return bool((self.sidebar_view is not None)and(self.sidebar_view & SIDEBAR_PUBLISHER == SIDEBAR_PUBLISHER))
def show_best_rated_books(self):
return bool((self.sidebar_view is not None)and(self.sidebar_view & SIDEBAR_BEST_RATED == SIDEBAR_BEST_RATED))
@@ -297,7 +301,7 @@ class Settings(Base):
config_anonbrowse = Column(SmallInteger, default=0)
config_public_reg = Column(SmallInteger, default=0)
config_default_role = Column(SmallInteger, default=0)
config_default_show = Column(SmallInteger, default=2047)
config_default_show = Column(SmallInteger, default=6143)
config_columns_to_ignore = Column(String)
config_use_google_drive = Column(Boolean)
config_google_drive_folder = Column(String)
@@ -485,6 +489,10 @@ class Config:
return bool((self.config_default_show is not None) and
(self.config_default_show & SIDEBAR_AUTHOR == SIDEBAR_AUTHOR))
def show_publisher(self):
return bool((self.config_default_show is not None) and
(self.config_default_show & SIDEBAR_PUBLISHER == SIDEBAR_PUBLISHER))
def show_best_rated_books(self):
return bool((self.config_default_show is not None) and
(self.config_default_show & SIDEBAR_BEST_RATED == SIDEBAR_BEST_RATED))
@@ -740,7 +748,7 @@ def create_admin_user():
user.role = ROLE_USER + ROLE_ADMIN + ROLE_DOWNLOAD + ROLE_UPLOAD + ROLE_EDIT + ROLE_DELETE_BOOKS + ROLE_PASSWD
user.sidebar_view = DETAIL_RANDOM + SIDEBAR_LANGUAGE + SIDEBAR_SERIES + SIDEBAR_CATEGORY + SIDEBAR_HOT + \
SIDEBAR_RANDOM + SIDEBAR_AUTHOR + SIDEBAR_BEST_RATED + SIDEBAR_READ_AND_UNREAD + SIDEBAR_RECENT + \
SIDEBAR_SORTED + MATURE_CONTENT
SIDEBAR_SORTED + MATURE_CONTENT + SIDEBAR_PUBLISHER
user.password = generate_password_hash(DEFAULT_PASS)
+143 -38
View File
@@ -529,6 +529,10 @@ def fill_indexpage(page, database, db_filter, order, *join):
# Modifies different Database objects, first check if elements have to be added to database, than check
# if elements have to be deleted, because they are no longer used
def modify_database_object(input_elements, db_book_object, db_object, db_session, db_type):
# passing input_elements not as a list may lead to undesired results
if not isinstance(input_elements, list):
raise TypeError(str(input_elements) + " should be passed as a list")
input_elements = [x for x in input_elements if x != '']
# we have all input element (authors, series, tags) names now
# 1. search for elements to remove
@@ -542,13 +546,13 @@ def modify_database_object(input_elements, db_book_object, db_object, db_session
else:
type_elements = c_elements.name
for inp_element in input_elements:
if inp_element == type_elements:
if inp_element.lower() == type_elements.lower():
found = True
break
# if the element was not found in the new list, add it to remove list
if not found:
del_elements.append(c_elements)
# 2. search for elements that need to be added
# 2. search for elements that need to be added
add_elements = []
for inp_element in input_elements:
found = False
@@ -580,20 +584,46 @@ def modify_database_object(input_elements, db_book_object, db_object, db_session
db_filter = db_object.name
for add_element in add_elements:
# check if a element with that name exists
new_element = db_session.query(db_object).filter(db_filter == add_element).first()
db_element = db_session.query(db_object).filter(db_filter == add_element).first()
# if no element is found add it
if new_element is None:
if db_type == 'author':
new_element = db_object(add_element, add_element.replace('|', ','), "")
elif db_type == 'series':
new_element = db_object(add_element, add_element)
elif db_type == 'custom':
new_element = db_object(value=add_element)
else: # db_type should be tag, language or publisher
new_element = db_object(add_element)
# if new_element is None:
if db_type == 'author':
new_element = db_object(add_element, add_element.replace('|', ','), "")
elif db_type == 'series':
new_element = db_object(add_element, add_element)
elif db_type == 'custom':
new_element = db_object(value=add_element)
elif db_type == 'publisher':
new_element = db_object(add_element, None)
else: # db_type should be tag or language
new_element = db_object(add_element)
if db_element is None:
db_session.add(new_element)
# add element to book
db_book_object.append(new_element)
db_book_object.append(new_element)
else:
if db_type == 'custom' and db_element.value != add_element:
new_element.value = add_element
# new_element = db_element
elif db_type == 'language' and db_element.lang_code != add_element:
db_element.lang_code = add_element
# new_element = db_element
elif db_type == 'series' and db_element.name != add_element:
db_element.name = add_element # = add_element # new_element = db_object(add_element, add_element)
db_element.sort = add_element
# new_element = db_element
elif db_type == 'author' and db_element.name != add_element:
db_element.name = add_element
db_element.sort = add_element.replace('|', ',')
# new_element = db_element
if db_type == 'publisher' and db_element.name != add_element:
db_element.name = add_element
db_element.sort = None
# new_element = db_element
elif db_element.name != add_element:
db_element.name = add_element
# new_element = db_element
# add element to book
db_book_object.append(db_element)
# read search results from calibre-database and return it (function is used for feed and simple search
@@ -745,6 +775,26 @@ def feed_author(book_id):
return render_xml_template('feed.xml', entries=entries, pagination=pagination)
@app.route("/opds/publisher")
@requires_basic_auth_if_no_ano
def feed_publisherindex():
off = request.args.get("offset") or 0
entries = db.session.query(db.Publishers).join(db.books_publishers_link).join(db.Books).filter(common_filters())\
.group_by('books_publishers_link.publisher').order_by(db.Publishers.sort).limit(config.config_books_per_page).offset(off)
pagination = Pagination((int(off) / (int(config.config_books_per_page)) + 1), config.config_books_per_page,
len(db.session.query(db.Publishers).all()))
return render_xml_template('feed.xml', listelements=entries, folder='feed_publisher', pagination=pagination)
@app.route("/opds/publisher/<int:book_id>")
@requires_basic_auth_if_no_ano
def feed_publisher(book_id):
off = request.args.get("offset") or 0
entries, __, pagination = fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1),
db.Books, db.Books.publishers.any(db.Publishers.id == book_id), [db.Books.timestamp.desc()])
return render_xml_template('feed.xml', entries=entries, pagination=pagination)
@app.route("/opds/category")
@requires_basic_auth_if_no_ano
def feed_categoryindex():
@@ -1027,7 +1077,17 @@ def get_authors_json():
json_dumps = json.dumps([dict(name=r.name.replace('|',',')) for r in entries])
return json_dumps
@app.route("/get_publishers_json", methods=['GET', 'POST'])
@login_required_if_no_ano
def get_publishers_json():
if request.method == "GET":
query = request.args.get('q')
entries = db.session.query(db.Publishers).filter(db.Publishers.name.ilike("%" + query + "%")).all()
json_dumps = json.dumps([dict(name=r.name.replace('|',',')) for r in entries])
return json_dumps
@app.route("/get_tags_json", methods=['GET', 'POST'])
@login_required_if_no_ano
def get_tags_json():
@@ -1340,7 +1400,8 @@ def best_rated_books(page):
[db.Books.timestamp.desc()])
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
title=_(u"Best rated books"), page="rated")
abort(404)
else:
abort(404)
@app.route("/discover", defaults={'page': 1})
@@ -1398,6 +1459,33 @@ def author(book_id, page):
title=name, author=author_info, other_books=other_books, page="author")
@app.route("/publisher")
@login_required_if_no_ano
def publisher_list():
if current_user.show_publisher():
entries = db.session.query(db.Publishers, func.count('books_publishers_link.book').label('count'))\
.join(db.books_publishers_link).join(db.Books).filter(common_filters())\
.group_by('books_publishers_link.publisher').order_by(db.Publishers.sort).all()
return render_title_template('list.html', entries=entries, folder='publisher',
title=_(u"Publisher list"), page="publisherlist")
else:
abort(404)
@app.route("/publisher/<int:book_id>", defaults={'page': 1})
@app.route('/publisher/<int:book_id>/<int:page>')
@login_required_if_no_ano
def publisher(book_id, page):
publisher = db.session.query(db.Publishers).filter(db.Publishers.id == book_id).first()
if publisher:
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.publishers.any(db.Publishers.id == book_id),
(db.Series.name, db.Books.series_index), db.books_series_link, db.Series)
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
title=_(u"Publisher: %(name)s", name=publisher.name), page="publisher")
else:
abort(404)
def get_unique_other_books(library_books, author_books):
# Get all identifiers (ISBN, Goodreads, etc) and filter author's books by that list so we show fewer duplicates
# Note: Not all images will be shown, even though they're available on Goodreads.com.
@@ -1434,15 +1522,18 @@ def series_list():
@app.route("/series/<int:book_id>/<int:page>'")
@login_required_if_no_ano
def series(book_id, page):
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.series.any(db.Series.id == book_id),
name = db.session.query(db.Series).filter(db.Series.id == book_id).first()
if name:
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.series.any(db.Series.id == book_id),
[db.Books.series_index])
name = db.session.query(db.Series).filter(db.Series.id == book_id).first().name
if entries:
return render_title_template('index.html', random=random, pagination=pagination, entries=entries,
title=_(u"Series: %(serie)s", serie=name), page="series")
if entries:
return render_title_template('index.html', random=random, pagination=pagination, entries=entries,
title=_(u"Series: %(serie)s", serie=name.name), page="series")
else:
flash(_(u"Error opening eBook. File does not exist or file is not accessible:"), category="error")
return redirect(url_for("index"))
else:
flash(_(u"Error opening eBook. File does not exist or file is not accessible:"), category="error")
return redirect(url_for("index"))
abort(404)
@app.route("/language")
@@ -1475,15 +1566,18 @@ def language_overview():
@app.route('/language/<name>/page/<int:page>')
@login_required_if_no_ano
def language(name, page):
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.languages.any(db.Languages.lang_code == name),
[db.Books.timestamp.desc()])
try:
cur_l = LC.parse(name)
name = cur_l.get_language_name(get_locale())
lang_name = cur_l.get_language_name(get_locale())
except UnknownLocaleError:
name = _(isoLanguages.get(part3=name).name)
try:
lang_name = _(isoLanguages.get(part3=name).name)
except KeyError:
abort(404)
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.languages.any(db.Languages.lang_code == name),
[db.Books.timestamp.desc()])
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
title=_(u"Language: %(name)s", name=name), page="language")
title=_(u"Language: %(name)s", name=lang_name), page="language")
@app.route("/category")
@@ -1503,12 +1597,14 @@ def category_list():
@app.route('/category/<int:book_id>/<int:page>')
@login_required_if_no_ano
def category(book_id, page):
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.tags.any(db.Tags.id == book_id),
(db.Series.name, db.Books.series_index),db.books_series_link,db.Series)
name = db.session.query(db.Tags).filter(db.Tags.id == book_id).first().name
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
title=_(u"Category: %(name)s", name=name), page="category")
name = db.session.query(db.Tags).filter(db.Tags.id == book_id).first()
if name:
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.tags.any(db.Tags.id == book_id),
(db.Series.name, db.Books.series_index),db.books_series_link,db.Series)
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
title=_(u"Category: %(name)s", name=name.name), page="category")
else:
abort(404)
@app.route("/ajax/toggleread/<int:book_id>", methods=['POST'])
@@ -2761,6 +2857,8 @@ def profile():
content.sidebar_view += ub.SIDEBAR_BEST_RATED
if "show_author" in to_save:
content.sidebar_view += ub.SIDEBAR_AUTHOR
if "show_publisher" in to_save:
content.sidebar_view += ub.SIDEBAR_PUBLISHER
if "show_read_and_unread" in to_save:
content.sidebar_view += ub.SIDEBAR_READ_AND_UNREAD
if "show_detail_random" in to_save:
@@ -2871,6 +2969,8 @@ def view_configuration():
content.config_default_show = content.config_default_show + ub.SIDEBAR_RANDOM
if "show_author" in to_save:
content.config_default_show = content.config_default_show + ub.SIDEBAR_AUTHOR
if "show_publisher" in to_save:
content.config_default_show = content.config_default_show + ub.SIDEBAR_PUBLISHER
if "show_best_rated" in to_save:
content.config_default_show = content.config_default_show + ub.SIDEBAR_BEST_RATED
if "show_read_and_unread" in to_save:
@@ -3120,6 +3220,8 @@ def new_user():
content.sidebar_view += ub.SIDEBAR_BEST_RATED
if "show_author" in to_save:
content.sidebar_view += ub.SIDEBAR_AUTHOR
if "show_publisher" in to_save:
content.sidebar_view += ub.SIDEBAR_PUBLISHER
if "show_detail_random" in to_save:
content.sidebar_view += ub.DETAIL_RANDOM
if "show_sorted" in to_save:
@@ -3643,11 +3745,14 @@ def edit_book(book_id):
book.pubdate = db.Books.DEFAULT_PUBDATE
else:
book.pubdate = db.Books.DEFAULT_PUBDATE
'''if len(book.publishers):
if to_save["publisher"] != book.publishers[0].name:
modify_database_object(to_save["publisher"], book.publishers, db.Publishers, db.session, 'series')
else:
modify_database_object(to_save["publisher"], book.publishers, db.Publishers, db.session, 'series')'''
if to_save["publisher"]:
publisher = to_save["publisher"].rstrip().strip()
if len(book.publishers) == 0 or (len(book.publishers) > 0 and publisher != book.publishers[0].name):
modify_database_object([publisher], book.publishers, db.Publishers, db.session, 'publisher')
elif len(book.publishers):
modify_database_object([], book.publishers, db.Publishers, db.session, 'publisher')
# handle book languages
input_languages = to_save["languages"].split(',')