Merge branch 'master' into Develop
# Conflicts: # cps/__init__.py # cps/comic.py # cps/editbooks.py # cps/helper.py # cps/kobo.py # cps/translations/nl/LC_MESSAGES/messages.mo # cps/translations/nl/LC_MESSAGES/messages.po # cps/ub.py # cps/uploader.py # cps/web.py
This commit is contained in:
commit
b160a8de0b
12
cps/__init__.py
Executable file → Normal file
12
cps/__init__.py
Executable file → Normal file
|
@ -36,6 +36,10 @@ from flask_principal import Principal
|
||||||
from . import config_sql, logger, cache_buster, cli, ub, db
|
from . import config_sql, logger, cache_buster, cli, ub, db
|
||||||
from .reverseproxy import ReverseProxied
|
from .reverseproxy import ReverseProxied
|
||||||
from .server import WebServer
|
from .server import WebServer
|
||||||
|
try:
|
||||||
|
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||||
|
except ImportError:
|
||||||
|
from werkzeug.contrib.fixers import ProxyFix
|
||||||
|
|
||||||
mimetypes.init()
|
mimetypes.init()
|
||||||
mimetypes.add_type('application/xhtml+xml', '.xhtml')
|
mimetypes.add_type('application/xhtml+xml', '.xhtml')
|
||||||
|
@ -76,7 +80,10 @@ log = logger.create()
|
||||||
from . import services
|
from . import services
|
||||||
|
|
||||||
def create_app():
|
def create_app():
|
||||||
app.wsgi_app = ReverseProxied(app.wsgi_app)
|
try:
|
||||||
|
app.wsgi_app = ReverseProxied(ProxyFix(app.wsgi_app, x_for=1, x_host=1))
|
||||||
|
except TypeError:
|
||||||
|
app.wsgi_app = ReverseProxied(ProxyFix(app.wsgi_app))
|
||||||
# For python2 convert path to unicode
|
# For python2 convert path to unicode
|
||||||
if sys.version_info < (3, 0):
|
if sys.version_info < (3, 0):
|
||||||
app.static_folder = app.static_folder.decode('utf-8')
|
app.static_folder = app.static_folder.decode('utf-8')
|
||||||
|
@ -88,7 +95,10 @@ def create_app():
|
||||||
log.info('Starting Calibre Web...')
|
log.info('Starting Calibre Web...')
|
||||||
Principal(app)
|
Principal(app)
|
||||||
lm.init_app(app)
|
lm.init_app(app)
|
||||||
|
if os.environ.get('FLASK_DEBUG'):
|
||||||
app.secret_key = os.getenv('SECRET_KEY', 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT')
|
app.secret_key = os.getenv('SECRET_KEY', 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT')
|
||||||
|
else:
|
||||||
|
app.secret_key = os.getenv('SECRET_KEY', os.urandom(32))
|
||||||
|
|
||||||
web_server.init_app(app, config)
|
web_server.init_app(app, config)
|
||||||
db.setup_db(config)
|
db.setup_db(config)
|
||||||
|
|
70
cps/admin.py
70
cps/admin.py
|
@ -50,11 +50,11 @@ feature_support = {
|
||||||
'kobo': bool(services.kobo)
|
'kobo': bool(services.kobo)
|
||||||
}
|
}
|
||||||
|
|
||||||
# try:
|
try:
|
||||||
# import rarfile
|
import rarfile
|
||||||
# feature_support['rar'] = True
|
feature_support['rar'] = True
|
||||||
# except ImportError:
|
except ImportError:
|
||||||
# feature_support['rar'] = False
|
feature_support['rar'] = False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from .oauth_bb import oauth_check, oauthblueprints
|
from .oauth_bb import oauth_check, oauthblueprints
|
||||||
|
@ -253,23 +253,23 @@ def list_domain(allow):
|
||||||
response.headers["Content-Type"] = "application/json; charset=utf-8"
|
response.headers["Content-Type"] = "application/json; charset=utf-8"
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@admi.route("/ajax/editrestriction/<int:type>", methods=['POST'])
|
@admi.route("/ajax/editrestriction/<int:res_type>", methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_required
|
@admin_required
|
||||||
def edit_restriction(type):
|
def edit_restriction(res_type):
|
||||||
element = request.form.to_dict()
|
element = request.form.to_dict()
|
||||||
if element['id'].startswith('a'):
|
if element['id'].startswith('a'):
|
||||||
if type == 0: # Tags as template
|
if res_type == 0: # Tags as template
|
||||||
elementlist = config.list_allowed_tags()
|
elementlist = config.list_allowed_tags()
|
||||||
elementlist[int(element['id'][1:])]=element['Element']
|
elementlist[int(element['id'][1:])]=element['Element']
|
||||||
config.config_allowed_tags = ','.join(elementlist)
|
config.config_allowed_tags = ','.join(elementlist)
|
||||||
config.save()
|
config.save()
|
||||||
if type == 1: # CustomC
|
if res_type == 1: # CustomC
|
||||||
elementlist = config.list_allowed_column_values()
|
elementlist = config.list_allowed_column_values()
|
||||||
elementlist[int(element['id'][1:])]=element['Element']
|
elementlist[int(element['id'][1:])]=element['Element']
|
||||||
config.config_allowed_column_value = ','.join(elementlist)
|
config.config_allowed_column_value = ','.join(elementlist)
|
||||||
config.save()
|
config.save()
|
||||||
if type == 2: # Tags per user
|
if res_type == 2: # Tags per user
|
||||||
usr_id = os.path.split(request.referrer)[-1]
|
usr_id = os.path.split(request.referrer)[-1]
|
||||||
if usr_id.isdigit() == True:
|
if usr_id.isdigit() == True:
|
||||||
usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first()
|
usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first()
|
||||||
|
@ -279,7 +279,7 @@ def edit_restriction(type):
|
||||||
elementlist[int(element['id'][1:])]=element['Element']
|
elementlist[int(element['id'][1:])]=element['Element']
|
||||||
usr.allowed_tags = ','.join(elementlist)
|
usr.allowed_tags = ','.join(elementlist)
|
||||||
ub.session.commit()
|
ub.session.commit()
|
||||||
if type == 3: # CColumn per user
|
if res_type == 3: # CColumn per user
|
||||||
usr_id = os.path.split(request.referrer)[-1]
|
usr_id = os.path.split(request.referrer)[-1]
|
||||||
if usr_id.isdigit() == True:
|
if usr_id.isdigit() == True:
|
||||||
usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first()
|
usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first()
|
||||||
|
@ -290,18 +290,17 @@ def edit_restriction(type):
|
||||||
usr.allowed_column_value = ','.join(elementlist)
|
usr.allowed_column_value = ','.join(elementlist)
|
||||||
ub.session.commit()
|
ub.session.commit()
|
||||||
if element['id'].startswith('d'):
|
if element['id'].startswith('d'):
|
||||||
if type == 0: # Tags as template
|
if res_type == 0: # Tags as template
|
||||||
elementlist = config.list_denied_tags()
|
elementlist = config.list_denied_tags()
|
||||||
elementlist[int(element['id'][1:])]=element['Element']
|
elementlist[int(element['id'][1:])]=element['Element']
|
||||||
config.config_denied_tags = ','.join(elementlist)
|
config.config_denied_tags = ','.join(elementlist)
|
||||||
config.save()
|
config.save()
|
||||||
if type == 1: # CustomC
|
if res_type == 1: # CustomC
|
||||||
elementlist = config.list_denied_column_values()
|
elementlist = config.list_denied_column_values()
|
||||||
elementlist[int(element['id'][1:])]=element['Element']
|
elementlist[int(element['id'][1:])]=element['Element']
|
||||||
config.config_denied_column_value = ','.join(elementlist)
|
config.config_denied_column_value = ','.join(elementlist)
|
||||||
config.save()
|
config.save()
|
||||||
pass
|
if res_type == 2: # Tags per user
|
||||||
if type == 2: # Tags per user
|
|
||||||
usr_id = os.path.split(request.referrer)[-1]
|
usr_id = os.path.split(request.referrer)[-1]
|
||||||
if usr_id.isdigit() == True:
|
if usr_id.isdigit() == True:
|
||||||
usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first()
|
usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first()
|
||||||
|
@ -311,7 +310,7 @@ def edit_restriction(type):
|
||||||
elementlist[int(element['id'][1:])]=element['Element']
|
elementlist[int(element['id'][1:])]=element['Element']
|
||||||
usr.denied_tags = ','.join(elementlist)
|
usr.denied_tags = ','.join(elementlist)
|
||||||
ub.session.commit()
|
ub.session.commit()
|
||||||
if type == 3: # CColumn per user
|
if res_type == 3: # CColumn per user
|
||||||
usr_id = os.path.split(request.referrer)[-1]
|
usr_id = os.path.split(request.referrer)[-1]
|
||||||
if usr_id.isdigit() == True:
|
if usr_id.isdigit() == True:
|
||||||
usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first()
|
usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first()
|
||||||
|
@ -339,26 +338,26 @@ def restriction_deletion(element, list_func):
|
||||||
return ','.join(elementlist)
|
return ','.join(elementlist)
|
||||||
|
|
||||||
|
|
||||||
@admi.route("/ajax/addrestriction/<int:type>", methods=['POST'])
|
@admi.route("/ajax/addrestriction/<int:res_type>", methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_required
|
@admin_required
|
||||||
def add_restriction(type):
|
def add_restriction(res_type):
|
||||||
element = request.form.to_dict()
|
element = request.form.to_dict()
|
||||||
if type == 0: # Tags as template
|
if res_type == 0: # Tags as template
|
||||||
if 'submit_allow' in element:
|
if 'submit_allow' in element:
|
||||||
config.config_allowed_tags = restriction_addition(element, config.list_allowed_tags)
|
config.config_allowed_tags = restriction_addition(element, config.list_allowed_tags)
|
||||||
config.save()
|
config.save()
|
||||||
elif 'submit_deny' in element:
|
elif 'submit_deny' in element:
|
||||||
config.config_denied_tags = restriction_addition(element, config.list_denied_tags)
|
config.config_denied_tags = restriction_addition(element, config.list_denied_tags)
|
||||||
config.save()
|
config.save()
|
||||||
if type == 1: # CCustom as template
|
if res_type == 1: # CCustom as template
|
||||||
if 'submit_allow' in element:
|
if 'submit_allow' in element:
|
||||||
config.config_allowed_column_value = restriction_addition(element, config.list_denied_column_values)
|
config.config_allowed_column_value = restriction_addition(element, config.list_denied_column_values)
|
||||||
config.save()
|
config.save()
|
||||||
elif 'submit_deny' in element:
|
elif 'submit_deny' in element:
|
||||||
config.config_denied_column_value = restriction_addition(element, config.list_allowed_column_values)
|
config.config_denied_column_value = restriction_addition(element, config.list_allowed_column_values)
|
||||||
config.save()
|
config.save()
|
||||||
if type == 2: # Tags per user
|
if res_type == 2: # Tags per user
|
||||||
usr_id = os.path.split(request.referrer)[-1]
|
usr_id = os.path.split(request.referrer)[-1]
|
||||||
if usr_id.isdigit() == True:
|
if usr_id.isdigit() == True:
|
||||||
usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first()
|
usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first()
|
||||||
|
@ -370,7 +369,7 @@ def add_restriction(type):
|
||||||
elif 'submit_deny' in element:
|
elif 'submit_deny' in element:
|
||||||
usr.denied_tags = restriction_addition(element, usr.list_denied_tags)
|
usr.denied_tags = restriction_addition(element, usr.list_denied_tags)
|
||||||
ub.session.commit()
|
ub.session.commit()
|
||||||
if type == 3: # CustomC per user
|
if res_type == 3: # CustomC per user
|
||||||
usr_id = os.path.split(request.referrer)[-1]
|
usr_id = os.path.split(request.referrer)[-1]
|
||||||
if usr_id.isdigit() == True:
|
if usr_id.isdigit() == True:
|
||||||
usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first()
|
usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first()
|
||||||
|
@ -384,26 +383,26 @@ def add_restriction(type):
|
||||||
ub.session.commit()
|
ub.session.commit()
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@admi.route("/ajax/deleterestriction/<int:type>", methods=['POST'])
|
@admi.route("/ajax/deleterestriction/<int:res_type>", methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@admin_required
|
@admin_required
|
||||||
def delete_restriction(type):
|
def delete_restriction(res_type):
|
||||||
element = request.form.to_dict()
|
element = request.form.to_dict()
|
||||||
if type == 0: # Tags as template
|
if res_type == 0: # Tags as template
|
||||||
if element['id'].startswith('a'):
|
if element['id'].startswith('a'):
|
||||||
config.config_allowed_tags = restriction_deletion(element, config.list_allowed_tags)
|
config.config_allowed_tags = restriction_deletion(element, config.list_allowed_tags)
|
||||||
config.save()
|
config.save()
|
||||||
elif element['id'].startswith('d'):
|
elif element['id'].startswith('d'):
|
||||||
config.config_denied_tags = restriction_deletion(element, config.list_denied_tags)
|
config.config_denied_tags = restriction_deletion(element, config.list_denied_tags)
|
||||||
config.save()
|
config.save()
|
||||||
elif type == 1: # CustomC as template
|
elif res_type == 1: # CustomC as template
|
||||||
if element['id'].startswith('a'):
|
if element['id'].startswith('a'):
|
||||||
config.config_allowed_column_value = restriction_deletion(element, config.list_allowed_column_values)
|
config.config_allowed_column_value = restriction_deletion(element, config.list_allowed_column_values)
|
||||||
config.save()
|
config.save()
|
||||||
elif element['id'].startswith('d'):
|
elif element['id'].startswith('d'):
|
||||||
config.config_denied_column_value = restriction_deletion(element, config.list_denied_column_values)
|
config.config_denied_column_value = restriction_deletion(element, config.list_denied_column_values)
|
||||||
config.save()
|
config.save()
|
||||||
elif type == 2: # Tags per user
|
elif res_type == 2: # Tags per user
|
||||||
usr_id = os.path.split(request.referrer)[-1]
|
usr_id = os.path.split(request.referrer)[-1]
|
||||||
if usr_id.isdigit() == True:
|
if usr_id.isdigit() == True:
|
||||||
usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first()
|
usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first()
|
||||||
|
@ -415,7 +414,7 @@ def delete_restriction(type):
|
||||||
elif element['id'].startswith('d'):
|
elif element['id'].startswith('d'):
|
||||||
usr.denied_tags = restriction_deletion(element, usr.list_denied_tags)
|
usr.denied_tags = restriction_deletion(element, usr.list_denied_tags)
|
||||||
ub.session.commit()
|
ub.session.commit()
|
||||||
elif type == 3: # Columns per user
|
elif res_type == 3: # Columns per user
|
||||||
usr_id = os.path.split(request.referrer)[-1]
|
usr_id = os.path.split(request.referrer)[-1]
|
||||||
if usr_id.isdigit() == True: # select current user if admins are editing their own rights
|
if usr_id.isdigit() == True: # select current user if admins are editing their own rights
|
||||||
usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first()
|
usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first()
|
||||||
|
@ -431,23 +430,23 @@ def delete_restriction(type):
|
||||||
|
|
||||||
|
|
||||||
#@admi.route("/ajax/listrestriction/<int:type>/<int:user_id>", defaults={'user_id': '0'})
|
#@admi.route("/ajax/listrestriction/<int:type>/<int:user_id>", defaults={'user_id': '0'})
|
||||||
@admi.route("/ajax/listrestriction/<int:type>")
|
@admi.route("/ajax/listrestriction/<int:res_type>")
|
||||||
@login_required
|
@login_required
|
||||||
@admin_required
|
@admin_required
|
||||||
def list_restriction(type):
|
def list_restriction(res_type):
|
||||||
if type == 0: # Tags as template
|
if res_type == 0: # Tags as template
|
||||||
restrict = [{'Element': x, 'type':_('Deny'), 'id': 'd'+str(i) }
|
restrict = [{'Element': x, 'type':_('Deny'), 'id': 'd'+str(i) }
|
||||||
for i,x in enumerate(config.list_denied_tags()) if x != '' ]
|
for i,x in enumerate(config.list_denied_tags()) if x != '' ]
|
||||||
allow = [{'Element': x, 'type':_('Allow'), 'id': 'a'+str(i) }
|
allow = [{'Element': x, 'type':_('Allow'), 'id': 'a'+str(i) }
|
||||||
for i,x in enumerate(config.list_allowed_tags()) if x != '']
|
for i,x in enumerate(config.list_allowed_tags()) if x != '']
|
||||||
json_dumps = restrict + allow
|
json_dumps = restrict + allow
|
||||||
elif type == 1: # CustomC as template
|
elif res_type == 1: # CustomC as template
|
||||||
restrict = [{'Element': x, 'type':_('Deny'), 'id': 'd'+str(i) }
|
restrict = [{'Element': x, 'type':_('Deny'), 'id': 'd'+str(i) }
|
||||||
for i,x in enumerate(config.list_denied_column_values()) if x != '' ]
|
for i,x in enumerate(config.list_denied_column_values()) if x != '' ]
|
||||||
allow = [{'Element': x, 'type':_('Allow'), 'id': 'a'+str(i) }
|
allow = [{'Element': x, 'type':_('Allow'), 'id': 'a'+str(i) }
|
||||||
for i,x in enumerate(config.list_allowed_column_values()) if x != '']
|
for i,x in enumerate(config.list_allowed_column_values()) if x != '']
|
||||||
json_dumps = restrict + allow
|
json_dumps = restrict + allow
|
||||||
elif type == 2: # Tags per user
|
elif res_type == 2: # Tags per user
|
||||||
usr_id = os.path.split(request.referrer)[-1]
|
usr_id = os.path.split(request.referrer)[-1]
|
||||||
if usr_id.isdigit() == True:
|
if usr_id.isdigit() == True:
|
||||||
usr = ub.session.query(ub.User).filter(ub.User.id == usr_id).first()
|
usr = ub.session.query(ub.User).filter(ub.User.id == usr_id).first()
|
||||||
|
@ -458,7 +457,7 @@ def list_restriction(type):
|
||||||
allow = [{'Element': x, 'type':_('Allow'), 'id': 'a'+str(i) }
|
allow = [{'Element': x, 'type':_('Allow'), 'id': 'a'+str(i) }
|
||||||
for i,x in enumerate(usr.list_allowed_tags()) if x != '']
|
for i,x in enumerate(usr.list_allowed_tags()) if x != '']
|
||||||
json_dumps = restrict + allow
|
json_dumps = restrict + allow
|
||||||
elif type == 3: # CustomC per user
|
elif res_type == 3: # CustomC per user
|
||||||
usr_id = os.path.split(request.referrer)[-1]
|
usr_id = os.path.split(request.referrer)[-1]
|
||||||
if usr_id.isdigit() == True:
|
if usr_id.isdigit() == True:
|
||||||
usr = ub.session.query(ub.User).filter(ub.User.id==usr_id).first()
|
usr = ub.session.query(ub.User).filter(ub.User.id==usr_id).first()
|
||||||
|
@ -540,8 +539,7 @@ def _configuration_update_helper():
|
||||||
_config_string("config_calibre")
|
_config_string("config_calibre")
|
||||||
_config_string("config_converterpath")
|
_config_string("config_converterpath")
|
||||||
|
|
||||||
if _config_int("config_login_type"):
|
reboot_required |= _config_int("config_login_type")
|
||||||
reboot_required |= config.config_login_type != constants.LOGIN_STANDARD
|
|
||||||
|
|
||||||
#LDAP configurator,
|
#LDAP configurator,
|
||||||
if config.config_login_type == constants.LOGIN_LDAP:
|
if config.config_login_type == constants.LOGIN_LDAP:
|
||||||
|
|
7
cps/comic.py
Executable file → Normal file
7
cps/comic.py
Executable file → Normal file
|
@ -43,9 +43,9 @@ except ImportError as e:
|
||||||
|
|
||||||
|
|
||||||
def _extractCover(tmp_file_name, original_file_extension, rarExceutable):
|
def _extractCover(tmp_file_name, original_file_extension, rarExceutable):
|
||||||
|
cover_data = extension = None
|
||||||
if use_comic_meta:
|
if use_comic_meta:
|
||||||
archive = ComicArchive(tmp_file_name)
|
archive = ComicArchive(tmp_file_name)
|
||||||
cover_data = None
|
|
||||||
for index, name in enumerate(archive.getPageNameList()):
|
for index, name in enumerate(archive.getPageNameList()):
|
||||||
ext = os.path.splitext(name)
|
ext = os.path.splitext(name)
|
||||||
if len(ext) > 1:
|
if len(ext) > 1:
|
||||||
|
@ -81,7 +81,7 @@ def _extractCover(tmp_file_name, original_file_extension, rarExceutable):
|
||||||
if len(ext) > 1:
|
if len(ext) > 1:
|
||||||
extension = ext[1].lower()
|
extension = ext[1].lower()
|
||||||
if extension == '.jpg' or extension == '.jpeg':
|
if extension == '.jpg' or extension == '.jpeg':
|
||||||
cover_data = cf.extractfile(name).read()
|
cover_data = cf.read(name)
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug('Rarfile failed with error: %s', e)
|
log.debug('Rarfile failed with error: %s', e)
|
||||||
|
@ -99,7 +99,7 @@ def _extractCover(tmp_file_name, original_file_extension, rarExceutable):
|
||||||
|
|
||||||
def get_comic_info(tmp_file_path, original_file_name, original_file_extension, rarExceutable):
|
def get_comic_info(tmp_file_path, original_file_name, original_file_extension, rarExceutable):
|
||||||
if use_comic_meta:
|
if use_comic_meta:
|
||||||
archive = ComicArchive(tmp_file_path)
|
archive = ComicArchive(tmp_file_path, rar_exe_path=rarExceutable)
|
||||||
if archive.seemsToBeAComicArchive():
|
if archive.seemsToBeAComicArchive():
|
||||||
if archive.hasMetadata(MetaDataStyle.CIX):
|
if archive.hasMetadata(MetaDataStyle.CIX):
|
||||||
style = MetaDataStyle.CIX
|
style = MetaDataStyle.CIX
|
||||||
|
@ -131,7 +131,6 @@ def get_comic_info(tmp_file_path, original_file_name, original_file_extension, r
|
||||||
series=loadedMetadata.series or "",
|
series=loadedMetadata.series or "",
|
||||||
series_id=loadedMetadata.issue or "",
|
series_id=loadedMetadata.issue or "",
|
||||||
languages=loadedMetadata.language)
|
languages=loadedMetadata.language)
|
||||||
else:
|
|
||||||
|
|
||||||
return BookMeta(
|
return BookMeta(
|
||||||
file_path=tmp_file_path,
|
file_path=tmp_file_path,
|
||||||
|
|
|
@ -102,8 +102,8 @@ DEFAULT_MAIL_SERVER = "mail.example.org"
|
||||||
|
|
||||||
DEFAULT_PASSWORD = "admin123"
|
DEFAULT_PASSWORD = "admin123"
|
||||||
DEFAULT_PORT = 8083
|
DEFAULT_PORT = 8083
|
||||||
try:
|
|
||||||
env_CALIBRE_PORT = os.environ.get("CALIBRE_PORT", DEFAULT_PORT)
|
env_CALIBRE_PORT = os.environ.get("CALIBRE_PORT", DEFAULT_PORT)
|
||||||
|
try:
|
||||||
DEFAULT_PORT = int(env_CALIBRE_PORT)
|
DEFAULT_PORT = int(env_CALIBRE_PORT)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print('Environment variable CALIBRE_PORT has invalid value (%s), faling back to default (8083)' % env_CALIBRE_PORT)
|
print('Environment variable CALIBRE_PORT has invalid value (%s), faling back to default (8083)' % env_CALIBRE_PORT)
|
||||||
|
|
|
@ -418,7 +418,7 @@ def dispose():
|
||||||
except: pass
|
except: pass
|
||||||
if old_session.bind:
|
if old_session.bind:
|
||||||
try: old_session.bind.dispose()
|
try: old_session.bind.dispose()
|
||||||
except: pass
|
except Exception: pass
|
||||||
|
|
||||||
for attr in list(Books.__dict__.keys()):
|
for attr in list(Books.__dict__.keys()):
|
||||||
if attr.startswith("custom_column_"):
|
if attr.startswith("custom_column_"):
|
||||||
|
|
|
@ -176,12 +176,12 @@ def delete_book(book_id, book_format):
|
||||||
if current_user.role_delete_books():
|
if current_user.role_delete_books():
|
||||||
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()
|
||||||
if book:
|
if book:
|
||||||
|
try:
|
||||||
helper.delete_book(book, config.config_calibre_dir, book_format=book_format.upper())
|
helper.delete_book(book, config.config_calibre_dir, book_format=book_format.upper())
|
||||||
if not book_format:
|
if not book_format:
|
||||||
# delete book from Shelfs, Downloads, Read list
|
# delete book from Shelfs, Downloads, Read list
|
||||||
ub.session.query(ub.BookShelf).filter(ub.BookShelf.book_id == book_id).delete()
|
ub.session.query(ub.BookShelf).filter(ub.BookShelf.book_id == book_id).delete()
|
||||||
ub.session.query(ub.ReadBook).filter(ub.ReadBook.book_id == book_id).delete()
|
ub.session.query(ub.ReadBook).filter(ub.ReadBook.book_id == book_id).delete()
|
||||||
ub.session.query(ub.ArchivedBook).filter(ub.ArchivedBook.book_id == book_id).delete()
|
|
||||||
ub.delete_download(book_id)
|
ub.delete_download(book_id)
|
||||||
ub.session.commit()
|
ub.session.commit()
|
||||||
|
|
||||||
|
@ -193,7 +193,8 @@ def delete_book(book_id, book_format):
|
||||||
modify_database_object([u''], book.languages, db.Languages, db.session, 'languages')
|
modify_database_object([u''], book.languages, db.Languages, db.session, 'languages')
|
||||||
modify_database_object([u''], book.publishers, db.Publishers, db.session, 'publishers')
|
modify_database_object([u''], book.publishers, db.Publishers, db.session, 'publishers')
|
||||||
|
|
||||||
cc = db.session.query(db.Custom_Columns).filter(db.Custom_Columns.datatype.notin_(db.cc_exceptions)).all()
|
cc = db.session.query(db.Custom_Columns).\
|
||||||
|
filter(db.Custom_Columns.datatype.notin_(db.cc_exceptions)).all()
|
||||||
for c in cc:
|
for c in cc:
|
||||||
cc_string = "custom_column_" + str(c.id)
|
cc_string = "custom_column_" + str(c.id)
|
||||||
if not c.is_multiple:
|
if not c.is_multiple:
|
||||||
|
@ -201,23 +202,33 @@ def delete_book(book_id, book_format):
|
||||||
if c.datatype == 'bool' or c.datatype == 'integer' or c.datatype == 'float':
|
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)
|
||||||
|
log.debug('remove ' + str(c.id))
|
||||||
db.session.delete(del_cc)
|
db.session.delete(del_cc)
|
||||||
|
db.session.commit()
|
||||||
elif c.datatype == 'rating':
|
elif c.datatype == 'rating':
|
||||||
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)
|
||||||
if len(del_cc.books) == 0:
|
if len(del_cc.books) == 0:
|
||||||
|
log.debug('remove ' + str(c.id))
|
||||||
db.session.delete(del_cc)
|
db.session.delete(del_cc)
|
||||||
|
db.session.commit()
|
||||||
else:
|
else:
|
||||||
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)
|
||||||
|
log.debug('remove ' + str(c.id))
|
||||||
db.session.delete(del_cc)
|
db.session.delete(del_cc)
|
||||||
|
db.session.commit()
|
||||||
else:
|
else:
|
||||||
modify_database_object([u''], getattr(book, cc_string), db.cc_classes[c.id],
|
modify_database_object([u''], getattr(book, cc_string), db.cc_classes[c.id],
|
||||||
db.session, 'custom')
|
db.session, 'custom')
|
||||||
db.session.query(db.Books).filter(db.Books.id == book_id).delete()
|
db.session.query(db.Books).filter(db.Books.id == book_id).delete()
|
||||||
else:
|
else:
|
||||||
db.session.query(db.Data).filter(db.Data.book == book.id).filter(db.Data.format == book_format).delete()
|
db.session.query(db.Data).filter(db.Data.book == book.id).\
|
||||||
|
filter(db.Data.format == book_format).delete()
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
except Exception as e:
|
||||||
|
log.debug(e)
|
||||||
|
db.session.rollback()
|
||||||
else:
|
else:
|
||||||
# book not found
|
# book not found
|
||||||
log.error('Book with id "%s" could not be deleted: not found', book_id)
|
log.error('Book with id "%s" could not be deleted: not found', book_id)
|
||||||
|
@ -524,11 +535,12 @@ def edit_book(book_id):
|
||||||
|
|
||||||
if not error:
|
if not error:
|
||||||
if to_save["cover_url"]:
|
if to_save["cover_url"]:
|
||||||
if helper.save_cover_from_url(to_save["cover_url"], book.path) is True:
|
result, error = helper.save_cover_from_url(to_save["cover_url"], book.path)
|
||||||
|
if result is True:
|
||||||
book.has_cover = 1
|
book.has_cover = 1
|
||||||
modif_date = True
|
modif_date = True
|
||||||
else:
|
else:
|
||||||
flash(_(u"Cover is not a jpg file, can't save"), category="error")
|
flash(error, category="error")
|
||||||
|
|
||||||
if book.series_index != to_save["series_index"]:
|
if book.series_index != to_save["series_index"]:
|
||||||
book.series_index = to_save["series_index"]
|
book.series_index = to_save["series_index"]
|
||||||
|
|
|
@ -298,6 +298,9 @@ def delete_book_file(book, calibrepath, book_format=None):
|
||||||
log.error("Deleting book %s failed, path has subfolders: %s", book.id, book.path)
|
log.error("Deleting book %s failed, path has subfolders: %s", book.id, book.path)
|
||||||
return False
|
return False
|
||||||
shutil.rmtree(path, ignore_errors=True)
|
shutil.rmtree(path, ignore_errors=True)
|
||||||
|
authorpath = os.path.join(calibrepath, os.path.split(book.path)[0])
|
||||||
|
if not os.listdir(authorpath):
|
||||||
|
shutil.rmtree(authorpath, ignore_errors=True)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
log.error("Deleting book %s failed, book path not valid: %s", book.id, book.path)
|
log.error("Deleting book %s failed, book path not valid: %s", book.id, book.path)
|
||||||
|
@ -318,8 +321,8 @@ def update_dir_structure_file(book_id, calibrepath, first_author):
|
||||||
new_titledir = get_valid_filename(localbook.title) + " (" + str(book_id) + ")"
|
new_titledir = get_valid_filename(localbook.title) + " (" + str(book_id) + ")"
|
||||||
|
|
||||||
if titledir != new_titledir:
|
if titledir != new_titledir:
|
||||||
try:
|
|
||||||
new_title_path = os.path.join(os.path.dirname(path), new_titledir)
|
new_title_path = os.path.join(os.path.dirname(path), new_titledir)
|
||||||
|
try:
|
||||||
if not os.path.exists(new_title_path):
|
if not os.path.exists(new_title_path):
|
||||||
os.renames(path, new_title_path)
|
os.renames(path, new_title_path)
|
||||||
else:
|
else:
|
||||||
|
@ -336,8 +339,8 @@ def update_dir_structure_file(book_id, calibrepath, first_author):
|
||||||
return _("Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s",
|
return _("Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s",
|
||||||
src=path, dest=new_title_path, error=str(ex))
|
src=path, dest=new_title_path, error=str(ex))
|
||||||
if authordir != new_authordir:
|
if authordir != new_authordir:
|
||||||
try:
|
|
||||||
new_author_path = os.path.join(calibrepath, new_authordir, os.path.basename(path))
|
new_author_path = os.path.join(calibrepath, new_authordir, os.path.basename(path))
|
||||||
|
try:
|
||||||
os.renames(path, new_author_path)
|
os.renames(path, new_author_path)
|
||||||
localbook.path = new_authordir + '/' + localbook.path.split('/')[1]
|
localbook.path = new_authordir + '/' + localbook.path.split('/')[1]
|
||||||
except OSError as ex:
|
except OSError as ex:
|
||||||
|
@ -530,12 +533,9 @@ def save_cover_from_filestorage(filepath, saved_filename, img):
|
||||||
return False, _(u"Failed to create path for cover")
|
return False, _(u"Failed to create path for cover")
|
||||||
try:
|
try:
|
||||||
img.save(os.path.join(filepath, saved_filename))
|
img.save(os.path.join(filepath, saved_filename))
|
||||||
except IOError:
|
except (IOError, OSError):
|
||||||
log.error(u"Cover-file is not a valid image file")
|
log.error(u"Cover-file is not a valid image file, or could not be stored")
|
||||||
return False, _(u"Cover-file is not a valid image file")
|
return False, _(u"Cover-file is not a valid image file, or could not be stored")
|
||||||
except OSError:
|
|
||||||
log.error(u"Failed to store cover-file")
|
|
||||||
return False, _(u"Failed to store cover-file")
|
|
||||||
return True, None
|
return True, None
|
||||||
|
|
||||||
|
|
||||||
|
@ -840,7 +840,7 @@ def get_search_results(term):
|
||||||
db.Books.authors.any(and_(*q)),
|
db.Books.authors.any(and_(*q)),
|
||||||
db.Books.publishers.any(func.lower(db.Publishers.name).ilike("%" + term + "%")),
|
db.Books.publishers.any(func.lower(db.Publishers.name).ilike("%" + term + "%")),
|
||||||
func.lower(db.Books.title).ilike("%" + term + "%")
|
func.lower(db.Books.title).ilike("%" + term + "%")
|
||||||
)).all()
|
)).order_by(db.Books.sort).all()
|
||||||
|
|
||||||
|
|
||||||
def get_cc_columns():
|
def get_cc_columns():
|
||||||
|
|
|
@ -66,8 +66,8 @@ log = logger.create()
|
||||||
|
|
||||||
def get_store_url_for_current_request():
|
def get_store_url_for_current_request():
|
||||||
# Programmatically modify the current url to point to the official Kobo store
|
# Programmatically modify the current url to point to the official Kobo store
|
||||||
base, sep, request_path_with_auth_token = request.full_path.rpartition("/kobo/")
|
__, __, request_path_with_auth_token = request.full_path.rpartition("/kobo/")
|
||||||
auth_token, sep, request_path = request_path_with_auth_token.rstrip("?").partition(
|
__, __, request_path = request_path_with_auth_token.rstrip("?").partition(
|
||||||
"/"
|
"/"
|
||||||
)
|
)
|
||||||
return KOBO_STOREAPI_URL + "/" + request_path
|
return KOBO_STOREAPI_URL + "/" + request_path
|
||||||
|
|
|
@ -62,7 +62,6 @@ particular calls to non-Kobo specific endpoints such as the CalibreWeb book down
|
||||||
from binascii import hexlify
|
from binascii import hexlify
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from os import urandom
|
from os import urandom
|
||||||
import os
|
|
||||||
|
|
||||||
from flask import g, Blueprint, url_for, abort, request
|
from flask import g, Blueprint, url_for, abort, request
|
||||||
from flask_login import login_user, login_required
|
from flask_login import login_user, login_required
|
||||||
|
@ -82,7 +81,7 @@ log = logger.create()
|
||||||
|
|
||||||
def register_url_value_preprocessor(kobo):
|
def register_url_value_preprocessor(kobo):
|
||||||
@kobo.url_value_preprocessor
|
@kobo.url_value_preprocessor
|
||||||
def pop_auth_token(endpoint, values):
|
def pop_auth_token(__, values):
|
||||||
g.auth_token = values.pop("auth_token")
|
g.auth_token = values.pop("auth_token")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ body {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
color: white;
|
color: white;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#main {
|
#main {
|
||||||
|
@ -13,7 +13,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.view {
|
.view {
|
||||||
padding-top:0px;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar a,
|
#sidebar a,
|
||||||
|
@ -34,13 +34,13 @@ body {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
|
|
||||||
transition: all .2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar a:hover,
|
#sidebar a:hover,
|
||||||
#sidebar a:focus {
|
#sidebar a:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
box-shadow: 0px 2px 8px 1px black;
|
box-shadow: 0 2px 8px 1px black;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar a.active,
|
#sidebar a.active,
|
||||||
|
@ -79,7 +79,6 @@ body {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
line-height: 10px;
|
line-height: 10px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
|
||||||
transition: min-height 150ms ease-in-out;
|
transition: min-height 150ms ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,18 +91,17 @@ body {
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
|
||||||
transition: width 150ms ease-in-out;
|
transition: width 150ms ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#progress .bar-load {
|
#progress .bar-load {
|
||||||
color: #000;
|
color: #000;
|
||||||
background-color: #CCC;
|
background-color: #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#progress .bar-read {
|
#progress .bar-read {
|
||||||
color: #FFF;
|
color: #fff;
|
||||||
background-color: #45B29D;
|
background-color: #45b29d;
|
||||||
}
|
}
|
||||||
|
|
||||||
#progress .text {
|
#progress .text {
|
||||||
|
@ -152,7 +150,8 @@ body {
|
||||||
max-width: 70%;
|
max-width: 70%;
|
||||||
}
|
}
|
||||||
|
|
||||||
th, td {
|
th,
|
||||||
|
td {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,18 +205,17 @@ th {
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-theme #titlebar {
|
.dark-theme #titlebar {
|
||||||
color: #DDD;
|
color: #ddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-theme #titlebar a:active {
|
.dark-theme #titlebar a:active {
|
||||||
color: #FFF;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-theme #progress .bar-read {
|
.dark-theme #progress .bar-read {
|
||||||
background-color: red;
|
background-color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.dark-theme .overlay {
|
.dark-theme .overlay {
|
||||||
background-color: rgba(0, 0, 0, 0.8);
|
background-color: rgba(0, 0, 0, 0.8);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.sm2-progress .sm2-progress-ball {
|
.sm2-progress .sm2-progress-ball {
|
||||||
width: .5333em;
|
width: 0.5333em;
|
||||||
height: 1.9333em;
|
height: 1.9333em;
|
||||||
border-radius: 0em;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sm2-progress .sm2-progress-track {
|
.sm2-progress .sm2-progress-track {
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
body {
|
body {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #272B30;
|
background: #272b30;
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@
|
||||||
height: 80%;
|
height: 80%;
|
||||||
margin: 5% auto;
|
margin: 5% auto;
|
||||||
max-width: 1250px;
|
max-width: 1250px;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
#area iframe {
|
#area iframe {
|
||||||
|
@ -74,10 +75,6 @@
|
||||||
margin: 1em 0;
|
margin: 1em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#area {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'fontello';
|
font-family: 'fontello';
|
||||||
src: url('fonts/fontello.eot?60518104');
|
src: url('fonts/fontello.eot?60518104');
|
||||||
src: url('fonts/fontello.eot?60518104#iefix') format('embedded-opentype'),
|
src:
|
||||||
|
url('fonts/fontello.eot?60518104#iefix') format('embedded-opentype'),
|
||||||
url('fonts/fontello.woff?60518104') format('woff'),
|
url('fonts/fontello.woff?60518104') format('woff'),
|
||||||
url('fonts/fontello.ttf?60518104') format('truetype'),
|
url('fonts/fontello.ttf?60518104') format('truetype'),
|
||||||
url('fonts/fontello.svg?60518104#fontello') format('svg');
|
url('fonts/fontello.svg?60518104#fontello') format('svg');
|
||||||
|
@ -22,17 +23,15 @@ body {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
-webkit-transition: -webkit-transform .4s, width .2s;
|
-webkit-transition: -webkit-transform 0.4s, width 0.2s;
|
||||||
-moz-transition: -webkit-transform .4s, width .2s;
|
-moz-transition: -webkit-transform 0.4s, width 0.2s;
|
||||||
-ms-transition: -webkit-transform .4s, width .2s;
|
-ms-transition: -webkit-transform 0.4s, width 0.2s;
|
||||||
|
-moz-box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.1);
|
||||||
-moz-box-shadow: inset 0 0 50px rgba(0,0,0,.1);
|
-webkit-box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.1);
|
||||||
-webkit-box-shadow: inset 0 0 50px rgba(0,0,0,.1);
|
-ms-box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.1);
|
||||||
-ms-box-shadow: inset 0 0 50px rgba(0,0,0,.1);
|
box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.1);
|
||||||
box-shadow: inset 0 0 50px rgba(0,0,0,.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#titlebar {
|
#titlebar {
|
||||||
height: 8%;
|
height: 8%;
|
||||||
min-height: 20px;
|
min-height: 20px;
|
||||||
|
@ -42,11 +41,11 @@ body {
|
||||||
color: #4f4f4f;
|
color: #4f4f4f;
|
||||||
font-weight: 100;
|
font-weight: 100;
|
||||||
font-family: Georgia, "Times New Roman", Times, serif;
|
font-family: Georgia, "Times New Roman", Times, serif;
|
||||||
opacity: .5;
|
opacity: 0.5;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
-webkit-transition: opacity .5s;
|
-webkit-transition: opacity 0.5s;
|
||||||
-moz-transition: opacity .5s;
|
-moz-transition: opacity 0.5s;
|
||||||
-ms-transition: opacity .5s;
|
-ms-transition: opacity 0.5s;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +59,7 @@ body {
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
opacity: .5;
|
opacity: 0.5;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
@ -70,35 +69,27 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
#titlebar a:hover {
|
#titlebar a:hover {
|
||||||
opacity: .8;
|
opacity: 0.8;
|
||||||
border: 1px rgba(0,0,0,.2) solid;
|
border: 1px rgba(0, 0, 0, 0.2) solid;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#titlebar a:active {
|
#titlebar a:active {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
color: rgba(0,0,0,.6);
|
color: rgba(0, 0, 0, 0.6);
|
||||||
/* margin: 1px -1px -1px 1px; */
|
-moz-box-shadow: inset 0 0 6px rgba(155, 155, 155, 0.8);
|
||||||
-moz-box-shadow: inset 0 0 6px rgba(155,155,155,.8);
|
-webkit-box-shadow: inset 0 0 6px rgba(155, 155, 155, 0.8);
|
||||||
-webkit-box-shadow: inset 0 0 6px rgba(155,155,155,.8);
|
-ms-box-shadow: inset 0 0 6px rgba(155, 155, 155, 0.8);
|
||||||
-ms-box-shadow: inset 0 0 6px rgba(155,155,155,.8);
|
box-shadow: inset 0 0 6px rgba(155, 155, 155, 0.8);
|
||||||
box-shadow: inset 0 0 6px rgba(155,155,155,.8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#book-title {
|
#book-title { font-weight: 600; }
|
||||||
font-weight: 600;
|
#title-seperator { display: none; }
|
||||||
}
|
|
||||||
|
|
||||||
#title-seperator {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#viewer {
|
#viewer {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
height: 80%;
|
height: 80%;
|
||||||
/* margin-left: 10%; */
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
/* max-width: 1250px; */
|
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -108,12 +99,14 @@ body {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#left,#prev {
|
#left,
|
||||||
|
#prev {
|
||||||
left: 40px;
|
left: 40px;
|
||||||
padding-right: 80px;
|
padding-right: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#right,#next {
|
#right,
|
||||||
|
#next {
|
||||||
right: 40px;
|
right: 40px;
|
||||||
padding-left: 80px;
|
padding-left: 80px;
|
||||||
}
|
}
|
||||||
|
@ -148,17 +141,13 @@ body {
|
||||||
#sidebar {
|
#sidebar {
|
||||||
background: #6b6b6b;
|
background: #6b6b6b;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
/* left: -260px; */
|
|
||||||
/* -webkit-transform: translate(-260px, 0);
|
|
||||||
-moz-transform: translate(-260px, 0); */
|
|
||||||
top: 0;
|
top: 0;
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
width: 25%;
|
width: 25%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
-webkit-transition: -webkit-transform .5s;
|
-webkit-transition: -webkit-transform 0.5s;
|
||||||
-moz-transition: -moz-transform .5s;
|
-moz-transition: -moz-transform 0.5s;
|
||||||
-ms-transition: -moz-transform .5s;
|
-ms-transition: -moz-transform 0.5s;
|
||||||
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,10 +181,10 @@ body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 13px 0;
|
padding: 13px 0;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
-moz-box-shadow: 0px 1px 3px rgba(0,0,0,.6);
|
-moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
|
||||||
-webkit-box-shadow: 0px 1px 3px rgba(0,0,0,.6);
|
-webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
|
||||||
-ms-box-shadow: 0px 1px 3px rgba(0,0,0,.6);
|
-ms-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
|
||||||
box-shadow: 0px 1px 3px rgba(0,0,0,.6);
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
#opener {
|
#opener {
|
||||||
|
@ -203,19 +192,13 @@ body {
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #opener #slider {
|
|
||||||
width: 25px;
|
|
||||||
} */
|
|
||||||
|
|
||||||
#metainfo {
|
#metainfo {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
max-width: 80%;
|
max-width: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#title-controls {
|
#title-controls { float: right; }
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
#panels a {
|
#panels a {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
|
@ -227,22 +210,17 @@ body {
|
||||||
margin-left: 6px;
|
margin-left: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#panels a::before {
|
#panels a::before { visibility: visible; }
|
||||||
visibility: visible;
|
#panels a:hover { color: #aaa; }
|
||||||
}
|
|
||||||
|
|
||||||
#panels a:hover {
|
|
||||||
color: #AAA;
|
|
||||||
}
|
|
||||||
|
|
||||||
#panels a:active {
|
#panels a:active {
|
||||||
color: #AAA;
|
color: #aaa;
|
||||||
margin: 1px 0 -1px 6px;
|
margin: 1px 0 -1px 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#panels a.active,
|
#panels a.active,
|
||||||
#panels a.active:hover {
|
#panels a.active:hover {
|
||||||
color: #AAA;
|
color: #aaa;
|
||||||
}
|
}
|
||||||
|
|
||||||
#searchBox {
|
#searchBox {
|
||||||
|
@ -250,28 +228,11 @@ body {
|
||||||
float: left;
|
float: left;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
margin-top: -1px;
|
margin-top: -1px;
|
||||||
/*
|
|
||||||
border-radius: 5px;
|
|
||||||
background: #9b9b9b;
|
|
||||||
float: left;
|
|
||||||
margin-left: 5px;
|
|
||||||
margin-top: -5px;
|
|
||||||
padding: 3px 10px;
|
|
||||||
color: #000;
|
|
||||||
border: none;
|
|
||||||
outline: none; */
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input::-webkit-input-placeholder {
|
input::-webkit-input-placeholder { color: #454545; }
|
||||||
color: #454545;
|
input:-moz-placeholder { color: #454545; }
|
||||||
}
|
input:-ms-placeholder { color: #454545; }
|
||||||
input:-moz-placeholder {
|
|
||||||
color: #454545;
|
|
||||||
}
|
|
||||||
input:-ms-placeholder {
|
|
||||||
color: #454545;
|
|
||||||
}
|
|
||||||
|
|
||||||
#divider {
|
#divider {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -307,13 +268,11 @@ input:-ms-placeholder {
|
||||||
width: 25%;
|
width: 25%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
-webkit-transition: visibility 0 ease .5s;
|
-webkit-transition: visibility 0 ease 0.5s;
|
||||||
-moz-transition: visibility 0 ease .5s;
|
-moz-transition: visibility 0 ease 0.5s;
|
||||||
-ms-transition: visibility 0 ease .5s;
|
-ms-transition: visibility 0 ease 0.5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#sidebar.open #tocView,
|
#sidebar.open #tocView,
|
||||||
#sidebar.open #bookmarksView {
|
#sidebar.open #bookmarksView {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
@ -351,7 +310,7 @@ input:-ms-placeholder {
|
||||||
}
|
}
|
||||||
|
|
||||||
.list_item a {
|
.list_item a {
|
||||||
color: #AAA;
|
color: #aaa;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,7 +319,7 @@ input:-ms-placeholder {
|
||||||
}
|
}
|
||||||
|
|
||||||
.list_item a.section {
|
.list_item a.section {
|
||||||
font-size: .8em;
|
font-size: 0.8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list_item.currentChapter > a,
|
.list_item.currentChapter > a,
|
||||||
|
@ -370,7 +329,7 @@ input:-ms-placeholder {
|
||||||
|
|
||||||
/* #tocView li.openChapter > a, */
|
/* #tocView li.openChapter > a, */
|
||||||
.list_item a:hover {
|
.list_item a:hover {
|
||||||
color: #E2E2E2;
|
color: #e2e2e2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list_item ul {
|
.list_item ul {
|
||||||
|
@ -431,7 +390,7 @@ input:-ms-placeholder {
|
||||||
}
|
}
|
||||||
|
|
||||||
#searchResults a {
|
#searchResults a {
|
||||||
color: #AAA;
|
color: #aaa;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,11 +406,11 @@ input:-ms-placeholder {
|
||||||
}
|
}
|
||||||
|
|
||||||
#searchResults li > p {
|
#searchResults li > p {
|
||||||
color: #AAA;
|
color: #aaa;
|
||||||
}
|
}
|
||||||
|
|
||||||
#searchResults li a:hover {
|
#searchResults li a:hover {
|
||||||
color: #E2E2E2;
|
color: #e2e2e2;
|
||||||
}
|
}
|
||||||
|
|
||||||
#searchView.shown {
|
#searchView.shown {
|
||||||
|
@ -496,7 +455,7 @@ input:-ms-placeholder {
|
||||||
}
|
}
|
||||||
|
|
||||||
#note-text[disabled], #note-text[disabled="disabled"]{
|
#note-text[disabled], #note-text[disabled="disabled"]{
|
||||||
opacity: .5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
#note-anchor {
|
#note-anchor {
|
||||||
|
@ -823,23 +782,18 @@ and (orientation : landscape)
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
speak: none;
|
speak: none;
|
||||||
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-decoration: inherit;
|
text-decoration: inherit;
|
||||||
width: 1em;
|
width: 1em;
|
||||||
margin-right: .2em;
|
margin-right: 0.2em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
/* opacity: .8; */
|
|
||||||
|
|
||||||
/* For safety - reset parent styles, that can break glyph codes*/
|
/* For safety - reset parent styles, that can break glyph codes*/
|
||||||
font-variant: normal;
|
font-variant: normal;
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
|
|
||||||
/* you can be more comfortable with increased icons size */
|
/* you can be more comfortable with increased icons size */
|
||||||
font-size: 112%;
|
font-size: 112%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.icon-search:before { content: '\e807'; } /* '' */
|
.icon-search:before { content: '\e807'; } /* '' */
|
||||||
.icon-resize-full-1:before { content: '\e804'; } /* '' */
|
.icon-resize-full-1:before { content: '\e804'; } /* '' */
|
||||||
.icon-cancel-circled2:before { content: '\e80f'; } /* '' */
|
.icon-cancel-circled2:before { content: '\e80f'; } /* '' */
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* http://davidwalsh.name/css-tooltips */
|
/* http://davidwalsh.name/css-tooltips */
|
||||||
|
|
||||||
/* base CSS element */
|
/* base CSS element */
|
||||||
.popup {
|
.popup {
|
||||||
background: #eee;
|
background: #eee;
|
||||||
|
@ -9,10 +10,8 @@
|
||||||
position: fixed;
|
position: fixed;
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|
||||||
display: none;
|
display: none;
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
|
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +37,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/* below */
|
/* below */
|
||||||
.popup:before {
|
.popup::before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border-bottom: 10px solid #eee;
|
border-bottom: 10px solid #eee;
|
||||||
|
@ -51,7 +50,7 @@
|
||||||
content: '';
|
content: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup:after {
|
.popup::after {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border-bottom: 9px solid #eee;
|
border-bottom: 9px solid #eee;
|
||||||
|
@ -64,33 +63,31 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/* above */
|
/* above */
|
||||||
.popup.above:before {
|
.popup.above::before {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
border-top: 10px solid #eee;
|
border-top: 10px solid #eee;
|
||||||
border-top-color: rgba(0, 0, 0, 0.2);
|
border-top-color: rgba(0, 0, 0, 0.2);
|
||||||
top: 100%;
|
top: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup.above:after {
|
.popup.above::after {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
border-top: 9px solid #eee;
|
border-top: 9px solid #eee;
|
||||||
top: 100%;
|
top: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup.left:before,
|
.popup.left::before,
|
||||||
.popup.left:after
|
.popup.left::after {
|
||||||
{
|
|
||||||
left: 20px;
|
left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup.right:before,
|
.popup.right::before,
|
||||||
.popup.right:after
|
.popup.right::after {
|
||||||
{
|
|
||||||
left: auto;
|
left: auto;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.popup.show,
|
||||||
.popup.show, .popup.on {
|
.popup.on {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
|
@ -1,5 +1,20 @@
|
||||||
|
|
||||||
.tooltip.bottom .tooltip-inner{font-size:13px;font-family:Open Sans Semibold,Helvetica Neue,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;padding:3px 10px;border-radius:4px;background-color:#fff;-webkit-box-shadow:0 4px 10px 0 rgba(0,0,0,.35);box-shadow:0 4px 10px 0 rgba(0,0,0,.35);opacity:1;white-space:nowrap;margin-top:-16px!important;line-height:1.71428571;color:#ddd}
|
.tooltip.bottom .tooltip-inner {
|
||||||
|
font-size: 13px;
|
||||||
|
font-family: Open Sans Semibold,Helvetica Neue,Helvetica,Arial,sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
padding: 3px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #fff;
|
||||||
|
-webkit-box-shadow: 0 4px 10px 0 rgba(0, 0, 0, 0.35);
|
||||||
|
box-shadow: 0 4px 10px 0 rgba(0, 0, 0, 0.35);
|
||||||
|
opacity: 1;
|
||||||
|
white-space: nowrap;
|
||||||
|
margin-top: -16px !important;
|
||||||
|
line-height: 1.71428571;
|
||||||
|
color: #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Grand Hotel';
|
font-family: 'Grand Hotel';
|
||||||
|
@ -12,49 +27,144 @@ html.http-error {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.http-error body {
|
.http-error body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: table;
|
display: table;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.http-error body > div {
|
.http-error body > div {
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
body{background:#f2f2f2}body h2{font-weight:normal;color:#444}
|
body {
|
||||||
body { margin-bottom: 40px;}
|
background: #f2f2f2;
|
||||||
a{color: #45b29d} /*a:hover{color: #444;}*/
|
margin-bottom: 40px;
|
||||||
.navigation .nav-head{text-transform:uppercase;color:#999;margin:20px 0}.navigation .nav-head:nth-child(1n+2){border-top:1px solid #ccc;padding-top:20px}
|
}
|
||||||
.navigation li a{color:#444;text-decoration:none;display:block;padding:10px}.navigation li a:hover{background:rgba(153,153,153,0.4);border-radius:5px}
|
|
||||||
.navigation li a span{margin-right:10px}
|
body h2 {
|
||||||
.navigation .create-shelf{margin:30px 0;font-size:12px;text-align:center}.navigation .create-shelf a{color:#fff;background:#45b29d;padding:10px 20px;border-radius:5px;text-decoration:none}
|
font-weight: normal;
|
||||||
.container-fluid img{display:block;max-width:100%;height:auto}
|
color:#444;
|
||||||
.container-fluid .discover{margin-bottom:50px}
|
}
|
||||||
.container-fluid .new-books{border-top:1px solid #ccc}.container-fluid .new-books h2{margin:50px 0 0 0}
|
|
||||||
.container-fluid .book{margin-top:20px}.container-fluid .book .cover{height:225px;position:relative}.container-fluid .book .cover img{border:1px solid #fff;/*border-radius:7px;*/box-sizeing:border-box;height:100%;bottom:0;position:absolute;-webkit-box-shadow: 0 5px 8px -6px #777;-moz-box-shadow: 0 5px 8px -6px #777;box-shadow: 0 5px 8px -6px #777;}
|
a { color: #45b29d; }
|
||||||
.container-fluid .book .meta{margin-top:10px}.container-fluid .book .meta p{margin:0}
|
|
||||||
.container-fluid .book .meta .title{font-weight:bold;font-size:15px;color:#444}
|
.navigation .nav-head {
|
||||||
.container-fluid .book .meta .author{font-size:12px;color:#999}
|
text-transform: uppercase;
|
||||||
.container-fluid .book .meta .rating{margin-top:5px}.rating .glyphicon-star{color:#999}.rating .glyphicon-star.good{color:#45b29d}
|
color: #999;
|
||||||
|
margin: 20px 0;
|
||||||
.container-fluid .author .author-hidden, .container-fluid .author .author-hidden-divider {
|
}
|
||||||
display: none;
|
|
||||||
|
.navigation .nav-head:nth-child(1n+2) {
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
padding-top: 20px;
|
||||||
|
}
|
||||||
|
.navigation li a {
|
||||||
|
color: #444;
|
||||||
|
text-decoration: none;
|
||||||
|
display: block;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation li a:hover {
|
||||||
|
background: rgba(153, 153, 153, 0.4);
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation li a span { margin-right: 10px; }
|
||||||
|
|
||||||
|
.navigation .create-shelf {
|
||||||
|
margin: 30px 0;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation .create-shelf a {
|
||||||
|
color: #fff;
|
||||||
|
background: #45b29d;
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-fluid img {
|
||||||
|
display: block;
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-fluid .discover{ margin-bottom: 50px; }
|
||||||
|
.container-fluid .new-books { border-top: 1px solid #ccc; }
|
||||||
|
.container-fluid .new-books h2 { margin: 50px 0 0 0; }
|
||||||
|
.container-fluid .book { margin-top: 20px; }
|
||||||
|
|
||||||
|
.container-fluid .book .cover {
|
||||||
|
height: 225px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-fluid .book .cover img {
|
||||||
|
border: 1px solid #fff;
|
||||||
|
box-sizeing: border-box;
|
||||||
|
height: 100%;
|
||||||
|
bottom: 0;
|
||||||
|
position: absolute;
|
||||||
|
-webkit-box-shadow: 0 5px 8px -6px #777;
|
||||||
|
-moz-box-shadow: 0 5px 8px -6px #777;
|
||||||
|
box-shadow: 0 5px 8px -6px #777;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-fluid .book .meta { margin-top: 10px; }
|
||||||
|
.container-fluid .book .meta p { margin: 0; }
|
||||||
|
|
||||||
|
.container-fluid .book .meta .title {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-fluid .book .meta .author {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-fluid .book .meta .rating { margin-top: 5px; }
|
||||||
|
.rating .glyphicon-star { color: #999; }
|
||||||
|
.rating .glyphicon-star.good { color: #45b29d; }
|
||||||
|
|
||||||
|
.container-fluid .author .author-hidden, .container-fluid .author .author-hidden-divider { display: none; }
|
||||||
|
|
||||||
|
.navbar-brand {
|
||||||
|
font-family: 'Grand Hotel', cursive;
|
||||||
|
font-size: 35px;
|
||||||
|
color: #45b29d !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.more-stuff {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding-top: 20px;
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-brand{font-family: 'Grand Hotel', cursive; font-size: 35px; color: #45b29d !important;}
|
|
||||||
.more-stuff{margin-top: 20px; padding-top: 20px; border-top: 1px solid #ccc}
|
|
||||||
.more-stuff>li { margin-bottom: 10px; }
|
.more-stuff>li { margin-bottom: 10px; }
|
||||||
.navbar-collapse.in .navbar-nav { margin: 0; }
|
.navbar-collapse.in .navbar-nav { margin: 0; }
|
||||||
span.glyphicon.glyphicon-tags {padding-right: 5px;color: #999;vertical-align: text-top;}
|
|
||||||
|
span.glyphicon.glyphicon-tags {
|
||||||
|
padding-right: 5px;
|
||||||
|
color: #999;
|
||||||
|
vertical-align: text-top;
|
||||||
|
}
|
||||||
|
|
||||||
.book-meta { padding-bottom: 20px; }
|
.book-meta { padding-bottom: 20px; }
|
||||||
.book-meta .tags a { display: inline; }
|
.book-meta .tags a { display: inline; }
|
||||||
.book-meta .identifiers a { display: inline; }
|
.book-meta .identifiers a { display: inline; }
|
||||||
|
|
||||||
.container-fluid .single .cover img {
|
.container-fluid .single .cover img {
|
||||||
border: 1px solid #fff;
|
border: 1px solid #fff;
|
||||||
/*border-radius: 7px;*/
|
|
||||||
box-sizeing: border-box;
|
box-sizeing: border-box;
|
||||||
-webkit-box-shadow: 0 5px 8px -6px #777;
|
-webkit-box-shadow: 0 5px 8px -6px #777;
|
||||||
-moz-box-shadow: 0 5px 8px -6px #777;
|
-moz-box-shadow: 0 5px 8px -6px #777;
|
||||||
|
@ -65,13 +175,29 @@ span.glyphicon.glyphicon-tags {padding-right: 5px;color: #999;vertical-align: te
|
||||||
.navbar-default .navbar-toggle {border-color: #000; }
|
.navbar-default .navbar-toggle {border-color: #000; }
|
||||||
.cover { margin-bottom: 10px; }
|
.cover { margin-bottom: 10px; }
|
||||||
.cover-height { max-height: 100px;}
|
.cover-height { max-height: 100px;}
|
||||||
|
|
||||||
.col-sm-2 a .cover-small {
|
.col-sm-2 a .cover-small {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
max-height: 200px;
|
max-height: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-file {position: relative; overflow: hidden;}
|
.btn-file {position: relative; overflow: hidden;}
|
||||||
.btn-file input[type=file] {position: absolute; top: 0; right: 0; min-width: 100%; min-height: 100%; font-size: 100px; text-align: right; filter: alpha(opacity=0); opacity: 0; outline: none; background: white; cursor: inherit; display: block;}
|
|
||||||
|
.btn-file input[type=file] {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
min-width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
font-size: 100px;
|
||||||
|
text-align: right;
|
||||||
|
filter: alpha(opacity=0);
|
||||||
|
opacity: 0;
|
||||||
|
outline: none;
|
||||||
|
background: white;
|
||||||
|
cursor: inherit;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
.btn-toolbar .btn,.discover .btn { margin-bottom: 5px; }
|
.btn-toolbar .btn,.discover .btn { margin-bottom: 5px; }
|
||||||
.button-link {color: #fff; }
|
.button-link {color: #fff; }
|
||||||
|
@ -87,11 +213,11 @@ table .bg-dark-danger a {color: #fff;}
|
||||||
table .bg-dark-danger:hover {background-color: #c9302c; }
|
table .bg-dark-danger:hover {background-color: #c9302c; }
|
||||||
table .bg-primary:hover {background-color: #1C5484; }
|
table .bg-primary:hover {background-color: #1C5484; }
|
||||||
table .bg-primary a {color: #fff; }
|
table .bg-primary a {color: #fff; }
|
||||||
|
|
||||||
.block-label {display: block;}
|
.block-label {display: block;}
|
||||||
.fake-input {position: absolute; pointer-events: none; top: 0; }
|
.fake-input {position: absolute; pointer-events: none; top: 0; }
|
||||||
|
|
||||||
input.pill { position: absolute; opacity: 0; }
|
input.pill { position: absolute; opacity: 0; }
|
||||||
|
|
||||||
input.pill + label {
|
input.pill + label {
|
||||||
border: 2px solid #45b29d;
|
border: 2px solid #45b29d;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
|
@ -103,23 +229,19 @@ input.pill + label {
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
input.pill:checked + label {
|
input.pill:checked + label {
|
||||||
background-color: #45b29d;
|
background-color: #45b29d;
|
||||||
border-color: #fff;
|
border-color: #fff;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
input.pill:not(:checked) + label .glyphicon {
|
|
||||||
display: none;
|
input.pill:not(:checked) + label .glyphicon { display: none; }
|
||||||
}
|
|
||||||
|
|
||||||
.author-bio img { margin: 0 1em 1em 0; }
|
.author-bio img { margin: 0 1em 1em 0; }
|
||||||
.author-link { display: inline-block; margin-top: 10px; width: 100px; }
|
.author-link { display: inline-block; margin-top: 10px; width: 100px; }
|
||||||
.author-link img { display: block; height: 100%; }
|
.author-link img { display: block; height: 100%; }
|
||||||
|
#remove-from-shelves .btn, #shelf-action-errors { margin-left: 5px; }
|
||||||
#remove-from-shelves .btn,
|
|
||||||
#shelf-action-errors {
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tags_click, .serie_click, .language_click { margin-right: 5px; }
|
.tags_click, .serie_click, .language_click { margin-right: 5px; }
|
||||||
|
|
||||||
|
@ -127,32 +249,38 @@ input.pill:not(:checked) + label .glyphicon {
|
||||||
height: 600px;
|
height: 600px;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
.media-list {
|
|
||||||
padding-right:15px;
|
.media-list { padding-right: 15px; }
|
||||||
|
.media-body p { text-align: justify; }
|
||||||
|
|
||||||
|
#meta-info img {
|
||||||
|
max-height: 150px;
|
||||||
|
max-width: 100px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.media-body p {
|
|
||||||
text-align: justify;
|
|
||||||
}
|
|
||||||
#meta-info img { max-height: 150px; max-width: 100px; cursor: pointer; }
|
|
||||||
|
|
||||||
.padded-bottom { margin-bottom: 15px; }
|
.padded-bottom { margin-bottom: 15px; }
|
||||||
|
|
||||||
.upload-format-input-text { display: initial; }
|
.upload-format-input-text { display: initial; }
|
||||||
#btn-upload-format { display: none; }
|
#btn-upload-format { display: none; }
|
||||||
|
|
||||||
.upload-cover-input-text { display: initial; }
|
.upload-cover-input-text { display: initial; }
|
||||||
#btn-upload-cover { display: none; }
|
#btn-upload-cover { display: none; }
|
||||||
|
|
||||||
.panel-title > a { text-decoration: none; }
|
.panel-title > a { text-decoration: none; }
|
||||||
|
.editable-buttons {
|
||||||
|
display:inline-block;
|
||||||
|
margin-left: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
.editable-buttons { display:inline-block; margin-left: 7px ;}
|
|
||||||
.editable-input { display:inline-block; }
|
.editable-input { display:inline-block; }
|
||||||
.editable-cancel { margin-bottom: 0px !important; margin-left: 7px !important;}
|
|
||||||
|
.editable-cancel {
|
||||||
|
margin-bottom: 0px !important;
|
||||||
|
margin-left: 7px !important;
|
||||||
|
}
|
||||||
|
|
||||||
.editable-submit { margin-bottom: 0px !important; }
|
.editable-submit { margin-bottom: 0px !important; }
|
||||||
|
|
||||||
.filterheader { margin-bottom: 20px; }
|
.filterheader { margin-bottom: 20px; }
|
||||||
|
|
||||||
.errorlink { margin-top: 20px; }
|
.errorlink { margin-top: 20px; }
|
||||||
|
|
||||||
.modal-body .comments {
|
.modal-body .comments {
|
||||||
max-height: 300px;
|
max-height: 300px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
|
@ -28,7 +28,7 @@ $( 'body.mailset' ).addClass( 'admin' );
|
||||||
curHref = window.location.href.split('/');
|
curHref = window.location.href.split('/');
|
||||||
prevHref = document.referrer.split('/');
|
prevHref = document.referrer.split('/');
|
||||||
$( '.navbar-form.navbar-left' )
|
$( '.navbar-form.navbar-left' )
|
||||||
.before( '<div class="plexBack"><a href="' + document.referrer + '"></a></div>' );
|
.before( '<div class="plexBack"><a href="' + encodeURI(document.referrer) + '"></a></div>' );
|
||||||
if ( history.length === 1 ||
|
if ( history.length === 1 ||
|
||||||
curHref[0] +
|
curHref[0] +
|
||||||
curHref[1] +
|
curHref[1] +
|
||||||
|
@ -43,7 +43,7 @@ if ( history.length === 1 ||
|
||||||
//Weird missing a after pressing back from edit.
|
//Weird missing a after pressing back from edit.
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
if ( $( '.plexBack a').length < 1 ) {
|
if ( $( '.plexBack a').length < 1 ) {
|
||||||
$( '.plexBack' ).append('<a href="' + document.referrer + '"></a>');
|
$( '.plexBack' ).append('<a href="' + encodeURI(document.referrer) + '"></a>');
|
||||||
}
|
}
|
||||||
},10);
|
},10);
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ $("#sort_name").click(function() {
|
||||||
});*/
|
});*/
|
||||||
// Find count of middle element
|
// Find count of middle element
|
||||||
if (count > 20) {
|
if (count > 20) {
|
||||||
var middle = parseInt(count / 2) + (count % 2);
|
var middle = parseInt(count / 2, 10) + (count % 2);
|
||||||
// search for the middle of all visibe elements
|
// search for the middle of all visibe elements
|
||||||
$(".row").each(function() {
|
$(".row").each(function() {
|
||||||
index++;
|
index++;
|
||||||
|
@ -146,7 +146,7 @@ $("#all").click(function() {
|
||||||
// Find count of middle element
|
// Find count of middle element
|
||||||
var listItems = $("#list").children(".row");
|
var listItems = $("#list").children(".row");
|
||||||
var listlength = listItems.length;
|
var listlength = listItems.length;
|
||||||
var middle = parseInt(listlength / 2) + (listlength % 2);
|
var middle = parseInt(listlength / 2, 10) + (listlength % 2);
|
||||||
// go through all elements and make them visible
|
// go through all elements and make them visible
|
||||||
listItems.each(function() {
|
listItems.each(function() {
|
||||||
$(this).show();
|
$(this).show();
|
||||||
|
@ -178,7 +178,7 @@ $(".char").click(function() {
|
||||||
});
|
});
|
||||||
if (count > 20) {
|
if (count > 20) {
|
||||||
// Find count of middle element
|
// Find count of middle element
|
||||||
var middle = parseInt(count / 2) + (count % 2);
|
var middle = parseInt(count / 2, 10) + (count % 2);
|
||||||
// search for the middle of all visibe elements
|
// search for the middle of all visibe elements
|
||||||
$(".row").each(function() {
|
$(".row").each(function() {
|
||||||
index++;
|
index++;
|
||||||
|
|
|
@ -112,7 +112,7 @@ $(function() {
|
||||||
return "";
|
return "";
|
||||||
},
|
},
|
||||||
url: path + "/../../ajax/listrestriction/" + type,
|
url: path + "/../../ajax/listrestriction/" + type,
|
||||||
rowStyle: function(row, index) {
|
rowStyle: function(row) {
|
||||||
// console.log('Reihe :' + row + " Index :" + index);
|
// console.log('Reihe :' + row + " Index :" + index);
|
||||||
if (row.id.charAt(0) === "a") {
|
if (row.id.charAt(0) === "a") {
|
||||||
return {classes: "bg-primary"};
|
return {classes: "bg-primary"};
|
||||||
|
@ -120,15 +120,15 @@ $(function() {
|
||||||
return {classes: "bg-dark-danger"};
|
return {classes: "bg-dark-danger"};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onClickCell: function (field, value, row, $element) {
|
onClickCell: function (field, value, row) {
|
||||||
if (field == 3) {
|
if (field === 3) {
|
||||||
$.ajax ({
|
$.ajax ({
|
||||||
type: "Post",
|
type: "Post",
|
||||||
data: "id=" + row.id + "&type=" + row.type + "&Element=" + row.Element,
|
data: "id=" + row.id + "&type=" + row.type + "&Element=" + row.Element,
|
||||||
url: path + "/../../ajax/deleterestriction/" + type,
|
url: path + "/../../ajax/deleterestriction/" + type,
|
||||||
async: true,
|
async: true,
|
||||||
timeout: 900,
|
timeout: 900,
|
||||||
success:function(data) {
|
success:function() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
method:"get",
|
method:"get",
|
||||||
url: path + "/../../ajax/listrestriction/" + type,
|
url: path + "/../../ajax/listrestriction/" + type,
|
||||||
|
@ -145,14 +145,14 @@ $(function() {
|
||||||
striped: false
|
striped: false
|
||||||
});
|
});
|
||||||
$("#restrict-elements-table").removeClass("table-hover");
|
$("#restrict-elements-table").removeClass("table-hover");
|
||||||
$("#restrict-elements-table").on("editable-save.bs.table", function (e, field, row, old, $el) {
|
$("#restrict-elements-table").on("editable-save.bs.table", function (e, field, row) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: path + "/../../ajax/editrestriction/" + type,
|
url: path + "/../../ajax/editrestriction/" + type,
|
||||||
type: "Post",
|
type: "Post",
|
||||||
data: row
|
data: row
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
$("[id^=submit_]").click(function(event) {
|
$("[id^=submit_]").click(function() {
|
||||||
$(this)[0].blur();
|
$(this)[0].blur();
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: path + "/../../ajax/addrestriction/" + type,
|
url: path + "/../../ajax/addrestriction/" + type,
|
||||||
|
@ -196,7 +196,7 @@ $(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Function for deleting domain restrictions */
|
/* Function for deleting domain restrictions */
|
||||||
function TableActions (value, row, index) {
|
function TableActions (value, row) {
|
||||||
return [
|
return [
|
||||||
"<a class=\"danger remove\" data-toggle=\"modal\" data-target=\"#DeleteDomain\" data-domain-id=\"" + row.id
|
"<a class=\"danger remove\" data-toggle=\"modal\" data-target=\"#DeleteDomain\" data-domain-id=\"" + row.id
|
||||||
+ "\" title=\"Remove\">",
|
+ "\" title=\"Remove\">",
|
||||||
|
@ -206,7 +206,7 @@ function TableActions (value, row, index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Function for deleting domain restrictions */
|
/* Function for deleting domain restrictions */
|
||||||
function RestrictionActions (value, row, index) {
|
function RestrictionActions (value, row) {
|
||||||
return [
|
return [
|
||||||
"<div class=\"danger remove\" data-restriction-id=\"" + row.id + "\" title=\"Remove\">",
|
"<div class=\"danger remove\" data-restriction-id=\"" + row.id + "\" title=\"Remove\">",
|
||||||
"<i class=\"glyphicon glyphicon-trash\"></i>",
|
"<i class=\"glyphicon glyphicon-trash\"></i>",
|
||||||
|
|
|
@ -344,7 +344,7 @@
|
||||||
<input type="text" class="form-control" id="config_converterpath" name="config_converterpath" value="{% if config.config_converterpath != None %}{{ config.config_converterpath }}{% endif %}" autocomplete="off">
|
<input type="text" class="form-control" id="config_converterpath" name="config_converterpath" value="{% if config.config_converterpath != None %}{{ config.config_converterpath }}{% endif %}" autocomplete="off">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if rarfile_support %}
|
{% if feature_support['rar'] %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="config_rarfile_location">{{_('Location of Unrar binary')}}</label>
|
<label for="config_rarfile_location">{{_('Location of Unrar binary')}}</label>
|
||||||
<input type="text" class="form-control" name="config_rarfile_location" id="config_rarfile_location" value="{% if config.config_rarfile_location != None %}{{ config.config_rarfile_location }}{% endif %}" autocomplete="off">
|
<input type="text" class="form-control" name="config_rarfile_location" id="config_rarfile_location" value="{% if config.config_rarfile_location != None %}{{ config.config_rarfile_location }}{% endif %}" autocomplete="off">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dcterms="http://purl.org/dc/terms/">
|
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/terms/">
|
||||||
<id>urn:uuid:2853dacf-ed79-42f5-8e8a-a7bb3d1ae6a2</id>
|
<id>urn:uuid:2853dacf-ed79-42f5-8e8a-a7bb3d1ae6a2</id>
|
||||||
<updated>{{ current_time }}</updated>
|
<updated>{{ current_time }}</updated>
|
||||||
<link rel="self"
|
<link rel="self"
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
<form class="navbar-form navbar-left" role="search" action="{{url_for('web.search')}}" method="GET">
|
<form class="navbar-form navbar-left" role="search" action="{{url_for('web.search')}}" method="GET">
|
||||||
<div class="form-group input-group input-group-sm">
|
<div class="form-group input-group input-group-sm">
|
||||||
<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 Library')}}">
|
<input type="text" class="form-control" id="query" name="query" placeholder="{{_('Search Library')}}" value="{{searchterm}}">
|
||||||
<span class="input-group-btn">
|
<span class="input-group-btn">
|
||||||
<button type="submit" id="query_submit" class="btn btn-default">{{_('Search')}}</button>
|
<button type="submit" id="query_submit" class="btn btn-default">{{_('Search')}}</button>
|
||||||
</span>
|
</span>
|
||||||
|
@ -224,6 +224,11 @@
|
||||||
$("#btn-upload").change(function() {
|
$("#btn-upload").change(function() {
|
||||||
$("#form-upload").submit();
|
$("#form-upload").submit();
|
||||||
});
|
});
|
||||||
|
$(document).ready(function() {
|
||||||
|
var inp = $('#query').first()
|
||||||
|
var val = inp.val()
|
||||||
|
inp.val('').blur().focus().val(val)
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% block js %}{% endblock %}
|
{% block js %}{% endblock %}
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="discover">
|
<div class="discover">
|
||||||
{% if entries|length < 1 %}
|
{% if entries|length < 1 %}
|
||||||
<h2>{{_('No Results Found')}} {{searchterm}}</h2>
|
<h2>{{_('No Results Found')}} {{adv_searchterm}}</h2>
|
||||||
<p>{{_('Search Term:')}} {{searchterm}}</p>
|
<p>{{_('Search Term:')}} {{adv_searchterm}}</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
<h2>{{entries|length}} {{_('Results for:')}} {{searchterm}}</h2>
|
<h2>{{entries|length}} {{_('Results for:')}} {{adv_searchterm}}</h2>
|
||||||
{% if g.user.is_authenticated %}
|
{% if g.user.is_authenticated %}
|
||||||
{% if g.user.shelf.all() or g.shelves_access %}
|
{% if g.user.shelf.all() or g.shelves_access %}
|
||||||
<div id="shelf-actions" class="btn-toolbar" role="toolbar">
|
<div id="shelf-actions" class="btn-toolbar" role="toolbar">
|
||||||
|
@ -28,8 +28,8 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="filterheader hidden-xs hidden-sm"><!-- ToDo: Implement filter for search results -->
|
<!--div class="filterheader hidden-xs hidden-sm"--><!-- ToDo: Implement filter for search results -->
|
||||||
<a id="new" class="btn btn-primary" href="{{url_for('web.books_list', data=page, sort='new')}}"><span class="glyphicon glyphicon-sort-by-order"></span></a>
|
<!--a id="new" class="btn btn-primary" href="{{url_for('web.books_list', data=page, sort='new')}}"><span class="glyphicon glyphicon-sort-by-order"></span></a>
|
||||||
<a id="old" class="btn btn-primary" href="{{url_for('web.books_list', data=page, sort='old')}}"><span class="glyphicon glyphicon-sort-by-order-alt"></span></a>
|
<a id="old" class="btn btn-primary" href="{{url_for('web.books_list', data=page, sort='old')}}"><span class="glyphicon glyphicon-sort-by-order-alt"></span></a>
|
||||||
<a id="asc" class="btn btn-primary" href="{{url_for('web.books_list', data=page, sort='abc')}}"><span class="glyphicon glyphicon-font"></span><span class="glyphicon glyphicon-sort-by-alphabet"></span></a>
|
<a id="asc" class="btn btn-primary" href="{{url_for('web.books_list', data=page, sort='abc')}}"><span class="glyphicon glyphicon-font"></span><span class="glyphicon glyphicon-sort-by-alphabet"></span></a>
|
||||||
<a id="desc" class="btn btn-primary" href="{{url_for('web.books_list', data=page, sort='zyx')}}"><span class="glyphicon glyphicon-font"></span><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span></a>
|
<a id="desc" class="btn btn-primary" href="{{url_for('web.books_list', data=page, sort='zyx')}}"><span class="glyphicon glyphicon-font"></span><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span></a>
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
<div class="btn-group character" role="group">
|
<div class="btn-group character" role="group">
|
||||||
<a id="no_shelf" class="btn btn-primary" href="{{url_for('web.books_list', data=page, sort='pubold')}}"><span class="glyphicon glyphicon-list"></span><b>?</b></a>
|
<a id="no_shelf" class="btn btn-primary" href="{{url_for('web.books_list', data=page, sort='pubold')}}"><span class="glyphicon glyphicon-list"></span><b>?</b></a>
|
||||||
<div id="all" class="btn btn-primary">{{_('All')}}</div>
|
<div id="all" class="btn btn-primary">{{_('All')}}</div>
|
||||||
</div>
|
</div-->
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -62,7 +62,7 @@ def get_sidebar_config(kwargs=None):
|
||||||
sidebar = list()
|
sidebar = list()
|
||||||
sidebar.append({"glyph": "glyphicon-book", "text": _('Recently Added'), "link": 'web.index', "id": "new",
|
sidebar.append({"glyph": "glyphicon-book", "text": _('Recently Added'), "link": 'web.index', "id": "new",
|
||||||
"visibility": constants.SIDEBAR_RECENT, 'public': True, "page": "root",
|
"visibility": constants.SIDEBAR_RECENT, 'public': True, "page": "root",
|
||||||
"show_text": _('Show recent books'), "config_show": True})
|
"show_text": _('Show recent books'), "config_show":False})
|
||||||
sidebar.append({"glyph": "glyphicon-fire", "text": _('Hot Books'), "link": 'web.books_list', "id": "hot",
|
sidebar.append({"glyph": "glyphicon-fire", "text": _('Hot Books'), "link": 'web.books_list', "id": "hot",
|
||||||
"visibility": constants.SIDEBAR_HOT, 'public': True, "page": "hot",
|
"visibility": constants.SIDEBAR_HOT, 'public': True, "page": "hot",
|
||||||
"show_text": _('Show Hot Books'), "config_show": True})
|
"show_text": _('Show Hot Books'), "config_show": True})
|
||||||
|
@ -161,6 +161,8 @@ class UserBase:
|
||||||
return self.default_language
|
return self.default_language
|
||||||
|
|
||||||
def check_visibility(self, value):
|
def check_visibility(self, value):
|
||||||
|
if value == constants.SIDEBAR_RECENT:
|
||||||
|
return True
|
||||||
return constants.has_flag(self.sidebar_view, value)
|
return constants.has_flag(self.sidebar_view, value)
|
||||||
|
|
||||||
def show_detail_random(self):
|
def show_detail_random(self):
|
||||||
|
@ -621,7 +623,7 @@ def create_anonymous_user(session):
|
||||||
session.add(user)
|
session.add(user)
|
||||||
try:
|
try:
|
||||||
session.commit()
|
session.commit()
|
||||||
except Exception as e:
|
except Exception:
|
||||||
session.rollback()
|
session.rollback()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ def process(tmp_file_path, original_file_name, original_file_extension, rarExcec
|
||||||
meta = epub.get_epub_info(tmp_file_path, original_file_name, original_file_extension)
|
meta = epub.get_epub_info(tmp_file_path, original_file_name, original_file_extension)
|
||||||
if ".FB2" == original_file_extension.upper() and use_fb2_meta is True:
|
if ".FB2" == original_file_extension.upper() and use_fb2_meta is True:
|
||||||
meta = fb2.get_fb2_info(tmp_file_path, original_file_extension)
|
meta = fb2.get_fb2_info(tmp_file_path, original_file_extension)
|
||||||
if original_file_extension.upper() in ['.CBZ', '.CBT', 'CBR']:
|
if original_file_extension.upper() in ['.CBZ', '.CBT', '.CBR']:
|
||||||
meta = comic.get_comic_info(tmp_file_path,
|
meta = comic.get_comic_info(tmp_file_path,
|
||||||
original_file_name,
|
original_file_name,
|
||||||
original_file_extension,
|
original_file_extension,
|
||||||
|
|
31
cps/web.py
31
cps/web.py
|
@ -38,8 +38,12 @@ from flask import render_template, request, redirect, send_from_directory, make_
|
||||||
from flask_babel import gettext as _
|
from flask_babel import gettext as _
|
||||||
from flask_login import login_user, logout_user, login_required, current_user
|
from flask_login import login_user, logout_user, login_required, current_user
|
||||||
from sqlalchemy.exc import IntegrityError
|
from sqlalchemy.exc import IntegrityError
|
||||||
from sqlalchemy.sql.expression import text, func, true, false, not_, and_, exists, or_
|
from sqlalchemy.sql.expression import text, func, true, false, not_, and_, or_
|
||||||
from werkzeug.exceptions import default_exceptions, FailedDependency
|
from werkzeug.exceptions import default_exceptions
|
||||||
|
try:
|
||||||
|
from werkzeug.exceptions import FailedDependency
|
||||||
|
except ImportError:
|
||||||
|
from werkzeug.exceptions import UnprocessableEntity as FailedDependency
|
||||||
from werkzeug.datastructures import Headers
|
from werkzeug.datastructures import Headers
|
||||||
from werkzeug.security import generate_password_hash, check_password_hash
|
from werkzeug.security import generate_password_hash, check_password_hash
|
||||||
|
|
||||||
|
@ -750,7 +754,7 @@ def render_category_books(page, book_id, order):
|
||||||
name = db.session.query(db.Tags).filter(db.Tags.id == book_id).first()
|
name = db.session.query(db.Tags).filter(db.Tags.id == book_id).first()
|
||||||
if name:
|
if name:
|
||||||
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.tags.any(db.Tags.id == book_id),
|
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.tags.any(db.Tags.id == book_id),
|
||||||
[db.Series.name, db.Books.series_index, order[0]],
|
[order[0], db.Series.name, db.Books.series_index],
|
||||||
db.books_series_link, db.Series)
|
db.books_series_link, db.Series)
|
||||||
return render_title_template('index.html', random=random, entries=entries, pagination=pagination, id=book_id,
|
return render_title_template('index.html', random=random, entries=entries, pagination=pagination, id=book_id,
|
||||||
title=_(u"Category: %(name)s", name=name.name), page="category")
|
title=_(u"Category: %(name)s", name=name.name), page="category")
|
||||||
|
@ -926,9 +930,17 @@ def search():
|
||||||
for element in entries:
|
for element in entries:
|
||||||
ids.append(element.id)
|
ids.append(element.id)
|
||||||
searched_ids[current_user.id] = ids
|
searched_ids[current_user.id] = ids
|
||||||
return render_title_template('search.html', searchterm=term, entries=entries, title=_(u"Search"), page="search")
|
return render_title_template('search.html',
|
||||||
|
searchterm=term,
|
||||||
|
adv_searchterm=term,
|
||||||
|
entries=entries,
|
||||||
|
title=_(u"Search"),
|
||||||
|
page="search")
|
||||||
else:
|
else:
|
||||||
return render_title_template('search.html', searchterm="", title=_(u"Search"), page="search")
|
return render_title_template('search.html',
|
||||||
|
searchterm="",
|
||||||
|
title=_(u"Search"),
|
||||||
|
page="search")
|
||||||
|
|
||||||
|
|
||||||
@web.route("/advanced_search", methods=['GET'])
|
@web.route("/advanced_search", methods=['GET'])
|
||||||
|
@ -937,7 +949,7 @@ def advanced_search():
|
||||||
# Build custom columns names
|
# Build custom columns names
|
||||||
cc = get_cc_columns()
|
cc = get_cc_columns()
|
||||||
db.session.connection().connection.connection.create_function("lower", 1, lcase)
|
db.session.connection().connection.connection.create_function("lower", 1, lcase)
|
||||||
q = db.session.query(db.Books).filter(common_filters())
|
q = db.session.query(db.Books).filter(common_filters()).order_by(db.Books.sort)
|
||||||
|
|
||||||
include_tag_inputs = request.args.getlist('include_tag')
|
include_tag_inputs = request.args.getlist('include_tag')
|
||||||
exclude_tag_inputs = request.args.getlist('exclude_tag')
|
exclude_tag_inputs = request.args.getlist('exclude_tag')
|
||||||
|
@ -1066,7 +1078,7 @@ def advanced_search():
|
||||||
for element in q:
|
for element in q:
|
||||||
ids.append(element.id)
|
ids.append(element.id)
|
||||||
searched_ids[current_user.id] = ids
|
searched_ids[current_user.id] = ids
|
||||||
return render_title_template('search.html', searchterm=searchterm,
|
return render_title_template('search.html', adv_searchterm=searchterm,
|
||||||
entries=q, title=_(u"search"), page="search")
|
entries=q, title=_(u"search"), page="search")
|
||||||
# prepare data for search-form
|
# prepare data for search-form
|
||||||
tags = db.session.query(db.Tags).join(db.books_tags_link).join(db.Books).filter(common_filters()) \
|
tags = db.session.query(db.Tags).join(db.books_tags_link).join(db.Books).filter(common_filters()) \
|
||||||
|
@ -1319,16 +1331,11 @@ def login():
|
||||||
log.info('Login failed for user "%s" IP-adress: %s', form['username'], ipAdress)
|
log.info('Login failed for user "%s" IP-adress: %s', form['username'], ipAdress)
|
||||||
flash(_(u"Wrong Username or Password"), category="error")
|
flash(_(u"Wrong Username or Password"), category="error")
|
||||||
|
|
||||||
if feature_support['oauth']:
|
|
||||||
oauth_status = get_oauth_status()
|
|
||||||
else:
|
|
||||||
oauth_status = None
|
|
||||||
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_status=oauth_status,
|
|
||||||
oauth_check=oauth_check,
|
oauth_check=oauth_check,
|
||||||
mail=config.get_mail_server_configured(), page="login")
|
mail=config.get_mail_server_configured(), page="login")
|
||||||
|
|
||||||
|
|
|
@ -300,11 +300,6 @@ class WorkerThread(threading.Thread):
|
||||||
# check which converter to use kindlegen is "1"
|
# check which converter to use kindlegen is "1"
|
||||||
if format_old_ext == '.epub' and format_new_ext == '.mobi':
|
if format_old_ext == '.epub' and format_new_ext == '.mobi':
|
||||||
if config.config_ebookconverter == 1:
|
if config.config_ebookconverter == 1:
|
||||||
'''if os.name == 'nt':
|
|
||||||
command = config.config_converterpath + u' "' + file_path + u'.epub"'
|
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
command = command.encode(sys.getfilesystemencoding())
|
|
||||||
else:'''
|
|
||||||
command = [config.config_converterpath, file_path + u'.epub']
|
command = [config.config_converterpath, file_path + u'.epub']
|
||||||
quotes = [1]
|
quotes = [1]
|
||||||
if config.config_ebookconverter == 2:
|
if config.config_ebookconverter == 2:
|
||||||
|
@ -314,12 +309,6 @@ class WorkerThread(threading.Thread):
|
||||||
# windows py 3.x no encode and as string with quotes empty element for parameters is okay
|
# windows py 3.x no encode and as string with quotes empty element for parameters is okay
|
||||||
# separate handling for windows and linux
|
# separate handling for windows and linux
|
||||||
quotes = [1,2]
|
quotes = [1,2]
|
||||||
'''if os.name == 'nt':
|
|
||||||
command = config.config_converterpath + u' "' + file_path + format_old_ext + u'" "' + \
|
|
||||||
file_path + format_new_ext + u'" ' + config.config_calibre
|
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
command = command.encode(sys.getfilesystemencoding())
|
|
||||||
else:'''
|
|
||||||
command = [config.config_converterpath, (file_path + format_old_ext),
|
command = [config.config_converterpath, (file_path + format_old_ext),
|
||||||
(file_path + format_new_ext)]
|
(file_path + format_new_ext)]
|
||||||
quotes_index = 3
|
quotes_index = 3
|
||||||
|
|
|
@ -31,8 +31,7 @@ rarfile>=2.7
|
||||||
|
|
||||||
# other
|
# other
|
||||||
natsort>=2.2.0,<7.1.0
|
natsort>=2.2.0,<7.1.0
|
||||||
git+https://github.com/OzzieIsaacs/comicapi.git@ad8bfe5a1c31db882480433f86db2c5c57634a3f#egg=comicapi
|
git+https://github.com/OzzieIsaacs/comicapi.git@15dff9ce4e1ffed29ba4a2feadfcdb6bed00bcad#egg=comicapi
|
||||||
|
|
||||||
#Kobo integration
|
#Kobo integration
|
||||||
jsonschema>=3.2.0,<3.3.0
|
jsonschema>=3.2.0,<3.3.0
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user