Translation of UI (german and english)
Bugfix for feeds
- removed categories related and up
- load new books now working
- category random now working
login page is free of non accessible elements
boolean custom column is vivible in UI
books with only with certain languages can be shown
book shelfs can be deleted from UI
Anonymous user view is more resticted
Added browse of series in sidebar
Dependencys in vendor folder are updated to newer versions (licencs files are now present)
Bugfix editing Authors names
Made upload on windows working
This commit is contained in:
@@ -52,23 +52,26 @@ books_languages_link = Table('books_languages_link', Base.metadata,
|
||||
|
||||
cc = conn.execute("SELECT id, datatype FROM custom_columns")
|
||||
cc_ids = []
|
||||
cc_exceptions = ['bool', 'datetime', 'int', 'comments', 'float', 'composite','series' ]
|
||||
cc_exceptions = [ 'datetime', 'int', 'comments', 'float', 'composite','series' ]
|
||||
books_custom_column_links = {}
|
||||
cc_classes = {}
|
||||
for row in cc:
|
||||
if row.datatype not in cc_exceptions:
|
||||
books_custom_column_links[row.id] = Table('books_custom_column_' + str(row.id) + '_link', Base.metadata,
|
||||
Column('book', Integer, ForeignKey('books.id'), primary_key=True),
|
||||
Column('value', Integer, ForeignKey('custom_column_' + str(row.id) + '.id'), primary_key=True)
|
||||
)
|
||||
#books_custom_column_links[row.id]=
|
||||
cc_ids.append(row.id)
|
||||
|
||||
cc_classes = {}
|
||||
for id in cc_ids:
|
||||
ccdict={'__tablename__':'custom_column_' + str(id),
|
||||
'id':Column(Integer, primary_key=True),
|
||||
'value':Column(String)}
|
||||
cc_classes[id] = type('Custom_Column_' + str(id), (Base,), ccdict)
|
||||
cc_ids.append([row.id,row.datatype])
|
||||
if row.datatype == 'bool':
|
||||
ccdict = {'__tablename__': 'custom_column_' + str(row.id),
|
||||
'id': Column(Integer, primary_key=True),
|
||||
'book': Column(Integer,ForeignKey('books.id')),
|
||||
'value': Column(Boolean)}
|
||||
else:
|
||||
ccdict={'__tablename__':'custom_column_' + str(row.id),
|
||||
'id':Column(Integer, primary_key=True),
|
||||
'value':Column(String)}
|
||||
cc_classes[row.id] = type('Custom_Column_' + str(row.id), (Base,), ccdict)
|
||||
|
||||
class Comments(Base):
|
||||
__tablename__ = 'comments'
|
||||
@@ -182,6 +185,7 @@ class Books(Base):
|
||||
last_modified = Column(String)
|
||||
path = Column(String)
|
||||
has_cover = Column(Integer)
|
||||
uuid = Column(String)
|
||||
|
||||
authors = relationship('Authors', secondary=books_authors_link, backref='books')
|
||||
tags = relationship('Tags', secondary=books_tags_link, backref='books')
|
||||
@@ -205,7 +209,10 @@ class Books(Base):
|
||||
def __repr__(self):
|
||||
return u"<Books('{0},{1}{2}{3}{4}{5}{6}{7}{8}')>".format(self.title, self.sort, self.author_sort, self.timestamp, self.pubdate, self.series_index, self.last_modified ,self.path, self.has_cover)
|
||||
for id in cc_ids:
|
||||
setattr(Books, 'custom_column_' + str(id), relationship(cc_classes[id], secondary=books_custom_column_links[id], backref='books'))
|
||||
if id[1] == 'bool':
|
||||
setattr(Books, 'custom_column_' + str(id[0]), relationship(cc_classes[id[0]], primaryjoin=(Books.id==cc_classes[id[0]].book), backref='books'))
|
||||
else:
|
||||
setattr(Books, 'custom_column_' + str(id[0]), relationship(cc_classes[id[0]], secondary=books_custom_column_links[id[0]], backref='books'))
|
||||
|
||||
class Custom_Columns(Base):
|
||||
__tablename__ = 'custom_columns'
|
||||
|
||||
+9
-8
@@ -18,6 +18,7 @@ from email.MIMEBase import MIMEBase
|
||||
from email.MIMEMultipart import MIMEMultipart
|
||||
from email.MIMEText import MIMEText
|
||||
from email.generator import Generator
|
||||
from flask_babel import gettext as _
|
||||
import subprocess
|
||||
|
||||
def update_download(book_id, user_id):
|
||||
@@ -72,8 +73,8 @@ def send_mail(book_id, kindle_mail):
|
||||
msg = MIMEMultipart()
|
||||
msg['From'] = settings["mail_from"]
|
||||
msg['To'] = kindle_mail
|
||||
msg['Subject'] = 'Send to Kindle'
|
||||
text = 'This email has been sent via calibre web.'
|
||||
msg['Subject'] = _('Send to Kindle')
|
||||
text = _('This email has been sent via calibre web.')
|
||||
msg.attach(MIMEText(text))
|
||||
|
||||
use_ssl = settings.get('mail_use_ssl', 0)
|
||||
@@ -95,7 +96,7 @@ def send_mail(book_id, kindle_mail):
|
||||
formats["pdf"] = os.path.join(config.DB_ROOT, book.path, entry.name + ".pdf")
|
||||
|
||||
if len(formats) == 0:
|
||||
return "Could not find any formats suitable for sending by email"
|
||||
return _("Could not find any formats suitable for sending by email")
|
||||
|
||||
if 'mobi' in formats:
|
||||
msg.attach(get_attachment(formats['mobi']))
|
||||
@@ -104,13 +105,13 @@ def send_mail(book_id, kindle_mail):
|
||||
if filepath is not None:
|
||||
msg.attach(get_attachment(filepath))
|
||||
elif filepath is None:
|
||||
return "Could not convert epub to mobi"
|
||||
return _("Could not convert epub to mobi")
|
||||
elif 'pdf' in formats:
|
||||
msg.attach(get_attachment(formats['pdf']))
|
||||
elif 'pdf' in formats:
|
||||
msg.attach(get_attachment(formats['pdf']))
|
||||
else:
|
||||
return "Could not find any formats suitable for sending by email"
|
||||
return _("Could not find any formats suitable for sending by email")
|
||||
|
||||
# convert MIME message to string
|
||||
fp = StringIO()
|
||||
@@ -134,7 +135,7 @@ def send_mail(book_id, kindle_mail):
|
||||
mailserver.quit()
|
||||
except (socket.error, smtplib.SMTPRecipientsRefused, smtplib.SMTPException), e:
|
||||
app.logger.error(traceback.print_exc())
|
||||
return "Failed to send mail: %s" % str(e)
|
||||
return _("Failed to send mail: %s" % str(e))
|
||||
|
||||
return None
|
||||
|
||||
@@ -154,8 +155,8 @@ def get_attachment(file_path):
|
||||
return attachment
|
||||
except IOError:
|
||||
traceback.print_exc()
|
||||
message = ('The requested file could not be read. Maybe wrong '
|
||||
'permissions?')
|
||||
message = (_('The requested file could not be read. Maybe wrong '\
|
||||
'permissions?'))
|
||||
return None
|
||||
|
||||
def get_valid_filename(value, replace_whitespace=True):
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
}
|
||||
|
||||
body{background:#f2f2f2}body h2{font-weight:normal;color:#444}
|
||||
body { margin-bottom: 40px;}
|
||||
a{color: #45b29d}a:hover{color: #444;}
|
||||
.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}
|
||||
|
||||
@@ -131,3 +131,49 @@
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
var languages = new Bloodhound({
|
||||
name: 'languages',
|
||||
datumTokenizer: function(datum) {
|
||||
return [datum.name];
|
||||
},
|
||||
queryTokenizer: function(query) {
|
||||
return [query];
|
||||
},
|
||||
remote: {
|
||||
url: '/get_languages_json?q=',
|
||||
replace: function(url, query) {
|
||||
url_query = url+encodeURIComponent(query);
|
||||
return url_query;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function language_source(query, cb) {
|
||||
var bh_adapter = languages.ttAdapter();
|
||||
|
||||
var tokens = query.split(",");
|
||||
var current_language = tokens[tokens.length-1].trim();
|
||||
|
||||
tokens.splice(tokens.length-1, 1); // remove last element
|
||||
var prefix = "";
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
var tag = tokens[i].trim();
|
||||
prefix += tag + ", ";
|
||||
}
|
||||
|
||||
prefixed_source(prefix, current_language, cb, bh_adapter);
|
||||
}
|
||||
|
||||
var promise = languages.initialize();
|
||||
promise.done(function(){
|
||||
$("#languages").typeahead(
|
||||
{
|
||||
highlight: true, minLength: 0,
|
||||
hint: true
|
||||
}, {
|
||||
name: 'languages', displayKey: 'name',
|
||||
source: language_source
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block body %}
|
||||
<div class="discover">
|
||||
<h1>{{title}}</h1>
|
||||
<ul class="list-unstyled">
|
||||
{% for entry in entries %}
|
||||
<li><a href="{{url_for('author', name=entry.name)}}">{{entry.sort}}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,11 +0,0 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block body %}
|
||||
<div class="discover">
|
||||
<h1>{{title}}</h1>
|
||||
<ul class="list-unstyled">
|
||||
{% for entry in entries %}
|
||||
<li><a href="{{url_for('category', name=entry.name)}}">{{entry.name}}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %}
|
||||
+18
-10
@@ -35,13 +35,13 @@
|
||||
{% endif %}
|
||||
|
||||
{% if entry.series|length > 0 %}
|
||||
<p>Book {{entry.series_index}} of <a href="{{url_for('series', name=entry.series[0].name)}}">{{entry.series[0].name}}</a></p>
|
||||
<p>{{_('Book')}} {{entry.series_index}} {{_('of')}} <a href="{{url_for('series', name=entry.series[0].name)}}">{{entry.series[0].name}}</a></p>
|
||||
{% endif %}
|
||||
|
||||
{% if entry.languages.__len__() > 0 %}
|
||||
<div class="languages">
|
||||
<p>
|
||||
<span class="label label-default">language: {{entry.languages[0].lang_code}}</span>
|
||||
<span class="label label-default">{{_('language')}}: {% for language in entry.languages %} {{language.language_name}}{% if not loop.last %},{% endif %}{% endfor %} </span>
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -69,7 +69,15 @@
|
||||
{% if c.datatype == 'rating' %}
|
||||
{{ '%d' % (column.value / 2) }}
|
||||
{% else %}
|
||||
{{ column.value }}
|
||||
{% if c.datatype == 'bool' %}
|
||||
{% if column.value == true %}
|
||||
<span class="glyphicon glyphicon-ok"></span>
|
||||
{% else %}
|
||||
<span class="glyphicon glyphicon-remove"></span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{ column.value }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<br />
|
||||
@@ -81,18 +89,18 @@
|
||||
|
||||
|
||||
{% if entry.comments|length > 0 %}
|
||||
<h3>Description:</h3>
|
||||
<h3>{{_('Description:')}}</h3>
|
||||
{{entry.comments[0].text|safe}}
|
||||
{% endif %}
|
||||
|
||||
{% if g.user.is_authenticated() %}
|
||||
{% if g.user.is_authenticated %}
|
||||
<div class="more-stuff">
|
||||
<div class="btn-toolbar" role="toolbar">
|
||||
|
||||
<div class="btn-group" role="group" aria-label="Download, send to Kindle, reading">
|
||||
<div class="btn-group" role="group">
|
||||
<button id="btnGroupDrop1" type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="glyphicon glyphicon-download"></span> Download
|
||||
<span class="glyphicon glyphicon-download"></span> {{_('Download')}}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="btnGroupDrop1">
|
||||
@@ -102,11 +110,11 @@
|
||||
</ul>
|
||||
</div>
|
||||
{% if g.user.kindle_mail %}
|
||||
<a href="{{url_for('send_to_kindle', book_id=entry.id)}}" id="sendbtn" class="btn btn-primary" role="button"><span class="glyphicon glyphicon-send"></span> Send to Kindle</a>
|
||||
<a href="{{url_for('send_to_kindle', book_id=entry.id)}}" id="sendbtn" class="btn btn-primary" role="button"><span class="glyphicon glyphicon-send"></span> {{_('Send to Kindle')}}</a>
|
||||
{% endif %}
|
||||
<div class="btn-group" role="group">
|
||||
<button id="btnGroupDrop2" type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="glyphicon glyphicon-eye-open"></span> Read in browser
|
||||
<span class="glyphicon glyphicon-eye-open"></span> {{_('Read in browser')}}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="btnGroupDrop2">
|
||||
@@ -125,7 +133,7 @@
|
||||
<div class="btn-toolbar" role="toolbar">
|
||||
<div class="btn-group" role="group" aria-label="Add to shelves">
|
||||
<button id="btnGroupDrop2" type="button" class="btn btn-primary btn-sm dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="glyphicon glyphicon-list"></span> Add to shelf
|
||||
<span class="glyphicon glyphicon-list"></span> {{_('Add to shelf')}}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="btnGroupDrop2">
|
||||
@@ -165,7 +173,7 @@
|
||||
{% if g.user.role_edit() %}
|
||||
<div class="btn-toolbar" role="toolbar">
|
||||
<div class="btn-group" role="group" aria-label="Edit/Delete book">
|
||||
<a href="{{ url_for('edit_book', book_id=entry.id) }}" class="btn btn-sm btn-warning" role="button"><span class="glyphicon glyphicon-edit"></span> Edit metadata</a>
|
||||
<a href="{{ url_for('edit_book', book_id=entry.id) }}" class="btn btn-sm btn-warning" role="button"><span class="glyphicon glyphicon-edit"></span> {{_('Edit metadata')}}</a>
|
||||
<!-- <a href="{{ url_for('edit_book', book_id=entry.id) }}" class="btn btn-sm btn-danger" role="button"><span class="glyphicon glyphicon-trash"></span> Delete</a> -->
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -11,42 +11,55 @@
|
||||
<div class="col-sm-8">
|
||||
<form role="form" action="{{ url_for('edit_book', book_id=book.id) }}" method="post">
|
||||
<div class="form-group">
|
||||
<label for="book_title">Book Title</label>
|
||||
<label for="book_title">{{_('Book Title')}}</label>
|
||||
<input type="text" class="form-control" name="book_title" id="book_title" value="{{book.title}}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="bookAuthor">Author</label>
|
||||
<label for="bookAuthor">{{_('Author')}}</label>
|
||||
<input type="text" class="form-control typeahead" name="author_name" id="bookAuthor" value="{{' & '.join(authors)}}" autocomplete="off">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description">Description</label>
|
||||
<label for="description">{{_('Description')}}</label>
|
||||
<textarea class="form-control" name="description" id="description" rows="7">{% if book.comments %}{{book.comments[0].text}}{%endif%}</textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="tags">Tags</label>
|
||||
<input type="text" class="form-control" name="tags" id="tags" value="{% for tag in book.tags %}{{tag.name.strip()}}, {% endfor %}">
|
||||
<label for="tags">{{_('Tags')}}</label>
|
||||
<input type="text" class="form-control typeahead" name="tags" id="tags" value="{% for tag in book.tags %}{{tag.name.strip()}}, {% endfor %}">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="series">Series</label>
|
||||
<input type="text" class="form-control" name="series" id="series" value="{% if book.series %}{{book.series[0].name}}{% endif %}">
|
||||
<label for="series">{{_('Series')}}</label>
|
||||
<input type="text" class="form-control typeahead" name="series" id="series" value="{% if book.series %}{{book.series[0].name}}{% endif %}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="series_index">Series id</label>
|
||||
<label for="series_index">{{_('Series id')}}</label>
|
||||
<input type="text" class="form-control" name="series_index" id="series_index" value="{{book.series_index}}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="rating">Rating</label>
|
||||
<label for="rating">{{_('Rating')}}</label>
|
||||
<input type="number" min="1" max="5" step="1" class="form-control" name="rating" id="rating" value="{% if book.ratings %}{{book.ratings[0].rating / 2}}{% endif %}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="cover_url">Cover URL (jpg)</label>
|
||||
<label for="cover_url">{{_('Cover URL (jpg)')}}</label>
|
||||
<input type="text" class="form-control" name="cover_url" id="cover_url" value="">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="languages">{{_('Language')}}</label>
|
||||
<input type="text" class="form-control typeahead" name="languages" id="languages" value="{% for language in book.languages %}{{language.language_name.strip()}}, {% endfor %}">
|
||||
</div>
|
||||
|
||||
{% if cc|length > 0 %}
|
||||
{% for c in cc %}
|
||||
<div class="form-group">
|
||||
<label for="{{ 'custom_column_' ~ c.id }}">{{ c.name }}</label>
|
||||
{% if c.datatype == 'bool' %}
|
||||
<select name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}" class="form-control">
|
||||
<option value="None" {% if book['custom_column_' ~ c.id]|length == 0 %} selected {% endif %}></option>
|
||||
<option value="True" {% if book['custom_column_' ~ c.id]|length > 0 %}{% if book['custom_column_' ~ c.id][0].value ==true %}selected{% endif %}{% endif %} >{{_('Yes')}}</option>
|
||||
<option value="False" {% if book['custom_column_' ~ c.id]|length > 0 %}{% if book['custom_column_' ~ c.id][0].value ==false %}selected{% endif %}{% endif %}>{{_('No')}}</option>
|
||||
</select>
|
||||
{% endif %}
|
||||
{% if c.datatype in ['text', 'series'] and not c.is_multiple %}
|
||||
<input type="text" class="form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}"
|
||||
{% if book['custom_column_' ~ c.id]|length > 0 %}
|
||||
@@ -72,7 +85,7 @@
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if c.datatype == 'rating' %}
|
||||
<input type="number" min="1" max="5" step="1" class="form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}"
|
||||
{% if book['custom_column_' ~ c.id]|length > 0 %}
|
||||
@@ -86,10 +99,10 @@
|
||||
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input name="detail_view" type="checkbox" checked> view book after edit
|
||||
<input name="detail_view" type="checkbox" checked> {{_('view book after edit')}}
|
||||
</label>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-default">Submit</button>
|
||||
<button type="submit" class="btn btn-default">{{_('Submit')}}</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -4,30 +4,30 @@
|
||||
<h1>{{title}}</h1>
|
||||
<form role="form" method="POST">
|
||||
<div class="form-group">
|
||||
<label for="mail_server">SMTP hostname</label>
|
||||
<label for="mail_server">{{_('SMTP hostname')}}</label>
|
||||
<input type="text" class="form-control" name="mail_server" id="mail_server" value="{{content.mail_server}}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="mail_port">SMTP port (usually 25 for plain SMTP and 587 for SSL)</label>
|
||||
<label for="mail_port">{{_('SMTP port (usually 25 for plain SMTP and 587 for SSL)')}}</label>
|
||||
<input type="text" class="form-control" name="mail_port" id="mail_port" value="{{content.mail_port}}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="mail_use_ssl">Server uses SSL (StartTLS)</label>
|
||||
<label for="mail_use_ssl">{{_('Server uses SSL (StartTLS)')}}</label>
|
||||
<input type="checkbox" name="mail_use_ssl" id="mail_use_ssl" {% if content.mail_use_ssl %}checked{% endif %}>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="mail_login">SMTP login</label>
|
||||
<label for="mail_login">{{_('SMTP login')}}</label>
|
||||
<input type="text" class="form-control" name="mail_login" id="mail_login" value="{{content.mail_login}}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="mail_password">SMTP password</label>
|
||||
<label for="mail_password">{{_('SMTP password')}}</label>
|
||||
<input type="password" class="form-control" name="mail_password" id="mail_password" value="{{content.mail_password}}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="mail_from">From e-mail</label>
|
||||
<label for="mail_from">{{_('From e-mail')}}</label>
|
||||
<input type="text" class="form-control" name="mail_from" id="mail_from" value="{{content.mail_from}}">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-default">Submit</button>
|
||||
<button type="submit" class="btn btn-default">{{_('Submit')}}</button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
+29
-12
@@ -7,17 +7,17 @@
|
||||
<link rel="start"
|
||||
href="{{url_for('feed_index')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
<link rel="related"
|
||||
href="{{url_for('feed_index')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
<link rel="up"
|
||||
href="{{url_for('feed_index')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
<link rel="next"
|
||||
title="{{_('Next')}}"
|
||||
href="{{ next_url }}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
<link rel="search"
|
||||
href="{{url_for('feed_osd')}}"
|
||||
type="application/opensearchdescription+xml"/>
|
||||
<title>Calibre Web</title>
|
||||
<updated>2010-01-10T10:03:10Z</updated>
|
||||
<author>
|
||||
<name>Calibre Web</name>
|
||||
<uri>https://github.com/janeczku/calibre-web</uri>
|
||||
@@ -27,7 +27,7 @@
|
||||
<entry>
|
||||
<title>{{entry.title}}</title>
|
||||
<id>{{entry.uuid}}</id>
|
||||
<updated>{{entry.last_modified}}</updated>
|
||||
<updated>{{entry.timestamp}}</updated>
|
||||
<author>
|
||||
<name>{{entry.authors[0].name}}</name>
|
||||
<uri>{{entry.authors[0].name}}</uri>
|
||||
@@ -41,18 +41,13 @@
|
||||
<summary>{% if entry.comments[0] %}{{entry.comments[0].text|striptags}}{% endif %}</summary>
|
||||
{% if entry.has_cover %}
|
||||
<link rel="http://opds-spec.org/image"
|
||||
href="{{ url_for('get_cover', cover_path=entry.path) }}"
|
||||
href="{{ url_for('feed_get_cover', cover_path=entry.path) }}"
|
||||
type="image/jpg"/>
|
||||
<link rel="http://opds-spec.org/image/thumbnail"
|
||||
href="{{ url_for('get_cover', cover_path=entry.path) }}"
|
||||
href="{{ url_for('feed_get_cover', cover_path=entry.path) }}"
|
||||
type="image/jpg"/>
|
||||
{% endif %}
|
||||
|
||||
<link rel="alternate"
|
||||
href="/opds-catalogs/entries/4571.complete.xml"
|
||||
type="application/atom+xml;type=entry;profile=opds-catalog"
|
||||
title="Complete Catalog Entry for Bob, Son of Bob"/>
|
||||
|
||||
{% for format in entry.data %}
|
||||
<link rel="http://opds-spec.org/acquisition"
|
||||
href="{{ url_for('get_opds_download_link', book_id=entry.id, format=format.format|lower)}}"{% if format.format|lower == "epub" %}
|
||||
@@ -63,4 +58,26 @@
|
||||
{% endfor %}
|
||||
</entry>
|
||||
{% endfor %}
|
||||
{% for author in authors %}
|
||||
<entry>
|
||||
<title>{{author.name}}</title>
|
||||
<!--content type="text">{{author.name}}</content-->
|
||||
<id>{{ url_for('feed_author', name=author.name) }}</id>
|
||||
<link href="{{ url_for('feed_author', name=author.name)}}" type="application/atom+xml;profile=opds-catalog;kind=navigation" rel="subsection"/>
|
||||
</entry>
|
||||
{% endfor %}
|
||||
{% for entry in categorys %}
|
||||
<entry>
|
||||
<title>{{entry.name}}</title>
|
||||
<id>{{ url_for('feed_category', name=entry.name) }}</id>
|
||||
<link href="{{ url_for('feed_category', name=entry.name)}}" type="application/atom+xml;profile=opds-catalog;kind=navigation" rel="subsection"/>
|
||||
</entry>
|
||||
{% endfor %}
|
||||
{% for entry in series %}
|
||||
<entry>
|
||||
<title>{{entry.name}}</title>
|
||||
<id>{{ url_for('feed_series', name=entry.name) }}</id>
|
||||
<link href="{{ url_for('feed_series', name=entry.name)}}" type="application/atom+xml;profile=opds-catalog;kind=navigation" rel="subsection"/>
|
||||
</entry>
|
||||
{% endfor %}
|
||||
</feed>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block body %}
|
||||
{% if random.count() > 0 %}
|
||||
{% if g.user.show_random_books() %}
|
||||
<div class="discover">
|
||||
<h2>Discover (Random Books)</h2>
|
||||
<h2>{{_('Discover (Random Books)')}}</h2>
|
||||
<div class="row">
|
||||
|
||||
{% for entry in random %}
|
||||
@@ -31,7 +31,6 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<!-- <p><a href="{{ url_for('edit_book', book_id=entry.id) }}">{{entry.authors[0].name}}: {{entry.title}}</a></p> -->
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -72,7 +71,6 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<!-- <p><a href="{{ url_for('edit_book', book_id=entry.id) }}">{{entry.authors[0].name}}: {{entry.title}}</a></p> -->
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+37
-21
@@ -5,19 +5,14 @@
|
||||
href="{{url_for('feed_index')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
<link rel="start"
|
||||
href="{{url_for('feed_index')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
<link rel="related"
|
||||
href="{{url_for('feed_index')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
<link rel="up"
|
||||
title="{{_('Start')}}"
|
||||
href="{{url_for('feed_index')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
<link rel="search"
|
||||
title="{{_('Search')}}"
|
||||
href="{{url_for('feed_osd')}}"
|
||||
type="application/opensearchdescription+xml"/>
|
||||
<title>Calibre Web</title>
|
||||
<updated>2010-01-10T10:03:10Z</updated>
|
||||
<author>
|
||||
<name>Calibre Web</name>
|
||||
<uri>https://github.com/janeczku/calibre-web</uri>
|
||||
@@ -25,32 +20,53 @@
|
||||
|
||||
|
||||
<entry>
|
||||
<title>Hot Books</title>
|
||||
<title>{{_('Hot Books')}}</title>
|
||||
<link rel="http://opds-spec.org/sort/popular"
|
||||
href="{{url_for('feed_hot')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
<updated>2010-01-10T10:01:01Z</updated>
|
||||
<id>urn:uuid:d49e8018-a0e0-499e-9423-7c175fa0c56e</id>
|
||||
<content type="text">Popular publications from this catalog based on Rating.</content>
|
||||
<id>{{url_for('feed_hot')}}</id>
|
||||
<content type="text">{{_('Popular publications from this catalog based on Rating.')}}</content>
|
||||
</entry>
|
||||
|
||||
<entry>
|
||||
<title>New Books</title>
|
||||
<link rel="http://opds-spec.org/sort/popular"
|
||||
<title>{{_('New Books')}}</title>
|
||||
<link rel="http://opds-spec.org/sort/new"
|
||||
href="{{url_for('feed_new')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
<updated>2010-01-10T10:01:01Z</updated>
|
||||
<id>urn:uuid:d49e8018-a0e0-499e-9423-7c175fa0c56e</id>
|
||||
<content type="text">The latest Books</content>
|
||||
<id>{{url_for('feed_new')}}</id>
|
||||
<content type="text">{{_('The latest Books')}}</content>
|
||||
</entry>
|
||||
|
||||
<entry>
|
||||
<title>Random Books</title>
|
||||
<link rel="http://opds-spec.org/sort/random"
|
||||
<title>{{_('Random Books')}}</title>
|
||||
<link rel="http://opds-spec.org/featured"
|
||||
href="{{url_for('feed_discover')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
<updated>2010-01-10T10:01:01Z</updated>
|
||||
<id>urn:uuid:d49e8018-a0e0-499e-9423-7c175fa0c56e</id>
|
||||
<content type="text">Show Random Books</content>
|
||||
<id>{{url_for('feed_discover')}}</id>
|
||||
<content type="text">{{_('Show Random Books')}}</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<title>{{_('Authors')}}</title>
|
||||
<link rel="subsection"
|
||||
href="{{url_for('feed_authorindex')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
<id>{{url_for('feed_authorindex')}}</id>
|
||||
<content type="text">{{_('Books ordered by Author')}}</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<title>{{_('Category list')}}</title>
|
||||
<link rel="subsection"
|
||||
href="{{url_for('feed_categoryindex')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
<id>{{url_for('feed_categoryindex')}}</id>
|
||||
<content type="text">{{_('Books ordered by category')}}</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<title>{{_('Series list')}}</title>
|
||||
<link rel="subsection"
|
||||
href="{{url_for('feed_seriesindex')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
<id>{{url_for('feed_seriesindex')}}</id>
|
||||
<content type="text">{{_('Books ordered by series')}}</content>
|
||||
</entry>
|
||||
</feed>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block body %}
|
||||
<h1>{{title}}</h1>
|
||||
<div class="container">
|
||||
{% for lang in languages %}
|
||||
<div class="row">
|
||||
<div class="col-xs-1" align="left"><span class="badge">{{lang_counter[loop.index0].bookcount}}</span></div>
|
||||
<div class="col-xs-6"><a href="{{url_for('language', name=lang.lang_code)}}">{{lang.name}}</a></div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
+51
-32
@@ -43,7 +43,7 @@
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="sr-only">{{_('Toggle navigation')}}</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
@@ -51,41 +51,44 @@
|
||||
<a class="navbar-brand" href="{{url_for('index')}}">Calibre Web</a>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse">
|
||||
{% if g.user.is_authenticated or g.user.is_anonymous() %}
|
||||
<ul class="nav navbar-nav ">
|
||||
<li>
|
||||
<form class="navbar-form navbar-left" role="search" action="{{url_for('search')}}" method="GET">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="query" placeholder="Search">
|
||||
<input type="text" class="form-control" name="query" placeholder="{{_('Search')}}">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-default">Go!</button>
|
||||
<button type="submit" class="btn btn-default">{{_('Go!')}}</button>
|
||||
</form>
|
||||
</li>
|
||||
<li><a href="{{url_for('advanced_search')}}"><span class="glyphicon glyphicon-search"></span> Advanced Search</a></li>
|
||||
<li><a href="{{url_for('advanced_search')}}"><span class="glyphicon glyphicon-search"></span> {{_('Advanced Search')}}</a></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
<ul class="nav navbar-nav navbar-right" id="main-nav">
|
||||
{% if g.user.is_authenticated() %}
|
||||
{% if g.user.is_authenticated or g.user.is_anonymous() %}
|
||||
{% if g.user.role_upload() or g.user.role_admin()%}
|
||||
{% if g.allow_upload %}
|
||||
<li>
|
||||
<form id="form-upload" class="navbar-form" action="{{ url_for('upload') }}" method="post" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<span class="btn btn-default btn-file">Upload <input id="btn-upload" name="btn-upload" type="file"></span>
|
||||
</div>
|
||||
</form>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if g.allow_upload %}
|
||||
<li>
|
||||
<form id="form-upload" class="navbar-form" action="{{ url_for('upload') }}" method="post" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<span class="btn btn-default btn-file">{{_('Upload')}} <input id="btn-upload" name="btn-upload" type="file"></span>
|
||||
</div>
|
||||
</form>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if g.user.role_admin() %}
|
||||
<li><a href="{{url_for('user_list')}}"><span class="glyphicon glyphicon-dashboard"></span> Admin</a></li>
|
||||
<li><a href="{{url_for('user_list')}}"><span class="glyphicon glyphicon-dashboard"></span> {{_('Admin')}}</a></li>
|
||||
{% endif %}
|
||||
<li><a href="{{url_for('profile')}}"><span class="glyphicon glyphicon-user"></span> {{g.user.nickname}}</a></li>
|
||||
<li><a href="{{url_for('logout', next='%s%s' % (request.script_root, request.path))}}"><span class="glyphicon glyphicon-log-out"></span> Logout</a></li>
|
||||
{% else %}
|
||||
<li><a href="{{url_for('login', next='%s%s' % (request.script_root, request.path))}}"><span class="glyphicon glyphicon-log-in"></span> Login</a></li>
|
||||
{% if g.allow_registration %}
|
||||
<li><a href="{{url_for('register')}}"><span class="glyphicon glyphicon-user"></span> Register</a></li>
|
||||
{% if not g.user.is_anonymous() %}
|
||||
<li><a href="{{url_for('logout', next='%s%s' % (request.script_root, request.path))}}"><span class="glyphicon glyphicon-log-out"></span> {{_('Logout')}}</a></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if g.allow_registration and not g.user.is_authenticated %}
|
||||
<li><a href="{{url_for('login', next='%s%s' % (request.script_root, request.path))}}"><span class="glyphicon glyphicon-log-in"></span> {{_('Login')}}</a></li>
|
||||
<li><a href="{{url_for('register')}}"><span class="glyphicon glyphicon-user"></span> {{_('Register')}}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
@@ -109,30 +112,46 @@
|
||||
{% endfor %}
|
||||
<div class="container-fluid">
|
||||
<div class="row-fluid">
|
||||
{% if g.user.is_authenticated or g.user.is_anonymous() %}
|
||||
<div class="col-sm-2">
|
||||
<nav class="navigation">
|
||||
<ul class="list-unstyled" id="scnd-nav" intent in-standard-append="nav.navigation" in-mobile-after="#main-nav" in-mobile-class="nav navbar-nav">
|
||||
<li class="nav-head hidden-xs">Browse</li>
|
||||
<li><a href="{{url_for('index')}}"><span class="glyphicon glyphicon-book"></span> New Books</a></li>
|
||||
<li><a href="{{url_for('hot_books')}}"><span class="glyphicon glyphicon-fire"></span> Hot Books</a></li>
|
||||
<li><a href="{{url_for('discover')}}"><span class="glyphicon glyphicon-random"></span> Discover</a></li>
|
||||
<li><a href="{{url_for('category_list')}}"><span class="glyphicon glyphicon-inbox"></span> Categories</a></li>
|
||||
<li><a href="{{url_for('author_list')}}"><span class="glyphicon glyphicon-user"></span> Authors</a></li>
|
||||
|
||||
{% if g.user.is_authenticated() %}
|
||||
<li class="nav-head hidden-xs">Public Shelves</li>
|
||||
<li class="nav-head hidden-xs">{{_('Browse')}}</li>
|
||||
<li><a href="{{url_for('index')}}"><span class="glyphicon glyphicon-book"></span> {{_('New Books')}}</a></li>
|
||||
{% if g.user.show_hot_books() %}
|
||||
<li><a href="{{url_for('hot_books')}}"><span class="glyphicon glyphicon-fire"></span> {{_('Hot Books')}}</a></li>
|
||||
{%endif%}
|
||||
{% if g.user.show_random_books() %}
|
||||
<li><a href="{{url_for('discover')}}"><span class="glyphicon glyphicon-random"></span> {{_('Discover')}}</a></li>
|
||||
{%endif%}
|
||||
{% if g.user.show_category() %}
|
||||
<li><a href="{{url_for('category_list')}}"><span class="glyphicon glyphicon-inbox"></span> {{_('Categories')}}</a></li>
|
||||
{%endif%}
|
||||
{% if g.user.show_series() %}
|
||||
<li><a href="{{url_for('series_list')}}"><span class="glyphicon glyphicon-bookmark"></span> {{_('Series')}}</a></li>
|
||||
{%endif%}
|
||||
<li><a href="{{url_for('author_list')}}"><span class="glyphicon glyphicon-user"></span> {{_('Authors')}}</a></li>
|
||||
{% if g.user.filter_language() == 'all' and g.user.show_language() %}
|
||||
<li><a href="{{url_for('language_overview')}}"><span class="glyphicon glyphicon-flag"></span> {{_('Languages')}} </a></li>
|
||||
{%endif%}
|
||||
{% if g.user.is_authenticated or g.user.is_anonymous() %}
|
||||
<li class="nav-head hidden-xs">{{_('Public Shelves')}}</li>
|
||||
{% for shelf in g.public_shelfes %}
|
||||
<li><a href="{{url_for('show_shelf', shelf_id=shelf.id)}}"><span class="glyphicon glyphicon-list"></span> {{shelf.name}}</a></li>
|
||||
{% endfor %}
|
||||
<li class="nav-head hidden-xs">Your Shelves</li>
|
||||
<li class="nav-head hidden-xs">{{_('Your Shelves')}}</li>
|
||||
{% for shelf in g.user.shelf %}
|
||||
<li><a href="{{url_for('show_shelf', shelf_id=shelf.id)}}"><span class="glyphicon glyphicon-list"></span> {{shelf.name}}</a></li>
|
||||
{% endfor %}
|
||||
<li class="create-shelf"><a href="{{url_for('create_shelf')}}">Create a Shelf</a></li>
|
||||
{% if not g.user.is_anonymous() %}
|
||||
<li class="create-shelf"><a href="{{url_for('create_shelf')}}">{{_('Create a Shelf')}}</a></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<li><a href="{{url_for('stats')}}"><span class="glyphicon glyphicon-info-sign"></span> {{_('About')}}</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="col-sm-10">
|
||||
{% block body %}{% endblock %}
|
||||
{% if pagination %}
|
||||
@@ -159,4 +178,4 @@
|
||||
</div>
|
||||
{% block js %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block body %}
|
||||
<h1>{{title}}</h1>
|
||||
<div class="container">
|
||||
{% for entry in entries %}
|
||||
<div class="row">
|
||||
<div class="col-xs-1" align="left"><span class="badge">{{entry.count}}</span></div>
|
||||
<div class="col-xs-6"><a href="{{url_for(folder, name=entry[0].name)}}">{{entry[0].name}}</a></div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,22 +1,22 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block body %}
|
||||
<div class="well col-sm-6 col-sm-offset-2">
|
||||
<h2 style="margin-top: 0">Login</h2>
|
||||
<h2 style="margin-top: 0">{{_('Login')}}</h2>
|
||||
<form method="POST" role="form">
|
||||
<div class="form-group">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" class="form-control" id="username" name="username" placeholder="Username">
|
||||
<label for="username">{{_('Username')}}</label>
|
||||
<input type="text" class="form-control" id="username" name="username" placeholder="{{_('Username')}}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" placeholder="Password">
|
||||
<label for="password">{{_('Password')}}</label>
|
||||
<input type="password" class="form-control" id="password" name="password" placeholder="{{_('Password')}}">
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="remember_me" checked> Remember me
|
||||
<input type="checkbox" name="remember_me" checked> {{_('Remember me')}}
|
||||
</label>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-default">Submit</button>
|
||||
<button type="submit" class="btn btn-default">{{_('Submit')}}</button>
|
||||
</form>
|
||||
</div>
|
||||
{% if error %}
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
<Image height="16" width="16" type="image/vnd.microsoft.icon">http://example.com/websearch.ico</Image>
|
||||
-->
|
||||
|
||||
<Query role="example" searchTerms="shakespeare hamlet" />
|
||||
<!--Query role="example" searchTerms="shakespeare hamlet" />
|
||||
<Query role="example" searchTerms="doyle detective" />
|
||||
<Query role="example" searchTerms="love stories" />
|
||||
<Query role="example" searchTerms="love stories" /-->
|
||||
|
||||
<Attribution>Search Data Copyright 1971-2012, Project Gutenberg, All Rights Reserved.</Attribution>
|
||||
<SyndicationRight>open</SyndicationRight>
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
<h3>Settings</h3>
|
||||
<div>
|
||||
<p>
|
||||
<input type="checkbox" id="sidebarReflow" name="sidebarReflow">Reflow text when sidebars are open.
|
||||
<input type="checkbox" id="sidebarReflow" name="sidebarReflow">{{_(Reflow text when sidebars are open.)}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="closer icon-cancel-circled"></div>
|
||||
|
||||
@@ -26,7 +26,7 @@ See https://github.com/adobe-type-tools/cmap-resources
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<meta name="google" content="notranslate">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>PDF.js viewer</title>
|
||||
<title>{{_(PDF.js viewer)}}</title>
|
||||
|
||||
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/viewer.css') }}">
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>Basic txt Reader</title>
|
||||
<title>{{_(Basic txt Reader)}}</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block body %}
|
||||
<div class="well col-sm-6 col-sm-offset-2">
|
||||
<h2 style="margin-top: 0">Register a new account</h2>
|
||||
<h2 style="margin-top: 0">{{_('Register a new account')}}</h2>
|
||||
<form method="POST" role="form">
|
||||
<div class="form-group required">
|
||||
<label for="nickname">Username</label>
|
||||
<input type="text" class="form-control" id="nickname" name="nickname" placeholder="Choose a username" required>
|
||||
<label for="nickname">{{_('Username')}}</label>
|
||||
<input type="text" class="form-control" id="nickname" name="nickname" placeholder="{{_('Choose a username')}}" required>
|
||||
</div>
|
||||
<div class="form-group required">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" placeholder="Choose a password" required>
|
||||
<label for="password">{{_('Password')}}</label>
|
||||
<input type="password" class="form-control" id="password" name="password" placeholder="{{_('Choose a password')}}" required>
|
||||
</div>
|
||||
<div class="form-group required">
|
||||
<label for="email">Email address</label>
|
||||
<input type="email" class="form-control" id="email" name="email" placeholder="Your email address" required>
|
||||
<label for="email">{{_('Email address')}}</label>
|
||||
<input type="email" class="form-control" id="email" name="email" placeholder="{{_('Your email address')}}" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Register</button>
|
||||
<button type="submit" class="btn btn-primary">{{_('Register')}}</button>
|
||||
</form>
|
||||
</div>
|
||||
{% if error %}
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
<div class="discover">
|
||||
|
||||
{% if entries|length < 1 %}
|
||||
<h2>No Results for: {{searchterm}}</h2>
|
||||
<p>Please try a diffrent Search</p>
|
||||
<h2>{{_('No Results for:')}} {{searchterm}}</h2>
|
||||
<p>{{_('Please try a diffrent Search')}}</p>
|
||||
{% else %}
|
||||
<h2>{{entries|length}} Results for: {{searchterm}}</h2>
|
||||
<h2>{{entries|length}} {{_('Results for:')}} {{searchterm}}</h2>
|
||||
{%endif%}
|
||||
|
||||
<div class="row">
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
<div class="col-sm-8">
|
||||
<form role="form" action="{{ url_for('advanced_search') }}" method="GET">
|
||||
<div class="form-group">
|
||||
<label for="book_title">Book Title</label>
|
||||
<label for="book_title">{{_('Book Title')}}</label>
|
||||
<input type="text" class="form-control" name="book_title" id="book_title" value="">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="bookAuthor">Author</label>
|
||||
<label for="bookAuthor">{{_('Author')}}</label>
|
||||
<input type="text" class="form-control typeahead" name="author_name" id="bookAuthor" value="" autocomplete="off">
|
||||
</div>
|
||||
<label for="Tags">Include Tags</label>
|
||||
<label for="Tags">{{_('Tags')}}</label>
|
||||
<div class="form-group">
|
||||
<div class="btn-toolbar btn-toolbar-lg" data-toggle="buttons">
|
||||
{% for tag in tags %}
|
||||
@@ -20,7 +20,7 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<label for="Tags">Exclude Tags</label>
|
||||
<label for="Tags">{{_('Exclude Tags')}}</label>
|
||||
<div class="form-group">
|
||||
<div class="btn-toolbar btn-toolbar-lg" data-toggle="buttons">
|
||||
{% for tag in tags %}
|
||||
@@ -30,7 +30,7 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-default">Submit</button>
|
||||
<button type="submit" class="btn btn-default">{{_('Submit')}}</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -39,8 +39,8 @@
|
||||
<script src="{{ url_for('static', filename='js/typeahead.bundle.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/edit_books.js') }}"></script>
|
||||
<script>
|
||||
$('form').on('change input typeahead:selected', function() {
|
||||
form = $('form').serialize();
|
||||
$('form')}}.on('change input typeahead:selected', function() {
|
||||
form = $('form')}}.serialize();
|
||||
$.getJSON( "{{ url_for('get_matching_tags') }}", form, function( data ) {
|
||||
$('.tags_click').each(function() {
|
||||
if ($.inArray(parseInt($(this).children('input').first().val(), 10), data.tags) == -1 ) {
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
{% block body %}
|
||||
<div class="discover">
|
||||
<h2>{{title}}</h2>
|
||||
{% if g.user.is_authenticated %}
|
||||
<a href=" {{ url_for('delete_shelf', shelf_id=shelf.id) }} " class="btn btn-danger">{{ _('Delete this Shelf') }} </a>
|
||||
{% endif %}
|
||||
<div class="row">
|
||||
|
||||
{% for entry in entries %}
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
<h1>{{title}}</h1>
|
||||
<form role="form" method="POST">
|
||||
<div class="form-group">
|
||||
<label for="title">Title</label>
|
||||
<label for="title">{{_('Title')}}</label>
|
||||
<input type="text" class="form-control" name="title" id="title" value="">
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="is_public"> should the shelf be public?
|
||||
<input type="checkbox" name="is_public"> {{_('should the shelf be public?')}}
|
||||
</label>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-default">Submit</button>
|
||||
<button type="submit" class="btn btn-default">{{_('Submit')}}</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block body %}
|
||||
<div class="discover">
|
||||
<h1>{{counter}} Books in this Library</h1>
|
||||
<h2>{{bookcounter}} {{_('Books in this Library')}}</h2>
|
||||
<h2>{{authorcounter}} {{_('Authors in this Library')}}</h2>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -5,58 +5,96 @@
|
||||
<form role="form" method="POST" autocomplete="off">
|
||||
{% if g.user and g.user.role_admin() and new_user %}
|
||||
<div class="form-group required">
|
||||
<label for="nickname">Username</label>
|
||||
<label for="nickname">{{_('Username')}}</label>
|
||||
<input type="text" class="form-control" name="nickname" id="nickname" value="{{ content.nickname if content.nickname != None }}" autocomplete="off">
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label for="email">Email address</label>
|
||||
<label for="email">{{_('Email address')}}</label>
|
||||
<input type="email" class="form-control" name="email" id="email" value="{{ content.email if content.email != None }}" autocomplete="off" required>
|
||||
</div>
|
||||
{% if g.user and g.user.role_passwd() or g.user.role_admin()%}
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<label for="password">{{_('Password')}}</label>
|
||||
<input type="password" class="form-control" name="password" id="password" value="" autocomplete="off">
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label for="kindle_mail">Kindle E-Mail</label>
|
||||
<label for="kindle_mail">{{_('Kindle E-Mail')}}</label>
|
||||
<input type="email" class="form-control" name="kindle_mail" id="kindle_mail" value="{{ content.kindle_mail if content.kindle_mail != None }}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="locale">{{_('Language')}}</label>
|
||||
<select name="locale" id="locale" class="form-control">
|
||||
{% for translation in translations %}
|
||||
<option value="{{translation.language}}" {% if translation.language == content.locale %}selected{% endif %}>{{ translation.display_name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="default_language">{{_('Show books with language')}}</label>
|
||||
<select name="default_language" id="default_language" class="form-control">
|
||||
<option value="all" >{{ _('Show all') }}</option>
|
||||
{% for language in languages %}
|
||||
<option value="{{ language.lang_code }}" {% if content.default_language == language.lang_code %}selected{% endif %}>{{ language.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{% if g.user and g.user.role_admin() and not profile %}
|
||||
<div class="form-group">
|
||||
<label for="admin_role">Admin user</label>
|
||||
<input type="checkbox" name="show_random" {% if content.random_books %}checked{% endif %}>
|
||||
<label for="show_random">{{_('Show random books')}}</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="checkbox" name="show_hot" {% if content.hot_books %}checked{% endif %}>
|
||||
<label for="show_hot">{{_('Show hot books')}}</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="checkbox" name="show_language" {% if content.language_books %}checked{% endif %}>
|
||||
<label for="show_language">{{_('Show language selection')}}</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="checkbox" name="show_series" {% if content.series_books %}checked{% endif %}>
|
||||
<label for="show_series">{{_('Show series selection')}}</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="checkbox" name="show_category" {% if content.category_books %}checked{% endif %}>
|
||||
<label for="show_category">{{_('Show category selection')}}</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<input type="checkbox" name="admin_role" id="admin_role" {% if content.role_admin() %}checked{% endif %}>
|
||||
<label for="admin_role">{{_('Admin user')}}</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="download_role">Allow Downloads</label>
|
||||
<input type="checkbox" name="download_role" id="download_role" {% if content.role_download() %}checked{% endif %}>
|
||||
<label for="download_role">{{_('Allow Downloads')}}</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="upload_role">Allow Uploads</label>
|
||||
<input type="checkbox" name="upload_role" id="upload_role" {% if content.role_upload() %}checked{% endif %}>
|
||||
<label for="upload_role">{{_('Allow Uploads')}}</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="edit_role">Allow Edit</label>
|
||||
<input type="checkbox" name="edit_role" id="edit_role" {% if content.role_edit() %}checked{% endif %}>
|
||||
<label for="edit_role">{{_('Allow Edit')}}</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="passwd_role">Allow Changing Password</label>
|
||||
<input type="checkbox" name="passwd_role" id="passwd_role" {% if content.role_passwd() %}checked{% endif %}>
|
||||
<label for="passwd_role">{{_('Allow Changing Password')}}</label>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if g.user and g.user.role_admin() and not profile and not new_user %}
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="delete"> Delete this user
|
||||
<input type="checkbox" name="delete"> {{_('Delete this user')}}
|
||||
</label>
|
||||
</div>
|
||||
{% endif %}
|
||||
<button type="submit" class="btn btn-default">Submit</button>
|
||||
<button type="submit" class="btn btn-default">{{_('Submit')}}</button>
|
||||
</form>
|
||||
|
||||
{% if downloads %}
|
||||
<h2>Recent Downloads</h2>
|
||||
<h2>{{_('Recent Downloads')}}</h2>
|
||||
{% for entry in downloads %}
|
||||
<div class="col-sm-2">
|
||||
<a class="pull-left" href="{{ url_for('show_book', id=entry.id) }}">
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
<h2>{{title}}</h2>
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
<th>Nickname</th>
|
||||
<th>Email</th>
|
||||
<th>Kindle</th>
|
||||
<th>DLS</th>
|
||||
<th>Admin</th>
|
||||
<th>Download</th>
|
||||
<th>Upload</th>
|
||||
<th>Edit</th>
|
||||
<th>Passwd</th>
|
||||
<th>{{_('Nickname')}}</th>
|
||||
<th>{{_('Email')}}</th>
|
||||
<th>{{_('Kindle')}}</th>
|
||||
<th>{{_('DLS')}}</th>
|
||||
<th>{{_('Admin')}}</th>
|
||||
<th>{{_('Download')}}</th>
|
||||
<th>{{_('Upload')}}</th>
|
||||
<th>{{_('Edit')}}</th>
|
||||
<th>{{_('Passwd')}}</th>
|
||||
|
||||
</tr>
|
||||
{% for user in content %}
|
||||
@@ -29,16 +29,16 @@
|
||||
|
||||
{% endfor %}
|
||||
</table>
|
||||
<div class="btn btn-default"><a href="{{url_for('new_user')}}">Add new user</a></div>
|
||||
<h2>SMTP mail settings</h2>
|
||||
<div class="btn btn-default"><a href="{{url_for('new_user')}}">{{_('Add new user')}}</a></div>
|
||||
<h2>{{_('SMTP mail settings')}}</h2>
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
<th>SMTP hostname</th>
|
||||
<th>SMTP port</th>
|
||||
<th>SSL</th>
|
||||
<th>SMTP login</th>
|
||||
<th>SMTP password</th>
|
||||
<th>From mail</th>
|
||||
<th>{{_('SMTP hostname')}}</th>
|
||||
<th>{{_('SMTP port')}}</th>
|
||||
<th>{{_('SSL')}}</th>
|
||||
<th>{{_('SMTP login')}}</th>
|
||||
<th>{{_('SMTP password')}}</th>
|
||||
<th>{{_('From mail')}}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{email.mail_server}}</td>
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
</table>
|
||||
|
||||
<div class="btn btn-default"><a href="{{url_for('edit_mailsettings')}}">Change SMTP settings</a></div>
|
||||
<div class="btn btn-default"><a href="{{url_for('edit_mailsettings')}}">{{_('Change SMTP settings')}}</a></div>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,673 @@
|
||||
# German translations for PROJECT.
|
||||
# Copyright (C) 2016 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2016-11-09 18:52+0100\n"
|
||||
"PO-Revision-Date: 2016-07-12 19:54+0200\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: de\n"
|
||||
"Language-Team: de <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.3.4\n"
|
||||
|
||||
#: cps/helper.py:76 cps/templates/detail.html:113
|
||||
msgid "Send to Kindle"
|
||||
msgstr "An Kindle senden"
|
||||
|
||||
#: cps/helper.py:77
|
||||
msgid "This email has been sent via calibre web."
|
||||
msgstr "Die E-Mail wurde via calibre-web versendet"
|
||||
|
||||
#: cps/helper.py:99 cps/helper.py:114
|
||||
msgid "Could not find any formats suitable for sending by email"
|
||||
msgstr "Konnte keine Formate finden welche für das versenden per E-Mail geeignet sind"
|
||||
|
||||
#: cps/helper.py:108
|
||||
msgid "Could not convert epub to mobi"
|
||||
msgstr "Konnte .epub nicht nach .mobi convertieren"
|
||||
|
||||
#: cps/helper.py:138
|
||||
#, python-format
|
||||
msgid "Failed to send mail: %s"
|
||||
msgstr "E-Mail: %s konnte nicht gesendet werden"
|
||||
|
||||
#: cps/helper.py:158
|
||||
msgid "The requested file could not be read. Maybe wrong permissions?"
|
||||
msgstr "Die angeforderte Datei konnte nicht gelesen werden. Falsche Dateirechte?"
|
||||
|
||||
#: cps/web.py:633
|
||||
msgid "Latest Books"
|
||||
msgstr "Letzte Bücher"
|
||||
|
||||
#: cps/web.py:655
|
||||
msgid "Hot Books (most downloaded)"
|
||||
msgstr "Beliebte Bücher (die meisten Downloads)"
|
||||
|
||||
#: cps/templates/index.xml:41 cps/web.py:662
|
||||
msgid "Random Books"
|
||||
msgstr "Zufällige Bücher"
|
||||
|
||||
#: cps/web.py:673
|
||||
msgid "Author list"
|
||||
msgstr "Autorenliste"
|
||||
|
||||
#: cps/web.py:689
|
||||
#, python-format
|
||||
msgid "Author: %(nam)s"
|
||||
msgstr "Autor: %(nam)s"
|
||||
|
||||
#: cps/templates/index.xml:65 cps/web.py:700
|
||||
msgid "Series list"
|
||||
msgstr "Liste Serien"
|
||||
|
||||
#: cps/web.py:708
|
||||
#, python-format
|
||||
msgid "Series: %(serie)s"
|
||||
msgstr "Serie: %(serie)s"
|
||||
|
||||
#: cps/web.py:710 cps/web.py:790 cps/web.py:908 cps/web.py:1518
|
||||
msgid "Error opening eBook. File does not exist or file is not accessible:"
|
||||
msgstr ""
|
||||
"Buch öffnen fehlgeschlagen. Datei existiert nicht, oder ist nicht "
|
||||
"zugänglich."
|
||||
|
||||
#: cps/web.py:736
|
||||
msgid "Available languages"
|
||||
msgstr "Verfügbare Sprachen"
|
||||
|
||||
#: cps/web.py:748
|
||||
#, python-format
|
||||
msgid "Language: %(name)s"
|
||||
msgstr "Sprache: %(name)s"
|
||||
|
||||
#: cps/templates/index.xml:57 cps/web.py:759
|
||||
msgid "Category list"
|
||||
msgstr "Kategorieliste"
|
||||
|
||||
#: cps/web.py:766
|
||||
#, python-format
|
||||
msgid "Category: %(name)s"
|
||||
msgstr "Kategorie: %(name)s"
|
||||
|
||||
#: cps/web.py:804
|
||||
msgid "Statistics"
|
||||
msgstr "Statistiken"
|
||||
|
||||
#: cps/web.py:892 cps/web.py:899 cps/web.py:906
|
||||
msgid "Read a Book"
|
||||
msgstr "Lese ein Buch"
|
||||
|
||||
#: cps/web.py:945 cps/web.py:1173
|
||||
msgid "Please fill out all fields!"
|
||||
msgstr "Bitte alle Felder ausfüllen!"
|
||||
|
||||
#: cps/web.py:961
|
||||
msgid "An unknown error occured. Please try again later."
|
||||
msgstr "Es ist ein unbekannter Fehler aufgetreten. Bitte später erneut versuchen."
|
||||
|
||||
#: cps/web.py:966
|
||||
msgid "This username or email address is already in use."
|
||||
msgstr "Der Benutzername oder die E-Mailadresse ist in bereits in Benutzung."
|
||||
|
||||
#: cps/web.py:969
|
||||
msgid "register"
|
||||
msgstr "Registieren"
|
||||
|
||||
#: cps/web.py:984
|
||||
#, python-format
|
||||
msgid "you are now logged in as: '%(nickname)s'"
|
||||
msgstr "Du bist nun eingeloggt als '%(nickname)s'"
|
||||
|
||||
#: cps/web.py:987
|
||||
msgid "Wrong Username or Password"
|
||||
msgstr "Flascher Benutzername oder Passwort"
|
||||
|
||||
#: cps/web.py:989
|
||||
msgid "login"
|
||||
msgstr "Login"
|
||||
|
||||
#: cps/web.py:1005
|
||||
msgid "Please configure the SMTP mail settings first..."
|
||||
msgstr "Bitte zuerst die SMTP Mail Einstellung konfigurieren ..."
|
||||
|
||||
#: cps/web.py:1009
|
||||
#, python-format
|
||||
msgid "Book successfully send to %(kindlemail)s"
|
||||
msgstr "Buch erfolgreich versandt an %(kindlemail)s"
|
||||
|
||||
#: cps/web.py:1012
|
||||
#, python-format
|
||||
msgid "There was an error sending this book: %(res)s"
|
||||
msgstr "Beim Senden des Buchs trat ein Fehler auf: %(res)s"
|
||||
|
||||
#: cps/web.py:1014
|
||||
msgid "Please configure your kindle email address first..."
|
||||
msgstr "Bitte die Kindle E-Mail Adresse zuuerst konfigurieren..."
|
||||
|
||||
#: cps/web.py:1029
|
||||
#, python-format
|
||||
msgid "Book has been added to shelf: %(sname)s"
|
||||
msgstr "Das Buch wurde dem Bücherregal: %(sname)s hinzugefügt"
|
||||
|
||||
#: cps/web.py:1048
|
||||
#, python-format
|
||||
msgid "Book has been removed from shelf: %(sname)s"
|
||||
msgstr "Das Buch wurde aus dem Bücherregal: %(sname)s entfernt"
|
||||
|
||||
#: cps/web.py:1064
|
||||
#, python-format
|
||||
msgid "A shelf with the name '%(title)s' already exists."
|
||||
msgstr "Es existiert bereits ein Bücheregal mit dem Titel '%(title)s'"
|
||||
|
||||
#: cps/web.py:1069
|
||||
#, python-format
|
||||
msgid "Shelf %(title)s created"
|
||||
msgstr "Bücherregal %(title)s erzeugt"
|
||||
|
||||
#: cps/web.py:1071
|
||||
msgid "There was an error"
|
||||
msgstr "Es trat ein Fehler auf"
|
||||
|
||||
#: cps/web.py:1072 cps/web.py:1074
|
||||
msgid "create a shelf"
|
||||
msgstr "Bücherregal erzeugen"
|
||||
|
||||
#: cps/web.py:1090
|
||||
#, python-format
|
||||
msgid "successfully deleted shelf %(name)s"
|
||||
msgstr "Bücherregal %(name)s erfolgreich gelöscht"
|
||||
|
||||
#: cps/web.py:1107
|
||||
#, python-format
|
||||
msgid "Shelf: '%(name)s'"
|
||||
msgstr "Bücherregal: '%(name)s'"
|
||||
|
||||
#: cps/web.py:1144
|
||||
msgid "Found an existing account for this email address."
|
||||
msgstr "Es existiert ein Benutzerkonto für diese E-Mailadresse"
|
||||
|
||||
#: cps/web.py:1145 cps/web.py:1147
|
||||
#, python-format
|
||||
msgid "%(name)s's profile"
|
||||
msgstr "%(name)s's Profil"
|
||||
|
||||
#: cps/web.py:1146
|
||||
msgid "Profile updated"
|
||||
msgstr "Profil aktualisiert"
|
||||
|
||||
#: cps/web.py:1155
|
||||
msgid "User list"
|
||||
msgstr "Benutzerliste"
|
||||
|
||||
#: cps/templates/user_list.html:32 cps/web.py:1174
|
||||
msgid "Add new user"
|
||||
msgstr "Neuen Benutzer hinzufügen"
|
||||
|
||||
#: cps/web.py:1207
|
||||
#, python-format
|
||||
msgid "User '%(user)s' created"
|
||||
msgstr "Benutzer '%(user)s' angelegt"
|
||||
|
||||
#: cps/web.py:1211
|
||||
msgid "Found an existing account for this email address or nickname."
|
||||
msgstr ""
|
||||
"Es existiert ein Benutzerkonto für diese Emailadresse oder den "
|
||||
"Benutzernamen"
|
||||
|
||||
#: cps/web.py:1232
|
||||
msgid "Mail settings updated"
|
||||
msgstr "E-Mail Einstellungen aktualisiert"
|
||||
|
||||
#: cps/web.py:1235
|
||||
msgid "Edit mail settings"
|
||||
msgstr "E-Mail Einstellungen editieren"
|
||||
|
||||
#: cps/web.py:1257
|
||||
#, python-format
|
||||
msgid "User '%(nick)s' deleted"
|
||||
msgstr "Benutzer '%(nick)s' gelöscht"
|
||||
|
||||
#: cps/web.py:1312
|
||||
#, python-format
|
||||
msgid "User '%(nick)s' updated"
|
||||
msgstr "Benutzer '%(nick)s' aktualisiert"
|
||||
|
||||
#: cps/web.py:1315
|
||||
msgid "An unknown error occured."
|
||||
msgstr "Es ist ein unbekanter Fehler aufgetreten"
|
||||
|
||||
#: cps/web.py:1316
|
||||
#, python-format
|
||||
msgid "Edit User %(nick)s"
|
||||
msgstr "Benutzer %(nick)s bearbeiten"
|
||||
|
||||
#: cps/web.py:1550
|
||||
#, python-format
|
||||
msgid "Failed to create path %s (Permission denied)."
|
||||
msgstr ""
|
||||
|
||||
#: cps/web.py:1555
|
||||
#, python-format
|
||||
msgid "Failed to store file %s (Permission denied)."
|
||||
msgstr ""
|
||||
|
||||
#: cps/web.py:1560
|
||||
#, python-format
|
||||
msgid "Failed to delete file %s (Permission denied)."
|
||||
msgstr ""
|
||||
|
||||
#: cps/templates/detail.html:38
|
||||
msgid "Book"
|
||||
msgstr "Buch"
|
||||
|
||||
#: cps/templates/detail.html:38
|
||||
msgid "of"
|
||||
msgstr "von"
|
||||
|
||||
#: cps/templates/detail.html:44
|
||||
msgid "language"
|
||||
msgstr "Sprache"
|
||||
|
||||
#: cps/templates/detail.html:92
|
||||
msgid "Description:"
|
||||
msgstr "Beschreibung"
|
||||
|
||||
#: cps/templates/detail.html:103 cps/templates/user_list.html:12
|
||||
msgid "Download"
|
||||
msgstr "Download"
|
||||
|
||||
#: cps/templates/detail.html:117
|
||||
msgid "Read in browser"
|
||||
msgstr "Im Browser lesen"
|
||||
|
||||
#: cps/templates/detail.html:136
|
||||
msgid "Add to shelf"
|
||||
msgstr "Zu Bücherregal hinzufügen"
|
||||
|
||||
#: cps/templates/detail.html:176
|
||||
msgid "Edit metadata"
|
||||
msgstr "Metadaten bearbeiten"
|
||||
|
||||
#: cps/templates/edit_book.html:14 cps/templates/search_form.html:6
|
||||
msgid "Book Title"
|
||||
msgstr "Buchtitel"
|
||||
|
||||
#: cps/templates/edit_book.html:18 cps/templates/search_form.html:10
|
||||
msgid "Author"
|
||||
msgstr "Autor"
|
||||
|
||||
#: cps/templates/edit_book.html:22
|
||||
msgid "Description"
|
||||
msgstr "Beschreibung"
|
||||
|
||||
#: cps/templates/edit_book.html:26 cps/templates/search_form.html:13
|
||||
msgid "Tags"
|
||||
msgstr "Tags"
|
||||
|
||||
#: cps/templates/edit_book.html:31 cps/templates/layout.html:131
|
||||
msgid "Series"
|
||||
msgstr "Serien"
|
||||
|
||||
#: cps/templates/edit_book.html:35
|
||||
msgid "Series id"
|
||||
msgstr "Serien ID"
|
||||
|
||||
#: cps/templates/edit_book.html:39
|
||||
msgid "Rating"
|
||||
msgstr "Bewertung"
|
||||
|
||||
#: cps/templates/edit_book.html:43
|
||||
msgid "Cover URL (jpg)"
|
||||
msgstr "Cover URL (jpg)"
|
||||
|
||||
#: cps/templates/edit_book.html:48 cps/templates/user_edit.html:27
|
||||
msgid "Language"
|
||||
msgstr "Sprache"
|
||||
|
||||
#: cps/templates/edit_book.html:59
|
||||
msgid "Yes"
|
||||
msgstr "Ja"
|
||||
|
||||
#: cps/templates/edit_book.html:60
|
||||
msgid "No"
|
||||
msgstr "Nein"
|
||||
|
||||
#: cps/templates/edit_book.html:102
|
||||
msgid "view book after edit"
|
||||
msgstr "Buch nach Bearbeitung ansehen"
|
||||
|
||||
#: cps/templates/edit_book.html:105 cps/templates/email_edit.html:30
|
||||
#: cps/templates/login.html:19 cps/templates/search_form.html:33
|
||||
#: cps/templates/shelf_edit.html:15 cps/templates/user_edit.html:93
|
||||
msgid "Submit"
|
||||
msgstr "Abschicken"
|
||||
|
||||
#: cps/templates/email_edit.html:7 cps/templates/user_list.html:36
|
||||
msgid "SMTP hostname"
|
||||
msgstr "SMTP Hostname"
|
||||
|
||||
#: cps/templates/email_edit.html:11
|
||||
msgid "SMTP port (usually 25 for plain SMTP and 587 for SSL)"
|
||||
msgstr "SMTP Port (normalerweise 25 für unverschlüsseltes SMTP und 587 für SSL)"
|
||||
|
||||
#: cps/templates/email_edit.html:15
|
||||
msgid "Server uses SSL (StartTLS)"
|
||||
msgstr "Server benutzt SSL (StartTLS)"
|
||||
|
||||
#: cps/templates/email_edit.html:19 cps/templates/user_list.html:39
|
||||
msgid "SMTP login"
|
||||
msgstr "SMTP Login"
|
||||
|
||||
#: cps/templates/email_edit.html:23 cps/templates/user_list.html:40
|
||||
msgid "SMTP password"
|
||||
msgstr "SMTP Passwort"
|
||||
|
||||
#: cps/templates/email_edit.html:27
|
||||
msgid "From e-mail"
|
||||
msgstr "Absenderadresse"
|
||||
|
||||
#: cps/templates/feed.xml:14
|
||||
msgid "Next"
|
||||
msgstr "Nächste"
|
||||
|
||||
#: cps/templates/index.html:5
|
||||
msgid "Discover (Random Books)"
|
||||
msgstr "Entdecke (Zufälliges Buch)"
|
||||
|
||||
#: cps/templates/index.xml:8
|
||||
msgid "Start"
|
||||
msgstr "Start"
|
||||
|
||||
#: cps/templates/index.xml:12 cps/templates/layout.html:59
|
||||
msgid "Search"
|
||||
msgstr "Suche"
|
||||
|
||||
#: cps/templates/index.xml:23 cps/templates/layout.html:122
|
||||
msgid "Hot Books"
|
||||
msgstr "Beliebte Bücher"
|
||||
|
||||
#: cps/templates/index.xml:28
|
||||
msgid "Popular publications from this catalog based on Rating."
|
||||
msgstr "Beliebte Veröffentlichungen dieses Katalogs basierend auf Bewertungen"
|
||||
|
||||
#: cps/templates/index.xml:32 cps/templates/layout.html:120
|
||||
msgid "New Books"
|
||||
msgstr "Neue Bücher"
|
||||
|
||||
#: cps/templates/index.xml:37
|
||||
msgid "The latest Books"
|
||||
msgstr "Die neuesten Bücher"
|
||||
|
||||
#: cps/templates/index.xml:46
|
||||
msgid "Show Random Books"
|
||||
msgstr "Zeige zufällige Bücher"
|
||||
|
||||
#: cps/templates/index.xml:49 cps/templates/layout.html:133
|
||||
msgid "Authors"
|
||||
msgstr "Autoren"
|
||||
|
||||
#: cps/templates/index.xml:54
|
||||
msgid "Books ordered by Author"
|
||||
msgstr "Bücher nach Autoren sortiert"
|
||||
|
||||
#: cps/templates/index.xml:62
|
||||
msgid "Books ordered by category"
|
||||
msgstr "Bücher nach Kategorien sortiert"
|
||||
|
||||
#: cps/templates/index.xml:70
|
||||
msgid "Books ordered by series"
|
||||
msgstr ""
|
||||
|
||||
#: cps/templates/layout.html:46
|
||||
msgid "Toggle navigation"
|
||||
msgstr "Nagivation umschalten"
|
||||
|
||||
#: cps/templates/layout.html:61
|
||||
msgid "Go!"
|
||||
msgstr "Los!"
|
||||
|
||||
#: cps/templates/layout.html:64
|
||||
msgid "Advanced Search"
|
||||
msgstr "Erweiterte Suche"
|
||||
|
||||
#: cps/templates/layout.html:74 cps/templates/user_list.html:13
|
||||
msgid "Upload"
|
||||
msgstr "Hochladen"
|
||||
|
||||
#: cps/templates/layout.html:81 cps/templates/user_list.html:11
|
||||
msgid "Admin"
|
||||
msgstr "Admin"
|
||||
|
||||
#: cps/templates/layout.html:85
|
||||
msgid "Logout"
|
||||
msgstr "Logout"
|
||||
|
||||
#: cps/templates/layout.html:89 cps/templates/login.html:4
|
||||
msgid "Login"
|
||||
msgstr "Login"
|
||||
|
||||
#: cps/templates/layout.html:90 cps/templates/register.html:18
|
||||
msgid "Register"
|
||||
msgstr "Registrieren"
|
||||
|
||||
#: cps/templates/layout.html:119
|
||||
msgid "Browse"
|
||||
msgstr "Browsen"
|
||||
|
||||
#: cps/templates/layout.html:125
|
||||
msgid "Discover"
|
||||
msgstr "Entdecke"
|
||||
|
||||
#: cps/templates/layout.html:128
|
||||
msgid "Categories"
|
||||
msgstr "Kategorien"
|
||||
|
||||
#: cps/templates/layout.html:135
|
||||
msgid "Languages"
|
||||
msgstr "Sprachen"
|
||||
|
||||
#: cps/templates/layout.html:138
|
||||
msgid "Public Shelves"
|
||||
msgstr "Öffentiche Bücherregale"
|
||||
|
||||
#: cps/templates/layout.html:142
|
||||
msgid "Your Shelves"
|
||||
msgstr "Deine Bücherregale"
|
||||
|
||||
#: cps/templates/layout.html:147
|
||||
msgid "Create a Shelf"
|
||||
msgstr "Bücherregal erzeugen"
|
||||
|
||||
#: cps/templates/layout.html:150
|
||||
msgid "About"
|
||||
msgstr "Über"
|
||||
|
||||
#: cps/templates/login.html:7 cps/templates/login.html:8
|
||||
#: cps/templates/register.html:7 cps/templates/user_edit.html:8
|
||||
msgid "Username"
|
||||
msgstr "Benutzername"
|
||||
|
||||
#: cps/templates/login.html:11 cps/templates/login.html:12
|
||||
#: cps/templates/register.html:11 cps/templates/user_edit.html:18
|
||||
msgid "Password"
|
||||
msgstr "Passwort"
|
||||
|
||||
#: cps/templates/login.html:16
|
||||
msgid "Remember me"
|
||||
msgstr "Merken"
|
||||
|
||||
#: cps/templates/register.html:4
|
||||
msgid "Register a new account"
|
||||
msgstr "Neues Benutzerkonto erzeugen"
|
||||
|
||||
#: cps/templates/register.html:8
|
||||
msgid "Choose a username"
|
||||
msgstr "Wähle einen Benutzernamen"
|
||||
|
||||
#: cps/templates/register.html:12
|
||||
msgid "Choose a password"
|
||||
msgstr "Wähle ein Passwort"
|
||||
|
||||
#: cps/templates/register.html:15 cps/templates/user_edit.html:13
|
||||
msgid "Email address"
|
||||
msgstr "E-Mail Adresse"
|
||||
|
||||
#: cps/templates/register.html:16
|
||||
msgid "Your email address"
|
||||
msgstr "Deine E-Mail Adresse"
|
||||
|
||||
#: cps/templates/search.html:6
|
||||
msgid "No Results for:"
|
||||
msgstr "Keine Ergebnisse für:"
|
||||
|
||||
#: cps/templates/search.html:7
|
||||
msgid "Please try a diffrent Search"
|
||||
msgstr "Versuche eine andere Suche"
|
||||
|
||||
#: cps/templates/search.html:9
|
||||
msgid "Results for:"
|
||||
msgstr "Ergebnisse für:"
|
||||
|
||||
#: cps/templates/search_form.html:23
|
||||
msgid "Exclude Tags"
|
||||
msgstr "Tags ausschließen"
|
||||
|
||||
#: cps/templates/shelf.html:6
|
||||
msgid "Delete this Shelf"
|
||||
msgstr "Lösche dieses Bücherregal"
|
||||
|
||||
#: cps/templates/shelf_edit.html:7
|
||||
msgid "Title"
|
||||
msgstr "Titel"
|
||||
|
||||
#: cps/templates/shelf_edit.html:12
|
||||
msgid "should the shelf be public?"
|
||||
msgstr "Soll das Bücherregal öffentlich sein?"
|
||||
|
||||
#: cps/templates/stats.html:4
|
||||
msgid "Books in this Library"
|
||||
msgstr "Bücher in dieser Bibliothek"
|
||||
|
||||
#: cps/templates/stats.html:5
|
||||
msgid "Authors in this Library"
|
||||
msgstr "Autoren in dieser Bibliothek"
|
||||
|
||||
#: cps/templates/stats.html:6
|
||||
msgid "Version"
|
||||
msgstr "Version"
|
||||
|
||||
#: cps/templates/user_edit.html:23
|
||||
msgid "Kindle E-Mail"
|
||||
msgstr "Kindle E-Mail"
|
||||
|
||||
#: cps/templates/user_edit.html:35
|
||||
msgid "Show books with language"
|
||||
msgstr "Zeige nur Bücher mit dieser Sprache"
|
||||
|
||||
#: cps/templates/user_edit.html:37
|
||||
msgid "Show all"
|
||||
msgstr "Zeige alle"
|
||||
|
||||
#: cps/templates/user_edit.html:46
|
||||
msgid "Show random books"
|
||||
msgstr "Zeige Zufällige Bücher"
|
||||
|
||||
#: cps/templates/user_edit.html:50
|
||||
msgid "Show hot books"
|
||||
msgstr "Zeige Auswahl Beliebte Bücher"
|
||||
|
||||
#: cps/templates/user_edit.html:54
|
||||
msgid "Show language selection"
|
||||
msgstr "Zeige Sprachauswahl"
|
||||
|
||||
#: cps/templates/user_edit.html:58
|
||||
msgid "Show series selection"
|
||||
msgstr "Zeige Auswahl Serien"
|
||||
|
||||
#: cps/templates/user_edit.html:62
|
||||
msgid "Show category selection"
|
||||
msgstr "Zeige Kategorie Auswahl"
|
||||
|
||||
#: cps/templates/user_edit.html:67
|
||||
msgid "Admin user"
|
||||
msgstr "Admin Benutzer"
|
||||
|
||||
#: cps/templates/user_edit.html:71
|
||||
msgid "Allow Downloads"
|
||||
msgstr "Downloads erlauben"
|
||||
|
||||
#: cps/templates/user_edit.html:75
|
||||
msgid "Allow Uploads"
|
||||
msgstr "Uploads erlauben"
|
||||
|
||||
#: cps/templates/user_edit.html:79
|
||||
msgid "Allow Edit"
|
||||
msgstr "Bearbeiten erlauben"
|
||||
|
||||
#: cps/templates/user_edit.html:83
|
||||
msgid "Allow Changing Password"
|
||||
msgstr "Passwort ändern erlauben"
|
||||
|
||||
#: cps/templates/user_edit.html:89
|
||||
msgid "Delete this user"
|
||||
msgstr "Benutzer löschen"
|
||||
|
||||
#: cps/templates/user_edit.html:97
|
||||
msgid "Recent Downloads"
|
||||
msgstr "Letzte Downloads"
|
||||
|
||||
#: cps/templates/user_list.html:7
|
||||
msgid "Nickname"
|
||||
msgstr "Benutzername"
|
||||
|
||||
#: cps/templates/user_list.html:8
|
||||
msgid "Email"
|
||||
msgstr "E-Mail"
|
||||
|
||||
#: cps/templates/user_list.html:9
|
||||
msgid "Kindle"
|
||||
msgstr "Kindle"
|
||||
|
||||
#: cps/templates/user_list.html:10
|
||||
msgid "DLS"
|
||||
msgstr "DLS"
|
||||
|
||||
#: cps/templates/user_list.html:14
|
||||
msgid "Edit"
|
||||
msgstr "Editieren"
|
||||
|
||||
#: cps/templates/user_list.html:15
|
||||
msgid "Passwd"
|
||||
msgstr "Passwort"
|
||||
|
||||
#: cps/templates/user_list.html:33
|
||||
msgid "SMTP mail settings"
|
||||
msgstr "SMTP Mail Einstellungen"
|
||||
|
||||
#: cps/templates/user_list.html:37
|
||||
msgid "SMTP port"
|
||||
msgstr "SMTP Port"
|
||||
|
||||
#: cps/templates/user_list.html:38
|
||||
msgid "SSL"
|
||||
msgstr "SSL"
|
||||
|
||||
#: cps/templates/user_list.html:41
|
||||
msgid "From mail"
|
||||
msgstr "Absenderadresse"
|
||||
|
||||
#: cps/templates/user_list.html:53
|
||||
msgid "Change SMTP settings"
|
||||
msgstr "SMTP Einstellungen ändern"
|
||||
|
||||
msgid "Latin"
|
||||
msgstr "Latein"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from sqlalchemy import *
|
||||
from sqlalchemy import exc
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import *
|
||||
import os
|
||||
@@ -32,6 +33,13 @@ class User(Base):
|
||||
shelf = relationship('Shelf', backref = 'user', lazy = 'dynamic')
|
||||
whislist = relationship('Whislist', backref = 'user', lazy = 'dynamic')
|
||||
downloads = relationship('Downloads', backref= 'user', lazy = 'dynamic')
|
||||
locale = Column(String(2), default="en")
|
||||
random_books = Column(Integer, default=1)
|
||||
language_books = Column(Integer, default=1)
|
||||
series_books = Column(Integer, default=1)
|
||||
category_books = Column(Integer, default=1)
|
||||
hot_books = Column(Integer, default=1)
|
||||
default_language = Column(String(3), default="all")
|
||||
|
||||
def is_authenticated(self):
|
||||
return True
|
||||
@@ -70,6 +78,25 @@ class User(Base):
|
||||
def get_id(self):
|
||||
return unicode(self.id)
|
||||
|
||||
def filter_language(self):
|
||||
return self.default_language
|
||||
|
||||
def show_random_books(self):
|
||||
return self.random_books
|
||||
|
||||
def show_language(self):
|
||||
return self.language_books
|
||||
|
||||
def show_hot_books(self):
|
||||
return self.hot_books
|
||||
|
||||
def show_series(self):
|
||||
return self.series_books
|
||||
|
||||
def show_category(self):
|
||||
return self.category_books
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return '<User %r>' % (self.nickname)
|
||||
|
||||
@@ -147,6 +174,28 @@ class Settings(Base):
|
||||
#return '<Smtp %r>' % (self.mail_server)
|
||||
pass
|
||||
|
||||
def migrate_Database():
|
||||
try:
|
||||
session.query(exists().where(User.random_books)).scalar()
|
||||
session.commit()
|
||||
except exc.OperationalError: # Database is not compatible, some rows are missing
|
||||
conn=engine.connect()
|
||||
conn.execute("ALTER TABLE user ADD column random_books INTEGER DEFAULT 1")
|
||||
conn.execute("ALTER TABLE user ADD column locale String(2) DEFAULT 'en'")
|
||||
conn.execute("ALTER TABLE user ADD column default_language String(3) DEFAULT 'all'")
|
||||
session.commit()
|
||||
try:
|
||||
session.query(exists().where(User.language_books)).scalar()
|
||||
session.commit()
|
||||
except exc.OperationalError: # Database is not compatible, some rows are missing
|
||||
conn = engine.connect()
|
||||
conn.execute("ALTER TABLE user ADD column language_books INTEGER DEFAULT 1")
|
||||
conn.execute("ALTER TABLE user ADD column series_books INTEGER DEFAULT 1")
|
||||
conn.execute("ALTER TABLE user ADD column category_books INTEGER DEFAULT 1")
|
||||
conn.execute("ALTER TABLE user ADD column hot_books INTEGER DEFAULT 1")
|
||||
session.commit()
|
||||
|
||||
|
||||
def create_default_config():
|
||||
settings = Settings()
|
||||
settings.mail_server = "mail.example.com"
|
||||
@@ -200,4 +249,6 @@ if not os.path.exists(dbpath):
|
||||
create_admin_user()
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
migrate_Database()
|
||||
|
||||
|
||||
+727
-359
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user