Added polish in readme to supported UI languages
Handling of missing tags in fb import naming of path is more imitating calibre (replacement of special characters, "pinyining" of author names if unidecode is available ) Sorting of authors (similar to calibre for jr./sr./I..IV endings) bugfix pathseparator on windows and linux during upload bugfix os.rename for authordir publishing date on detailview is formated according to slected locale filename on downloading from web ui is now correct displayed added ids to html for testing
This commit is contained in:
parent
13caa54aad
commit
93b19165cf
|
@ -99,7 +99,7 @@ def pdf_preview(tmp_file_path, tmp_dir):
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
cover_file_name = os.path.splitext(tmp_file_path)[0] + ".cover.jpg"
|
cover_file_name = os.path.splitext(tmp_file_path)[0] + ".cover.jpg"
|
||||||
with Image(filename=tmp_file_path +"[0]", resolution=150) as img:
|
with Image(filename=tmp_file_path + "[0]", resolution=150) as img:
|
||||||
img.compression_quality = 88
|
img.compression_quality = 88
|
||||||
img.save(filename=os.path.join(tmp_dir, cover_file_name))
|
img.save(filename=os.path.join(tmp_dir, cover_file_name))
|
||||||
return cover_file_name
|
return cover_file_name
|
||||||
|
|
|
@ -227,7 +227,7 @@ class Books(Base):
|
||||||
identifiers = relationship('Identifiers', backref='books')
|
identifiers = relationship('Identifiers', backref='books')
|
||||||
|
|
||||||
def __init__(self, title, sort, author_sort, timestamp, pubdate, series_index, last_modified, path, has_cover,
|
def __init__(self, title, sort, author_sort, timestamp, pubdate, series_index, last_modified, path, has_cover,
|
||||||
authors, tags): # ToDO check Authors and tags necessary
|
authors, tags):
|
||||||
self.title = title
|
self.title = title
|
||||||
self.sort = sort
|
self.sort = sort
|
||||||
self.author_sort = author_sort
|
self.author_sort = author_sort
|
||||||
|
|
30
cps/fb2.py
30
cps/fb2.py
|
@ -6,7 +6,7 @@ import os
|
||||||
import uploader
|
import uploader
|
||||||
import StringIO
|
import StringIO
|
||||||
|
|
||||||
# ToDo: Check usage of original_file_name
|
|
||||||
def get_fb2_info(tmp_file_path, original_file_extension):
|
def get_fb2_info(tmp_file_path, original_file_extension):
|
||||||
|
|
||||||
ns = {
|
ns = {
|
||||||
|
@ -20,37 +20,35 @@ def get_fb2_info(tmp_file_path, original_file_extension):
|
||||||
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)
|
||||||
|
|
||||||
def get_author(element):
|
def get_author(element):
|
||||||
last_name=element.xpath('fb:last-name/text()', namespaces=ns)
|
last_name = element.xpath('fb:last-name/text()', namespaces=ns)
|
||||||
if len(last_name):
|
if len(last_name):
|
||||||
last_name=last_name[0]
|
last_name = last_name[0]
|
||||||
else:
|
else:
|
||||||
last_name=u''
|
last_name = u''
|
||||||
middle_name=element.xpath('fb:middle-name/text()', namespaces=ns)
|
middle_name = element.xpath('fb:middle-name/text()', namespaces=ns)
|
||||||
if len(middle_name):
|
if len(middle_name):
|
||||||
middle_name=middle_name[0]
|
middle_name = middle_name[0]
|
||||||
else:
|
else:
|
||||||
middle_name=u''
|
middle_name = u''
|
||||||
first_name=element.xpath('fb:first-name/text()', namespaces=ns)
|
first_name = element.xpath('fb:first-name/text()', namespaces=ns)
|
||||||
if len(first_name):
|
if len(first_name):
|
||||||
first_name=first_name[0]
|
first_name = first_name[0]
|
||||||
else:
|
else:
|
||||||
first_name=u''
|
first_name = u''
|
||||||
return first_name + ' ' + middle_name + ' ' + last_name
|
return first_name + ' ' + middle_name + ' ' + last_name
|
||||||
|
|
||||||
author = unicode(", ".join(map(get_author, authors)))
|
author = unicode(", ".join(map(get_author, authors)))
|
||||||
|
|
||||||
title = tree.xpath('/fb:FictionBook/fb:description/fb:title-info/fb:book-title/text()', namespaces=ns)
|
title = tree.xpath('/fb:FictionBook/fb:description/fb:title-info/fb:book-title/text()', namespaces=ns)
|
||||||
if len(title):
|
if len(title):
|
||||||
title=unicode(title[0])
|
title = unicode(title[0])
|
||||||
else:
|
else:
|
||||||
title=u''
|
title = u''
|
||||||
description = tree.xpath('/fb:FictionBook/fb:description/fb:publish-info/fb:book-name/text()', namespaces=ns)
|
description = tree.xpath('/fb:FictionBook/fb:description/fb:publish-info/fb:book-name/text()', namespaces=ns)
|
||||||
if len(description):
|
if len(description):
|
||||||
description=unicode(description[0])
|
description = unicode(description[0])
|
||||||
else:
|
else:
|
||||||
description=u''
|
description = u''
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return uploader.BookMeta(
|
return uploader.BookMeta(
|
||||||
file_path=tmp_file_path,
|
file_path=tmp_file_path,
|
||||||
|
|
|
@ -22,6 +22,11 @@ from email.generator import Generator
|
||||||
from flask_babel import gettext as _
|
from flask_babel import gettext as _
|
||||||
import subprocess
|
import subprocess
|
||||||
import shutil
|
import shutil
|
||||||
|
try:
|
||||||
|
import unidecode
|
||||||
|
use_unidecode=True
|
||||||
|
except:
|
||||||
|
use_unidecode=False
|
||||||
|
|
||||||
def update_download(book_id, user_id):
|
def update_download(book_id, user_id):
|
||||||
check = ub.session.query(ub.Downloads).filter(ub.Downloads.user_id == user_id).filter(ub.Downloads.book_id ==
|
check = ub.session.query(ub.Downloads).filter(ub.Downloads.user_id == user_id).filter(ub.Downloads.book_id ==
|
||||||
|
@ -203,7 +208,7 @@ def get_attachment(file_path):
|
||||||
return attachment
|
return attachment
|
||||||
except IOError:
|
except IOError:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
message = (_('The requested file could not be read. Maybe wrong permissions?')) # ToDo: What is this?
|
app.logger.error = (u'The requested file could not be read. Maybe wrong permissions?')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@ -212,47 +217,54 @@ def get_valid_filename(value, replace_whitespace=True):
|
||||||
Returns the given string converted to a string that can be used for a clean
|
Returns the given string converted to a string that can be used for a clean
|
||||||
filename. Limits num characters to 128 max.
|
filename. Limits num characters to 128 max.
|
||||||
"""
|
"""
|
||||||
value = value[:128]
|
if value[-1:] ==u'.':
|
||||||
# re_slugify = re.compile('[^\w\s-]', re.UNICODE)
|
value = value[:-1]+u'_'
|
||||||
|
if use_unidecode:
|
||||||
|
value=(unidecode.unidecode(value)).strip()
|
||||||
|
else:
|
||||||
|
value=value.replace('§','SS')
|
||||||
|
value=value.replace('ß','ss')
|
||||||
value = unicodedata.normalize('NFKD', value)
|
value = unicodedata.normalize('NFKD', value)
|
||||||
re_slugify = re.compile('[^\w\s-]', re.UNICODE)
|
re_slugify = re.compile('[\W\s-]', re.UNICODE)
|
||||||
value = unicode(re_slugify.sub('', value).strip())
|
value = unicode(re_slugify.sub('', value).strip())
|
||||||
if replace_whitespace:
|
if replace_whitespace:
|
||||||
value = re.sub('[\s]+', '_', value, flags=re.U)
|
#*+:\"/<>? werden durch _ ersetzt
|
||||||
value = value.replace(u"\u00DF", "ss")
|
value = re.sub('[\*\+:\\\"/<>\?]+', '_', value, flags=re.U)
|
||||||
|
|
||||||
|
value = value[:128]
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def get_sorted_author(value):
|
||||||
def get_normalized_author(value):
|
regexes = ["^(JR|SR)\.?$","^I{1,3}\.?$","^IV\.?$"]
|
||||||
"""
|
combined = "(" + ")|(".join(regexes) + ")"
|
||||||
Normalizes sorted author name
|
value = value.split(" ")
|
||||||
"""
|
if re.match(combined,value[-1].upper()):
|
||||||
value = unicodedata.normalize('NFKD', value)
|
value2 = value[-2] + ", " + " ".join(value[:-2]) + " " + value[-1]
|
||||||
value = re.sub('[^\w,\s]', '', value, flags=re.U)
|
else:
|
||||||
value = " ".join(value.split(", ")[::-1])
|
value2 = value[-1] + ", " + " ".join(value[:-1])
|
||||||
return value
|
return value2
|
||||||
|
|
||||||
|
|
||||||
def update_dir_stucture(book_id, calibrepath):
|
def update_dir_stucture(book_id, calibrepath):
|
||||||
db.session.connection().connection.connection.create_function("title_sort", 1, db.title_sort)
|
db.session.connection().connection.connection.create_function("title_sort", 1, db.title_sort)
|
||||||
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||||
path = os.path.join(calibrepath, book.path)
|
path = os.path.join(calibrepath, book.path)#.replace('/',os.path.sep)).replace('\\',os.path.sep)
|
||||||
|
|
||||||
authordir = book.path.split(os.sep)[0]
|
authordir = book.path.split('/')[0]
|
||||||
new_authordir = get_valid_filename(book.authors[0].name, False)
|
new_authordir = get_valid_filename(book.authors[0].name)
|
||||||
titledir = book.path.split(os.sep)[1]
|
titledir = book.path.split('/')[1]
|
||||||
new_titledir = get_valid_filename(book.title, False) + " (" + str(book_id) + ")"
|
new_titledir = get_valid_filename(book.title) + " (" + str(book_id) + ")"
|
||||||
|
|
||||||
if titledir != new_titledir:
|
if titledir != new_titledir:
|
||||||
new_title_path = os.path.join(os.path.dirname(path), new_titledir)
|
new_title_path = os.path.join(os.path.dirname(path), new_titledir)
|
||||||
os.rename(path, new_title_path)
|
os.rename(path, new_title_path)
|
||||||
path = new_title_path
|
path = new_title_path
|
||||||
book.path = book.path.split(os.sep)[0] + os.sep + new_titledir
|
book.path = book.path.split('/')[0] + '/' + new_titledir
|
||||||
|
|
||||||
if authordir != new_authordir:
|
if authordir != new_authordir:
|
||||||
new_author_path = os.path.join(os.path.join(calibrepath, new_authordir), os.path.basename(path))
|
new_author_path = os.path.join(os.path.join(calibrepath, new_authordir), os.path.basename(path))
|
||||||
os.renames(path, new_author_path)
|
os.rename(path, new_author_path)
|
||||||
book.path = new_authordir + os.sep + book.path.split(os.sep)[1]
|
book.path = new_authordir + '/' + book.path.split('/')[1]
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="discover">
|
<div class="discover">
|
||||||
<h2>{{_('User list')}}</h2>
|
<h2>{{_('User list')}}</h2>
|
||||||
<table class="table table-striped">
|
<table class="table table-striped" id="table_user">
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{_('Nickname')}}</th>
|
<th>{{_('Nickname')}}</th>
|
||||||
<th>{{_('Email')}}</th>
|
<th>{{_('Email')}}</th>
|
||||||
|
@ -30,9 +30,9 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
<div class="btn btn-default"><a href="{{url_for('new_user')}}">{{_('Add new user')}}</a></div>
|
<div class="btn btn-default" id="admin_new_user"><a href="{{url_for('new_user')}}">{{_('Add new user')}}</a></div>
|
||||||
<h2>{{_('SMTP mail settings')}}</h2>
|
<h2>{{_('SMTP mail settings')}}</h2>
|
||||||
<table class="table table-striped">
|
<table class="table table-striped" id="table_email">
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{_('SMTP hostname')}}</th>
|
<th>{{_('SMTP hostname')}}</th>
|
||||||
<th>{{_('SMTP port')}}</th>
|
<th>{{_('SMTP port')}}</th>
|
||||||
|
@ -51,10 +51,10 @@
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div class="btn btn-default"><a href="{{url_for('edit_mailsettings')}}">{{_('Change SMTP settings')}}</a></div>
|
<div class="btn btn-default" id="admin_edit_email"><a href="{{url_for('edit_mailsettings')}}">{{_('Change SMTP settings')}}</a></div>
|
||||||
|
|
||||||
<h2>{{_('Configuration')}}</h2>
|
<h2>{{_('Configuration')}}</h2>
|
||||||
<table class="table table-striped">
|
<table class="table table-striped" id="table_configuration">
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{_('Calibre DB dir')}}</th>
|
<th>{{_('Calibre DB dir')}}</th>
|
||||||
<th>{{_('Log Level')}}</th>
|
<th>{{_('Log Level')}}</th>
|
||||||
|
@ -76,6 +76,7 @@
|
||||||
<div class="btn btn-default"><a href="{{url_for('configuration')}}">{{_('Configuration')}}</a></div>
|
<div class="btn btn-default"><a href="{{url_for('configuration')}}">{{_('Configuration')}}</a></div>
|
||||||
<h2>{{_('Administration')}}</h2>
|
<h2>{{_('Administration')}}</h2>
|
||||||
{% if not development %}
|
{% if not development %}
|
||||||
|
<p>{{_('Current commit timestamp')}}: {{commit}} </p>
|
||||||
<div class="btn btn-default" data-toggle="modal" data-target="#RestartDialog">{{_('Restart Calibre-web')}}</a></div>
|
<div class="btn btn-default" data-toggle="modal" data-target="#RestartDialog">{{_('Restart Calibre-web')}}</a></div>
|
||||||
<div class="btn btn-default" data-toggle="modal" data-target="#ShutdownDialog">{{_('Stop Calibre-web')}}</a></div>
|
<div class="btn btn-default" data-toggle="modal" data-target="#ShutdownDialog">{{_('Stop Calibre-web')}}</a></div>
|
||||||
<div class="btn btn-default" id="check_for_update">{{_('Check for update')}}</a></div>
|
<div class="btn btn-default" id="check_for_update">{{_('Check for update')}}</a></div>
|
||||||
|
|
|
@ -70,8 +70,8 @@
|
||||||
</div>
|
</div>
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if entry.pubdate != '0101-01-01 00:00:00' %}
|
{% if entry.pubdate[:10] != '0101-01-01' %}
|
||||||
<p>{{_('Publishing date')}}: {{entry.pubdate[:10]}} </p>
|
<p>{{_('Publishing date')}}: {{entry.pubdate|formatdate}} </p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if cc|length > 0 %}
|
{% if cc|length > 0 %}
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
||||||
{% for entry in random %}
|
{% for entry in random %}
|
||||||
<div class="col-sm-3 col-lg-2 col-xs-6 book">
|
<div id="books_rand" class="col-sm-3 col-lg-2 col-xs-6 book">
|
||||||
<div class="cover">
|
<div class="cover">
|
||||||
<a href="{{ url_for('show_book', id=entry.id) }}">
|
<a href="{{ url_for('show_book', id=entry.id) }}">
|
||||||
{% if entry.has_cover %}
|
{% if entry.has_cover %}
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
<h2>{{title}}</h2>
|
<h2>{{title}}</h2>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for entry in entries %}
|
{% for entry in entries %}
|
||||||
<div class="col-sm-3 col-lg-2 col-xs-6 book">
|
<div id="books" class="col-sm-3 col-lg-2 col-xs-6 book">
|
||||||
<div class="cover">
|
<div class="cover">
|
||||||
<a href="{{ url_for('show_book', id=entry.id) }}">
|
<a href="{{ url_for('show_book', id=entry.id) }}">
|
||||||
{% if entry.has_cover %}
|
{% if entry.has_cover %}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
{% for lang in languages %}
|
{% for lang in languages %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-1" align="left"><span class="badge">{{lang_counter[loop.index0].bookcount}}</span></div>
|
<div class="col-xs-1" align="left"><span class="badge">{{lang_counter[loop.index0].bookcount}}</span></div>
|
||||||
<div class="col-xs-6"><a href="{{url_for('language', name=lang.lang_code)}}">{{lang.name}}</a></div>
|
<div class="col-xs-6"><a id="list_{{loop.index0}}" href="{{url_for('language', name=lang.lang_code)}}">{{lang.name}}</a></div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -80,16 +80,16 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if g.user.role_admin() %}
|
{% if g.user.role_admin() %}
|
||||||
<li><a href="{{url_for('admin')}}"><span class="glyphicon glyphicon-dashboard"></span> {{_('Admin')}}</a></li>
|
<li><a id="top_admin" href="{{url_for('admin')}}"><span class="glyphicon glyphicon-dashboard"></span> {{_('Admin')}}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li><a href="{{url_for('profile')}}"><span class="glyphicon glyphicon-user"></span> {{g.user.nickname}}</a></li>
|
<li><a id="top_user" href="{{url_for('profile')}}"><span class="glyphicon glyphicon-user"></span> {{g.user.nickname}}</a></li>
|
||||||
{% if not g.user.is_anonymous() %}
|
{% if not g.user.is_anonymous() %}
|
||||||
<li><a href="{{url_for('logout')}}"><span class="glyphicon glyphicon-log-out"></span> {{_('Logout')}}</a></li>
|
<li><a id="logout" href="{{url_for('logout')}}"><span class="glyphicon glyphicon-log-out"></span> {{_('Logout')}}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if g.allow_registration and not g.user.is_authenticated %}
|
{% if g.allow_registration and not g.user.is_authenticated %}
|
||||||
<li><a href="{{url_for('login')}}"><span class="glyphicon glyphicon-log-in"></span> {{_('Login')}}</a></li>
|
<li><a id="login" href="{{url_for('login')}}"><span class="glyphicon glyphicon-log-in"></span> {{_('Login')}}</a></li>
|
||||||
<li><a href="{{url_for('register')}}"><span class="glyphicon glyphicon-user"></span> {{_('Register')}}</a></li>
|
<li><a id="register" href="{{url_for('register')}}"><span class="glyphicon glyphicon-user"></span> {{_('Register')}}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</div><!--/.nav-collapse -->
|
</div><!--/.nav-collapse -->
|
||||||
|
@ -98,17 +98,17 @@
|
||||||
{% for message in get_flashed_messages(with_categories=True) %}
|
{% for message in get_flashed_messages(with_categories=True) %}
|
||||||
{%if message[0] == "error" %}
|
{%if message[0] == "error" %}
|
||||||
<div class="row-fluid" style="margin-top: -20px; text-align: center;">
|
<div class="row-fluid" style="margin-top: -20px; text-align: center;">
|
||||||
<div class="alert alert-danger">{{ message[1] }}</div>
|
<div id="flash_alert" class="alert alert-danger">{{ message[1] }}</div>
|
||||||
</div>
|
</div>
|
||||||
{%endif%}
|
{%endif%}
|
||||||
{%if message[0] == "info" %}
|
{%if message[0] == "info" %}
|
||||||
<div class="row-fluid" style="margin-top: -20px; text-align: center;">
|
<div class="row-fluid" style="margin-top: -20px; text-align: center;">
|
||||||
<div class="alert alert-info">{{ message[1] }}</div>
|
<div id="flash_info" class="alert alert-info">{{ message[1] }}</div>
|
||||||
</div>
|
</div>
|
||||||
{%endif%}
|
{%endif%}
|
||||||
{%if message[0] == "success" %}
|
{%if message[0] == "success" %}
|
||||||
<div class="row-fluid" style="margin-top: -20px; text-align: center;">
|
<div class="row-fluid" style="margin-top: -20px; text-align: center;">
|
||||||
<div class="alert alert-success">{{ message[1] }}</div>
|
<div id="flash_success" class="alert alert-success">{{ message[1] }}</div>
|
||||||
</div>
|
</div>
|
||||||
{%endif%}
|
{%endif%}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -119,25 +119,25 @@
|
||||||
<nav class="navigation">
|
<nav class="navigation">
|
||||||
<ul class="list-unstyled" id="scnd-nav" intent in-standard-append="nav.navigation" in-mobile-after="#main-nav" in-mobile-class="nav navbar-nav">
|
<ul class="list-unstyled" id="scnd-nav" intent in-standard-append="nav.navigation" in-mobile-after="#main-nav" in-mobile-class="nav navbar-nav">
|
||||||
<li class="nav-head hidden-xs">{{_('Browse')}}</li>
|
<li class="nav-head hidden-xs">{{_('Browse')}}</li>
|
||||||
<li><a href="{{url_for('index')}}"><span class="glyphicon glyphicon-book"></span> {{_('New Books')}}</a></li>
|
<li id="nav_new"><a href="{{url_for('index')}}"><span class="glyphicon glyphicon-book"></span> {{_('New Books')}}</a></li>
|
||||||
{% if g.user.show_hot_books() %}
|
{% if g.user.show_hot_books() %}
|
||||||
<li><a href="{{url_for('hot_books')}}"><span class="glyphicon glyphicon-fire"></span> {{_('Hot Books')}}</a></li>
|
<li id="nav_hot"><a href="{{url_for('hot_books')}}"><span class="glyphicon glyphicon-fire"></span> {{_('Hot Books')}}</a></li>
|
||||||
{%endif%}
|
{%endif%}
|
||||||
{% if g.user.show_best_rated_books() %}
|
{% if g.user.show_best_rated_books() %}
|
||||||
<li><a href="{{url_for('best_rated_books')}}"><span class="glyphicon glyphicon-star"></span> {{_('Best rated Books')}}</a></li>
|
<li><a href="{{url_for('best_rated_books')}}"><span class="glyphicon glyphicon-star"></span> {{_('Best rated Books')}}</a></li>
|
||||||
{%endif%}
|
{%endif%}
|
||||||
{% if g.user.show_random_books() %}
|
{% if g.user.show_random_books() %}
|
||||||
<li><a href="{{url_for('discover')}}"><span class="glyphicon glyphicon-random"></span> {{_('Discover')}}</a></li>
|
<li id="nav_rand"><a href="{{url_for('discover')}}"><span class="glyphicon glyphicon-random"></span> {{_('Discover')}}</a></li>
|
||||||
{%endif%}
|
{%endif%}
|
||||||
{% if g.user.show_category() %}
|
{% if g.user.show_category() %}
|
||||||
<li><a href="{{url_for('category_list')}}"><span class="glyphicon glyphicon-inbox"></span> {{_('Categories')}}</a></li>
|
<li id="nav_cat"><a href="{{url_for('category_list')}}"><span class="glyphicon glyphicon-inbox"></span> {{_('Categories')}}</a></li>
|
||||||
{%endif%}
|
{%endif%}
|
||||||
{% if g.user.show_series() %}
|
{% if g.user.show_series() %}
|
||||||
<li><a href="{{url_for('series_list')}}"><span class="glyphicon glyphicon-bookmark"></span> {{_('Series')}}</a></li>
|
<li id="nav_serie"><a href="{{url_for('series_list')}}"><span class="glyphicon glyphicon-bookmark"></span> {{_('Series')}}</a></li>
|
||||||
{%endif%}
|
{%endif%}
|
||||||
<li><a href="{{url_for('author_list')}}"><span class="glyphicon glyphicon-user"></span> {{_('Authors')}}</a></li>
|
<li id="nav_author"><a href="{{url_for('author_list')}}"><span class="glyphicon glyphicon-user"></span> {{_('Authors')}}</a></li>
|
||||||
{% if g.user.filter_language() == 'all' and g.user.show_language() %}
|
{% if g.user.filter_language() == 'all' and g.user.show_language() %}
|
||||||
<li><a href="{{url_for('language_overview')}}"><span class="glyphicon glyphicon-flag"></span> {{_('Languages')}} </a></li>
|
<li id="nav_lang"><a href="{{url_for('language_overview')}}"><span class="glyphicon glyphicon-flag"></span> {{_('Languages')}} </a></li>
|
||||||
{%endif%}
|
{%endif%}
|
||||||
{% if g.user.is_authenticated or g.user.is_anonymous() %}
|
{% if g.user.is_authenticated or g.user.is_anonymous() %}
|
||||||
<li class="nav-head hidden-xs">{{_('Public Shelves')}}</li>
|
<li class="nav-head hidden-xs">{{_('Public Shelves')}}</li>
|
||||||
|
@ -160,9 +160,9 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
{% block body %}{% endblock %}
|
{% block body %}{% endblock %}
|
||||||
{% if pagination %}
|
{% if pagination and (pagination.has_next or pagination.has_prev) %}
|
||||||
<div class="pagination">
|
<div class="pagination">
|
||||||
{%- for page in pagination.iter_pages() %}
|
{% for page in pagination.iter_pages() %}
|
||||||
{% if page %}
|
{% if page %}
|
||||||
{% if page != pagination.page %}
|
{% if page != pagination.page %}
|
||||||
<a href="{{ url_for_other_page(page) }}">{{ page }}</a>
|
<a href="{{ url_for_other_page(page) }}">{{ page }}</a>
|
||||||
|
@ -172,7 +172,7 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="ellipsis">…</span>
|
<span class="ellipsis">…</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{%- endfor %}
|
{% endfor %}
|
||||||
{% if pagination.has_next %}
|
{% if pagination.has_next %}
|
||||||
<a class="next" href="{{ url_for_other_page(pagination.page + 1)
|
<a class="next" href="{{ url_for_other_page(pagination.page + 1)
|
||||||
}}">Next »</a>
|
}}">Next »</a>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
{% for entry in entries %}
|
{% for entry in entries %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-1" align="left"><span class="badge">{{entry.count}}</span></div>
|
<div class="col-xs-1" align="left"><span class="badge">{{entry.count}}</span></div>
|
||||||
<div class="col-xs-6"><a href="{{url_for(folder, id=entry[0].id )}}">{{entry[0].name}}</a></div>
|
<div class="col-xs-6"><a id="list_{{loop.index0}}" href="{{url_for(folder, id=entry[0].id )}}">{{entry[0].name}}</a></div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<input type="checkbox" name="remember_me" checked> {{_('Remember me')}}
|
<input type="checkbox" name="remember_me" checked> {{_('Remember me')}}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-default">{{_('Submit')}}</button>
|
<button type="submit" name="submit" class="btn btn-default">{{_('Submit')}}</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{% if error %}
|
{% if error %}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
|
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
|
||||||
<LongName>{{instance}}</LongName>
|
<LongName>{{instance}}</LongName>
|
||||||
<ShortName>{{instance}}</ShortName>
|
<ShortName>{{instance}}</ShortName>
|
||||||
<Description>{{_('instanceCalibre Web ebook catalog')}}</Description>
|
<Description>{{_('Calibre Web ebook catalog')}}</Description>
|
||||||
<Developer>Janeczku</Developer>
|
<Developer>Janeczku</Developer>
|
||||||
<Contact>https://github.com/janeczku/calibre-web</Contact>
|
<Contact>https://github.com/janeczku/calibre-web</Contact>
|
||||||
<Url type="text/html"
|
<Url type="text/html"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<h3>{{_('Linked libraries')}}</h3>
|
<h3>{{_('Linked libraries')}}</h3>
|
||||||
|
|
||||||
<table class="table">
|
<table id="libs" class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{_('Program library')}}</th>
|
<th>{{_('Program library')}}</th>
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h3>{{_('Calibre library statistics')}}</h3>
|
<h3>{{_('Calibre library statistics')}}</h3>
|
||||||
<table class="table">
|
<table id="stats" class="table">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{bookcounter}}</th>
|
<th>{{bookcounter}}</th>
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
<label for="locale">{{_('Language')}}</label>
|
<label for="locale">{{_('Language')}}</label>
|
||||||
<select name="locale" id="locale" class="form-control">
|
<select name="locale" id="locale" class="form-control">
|
||||||
{% for translation in translations %}
|
{% for translation in translations %}
|
||||||
<option value="{{translation}}" {% if translation.language == content.locale %}selected{% endif %} {% if new_user == 1 and loop.first %}selected{% endif %}>{{ translation.display_name }}</option>
|
<option value="{{translation}}" {% if translation|string == content.locale %}selected{% endif %} {% if new_user == 1 and loop.first %}selected{% endif %}>{{ translation.display_name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -108,7 +108,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button type="submit" id="submit" class="btn btn-default">{{_('Submit')}}</button>
|
<button type="submit" id="submit" class="btn btn-default">{{_('Submit')}}</button>
|
||||||
{% if not profile %}
|
{% if not profile %}
|
||||||
<a href="{{ url_for('admin') }}" class="btn btn-default">{{_('Back')}}</a>
|
<a href="{{ url_for('admin') }}" id="back" class="btn btn-default">{{_('Back')}}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ msgstr "Beliebte Bücher (die meisten Downloads)"
|
||||||
|
|
||||||
#: cps/web.py:813
|
#: cps/web.py:813
|
||||||
msgid "Best rated books"
|
msgid "Best rated books"
|
||||||
msgstr ""
|
msgstr "Best bewertete Bücher"
|
||||||
|
|
||||||
#: cps/templates/index.xml:36 cps/web.py:822
|
#: cps/templates/index.xml:36 cps/web.py:822
|
||||||
msgid "Random Books"
|
msgid "Random Books"
|
||||||
|
@ -94,7 +94,7 @@ msgstr "Autorenliste"
|
||||||
#: cps/web.py:846
|
#: cps/web.py:846
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Author: %(name)s"
|
msgid "Author: %(name)s"
|
||||||
msgstr ""
|
msgstr "Autor: %(name)s"
|
||||||
|
|
||||||
#: cps/web.py:848 cps/web.py:876 cps/web.py:975 cps/web.py:1216 cps/web.py:2103
|
#: cps/web.py:848 cps/web.py:876 cps/web.py:975 cps/web.py:1216 cps/web.py:2103
|
||||||
msgid "Error opening eBook. File does not exist or file is not accessible:"
|
msgid "Error opening eBook. File does not exist or file is not accessible:"
|
||||||
|
@ -143,7 +143,7 @@ msgstr "Server wird runtergefahren, bitte Fenster schließen"
|
||||||
|
|
||||||
#: cps/web.py:1055
|
#: cps/web.py:1055
|
||||||
msgid "Update done"
|
msgid "Update done"
|
||||||
msgstr ""
|
msgstr "Update durchgeführt"
|
||||||
|
|
||||||
#: cps/web.py:1128 cps/web.py:1141
|
#: cps/web.py:1128 cps/web.py:1141
|
||||||
msgid "search"
|
msgid "search"
|
||||||
|
@ -470,11 +470,11 @@ msgstr "Stoppe Calibre-web"
|
||||||
|
|
||||||
#: cps/templates/admin.html:81
|
#: cps/templates/admin.html:81
|
||||||
msgid "Check for update"
|
msgid "Check for update"
|
||||||
msgstr ""
|
msgstr "Suche nach Update"
|
||||||
|
|
||||||
#: cps/templates/admin.html:82
|
#: cps/templates/admin.html:82
|
||||||
msgid "Perform Update"
|
msgid "Perform Update"
|
||||||
msgstr ""
|
msgstr "Update durchführen"
|
||||||
|
|
||||||
#: cps/templates/admin.html:93
|
#: cps/templates/admin.html:93
|
||||||
msgid "Do you really want to restart Calibre-web?"
|
msgid "Do you really want to restart Calibre-web?"
|
||||||
|
@ -584,7 +584,7 @@ msgstr "Öffentliche Registrierung aktivieren"
|
||||||
|
|
||||||
#: cps/templates/config_edit.html:52
|
#: cps/templates/config_edit.html:52
|
||||||
msgid "Default Settings for new users"
|
msgid "Default Settings for new users"
|
||||||
msgstr ""
|
msgstr "Default Einstellungen für neue Benutzer"
|
||||||
|
|
||||||
#: cps/templates/config_edit.html:55 cps/templates/user_edit.html:80
|
#: cps/templates/config_edit.html:55 cps/templates/user_edit.html:80
|
||||||
msgid "Admin user"
|
msgid "Admin user"
|
||||||
|
@ -625,7 +625,7 @@ msgstr "Sprache"
|
||||||
|
|
||||||
#: cps/templates/detail.html:74
|
#: cps/templates/detail.html:74
|
||||||
msgid "Publishing date"
|
msgid "Publishing date"
|
||||||
msgstr ""
|
msgstr "Herausgabedatum"
|
||||||
|
|
||||||
#: cps/templates/detail.html:106
|
#: cps/templates/detail.html:106
|
||||||
msgid "Description:"
|
msgid "Description:"
|
||||||
|
@ -699,11 +699,11 @@ msgstr "Beliebte Bücher"
|
||||||
|
|
||||||
#: cps/templates/index.xml:19
|
#: cps/templates/index.xml:19
|
||||||
msgid "Popular publications from this catalog based on Downloads."
|
msgid "Popular publications from this catalog based on Downloads."
|
||||||
msgstr ""
|
msgstr "Beliebte Publikationen aus dieser Bibliothek basierend auf Downloadzahlen"
|
||||||
|
|
||||||
#: cps/templates/index.xml:22 cps/templates/layout.html:127
|
#: cps/templates/index.xml:22 cps/templates/layout.html:127
|
||||||
msgid "Best rated Books"
|
msgid "Best rated Books"
|
||||||
msgstr ""
|
msgstr "Best bewertete Bücher"
|
||||||
|
|
||||||
#: cps/templates/index.xml:26
|
#: cps/templates/index.xml:26
|
||||||
msgid "Popular publications from this catalog based on Rating."
|
msgid "Popular publications from this catalog based on Rating."
|
||||||
|
@ -804,8 +804,8 @@ msgid "Remember me"
|
||||||
msgstr "Merken"
|
msgstr "Merken"
|
||||||
|
|
||||||
#: cps/templates/osd.xml:5
|
#: cps/templates/osd.xml:5
|
||||||
msgid "instanceCalibre Web ebook catalog"
|
msgid "Calibre Web ebook catalog"
|
||||||
msgstr ""
|
msgstr "Calibre Web Ebook Katalog"
|
||||||
|
|
||||||
#: cps/templates/read.html:136
|
#: cps/templates/read.html:136
|
||||||
msgid "Reflow text when sidebars are open."
|
msgid "Reflow text when sidebars are open."
|
||||||
|
@ -909,11 +909,11 @@ msgstr "Autoren in dieser Bibliothek"
|
||||||
|
|
||||||
#: cps/templates/stats.html:45
|
#: cps/templates/stats.html:45
|
||||||
msgid "Categories in this Library"
|
msgid "Categories in this Library"
|
||||||
msgstr ""
|
msgstr "Kategorien in dieser Bibliothek"
|
||||||
|
|
||||||
#: cps/templates/stats.html:49
|
#: cps/templates/stats.html:49
|
||||||
msgid "Series in this Library"
|
msgid "Series in this Library"
|
||||||
msgstr ""
|
msgstr "Serien in dieser Bibliothek"
|
||||||
|
|
||||||
#: cps/templates/user_edit.html:23
|
#: cps/templates/user_edit.html:23
|
||||||
msgid "Kindle E-Mail"
|
msgid "Kindle E-Mail"
|
||||||
|
@ -937,7 +937,7 @@ msgstr "Zeige Auswahl Beliebte Bücher"
|
||||||
|
|
||||||
#: cps/templates/user_edit.html:53
|
#: cps/templates/user_edit.html:53
|
||||||
msgid "Show best rated books"
|
msgid "Show best rated books"
|
||||||
msgstr ""
|
msgstr "Zeige am besten bewertete Bücher"
|
||||||
|
|
||||||
#: cps/templates/user_edit.html:57
|
#: cps/templates/user_edit.html:57
|
||||||
msgid "Show language selection"
|
msgid "Show language selection"
|
||||||
|
|
|
@ -144,7 +144,6 @@ class UserBase:
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<User %r>' % self.nickname
|
return '<User %r>' % self.nickname
|
||||||
|
|
||||||
|
@ -164,10 +163,6 @@ class User(UserBase, Base):
|
||||||
downloads = relationship('Downloads', backref='user', lazy='dynamic')
|
downloads = relationship('Downloads', backref='user', lazy='dynamic')
|
||||||
locale = Column(String(2), default="en")
|
locale = Column(String(2), default="en")
|
||||||
sidebar_view = Column(Integer, default=1)
|
sidebar_view = Column(Integer, default=1)
|
||||||
#language_books = Column(Integer, default=1)
|
|
||||||
#series_books = Column(Integer, default=1)
|
|
||||||
#category_books = Column(Integer, default=1)
|
|
||||||
#hot_books = Column(Integer, default=1)
|
|
||||||
default_language = Column(String(3), default="all")
|
default_language = Column(String(3), default="all")
|
||||||
|
|
||||||
|
|
||||||
|
@ -184,10 +179,6 @@ class Anonymous(AnonymousUserMixin, UserBase):
|
||||||
self.role = data.role
|
self.role = data.role
|
||||||
self.sidebar_view = data.sidebar_view
|
self.sidebar_view = data.sidebar_view
|
||||||
self.default_language = data.default_language
|
self.default_language = data.default_language
|
||||||
#self.language_books = data.language_books
|
|
||||||
#self.series_books = data.series_books
|
|
||||||
#self.category_books = data.category_books
|
|
||||||
#self.hot_books = data.hot_books
|
|
||||||
self.default_language = data.default_language
|
self.default_language = data.default_language
|
||||||
self.locale = data.locale
|
self.locale = data.locale
|
||||||
self.anon_browse = settings.config_anonbrowse
|
self.anon_browse = settings.config_anonbrowse
|
||||||
|
|
39
cps/web.py
39
cps/web.py
|
@ -25,6 +25,7 @@ import zipfile
|
||||||
from werkzeug.security import generate_password_hash, check_password_hash
|
from werkzeug.security import generate_password_hash, check_password_hash
|
||||||
from babel import Locale as LC
|
from babel import Locale as LC
|
||||||
from babel import negotiate_locale
|
from babel import negotiate_locale
|
||||||
|
from babel.dates import format_date
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
import base64
|
import base64
|
||||||
from sqlalchemy.sql import *
|
from sqlalchemy.sql import *
|
||||||
|
@ -279,6 +280,12 @@ def mimetype_filter(val):
|
||||||
s = 'application/octet-stream'
|
s = 'application/octet-stream'
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
@app.template_filter('formatdate')
|
||||||
|
def formatdate(val):
|
||||||
|
conformed_timestamp = re.sub(r"[:]|([-](?!((\d{2}[:]\d{2})|(\d{4}))$))", '', val)
|
||||||
|
formatdate = datetime.datetime.strptime(conformed_timestamp[:-5], "%Y%m%d %H%M%S")
|
||||||
|
return format_date(formatdate, format='medium',locale=get_locale())
|
||||||
|
|
||||||
|
|
||||||
def admin_required(f):
|
def admin_required(f):
|
||||||
"""
|
"""
|
||||||
|
@ -658,10 +665,9 @@ def get_opds_download_link(book_id, format):
|
||||||
data = db.session.query(db.Data).filter(db.Data.book == book.id).filter(db.Data.format == format.upper()).first()
|
data = db.session.query(db.Data).filter(db.Data.book == book.id).filter(db.Data.format == format.upper()).first()
|
||||||
if current_user.is_authenticated:
|
if current_user.is_authenticated:
|
||||||
helper.update_download(book_id, int(current_user.id))
|
helper.update_download(book_id, int(current_user.id))
|
||||||
author = helper.get_normalized_author(book.author_sort)
|
|
||||||
file_name = book.title
|
file_name = book.title
|
||||||
if len(author) > 0:
|
if len(book.authors) > 0:
|
||||||
file_name = author + '-' + file_name
|
file_name = book.authors[0].name + '-' + file_name
|
||||||
file_name = helper.get_valid_filename(file_name)
|
file_name = helper.get_valid_filename(file_name)
|
||||||
response = make_response(send_from_directory(os.path.join(config.config_calibre_dir, book.path), data.name + "." + format))
|
response = make_response(send_from_directory(os.path.join(config.config_calibre_dir, book.path), data.name + "." + format))
|
||||||
response.headers["Content-Disposition"] = "attachment; filename=\"%s.%s\"" % (data.name, format)
|
response.headers["Content-Disposition"] = "attachment; filename=\"%s.%s\"" % (data.name, format)
|
||||||
|
@ -1228,10 +1234,9 @@ def get_download_link(book_id, format):
|
||||||
# collect downloaded books only for registered user and not for anonymous user
|
# collect downloaded books only for registered user and not for anonymous user
|
||||||
if current_user.is_authenticated:
|
if current_user.is_authenticated:
|
||||||
helper.update_download(book_id, int(current_user.id))
|
helper.update_download(book_id, int(current_user.id))
|
||||||
author = helper.get_normalized_author(book.author_sort)
|
|
||||||
file_name = book.title
|
file_name = book.title
|
||||||
if len(author) > 0:
|
if len(book.authors) > 0:
|
||||||
file_name = author + '-' + file_name
|
file_name = book.authors[0].name + '-' + file_name
|
||||||
file_name = helper.get_valid_filename(file_name)
|
file_name = helper.get_valid_filename(file_name)
|
||||||
response = make_response(
|
response = make_response(
|
||||||
send_from_directory(os.path.join(config.config_calibre_dir, book.path), data.name + "." + format))
|
send_from_directory(os.path.join(config.config_calibre_dir, book.path), data.name + "." + format))
|
||||||
|
@ -1239,13 +1244,7 @@ def get_download_link(book_id, format):
|
||||||
response.headers["Content-Type"] = mimetypes.types_map['.' + format]
|
response.headers["Content-Type"] = mimetypes.types_map['.' + format]
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
response.headers["Content-Disposition"] = \
|
response.headers["Content-Disposition"] = "attachment; filename=\"%s.%s\"" % (file_name.encode('utf-8'), format)
|
||||||
"attachment; " \
|
|
||||||
"filename={utf_filename}.{suffix};" \
|
|
||||||
"filename*=UTF-8''{utf_filename}.{suffix}".format(
|
|
||||||
utf_filename=file_name.encode('utf-8'),
|
|
||||||
suffix=format
|
|
||||||
)
|
|
||||||
return response
|
return response
|
||||||
else:
|
else:
|
||||||
abort(404)
|
abort(404)
|
||||||
|
@ -1599,6 +1598,7 @@ def basic_configuration():
|
||||||
|
|
||||||
def configuration_helper(origin):
|
def configuration_helper(origin):
|
||||||
global global_task
|
global global_task
|
||||||
|
commit='$Format:%cI$'
|
||||||
reboot_required = False
|
reboot_required = False
|
||||||
db_change = False
|
db_change = False
|
||||||
success = False
|
success = False
|
||||||
|
@ -1659,13 +1659,13 @@ def configuration_helper(origin):
|
||||||
logging.getLogger("book_formats").setLevel(config.config_log_level)
|
logging.getLogger("book_formats").setLevel(config.config_log_level)
|
||||||
except e:
|
except e:
|
||||||
flash(e, category="error")
|
flash(e, category="error")
|
||||||
return render_title_template("config_edit.html", content=config, origin=origin,
|
return render_title_template("config_edit.html", content=config, origin=origin, commit=commit,
|
||||||
title=_(u"Basic Configuration"))
|
title=_(u"Basic Configuration"))
|
||||||
if db_change:
|
if db_change:
|
||||||
reload(db)
|
reload(db)
|
||||||
if not db.setup_db():
|
if not db.setup_db():
|
||||||
flash(_(u'DB location is not valid, please enter correct path'), category="error")
|
flash(_(u'DB location is not valid, please enter correct path'), category="error")
|
||||||
return render_title_template("config_edit.html", content=config, origin=origin,
|
return render_title_template("config_edit.html", content=config, origin=origin, commit=commit,
|
||||||
title=_(u"Basic Configuration"))
|
title=_(u"Basic Configuration"))
|
||||||
if reboot_required:
|
if reboot_required:
|
||||||
# db.engine.dispose() # ToDo verify correct
|
# db.engine.dispose() # ToDo verify correct
|
||||||
|
@ -1678,7 +1678,7 @@ def configuration_helper(origin):
|
||||||
app.logger.info('Reboot required, restarting')
|
app.logger.info('Reboot required, restarting')
|
||||||
if origin:
|
if origin:
|
||||||
success = True
|
success = True
|
||||||
return render_title_template("config_edit.html", origin=origin, success=success, content=config,
|
return render_title_template("config_edit.html", origin=origin, success=success, content=config, commit=commit,
|
||||||
title=_(u"Basic Configuration"))
|
title=_(u"Basic Configuration"))
|
||||||
|
|
||||||
|
|
||||||
|
@ -1927,7 +1927,7 @@ def edit_book(book_id):
|
||||||
modify_database_object(input_authors, book.authors, db.Authors, db.session, 'author')
|
modify_database_object(input_authors, book.authors, db.Authors, db.session, 'author')
|
||||||
if author0_before_edit != book.authors[0].name:
|
if author0_before_edit != book.authors[0].name:
|
||||||
edited_books_id.add(book.id)
|
edited_books_id.add(book.id)
|
||||||
book.author_sort=helper.get_normalized_author(input_authors[0]) # ToDo: wrong sorting
|
book.author_sort=helper.get_sorted_author(input_authors[0])
|
||||||
|
|
||||||
if to_save["cover_url"] and os.path.splitext(to_save["cover_url"])[1].lower() == ".jpg":
|
if to_save["cover_url"] and os.path.splitext(to_save["cover_url"])[1].lower() == ".jpg":
|
||||||
img = requests.get(to_save["cover_url"])
|
img = requests.get(to_save["cover_url"])
|
||||||
|
@ -2155,9 +2155,10 @@ def upload():
|
||||||
if is_author:
|
if is_author:
|
||||||
db_author = is_author
|
db_author = is_author
|
||||||
else:
|
else:
|
||||||
db_author = db.Authors(author, helper.get_normalized_author(author), "") # TODO: WRONG Sorting Author function
|
db_author = db.Authors(author, helper.get_sorted_author(author), "")
|
||||||
db.session.add(db_author)
|
db.session.add(db_author)
|
||||||
path = os.path.join(author_dir, title_dir)
|
# combine path and normalize path from windows systems
|
||||||
|
path = os.path.join(author_dir, title_dir).replace('\\','/')
|
||||||
db_book = db.Books(title, "", db_author.sort, datetime.datetime.now(), datetime.datetime(101, 01, 01), 1,
|
db_book = db.Books(title, "", db_author.sort, datetime.datetime.now(), datetime.datetime(101, 01, 01), 1,
|
||||||
datetime.datetime.now(), path, has_cover, db_author, [])
|
datetime.datetime.now(), path, has_cover, db_author, [])
|
||||||
db_book.authors.append(db_author)
|
db_book.authors.append(db_author)
|
||||||
|
|
|
@ -11,7 +11,7 @@ Calibre Web is a web app providing a clean interface for browsing, reading and d
|
||||||
- full graphical setup
|
- full graphical setup
|
||||||
- User management
|
- User management
|
||||||
- Admin interface
|
- Admin interface
|
||||||
- User Interface in english, french, german, simplified chinese, spanish
|
- User Interface in english, french, german, polish, simplified chinese, spanish
|
||||||
- OPDS feed for eBook reader apps
|
- OPDS feed for eBook reader apps
|
||||||
- Filter and search by titles, authors, tags, series and language
|
- Filter and search by titles, authors, tags, series and language
|
||||||
- Create custom book collection (shelves)
|
- Create custom book collection (shelves)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user