Merge with branch develop
Release version
This commit is contained in:
parent
3a70c86f49
commit
7c89f0b5b9
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -21,14 +21,12 @@ vendor/
|
||||||
# calibre-web
|
# calibre-web
|
||||||
*.db
|
*.db
|
||||||
*.log
|
*.log
|
||||||
config.ini
|
|
||||||
cps/static/[0-9]*
|
|
||||||
|
|
||||||
.idea/
|
.idea/
|
||||||
*.bak
|
*.bak
|
||||||
*.log.*
|
*.log.*
|
||||||
tags
|
|
||||||
|
|
||||||
settings.yaml
|
settings.yaml
|
||||||
gdrive_credentials
|
gdrive_credentials
|
||||||
client_secrets.json
|
client_secrets.json
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ parser.add_argument('-k', metavar='path',
|
||||||
help='path and name to SSL keyfile, e.g. /opt/test.key, works only in combination with certfile')
|
help='path and name to SSL keyfile, e.g. /opt/test.key, works only in combination with certfile')
|
||||||
parser.add_argument('-v', '--version', action='version', help='Shows version number and exits Calibre-web',
|
parser.add_argument('-v', '--version', action='version', help='Shows version number and exits Calibre-web',
|
||||||
version=version_info())
|
version=version_info())
|
||||||
parser.add_argument('-i', metavar='ip-adress', help='Server IP-Adress to listen')
|
parser.add_argument('-i', metavar='ip-address', help='Server IP-Address to listen')
|
||||||
parser.add_argument('-s', metavar='user:pass', help='Sets specific username to new password')
|
parser.add_argument('-s', metavar='user:pass', help='Sets specific username to new password')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,6 @@ except ValueError:
|
||||||
del env_CALIBRE_PORT
|
del env_CALIBRE_PORT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EXTENSIONS_AUDIO = {'mp3', 'm4a', 'm4b'}
|
EXTENSIONS_AUDIO = {'mp3', 'm4a', 'm4b'}
|
||||||
EXTENSIONS_CONVERT = {'pdf', 'epub', 'mobi', 'azw3', 'docx', 'rtf', 'fb2', 'lit', 'lrf', 'txt', 'htmlz', 'rtf', 'odt'}
|
EXTENSIONS_CONVERT = {'pdf', 'epub', 'mobi', 'azw3', 'docx', 'rtf', 'fb2', 'lit', 'lrf', 'txt', 'htmlz', 'rtf', 'odt'}
|
||||||
EXTENSIONS_UPLOAD = {'txt', 'pdf', 'epub', 'mobi', 'azw', 'azw3', 'cbr', 'cbz', 'cbt', 'djvu', 'prc', 'doc', 'docx',
|
EXTENSIONS_UPLOAD = {'txt', 'pdf', 'epub', 'mobi', 'azw', 'azw3', 'cbr', 'cbz', 'cbt', 'djvu', 'prc', 'doc', 'docx',
|
||||||
|
@ -126,7 +125,7 @@ def selected_roles(dictionary):
|
||||||
BookMeta = namedtuple('BookMeta', 'file_path, extension, title, author, cover, description, tags, series, '
|
BookMeta = namedtuple('BookMeta', 'file_path, extension, title, author, cover, description, tags, series, '
|
||||||
'series_id, languages')
|
'series_id, languages')
|
||||||
|
|
||||||
STABLE_VERSION = {'version': '0.6.6 Beta'}
|
STABLE_VERSION = {'version': '0.6.6'}
|
||||||
|
|
||||||
NIGHTLY_VERSION = {}
|
NIGHTLY_VERSION = {}
|
||||||
NIGHTLY_VERSION[0] = '$Format:%H$'
|
NIGHTLY_VERSION[0] = '$Format:%H$'
|
||||||
|
|
11
cps/db.py
11
cps/db.py
|
@ -25,13 +25,13 @@ import ast
|
||||||
|
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
from sqlalchemy import Table, Column, ForeignKey
|
from sqlalchemy import Table, Column, ForeignKey
|
||||||
from sqlalchemy import String, Integer, Boolean
|
from sqlalchemy import String, Integer, Boolean, Float
|
||||||
from sqlalchemy.orm import relationship, sessionmaker, scoped_session
|
from sqlalchemy.orm import relationship, sessionmaker, scoped_session
|
||||||
from sqlalchemy.ext.declarative import declarative_base
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
|
|
||||||
|
|
||||||
session = None
|
session = None
|
||||||
cc_exceptions = ['datetime', 'comments', 'float', 'composite', 'series']
|
cc_exceptions = ['datetime', 'comments', 'composite', 'series']
|
||||||
cc_classes = {}
|
cc_classes = {}
|
||||||
engine = None
|
engine = None
|
||||||
|
|
||||||
|
@ -378,6 +378,11 @@ def setup_db(config):
|
||||||
'id': Column(Integer, primary_key=True),
|
'id': Column(Integer, primary_key=True),
|
||||||
'book': Column(Integer, ForeignKey('books.id')),
|
'book': Column(Integer, ForeignKey('books.id')),
|
||||||
'value': Column(Integer)}
|
'value': Column(Integer)}
|
||||||
|
elif row.datatype == 'float':
|
||||||
|
ccdict = {'__tablename__': 'custom_column_' + str(row.id),
|
||||||
|
'id': Column(Integer, primary_key=True),
|
||||||
|
'book': Column(Integer, ForeignKey('books.id')),
|
||||||
|
'value': Column(Float)}
|
||||||
else:
|
else:
|
||||||
ccdict = {'__tablename__': 'custom_column_' + str(row.id),
|
ccdict = {'__tablename__': 'custom_column_' + str(row.id),
|
||||||
'id': Column(Integer, primary_key=True),
|
'id': Column(Integer, primary_key=True),
|
||||||
|
@ -385,7 +390,7 @@ def setup_db(config):
|
||||||
cc_classes[row.id] = type(str('Custom_Column_' + str(row.id)), (Base,), ccdict)
|
cc_classes[row.id] = type(str('Custom_Column_' + str(row.id)), (Base,), ccdict)
|
||||||
|
|
||||||
for cc_id in cc_ids:
|
for cc_id in cc_ids:
|
||||||
if (cc_id[1] == 'bool') or (cc_id[1] == 'int'):
|
if (cc_id[1] == 'bool') or (cc_id[1] == 'int') or (cc_id[1] == 'float'):
|
||||||
setattr(Books, 'custom_column_' + str(cc_id[0]), relationship(cc_classes[cc_id[0]],
|
setattr(Books, 'custom_column_' + str(cc_id[0]), relationship(cc_classes[cc_id[0]],
|
||||||
primaryjoin=(
|
primaryjoin=(
|
||||||
Books.id == cc_classes[cc_id[0]].book),
|
Books.id == cc_classes[cc_id[0]].book),
|
||||||
|
|
|
@ -175,7 +175,7 @@ def delete_book(book_id, book_format):
|
||||||
cc_string = "custom_column_" + str(c.id)
|
cc_string = "custom_column_" + str(c.id)
|
||||||
if not c.is_multiple:
|
if not c.is_multiple:
|
||||||
if len(getattr(book, cc_string)) > 0:
|
if len(getattr(book, cc_string)) > 0:
|
||||||
if c.datatype == 'bool' or c.datatype == 'integer':
|
if c.datatype == 'bool' or c.datatype == 'integer' or c.datatype == 'float':
|
||||||
del_cc = getattr(book, cc_string)[0]
|
del_cc = getattr(book, cc_string)[0]
|
||||||
getattr(book, cc_string).remove(del_cc)
|
getattr(book, cc_string).remove(del_cc)
|
||||||
db.session.delete(del_cc)
|
db.session.delete(del_cc)
|
||||||
|
@ -254,7 +254,7 @@ def edit_cc_data(book_id, book, to_save):
|
||||||
else:
|
else:
|
||||||
cc_db_value = None
|
cc_db_value = None
|
||||||
if to_save[cc_string].strip():
|
if to_save[cc_string].strip():
|
||||||
if c.datatype == 'int' or c.datatype == 'bool':
|
if c.datatype == 'int' or c.datatype == 'bool' or c.datatype == 'float':
|
||||||
if to_save[cc_string] == 'None':
|
if to_save[cc_string] == 'None':
|
||||||
to_save[cc_string] = None
|
to_save[cc_string] = None
|
||||||
elif c.datatype == 'bool':
|
elif c.datatype == 'bool':
|
||||||
|
@ -697,7 +697,6 @@ def upload():
|
||||||
# Reread book. It's important not to filter the result, as it could have language which hide it from
|
# Reread book. It's important not to filter the result, as it could have language which hide it from
|
||||||
# current users view (tags are not stored/extracted from metadata and could also be limited)
|
# current users view (tags are not stored/extracted from metadata and could also be limited)
|
||||||
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()
|
||||||
|
|
||||||
# upload book to gdrive if nesseccary and add "(bookid)" to folder name
|
# upload book to gdrive if nesseccary and add "(bookid)" to folder name
|
||||||
if config.config_use_google_drive:
|
if config.config_use_google_drive:
|
||||||
gdriveutils.updateGdriveCalibreFromLocal()
|
gdriveutils.updateGdriveCalibreFromLocal()
|
||||||
|
|
|
@ -156,7 +156,7 @@ class WebServer(object):
|
||||||
max_buffer_size=209700000,
|
max_buffer_size=209700000,
|
||||||
ssl_options=self.ssl_args)
|
ssl_options=self.ssl_args)
|
||||||
http_server.listen(self.listen_port, self.listen_address)
|
http_server.listen(self.listen_port, self.listen_address)
|
||||||
self.wsgiserver = IOLoop.instance()
|
self.wsgiserver = IOLoop.current()
|
||||||
self.wsgiserver.start()
|
self.wsgiserver.start()
|
||||||
# wait for stop signal
|
# wait for stop signal
|
||||||
self.wsgiserver.close(True)
|
self.wsgiserver.close(True)
|
||||||
|
@ -177,6 +177,8 @@ class WebServer(object):
|
||||||
|
|
||||||
if not self.restart:
|
if not self.restart:
|
||||||
log.info("Performing shutdown of Calibre-Web")
|
log.info("Performing shutdown of Calibre-Web")
|
||||||
|
# prevent irritiating log of pending tasks message from asyncio
|
||||||
|
logger.get('asyncio').setLevel(logger.logging.CRITICAL)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
log.info("Performing restart of Calibre-Web")
|
log.info("Performing restart of Calibre-Web")
|
||||||
|
@ -197,4 +199,4 @@ class WebServer(object):
|
||||||
if _GEVENT:
|
if _GEVENT:
|
||||||
self.wsgiserver.close()
|
self.wsgiserver.close()
|
||||||
else:
|
else:
|
||||||
self.wsgiserver.add_callback(self.wsgiserver.stop)
|
self.wsgiserver.add_callback_from_signal(self.wsgiserver.stop)
|
||||||
|
|
|
@ -159,10 +159,12 @@ if ( $( 'body.book' ).length > 0 ) {
|
||||||
real_custom_column = $( '.real_custom_columns' );
|
real_custom_column = $( '.real_custom_columns' );
|
||||||
// $( '.real_custom_columns' ).remove();
|
// $( '.real_custom_columns' ).remove();
|
||||||
$.each(real_custom_column, function(i, val) {
|
$.each(real_custom_column, function(i, val) {
|
||||||
real_cc = $(this).text().split( ':' );
|
var split = $(this).text().split( ':' );
|
||||||
|
real_cc_key = split.shift();
|
||||||
|
real_cc_value = split.join(':');
|
||||||
$( this ).text("");
|
$( this ).text("");
|
||||||
if (real_cc.length > 1) {
|
if (real_cc_value != "") {
|
||||||
$( this ).append( '<span>' + real_cc[0] + '</span><span>' + real_cc[1] + '</span>' );
|
$( this ).append( '<span>' + real_cc_key + '</span><span>' + real_cc_value + '</span>' );
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
//$( '.real_custom_columns:nth-child(3)' ).text(function() {
|
//$( '.real_custom_columns:nth-child(3)' ).text(function() {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
{% extends "layout.html" %}
|
{% extends "layout.html" %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
{% if book %}
|
{% if book %}
|
||||||
|
|
||||||
|
|
||||||
<div class="col-sm-3 col-lg-3 col-xs-12">
|
<div class="col-sm-3 col-lg-3 col-xs-12">
|
||||||
<div class="cover">
|
<div class="cover">
|
||||||
<img src="{{ url_for('web.get_cover', book_id=book.id) }}" alt="{{ book.title }}"/>
|
<img src="{{ url_for('web.get_cover', book_id=book.id) }}" alt="{{ book.title }}"/>
|
||||||
|
@ -115,8 +113,8 @@
|
||||||
</select>
|
</select>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if c.datatype == 'int' %}
|
{% if c.datatype == 'int' or c.datatype == 'float' %}
|
||||||
<input type="number" step="1" class="form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}" value="{% if book['custom_column_' ~ c.id]|length > 0 %}{{ book['custom_column_' ~ c.id][0].value }}{% endif %}">
|
<input type="number" step="{% if c.datatype == 'float' %}0.01{% else %}1{% endif %}" class="form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}" value="{% if book['custom_column_' ~ c.id]|length > 0 %}{{ book['custom_column_' ~ c.id][0].value }}{% endif %}">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if c.datatype in ['text', 'series'] and not c.is_multiple %}
|
{% if c.datatype in ['text', 'series'] and not c.is_multiple %}
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
<label for="query" class="sr-only">{{_('Search')}}</label>
|
<label for="query" class="sr-only">{{_('Search')}}</label>
|
||||||
<input type="text" class="form-control" id="query" name="query" placeholder="{{_('Search')}}">
|
<input type="text" class="form-control" id="query" name="query" placeholder="{{_('Search')}}">
|
||||||
<span class="input-group-btn">
|
<span class="input-group-btn">
|
||||||
<button type="submit" class="btn btn-default">{{_('Go!')}}</button>
|
<button type="submit" id="query_submit" class="btn btn-default">{{_('Go!')}}</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
<div class="navbar-collapse collapse">
|
<div class="navbar-collapse collapse">
|
||||||
{% if g.user.is_authenticated or g.allow_anonymous %}
|
{% if g.user.is_authenticated or g.allow_anonymous %}
|
||||||
<ul class="nav navbar-nav ">
|
<ul class="nav navbar-nav ">
|
||||||
<li><a href="{{url_for('web.advanced_search')}}"><span class="glyphicon glyphicon-search"></span><span class="hidden-sm">{{_('Advanced Search')}}</span></a></li>
|
<li><a href="{{url_for('web.advanced_search')}}" id="advanced_search"><span class="glyphicon glyphicon-search"></span><span class="hidden-sm">{{_('Advanced Search')}}</span></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<ul class="nav navbar-nav navbar-right" id="main-nav">
|
<ul class="nav navbar-nav navbar-right" id="main-nav">
|
||||||
|
@ -229,7 +229,6 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% block js %}{% endblock %}
|
{% block js %}{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -167,7 +167,7 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<button type="submit" class="btn btn-default">{{_('Submit')}}</button>
|
<button type="submit" id="adv_submit" class="btn btn-default">{{_('Submit')}}</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -5,19 +5,19 @@
|
||||||
<div>{{_('Drag \'n drop to rearrange order')}}</div>
|
<div>{{_('Drag \'n drop to rearrange order')}}</div>
|
||||||
<div id="sortTrue" class="list-group">
|
<div id="sortTrue" class="list-group">
|
||||||
{% for entry in entries %}
|
{% for entry in entries %}
|
||||||
<div id="{{entry.id}}" class="list-group-item">
|
<div id="{{entry['id']}}" class="list-group-item">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-2 col-sm-4 hidden-xs">
|
<div class="col-lg-2 col-sm-4 hidden-xs">
|
||||||
<img class="cover-height" src="{{ url_for('web.get_cover', book_id=entry.id) }}">
|
<img class="cover-height" src="{{ url_for('web.get_cover', book_id=entry['id']) }}">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-10 col-sm-8 col-xs-12">
|
<div class="col-lg-10 col-sm-8 col-xs-12">
|
||||||
{{entry.title}}
|
{{entry['title']}}
|
||||||
{% if entry.series|length > 0 %}
|
{% if entry['series']|length > 0 %}
|
||||||
<br>
|
<br>
|
||||||
{{entry.series_index}} - {{entry.series[0].name}}
|
{{entry['series_index']}} - {{entry['series'][0].name}}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<br>
|
<br>
|
||||||
{% for author in entry.authors %}
|
{% for author in entry['authors'] %}
|
||||||
{{author.name.replace('|',',')}}
|
{{author.name.replace('|',',')}}
|
||||||
{% if not loop.last %}
|
{% if not loop.last %}
|
||||||
&
|
&
|
||||||
|
|
|
@ -46,7 +46,6 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if registered_oauth.keys()| length > 0 %}
|
{% if registered_oauth.keys()| length > 0 %}
|
||||||
{% for id, name in registered_oauth.items() %}
|
{% for id, name in registered_oauth.items() %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -60,7 +59,6 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
{% for element in sidebar %}
|
{% for element in sidebar %}
|
||||||
{% if element['config_show'] %}
|
{% if element['config_show'] %}
|
||||||
|
|
|
@ -307,7 +307,7 @@ class RemoteAuthToken(Base):
|
||||||
__tablename__ = 'remote_auth_token'
|
__tablename__ = 'remote_auth_token'
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True)
|
id = Column(Integer, primary_key=True)
|
||||||
auth_token = Column(String(8), unique=True)
|
auth_token = Column(String, unique=True)
|
||||||
user_id = Column(Integer, ForeignKey('user.id'))
|
user_id = Column(Integer, ForeignKey('user.id'))
|
||||||
verified = Column(Boolean, default=False)
|
verified = Column(Boolean, default=False)
|
||||||
expiration = Column(DateTime)
|
expiration = Column(DateTime)
|
||||||
|
|
|
@ -198,7 +198,7 @@ class Updater(threading.Thread):
|
||||||
)
|
)
|
||||||
additional_path = self.is_venv()
|
additional_path = self.is_venv()
|
||||||
if additional_path:
|
if additional_path:
|
||||||
exclude = exclude + (additional_path)
|
exclude = exclude + (additional_path,)
|
||||||
for root, dirs, files in os.walk(destination, topdown=True):
|
for root, dirs, files in os.walk(destination, topdown=True):
|
||||||
for name in files:
|
for name in files:
|
||||||
old_list.append(os.path.join(root, name).replace(destination, ''))
|
old_list.append(os.path.join(root, name).replace(destination, ''))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user