Commit 1b2124aa authored by cbartondock's avatar cbartondock

Merge branch 'master' of https://github.com/janeczku/calibre-web

parents b35483ed bd4fde9e
...@@ -287,7 +287,7 @@ def list_users(): ...@@ -287,7 +287,7 @@ def list_users():
for user in users: for user in users:
if user.default_language == "all": if user.default_language == "all":
user.default = _("all") user.default = _("All")
else: else:
user.default = LC.parse(user.default_language).get_language_name(get_locale()) user.default = LC.parse(user.default_language).get_language_name(get_locale())
...@@ -985,10 +985,13 @@ def _config_string(to_save, x): ...@@ -985,10 +985,13 @@ def _config_string(to_save, x):
def _configuration_gdrive_helper(to_save): def _configuration_gdrive_helper(to_save):
gdrive_error = None
gdrive_secrets = {}
if not os.path.isfile(gdriveutils.SETTINGS_YAML): if not os.path.isfile(gdriveutils.SETTINGS_YAML):
config.config_use_google_drive = False config.config_use_google_drive = False
gdrive_secrets = {} if gdrive_support:
gdrive_error = gdriveutils.get_error_text(gdrive_secrets) gdrive_error = gdriveutils.get_error_text(gdrive_secrets)
if "config_use_google_drive" in to_save and not config.config_use_google_drive and not gdrive_error: if "config_use_google_drive" in to_save and not config.config_use_google_drive and not gdrive_error:
with open(gdriveutils.CLIENT_SECRETS, 'r') as settings: with open(gdriveutils.CLIENT_SECRETS, 'r') as settings:
...@@ -1254,7 +1257,7 @@ def _configuration_result(error_flash=None, gdrive_error=None, configured=True): ...@@ -1254,7 +1257,7 @@ def _configuration_result(error_flash=None, gdrive_error=None, configured=True):
gdrivefolders = [] gdrivefolders = []
if gdrive_error is None: if gdrive_error is None:
gdrive_error = gdriveutils.get_error_text() gdrive_error = gdriveutils.get_error_text()
if gdrive_error: if gdrive_error and gdrive_support:
log.error(gdrive_error) log.error(gdrive_error)
gdrive_error = _(gdrive_error) gdrive_error = _(gdrive_error)
else: else:
...@@ -1414,7 +1417,7 @@ def _handle_edit_user(to_save, content, languages, translations, kobo_support): ...@@ -1414,7 +1417,7 @@ def _handle_edit_user(to_save, content, languages, translations, kobo_support):
except IntegrityError as ex: except IntegrityError as ex:
ub.session.rollback() ub.session.rollback()
log.error("An unknown error occurred while changing user: {}".format(str(ex))) log.error("An unknown error occurred while changing user: {}".format(str(ex)))
flash(_(u"An unknown error occurred."), category="error") flash(_(u"An unknown error occurred. Please try again later."), category="error")
except OperationalError: except OperationalError:
ub.session.rollback() ub.session.rollback()
log.error("Settings DB is not Writeable") log.error("Settings DB is not Writeable")
...@@ -1465,7 +1468,7 @@ def update_mailsettings(): ...@@ -1465,7 +1468,7 @@ def update_mailsettings():
elif to_save.get("gmail"): elif to_save.get("gmail"):
try: try:
config.mail_gmail_token = services.gmail.setup_gmail(config.mail_gmail_token) config.mail_gmail_token = services.gmail.setup_gmail(config.mail_gmail_token)
flash(_(u"G-Mail Account Verification Successful"), category="success") flash(_(u"Gmail Account Verification Successful"), category="success")
except Exception as ex: except Exception as ex:
flash(str(ex), category="error") flash(str(ex), category="error")
log.error(ex) log.error(ex)
......
...@@ -367,7 +367,7 @@ def render_edit_book(book_id): ...@@ -367,7 +367,7 @@ def render_edit_book(book_id):
cc = calibre_db.session.query(db.Custom_Columns).filter(db.Custom_Columns.datatype.notin_(db.cc_exceptions)).all() cc = calibre_db.session.query(db.Custom_Columns).filter(db.Custom_Columns.datatype.notin_(db.cc_exceptions)).all()
book = calibre_db.get_filtered_book(book_id, allow_show_archived=True) book = calibre_db.get_filtered_book(book_id, allow_show_archived=True)
if not book: if not book:
flash(_(u"Error opening eBook. File does not exist or file is not accessible"), category="error") flash(_(u"Oops! Selected book title is unavailable. File does not exist or is not accessible"), category="error")
return redirect(url_for("web.index")) return redirect(url_for("web.index"))
for lang in book.languages: for lang in book.languages:
...@@ -448,6 +448,9 @@ def edit_book_series_index(series_index, book): ...@@ -448,6 +448,9 @@ def edit_book_series_index(series_index, book):
# Add default series_index to book # Add default series_index to book
modif_date = False modif_date = False
series_index = series_index or '1' series_index = series_index or '1'
if not series_index.replace('.', '', 1).isdigit():
flash(_("%(seriesindex)s is not a valid number, skipping", seriesindex=series_index), category="warning")
return False
if book.series_index != series_index: if book.series_index != series_index:
book.series_index = series_index book.series_index = series_index
modif_date = True modif_date = True
...@@ -510,6 +513,8 @@ def edit_cc_data_value(book_id, book, c, to_save, cc_db_value, cc_string): ...@@ -510,6 +513,8 @@ def edit_cc_data_value(book_id, book, c, to_save, cc_db_value, cc_string):
to_save[cc_string] = None to_save[cc_string] = None
elif c.datatype == 'bool': elif c.datatype == 'bool':
to_save[cc_string] = 1 if to_save[cc_string] == 'True' else 0 to_save[cc_string] = 1 if to_save[cc_string] == 'True' else 0
elif c.datatype == 'comments':
to_save[cc_string] = Markup(to_save[cc_string]).unescape()
elif c.datatype == 'datetime': elif c.datatype == 'datetime':
try: try:
to_save[cc_string] = datetime.strptime(to_save[cc_string], "%Y-%m-%d") to_save[cc_string] = datetime.strptime(to_save[cc_string], "%Y-%m-%d")
...@@ -735,7 +740,7 @@ def edit_book(book_id): ...@@ -735,7 +740,7 @@ def edit_book(book_id):
# Book not found # Book not found
if not book: if not book:
flash(_(u"Error opening eBook. File does not exist or file is not accessible"), category="error") flash(_(u"Oops! Selected book title is unavailable. File does not exist or is not accessible"), category="error")
return redirect(url_for("web.index")) return redirect(url_for("web.index"))
meta = upload_single_file(request, book, book_id) meta = upload_single_file(request, book, book_id)
...@@ -781,7 +786,7 @@ def edit_book(book_id): ...@@ -781,7 +786,7 @@ def edit_book(book_id):
# Add default series_index to book # Add default series_index to book
modif_date |= edit_book_series_index(to_save["series_index"], book) modif_date |= edit_book_series_index(to_save["series_index"], book)
# Handle book comments/description # Handle book comments/description
modif_date |= edit_book_comments(to_save["description"], book) modif_date |= edit_book_comments(Markup(to_save['description']).unescape(), book)
# Handle identifiers # Handle identifiers
input_identifiers = identifier_list(to_save, book) input_identifiers = identifier_list(to_save, book)
modification, warning = modify_identifiers(input_identifiers, book.identifiers, calibre_db.session) modification, warning = modify_identifiers(input_identifiers, book.identifiers, calibre_db.session)
......
...@@ -29,7 +29,7 @@ def get_fb2_info(tmp_file_path, original_file_extension): ...@@ -29,7 +29,7 @@ def get_fb2_info(tmp_file_path, original_file_extension):
'l': 'http://www.w3.org/1999/xlink', 'l': 'http://www.w3.org/1999/xlink',
} }
fb2_file = open(tmp_file_path) fb2_file = open(tmp_file_path, encoding="utf-8")
tree = etree.fromstring(fb2_file.read().encode()) tree = etree.fromstring(fb2_file.read().encode())
authors = tree.xpath('/fb:FictionBook/fb:description/fb:title-info/fb:author', namespaces=ns) authors = tree.xpath('/fb:FictionBook/fb:description/fb:title-info/fb:author', namespaces=ns)
......
...@@ -122,10 +122,13 @@ def formatfloat(value, decimals=1): ...@@ -122,10 +122,13 @@ def formatfloat(value, decimals=1):
@jinjia.app_template_filter('formatseriesindex') @jinjia.app_template_filter('formatseriesindex')
def formatseriesindex_filter(series_index): def formatseriesindex_filter(series_index):
if series_index: if series_index:
try:
if int(series_index) - series_index == 0: if int(series_index) - series_index == 0:
return int(series_index) return int(series_index)
else: else:
return series_index return series_index
except ValueError:
return series_index
return 0 return 0
@jinjia.app_template_filter('uuidfilter') @jinjia.app_template_filter('uuidfilter')
......
...@@ -62,7 +62,7 @@ def remote_login(): ...@@ -62,7 +62,7 @@ def remote_login():
ub.session_commit() ub.session_commit()
verify_url = url_for('remotelogin.verify_token', token=auth_token.auth_token, _external=true) verify_url = url_for('remotelogin.verify_token', token=auth_token.auth_token, _external=true)
log.debug(u"Remot Login request with token: %s", auth_token.auth_token) log.debug(u"Remot Login request with token: %s", auth_token.auth_token)
return render_title_template('remote_login.html', title=_(u"login"), token=auth_token.auth_token, return render_title_template('remote_login.html', title=_(u"Login"), token=auth_token.auth_token,
verify_url=verify_url, page="remotelogin") verify_url=verify_url, page="remotelogin")
......
...@@ -65,7 +65,7 @@ def get_sidebar_config(kwargs=None): ...@@ -65,7 +65,7 @@ def get_sidebar_config(kwargs=None):
"show_text": _('Show unread'), "config_show": False}) "show_text": _('Show unread'), "config_show": False})
sidebar.append({"glyph": "glyphicon-random", "text": _('Discover'), "link": 'web.books_list', "id": "rand", sidebar.append({"glyph": "glyphicon-random", "text": _('Discover'), "link": 'web.books_list', "id": "rand",
"visibility": constants.SIDEBAR_RANDOM, 'public': True, "page": "discover", "visibility": constants.SIDEBAR_RANDOM, 'public': True, "page": "discover",
"show_text": _('Show random books'), "config_show": True}) "show_text": _('Show Random Books'), "config_show": True})
sidebar.append({"glyph": "glyphicon-inbox", "text": _('Categories'), "link": 'web.category_list', "id": "cat", sidebar.append({"glyph": "glyphicon-inbox", "text": _('Categories'), "link": 'web.category_list', "id": "cat",
"visibility": constants.SIDEBAR_CATEGORY, 'public': True, "page": "category", "visibility": constants.SIDEBAR_CATEGORY, 'public': True, "page": "category",
"show_text": _('Show category selection'), "config_show": True}) "show_text": _('Show category selection'), "config_show": True})
......
...@@ -227,3 +227,14 @@ th { ...@@ -227,3 +227,14 @@ th {
.dark-theme .overlay { .dark-theme .overlay {
background-color: rgba(0, 0, 0, 0.8); background-color: rgba(0, 0, 0, 0.8);
} }
/* Hide scrollbar for Chrome, Safari and Opera */
.disabled-scrollbar::-webkit-scrollbar {
display: none;
}
/* Hide scrollbar for IE, Edge and Firefox */
.disabled-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
\ No newline at end of file
...@@ -69,7 +69,9 @@ var settings = { ...@@ -69,7 +69,9 @@ var settings = {
rotateTimes: 0, rotateTimes: 0,
fitMode: kthoom.Key.B, fitMode: kthoom.Key.B,
theme: "light", theme: "light",
direction: 0 // 0 = Left to Right, 1 = Right to Left direction: 0, // 0 = Left to Right, 1 = Right to Left
nextPage: 0, // 0 = Reset to Top, 1 = Remember Position
scrollbar: 1 // 0 = Hide Scrollbar, 1 = Show Scrollbar
}; };
kthoom.saveSettings = function() { kthoom.saveSettings = function() {
...@@ -282,6 +284,7 @@ function updatePage() { ...@@ -282,6 +284,7 @@ function updatePage() {
} }
$("body").toggleClass("dark-theme", settings.theme === "dark"); $("body").toggleClass("dark-theme", settings.theme === "dark");
$("#mainContent").toggleClass("disabled-scrollbar", settings.scrollbar === 0);
kthoom.setSettings(); kthoom.setSettings();
kthoom.saveSettings(); kthoom.saveSettings();
...@@ -439,6 +442,9 @@ function showPrevPage() { ...@@ -439,6 +442,9 @@ function showPrevPage() {
currentImage++; currentImage++;
} else { } else {
updatePage(); updatePage();
if (settings.nextPage === 0) {
$("#mainContent").scrollTop(0);
}
} }
} }
...@@ -449,6 +455,9 @@ function showNextPage() { ...@@ -449,6 +455,9 @@ function showNextPage() {
currentImage--; currentImage--;
} else { } else {
updatePage(); updatePage();
if (settings.nextPage === 0) {
$("#mainContent").scrollTop(0);
}
} }
} }
...@@ -650,6 +659,9 @@ function init(filename) { ...@@ -650,6 +659,9 @@ function init(filename) {
$("#thumbnails").on("click", "a", function() { $("#thumbnails").on("click", "a", function() {
currentImage = $(this).data("page") - 1; currentImage = $(this).data("page") - 1;
updatePage(); updatePage();
if (settings.nextPage === 0) {
$("#mainContent").scrollTop(0);
}
}); });
// Fullscreen mode // Fullscreen mode
......
...@@ -145,7 +145,7 @@ ...@@ -145,7 +145,7 @@
</div> </div>
{% if config.config_allow_reverse_proxy_header_login %} {% if config.config_allow_reverse_proxy_header_login %}
<div class="row"> <div class="row">
<div class="col-xs-6 col-sm-7">{{_('Reverse proxy header name')}}</div> <div class="col-xs-6 col-sm-7">{{_('Reverse Proxy Header Name')}}</div>
<div class="col-xs-6 col-sm-5">{{ config.config_reverse_proxy_login_header_name }}</div> <div class="col-xs-6 col-sm-5">{{ config.config_reverse_proxy_login_header_name }}</div>
</div> </div>
{% endif %} {% endif %}
......
...@@ -161,7 +161,7 @@ ...@@ -161,7 +161,7 @@
value="{% if book['custom_column_' ~ c.id][0].value %}{{book['custom_column_' ~ c.id][0].value|formatdate}}{% endif %}" value="{% if book['custom_column_' ~ c.id][0].value %}{{book['custom_column_' ~ c.id][0].value|formatdate}}{% endif %}"
{% endif %}> {% endif %}>
<span class="input-group-btn"> <span class="input-group-btn">
<button type="button" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button> <button type="button" id="{{ 'custom_column_' ~ c.id }}_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button>
</span> </span>
</div> </div>
{% endif %} {% endif %}
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
{{ text_table_row('authors', _('Enter Authors'),_('Authors'), true, true) }} {{ text_table_row('authors', _('Enter Authors'),_('Authors'), true, true) }}
{{ text_table_row('tags', _('Enter Categories'),_('Categories'), false, true) }} {{ text_table_row('tags', _('Enter Categories'),_('Categories'), false, true) }}
{{ text_table_row('series', _('Enter Series'),_('Series'), false, true) }} {{ text_table_row('series', _('Enter Series'),_('Series'), false, true) }}
<th data-field="series_index" id="series_index" data-visible="{{visiblility.get('series_index')}}" data-edit-validate="{{ _('This Field is Required') }}" data-sortable="true" {% if g.user.role_edit() %} data-editable-type="number" data-editable-placeholder="1" data-editable-step="0.01" data-editable-min="0" data-editable-url="{{ url_for('editbook.edit_list_book', param='series_index')}}" data-edit="true" data-editable-title="{{_('Enter title')}}"{% endif %}>{{_('Series Index')}}</th> <th data-field="series_index" id="series_index" data-visible="{{visiblility.get('series_index')}}" data-edit-validate="{{ _('This Field is Required') }}" data-sortable="true" {% if g.user.role_edit() %} data-editable-type="number" data-editable-placeholder="1" data-editable-step="0.01" data-editable-min="0" data-editable-url="{{ url_for('editbook.edit_list_book', param='series_index')}}" data-edit="true" data-editable-title="{{_('Enter Title')}}"{% endif %}>{{_('Series Index')}}</th>
{{ text_table_row('languages', _('Enter Languages'),_('Languages'), false, true) }} {{ text_table_row('languages', _('Enter Languages'),_('Languages'), false, true) }}
<!--th data-field="pubdate" data-type="date" data-visible="{{visiblility.get('pubdate')}}" data-viewformat="dd.mm.yyyy" id="pubdate" data-sortable="true">{{_('Publishing Date')}}</th--> <!--th data-field="pubdate" data-type="date" data-visible="{{visiblility.get('pubdate')}}" data-viewformat="dd.mm.yyyy" id="pubdate" data-sortable="true">{{_('Publishing Date')}}</th-->
{{ text_table_row('publishers', _('Enter Publishers'),_('Publishers'), false, true) }} {{ text_table_row('publishers', _('Enter Publishers'),_('Publishers'), false, true) }}
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
<label for="mail_server_type">{{_('Choose Server Type')}}</label> <label for="mail_server_type">{{_('Choose Server Type')}}</label>
<select name="mail_server_type" id="config_email_type" class="form-control" data-control="email-settings"> <select name="mail_server_type" id="config_email_type" class="form-control" data-control="email-settings">
<option value="0" {% if content.mail_server_type == 0 %}selected{% endif %}>{{_('Use Standard E-Mail Account')}}</option> <option value="0" {% if content.mail_server_type == 0 %}selected{% endif %}>{{_('Use Standard E-Mail Account')}}</option>
<option value="1" {% if content.mail_server_type == 1 %}selected{% endif %}>{{_('Gmail Account with OAuth2 Verfification')}}</option> <option value="1" {% if content.mail_server_type == 1 %}selected{% endif %}>{{_('Gmail Account with OAuth2 Verification')}}</option>
</select> </select>
</div> </div>
<div data-related="email-settings-1"> <div data-related="email-settings-1">
......
...@@ -157,6 +157,24 @@ ...@@ -157,6 +157,24 @@
<label for="rightToLeft"><input type="radio" id="rightToLeft" name="direction" value="1" /> {{_('Right to Left')}}</label> <label for="rightToLeft"><input type="radio" id="rightToLeft" name="direction" value="1" /> {{_('Right to Left')}}</label>
</div> </div>
</td> </td>
</tr>
<tr>
<th>{{_('Next Page')}}:</th>
<td>
<div class="inputs">
<label for="resetToTop"><input type="radio" id="resetToTop" name="nextPage" value="0" /> {{_('Reset to Top')}}</label>
<label for="rememberPosition"><input type="radio" id="rememberPosition" name="nextPage" value="1" /> {{_('Remember Position')}}</label>
</div>
</td>
</tr>
<tr>
<th>{{_('Scrollbar')}}:</th>
<td>
<div class="inputs">
<label for="showScrollbar"><input type="radio" id="showScrollbar" name="scrollbar" value="1" /> {{_('Show')}}</label>
<label for="hideScrollbar"><input type="radio" id="hideScrollbar" name="scrollbar" value="0" /> {{_('Hide')}}</label>
</div>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
......
...@@ -17,22 +17,22 @@ ...@@ -17,22 +17,22 @@
</div> </div>
<div class="row"> <div class="row">
<div class="form-group col-sm-6"> <div class="form-group col-sm-6">
<label for="Publishstart">{{_('Published Date From')}}</label> <label for="publishstart">{{_('Published Date From')}}</label>
<div class="input-group"> <div class="input-group">
<input type="text" style="position: static;" class="datepicker form-control" name="Publishstart" id="Publishstart" value=""> <input type="text" style="position: static;" class="datepicker form-control" name="publish_start" id="publishstart" value="">
<input type="text" style="position: absolute;" class="form-control fake-input hidden" id="fake_Publishstart" value=""> <input type="text" style="position: absolute;" class="form-control fake-input hidden" id="fake_publishstart" value="">
<span class="input-group-btn"> <span class="input-group-btn">
<button type="button" id="pubstart_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button> <button type="button" id="publishstart_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button>
</span> </span>
</div> </div>
</div> </div>
<div class="form-group col-sm-6"> <div class="form-group col-sm-6">
<label for="Publishend">{{_('Published Date To')}}</label> <label for="publishend">{{_('Published Date To')}}</label>
<div class="input-group "> <div class="input-group ">
<input type="text" style="position: static;" class="datepicker form-control" name="Publishend" id="Publishend" value=""> <input type="text" style="position: static;" class="datepicker form-control" name="publishend" id="publishend" value="">
<input type="text" style="position: absolute;" class="form-control fake-input hidden" id="fake_Publishend" value=""> <input type="text" style="position: absolute;" class="form-control fake-input hidden" id="fake_publishend" value="">
<span class="input-group-btn"> <span class="input-group-btn">
<button type="button" id="pubend_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button> <button type="button" id="publishend_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button>
</span> </span>
</div> </div>
</div> </div>
...@@ -181,7 +181,7 @@ ...@@ -181,7 +181,7 @@
<input type="text" style="position: static;" class="datepicker form-control" name="{{ 'custom_column_' ~ c.id }}_start" id="{{ 'custom_column_' ~ c.id }}_start" value=""> <input type="text" style="position: static;" class="datepicker form-control" name="{{ 'custom_column_' ~ c.id }}_start" id="{{ 'custom_column_' ~ c.id }}_start" value="">
<input type="text" style="position: absolute;" class="form-control fake-input hidden" id="fake_{{ 'custom_column_' ~ c.id }}_start" value=""> <input type="text" style="position: absolute;" class="form-control fake-input hidden" id="fake_{{ 'custom_column_' ~ c.id }}_start" value="">
<span class="input-group-btn"> <span class="input-group-btn">
<button type="button" id="pubstart_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button> <button type="button" id="{{ 'custom_column_' ~ c.id }}_start_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button>
</span> </span>
</div> </div>
</div> </div>
...@@ -191,7 +191,7 @@ ...@@ -191,7 +191,7 @@
<input type="text" style="position: static;" class="datepicker form-control" name="{{ 'custom_column_' ~ c.id }}_end" id="{{ 'custom_column_' ~ c.id }}_end" value=""> <input type="text" style="position: static;" class="datepicker form-control" name="{{ 'custom_column_' ~ c.id }}_end" id="{{ 'custom_column_' ~ c.id }}_end" value="">
<input type="text" style="position: absolute;" class="form-control fake-input hidden" id="fake_{{ 'custom_column_' ~ c.id }}_end" value=""> <input type="text" style="position: absolute;" class="form-control fake-input hidden" id="fake_{{ 'custom_column_' ~ c.id }}_end" value="">
<span class="input-group-btn"> <span class="input-group-btn">
<button type="button" id="pubend_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button> <button type="button" id="{{ 'custom_column_' ~ c.id }}_end_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button>
</span> </span>
</div> </div>
</div> </div>
......
...@@ -143,7 +143,7 @@ ...@@ -143,7 +143,7 @@
{{ user_checkbox_row("sidebar_view", "sidebar_random", _('Show random books'), visiblility, sidebar_settings)}} {{ user_checkbox_row("sidebar_view", "sidebar_random", _('Show random books'), visiblility, sidebar_settings)}}
{{ user_checkbox_row("sidebar_view", "sidebar_author", _('Show author selection'), visiblility, sidebar_settings)}} {{ user_checkbox_row("sidebar_view", "sidebar_author", _('Show author selection'), visiblility, sidebar_settings)}}
{{ user_checkbox_row("sidebar_view", "sidebar_best_rated", _('Show Top Rated Books'), visiblility, sidebar_settings)}} {{ user_checkbox_row("sidebar_view", "sidebar_best_rated", _('Show Top Rated Books'), visiblility, sidebar_settings)}}
{{ user_checkbox_row("sidebar_view", "sidebar_read_and_unread", _('Show random books'), visiblility, sidebar_settings)}} {{ user_checkbox_row("sidebar_view", "sidebar_read_and_unread", _('Show Random Books'), visiblility, sidebar_settings)}}
{{ user_checkbox_row("sidebar_view", "sidebar_publisher", _('Show publisher selection'), visiblility, sidebar_settings)}} {{ user_checkbox_row("sidebar_view", "sidebar_publisher", _('Show publisher selection'), visiblility, sidebar_settings)}}
{{ user_checkbox_row("sidebar_view", "sidebar_rating", _('Show ratings selection'), visiblility, sidebar_settings)}} {{ user_checkbox_row("sidebar_view", "sidebar_rating", _('Show ratings selection'), visiblility, sidebar_settings)}}
{{ user_checkbox_row("sidebar_view", "sidebar_format", _('Show file formats selection'), visiblility, sidebar_settings)}} {{ user_checkbox_row("sidebar_view", "sidebar_format", _('Show file formats selection'), visiblility, sidebar_settings)}}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -1080,10 +1080,10 @@ def adv_search_custom_columns(cc, term, q): ...@@ -1080,10 +1080,10 @@ def adv_search_custom_columns(cc, term, q):
custom_end = term.get('custom_column_' + str(c.id) + '_end') custom_end = term.get('custom_column_' + str(c.id) + '_end')
if custom_start: if custom_start:
q = q.filter(getattr(db.Books, 'custom_column_' + str(c.id)).any( q = q.filter(getattr(db.Books, 'custom_column_' + str(c.id)).any(
db.cc_classes[c.id].value >= custom_start)) func.datetime(db.cc_classes[c.id].value) >= func.datetime(custom_start)))
if custom_end: if custom_end:
q = q.filter(getattr(db.Books, 'custom_column_' + str(c.id)).any( q = q.filter(getattr(db.Books, 'custom_column_' + str(c.id)).any(
db.cc_classes[c.id].value <= custom_end)) func.datetime(db.cc_classes[c.id].value) <= func.datetime(custom_end)))
else: else:
custom_query = term.get('custom_column_' + str(c.id)) custom_query = term.get('custom_column_' + str(c.id))
if custom_query != '' and custom_query is not None: if custom_query != '' and custom_query is not None:
...@@ -1254,8 +1254,8 @@ def render_adv_search_results(term, offset=None, order=None, limit=None): ...@@ -1254,8 +1254,8 @@ def render_adv_search_results(term, offset=None, order=None, limit=None):
author_name = term.get("author_name") author_name = term.get("author_name")
book_title = term.get("book_title") book_title = term.get("book_title")
publisher = term.get("publisher") publisher = term.get("publisher")
pub_start = term.get("Publishstart") pub_start = term.get("publishstart")
pub_end = term.get("Publishend") pub_end = term.get("publishend")
rating_low = term.get("ratinghigh") rating_low = term.get("ratinghigh")
rating_high = term.get("ratinglow") rating_high = term.get("ratinglow")
description = term.get("comment") description = term.get("comment")
...@@ -1310,9 +1310,9 @@ def render_adv_search_results(term, offset=None, order=None, limit=None): ...@@ -1310,9 +1310,9 @@ def render_adv_search_results(term, offset=None, order=None, limit=None):
if book_title: if book_title:
q = q.filter(func.lower(db.Books.title).ilike("%" + book_title + "%")) q = q.filter(func.lower(db.Books.title).ilike("%" + book_title + "%"))
if pub_start: if pub_start:
q = q.filter(db.Books.pubdate >= pub_start) q = q.filter(func.datetime(db.Books.pubdate) > func.datetime(pub_start))
if pub_end: if pub_end:
q = q.filter(db.Books.pubdate <= pub_end) q = q.filter(func.datetime(db.Books.pubdate) < func.datetime(pub_end))
q = adv_search_read_status(q, read_status) q = adv_search_read_status(q, read_status)
if publisher: if publisher:
q = q.filter(db.Books.publishers.any(func.lower(db.Publishers.name).ilike("%" + publisher + "%"))) q = q.filter(db.Books.publishers.any(func.lower(db.Publishers.name).ilike("%" + publisher + "%")))
...@@ -1442,20 +1442,20 @@ def register(): ...@@ -1442,20 +1442,20 @@ def register():
return redirect(url_for('web.index')) return redirect(url_for('web.index'))
if not config.get_mail_server_configured(): if not config.get_mail_server_configured():
flash(_(u"E-Mail server is not configured, please contact your administrator!"), category="error") flash(_(u"E-Mail server is not configured, please contact your administrator!"), category="error")
return render_title_template('register.html', title=_(u"register"), page="register") return render_title_template('register.html', title=_("Register"), page="register")
if request.method == "POST": if request.method == "POST":
to_save = request.form.to_dict() to_save = request.form.to_dict()
nickname = to_save["email"].strip() if config.config_register_email else to_save.get('name') nickname = to_save["email"].strip() if config.config_register_email else to_save.get('name')
if not nickname or not to_save.get("email"): if not nickname or not to_save.get("email"):
flash(_(u"Please fill out all fields!"), category="error") flash(_(u"Please fill out all fields!"), category="error")
return render_title_template('register.html', title=_(u"register"), page="register") return render_title_template('register.html', title=_("Register"), page="register")
try: try:
nickname = check_username(nickname) nickname = check_username(nickname)
email = check_email(to_save["email"]) email = check_email(to_save["email"])
except Exception as ex: except Exception as ex:
flash(str(ex), category="error") flash(str(ex), category="error")
return render_title_template('register.html', title=_(u"register"), page="register") return render_title_template('register.html', title=_("Register"), page="register")
content = ub.User() content = ub.User()
if check_valid_domain(email): if check_valid_domain(email):
...@@ -1474,17 +1474,17 @@ def register(): ...@@ -1474,17 +1474,17 @@ def register():
except Exception: except Exception:
ub.session.rollback() ub.session.rollback()
flash(_(u"An unknown error occurred. Please try again later."), category="error") flash(_(u"An unknown error occurred. Please try again later."), category="error")
return render_title_template('register.html', title=_(u"register"), page="register") return render_title_template('register.html', title=_("Register"), page="register")
else: else:
flash(_(u"Your e-mail is not allowed to register"), category="error") flash(_(u"Your e-mail is not allowed to register"), category="error")
log.warning('Registering failed for user "%s" e-mail address: %s', nickname, to_save["email"]) log.warning('Registering failed for user "%s" e-mail address: %s', nickname, to_save["email"])
return render_title_template('register.html', title=_(u"register"), page="register") return render_title_template('register.html', title=_("Register"), page="register")
flash(_(u"Confirmation e-mail was send to your e-mail account."), category="success") flash(_(u"Confirmation e-mail was send to your e-mail account."), category="success")
return redirect(url_for('web.login')) return redirect(url_for('web.login'))
if feature_support['oauth']: if feature_support['oauth']:
register_user_with_oauth() register_user_with_oauth()
return render_title_template('register.html', config=config, title=_(u"register"), page="register") return render_title_template('register.html', config=config, title=_("Register"), page="register")
@web.route('/login', methods=['GET', 'POST']) @web.route('/login', methods=['GET', 'POST'])
...@@ -1553,7 +1553,7 @@ def login(): ...@@ -1553,7 +1553,7 @@ def login():
if url_for("web.logout") == next_url: if url_for("web.logout") == next_url:
next_url = url_for("web.index") next_url = url_for("web.index")
return render_title_template('login.html', return render_title_template('login.html',
title=_(u"login"), title=_(u"Login"),
next_url=next_url, next_url=next_url,
config=config, config=config,
oauth_check=oauth_check, oauth_check=oauth_check,
...@@ -1614,8 +1614,8 @@ def change_profile(kobo_support, local_oauth_check, oauth_status, translations, ...@@ -1614,8 +1614,8 @@ def change_profile(kobo_support, local_oauth_check, oauth_status, translations,
log.debug(u"Profile updated") log.debug(u"Profile updated")
except IntegrityError: except IntegrityError:
ub.session.rollback() ub.session.rollback()
flash(_(u"Found an existing account for this e-mail address."), category="error") flash(_(u"Found an existing account for this e-mail address"), category="error")
log.debug(u"Found an existing account for this e-mail address.") log.debug(u"Found an existing account for this e-mail address")
except OperationalError as e: except OperationalError as e:
ub.session.rollback() ub.session.rollback()
log.error("Database error: %s", e) log.error("Database error: %s", e)
...@@ -1658,8 +1658,8 @@ def profile(): ...@@ -1658,8 +1658,8 @@ def profile():
def read_book(book_id, book_format): def read_book(book_id, book_format):
book = calibre_db.get_filtered_book(book_id) book = calibre_db.get_filtered_book(book_id)
if not book: if not book:
flash(_(u"Error opening eBook. File does not exist or file is not accessible"), category="error") flash(_(u"Oops! Selected book title is unavailable. File does not exist or is not accessible"), category="error")
log.debug(u"Error opening eBook. File does not exist or file is not accessible") log.debug(u"Oops! Selected book title is unavailable. File does not exist or is not accessible")
return redirect(url_for("web.index")) return redirect(url_for("web.index"))
# check if book has bookmark # check if book has bookmark
...@@ -1693,8 +1693,8 @@ def read_book(book_id, book_format): ...@@ -1693,8 +1693,8 @@ def read_book(book_id, book_format):
log.debug(u"Start comic reader for %d", book_id) log.debug(u"Start comic reader for %d", book_id)
return render_title_template('readcbr.html', comicfile=all_name, title=_(u"Read a Book"), return render_title_template('readcbr.html', comicfile=all_name, title=_(u"Read a Book"),
extension=fileExt) extension=fileExt)
log.debug(u"Error opening eBook. File does not exist or file is not accessible") log.debug(u"Oops! Selected book title is unavailable. File does not exist or is not accessible")
flash(_(u"Error opening eBook. File does not exist or file is not accessible"), category="error") flash(_(u"Oops! Selected book title is unavailable. File does not exist or is not accessible"), category="error")
return redirect(url_for("web.index")) return redirect(url_for("web.index"))
...@@ -1764,6 +1764,7 @@ def show_book(book_id): ...@@ -1764,6 +1764,7 @@ def show_book(book_id):
reader_list=reader_list, reader_list=reader_list,
page="book") page="book")
else: else:
log.debug(u"Error opening eBook. File does not exist or file is not accessible") log.debug(u"Oops! Selected book title is unavailable. File does not exist or is not accessible")
flash(_(u"Error opening eBook. File does not exist or file is not accessible"), category="error") flash(_(u"Oops! Selected book title is unavailable. File does not exist or is not accessible"),
category="error")
return redirect(url_for("web.index")) return redirect(url_for("web.index"))
This diff is collapsed.
# GDrive Integration # GDrive Integration
gevent>20.6.0,<21.2.0 gevent>20.6.0,<21.2.0
greenlet>=0.4.17,<1.1.0 greenlet>=0.4.17,<1.2.0
httplib2>=0.9.2,<0.18.0 httplib2>=0.9.2,<0.20.0
oauth2client>=4.0.0,<4.1.4 oauth2client>=4.0.0,<4.1.4
uritemplate>=3.0.0,<3.1.0 uritemplate>=3.0.0,<3.1.0
pyasn1-modules>=0.0.8,<0.3.0 pyasn1-modules>=0.0.8,<0.3.0
pyasn1>=0.1.9,<0.5.0 pyasn1>=0.1.9,<0.5.0
PyDrive2>=1.3.1,<1.8.0 PyDrive2>=1.3.1,<1.9.0
PyYAML>=3.12 PyYAML>=3.12
rsa>=3.4.2,<4.1.0 rsa>=3.4.2,<4.8.0
six>=1.10.0,<1.15.0 six>=1.10.0,<1.17.0
# Gdrive and Gmail integration # Gdrive and Gmail integration
google-api-python-client>=1.7.11,<2.1.0 google-api-python-client>=1.7.11,<2.1.0
...@@ -26,7 +26,7 @@ python-ldap>=3.0.0,<3.4.0 ...@@ -26,7 +26,7 @@ python-ldap>=3.0.0,<3.4.0
Flask-SimpleLDAP>=1.4.0,<1.5.0 Flask-SimpleLDAP>=1.4.0,<1.5.0
#oauth #oauth
Flask-Dance>=1.4.0,<4.1.0 Flask-Dance>=2.0.0,<5.1.0
SQLAlchemy-Utils>=0.33.5,<0.38.0 SQLAlchemy-Utils>=0.33.5,<0.38.0
# extracting metadata # extracting metadata
...@@ -34,7 +34,7 @@ lxml>=3.8.0,<4.7.0 ...@@ -34,7 +34,7 @@ lxml>=3.8.0,<4.7.0
rarfile>=2.7 rarfile>=2.7
# other # other
natsort>=2.2.0,<7.1.0 natsort>=2.2.0,<7.2.0
comicapi>= 2.2.0,<2.3.0 comicapi>= 2.2.0,<2.3.0
#Kobo integration #Kobo integration
......
Babel>=1.3, <2.9 Babel>=1.3, <3.0
Flask-Babel>=0.11.1,<2.1.0 Flask-Babel>=0.11.1,<2.1.0
Flask-Login>=0.3.2,<0.5.1 Flask-Login>=0.3.2,<0.5.1
Flask-Principal>=0.3.2,<0.5.1 Flask-Principal>=0.3.2,<0.5.1
backports_abc>=0.4 backports_abc>=0.4
Flask>=1.0.2,<1.2.0 Flask>=1.0.2,<2.0.0
iso-639>=0.4.5,<0.5.0 iso-639>=0.4.5,<0.5.0
PyPDF3>=1.0.0,<1.0.4 PyPDF3>=1.0.0,<1.0.4
pytz>=2016.10 pytz>=2016.10
requests>=2.11.1,<2.25.0 requests>=2.11.1,<2.25.0
SQLAlchemy>=1.3.0,<1.4.0 # oauth fails on 1.4+ due to import problems in flask_dance SQLAlchemy>=1.3.0,<1.5.0
tornado>=4.1,<6.2 tornado>=4.1,<6.2
Wand>=0.4.4,<0.7.0 Wand>=0.4.4,<0.7.0
unidecode>=0.04.19,<1.2.0 unidecode>=0.04.19,<1.3.0
...@@ -34,35 +34,38 @@ console_scripts = ...@@ -34,35 +34,38 @@ console_scripts =
[options] [options]
include_package_data = True include_package_data = True
install_requires = install_requires =
Babel>=1.3, <2.9 Babel>=1.3, <3.0
Flask-Babel>=0.11.1,<2.1.0 Flask-Babel>=0.11.1,<2.1.0
Flask-Login>=0.3.2,<0.5.1 Flask-Login>=0.3.2,<0.5.1
Flask-Principal>=0.3.2,<0.5.1 Flask-Principal>=0.3.2,<0.5.1
backports_abc>=0.4 backports_abc>=0.4
Flask>=1.0.2,<1.2.0 Flask>=1.0.2,<2.1.0
iso-639>=0.4.5,<0.5.0 iso-639>=0.4.5,<0.5.0
PyPDF3>=1.0.0,<1.0.4 PyPDF3>=1.0.0,<1.0.4
pytz>=2016.10 pytz>=2016.10
requests>=2.11.1,<2.25.0 requests>=2.11.1,<2.25.0
SQLAlchemy>=1.3.0,<1.4.0 SQLAlchemy>=1.3.0,<1.5.0
tornado>=4.1,<6.2 tornado>=4.1,<6.2
Wand>=0.4.4,<0.7.0 Wand>=0.4.4,<0.7.0
unidecode>=0.04.19,<1.2.0 unidecode>=0.04.19,<1.3.0
[options.extras_require] [options.extras_require]
gdrive = gdrive =
google-api-python-client>=1.7.11,<1.13.0 google-api-python-client>=1.7.11,<2.1.0
gevent>20.6.0,<21.2.0 gevent>20.6.0,<21.2.0
greenlet>=0.4.17,<1.1.0 greenlet>=0.4.17,<1.2.0
httplib2>=0.9.2,<0.18.0 httplib2>=0.9.2,<0.20.0
oauth2client>=4.0.0,<4.1.4 oauth2client>=4.0.0,<4.1.4
uritemplate>=3.0.0,<3.1.0 uritemplate>=3.0.0,<3.1.0
pyasn1-modules>=0.0.8,<0.3.0 pyasn1-modules>=0.0.8,<0.3.0
pyasn1>=0.1.9,<0.5.0 pyasn1>=0.1.9,<0.5.0
PyDrive2>=1.3.1,<1.8.0 PyDrive2>=1.3.1,<1.9.0
PyYAML>=3.12 PyYAML>=3.12
rsa>=3.4.2,<4.1.0 rsa>=3.4.2,<4.8.0
six>=1.10.0,<1.15.0 six>=1.10.0,<1.17.0
gmail =
google-auth-oauthlib>=0.4.3,<0.5.0
google-api-python-client>=1.7.11,<2.1.0
goodreads = goodreads =
goodreads>=0.3.2,<0.4.0 goodreads>=0.3.2,<0.4.0
python-Levenshtein>=0.12.0,<0.13.0 python-Levenshtein>=0.12.0,<0.13.0
...@@ -70,14 +73,14 @@ ldap = ...@@ -70,14 +73,14 @@ ldap =
python-ldap>=3.0.0,<3.4.0 python-ldap>=3.0.0,<3.4.0
Flask-SimpleLDAP>=1.4.0,<1.5.0 Flask-SimpleLDAP>=1.4.0,<1.5.0
oauth = oauth =
Flask-Dance>=1.4.0,<3.1.0 Flask-Dance>=2.0.0,<5.1.0
SQLAlchemy-Utils>=0.33.5,<0.37.0 SQLAlchemy-Utils>=0.33.5,<0.38.0
metadata = metadata =
lxml>=3.8.0,<4.7.0 lxml>=3.8.0,<4.7.0
rarfile>=2.7 rarfile>=2.7
comics = comics =
natsort>=2.2.0,<7.1.0 natsort>=2.2.0,<7.2.0
comicapi>= 2.1.3,<2.2.0 comicapi>= 2.2.0,<2.3.0
kobo = kobo =
jsonschema>=3.2.0,<3.3.0 jsonschema>=3.2.0,<3.3.0
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment