From edadf84710ec97a362b144c8dea1d519cc664519 Mon Sep 17 00:00:00 2001 From: OzzieIsaacs Date: Tue, 7 Mar 2017 19:10:17 +0100 Subject: [PATCH] Added editing star rating graphically Added ability to reload database connection (refresh problem) Bugfix display hot books (no hot books, hot books are deleted books, no longer result in error 500) --- cps/db.py | 82 +++++++++---------- .../js/libs/bootstrap-rating-input.min.js | 1 + cps/static/js/main.js | 7 ++ cps/templates/admin.html | 1 + cps/templates/book_edit.html | 3 +- cps/templates/feed.xml | 2 + cps/templates/index.html | 2 + cps/web.py | 30 ++++++- 8 files changed, 81 insertions(+), 47 deletions(-) create mode 100644 cps/static/js/libs/bootstrap-rating-input.min.js diff --git a/cps/db.py b/cps/db.py index 9c48cfbb..a8a33601 100755 --- a/cps/db.py +++ b/cps/db.py @@ -11,10 +11,8 @@ from ub import config import ub session = None -cc_exceptions = None +cc_exceptions = ['datetime', 'int', 'comments', 'float', 'composite', 'series'] cc_classes = None -cc_ids = None -books_custom_column_links = None engine = None @@ -283,12 +281,9 @@ class Custom_Columns(Base): def setup_db(): + global engine global session - global cc_exceptions global cc_classes - global cc_ids - global books_custom_column_links - global engine if config.config_calibre_dir is None or config.config_calibre_dir == u'': return False @@ -297,7 +292,6 @@ def setup_db(): engine = create_engine('sqlite:///{0}'.format(dbpath.encode('utf-8')), echo=False, isolation_level="SERIALIZABLE") try: conn = engine.connect() - except: content = ub.session.query(ub.Settings).first() content.config_calibre_dir = None @@ -311,43 +305,43 @@ def setup_db(): config.loadSettings() conn.connection.create_function('title_sort', 1, title_sort) - cc = conn.execute("SELECT id, datatype FROM custom_columns") - - cc_ids = [] - 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) - ) - 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)} + if not cc_classes: + cc = conn.execute("SELECT id, datatype FROM custom_columns") + + cc_ids = [] + 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) + ) + 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) + + for id in cc_ids: + 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: - 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) - - for id in cc_ids: - 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')) + setattr(Books, 'custom_column_' + str(id[0]), relationship(cc_classes[id[0]], + secondary=books_custom_column_links[id[0]], + backref='books')) # Base.metadata.create_all(engine) Session = sessionmaker() diff --git a/cps/static/js/libs/bootstrap-rating-input.min.js b/cps/static/js/libs/bootstrap-rating-input.min.js new file mode 100644 index 00000000..0398742e --- /dev/null +++ b/cps/static/js/libs/bootstrap-rating-input.min.js @@ -0,0 +1 @@ +!function(a){"use strict";function b(a){return"[data-value"+(a?"="+a:"")+"]"}function c(a,b,c){var d=c.activeIcon,e=c.inactiveIcon;a.removeClass(b?e:d).addClass(b?d:e)}function d(b,c){var d=a.extend({},i,b.data(),c);return d.inline=""===d.inline||d.inline,d.readonly=""===d.readonly||d.readonly,d.clearable===!1?d.clearableLabel="":d.clearableLabel=d.clearable,d.clearable=""===d.clearable||d.clearable,d}function e(b,c){if(c.inline)var d=a('');else var d=a('
');d.addClass(b.attr("class")),d.removeClass("rating");for(var e=c.min;e<=c.max;e++)d.append('');return c.clearable&&!c.readonly&&d.append(" ").append(''+c.clearableLabel+""),d}var f="rating-clear",g="."+f,h="hidden",i={min:1,max:5,"empty-value":0,iconLib:"glyphicon",activeIcon:"glyphicon-star",inactiveIcon:"glyphicon-star-empty",clearable:!1,clearableIcon:"glyphicon-remove",clearableRemain:!1,inline:!1,readonly:!1},j=function(a,b){var c=this.$input=a;this.options=d(c,b);var f=this.$el=e(c,this.options);c.addClass(h).before(f),c.attr("type","hidden"),this.highlight(c.val())};j.VERSION="0.4.0",j.DEFAULTS=i,j.prototype={clear:function(){this.setValue(this.options["empty-value"])},setValue:function(a){this.highlight(a),this.updateInput(a)},highlight:function(a,d){var e=this.options,f=this.$el;if(a>=this.options.min&&a<=this.options.max){var i=f.find(b(a));c(i.prevAll("i").andSelf(),!0,e),c(i.nextAll("i"),!1,e)}else c(f.find(b()),!1,e);d||(this.options.clearableRemain?f.find(g).removeClass(h):a&&a!=this.options["empty-value"]?f.find(g).removeClass(h):f.find(g).addClass(h))},updateInput:function(a){var b=this.$input;b.val()!=a&&b.val(a).change()}};var k=a.fn.rating=function(c){return this.filter("input[type=number]").each(function(){var d=a(this),e="object"==typeof c&&c||{},f=new j(d,e);f.options.readonly||f.$el.on("mouseenter",b(),function(){f.highlight(a(this).data("value"),!0)}).on("mouseleave",b(),function(){f.highlight(d.val(),!0)}).on("click",b(),function(){f.setValue(a(this).data("value"))}).on("click",g,function(){f.clear()})})};k.Constructor=j,a(function(){a("input.rating[type=number]").each(function(){a(this).rating()})})}(jQuery); \ No newline at end of file diff --git a/cps/static/js/main.js b/cps/static/js/main.js index 8b0b099f..7a498f36 100644 --- a/cps/static/js/main.js +++ b/cps/static/js/main.js @@ -65,6 +65,13 @@ $(function() { } }); }); + $("#restart_database").click(function() { + $.ajax({ + dataType: 'json', + url: window.location.pathname+"/../../shutdown", + data: {"parameter":2} + }); + }); $("#perform_update").click(function() { $('#spinner2').show(); $.ajax({ diff --git a/cps/templates/admin.html b/cps/templates/admin.html index b386e4ff..18d99ab8 100644 --- a/cps/templates/admin.html +++ b/cps/templates/admin.html @@ -80,6 +80,7 @@
{{_('Current commit timestamp')}}: {{commit}}

+
{{_('Reconnect to Calibre DB')}}
{{_('Restart Calibre-web')}}
{{_('Stop Calibre-web')}}
{{_('Check for update')}}
diff --git a/cps/templates/book_edit.html b/cps/templates/book_edit.html index 32452dd8..19abf315 100644 --- a/cps/templates/book_edit.html +++ b/cps/templates/book_edit.html @@ -39,7 +39,7 @@
- +
@@ -114,6 +114,7 @@ {% block js %} + {% endblock %} {% block header %} diff --git a/cps/templates/feed.xml b/cps/templates/feed.xml index 5bda14f9..52fb2ba3 100644 --- a/cps/templates/feed.xml +++ b/cps/templates/feed.xml @@ -35,6 +35,7 @@ https://github.com/janeczku/calibre-web + {% if entries[0] %} {% for entry in entries %} {{entry.title}} @@ -60,6 +61,7 @@ {% endfor %} {% endfor %} + {% endif %} {% for entry in listelements %} {{entry.name}} diff --git a/cps/templates/index.html b/cps/templates/index.html index 7ab46a7b..744fea89 100755 --- a/cps/templates/index.html +++ b/cps/templates/index.html @@ -40,6 +40,7 @@

{{title}}

+ {% if entries[0] %} {% for entry in entries %}
@@ -76,6 +77,7 @@
{% endfor %} + {% endif %}
{% endblock %} diff --git a/cps/web.py b/cps/web.py index 7008a622..8f36f79f 100755 --- a/cps/web.py +++ b/cps/web.py @@ -136,6 +136,15 @@ lm.anonymous_user = ub.Anonymous app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT' db.setup_db() +if config.config_log_level == logging.DEBUG : + logging.getLogger("sqlalchemy.engine").addHandler(file_handler) + logging.getLogger("sqlalchemy.engine").setLevel(logging.INFO) + logging.getLogger("sqlalchemy.pool").addHandler(file_handler) + logging.getLogger("sqlalchemy.pool").setLevel(config.config_log_level) + logging.getLogger("sqlalchemy.orm").addHandler(file_handler) + logging.getLogger("sqlalchemy.orm").setLevel(config.config_log_level) + + @babel.localeselector def get_locale(): # if a user is logged in, use the locale from the user settings @@ -550,7 +559,13 @@ def feed_hot(): hot_books = all_books.offset(off).limit(config.config_books_per_page) entries = list() for book in hot_books: - entries.append(db.session.query(db.Books).filter(filter).filter(db.Books.id == book.Downloads.book_id).first()) + downloadBook = db.session.query(db.Books).filter(db.Books.id == book.Downloads.book_id).first() + if downloadBook: + entries.append( + db.session.query(db.Books).filter(filter).filter(db.Books.id == book.Downloads.book_id).first()) + else: + ub.session.query(ub.Downloads).filter(book.Downloads.book_id == ub.Downloads.book_id).delete() + ub.session.commit() numBooks = entries.__len__() pagination = Pagination((int(off) / (int(config.config_books_per_page)) + 1), config.config_books_per_page, numBooks) xml = render_title_template('feed.xml', entries=entries, pagination=pagination) @@ -839,7 +854,13 @@ def hot_books(page): hot_books = all_books.offset(off).limit(config.config_books_per_page) entries = list() for book in hot_books: - entries.append(db.session.query(db.Books).filter(filter).filter(db.Books.id == book.Downloads.book_id).first()) + downloadBook = db.session.query(db.Books).filter(db.Books.id == book.Downloads.book_id).first() + if downloadBook: + entries.append( + db.session.query(db.Books).filter(filter).filter(db.Books.id == book.Downloads.book_id).first()) + else: + ub.session.query(ub.Downloads).filter(book.Downloads.book_id == ub.Downloads.book_id).delete() + ub.session.commit() numBooks = entries.__len__() pagination = Pagination(page, config.config_books_per_page, numBooks) return render_title_template('index.html', random=random, entries=entries, pagination=pagination, @@ -1085,6 +1106,11 @@ def shutdown(): showtext['text'] = _(u'Performing shutdown of server, please close window') return json.dumps(showtext) else: + if task == 2: + db.session.close() + db.engine.dispose() + db.setup_db() + return json.dumps({}) abort(404) @app.route("/update")