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")