diff --git a/cps/static/css/style.css b/cps/static/css/style.css
index 7f053629..be91f295 100644
--- a/cps/static/css/style.css
+++ b/cps/static/css/style.css
@@ -44,7 +44,7 @@ span.glyphicon.glyphicon-tags {padding-right: 5px;color: #999;vertical-align: te
.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; }
-
+.button-link {color:#fff;}
.btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary{ background-color: #1C5484; }
.btn-primary.disabled, .btn-primary[disabled], fieldset[disabled] .btn-primary, .btn-primary.disabled:hover, .btn-primary[disabled]:hover, fieldset[disabled] .btn-primary:hover, .btn-primary.disabled:focus, .btn-primary[disabled]:focus, fieldset[disabled] .btn-primary:focus, .btn-primary.disabled:active, .btn-primary[disabled]:active, fieldset[disabled] .btn-primary:active, .btn-primary.disabled.active, .btn-primary[disabled].active, fieldset[disabled] .btn-primary.active { background-color: #89B9E2; }
.btn-toolbar>.btn+.btn, .btn-toolbar>.btn-group+.btn, .btn-toolbar>.btn+.btn-group, .btn-toolbar>.btn-group+.btn-group { margin-left:0px; }
@@ -58,3 +58,5 @@ span.glyphicon.glyphicon-tags {padding-right: 5px;color: #999;vertical-align: te
#shelf-action-errors {
margin-left: 5px;
}
+.author-bio img {margin: 0 1em 1em 0;}
+.author-link img {display: inline-block;max-width: 100px;}
diff --git a/cps/static/img/goodreads.svg b/cps/static/img/goodreads.svg
new file mode 100644
index 00000000..f89130e9
--- /dev/null
+++ b/cps/static/img/goodreads.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/cps/static/js/main.js b/cps/static/js/main.js
index d759a3b8..6c41bdf2 100644
--- a/cps/static/js/main.js
+++ b/cps/static/js/main.js
@@ -2,6 +2,20 @@ var displaytext;
var updateTimerID;
var updateText;
+// Generic control/related handler to show/hide fields based on a checkbox' value
+// e.g.
+//
+//
...
+$(document).on("change", "input[type=\"checkbox\"][data-control]", function () {
+ var $this = $(this);
+ var name = $this.data("control");
+ var showOrHide = $this.prop("checked");
+
+ $("[data-related=\""+name+"\"]").each(function () {
+ $(this).toggle(showOrHide);
+ });
+});
+
$(function() {
function restartTimer() {
@@ -121,6 +135,8 @@ $(function() {
});
});
+ $("input[data-control]").trigger("change");
+
$(window).resize(function(event) {
$(".discover .row").isotope("reLayout");
});
diff --git a/cps/templates/author.html b/cps/templates/author.html
new file mode 100644
index 00000000..bf33c812
--- /dev/null
+++ b/cps/templates/author.html
@@ -0,0 +1,65 @@
+{% extends "layout.html" %}
+{% block body %}
+{{title}}
+
+{% if author is not none %}
+
+ {%if author.image_url is not none %}
+
+ {% endif %}
+
+ {%if author.about is not none %}
+ {{author.about|safe}}
+ {% endif %}
+
+
+
+
+
+
+
+{% endif %}
+
+
+
+ {% if entries[0] %}
+ {% for entry in entries %}
+
+ {% endfor %}
+ {% endif %}
+
+
+{% endblock %}
diff --git a/cps/templates/config_edit.html b/cps/templates/config_edit.html
index 1b86616a..7ccd826d 100644
--- a/cps/templates/config_edit.html
+++ b/cps/templates/config_edit.html
@@ -97,6 +97,24 @@
{{_('Enable remote login ("magic link")')}}
+ {% if goodreads %}
+
+
+ {% endif %}
+
{{_('Default Settings for new users')}}
diff --git a/cps/ub.py b/cps/ub.py
index 7fae5b51..73ce8669 100644
--- a/cps/ub.py
+++ b/cps/ub.py
@@ -263,6 +263,9 @@ class Settings(Base):
config_google_drive_watch_changes_response = Column(String)
config_columns_to_ignore = Column(String)
config_remote_login = Column(Boolean)
+ config_use_goodreads = Column(Boolean)
+ config_goodreads_api_key = Column(String)
+ config_goodreads_api_secret = Column(String)
def __repr__(self):
pass
@@ -320,6 +323,9 @@ class Config:
self.db_configured = bool(self.config_calibre_dir is not None and
(not self.config_use_google_drive or os.path.exists(self.config_calibre_dir + '/metadata.db')))
self.config_remote_login = data.config_remote_login
+ self.config_use_goodreads = data.config_use_goodreads
+ self.config_goodreads_api_key = data.config_goodreads_api_key
+ self.config_goodreads_api_secret = data.config_goodreads_api_secret
@property
def get_main_dir(self):
@@ -471,6 +477,13 @@ def migrate_Database():
except exc.OperationalError:
conn = engine.connect()
conn.execute("ALTER TABLE Settings ADD column `config_remote_login` INTEGER DEFAULT 0")
+ try:
+ session.query(exists().where(Settings.config_use_goodreads)).scalar()
+ except exc.OperationalError:
+ conn = engine.connect()
+ conn.execute("ALTER TABLE Settings ADD column `config_use_goodreads` INTEGER DEFAULT 0")
+ conn.execute("ALTER TABLE Settings ADD column `config_goodreads_api_key` String DEFAULT ''")
+ conn.execute("ALTER TABLE Settings ADD column `config_goodreads_api_secret` String DEFAULT ''")
def clean_database():
# Remove expired remote login tokens
diff --git a/cps/web.py b/cps/web.py
index baf00c58..1437cb3a 100755
--- a/cps/web.py
+++ b/cps/web.py
@@ -7,6 +7,12 @@ try:
except ImportError:
gdrive_support = False
+try:
+ from goodreads import client as gr_client
+ goodreads_support = True
+except ImportError:
+ goodreads_support = False
+
import mimetypes
import logging
from logging.handlers import RotatingFileHandler
@@ -1117,10 +1123,16 @@ def author_list():
def author(book_id, page):
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.authors.any(db.Authors.id == book_id),
db.Books.timestamp.desc())
- name = db.session.query(db.Authors).filter(db.Authors.id == book_id).first().name
if entries:
- return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
- title=_(u"Author: %(name)s", name=name))
+ name = db.session.query(db.Authors).filter(db.Authors.id == book_id).first().name
+
+ author_info = None
+ if goodreads_support and config.config_use_goodreads:
+ gc = gr_client.GoodreadsClient(config.config_goodreads_api_key, config.config_goodreads_api_secret)
+ author_info = gc.find_author(author_name=name)
+
+ return render_title_template('author.html', entries=entries, pagination=pagination,
+ title=name, author=author_info)
else:
flash(_(u"Error opening eBook. File does not exist or file is not accessible:"), category="error")
return redirect(url_for("index"))
@@ -2355,11 +2367,20 @@ def configuration_helper(origin):
content.config_anonbrowse = 1
if "config_public_reg" in to_save and to_save["config_public_reg"] == "on":
content.config_public_reg = 1
- content.config_remote_login = ("config_remote_login" in to_save and to_save["config_remote_login"] == "on")
+ # Remote login configuration
+ content.config_remote_login = ("config_remote_login" in to_save and to_save["config_remote_login"] == "on")
if not content.config_remote_login:
ub.session.query(ub.RemoteAuthToken).delete()
+ # Goodreads configuration
+ content.config_use_goodreads = ("config_use_goodreads" in to_save and to_save["config_use_goodreads"] == "on")
+ if "config_goodreads_api_key" in to_save:
+ content.config_goodreads_api_key = to_save["config_goodreads_api_key"]
+ if "config_goodreads_api_secret" in to_save:
+ content.config_goodreads_api_secret = to_save["config_goodreads_api_secret"]
+
+
content.config_default_role = 0
if "admin_role" in to_save:
content.config_default_role = content.config_default_role + ub.ROLE_ADMIN
@@ -2390,13 +2411,13 @@ def configuration_helper(origin):
except e:
flash(e, category="error")
return render_title_template("config_edit.html", content=config, origin=origin, gdrive=gdrive_support,
- title=_(u"Basic Configuration"))
+ goodreads=goodreads_support, title=_(u"Basic Configuration"))
if db_change:
reload(db)
if not db.setup_db():
flash(_(u'DB location is not valid, please enter correct path'), category="error")
return render_title_template("config_edit.html", content=config, origin=origin, gdrive=gdrive_support,
- title=_(u"Basic Configuration"))
+ goodreads=goodreads_support, title=_(u"Basic Configuration"))
if reboot_required:
# db.engine.dispose() # ToDo verify correct
ub.session.close()
@@ -2410,7 +2431,7 @@ def configuration_helper(origin):
success = True
return render_title_template("config_edit.html", origin=origin, success=success, content=config,
show_authenticate_google_drive=not is_gdrive_ready(), gdrive=gdrive_support,
- title=_(u"Basic Configuration"))
+ goodreads=goodreads_support, title=_(u"Basic Configuration"))
@app.route("/admin/user/new", methods=["GET", "POST"])
diff --git a/optional-requirements.txt b/optional-requirements.txt
index 71c7b4ea..5e4c4414 100644
--- a/optional-requirements.txt
+++ b/optional-requirements.txt
@@ -11,3 +11,4 @@ PyYAML==3.12
rsa==3.4.2
six==1.10.0
uritemplate==3.0.0
+goodreads==0.3.2
\ No newline at end of file