From 99d653eece37aa874d5dd47a57c74ed82e9a6409 Mon Sep 17 00:00:00 2001 From: norangebit Date: Tue, 1 Sep 2020 18:22:49 +0200 Subject: [PATCH 001/255] Add automatic conversion in kepub Automatic conversion from epub to kepub of new book on Kobo sync. --- cps/kobo.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cps/kobo.py b/cps/kobo.py index a6dfc3f6..dabfb6b9 100644 --- a/cps/kobo.py +++ b/cps/kobo.py @@ -178,6 +178,10 @@ def HandleSyncRequest(): reading_states_in_new_entitlements = [] for book in changed_entries: + formats = [data.format for data in book.data] + if not 'KEPUB' in formats and config.config_kepubifypath and 'EPUB' in formats: + helper.convert_book_format(book.id, config.config_calibre_dir, 'EPUB', 'KEPUB', current_user.nickname) + kobo_reading_state = get_or_create_reading_state(book.id) entitlement = { "BookEntitlement": create_book_entitlement(book, archived=(book.id in archived_book_ids)), From bdf6052388ede46c99b9cc8bec57f93382881fb0 Mon Sep 17 00:00:00 2001 From: norangebit Date: Thu, 3 Sep 2020 21:57:14 +0200 Subject: [PATCH 002/255] Conversion to kepub when creating a sync token --- cps/kobo_auth.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cps/kobo_auth.py b/cps/kobo_auth.py index 0f6cd174..f21d1cb6 100644 --- a/cps/kobo_auth.py +++ b/cps/kobo_auth.py @@ -64,10 +64,10 @@ from datetime import datetime from os import urandom from flask import g, Blueprint, url_for, abort, request -from flask_login import login_user, login_required +from flask_login import current_user, login_user, login_required from flask_babel import gettext as _ -from . import logger, ub, lm +from . import logger, config, calibre_db, db, helper, ub, lm from .web import render_title_template try: @@ -148,6 +148,14 @@ def generate_auth_token(user_id): ub.session.add(auth_token) ub.session.commit() + + books = calibre_db.session.query(db.Books).join(db.Data).all() + + for book in books: + formats = [data.format for data in book.data] + if not 'KEPUB' in formats and config.config_kepubifypath and 'EPUB' in formats: + helper.convert_book_format(book.id, config.config_calibre_dir, 'EPUB', 'KEPUB', current_user.nickname) + return render_title_template( "generate_kobo_auth_url.html", title=_(u"Kobo Setup"), From cb7727900c4e96b90480bc70ea71d5042401aac0 Mon Sep 17 00:00:00 2001 From: dickreckard Date: Mon, 7 Sep 2020 13:30:03 +0200 Subject: [PATCH 003/255] Update uploader.py default cover changed from none to pdf_preview when metadata parsing fails --- cps/uploader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cps/uploader.py b/cps/uploader.py index 2cb982b9..863d094d 100644 --- a/cps/uploader.py +++ b/cps/uploader.py @@ -106,7 +106,7 @@ def default_meta(tmp_file_path, original_file_name, original_file_extension): extension=original_file_extension, title=original_file_name, author=_(u'Unknown'), - cover=None, + cover=pdf_preview(tmp_file_path, original_file_name), description="", tags="", series="", From 23fe79c6182b7f08eb8769ed7c8c1203c61ef63a Mon Sep 17 00:00:00 2001 From: dickreckard Date: Fri, 11 Sep 2020 03:42:19 +0200 Subject: [PATCH 004/255] Update uploader.py --- cps/uploader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cps/uploader.py b/cps/uploader.py index 863d094d..dd37bf62 100644 --- a/cps/uploader.py +++ b/cps/uploader.py @@ -135,7 +135,7 @@ def pdf_meta(tmp_file_path, original_file_name, original_file_extension): author=' & '.join(split_authors([author])), cover=pdf_preview(tmp_file_path, original_file_name), description=subject, - tags="", + tags=doc_info['/Keywords'], series="", series_id="", languages="") From 22466d6b98fabf0046245c68b7db2bcf8c45991f Mon Sep 17 00:00:00 2001 From: root Date: Fri, 11 Sep 2020 10:08:55 +0000 Subject: [PATCH 005/255] xmp data processing added to the uploader --- cps/uploader.py | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/cps/uploader.py b/cps/uploader.py index dd37bf62..3747b24f 100644 --- a/cps/uploader.py +++ b/cps/uploader.py @@ -119,10 +119,36 @@ def pdf_meta(tmp_file_path, original_file_name, original_file_extension): if use_pdf_meta: with open(tmp_file_path, 'rb') as f: doc_info = PdfFileReader(f).getDocumentInfo() - if doc_info: - author = doc_info.author if doc_info.author else u'Unknown' - title = doc_info.title if doc_info.title else original_file_name - subject = doc_info.subject + xmp_info = PdfFileReader(f).getXmpMetadata() + if xmp_info: + xmp_author = xmp_info.dc_creator + if xmp_info.dc_title: + xmp_title = xmp_info.dc_title['x-default'] + else: + xmp_title = '' + if xmp_info.dc_description: + xmp_description = xmp_info.dc_description['x-default'] + else: + xmp_description = '' + if xmp_info.dc_subject: + xmp_tags = ', '.join(xmp_info.dc_subject) + else: + xmp_tags = '' + if xmp_info.dc_language: + xmp_language = ', '.join(xmp_info.dc_language) + else: + xmp_language='' + if xmp_info.dc_publisher: + xmp_publisher = ', '.join(xmp_info.dc_publisher) + else: + xmp_publisher='' + if xmp_info or doc_info: + author = xmp_author or split_authors([doc_info.author]) or u'Unknown' + title = xmp_title or doc_info.title or original_file_name + subject = xmp_description or doc_info.subject + publisher = xmp_publisher + tags = xmp_tags or doc_info['/Keywords'] + language = xmp_language else: author = u'Unknown' title = original_file_name @@ -132,13 +158,13 @@ def pdf_meta(tmp_file_path, original_file_name, original_file_extension): file_path=tmp_file_path, extension=original_file_extension, title=title, - author=' & '.join(split_authors([author])), + author=' & '.join(author), cover=pdf_preview(tmp_file_path, original_file_name), description=subject, - tags=doc_info['/Keywords'], + tags=tags, series="", series_id="", - languages="") + languages=language) def pdf_preview(tmp_file_path, tmp_dir): From 65929c02bc2150ad932fc61366cf5ca4b771c208 Mon Sep 17 00:00:00 2001 From: dickreckard Date: Fri, 11 Sep 2020 10:49:45 +0000 Subject: [PATCH 006/255] isolanguage parsing of xmp data --- cps/uploader.py | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/cps/uploader.py b/cps/uploader.py index 3747b24f..3f2b986a 100644 --- a/cps/uploader.py +++ b/cps/uploader.py @@ -22,7 +22,7 @@ import hashlib from tempfile import gettempdir from flask_babel import gettext as _ -from . import logger, comic +from . import logger, comic, isoLanguages from .constants import BookMeta from .helper import split_authors @@ -118,8 +118,9 @@ def pdf_meta(tmp_file_path, original_file_name, original_file_extension): doc_info = None if use_pdf_meta: with open(tmp_file_path, 'rb') as f: - doc_info = PdfFileReader(f).getDocumentInfo() - xmp_info = PdfFileReader(f).getXmpMetadata() + pdf_file = PdfFileReader(f) + doc_info = pdf_file.getDocumentInfo() + xmp_info = pdf_file.getXmpMetadata() if xmp_info: xmp_author = xmp_info.dc_creator if xmp_info.dc_title: @@ -130,25 +131,26 @@ def pdf_meta(tmp_file_path, original_file_name, original_file_extension): xmp_description = xmp_info.dc_description['x-default'] else: xmp_description = '' - if xmp_info.dc_subject: - xmp_tags = ', '.join(xmp_info.dc_subject) - else: - xmp_tags = '' - if xmp_info.dc_language: - xmp_language = ', '.join(xmp_info.dc_language) - else: - xmp_language='' - if xmp_info.dc_publisher: - xmp_publisher = ', '.join(xmp_info.dc_publisher) - else: - xmp_publisher='' + xmp_tags = ', '.join(xmp_info.dc_subject) + xmp_language = xmp_info.dc_language[0] + xmp_publisher = ', '.join(xmp_info.dc_publisher) + if xmp_info or doc_info: author = xmp_author or split_authors([doc_info.author]) or u'Unknown' title = xmp_title or doc_info.title or original_file_name subject = xmp_description or doc_info.subject publisher = xmp_publisher tags = xmp_tags or doc_info['/Keywords'] - language = xmp_language + if xmp_language : + lang = xmp_language.split('-', 1)[0].lower() + if len(lang) == 2: + language = isoLanguages.get(part1=lang).name + elif len(lang) == 3: + language = isoLanguages.get(part3=lang).name + else: + language = '' + else: + language = '' else: author = u'Unknown' title = original_file_name From 097ac879eabb57b7dcf310dbe0bae956e2512013 Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Mon, 12 Oct 2020 09:31:58 +0200 Subject: [PATCH 007/255] render read --- cps/static/css/style.css | 23 +++++++++++++++++++---- cps/templates/grid.html | 6 ++++-- cps/templates/index.html | 3 +++ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/cps/static/css/style.css b/cps/static/css/style.css index 2294d326..6b3cba15 100644 --- a/cps/static/css/style.css +++ b/cps/static/css/style.css @@ -123,12 +123,19 @@ a, .danger,.book-remove, .editable-empty, .editable-empty:hover { color: #45b29d position: relative; } -.container-fluid .book .cover img { +.container-fluid .book .cover span.img { + bottom: 0; + height: 100%; + position: absolute; +} + +.container-fluid .book .cover span img { + position: relative; + top: 0; + left: 0; + height: 100%; border: 1px solid #fff; box-sizing: border-box; - height: 100%; - bottom: 0; - position: absolute; -webkit-box-shadow: 0 5px 8px -6px #777; -moz-box-shadow: 0 5px 8px -6px #777; box-shadow: 0 5px 8px -6px #777; @@ -203,6 +210,14 @@ span.glyphicon.glyphicon-tags { left: 2px; background-color: #777; } +.cover .read{ + left: auto; + right: 2px; + width: 17px; + height: 17px; + display: inline-block; + padding: 2px; +} .cover-height { max-height: 100px;} .col-sm-2 a .cover-small { diff --git a/cps/templates/grid.html b/cps/templates/grid.html index 4aa0b7df..c44af387 100644 --- a/cps/templates/grid.html +++ b/cps/templates/grid.html @@ -28,8 +28,10 @@
diff --git a/cps/templates/index.html b/cps/templates/index.html index e60f92fe..319fd60f 100644 --- a/cps/templates/index.html +++ b/cps/templates/index.html @@ -79,7 +79,10 @@
From 754b9832e95081b22e22e91dd57b65cf595adf37 Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Sat, 17 Oct 2020 13:30:19 +0200 Subject: [PATCH 008/255] fix height container --- cps/static/css/style.css | 1 + 1 file changed, 1 insertion(+) diff --git a/cps/static/css/style.css b/cps/static/css/style.css index 6b3cba15..abe0ca48 100644 --- a/cps/static/css/style.css +++ b/cps/static/css/style.css @@ -111,6 +111,7 @@ a, .danger,.book-remove, .editable-empty, .editable-empty:hover { color: #45b29d display: block; max-width: 100%; height: auto; + max-height: 100%; } .container-fluid .discover{ margin-bottom: 50px; } From b2594468b41b3ce99f732543bd79ee13a4463258 Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Sat, 17 Oct 2020 16:49:06 +0200 Subject: [PATCH 009/255] add helper to get all read books --- cps/helper.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cps/helper.py b/cps/helper.py index 82d0b232..71dd2cc4 100644 --- a/cps/helper.py +++ b/cps/helper.py @@ -819,3 +819,18 @@ def get_download_link(book_id, book_format, client): return do_download_file(book, book_format, client, data1, headers) else: abort(404) + + +def get_readbooks_ids(): + if not config.config_read_column: + readBooks = ub.session.query(ub.ReadBook).filter(ub.ReadBook.user_id == int(current_user.id))\ + .filter(ub.ReadBook.is_read == True).all() + return frozenset([x.book_id for x in readBooks]) + else: + try: + readBooks = calibre_db.session.query(db.cc_classes[config.config_read_column])\ + .filter(db.cc_classes[config.config_read_column].value == True).all() + return frozenset([x.book for x in readBooks]) + except KeyError: + log.error("Custom Column No.%d is not existing in calibre database", config.config_read_column) + return [] \ No newline at end of file From 7d28963a32769f9749d2478241281422e3809bee Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Sat, 17 Oct 2020 16:49:38 +0200 Subject: [PATCH 010/255] connect read books to all render --- cps/web.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cps/web.py b/cps/web.py index aa1cac1a..a3eb37d5 100644 --- a/cps/web.py +++ b/cps/web.py @@ -59,7 +59,8 @@ from . import calibre_db from .gdriveutils import getFileFromEbooksFolder, do_gdrive_download from .helper import check_valid_domain, render_task_status, \ get_cc_columns, get_book_cover, get_download_link, send_mail, generate_random_password, \ - send_registration_mail, check_send_to_kindle, check_read_formats, tags_filters, reset_password + send_registration_mail, check_send_to_kindle, check_read_formats, tags_filters, reset_password, \ + get_readbooks_ids from .pagination import Pagination from .redirect import redirect_back @@ -602,7 +603,7 @@ def get_matching_tags(): def render_title_template(*args, **kwargs): sidebar = ub.get_sidebar_config(kwargs) return render_template(instance=config.config_calibre_web_title, sidebar=sidebar, - accept=constants.EXTENSIONS_UPLOAD, + accept=constants.EXTENSIONS_UPLOAD, read_book_ids=get_readbooks_ids(), *args, **kwargs) From 4d81d3613ca7baa9416c82193186efc4f31b8e99 Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Sat, 17 Oct 2020 16:49:57 +0200 Subject: [PATCH 011/255] display the check when books are read --- cps/templates/author.html | 5 ++++- cps/templates/discover.html | 5 ++++- cps/templates/index.html | 7 +++++-- cps/templates/search.html | 5 ++++- cps/templates/shelf.html | 5 ++++- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/cps/templates/author.html b/cps/templates/author.html index 0015d6e2..fadc9a04 100644 --- a/cps/templates/author.html +++ b/cps/templates/author.html @@ -40,7 +40,10 @@
diff --git a/cps/templates/discover.html b/cps/templates/discover.html index 9abe3666..ed95bc03 100644 --- a/cps/templates/discover.html +++ b/cps/templates/discover.html @@ -8,7 +8,10 @@
{% if entry.has_cover is defined %} - {{ entry.title }} + + {{ entry.title }} + {% if entry.id in read_book_ids %}{% endif %} + {% endif %}
diff --git a/cps/templates/index.html b/cps/templates/index.html index 319fd60f..4f341e1e 100644 --- a/cps/templates/index.html +++ b/cps/templates/index.html @@ -8,7 +8,10 @@
diff --git a/cps/templates/search.html b/cps/templates/search.html index cba430a4..e619e856 100644 --- a/cps/templates/search.html +++ b/cps/templates/search.html @@ -41,7 +41,10 @@
{% if entry.has_cover is defined %} - {{ entry.title }} + + {{ entry.title }} + {% if entry.id in read_book_ids %}{% endif %} + {% endif %}
diff --git a/cps/templates/shelf.html b/cps/templates/shelf.html index a2655f96..db1c3bcf 100644 --- a/cps/templates/shelf.html +++ b/cps/templates/shelf.html @@ -18,7 +18,10 @@
From 09a5a69f86c210ed07a8e5bc803432ff48999e74 Mon Sep 17 00:00:00 2001 From: verglor Date: Sun, 15 Nov 2020 13:09:32 +0100 Subject: [PATCH 012/255] djvu_html5 0.3.0-beta1 static assets --- cps/static/js/libs/djvu_html5/Djvu_html5.css | 194 ++++ cps/static/js/libs/djvu_html5/Djvu_html5.html | 35 + .../091ECB3AE852C68866FBC86AA8FCDB1F.cache.js | 8 + .../1A420474460884E73E3288F783AD7024.cache.js | 8 + .../3CFDA9D9AFA2798299BBAE243DB2E9B5.cache.js | 8 + .../564CB406D925C79CCD67EB98CA5AD4EF.cache.js | 8 + .../A8305F17E026239876FCBC730B035A55.cache.js | 8 + .../djvu_html5/djvu_html5/clear.cache.gif | Bin 0 -> 43 bytes .../djvu_html5/compilation-mappings.txt | 16 + .../djvu_html5/djvu_html5.devmode.js | 1 + .../djvu_html5/djvu_html5.nocache.js | 26 + .../81EB501BD7AB47786C30D3175CE1EA2B.cache.js | 827 ++++++++++++++++++ .../djvu_html5/djvu_worker/clear.cache.gif | Bin 0 -> 43 bytes .../djvu_worker/djvu_worker.nocache.js | 2 + cps/static/js/libs/djvu_html5/img/blank.jpg | Bin 0 -> 13223 bytes cps/static/js/libs/djvu_html5/img/status.png | Bin 0 -> 16208 bytes .../libs/djvu_html5/img/toolbar-buttons.png | Bin 0 -> 14381 bytes 17 files changed, 1141 insertions(+) create mode 100644 cps/static/js/libs/djvu_html5/Djvu_html5.css create mode 100644 cps/static/js/libs/djvu_html5/Djvu_html5.html create mode 100644 cps/static/js/libs/djvu_html5/djvu_html5/091ECB3AE852C68866FBC86AA8FCDB1F.cache.js create mode 100644 cps/static/js/libs/djvu_html5/djvu_html5/1A420474460884E73E3288F783AD7024.cache.js create mode 100644 cps/static/js/libs/djvu_html5/djvu_html5/3CFDA9D9AFA2798299BBAE243DB2E9B5.cache.js create mode 100644 cps/static/js/libs/djvu_html5/djvu_html5/564CB406D925C79CCD67EB98CA5AD4EF.cache.js create mode 100644 cps/static/js/libs/djvu_html5/djvu_html5/A8305F17E026239876FCBC730B035A55.cache.js create mode 100644 cps/static/js/libs/djvu_html5/djvu_html5/clear.cache.gif create mode 100644 cps/static/js/libs/djvu_html5/djvu_html5/compilation-mappings.txt create mode 100644 cps/static/js/libs/djvu_html5/djvu_html5/djvu_html5.devmode.js create mode 100644 cps/static/js/libs/djvu_html5/djvu_html5/djvu_html5.nocache.js create mode 100644 cps/static/js/libs/djvu_html5/djvu_worker/81EB501BD7AB47786C30D3175CE1EA2B.cache.js create mode 100644 cps/static/js/libs/djvu_html5/djvu_worker/clear.cache.gif create mode 100644 cps/static/js/libs/djvu_html5/djvu_worker/djvu_worker.nocache.js create mode 100644 cps/static/js/libs/djvu_html5/img/blank.jpg create mode 100644 cps/static/js/libs/djvu_html5/img/status.png create mode 100644 cps/static/js/libs/djvu_html5/img/toolbar-buttons.png diff --git a/cps/static/js/libs/djvu_html5/Djvu_html5.css b/cps/static/js/libs/djvu_html5/Djvu_html5.css new file mode 100644 index 00000000..77e37c97 --- /dev/null +++ b/cps/static/js/libs/djvu_html5/Djvu_html5.css @@ -0,0 +1,194 @@ +body { + margin: 0px; +} + +#djvuContainer { + position: absolute; + width: 100%; + height: 100%; + max-width: 100%; + text-align: center; + overflow: hidden; +} + +.toolbar { + position: relative; + display: inline-block; + padding-top: 10px; + + transform: translate(0, 0); + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + transition: transform 0.3s; + -webkit-transition: -webkit-transform 0.3s; +} + +.toolbarHidden { + transform: translate(0, -100%); + -webkit-transform: translate(0, -100%); + -ms-transform: translate(0, -100%); + transition: transform 1s; + -webkit-transition: transform 1s; +} + +.toolbarSquareButton { + float: left; + width: 40px; + height: 40px; + background-image: url("img/toolbar-buttons.png"); + background-repeat: no-repeat; + background-size: 500% 300%; +} + +.scrollbar { + position: absolute; + border-radius: 6px; + opacity: 0.6; + box-shadow: inset 0 0 0 1px black, inset 0 0 0 2px white, inset 0 0 0 10px #BBB; + transition: opacity 0.3s; +} +.scrollbar:hover { + box-shadow: inset 0 0 0 1px black, inset 0 0 0 2px white, inset 0 0 0 10px #999; +} +.scrollbarClicked, .scrollbarClicked:hover { + box-shadow: inset 0 0 0 1px black, inset 0 0 0 2px white, inset 0 0 0 10px #777; +} +.scrollbarHidden { + opacity: 0; + transition: opacity 0.6s; +} + +.scrollbarVertical { + right: 0px; + border-right: 1px solid transparent; + width: 13px; +} + +.scrollbarHorizontal { + bottom: 0px; + border-bottom: 1px solid transparent; + height: 13px; +} + +.content { + overflow: hidden; + position: absolute; + height: 100%; + width: 100%; +} + +.textLayer { + position: absolute; + height: 120%; + width: 120%; + overflow: scroll; + text-align: left; +} +_:-ms-lang(x), .textLayer { + height: 100%; + width: 100%; + -ms-overflow-style: none; +} +.textPage { + margin-top: 100vh; + margin-bottom: 100vh; + padding-right: 100vw; +} +.textPage span { + font-family: sans-serif; + color: #000; + color: rgba(0, 0, 0, 0); + white-space: nowrap; +} +.visibleTextPage span { + display: inline-block; + position: relative; + + top: 50%; + transform: translateY(-50%); + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + /* border: 1px solid red; /* for easy debug */ +} + +.buttonZoomIn { + background-position: 25% 0; +} +.buttonZoomIn:hover { + background-position: 25% 50%; +} +.buttonZoomIn:disabled { + background-position: 25% 100%; +} + +.buttonZoomOut { + background-position: 0 0; +} +.buttonZoomOut:hover { + background-position: 0 50%; +} +.buttonZoomOut:disabled { + background-position: 0 100%; +} + +.buttonPagePrev { + background-position: 50% 0; +} +.buttonPagePrev:hover { + background-position: 50% 50%; +} +.buttonPagePrev:disabled { + background-position: 50% 100%; +} + +.buttonPageNext { + background-position: 75% 0; +} +.buttonPageNext:hover { + background-position: 75% 50%; +} +.buttonPageNext:disabled { + background-position: 75% 100%; +} + +.toolbarItem { + display: inline-block; + margin: 0 10px; +} + +.comboBox { + float: left; + position: relative; +} + +.comboBoxSelection { + width: 8.25ex; + margin: 10px 12px 0px 12px; +} + +.comboBoxText { + width: 5ex; + border: none; + padding: 0px; + outline: none; + + position: absolute; + margin: 10px 0px 0px 12px; + top: 2px; + left: 3px; +} + +.statusImage { + position: absolute; + left: 50%; + top: 50%; + width: 128px; + height: 128px; + margin: -72px 0 0 -64px; + background-image: url("img/status.png"); + background-repeat: no-repeat; +} + +.blankImage { + background-image: url("img/blank.jpg"); +} \ No newline at end of file diff --git a/cps/static/js/libs/djvu_html5/Djvu_html5.html b/cps/static/js/libs/djvu_html5/Djvu_html5.html new file mode 100644 index 00000000..34886649 --- /dev/null +++ b/cps/static/js/libs/djvu_html5/Djvu_html5.html @@ -0,0 +1,35 @@ + + + + + + + + + +Djvu HTML5 browser demo + + + + + + + + + +
+ + + + diff --git a/cps/static/js/libs/djvu_html5/djvu_html5/091ECB3AE852C68866FBC86AA8FCDB1F.cache.js b/cps/static/js/libs/djvu_html5/djvu_html5/091ECB3AE852C68866FBC86AA8FCDB1F.cache.js new file mode 100644 index 00000000..602edae2 --- /dev/null +++ b/cps/static/js/libs/djvu_html5/djvu_html5/091ECB3AE852C68866FBC86AA8FCDB1F.cache.js @@ -0,0 +1,8 @@ +djvu_html5.onScriptDownloaded(["var $wnd = $wnd || window.parent;var __gwtModuleFunction = $wnd.djvu_html5;var $sendStats = __gwtModuleFunction.__sendStats;$sendStats('moduleStartup', 'moduleEvalStart');var $gwt_version = \"2.8.1\";var $strongName = '091ECB3AE852C68866FBC86AA8FCDB1F';var $gwt = {};var $doc = $wnd.document;var $moduleName, $moduleBase;function __gwtStartLoadingFragment(frag) {var fragFile = 'deferredjs/' + $strongName + '/' + frag + '.cache.js';return __gwtModuleFunction.__startLoadingFragment(fragFile);}function __gwtInstallCode(code) {return __gwtModuleFunction.__installRunAsyncCode(code);}function __gwt_isKnownPropertyValue(propName, propValue) {return __gwtModuleFunction.__gwt_isKnownPropertyValue(propName, propValue);}function __gwt_getMetaProperty(name) {return __gwtModuleFunction.__gwt_getMetaProperty(name);}var $stats = $wnd.__gwtStatsEvent ? function(a) {return $wnd.__gwtStatsEvent && $wnd.__gwtStatsEvent(a);} : null;var $sessionId = $wnd.__gwtStatsSessionId ? $wnd.__gwtStatsSessionId : null;function Lp(){}\nfunction Hp(){}\nfunction ub(){}\nfunction zd(){}\nfunction Gd(){}\nfunction jd(){}\nfunction dc(){}\nfunction nf(){}\nfunction sf(){}\nfunction zf(){}\nfunction Jf(){}\nfunction Of(){}\nfunction Tf(){}\nfunction Yf(){}\nfunction bg(){}\nfunction gg(){}\nfunction mg(){}\nfunction ug(){}\nfunction zg(){}\nfunction Eg(){}\nfunction Jg(){}\nfunction Ng(){}\nfunction ah(){}\nfunction _p(){}\nfunction oq(){}\nfunction qq(){}\nfunction Mq(){}\nfunction Mr(){}\nfunction Kr(){}\nfunction zs(){}\nfunction Bs(){}\nfunction ut(){}\nfunction gu(){}\nfunction vu(){}\nfunction Gx(){}\nfunction Mx(){}\nfunction Yx(){}\nfunction Sz(){}\nfunction XH(){}\nfunction eI(){}\nfunction NJ(){}\nfunction RJ(){}\nfunction FL(){}\nfunction HL(){}\nfunction bM(){}\nfunction dM(){}\nfunction fM(){}\nfunction hM(){}\nfunction jM(){}\nfunction lM(){}\nfunction nM(){}\nfunction pM(){}\nfunction rM(){}\nfunction iO(){}\nfunction EP(){}\nfunction JP(){}\nfunction OP(){}\nfunction cq(a){}\nfunction xu(a){}\nfunction Lz(a){}\nfunction Wz(a){}\nfunction jc(a){ic=a}\nfunction _q(){$q()}\nfunction EO(){AO()}\nfunction zu(){xu(this)}\nfunction Zz(){Wz(this)}\nfunction Ot(){this.a=0}\nfunction Op(a,b){a.a=b}\nfunction gf(a,b){a.a=b}\nfunction ef(a,b){a.d=b}\nfunction hf(a,b){a.b=b}\nfunction Pp(a,b){a.b=b}\nfunction ZB(a,b){a.b=b}\nfunction $B(a,b){a.c=b}\nfunction Xx(a,b){a.c=b}\nfunction Xr(a,b){a.a=b}\nfunction zM(a,b){a.a=b}\nfunction Ib(a,b){a.n=b}\nfunction pQ(a,b){a.e=b}\nfunction uD(a){this.a=a}\nfunction od(a){this.a=a}\nfunction qd(a){this.a=a}\nfunction Xp(a){this.a=a}\nfunction bq(a){this.a=a}\nfunction CB(a){this.a=a}\nfunction zC(a){this.a=a}\nfunction HF(a){this.a=a}\nfunction UF(a){this.d=a}\nfunction dt(a){this.c=a}\nfunction uH(a){this.c=a}\nfunction rx(a){this.b=a}\nfunction kI(a){this.b=a}\nfunction zI(a){this.b=a}\nfunction XI(a){this.c=a}\nfunction gG(a){this.a=a}\nfunction mG(a){this.a=a}\nfunction qG(a){this.a=a}\nfunction vG(a){this.a=a}\nfunction xJ(a){this.a=a}\nfunction BJ(a){this.a=a}\nfunction rL(a){this.a=a}\nfunction RM(a){this.a=a}\nfunction CN(a){this.a=a}\nfunction JN(a){this.a=a}\nfunction JQ(a){this.a=a}\nfunction LQ(a){this.a=a}\nfunction VQ(a){this.a=a}\nfunction XQ(a){this.a=a}\nfunction gO(a){this.a=a}\nfunction MO(a){this.a=a}\nfunction eP(a){this.a=a}\nfunction CP(a){this.a=a}\nfunction DR(a){this.a=a}\nfunction HR(a){this.a=a}\nfunction IR(a){this.a=a}\nfunction KR(a){this.a=a}\nfunction LR(a){this.a=a}\nfunction NR(a){this.a=a}\nfunction OR(a){this.a=a}\nfunction QR(a){this.a=a}\nfunction rg(){this.a={}}\nfunction $G(){KG(this)}\nfunction hK(){tF(this)}\nfunction ac(a){Ib(this,a)}\nfunction Hb(a,b){Ib(a,b)}\nfunction lg(a,b){zQ(b,a)}\nfunction Nt(a,b){a.a=b.a}\nfunction he(b,a){b.src=a}\nfunction rq(b,a){b.set(a)}\nfunction MN(a){return a}\nfunction yO(a){qO();oO=a}\nfunction Az(a){xz(this,a)}\nfunction hc(){this.a=Lc()}\nfunction Ff(){this.c=++Cf}\nfunction IC(){IC=Hp;IC()}\nfunction Vr(){Vr=Hp;we()}\nfunction Js(){Js=Hp;Qs()}\nfunction Wr(){Wr=Hp;new hK}\nfunction JA(){BA();new ZA}\nfunction fC(a){a.a=new uC}\nfunction rC(a){a.b=new zz}\nfunction Bq(a){return true}\nfunction ps(a,b){ie(a.n,b)}\nfunction Jb(a,b){Od(a.n,b)}\nfunction Kb(a,b){Mb(a.n,b)}\nfunction SA(a,b){MG(a.b,b)}\nfunction QN(a,b){MG(a.b,b)}\nfunction RN(a,b){MG(a.d,b)}\nfunction SN(a,b){MG(a.j,b)}\nfunction TN(a,b){MG(a.k,b)}\nfunction $P(a,b){MG(a.b,b)}\nfunction hs(a,b){Rr(a.d,b)}\nfunction JO(a,b){DO(a.a,b)}\nfunction qg(a,b,c){a.a[b]=c}\nfunction vD(a){this.a=Iz(a)}\nfunction th(){this.c=new dL}\nfunction Ey(){this.g=new ZA}\nfunction ZA(){this.b=new $G}\nfunction _B(){this.a=new $G}\nfunction GB(){this.e=new Yw}\nfunction zz(){xz(this,null)}\nfunction It(){Bt();Ct(this)}\nfunction kD(){zc.call(this)}\nfunction ND(){zc.call(this)}\nfunction pD(){zc.call(this)}\nfunction rD(){zc.call(this)}\nfunction CC(){zc.call(this)}\nfunction GC(){zc.call(this)}\nfunction IE(){zc.call(this)}\nfunction XJ(){zc.call(this)}\nfunction JL(){zc.call(this)}\nfunction KB(){GB.call(this)}\nfunction LB(){GB.call(this)}\nfunction WB(){GB.call(this)}\nfunction EC(){CC.call(this)}\nfunction HK(){HK=Hp;GK=JK()}\nfunction nK(){this.a=new hK}\nfunction xM(){this.a=new hK}\nfunction iP(){this.d=new $G}\nfunction ud(a){td();sd.jb(a)}\nfunction rO(a){qO();MG(pO,a)}\nfunction Jq(a){lr();tr(a,kT)}\nfunction Fq(a){return kr(a)}\nfunction kd(a){return a.hb()}\nfunction jN(a){cN(a);return a}\nfunction Cr(a,b){xr(a,b,a.n)}\nfunction Tr(a,b){xr(a,b,a.n)}\nfunction Xs(a,b){Zs(a,b,a.c)}\nfunction ks(a,b){os(a,b,b,-1)}\nfunction GO(a,b){_N(a.a.d,b)}\nfunction HO(a,b){aO(a.a.d,b)}\nfunction LO(a,b){dO(a.a.d,b)}\nfunction Dq(a,b){lr();tr(a,b)}\nfunction DM(a,b){!!b&&(a.c=b)}\nfunction Ju(a){return btoa(a)}\nfunction Ac(a){yc.call(this,a)}\nfunction OD(a){Cc.call(this,a)}\nfunction PD(a){Ac.call(this,a)}\nfunction eh(a){bh.call(this,a)}\nfunction dq(a){cq.call(this,a)}\nfunction Ir(a){eh.call(this,a)}\nfunction Or(a){ac.call(this,a)}\nfunction Gs(a){ac.call(this,a)}\nfunction LH(a){cN(a);this.a=a}\nfunction TH(){TH=Hp;SH=new XH}\nfunction Ec(){Ec=Hp;Dc=new ub}\nfunction _c(){_c=Hp;$c=new jd}\nfunction Vp(){Vp=Hp;Up=new _p}\nfunction $q(){$q=Hp;Zq=new Ff}\nfunction Gu(){Gu=Hp;Fu=new hK}\nfunction dI(){dI=Hp;cI=new eI}\nfunction Eu(){Eu=Hp;GE();Du=FE}\nfunction wC(a){yc.call(this,a)}\nfunction DC(a){Ac.call(this,a)}\nfunction HC(a){Ac.call(this,a)}\nfunction qD(a){Ac.call(this,a)}\nfunction sD(a){Ac.call(this,a)}\nfunction MD(a){Ac.call(this,a)}\nfunction JE(a){Ac.call(this,a)}\nfunction EE(a){DC.call(this,a)}\nfunction FC(a){DC.call(this,a)}\nfunction WD(a){qD.call(this,a)}\nfunction oJ(a){kI.call(this,a)}\nfunction IJ(a){DI.call(this,a)}\nfunction sJ(a){oJ.call(this,a)}\nfunction SM(a){RM.call(this,a)}\nfunction xE(){zC.call(this,'')}\nfunction CE(){zC.call(this,'')}\nfunction KL(){Ac.call(this,UT)}\nfunction Bp(){zp==null&&(zp=[])}\nfunction yI(){throw dp(new IE)}\nfunction WI(){throw dp(new IE)}\nfunction Qc(){Qc=Hp;!!(td(),sd)}\nfunction sN(){sN=Hp;pN={};rN={}}\nfunction UC(a){TC(a);return a.k}\nfunction Qd(a){a=qE(a);return a}\nfunction rh(a,b){a.e=b;return a}\nfunction Mt(a,b){a.a=b<<24>>24}\nfunction Pt(a){this.a=a<<24>>24}\nfunction ID(a){return a<0?-a:a}\nfunction je(a,b){return a.c-b.c}\nfunction pg(a,b){return a.a[b]}\nfunction Dh(a,b){return aD(a,b)}\nfunction JD(a,b){return a>b?a:b}\nfunction KD(a,b){return a0}\nfunction _v(a,b){a.d.e[a.c+a.b]=b}\nfunction $v(a,b){a.d.e[a.c+a.a]=b}\nfunction bw(a,b){a.d.e[a.c+a.e]=b}\nfunction qx(a,b,c){a.b.c[b+a.a]=c}\nfunction uF(a){return a.d.c+a.e.c}\nfunction lK(a,b){return lF(a.a,b)}\nfunction Bc(a,b){rc.call(this,a,b)}\nfunction ir(){Tg.call(this,null)}\nfunction Mz(){Lz(this);this.a=0}\nfunction Nz(){Lz(this);this.a=0}\nfunction ke(a,b){this.b=a;this.c=b}\nfunction xe(a,b){ke.call(this,a,b)}\nfunction Ne(a,b){ke.call(this,a,b)}\nfunction Pe(){Ne.call(this,'PX',0)}\nfunction Re(){Ne.call(this,'EM',2)}\nfunction Se(){Ne.call(this,'EX',3)}\nfunction Te(){Ne.call(this,'PT',4)}\nfunction Ue(){Ne.call(this,'PC',5)}\nfunction Ve(){Ne.call(this,'IN',6)}\nfunction We(){Ne.call(this,'CM',7)}\nfunction Xe(){Ne.call(this,'MM',8)}\nfunction _e(a,b){ke.call(this,a,b)}\nfunction Ah(a,b){ke.call(this,a,b)}\nfunction jp(a,b){return gp(a,b)==0}\nfunction mp(a,b){return gp(a,b)>=0}\nfunction pp(a,b){return gp(a,b)<=0}\nfunction dd(a){return !!a.a||!!a.f}\nfunction LK(){HK();return new GK}\nfunction $x(){$x=Hp;Zx=new uD(-1)}\nfunction zr(){this.f=new at(this)}\nfunction cs(a,b){this.a=a;this.b=b}\nfunction av(a,b){this.a=a;this.b=b}\nfunction cv(a,b){this.b=a;this.a=b}\nfunction Bx(a,b){this.b=a;this.a=b}\nfunction eA(a,b){this.a=a;this.b=b}\nfunction BB(a,b){this.b=a;this.a=b}\nfunction GG(a,b){this.d=a;this.e=b}\nfunction Qy(){this.b=0;this.a=null}\nfunction Rs(a,b){ke.call(this,a,b)}\nfunction jt(a,b){rc.call(this,a,b)}\nfunction gP(a,b){this.a=a;this.b=b}\nfunction mP(a,b){this.i=a;this.e=b}\nfunction oP(a,b){this.a=a;this.b=b}\nfunction qP(a,b){this.a=a;this.b=b}\nfunction HQ(a,b){this.a=a;this.b=b}\nfunction bS(a,b){this.b=a;this.a=b}\nfunction ae(a,b){a.innerText=b||''}\nfunction Od(b,a){b.className=a||''}\nfunction nt(b,a){b.responseType=a}\nfunction ie(b,a){b.selectedIndex=a}\nfunction JM(a,b,c){a.splice(b,0,c)}\nfunction tD(a,b){return wD(a.a,b.a)}\nfunction NK(a,b){return a.a.get(b)}\nfunction nE(a,b){return a.substr(b)}\nfunction dE(a,b){return cN(a),a===b}\nfunction wz(b,a){return b.array[a]}\nfunction Bi(a){return typeof a===jS}\nfunction Ci(a){return typeof a===kS}\nfunction Fi(a){return typeof a===lS}\nfunction np(a){return typeof a===kS}\nfunction Rw(a){return a.ymax-a.ymin}\nfunction Xw(a){return a.xmax-a.xmin}\nfunction FO(a){AO();console.log(a)}\nfunction Yc(a){$wnd.clearTimeout(a)}\nfunction Oq(a){$wnd.clearTimeout(a)}\nfunction xC(){wC.call(this,'UTF-8')}\nfunction Qe(){Ne.call(this,'PCT',1)}\nfunction UM(){RM.call(this,'UTF-8')}\nfunction Zc(){Mc!=0&&(Mc=0);Pc=-1}\nfunction lr(){if(!jr){sr();jr=true}}\nfunction AK(a){this.a=LK();this.b=a}\nfunction QK(a){this.a=LK();this.b=a}\nfunction AE(a,b){a.a+=''+b;return a}\nfunction BE(a,b){a.a+=''+b;return a}\nfunction _b(a,b){a.n['disabled']=!b}\nfunction gc(c,a,b){c.translate(a,b)}\nfunction KE(a,b){return bE(a.a,b.a)}\nfunction fE(a,b){return a.indexOf(b)}\nfunction vE(a){return wE(a,a.length)}\nfunction Hi(a){return a==null?null:a}\nfunction my(a,b){return nA(a.d,b)!=0}\nfunction ih(a){fh(ZS,a);return jh(a)}\nfunction Nq(a){$wnd.clearInterval(a)}\nfunction $E(a){return !a?null:a.wc()}\nfunction Fv(a,b){a.c=b;a.b=sv(a,a.k)}\nfunction lQ(a,b){b.a==a.n&&qQ(a,b.a)}\nfunction Tx(a,b){a.a=a.a+(b<<16>>16)}\nfunction Ux(a,b){a.a=a.a-(b<<16>>16)}\nfunction Wx(a,b){a.b=a.b-(b<<16>>16)}\nfunction Vx(a,b){a.b=a.b+(b<<16>>16)}\nfunction KG(a){a.a=Hh(ym,gS,1,0,5,1)}\nfunction kc(a){a.i=Hh(Am,gS,60,0,0,1)}\nfunction Be(){xe.call(this,'LEFT',2)}\nfunction Vs(){Rs.call(this,'LEFT',2)}\nfunction Ws(){Rs.call(this,'RIGHT',3)}\nfunction Ce(){xe.call(this,'RIGHT',3)}\nfunction Cs(){vs.call(this,$doc.body)}\nfunction uC(){Yw.call(this);rC(this)}\nfunction vB(a){ZA.call(this);this.a=a}\nfunction Tg(a){this.a=new _g;this.b=a}\nfunction Xz(a,b){a.a=b;a.c=0;return a}\nfunction qA(a,b){a.k=b;oA(a);return a}\nfunction Fs(a,b){a.n[zT]=b!=null?b:''}\nfunction ML(a){return a!=null?Ab(a):0}\nfunction Ph(a){return Qh(a.l,a.m,a.h)}\nfunction nD(a){return dE(kS,typeof a)}\nfunction gE(a){return dE(lS,typeof a)}\nfunction LD(a,b){return gp(a,b)<0?a:b}\nfunction lN(a,b){return parseInt(a,b)}\nfunction wD(a,b){return ab?1:0}\nfunction cK(a){return a<10?'0'+a:''+a}\nfunction xz(b,a){b.array=a?a.array:[]}\nfunction XG(a,b){HH(a.a,a.a.length,b)}\nfunction bL(a,b){if(a.a){nL(b);mL(b)}}\nfunction xN(a){if(!a.c)return;a.b=true}\nfunction xQ(a){this.a=a;Mq.call(this)}\nfunction _R(a){this.a=a;Mq.call(this)}\nfunction YA(a){dB(true);a.b.a.length=0}\nfunction dp(a){return a.backingJsObject}\nfunction _D(a,b){return a.charCodeAt(b)}\nfunction kP(a,b){a.a=b;IO(a.i.a,a.e,b)}\nfunction VJ(a,b){var c;c=a[yU];b[yU]=c}\nfunction ze(){xe.call(this,'CENTER',0)}\nfunction Ts(){Rs.call(this,'CENTER',0)}\nfunction cf(){_e.call(this,'HIDDEN',1)}\nfunction Hv(){tv.call(this,3,3,3,true)}\nfunction DE(a){zC.call(this,(cN(a),a))}\nfunction Ae(){xe.call(this,'JUSTIFY',1)}\nfunction bf(){_e.call(this,'VISIBLE',0)}\nfunction WM(a){if(!a){throw dp(new pD)}}\nfunction $M(a){if(!a){throw dp(new GC)}}\nfunction aN(a){if(!a){throw dp(new JL)}}\nfunction gN(a){if(!a){throw dp(new rD)}}\nfunction iN(a){if(!a){throw dp(new kD)}}\nfunction $e(){$e=Hp;Ze=new bf;Ye=new cf}\nfunction sq(a){return new Int16Array(a)}\nfunction tq(a){return new Int32Array(a)}\nfunction wq(a){return new Uint8Array(a)}\nfunction xq(a){return new Uint8Array(a)}\nfunction oN(a){return a.$H||(a.$H=++nN)}\nfunction Zh(a){return a.l+a.m*bT+a.h*cT}\nfunction Qh(a,b,c){return {l:a,m:b,h:c}}\nfunction kN(a,b){return a==b?0:a>1))}\nfunction Hq(a){zq=a;lr();a.setCapture()}\nfunction SI(a){zI.call(this,a);this.a=a}\nfunction DI(a){kI.call(this,a);this.a=a}\nfunction Us(){Rs.call(this,'JUSTIFY',1)}\nfunction Kv(){Kv=Hp;Jv=new Ov(-1,-1,-1)}\nfunction LJ(){LJ=Hp;JJ=new NJ;KJ=new RJ}\nfunction Hr(){Hr=Hp;Fr=new Kr;Gr=new Mr}\nfunction EL(){EL=Hp;CL=new FL;DL=new HL}\nfunction qO(){qO=Hp;nO=new Yw;pO=new $G}\nfunction ex(a,b){a.c=new hu(b);return a}\nfunction IP(a,b,c){a.c=b;a.d=c;return a}\nfunction aw(a,b,c){a.c=(sv(a.d,b)+c)*qv}\nfunction mK(a,b){return sF(a.a,b)!=null}\nfunction hE(a,b){return a.lastIndexOf(b)}\nfunction Ai(a,b){return a!=null&&ui(a,b)}\nfunction Id(b,a){return b.appendChild(a)}\nfunction Jd(b,a){return b.removeChild(a)}\nfunction Ld(b,a){return parseInt(b[a])|0}\nfunction hq(c,a,b){return a.replace(c,b)}\nfunction Su(a,b){return vi(oF(a.e,b),54)}\nfunction ou(a,b){return vi(oF(a.b,b),34)}\nfunction YG(a){return HM(a.a,a.a.length)}\nfunction oL(a){pL.call(this,a,null,null)}\nfunction bQ(a){this.a=a;TP.call(this,a)}\nfunction _g(){this.d=new hK;this.c=false}\nfunction Ig(){Ig=Hp;Hg=new Gf(WS,new Jg)}\nfunction Xf(){Xf=Hp;Wf=new Gf(JS,new Yf)}\nfunction TC(a){if(a.k!=null){return}eD(a)}\nfunction Ic(a){return a==null?null:a.name}\nfunction VN(a){return a.e?a.e.a.length:1}\nfunction oE(a,b,c){return a.substr(b,c-b)}\nfunction vq(c,a,b){return c.subarray(a,b)}\nfunction iv(a,b){return jv(a,qu(a.c,b).b)}\nfunction sv(a,b){return b*a.Sb()+a.border}\nfunction ec(d,a,b,c){d.drawImage(a,b,c)}\nfunction Zr(a,b){Yr(a,(mq(),new iq(b)))}\nfunction Qt(a,b){b-a.a.length>0&&Rt(a,b)}\nfunction lC(a,b){a.b=gC(b);a.c=a.b.buffer}\nfunction ON(a,b){this.order=a;this.data=b}\nfunction zc(){kc(this);mc(this);this.fb()}\nfunction Ny(){Ey.call(this);this.a=new ZA}\nfunction QB(){GB.call(this);this.d=new ZA}\nfunction QE(a){qD.call(this,a==null?rS:a)}\nfunction RE(a){qD.call(this,a==null?rS:a)}\nfunction wO(a){qO();if(lO!=a){lO=a;sO()}}\nfunction xd(a){td();return parseInt(a)||-1}\nfunction LC(a,b){IC();return a==b?0:a?1:-1}\nfunction KC(a){IC();return dE(jS,typeof a)}\nfunction jQ(a){return Ii(a.r/a.s*100+0.5)}\nfunction $O(a){return !a.i?0:a.i.a.length}\nfunction _K(a){tF(a.c);a.b.b=a.b;a.b.a=a.b}\nfunction WJ(a){var b;b=a[yU]|0;a[yU]=b+1}\nfunction Py(a,b){a.b=b;a.a=new Hv;return a}\nfunction yi(a){iN(a==null||Fi(a));return a}\nfunction $J(a){this.a=new $wnd.Date(wp(a))}\nfunction Tt(){this.a=Hh(Ji,GT,11,32,15,1)}\nfunction GD(){GD=Hp;FD=Hh(sm,gS,18,256,0,1)}\nfunction Xq(){Sq&&Pg((!Tq&&(Tq=new ir),Tq))}\nfunction Nv(){Kv();this.f=this.g=this.i=-51}\nfunction mN(b,c,d){try{b[c]=d}catch(a){}}\nfunction cE(a,b,c,d){return vE(d.Ac(a,b,c))}\nfunction iE(a,b,c){return a.lastIndexOf(b,c)}\nfunction Ei(a,b){return a&&b&&a instanceof b}\nfunction Rc(a,b,c){return a.apply(b,c);var d}\nfunction ee(b,a){return b.getElementById(a)}\nfunction Hc(a){return a==null?null:a.message}\nfunction Rg(a,b,c){return Vg(a.a,b,c),new ah}\nfunction Rq(a,b){return $wnd.setTimeout(a,b)}\nfunction ot(){return new $wnd.XMLHttpRequest}\nfunction mf(){mf=Hp;lf=new Gf('blur',new nf)}\nfunction Wd(a,b){a.fireEvent('on'+b.type,b)}\nfunction hd(a,b){a.a=ld(a.a,[b,true]);ed(a)}\nfunction gd(a,b){a.a=ld(a.a,[b,false]);ed(a)}\nfunction Xt(a,b){a.d=b;a.c=0;a.a=mS;return a}\nfunction zG(a,b){var c;c=a.e;a.e=b;return c}\nfunction RG(a,b){return SG(a,b,a.a.length-1)}\nfunction yH(a,b,c){return zH(a,a.length,b,c)}\nfunction fc(e,a,b,c,d){e.fillRect(a,b,c,d)}\nfunction LP(a){KP.call(this,a.a,a.b,a.c,a.d)}\nfunction BC(){Ac.call(this,'divide by zero')}\nfunction xw(){pw();tv.call(this,0,1,2,false)}\nfunction yN(a){hd((_c(),$c),a);return false}\nfunction GR(a,b){Fs(a.a.e.e,b+'%');rR(a.a.e)}\nfunction Ug(a,b){!a.a&&(a.a=new $G);MG(a.a,b)}\nfunction Pg(a){var b;if(Mg){b=new Ng;Sg(a,b)}}\nfunction XM(a,b){if(!a){throw dp(new qD(b))}}\nfunction _M(a,b){if(!a){throw dp(new HC(b))}}\nfunction dB(a){if(!a){throw dp(new FC('0'))}}\nfunction gs(a){this.n=a;this.d=new Sr(this.n)}\nfunction XK(a,b,c){this.a=a;this.b=b;this.c=c}\nfunction st(a,b,c){ke.call(this,a,b);this.a=c}\nfunction pL(a,b,c){this.c=a;GG.call(this,b,c)}\nfunction HH(a,b,c){YM(b,a.length);FH(a,0,b,c)}\nfunction WA(a,b){cB(b,a.b.a.length);TG(a.b,b)}\nfunction KM(a,b,c){IM(c,0,a,b,c.length,false)}\nfunction _d(a,b,c){c?a.add(b,c.index):a.add(b)}\nfunction FN(b,a){b.djvuWorker.postMessage(a)}\nfunction Pw(a){a.xmin=a.xmax=a.ymin=a.ymax=0}\nfunction hy(a,b){a.U[0]=a.U[1]=a.U[2]=b;a.V=0}\nfunction MG(a,b){a.a[a.a.length]=b;return true}\nfunction vi(a,b){iN(a==null||ui(a,b));return a}\nfunction lR(a,b){a.a=b;pQ(b,new HR(a));rR(a.e)}\nfunction QJ(a,b){return cN(b),MC(b,(cN(a),a))}\nfunction MJ(a,b){return cN(a),MC(a,(cN(b),b))}\nfunction JC(a,b){return LC((cN(a),a),(cN(b),b))}\nfunction mD(a,b){return oD((cN(a),a),(cN(b),b))}\nfunction aE(a,b){return kN((cN(a),a),(cN(b),b))}\nfunction AM(a){this.c=a;this.b=(GE(),kp(MM()))}\nfunction Jx(a){a.j=a.e=a.a=null;a.i=a.g=0;Eu()}\nfunction nv(){ev();this.b=new hK;this.c=new su}\nfunction zy(){$x();ly.call(this);this.e=new Ot}\nfunction yf(){yf=Hp;xf=new Gf('click',new zf)}\nfunction rf(){rf=Hp;qf=new Gf('change',new sf)}\nfunction If(){If=Hp;Hf=new Gf('keydown',new Jf)}\nfunction tg(){tg=Hp;sg=new Gf('scroll',new ug)}\nfunction fg(){fg=Hp;eg=new Gf('mouseup',new gg)}\nfunction tp(a,b){return hp(gi(np(a)?vp(a):a,b))}\nfunction Pq(a,b){return cS(function(){a.Bb(b)})}\nfunction LG(a,b,c){eN(b,a.a.length);JM(a.a,b,c)}\nfunction PG(a,b){bN(b,a.a.length);return a.a[b]}\nfunction IH(a,b){bN(b,a.a.length);return a.a[b]}\nfunction vw(a,b,c,d){a.k=c;a.i=d;a.e=b;return a}\nfunction GN(a){!a.border&&(a.border=0);return a}\nfunction Np(a){if(a.b){return a.b}return ZL(),QL}\nfunction rQ(a,b){if(!a.o)return;gQ(a,b*a.s/100)}\nfunction Gv(a,b){if(b!=a.k){a.k=b;a.b=sv(a,a.k)}}\nfunction wA(a,b){a.c=b.c;a.b=b.b;a.d=b.d;a.a=b.a}\nfunction nL(a){a.a.b=a.b;a.b.a=a.a;a.a=a.b=null}\nfunction rR(a){_b(a.b,a.Ec(-1));_b(a.c,a.Ec(1))}\nfunction aH(a){KG(this);KM(this.a,0,a.toArray())}\nfunction wQ(a){$wnd.history.replaceState(a,'',a)}\nfunction ws(a){us();try{Sb(a)}finally{mK(ts,a)}}\nfunction Kz(a){return Ci(a)?Ii((cN(a),a)):a.hc()}\nfunction Jh(a){return Array.isArray(a)&&a.Jc===Lp}\nfunction Wg(a,b,c,d){var e;e=Yg(a,b,c);e.add(d)}\nfunction Fh(a,b,c,d,e,f){return Gh(a,b,c,d,e,0,f)}\nfunction yg(){yg=Hp;xg=new Gf('touchend',new zg)}\nfunction Dg(){Dg=Hp;Cg=new Gf('touchmove',new Eg)}\nfunction ag(){ag=Hp;_f=new Gf('mouseover',new bg)}\nfunction Sf(){Sf=Hp;Rf=new Gf('mousemove',new Tf)}\nfunction Nf(){Nf=Hp;Mf=new Gf('mousedown',new Of)}\nfunction GE(){GE=Hp;FE=new dq(null);new dq(null)}\nfunction us(){us=Hp;rs=new zs;ss=new hK;ts=new nK}\nfunction EM(a){this.b=a;this.d=true;this.a=new $G}\nfunction at(a){this.b=a;this.a=Hh(Rk,gS,20,4,0,1)}\nfunction js(a){gs.call(this,(eE('span',$d(a)),a))}\nfunction lF(a,b){return Fi(b)?pF(a,b):!!xK(a.d,b)}\nfunction MK(a,b){return !(a.a.get(b)===undefined)}\nfunction WN(a,b){return a.e?vi(IH(a.e,b),38):null}\nfunction XN(a,b){return a.f?vi(IH(a.f,b),61):null}\nfunction Di(a){return a!=null&&Gi(a)&&!(a.Jc===Lp)}\nfunction zi(a){return !Array.isArray(a)&&a.Jc===Lp}\nfunction Gi(a){return typeof a===dS||typeof a===iS}\nfunction HD(a,b){return gp(a,b)<0?-1:gp(a,b)>0?1:0}\nfunction ru(a,b){return gA(a.c,vi(UA(a.d,b),34).b)}\nfunction Uq(a){Wq();return Vq(Mg?Mg:(Mg=new Ff),a)}\nfunction dN(a,b){if(a==null){throw dp(new PD(b))}}\nfunction kh(a,b){if(a==null){throw dp(new qD(b))}}\nfunction cB(a,b){if(a<0||a>=b){throw dp(new EC)}}\nfunction XA(a,b,c){cB(c,a.b.a.length);WG(a.b,c,b)}\nfunction ld(a,b){!a&&(a=[]);a[a.length]=b;return a}\nfunction YC(a,b,c){var d;d=XC(a,b);iD(c,d);return d}\nfunction nF(a,b){return Fi(b)?oF(a,b):$E(xK(a.d,b))}\nfunction ai(a,b){return Qh(a.l&b.l,a.m&b.m,a.h&b.h)}\nfunction fi(a,b){return Qh(a.l|b.l,a.m|b.m,a.h|b.h)}\nfunction li(a,b){return Qh(a.l^b.l,a.m^b.m,a.h^b.h)}\nfunction FP(a,b,c,d){GP(a,b,c*a.b,d.width,d.height)}\nfunction VA(a,b,c){cB(c,a.b.a.length+1);LG(a.b,c,b)}\nfunction UJ(a,b){if(b[yU]!=a[yU]){throw dp(new XJ)}}\nfunction cN(a){if(a==null){throw dp(new ND)}return a}\nfunction vN(){if(qN==256){pN=rN;rN={};qN=0}++qN}\nfunction yc(a){kc(this);this.f=a;mc(this);this.fb()}\nfunction uA(a){iA();tA.call(this);this.k=a;oA(this)}\nfunction Ur(){zr.call(this);Hb(this,Vd($doc,'div'))}\nfunction fq(a){dq.call(this,new cq(null));this.a=a}\nfunction Md(b,a){return b[a]==null?null:String(b[a])}\nfunction TA(a,b){return cB(b,a.b.a.length),PG(a.b,b)}\nfunction UA(a,b){cB(b,a.b.a.length);return PG(a.b,b)}\nfunction HM(a,b){var c;c=a.slice(0,b);return Mh(c,a)}\nfunction kK(a,b){var c;c=qF(a.a,b,a);return c==null}\nfunction XC(a,b){var c;c=new VC;c.g=a;c.d=b;return c}\nfunction yE(a,b){a.a+=String.fromCharCode(b);return a}\nfunction Kh(a,b,c){$M(c==null||Ch(a,c));return a[b]=c}\nfunction yy(a,b,c,d){a.c=c;a.d=new uA(b);a.a=d;a.b=0}\nfunction eu(a,b){var c;c=a.c+b;op(c,a.a)&&(a.a=xp(c))}\nfunction $C(a,b){var c;c=XC('',a);c.j=b;c.f=1;return c}\nfunction Ds(a){var b;b=Md(a.n,zT).length;b>0&&Es(a,b)}\nfunction hh(a){fh('decodedURL',a);return encodeURI(a)}\nfunction xp(a){if(np(a)){return a|0}return a.l|a.m<<22}\nfunction Uw(a){return a.xmin>=a.xmax||a.ymin>=a.ymax}\nfunction Xd(a){return Math.round(-a.wheelDelta/40)||0}\nfunction KA(a){return a==null||a.length==0?-1:LA(a,MT)}\nfunction Vq(a,b){return Rg((!Tq&&(Tq=new ir),Tq),a,b)}\nfunction qF(a,b,c){return Fi(b)?rF(a,b,c):yK(a.d,b,c)}\nfunction af(){$e();return Lh(Dh(qj,1),gS,80,0,[Ze,Ye])}\nfunction tt(){rt();return Lh(Dh(Tk,1),gS,106,0,[qt,pt])}\nfunction Qp(){Op(this,new bq(true));Pp(this,(ZL(),QL))}\nfunction Sp(){Op(this,new bq(false));Pp(this,(ZL(),QL))}\nfunction su(){this.b=new hK;this.a=new ZA;this.d=new ZA}\nfunction yL(a){this.c=a;this.b=a.a.b.a;VJ(a.a.c,this)}\nfunction Yw(){this.xmin=this.xmax=this.ymin=this.ymax=0}\nfunction XD(a,b,c){this.a=hS;this.d=a;this.b=b;this.c=c}\nfunction Yt(a,b){a.d=Yz(new Zz,b);a.c=0;a.a=mS;return a}\nfunction fv(a){var b;b=a.a;!b&&(a.a=b=new _B);return b}\nfunction wK(a,b){var c;c=a.a.get(b);return c==null?[]:c}\nfunction LL(a,b){return Hi(a)===Hi(b)||a!=null&&wb(a,b)}\nfunction pc(a,b){a.backingJsObject=b;b!=null&&mN(b,nS,a)}\nfunction Yp(a){a.a=wM(yM(),'');a.a.d=false;$p();Zp(a.a)}\nfunction vs(a){zr.call(this);this.n=a,undefined;Qb(this)}\nfunction Ov(a,b,c){Kv();this.Xb(a);this.Yb(b);this.Zb(c)}\nfunction $z(a){Wz(this);this.a=a.a;this.c=a.c;this.b=a.b}\nfunction xA(a,b,c,d){this.c=a;this.b=b;this.d=c;this.a=d}\nfunction xr(a,b,c){Tb(b);Xs(a.f,b);Id(c,Cq(b.n));Vb(b,a)}\nfunction Lv(a,b){$v(a,b.Tb());_v(a,b.Ub());bw(a,b.Vb())}\nfunction pF(a,b){return b==null?!!xK(a.d,null):MK(a.e,b)}\nfunction rE(a){return String.fromCharCode.apply(null,a)}\nfunction PC(a){return /\\d/.test(String.fromCharCode(a))}\nfunction Cq(a){return a.__gwt_resolve?a.__gwt_resolve():a}\nfunction WH(a){TH();return Ai(a,82)?new IJ(a):new DI(a)}\nfunction Bh(){zh();return Lh(Dh(Vj,1),gS,89,0,[yh,xh,wh])}\nfunction mC(){eC();fC(this);lC(this,Hh(Ji,GT,11,0,15,1))}\nfunction KP(a,b,c,d){this.a=a;this.b=b;this.c=c;this.d=d}\nfunction vt(a,b,c){this.a=a;this.d=b;this.c=null;this.b=c}\nfunction xK(a,b){return vK(a,b,wK(a,b==null?0:a.b.sc(b)))}\nfunction AH(a,b){ZM(b);return BH(a,Hh(Ji,GT,11,b,15,1),b)}\nfunction Wc(a){$wnd.setTimeout(function(){throw a},0)}\nfunction Hz(a){return dE(kS,typeof a)||a instanceof Number}\nfunction HA(a){switch(a){case 4:case 2:case 5:return;}}\nfunction EA(a){switch(a){case 1:case 2:case 3:return;}}\nfunction xi(a){iN(a==null||Gi(a)&&!(a.Jc===Lp));return a}\nfunction gv(a,b){var c,d;c=qu(a.c,b).b;d=hv(a,c);return d}\nfunction Qr(a){var b;b=a.c?Sd(a.a):a.a;return b.innerText}\nfunction qc(a,b){var c;c=UC(a.Hc);return b==null?c:c+': '+b}\nfunction oF(a,b){return b==null?$E(xK(a.d,null)):NK(a.e,b)}\nfunction bE(a,b){return aE(a.toLowerCase(),b.toLowerCase())}\nfunction fp(a,b){return hp(ai(np(a)?vp(a):a,np(b)?vp(b):b))}\nfunction sp(a,b){return hp(fi(np(a)?vp(a):a,np(b)?vp(b):b))}\nfunction yp(a,b){return hp(li(np(a)?vp(a):a,np(b)?vp(b):b))}\nfunction hN(a,b){if(a>b||a<0){throw dp(new EE(yS+a+zS+b))}}\nfunction Yr(a,b){!!a.a&&(a.n[wT]='',undefined);he(a.n,b.a)}\nfunction es(a,b){!!a.a&&(a.n[wT]='',undefined);he(a.n,b.a)}\nfunction FR(a,b){Fs(a.a.b.e,b+1+'');ps(a.a.b.d,b);rR(a.a.b)}\nfunction Ly(a){a.d=a.b=0;YA(a.a);Dy(a,null,false);YA(a.g)}\nfunction CK(a){this.e=a;this.b=this.e.a.entries();this.a=[]}\nfunction xs(){us();try{Jr(ts,rs)}finally{tF(ts.a);tF(ss)}}\nfunction Qs(){Qs=Hp;Ms=new Ts;Ns=new Us;Os=new Vs;Ps=new Ws}\nfunction we(){we=Hp;se=new ze;te=new Ae;ue=new Be;ve=new Ce}\nfunction kg(){kg=Hp;jg=new Gf(US,new mg);new Gf(VS,new mg)}\nfunction td(){td=Hp;var a,b;b=!yd();a=new Gd;sd=b?new zd:a}\nfunction Jy(a,b,c){var d;Ly(a);d=new zy;yy(d,b,c,a);return d}\nfunction Zp(a){var b,c;b=new Qp;MG(a.a,b);c=new Sp;MG(a.a,c)}\nfunction mL(a){var b;b=a.c.b.b;a.b=b;a.a=a.c.b;b.a=a.c.b.b=a}\nfunction vO(a){qO();a.xmin=a.xmax=a.ymin=a.ymax=0;Vw(a,a,nO)}\nfunction Ii(a){return Math.max(Math.min(a,mS),-2147483648)|0}\nfunction UQ(a,b){return wp(kp($wnd.Math.round((a+b/2)/b)))*b}\nfunction UE(a,b){return b===a?'(this Map)':b==null?rS:Kp(b)}\nfunction rF(a,b,c){return b==null?yK(a.d,null,c):OK(a.e,b,c)}\nfunction VG(a,b,c){var d;fN(b,c,a.a.length);d=c-b;LM(a.a,b,d)}\nfunction fu(a,b){var c;c=a.d.Ob(b);a.c=xp(ep(a.c,c));return c}\nfunction ZO(a,b){var c;c=vi(PG(a.i,b),51);return c.b?c.d:null}\nfunction aD(a,b){var c=a.a=a.a||[];return c[b]||(c[b]=a.kc(b))}\nfunction PN(a,b){ON.call(this,'context-init',a);this.data2=b}\nfunction rc(a,b){kc(this);this.e=b;this.f=a;mc(this);this.fb()}\nfunction lh(a,b){if(a==null||a.length==0){throw dp(new qD(b))}}\nfunction qu(a,b){return b=a.n.options.length){throw dp(new CC)}}\nfunction uQ(a){if(!a.o)return;gQ(a,(null.Kc()-a.p*2)/a.o.width)}\nfunction YJ(a,b){return HD(kp(a.a.getTime()),kp(b.a.getTime()))}\nfunction YF(a,b){this.a=a;UF.call(this,a);eN(b,a.size());this.b=b}\nfunction aG(a,b,c){fN(b,c,a.size());this.c=a;this.a=b;this.b=c-b}\nfunction TF(a){gN(a.c!=-1);a.d.removeAtIndex(a.c);a.b=a.c;a.c=-1}\nfunction Ct(a){a.c=Hh(al,IT,29,300,0,1);a.g=Hh(Ji,GT,11,1,15,1)}\nfunction PQ(a,b){var c;c=WN(a.a.d,b);aR(OQ(a,b),c.width,c.height)}\nfunction kQ(a,b,c){var d;kR(b.j,c.a);d=JD(0,KD(c.a-1,a.n));qQ(a,d)}\nfunction CM(a,b,c){var d;ZL();d=new AM(b);d.d=c;zM(d,a.b);BM(a,d)}\nfunction kE(a,b,c){c=uE(c);return a.replace(new RegExp(b,'g'),c)}\nfunction GF(a,b){if(Ai(b,22)){return SE(a.a,vi(b,22))}return false}\nfunction qL(a,b){if(Ai(b,22)){return SE(a.a,vi(b,22))}return false}\nfunction fh(a,b){if(null==b){throw dp(new PD(a+' cannot be null'))}}\nfunction iq(a){if(a==null){throw dp(new PD('uri is null'))}this.a=a}\nfunction ZM(a){if(a<0){throw dp(new MD('Negative array size: '+a))}}\nfunction IA(a){switch(a){case -4:case -3:case -2:case -1:return;}}\nfunction tc(b){if(!('stack' in b)){try{throw b}catch(a){}}return b}\nfunction jC(a,b){var c;c=Wt(b);if(c){return kC(a,c)}hC(a,b);return a}\nfunction _s(a,b){var c;c=Ys(a,b);if(c==-1){throw dp(new JL)}$s(a,c)}\nfunction rJ(a,b){var c;for(c=0;c>8]:a.j[255&b]+8}\nfunction sF(a,b){return Fi(b)?b==null?zK(a.d,null):PK(a.e,b):zK(a.d,b)}\nfunction Kq(a){if(!a.d){return}++a.b;a.c?Nq(a.d.a):Oq(a.d.a);a.d=null}\nfunction NL(a,b){!a.a?(a.a=new DE(a.d)):BE(a.a,a.b);AE(a.a,b);return a}\nfunction WG(a,b,c){var d;d=(bN(b,a.a.length),a.a[b]);a.a[b]=c;return d}\nfunction SG(a,b,c){for(;c>=0;--c){if(LL(b,a.a[c])){return c}}return -1}\nfunction ny(a,b,c){var d;Mt(a.e,b[c]);d=nA(a.d,a.e);b[c]=a.e.a;return d}\nfunction TG(a,b){var c;c=(bN(b,a.a.length),a.a[b]);LM(a.a,b,1);return c}\nfunction Oh(a){var b,c,d;b=a&$S;c=a>>22&$S;d=a<0?_S:0;return Qh(b,c,d)}\nfunction jh(a){var b=/%20/g;return encodeURIComponent(a).replace(b,'+')}\n", +"function Lc(){if(Date.now){return Date.now()}return (new Date).getTime()}\nfunction Tc(b){Qc();return function(){return Uc(b,this,arguments);var a}}\nfunction SK(a){this.d=a;this.b=this.d.a.entries();this.a=this.b.next()}\nfunction zR(a){this.a=a;sR.call(this,'buttonPagePrev','buttonPageNext')}\nfunction mc(a){if(a.k){a.backingJsObject!==oS&&a.fb();a.i=null}return a}\nfunction fx(a){var b;if(!dx(a)){throw dp(new KL)}b=a.d;a.d=null;return b}\nfunction Td(a){var b=a.parentNode;(!b||b.nodeType!=1)&&(b=null);return b}\nfunction gh(a){var b=/\\+/g;return decodeURIComponent(a.replace(b,'%20'))}\nfunction Wp(){var a;Yp(Up);if(!ic){a=FM((TC(_j),_j.k));jc(new Xp(a))}}\nfunction Mp(){$wnd.setTimeout(cS(it));Eq();Vp();Wp();BO(new EO)}\nfunction oQ(a){if(!a.j)return;!a.k&&(a.k=new xQ(a));Kq(a.k);Lq(a.k,500)}\nfunction MM(){if(Date.now){return Date.now()}return (new Date).getTime()}\nfunction _G(a){KG(this);XM(a>=0,'Initial capacity must not be negative')}\nfunction is(){gs.call(this,Vd($doc,'div'));this.n.className='gwt-Label'}\nfunction OL(a,b){this.b=', ';this.d=a;this.e=b;this.c=this.d+(''+this.e)}\nfunction Zw(a,b,c,d){this.xmin=a;this.ymin=b;this.xmax=a+c;this.ymax=b+d}\nfunction hx(){cx();this.a=Hh(Ji,GT,11,4,15,1);this.b=Hh(Ji,GT,11,4,15,1)}\nfunction xO(a,b){qO();if(!Qw(nO,a)||mO!=b){Pw(nO);Vw(nO,nO,a);mO=b;sO()}}\nfunction JH(a,b,c){var d;d=(bN(b,a.a.length),a.a[b]);Kh(a.a,b,c);return d}\nfunction XO(a,b){var c;c=vi(oF(a.d,b),69);!c&&rF(a.d,b,c=new iP);return c}\nfunction $t(a){var b;if(a.c>=a.a)return -1;b=a.d.Lb();b>=0&&++a.c;return b}\nfunction xL(a){UJ(a.c.a.c,a);aN(a.b!=a.c.a.b);a.a=a.b;a.b=a.b.a;return a.a}\nfunction _N(a,b){var c,d;for(d=b.Db();d.Gb();){c=vi(d.Hb(),41);sF(a.o,c)}}\nfunction Vc(a){a&&bd((_c(),$c));--Mc;if(a){if(Pc!=-1){Yc(Pc);Pc=-1}}}\nfunction de(a,b){a.currentStyle.direction=='rtl'&&(b=-b);a.scrollLeft=b}\nfunction Dr(a){a.style['left']='';a.style['top']='';a.style['position']=''}\nfunction CO(){!cc&&(cc=new dc);throw dp(new Ac('Canvas not supported!'))}\nfunction eN(a,b){if(a<0||a>b){throw dp(new DC('Index: '+a+', Size: '+b))}}\nfunction bN(a,b){if(a<0||a>=b){throw dp(new DC('Index: '+a+', Size: '+b))}}\nfunction $N(a,b){if(kT==kr(b.type)){null.Kc().Kc();Jd((us(),ys(null)).n,a)}}\nfunction sP(a,b){if(b.b==12)return vi(nF(a.g,b),70);return vi(nF(a.a,b),70)}\nfunction fR(a){a.c.c==null&&(a.c.c=dR(a.n));null.Kc();return null.Kc().Kc()}\nfunction Yq(){var a;if(Sq){a=new _q;!!Tq&&Sg(Tq,a);return null}return null}\nfunction yM(){var a;if(!uM){uM=new xM;a=new EM('');ZL();vM(uM,a)}return uM}\nfunction Ys(a,b){var c;for(c=0;c=0?a.e[b*qv+3]:0;return (c*(a.a-1)+(a.a-2))/255|0}\nfunction cL(a,b){var c;c=vi(sF(a.c,b),73);if(c){nL(c);return c.e}return null}\nfunction rp(a){var b;if(np(a)){b=0-a;if(!isNaN(b)){return b}}return hp(ei(a))}\nfunction au(a){var b,c;c=$t(a);if(c<0){return c}b=$t(a);return b>=0?c<<8|b:-1}\nfunction bu(a){var b,c;c=au(a);if(c<0){return c}b=$t(a);return b>=0?c<<8|b:-1}\nfunction du(a,b){var c,d;c=cu(Vt(a,b));d=a.d.Ob(b);a.c=xp(ep(a.c,d));return c}\nfunction Yz(a,b){a.a=YO(Vz,b,null);!a.a&&YO(Vz,b,new eA(a,b));a.c=0;return a}\nfunction rv(a,b,c){a.e=wq(b*c*qv);a.f=a.e.buffer;a.dataWidth=b;a.dataHeight=c}\nfunction iR(a){var b;b=a.b.d.n.selectedIndex;!!a.a&&qQ(a.a,b);a.b.d.n.blur()}\nfunction ct(a){if(a.b>=a.c.c){throw dp(new JL)}a.a=a.c.a[a.b];++a.b;return a.a}\nfunction WK(a){if(a.a.d!=a.c){return NK(a.a,a.b.value[0])}return a.b.value[1]}\nfunction QG(a,b,c){for(;c0?(cE(a,0,a.length,(QM(),PM))+eU).substr(0,4):eU}\nfunction Eh(a){return a.__elementTypeCategory$==null?10:a.__elementTypeCategory$}\nfunction $p(){var a,b;b=hr('logLevel');a=b==null?null:_L(b);if(a);else{ZL()}}\nfunction gC(a){var b,c;c=wq(a.length);for(b=0;b0&&(a.i.n=true);KO(a.i.a,a.e,b)}\nfunction ki(a){if(bi(a,(qi(),pi))<0){return -Zh(ei(a))}return a.l+a.m*bT+a.h*cT}\nfunction qi(){qi=Hp;mi=Qh($S,$S,524287);ni=Qh(0,0,aT);oi=Oh(1);Oh(2);pi=Oh(0)}\nfunction zh(){zh=Hp;yh=new Ah('RTL',0);xh=new Ah('LTR',1);wh=new Ah('DEFAULT',2)}\nfunction QM(){QM=Hp;PM=new UM;OM=new SM('ISO-LATIN-1');NM=new SM('ISO-8859-1')}\nfunction Wt(a){var b;b=null;(a.b==null||a.b.length!=4)&&(b=ex(new hx,a));return b}\nfunction Sd(a){var b=a.firstChild;while(b&&b.nodeType!=1)b=b.nextSibling;return b}\nfunction FB(a){switch(a){case 1:case 2:case 3:case 4:case 5:case 6:return;}}\nfunction qs(){ac.call(this,Vd($doc,'select'));this.n.className='gwt-ListBox'}\nfunction Ks(){var a;Js();Ls.call(this,(a=$doc.createElement('INPUT'),a.type=AT,a))}\nfunction sO(){var a,b;for(b=new uH(pO);b.a=a.border||b=14&&b<=16)));return a}\nfunction BP(a){var b;b=Ii($wnd.Math.floor(1/a));b=1>(12>24}\nfunction MB(a,b,c){var d;d=Lh(Dh(Li,1),KT,11,15,[b,c]);SA(a.d,d);return a.d.b.a.length}\nfunction Gt(a,b){var c;a.i=qA(new tA,b);for(c=0;c>24}}\nfunction rt(){rt=Hp;qt=new st('Default',0,'');pt=new st('ArrayBuffer',1,'arraybuffer')}\nfunction px(){mx();this.c=new Int16Array(nT);this.b=new Int8Array(64);this.a=new rx(this)}\nfunction dL(){tF(this);this.b=new oL(this);this.c=new hK;this.b.b=this.b;this.b.a=this.b}\nfunction cw(a,b){Kv();Nv.call(this);this.d=a;this.c=b*qv;this.a=a.d;this.b=a.g;this.e=a.o}\nfunction Ub(a,b){a.g&&(a.n.__listener=null,undefined);!!a.n&&Gb(a.n,b);a.n=b;a.g&&nr(a.n,a)}\nfunction GA(a,b){b=qE(b);if(b.length==0){a.a=null}else if(!dE(b,a.a)){a.a=b;CA(new xB(a.a))}}\nfunction yC(a,b){var c;c=a.a.length;bc&&(a.a+=vE(Hh(Ki,GT,11,b-c,15,1)))}\nfunction HP(a,b,c,d){var e,f;f=(d.width+a.b-1)/a.b|0;e=(d.height+a.b-1)/a.b|0;GP(a,b,c,f,e)}\nfunction Et(a,b,c){var d,e,f;f=1;e=1<>22);e=a.h+b.h+(d>>22);return Qh(c&$S,d&$S,e&_S)}\nfunction ji(a,b){var c,d,e;c=a.l-b.l;d=a.m-b.m+(c>>22);e=a.h-b.h+(d>>22);return Qh(c&$S,d&$S,e&_S)}\nfunction fz(a,b){var c,d;for(c=0,d=a.size();cb){return 1}if(a==b){return 0}return isNaN(a)?isNaN(b)?0:1:-1}\nfunction NC(a){if(dE(typeof a,lS)){return true}return a!=null&&a.$implements__java_lang_CharSequence}\nfunction Lh(a,b,c,d,e){e.Hc=a;e.Ic=b;e.Jc=Lp;e.__elementTypeId$=c;e.__elementTypeCategory$=d;return e}\nfunction Zv(a,b,c,d){a.d.e[a.c+a.a]=b<<24>>24;a.d.e[a.c+a.b]=c<<24>>24;a.d.e[a.c+a.e]=d<<24>>24}\nfunction fQ(a,b,c,d){if(b>=0&&b0&&(a.c=mS);d<0?(a.d=0):d>0&&(a.d=mS);qQ(a,b)}}\nfunction ky(a,b,c){var d;d=a.T.b.a.length;if(d<=b){while(d++a){throw dp(new qD('fromIndex: 0 > toIndex: '+a))}if(a>b){throw dp(new FC(yS+a+zS+b))}}\nfunction Dv(a,b){if(b<2||b>256){throw dp(new qD('(GBitmap::set_grays) Illegal number of gray levels'))}a.a=b}\nfunction St(a,b,c){if(0>b.length||c<0||c-b.length>0){throw dp(new CC)}Qt(a,a.b+c);HE(b,0,a.a,a.b,c);a.b+=c}\nfunction Th(a,b,c,d,e){var f;f=hi(a,b);c&&Wh(f);if(e){a=Vh(a,b);d?(Nh=ei(a)):(Nh=Qh(a.l,a.m,a.h))}return f}\nfunction _t(a,b){var c;if(b.length==0)return 0;c=a.d.Mb(b);c=KD(c,a.a-a.c);if(c>0){a.c+=c;return c}return -1}\nfunction wE(a,b){var c,d,e;hN(b,a.length);e='';for(d=0;d=0&&(a.n.style[nU]=b+'px',undefined);c>=0&&(a.n.style[SU]=c+'px',undefined)}\nfunction $s(a,b){var c;if(b<0||b>=a.c){throw dp(new CC)}--a.c;for(c=b;c0.999&&b<1.001){return}c=zw(b);for(d=0;d>24}}\nfunction ED(a){var b,c;if(a>-129&&a<128){b=a+128;c=(GD(),FD)[b];!c&&(c=FD[b]=new uD(a));return c}return new uD(a)}\nfunction By(a){var b,c,d;d=0;for(c=new uH(a.g.b);c.a=a.f){c=vi(TA(a.g,b-a.f),71)}else if(a.e){c=Cy(a.e,b)}else{throw dp(new sD(iU))}return c}\nfunction Ev(a,b){var c;if(a.border>>0).toString(16)}return a.toString()}\nfunction Pr(){Or.call(this,$doc.createElement(\" - -
-
-
-
+{{ delete_confirm_modal() }} {% endif %} {% endblock %} {% block js %} diff --git a/cps/templates/layout.html b/cps/templates/layout.html index 3b89a7ce..643459cd 100644 --- a/cps/templates/layout.html +++ b/cps/templates/layout.html @@ -1,4 +1,4 @@ -{% from 'modal_dialogs.html' import restrict_modal, delete_book, filechooser_modal %} +{% from 'modal_dialogs.html' import restrict_modal, delete_book, filechooser_modal, delete_confirm_modal %} @@ -189,8 +189,6 @@
{% block modal %}{% endblock %} - - @@ -200,14 +198,7 @@ - - {% if g.current_theme == 1 %} - - - - - {% endif %} + + {% if g.current_theme == 1 %} + + + + + {% endif %} {% block js %}{% endblock %} diff --git a/cps/templates/modal_dialogs.html b/cps/templates/modal_dialogs.html index 038681b4..da83649a 100644 --- a/cps/templates/modal_dialogs.html +++ b/cps/templates/modal_dialogs.html @@ -37,7 +37,7 @@
{% endmacro %} -{% macro delete_book(bookid) %} +{% macro delete_book() %} {% if g.user.role_delete_books() %} {% endmacro %} + +{% macro delete_confirm_modal() %} + + +{% endmacro %} diff --git a/cps/templates/shelf.html b/cps/templates/shelf.html index f7e3c1ae..dab42d2f 100644 --- a/cps/templates/shelf.html +++ b/cps/templates/shelf.html @@ -7,7 +7,8 @@ {% endif %} {% if g.user.is_authenticated %} {% if (g.user.role_edit_shelfs() and shelf.is_public ) or not shelf.is_public %} -
{{ _('Delete this Shelf') }}
+ +
{{ _('Delete this Shelf') }}
{{ _('Edit Shelf') }} {% if entries.__len__() %}
- @@ -125,19 +125,15 @@ {% endif %} {% endif %} - {% if g.user and g.user.role_admin() and not profile and not new_user and not content.role_anonymous() %} -
- -
- {% endif %}
- +
{{_('Save')}}
{% if not profile %} {{_('Cancel')}} {% endif %} + {% if g.user and g.user.role_admin() and not profile and not new_user and not content.role_anonymous() %} +
{{_('Delete User')}}
+ {% endif %}
@@ -157,23 +153,10 @@ - - {% endblock %} {% block modal %} {{ restrict_modal() }} +{{ delete_confirm_modal() }} {% endblock %} {% block js %} From 2bea447de5d5eac3cab7a6e8e993534f9eefe632 Mon Sep 17 00:00:00 2001 From: Ozzieisaacs Date: Wed, 23 Dec 2020 09:07:49 +0100 Subject: [PATCH 052/255] Fix show archived books --- cps/templates/shelf.html | 1 - cps/web.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/cps/templates/shelf.html b/cps/templates/shelf.html index dab42d2f..32e3da4f 100644 --- a/cps/templates/shelf.html +++ b/cps/templates/shelf.html @@ -7,7 +7,6 @@ {% endif %} {% if g.user.is_authenticated %} {% if (g.user.role_edit_shelfs() and shelf.is_public ) or not shelf.is_public %} -
{{ _('Delete this Shelf') }}
{{ _('Edit Shelf') }} {% if entries.__len__() %} diff --git a/cps/web.py b/cps/web.py index 4baf82cb..10eb11f3 100644 --- a/cps/web.py +++ b/cps/web.py @@ -421,7 +421,7 @@ def render_books_list(data, sort, book_id, page): elif data == "language": return render_language_books(page, book_id, order) elif data == "archived": - return render_archived_books(page, book_id, order) + return render_archived_books(page, order) elif data == "search": term = (request.args.get('query') or '') offset = int(int(config.config_books_per_page) * (page - 1)) From abf0f4d699d77e9d84c1f52452395098f6012d8d Mon Sep 17 00:00:00 2001 From: OzzieIsaacs Date: Tue, 22 Dec 2020 17:50:07 +0100 Subject: [PATCH 053/255] Updated Testresult Fixed delete book call --- cps/templates/book_table.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cps/templates/book_table.html b/cps/templates/book_table.html index 067ff5e0..ecd840b5 100644 --- a/cps/templates/book_table.html +++ b/cps/templates/book_table.html @@ -61,7 +61,7 @@ {% endblock %} {% block modal %} -{{ delete_book(0) }} +{{ delete_book() }} {% if g.user.role_edit() %} - + {{_('Back')}} {% endblock %} diff --git a/cps/templates/shelfdown.html b/cps/templates/shelfdown.html index 9ec154be..77251e02 100644 --- a/cps/templates/shelfdown.html +++ b/cps/templates/shelfdown.html @@ -55,27 +55,14 @@
- {% if g.user.role_download() %} + {% if g.user.role_download() %} {% if entry.data|length %}
- {% if entry.data|length < 2 %} - - {% for format in entry.data %} - - {{format.format}} ({{ format.uncompressed_size|filesizeformat }}) - - {% endfor %} - {% else %} - - - {% endif %} + {% for format in entry.data %} + + {{format.format}} ({{ format.uncompressed_size|filesizeformat }}) + + {% endfor %}
{% endif %} {% endif %} diff --git a/cps/ub.py b/cps/ub.py index dbc3b419..f11b77b9 100644 --- a/cps/ub.py +++ b/cps/ub.py @@ -452,7 +452,7 @@ def migrate_Database(session): if not engine.dialect.has_table(engine.connect(), "archived_book"): ArchivedBook.__table__.create(bind=engine) if not engine.dialect.has_table(engine.connect(), "registration"): - ReadBook.__table__.create(bind=engine) + Registration.__table__.create(bind=engine) with engine.connect() as conn: conn.execute("insert into registration (domain, allow) values('%.%',1)") session.commit() @@ -501,12 +501,16 @@ def migrate_Database(session): for book_shelf in session.query(BookShelf).all(): book_shelf.date_added = datetime.datetime.now() session.commit() - # Handle table exists, but no content - cnt = session.query(Registration).count() - if not cnt: - with engine.connect() as conn: - conn.execute("insert into registration (domain, allow) values('%.%',1)") - session.commit() + try: + # Handle table exists, but no content + cnt = session.query(Registration).count() + if not cnt: + with engine.connect() as conn: + conn.execute("insert into registration (domain, allow) values('%.%',1)") + session.commit() + except exc.OperationalError: # Database is not writeable + print('Settings database is not writeable. Exiting...') + sys.exit(2) try: session.query(exists().where(BookShelf.order)).scalar() except exc.OperationalError: # Database is not compatible, some columns are missing @@ -591,7 +595,7 @@ def migrate_Database(session): session.commit() except exc.OperationalError: print('Settings database is not writeable. Exiting...') - sys.exit(1) + sys.exit(2) def clean_database(session): From 2a63c357436b9494db225bc41166ab1d8326f46c Mon Sep 17 00:00:00 2001 From: Ozzieisaacs Date: Sun, 27 Dec 2020 11:27:15 +0100 Subject: [PATCH 056/255] Activate serverside filepicker with parameter in unconfigured state --- cps/admin.py | 44 ++++++++++++++++++++-------------- cps/cli.py | 4 ++++ cps/templates/config_edit.html | 9 ++++++- 3 files changed, 38 insertions(+), 19 deletions(-) diff --git a/cps/admin.py b/cps/admin.py index 5831234f..9c016e5b 100644 --- a/cps/admin.py +++ b/cps/admin.py @@ -39,6 +39,7 @@ from sqlalchemy.exc import IntegrityError, OperationalError, InvalidRequestError from sqlalchemy.sql.expression import func, or_ from . import constants, logger, helper, services +from .cli import filepicker from . import db, calibre_db, ub, web_server, get_locale, config, updater_thread, babel, gdriveutils from .helper import check_valid_domain, send_test_mail, reset_password, generate_password_hash from .gdriveutils import is_gdrive_ready, gdrive_support @@ -118,7 +119,7 @@ def before_request(): g.shelves_access = ub.session.query(ub.Shelf).filter( or_(ub.Shelf.is_public == 1, ub.Shelf.user_id == current_user.id)).order_by(ub.Shelf.name).all() if not config.db_configured and request.endpoint not in ( - 'admin.basic_configuration', 'login') and '/static/' not in request.path: + 'admin.basic_configuration', 'login', 'admin.config_pathchooser') and '/static/' not in request.path: return redirect(url_for('admin.basic_configuration')) @@ -192,7 +193,7 @@ def admin(): @admin_required def configuration(): if request.method == "POST": - return _configuration_update_helper() + return _configuration_update_helper(True) return _configuration_result() @@ -587,10 +588,11 @@ def list_restriction(res_type): return response @admi.route("/basicconfig/pathchooser/") -# @unconfigured -@login_required +@unconfigured def config_pathchooser(): - return pathchooser() + if filepicker: + return pathchooser() + abort(403) @admi.route("/ajax/pathchooser/") @login_required @@ -599,7 +601,7 @@ def ajax_pathchooser(): return pathchooser() def pathchooser(): - browse_for = "folder" # if request.endpoint == "admin.pathchooser" else "file" + browse_for = "folder" folder_only = request.args.get('folder', False) == "true" file_filter = request.args.get('filter', "") path = os.path.normpath(request.args.get('path', "")) @@ -685,8 +687,8 @@ def pathchooser(): def basic_configuration(): logout_user() if request.method == "POST": - return _configuration_update_helper() - return _configuration_result() + return _configuration_update_helper(configured=filepicker) + return _configuration_result(configured=filepicker) def _config_int(to_save, x, func=int): @@ -841,7 +843,7 @@ def _configuration_ldap_helper(to_save, gdriveError): return reboot_required, None -def _configuration_update_helper(): +def _configuration_update_helper(configured): reboot_required = False db_change = False to_save = request.form.to_dict() @@ -861,11 +863,15 @@ def _configuration_update_helper(): reboot_required |= _config_string(to_save, "config_keyfile") if config.config_keyfile and not os.path.isfile(config.config_keyfile): - return _configuration_result(_('Keyfile Location is not Valid, Please Enter Correct Path'), gdriveError) + return _configuration_result(_('Keyfile Location is not Valid, Please Enter Correct Path'), + gdriveError, + configured) reboot_required |= _config_string(to_save, "config_certfile") if config.config_certfile and not os.path.isfile(config.config_certfile): - return _configuration_result(_('Certfile Location is not Valid, Please Enter Correct Path'), gdriveError) + return _configuration_result(_('Certfile Location is not Valid, Please Enter Correct Path'), + gdriveError, + configured) _config_checkbox_int(to_save, "config_uploading") # Reboot on config_anonbrowse with enabled ldap, as decoraters are changed in this case @@ -930,10 +936,10 @@ def _configuration_update_helper(): if "config_rarfile_location" in to_save: unrar_status = helper.check_unrar(config.config_rarfile_location) if unrar_status: - return _configuration_result(unrar_status, gdriveError) + return _configuration_result(unrar_status, gdriveError, configured) except (OperationalError, InvalidRequestError): ub.session.rollback() - _configuration_result(_(u"Settings DB is not Writeable"), gdriveError) + _configuration_result(_(u"Settings DB is not Writeable"), gdriveError, configured) try: metadata_db = os.path.join(config.config_calibre_dir, "metadata.db") @@ -941,11 +947,13 @@ def _configuration_update_helper(): gdriveutils.downloadFile(None, "metadata.db", metadata_db) db_change = True except Exception as e: - return _configuration_result('%s' % e, gdriveError) + return _configuration_result('%s' % e, gdriveError, configured) if db_change: if not calibre_db.setup_db(config, ub.app_DB_path): - return _configuration_result(_('DB Location is not Valid, Please Enter Correct Path'), gdriveError) + return _configuration_result(_('DB Location is not Valid, Please Enter Correct Path'), + gdriveError, + configured) if not os.access(os.path.join(config.config_calibre_dir, "metadata.db"), os.W_OK): flash(_(u"DB is not Writeable"), category="warning") @@ -954,10 +962,10 @@ def _configuration_update_helper(): if reboot_required: web_server.stop(True) - return _configuration_result(None, gdriveError) + return _configuration_result(None, gdriveError, configured) -def _configuration_result(error_flash=None, gdriveError=None): +def _configuration_result(error_flash=None, gdriveError=None, configured=True): gdrive_authenticate = not is_gdrive_ready() gdrivefolders = [] if gdriveError is None: @@ -978,7 +986,7 @@ def _configuration_result(error_flash=None, gdriveError=None): return render_title_template("config_edit.html", config=config, provider=oauthblueprints, show_back_button=show_back_button, show_login_button=show_login_button, - show_authenticate_google_drive=gdrive_authenticate, + show_authenticate_google_drive=gdrive_authenticate, filepicker=configured, gdriveError=gdriveError, gdrivefolders=gdrivefolders, feature_support=feature_support, title=_(u"Basic Configuration"), page="config") diff --git a/cps/cli.py b/cps/cli.py index c94cb89d..65a4185a 100644 --- a/cps/cli.py +++ b/cps/cli.py @@ -45,6 +45,7 @@ parser.add_argument('-v', '--version', action='version', help='Shows version num version=version_info()) parser.add_argument('-i', metavar='ip-address', help='Server IP-Address to listen') parser.add_argument('-s', metavar='user:pass', help='Sets specific username to new password') +parser.add_argument('-f', action='store_true', help='Enables filepicker in unconfigured mode') args = parser.parse_args() if sys.version_info < (3, 0): @@ -110,3 +111,6 @@ if ipadress: # handle and check user password argument user_password = args.s or None + +# Handles enableing of filepicker +filepicker = args.f or None diff --git a/cps/templates/config_edit.html b/cps/templates/config_edit.html index b86fd36b..cf3c7bcd 100644 --- a/cps/templates/config_edit.html +++ b/cps/templates/config_edit.html @@ -16,12 +16,19 @@
-
+
+ {% if filepicker %} + {% endif %}
+ {% if not filepicker %} +
+ +
+ {% endif %} {% if feature_support['gdrive'] %}
From 1e351eb01d73f00a6cde8bf976650279374aca46 Mon Sep 17 00:00:00 2001 From: Ozzieisaacs Date: Sun, 27 Dec 2020 18:59:33 +0100 Subject: [PATCH 057/255] Search for read status --- cps/templates/search_form.html | 8 ++++++++ cps/web.py | 25 +++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/cps/templates/search_form.html b/cps/templates/search_form.html index e713fb93..98ab392c 100644 --- a/cps/templates/search_form.html +++ b/cps/templates/search_form.html @@ -31,6 +31,14 @@
+
+ + +
diff --git a/cps/web.py b/cps/web.py index 10eb11f3..21bc41a0 100644 --- a/cps/web.py +++ b/cps/web.py @@ -618,7 +618,8 @@ def render_read_books(page, are_read, as_xml=False, order=None): db_filter = and_(ub.ReadBook.user_id == int(current_user.id), ub.ReadBook.read_status == ub.ReadBook.STATUS_FINISHED) else: - db_filter = coalesce(ub.ReadBook.read_status, 0) != ub.ReadBook.STATUS_FINISHED + db_filter = and_(ub.ReadBook.user_id == int(current_user.id), + coalesce(ub.ReadBook.read_status, 0) != ub.ReadBook.STATUS_FINISHED) entries, random, pagination = calibre_db.fill_indexpage(page, 0, db.Books, db_filter, @@ -1030,6 +1031,7 @@ def render_adv_search_results(term, offset=None, order=None, limit=None): rating_low = term.get("ratinghigh") rating_high = term.get("ratinglow") description = term.get("comment") + read_status = term.get("read_status") if author_name: author_name = author_name.strip().lower().replace(',', '|') if book_title: @@ -1047,7 +1049,7 @@ def render_adv_search_results(term, offset=None, order=None, limit=None): if include_tag_inputs or exclude_tag_inputs or include_series_inputs or exclude_series_inputs or \ include_languages_inputs or exclude_languages_inputs or author_name or book_title or \ publisher or pub_start or pub_end or rating_low or rating_high or description or cc_present or \ - include_extension_inputs or exclude_extension_inputs: + include_extension_inputs or exclude_extension_inputs or read_status: searchterm.extend((author_name.replace('|', ','), book_title, publisher)) if pub_start: try: @@ -1076,6 +1078,8 @@ def render_adv_search_results(term, offset=None, order=None, limit=None): searchterm.extend([_(u"Rating <= %(rating)s", rating=rating_high)]) if rating_low: searchterm.extend([_(u"Rating >= %(rating)s", rating=rating_low)]) + if read_status: + searchterm.extend([_(u"Read Status = %(status)s", status=read_status)]) searchterm.extend(ext for ext in include_extension_inputs) searchterm.extend(ext for ext in exclude_extension_inputs) # handle custom columns @@ -1092,6 +1096,23 @@ def render_adv_search_results(term, offset=None, order=None, limit=None): q = q.filter(db.Books.pubdate >= pub_start) if pub_end: q = q.filter(db.Books.pubdate <= pub_end) + if read_status: + if config.config_read_column: + if read_status=="True": + q = q.join(db.cc_classes[config.config_read_column], isouter=True) \ + .filter(db.cc_classes[config.config_read_column].value == True) + else: + q = q.join(db.cc_classes[config.config_read_column], isouter=True) \ + .filter(coalesce(db.cc_classes[config.config_read_column].value, False) != True) + else: + if read_status == "True": + q = q.join(ub.ReadBook, db.Books.id==ub.ReadBook.book_id, isouter=True)\ + .filter(ub.ReadBook.user_id == int(current_user.id), + ub.ReadBook.read_status == ub.ReadBook.STATUS_FINISHED) + else: + q = q.join(ub.ReadBook, db.Books.id == ub.ReadBook.book_id, isouter=True) \ + .filter(ub.ReadBook.user_id == int(current_user.id), + coalesce(ub.ReadBook.read_status, 0) != ub.ReadBook.STATUS_FINISHED) if publisher: q = q.filter(db.Books.publishers.any(func.lower(db.Publishers.name).ilike("%" + publisher + "%"))) for tag in include_tag_inputs: From 7e0ed537b7a58e849c23f6477b5be760a752a893 Mon Sep 17 00:00:00 2001 From: Ozzieisaacs Date: Sun, 27 Dec 2020 19:12:27 +0100 Subject: [PATCH 058/255] irst steps Advanced search with mulitselects --- cps/static/css/libs/bootstrap-select.min.css | 6 + cps/static/js/libs/bootstrap-select.min.js | 9 ++ .../libs/bootstrap-select/defaults-cs.min.js | 8 ++ .../libs/bootstrap-select/defaults-de.min.js | 8 ++ .../libs/bootstrap-select/defaults-es.min.js | 8 ++ .../libs/bootstrap-select/defaults-fi.min.js | 8 ++ .../libs/bootstrap-select/defaults-fr.min.js | 8 ++ .../libs/bootstrap-select/defaults-hu.min.js | 8 ++ .../libs/bootstrap-select/defaults-it.min.js | 8 ++ .../libs/bootstrap-select/defaults-ja.min.js | 8 ++ .../libs/bootstrap-select/defaults-km.min.js | 8 ++ .../libs/bootstrap-select/defaults-nl.min.js | 8 ++ .../libs/bootstrap-select/defaults-pl.min.js | 8 ++ .../libs/bootstrap-select/defaults-ru.min.js | 8 ++ .../libs/bootstrap-select/defaults-sv.min.js | 8 ++ .../libs/bootstrap-select/defaults-tr.min.js | 8 ++ .../defaults-zh_Hans_CN.min.js | 8 ++ cps/templates/search_form.html | 135 +++++++++--------- 18 files changed, 200 insertions(+), 70 deletions(-) create mode 100644 cps/static/css/libs/bootstrap-select.min.css create mode 100644 cps/static/js/libs/bootstrap-select.min.js create mode 100644 cps/static/js/libs/bootstrap-select/defaults-cs.min.js create mode 100644 cps/static/js/libs/bootstrap-select/defaults-de.min.js create mode 100644 cps/static/js/libs/bootstrap-select/defaults-es.min.js create mode 100644 cps/static/js/libs/bootstrap-select/defaults-fi.min.js create mode 100644 cps/static/js/libs/bootstrap-select/defaults-fr.min.js create mode 100644 cps/static/js/libs/bootstrap-select/defaults-hu.min.js create mode 100644 cps/static/js/libs/bootstrap-select/defaults-it.min.js create mode 100644 cps/static/js/libs/bootstrap-select/defaults-ja.min.js create mode 100644 cps/static/js/libs/bootstrap-select/defaults-km.min.js create mode 100644 cps/static/js/libs/bootstrap-select/defaults-nl.min.js create mode 100644 cps/static/js/libs/bootstrap-select/defaults-pl.min.js create mode 100644 cps/static/js/libs/bootstrap-select/defaults-ru.min.js create mode 100644 cps/static/js/libs/bootstrap-select/defaults-sv.min.js create mode 100644 cps/static/js/libs/bootstrap-select/defaults-tr.min.js create mode 100644 cps/static/js/libs/bootstrap-select/defaults-zh_Hans_CN.min.js diff --git a/cps/static/css/libs/bootstrap-select.min.css b/cps/static/css/libs/bootstrap-select.min.css new file mode 100644 index 00000000..59708ed5 --- /dev/null +++ b/cps/static/css/libs/bootstrap-select.min.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) + * + * Copyright 2012-2020 SnapAppointments, LLC + * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) + */@-webkit-keyframes bs-notify-fadeOut{0%{opacity:.9}100%{opacity:0}}@-o-keyframes bs-notify-fadeOut{0%{opacity:.9}100%{opacity:0}}@keyframes bs-notify-fadeOut{0%{opacity:.9}100%{opacity:0}}.bootstrap-select>select.bs-select-hidden,select.bs-select-hidden,select.selectpicker{display:none!important}.bootstrap-select{width:220px\0;vertical-align:middle}.bootstrap-select>.dropdown-toggle{position:relative;width:100%;text-align:right;white-space:nowrap;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.bootstrap-select>.dropdown-toggle:after{margin-top:-1px}.bootstrap-select>.dropdown-toggle.bs-placeholder,.bootstrap-select>.dropdown-toggle.bs-placeholder:active,.bootstrap-select>.dropdown-toggle.bs-placeholder:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder:hover{color:#999}.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-danger,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-danger:active,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-danger:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-danger:hover,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-dark,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-dark:active,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-dark:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-dark:hover,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-info,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-info:active,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-info:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-info:hover,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-primary,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-primary:active,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-primary:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-primary:hover,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-secondary,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-secondary:active,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-secondary:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-secondary:hover,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-success,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-success:active,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-success:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-success:hover{color:rgba(255,255,255,.5)}.bootstrap-select>select{position:absolute!important;bottom:0;left:50%;display:block!important;width:.5px!important;height:100%!important;padding:0!important;opacity:0!important;border:none;z-index:0!important}.bootstrap-select>select.mobile-device{top:0;left:0;display:block!important;width:100%!important;z-index:2!important}.bootstrap-select.is-invalid .dropdown-toggle,.error .bootstrap-select .dropdown-toggle,.has-error .bootstrap-select .dropdown-toggle,.was-validated .bootstrap-select select:invalid+.dropdown-toggle{border-color:#b94a48}.bootstrap-select.is-valid .dropdown-toggle,.was-validated .bootstrap-select select:valid+.dropdown-toggle{border-color:#28a745}.bootstrap-select.fit-width{width:auto!important}.bootstrap-select:not([class*=col-]):not([class*=form-control]):not(.input-group-btn){width:220px}.bootstrap-select .dropdown-toggle:focus,.bootstrap-select>select.mobile-device:focus+.dropdown-toggle{outline:thin dotted #333!important;outline:5px auto -webkit-focus-ring-color!important;outline-offset:-2px}.bootstrap-select.form-control{margin-bottom:0;padding:0;border:none;height:auto}:not(.input-group)>.bootstrap-select.form-control:not([class*=col-]){width:100%}.bootstrap-select.form-control.input-group-btn{float:none;z-index:auto}.form-inline .bootstrap-select,.form-inline .bootstrap-select.form-control:not([class*=col-]){width:auto}.bootstrap-select:not(.input-group-btn),.bootstrap-select[class*=col-]{float:none;display:inline-block;margin-left:0}.bootstrap-select.dropdown-menu-right,.bootstrap-select[class*=col-].dropdown-menu-right,.row .bootstrap-select[class*=col-].dropdown-menu-right{float:right}.form-group .bootstrap-select,.form-horizontal .bootstrap-select,.form-inline .bootstrap-select{margin-bottom:0}.form-group-lg .bootstrap-select.form-control,.form-group-sm .bootstrap-select.form-control{padding:0}.form-group-lg .bootstrap-select.form-control .dropdown-toggle,.form-group-sm .bootstrap-select.form-control .dropdown-toggle{height:100%;font-size:inherit;line-height:inherit;border-radius:inherit}.bootstrap-select.form-control-lg .dropdown-toggle,.bootstrap-select.form-control-sm .dropdown-toggle{font-size:inherit;line-height:inherit;border-radius:inherit}.bootstrap-select.form-control-sm .dropdown-toggle{padding:.25rem .5rem}.bootstrap-select.form-control-lg .dropdown-toggle{padding:.5rem 1rem}.form-inline .bootstrap-select .form-control{width:100%}.bootstrap-select.disabled,.bootstrap-select>.disabled{cursor:not-allowed}.bootstrap-select.disabled:focus,.bootstrap-select>.disabled:focus{outline:0!important}.bootstrap-select.bs-container{position:absolute;top:0;left:0;height:0!important;padding:0!important}.bootstrap-select.bs-container .dropdown-menu{z-index:1060}.bootstrap-select .dropdown-toggle .filter-option{position:static;top:0;left:0;float:left;height:100%;width:100%;text-align:left;overflow:hidden;-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.bs3.bootstrap-select .dropdown-toggle .filter-option{padding-right:inherit}.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option{position:absolute;padding-top:inherit;padding-bottom:inherit;padding-left:inherit;float:none}.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option .filter-option-inner{padding-right:inherit}.bootstrap-select .dropdown-toggle .filter-option-inner-inner{overflow:hidden}.bootstrap-select .dropdown-toggle .filter-expand{width:0!important;float:left;opacity:0!important;overflow:hidden}.bootstrap-select .dropdown-toggle .caret{position:absolute;top:50%;right:12px;margin-top:-2px;vertical-align:middle}.input-group .bootstrap-select.form-control .dropdown-toggle{border-radius:inherit}.bootstrap-select[class*=col-] .dropdown-toggle{width:100%}.bootstrap-select .dropdown-menu{min-width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select .dropdown-menu>.inner:focus{outline:0!important}.bootstrap-select .dropdown-menu.inner{position:static;float:none;border:0;padding:0;margin:0;border-radius:0;-webkit-box-shadow:none;box-shadow:none}.bootstrap-select .dropdown-menu li{position:relative}.bootstrap-select .dropdown-menu li.active small{color:rgba(255,255,255,.5)!important}.bootstrap-select .dropdown-menu li.disabled a{cursor:not-allowed}.bootstrap-select .dropdown-menu li a{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.bootstrap-select .dropdown-menu li a.opt{position:relative;padding-left:2.25em}.bootstrap-select .dropdown-menu li a span.check-mark{display:none}.bootstrap-select .dropdown-menu li a span.text{display:inline-block}.bootstrap-select .dropdown-menu li small{padding-left:.5em}.bootstrap-select .dropdown-menu .notify{position:absolute;bottom:5px;width:96%;margin:0 2%;min-height:26px;padding:3px 5px;background:#f5f5f5;border:1px solid #e3e3e3;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05);pointer-events:none;opacity:.9;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select .dropdown-menu .notify.fadeOut{-webkit-animation:.3s linear 750ms forwards bs-notify-fadeOut;-o-animation:.3s linear 750ms forwards bs-notify-fadeOut;animation:.3s linear 750ms forwards bs-notify-fadeOut}.bootstrap-select .no-results{padding:3px;background:#f5f5f5;margin:0 5px;white-space:nowrap}.bootstrap-select.fit-width .dropdown-toggle .filter-option{position:static;display:inline;padding:0}.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner,.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner-inner{display:inline}.bootstrap-select.fit-width .dropdown-toggle .bs-caret:before{content:'\00a0'}.bootstrap-select.fit-width .dropdown-toggle .caret{position:static;top:auto;margin-top:-1px}.bootstrap-select.show-tick .dropdown-menu .selected span.check-mark{position:absolute;display:inline-block;right:15px;top:5px}.bootstrap-select.show-tick .dropdown-menu li a span.text{margin-right:34px}.bootstrap-select .bs-ok-default:after{content:'';display:block;width:.5em;height:1em;border-style:solid;border-width:0 .26em .26em 0;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle,.bootstrap-select.show-menu-arrow.show>.dropdown-toggle{z-index:1061}.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:before{content:'';border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid rgba(204,204,204,.2);position:absolute;bottom:-4px;left:9px;display:none}.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:after{content:'';border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;bottom:-4px;left:10px;display:none}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:before{bottom:auto;top:-4px;border-top:7px solid rgba(204,204,204,.2);border-bottom:0}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:after{bottom:auto;top:-4px;border-top:6px solid #fff;border-bottom:0}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:before{right:12px;left:auto}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:after{right:13px;left:auto}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle .filter-option:after,.bootstrap-select.show-menu-arrow.open>.dropdown-toggle .filter-option:before,.bootstrap-select.show-menu-arrow.show>.dropdown-toggle .filter-option:after,.bootstrap-select.show-menu-arrow.show>.dropdown-toggle .filter-option:before{display:block}.bs-actionsbox,.bs-donebutton,.bs-searchbox{padding:4px 8px}.bs-actionsbox{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-actionsbox .btn-group button{width:50%}.bs-donebutton{float:left;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-donebutton .btn-group button{width:100%}.bs-searchbox+.bs-actionsbox{padding:0 8px 4px}.bs-searchbox .form-control{margin-bottom:0;width:100%;float:none} \ No newline at end of file diff --git a/cps/static/js/libs/bootstrap-select.min.js b/cps/static/js/libs/bootstrap-select.min.js new file mode 100644 index 00000000..92e3a32e --- /dev/null +++ b/cps/static/js/libs/bootstrap-select.min.js @@ -0,0 +1,9 @@ +/*! + * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) + * + * Copyright 2012-2020 SnapAppointments, LLC + * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) + */ + +!function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){!function(z){"use strict";var d=["sanitize","whiteList","sanitizeFn"],r=["background","cite","href","itemtype","longdesc","poster","src","xlink:href"],e={"*":["class","dir","id","lang","role","tabindex","style",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},l=/^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi,a=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i;function v(e,t){var i=e.nodeName.toLowerCase();if(-1!==z.inArray(i,t))return-1===z.inArray(i,r)||Boolean(e.nodeValue.match(l)||e.nodeValue.match(a));for(var s=z(t).filter(function(e,t){return t instanceof RegExp}),n=0,o=s.length;n]+>/g,"")),s&&(a=w(a)),a=a.toUpperCase(),o="contains"===i?0<=a.indexOf(t):a.startsWith(t)))break}return o}function L(e){return parseInt(e,10)||0}z.fn.triggerNative=function(e){var t,i=this[0];i.dispatchEvent?(u?t=new Event(e,{bubbles:!0}):(t=document.createEvent("Event")).initEvent(e,!0,!1),i.dispatchEvent(t)):i.fireEvent?((t=document.createEventObject()).eventType=e,i.fireEvent("on"+e,t)):this.trigger(e)};var f={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\u0100":"A","\u0102":"A","\u0104":"A","\u0101":"a","\u0103":"a","\u0105":"a","\u0106":"C","\u0108":"C","\u010a":"C","\u010c":"C","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\u010e":"D","\u0110":"D","\u010f":"d","\u0111":"d","\u0112":"E","\u0114":"E","\u0116":"E","\u0118":"E","\u011a":"E","\u0113":"e","\u0115":"e","\u0117":"e","\u0119":"e","\u011b":"e","\u011c":"G","\u011e":"G","\u0120":"G","\u0122":"G","\u011d":"g","\u011f":"g","\u0121":"g","\u0123":"g","\u0124":"H","\u0126":"H","\u0125":"h","\u0127":"h","\u0128":"I","\u012a":"I","\u012c":"I","\u012e":"I","\u0130":"I","\u0129":"i","\u012b":"i","\u012d":"i","\u012f":"i","\u0131":"i","\u0134":"J","\u0135":"j","\u0136":"K","\u0137":"k","\u0138":"k","\u0139":"L","\u013b":"L","\u013d":"L","\u013f":"L","\u0141":"L","\u013a":"l","\u013c":"l","\u013e":"l","\u0140":"l","\u0142":"l","\u0143":"N","\u0145":"N","\u0147":"N","\u014a":"N","\u0144":"n","\u0146":"n","\u0148":"n","\u014b":"n","\u014c":"O","\u014e":"O","\u0150":"O","\u014d":"o","\u014f":"o","\u0151":"o","\u0154":"R","\u0156":"R","\u0158":"R","\u0155":"r","\u0157":"r","\u0159":"r","\u015a":"S","\u015c":"S","\u015e":"S","\u0160":"S","\u015b":"s","\u015d":"s","\u015f":"s","\u0161":"s","\u0162":"T","\u0164":"T","\u0166":"T","\u0163":"t","\u0165":"t","\u0167":"t","\u0168":"U","\u016a":"U","\u016c":"U","\u016e":"U","\u0170":"U","\u0172":"U","\u0169":"u","\u016b":"u","\u016d":"u","\u016f":"u","\u0171":"u","\u0173":"u","\u0174":"W","\u0175":"w","\u0176":"Y","\u0177":"y","\u0178":"Y","\u0179":"Z","\u017b":"Z","\u017d":"Z","\u017a":"z","\u017c":"z","\u017e":"z","\u0132":"IJ","\u0133":"ij","\u0152":"Oe","\u0153":"oe","\u0149":"'n","\u017f":"s"},m=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,g=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\u1ab0-\\u1aff\\u1dc0-\\u1dff]","g");function b(e){return f[e]}function w(e){return(e=e.toString())&&e.replace(m,b).replace(g,"")}var I,x,y,$,S=(I={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},x="(?:"+Object.keys(I).join("|")+")",y=RegExp(x),$=RegExp(x,"g"),function(e){return e=null==e?"":""+e,y.test(e)?e.replace($,E):e});function E(e){return I[e]}var C={32:" ",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",65:"A",66:"B",67:"C",68:"D",69:"E",70:"F",71:"G",72:"H",73:"I",74:"J",75:"K",76:"L",77:"M",78:"N",79:"O",80:"P",81:"Q",82:"R",83:"S",84:"T",85:"U",86:"V",87:"W",88:"X",89:"Y",90:"Z",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9"},N=27,D=13,H=32,W=9,B=38,M=40,R={success:!1,major:"3"};try{R.full=(z.fn.dropdown.Constructor.VERSION||"").split(" ")[0].split("."),R.major=R.full[0],R.success=!0}catch(e){}var U=0,j=".bs.select",V={DISABLED:"disabled",DIVIDER:"divider",SHOW:"open",DROPUP:"dropup",MENU:"dropdown-menu",MENURIGHT:"dropdown-menu-right",MENULEFT:"dropdown-menu-left",BUTTONCLASS:"btn-default",POPOVERHEADER:"popover-title",ICONBASE:"glyphicon",TICKICON:"glyphicon-ok"},F={MENU:"."+V.MENU},_={span:document.createElement("span"),i:document.createElement("i"),subtext:document.createElement("small"),a:document.createElement("a"),li:document.createElement("li"),whitespace:document.createTextNode("\xa0"),fragment:document.createDocumentFragment()};_.a.setAttribute("role","option"),"4"===R.major&&(_.a.className="dropdown-item"),_.subtext.className="text-muted",_.text=_.span.cloneNode(!1),_.text.className="text",_.checkMark=_.span.cloneNode(!1);var G=new RegExp(B+"|"+M),q=new RegExp("^"+W+"$|"+N),K={li:function(e,t,i){var s=_.li.cloneNode(!1);return e&&(1===e.nodeType||11===e.nodeType?s.appendChild(e):s.innerHTML=e),void 0!==t&&""!==t&&(s.className=t),null!=i&&s.classList.add("optgroup-"+i),s},a:function(e,t,i){var s=_.a.cloneNode(!0);return e&&(11===e.nodeType?s.appendChild(e):s.insertAdjacentHTML("beforeend",e)),void 0!==t&&""!==t&&s.classList.add.apply(s.classList,t.split(" ")),i&&s.setAttribute("style",i),s},text:function(e,t){var i,s,n=_.text.cloneNode(!1);if(e.content)n.innerHTML=e.content;else{if(n.textContent=e.text,e.icon){var o=_.whitespace.cloneNode(!1);(s=(!0===t?_.i:_.span).cloneNode(!1)).className=this.options.iconBase+" "+e.icon,_.fragment.appendChild(s),_.fragment.appendChild(o)}e.subtext&&((i=_.subtext.cloneNode(!1)).textContent=e.subtext,n.appendChild(i))}if(!0===t)for(;0'},maxOptions:!1,mobile:!1,selectOnTab:!1,dropdownAlignRight:!1,windowPadding:0,virtualScroll:600,display:!1,sanitize:!0,sanitizeFn:null,whiteList:e},Y.prototype={constructor:Y,init:function(){var i=this,e=this.$element.attr("id");U++,this.selectId="bs-select-"+U,this.$element[0].classList.add("bs-select-hidden"),this.multiple=this.$element.prop("multiple"),this.autofocus=this.$element.prop("autofocus"),this.$element[0].classList.contains("show-tick")&&(this.options.showTick=!0),this.$newElement=this.createDropdown(),this.buildData(),this.$element.after(this.$newElement).prependTo(this.$newElement),this.$button=this.$newElement.children("button"),this.$menu=this.$newElement.children(F.MENU),this.$menuInner=this.$menu.children(".inner"),this.$searchbox=this.$menu.find("input"),this.$element[0].classList.remove("bs-select-hidden"),!0===this.options.dropdownAlignRight&&this.$menu[0].classList.add(V.MENURIGHT),void 0!==e&&this.$button.attr("data-id",e),this.checkDisabled(),this.clickListener(),this.options.liveSearch?(this.liveSearchListener(),this.focusedParent=this.$searchbox[0]):this.focusedParent=this.$menuInner[0],this.setStyle(),this.render(),this.setWidth(),this.options.container?this.selectPosition():this.$element.on("hide"+j,function(){if(i.isVirtual()){var e=i.$menuInner[0],t=e.firstChild.cloneNode(!1);e.replaceChild(t,e.firstChild),e.scrollTop=0}}),this.$menu.data("this",this),this.$newElement.data("this",this),this.options.mobile&&this.mobile(),this.$newElement.on({"hide.bs.dropdown":function(e){i.$element.trigger("hide"+j,e)},"hidden.bs.dropdown":function(e){i.$element.trigger("hidden"+j,e)},"show.bs.dropdown":function(e){i.$element.trigger("show"+j,e)},"shown.bs.dropdown":function(e){i.$element.trigger("shown"+j,e)}}),i.$element[0].hasAttribute("required")&&this.$element.on("invalid"+j,function(){i.$button[0].classList.add("bs-invalid"),i.$element.on("shown"+j+".invalid",function(){i.$element.val(i.$element.val()).off("shown"+j+".invalid")}).on("rendered"+j,function(){this.validity.valid&&i.$button[0].classList.remove("bs-invalid"),i.$element.off("rendered"+j)}),i.$button.on("blur"+j,function(){i.$element.trigger("focus").trigger("blur"),i.$button.off("blur"+j)})}),setTimeout(function(){i.buildList(),i.$element.trigger("loaded"+j)})},createDropdown:function(){var e=this.multiple||this.options.showTick?" show-tick":"",t=this.multiple?' aria-multiselectable="true"':"",i="",s=this.autofocus?" autofocus":"";R.major<4&&this.$element.parent().hasClass("input-group")&&(i=" input-group-btn");var n,o="",r="",l="",a="";return this.options.header&&(o='
'+this.options.header+"
"),this.options.liveSearch&&(r=''),this.multiple&&this.options.actionsBox&&(l='
"),this.multiple&&this.options.doneButton&&(a='
"),n='",z(n)},setPositionData:function(){this.selectpicker.view.canHighlight=[];for(var e=this.selectpicker.view.size=0;e=this.options.virtualScroll||!0===this.options.virtualScroll},createView:function(A,e,t){var L,N,D=this,i=0,H=[];if(this.selectpicker.isSearching=A,this.selectpicker.current=A?this.selectpicker.search:this.selectpicker.main,this.setPositionData(),e)if(t)i=this.$menuInner[0].scrollTop;else if(!D.multiple){var s=D.$element[0],n=(s.options[s.selectedIndex]||{}).liIndex;if("number"==typeof n&&!1!==D.options.size){var o=D.selectpicker.main.data[n],r=o&&o.position;r&&(i=r-(D.sizeInfo.menuInnerHeight+D.sizeInfo.liHeight)/2)}}function l(e,t){var i,s,n,o,r,l,a,c,d=D.selectpicker.current.elements.length,h=[],p=!0,u=D.isVirtual();D.selectpicker.view.scrollTop=e,i=Math.ceil(D.sizeInfo.menuInnerHeight/D.sizeInfo.liHeight*1.5),s=Math.round(d/i)||1;for(var f=0;fd-1?0:D.selectpicker.current.data[d-1].position-D.selectpicker.current.data[D.selectpicker.view.position1-1].position,b.firstChild.style.marginTop=v+"px",b.firstChild.style.marginBottom=g+"px"):(b.firstChild.style.marginTop=0,b.firstChild.style.marginBottom=0),b.firstChild.appendChild(w),!0===u&&D.sizeInfo.hasScrollBar){var C=b.firstChild.offsetWidth;if(t&&CD.sizeInfo.selectWidth)b.firstChild.style.minWidth=D.sizeInfo.menuInnerInnerWidth+"px";else if(C>D.sizeInfo.menuInnerInnerWidth){D.$menu[0].style.minWidth=0;var O=b.firstChild.offsetWidth;O>D.sizeInfo.menuInnerInnerWidth&&(D.sizeInfo.menuInnerInnerWidth=O,b.firstChild.style.minWidth=D.sizeInfo.menuInnerInnerWidth+"px"),D.$menu[0].style.minWidth=""}}}if(D.prevActiveIndex=D.activeIndex,D.options.liveSearch){if(A&&t){var z,T=0;D.selectpicker.view.canHighlight[T]||(T=1+D.selectpicker.view.canHighlight.slice(1).indexOf(!0)),z=D.selectpicker.view.visibleElements[T],D.defocusItem(D.selectpicker.view.currentActive),D.activeIndex=(D.selectpicker.current.data[T]||{}).index,D.focusItem(z)}}else D.$menuInner.trigger("focus")}l(i,!0),this.$menuInner.off("scroll.createView").on("scroll.createView",function(e,t){D.noScroll||l(this.scrollTop,t),D.noScroll=!1}),z(window).off("resize"+j+"."+this.selectId+".createView").on("resize"+j+"."+this.selectId+".createView",function(){D.$newElement.hasClass(V.SHOW)&&l(D.$menuInner[0].scrollTop)})},focusItem:function(e,t,i){if(e){t=t||this.selectpicker.main.data[this.activeIndex];var s=e.firstChild;s&&(s.setAttribute("aria-setsize",this.selectpicker.view.size),s.setAttribute("aria-posinset",t.posinset),!0!==i&&(this.focusedParent.setAttribute("aria-activedescendant",s.id),e.classList.add("active"),s.classList.add("active")))}},defocusItem:function(e){e&&(e.classList.remove("active"),e.firstChild&&e.firstChild.classList.remove("active"))},setPlaceholder:function(){var e=!1;if(this.options.title&&!this.multiple){this.selectpicker.view.titleOption||(this.selectpicker.view.titleOption=document.createElement("option")),e=!0;var t=this.$element[0],i=!1,s=!this.selectpicker.view.titleOption.parentNode;if(s)this.selectpicker.view.titleOption.className="bs-title-option",this.selectpicker.view.titleOption.value="",i=void 0===z(t.options[t.selectedIndex]).attr("selected")&&void 0===this.$element.data("selected");!s&&0===this.selectpicker.view.titleOption.index||t.insertBefore(this.selectpicker.view.titleOption,t.firstChild),i&&(t.selectedIndex=0)}return e},buildData:function(){var p=':not([hidden]):not([data-hidden="true"])',u=[],f=0,e=this.setPlaceholder()?1:0;this.options.hideDisabled&&(p+=":not(:disabled)");var t=this.$element[0].querySelectorAll("select > *"+p);function m(e){var t=u[u.length-1];t&&"divider"===t.type&&(t.optID||e.optID)||((e=e||{}).type="divider",u.push(e))}function v(e,t){if((t=t||{}).divider="true"===e.getAttribute("data-divider"),t.divider)m({optID:t.optID});else{var i=u.length,s=e.style.cssText,n=s?S(s):"",o=(e.className||"")+(t.optgroupClass||"");t.optID&&(o="opt "+o),t.optionClass=o.trim(),t.inlineStyle=n,t.text=e.textContent,t.content=e.getAttribute("data-content"),t.tokens=e.getAttribute("data-tokens"),t.subtext=e.getAttribute("data-subtext"),t.icon=e.getAttribute("data-icon"),e.liIndex=i,t.display=t.content||t.text,t.type="option",t.index=i,t.option=e,t.selected=!!e.selected,t.disabled=t.disabled||!!e.disabled,u.push(t)}}function i(e,t){var i=t[e],s=t[e-1],n=t[e+1],o=i.querySelectorAll("option"+p);if(o.length){var r,l,a={display:S(i.label),subtext:i.getAttribute("data-subtext"),icon:i.getAttribute("data-icon"),type:"optgroup-label",optgroupClass:" "+(i.className||"")};f++,s&&m({optID:f}),a.optID=f,u.push(a);for(var c=0,d=o.length;c li")},render:function(){var e,t=this,i=this.$element[0],s=this.setPlaceholder()&&0===i.selectedIndex,n=O(i,this.options.hideDisabled),o=n.length,r=this.$button[0],l=r.querySelector(".filter-option-inner-inner"),a=document.createTextNode(this.options.multipleSeparator),c=_.fragment.cloneNode(!1),d=!1;if(r.classList.toggle("bs-placeholder",t.multiple?!o:!T(i,n)),this.tabIndex(),"static"===this.options.selectedTextFormat)c=K.text.call(this,{text:this.options.title},!0);else if(!1===(this.multiple&&-1!==this.options.selectedTextFormat.indexOf("count")&&1")).length&&o>e[1]||1===e.length&&2<=o))){if(!s){for(var h=0;h option"+m+", optgroup"+m+" option"+m).length,g="function"==typeof this.options.countSelectedText?this.options.countSelectedText(o,v):this.options.countSelectedText;c=K.text.call(this,{text:g.replace("{0}",o.toString()).replace("{1}",v.toString())},!0)}if(null==this.options.title&&(this.options.title=this.$element.attr("title")),c.childNodes.length||(c=K.text.call(this,{text:void 0!==this.options.title?this.options.title:this.options.noneSelectedText},!0)),r.title=c.textContent.replace(/<[^>]*>?/g,"").trim(),this.options.sanitize&&d&&P([c],t.options.whiteList,t.options.sanitizeFn),l.innerHTML="",l.appendChild(c),R.major<4&&this.$newElement[0].classList.contains("bs3-has-addon")){var b=r.querySelector(".filter-expand"),w=l.cloneNode(!0);w.className="filter-expand",b?r.replaceChild(w,b):r.appendChild(w)}this.$element.trigger("rendered"+j)},setStyle:function(e,t){var i,s=this.$button[0],n=this.$newElement[0],o=this.options.style.trim();this.$element.attr("class")&&this.$newElement.addClass(this.$element.attr("class").replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi,"")),R.major<4&&(n.classList.add("bs3"),n.parentNode.classList.contains("input-group")&&(n.previousElementSibling||n.nextElementSibling)&&(n.previousElementSibling||n.nextElementSibling).classList.contains("input-group-addon")&&n.classList.add("bs3-has-addon")),i=e?e.trim():o,"add"==t?i&&s.classList.add.apply(s.classList,i.split(" ")):"remove"==t?i&&s.classList.remove.apply(s.classList,i.split(" ")):(o&&s.classList.remove.apply(s.classList,o.split(" ")),i&&s.classList.add.apply(s.classList,i.split(" ")))},liHeight:function(e){if(e||!1!==this.options.size&&!Object.keys(this.sizeInfo).length){var t=document.createElement("div"),i=document.createElement("div"),s=document.createElement("div"),n=document.createElement("ul"),o=document.createElement("li"),r=document.createElement("li"),l=document.createElement("li"),a=document.createElement("a"),c=document.createElement("span"),d=this.options.header&&0this.sizeInfo.menuExtras.vert&&l+this.sizeInfo.menuExtras.vert+50>this.sizeInfo.selectOffsetBot,!0===this.selectpicker.isSearching&&(a=this.selectpicker.dropup),this.$newElement.toggleClass(V.DROPUP,a),this.selectpicker.dropup=a),"auto"===this.options.size)n=3this.options.size){for(var b=0;bthis.sizeInfo.menuInnerHeight&&(this.sizeInfo.hasScrollBar=!0,this.sizeInfo.totalMenuWidth=this.sizeInfo.menuWidth+this.sizeInfo.scrollBarWidth),"auto"===this.options.dropdownAlignRight&&this.$menu.toggleClass(V.MENURIGHT,this.sizeInfo.selectOffsetLeft>this.sizeInfo.selectOffsetRight&&this.sizeInfo.selectOffsetRightthis.options.size&&i.off("resize"+j+"."+this.selectId+".setMenuSize scroll"+j+"."+this.selectId+".setMenuSize")}this.createView(!1,!0,e)},setWidth:function(){var i=this;"auto"===this.options.width?requestAnimationFrame(function(){i.$menu.css("min-width","0"),i.$element.on("loaded"+j,function(){i.liHeight(),i.setMenuSize();var e=i.$newElement.clone().appendTo("body"),t=e.css("width","auto").children("button").outerWidth();e.remove(),i.sizeInfo.selectWidth=Math.max(i.sizeInfo.totalMenuWidth,t),i.$newElement.css("width",i.sizeInfo.selectWidth+"px")})}):"fit"===this.options.width?(this.$menu.css("min-width",""),this.$newElement.css("width","").addClass("fit-width")):this.options.width?(this.$menu.css("min-width",""),this.$newElement.css("width",this.options.width)):(this.$menu.css("min-width",""),this.$newElement.css("width","")),this.$newElement.hasClass("fit-width")&&"fit"!==this.options.width&&this.$newElement[0].classList.remove("fit-width")},selectPosition:function(){this.$bsContainer=z('
');function e(e){var t={},i=r.options.display||!!z.fn.dropdown.Constructor.Default&&z.fn.dropdown.Constructor.Default.display;r.$bsContainer.addClass(e.attr("class").replace(/form-control|fit-width/gi,"")).toggleClass(V.DROPUP,e.hasClass(V.DROPUP)),s=e.offset(),l.is("body")?n={top:0,left:0}:((n=l.offset()).top+=parseInt(l.css("borderTopWidth"))-l.scrollTop(),n.left+=parseInt(l.css("borderLeftWidth"))-l.scrollLeft()),o=e.hasClass(V.DROPUP)?0:e[0].offsetHeight,(R.major<4||"static"===i)&&(t.top=s.top-n.top+o,t.left=s.left-n.left),t.width=e[0].offsetWidth,r.$bsContainer.css(t)}var s,n,o,r=this,l=z(this.options.container);this.$button.on("click.bs.dropdown.data-api",function(){r.isDisabled()||(e(r.$newElement),r.$bsContainer.appendTo(r.options.container).toggleClass(V.SHOW,!r.$button.hasClass(V.SHOW)).append(r.$menu))}),z(window).off("resize"+j+"."+this.selectId+" scroll"+j+"."+this.selectId).on("resize"+j+"."+this.selectId+" scroll"+j+"."+this.selectId,function(){r.$newElement.hasClass(V.SHOW)&&e(r.$newElement)}),this.$element.on("hide"+j,function(){r.$menu.data("height",r.$menu.height()),r.$bsContainer.detach()})},setOptionStatus:function(e){var t=this;if(t.noScroll=!1,t.selectpicker.view.visibleElements&&t.selectpicker.view.visibleElements.length)for(var i=0;i
');y[2]&&($=$.replace("{var}",y[2][1"+$+"
")),d=!1,C.$element.trigger("maxReached"+j)),g&&w&&(E.append(z("
"+S+"
")),d=!1,C.$element.trigger("maxReachedGrp"+j)),setTimeout(function(){C.setSelected(r,!1)},10),E[0].classList.add("fadeOut"),setTimeout(function(){E.remove()},1050)}}}else c&&(c.selected=!1),h.selected=!0,C.setSelected(r,!0);!C.multiple||C.multiple&&1===C.options.maxOptions?C.$button.trigger("focus"):C.options.liveSearch&&C.$searchbox.trigger("focus"),d&&(!C.multiple&&a===s.selectedIndex||(A=[h.index,p.prop("selected"),l],C.$element.triggerNative("change")))}}),this.$menu.on("click","li."+V.DISABLED+" a, ."+V.POPOVERHEADER+", ."+V.POPOVERHEADER+" :not(.close)",function(e){e.currentTarget==this&&(e.preventDefault(),e.stopPropagation(),C.options.liveSearch&&!z(e.target).hasClass("close")?C.$searchbox.trigger("focus"):C.$button.trigger("focus"))}),this.$menuInner.on("click",".divider, .dropdown-header",function(e){e.preventDefault(),e.stopPropagation(),C.options.liveSearch?C.$searchbox.trigger("focus"):C.$button.trigger("focus")}),this.$menu.on("click","."+V.POPOVERHEADER+" .close",function(){C.$button.trigger("click")}),this.$searchbox.on("click",function(e){e.stopPropagation()}),this.$menu.on("click",".actions-btn",function(e){C.options.liveSearch?C.$searchbox.trigger("focus"):C.$button.trigger("focus"),e.preventDefault(),e.stopPropagation(),z(this).hasClass("bs-select-all")?C.selectAll():C.deselectAll()}),this.$element.on("change"+j,function(){C.render(),C.$element.trigger("changed"+j,A),A=null}).on("focus"+j,function(){C.options.mobile||C.$button.trigger("focus")})},liveSearchListener:function(){var u=this,f=document.createElement("li");this.$button.on("click.bs.dropdown.data-api",function(){u.$searchbox.val()&&u.$searchbox.val("")}),this.$searchbox.on("click.bs.dropdown.data-api focus.bs.dropdown.data-api touchend.bs.dropdown.data-api",function(e){e.stopPropagation()}),this.$searchbox.on("input propertychange",function(){var e=u.$searchbox.val();if(u.selectpicker.search.elements=[],u.selectpicker.search.data=[],e){var t=[],i=e.toUpperCase(),s={},n=[],o=u._searchStyle(),r=u.options.liveSearchNormalize;r&&(i=w(i));for(var l=0;l=a.selectpicker.view.canHighlight.length&&(t=0),a.selectpicker.view.canHighlight[t+f]||(t=t+1+a.selectpicker.view.canHighlight.slice(t+f+1).indexOf(!0))),e.preventDefault();var m=f+t;e.which===B?0===f&&t===c.length-1?(a.$menuInner[0].scrollTop=a.$menuInner[0].scrollHeight,m=a.selectpicker.current.elements.length-1):d=(o=(n=a.selectpicker.current.data[m]).position-n.height)u+a.sizeInfo.menuInnerHeight),s=a.selectpicker.main.elements[v],a.activeIndex=b[x],a.focusItem(s),s&&s.firstChild.focus(),d&&(a.$menuInner[0].scrollTop=o),r.trigger("focus")}}i&&(e.which===H&&!a.selectpicker.keydown.keyHistory||e.which===D||e.which===W&&a.options.selectOnTab)&&(e.which!==H&&e.preventDefault(),a.options.liveSearch&&e.which===H||(a.$menuInner.find(".active a").trigger("click",!0),r.trigger("focus"),a.options.liveSearch||(e.preventDefault(),z(document).data("spaceSelect",!0))))}},mobile:function(){this.$element[0].classList.add("mobile-device")},refresh:function(){var e=z.extend({},this.options,this.$element.data());this.options=e,this.checkDisabled(),this.setStyle(),this.render(),this.buildData(),this.buildList(),this.setWidth(),this.setSize(!0),this.$element.trigger("refreshed"+j)},hide:function(){this.$newElement.hide()},show:function(){this.$newElement.show()},remove:function(){this.$newElement.remove(),this.$element.remove()},destroy:function(){this.$newElement.before(this.$element).remove(),this.$bsContainer?this.$bsContainer.remove():this.$menu.remove(),this.$element.off(j).removeData("selectpicker").removeClass("bs-select-hidden selectpicker"),z(window).off(j+"."+this.selectId)}};var J=z.fn.selectpicker;z.fn.selectpicker=Z,z.fn.selectpicker.Constructor=Y,z.fn.selectpicker.noConflict=function(){return z.fn.selectpicker=J,this};var Q=z.fn.dropdown.Constructor._dataApiKeydownHandler||z.fn.dropdown.Constructor.prototype.keydown;z(document).off("keydown.bs.dropdown.data-api").on("keydown.bs.dropdown.data-api",':not(.bootstrap-select) > [data-toggle="dropdown"]',Q).on("keydown.bs.dropdown.data-api",":not(.bootstrap-select) > .dropdown-menu",Q).on("keydown"+j,'.bootstrap-select [data-toggle="dropdown"], .bootstrap-select [role="listbox"], .bootstrap-select .bs-searchbox input',Y.prototype.keydown).on("focusin.modal",'.bootstrap-select [data-toggle="dropdown"], .bootstrap-select [role="listbox"], .bootstrap-select .bs-searchbox input',function(e){e.stopPropagation()}),z(window).on("load"+j+".data-api",function(){z(".selectpicker").each(function(){var e=z(this);Z.call(e,e.data())})})}(e)}); +//# sourceMappingURL=bootstrap-select.min.js.map \ No newline at end of file diff --git a/cps/static/js/libs/bootstrap-select/defaults-cs.min.js b/cps/static/js/libs/bootstrap-select/defaults-cs.min.js new file mode 100644 index 00000000..be309a10 --- /dev/null +++ b/cps/static/js/libs/bootstrap-select/defaults-cs.min.js @@ -0,0 +1,8 @@ +/*! + * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) + * + * Copyright 2012-2020 SnapAppointments, LLC + * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) + */ + +!function(e,n){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return n(e)}):"object"==typeof module&&module.exports?module.exports=n(require("jquery")):n(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"Vyberte ze seznamu",noneResultsText:"Pro hled\xe1n\xed {0} nebyly nalezeny \u017e\xe1dn\xe9 v\xfdsledky",countSelectedText:"Vybran\xe9 {0} z {1}",maxOptionsText:["Limit p\u0159ekro\u010den ({n} {var} max)","Limit skupiny p\u0159ekro\u010den ({n} {var} max)",["polo\u017eek","polo\u017eka"]],multipleSeparator:", ",selectAllText:"Vybrat v\u0161e",deselectAllText:"Zru\u0161it v\xfdb\u011br"}}); \ No newline at end of file diff --git a/cps/static/js/libs/bootstrap-select/defaults-de.min.js b/cps/static/js/libs/bootstrap-select/defaults-de.min.js new file mode 100644 index 00000000..e625440b --- /dev/null +++ b/cps/static/js/libs/bootstrap-select/defaults-de.min.js @@ -0,0 +1,8 @@ +/*! + * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) + * + * Copyright 2012-2020 SnapAppointments, LLC + * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) + */ + +!function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"Bitte w\xe4hlen...",noneResultsText:"Keine Ergebnisse f\xfcr {0}",countSelectedText:function(e,t){return 1==e?"{0} Element ausgew\xe4hlt":"{0} Elemente ausgew\xe4hlt"},maxOptionsText:function(e,t){return[1==e?"Limit erreicht ({n} Element max.)":"Limit erreicht ({n} Elemente max.)",1==t?"Gruppen-Limit erreicht ({n} Element max.)":"Gruppen-Limit erreicht ({n} Elemente max.)"]},selectAllText:"Alles ausw\xe4hlen",deselectAllText:"Nichts ausw\xe4hlen",multipleSeparator:", "}}); \ No newline at end of file diff --git a/cps/static/js/libs/bootstrap-select/defaults-es.min.js b/cps/static/js/libs/bootstrap-select/defaults-es.min.js new file mode 100644 index 00000000..25efec39 --- /dev/null +++ b/cps/static/js/libs/bootstrap-select/defaults-es.min.js @@ -0,0 +1,8 @@ +/*! + * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) + * + * Copyright 2012-2020 SnapAppointments, LLC + * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) + */ + +!function(e,o){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return o(e)}):"object"==typeof module&&module.exports?module.exports=o(require("jquery")):o(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"No hay selecci\xf3n",noneResultsText:"No hay resultados {0}",countSelectedText:"Seleccionados {0} de {1}",maxOptionsText:["L\xedmite alcanzado ({n} {var} max)","L\xedmite del grupo alcanzado({n} {var} max)",["elementos","element"]],multipleSeparator:", ",selectAllText:"Seleccionar Todos",deselectAllText:"Desmarcar Todos"}}); \ No newline at end of file diff --git a/cps/static/js/libs/bootstrap-select/defaults-fi.min.js b/cps/static/js/libs/bootstrap-select/defaults-fi.min.js new file mode 100644 index 00000000..bee14048 --- /dev/null +++ b/cps/static/js/libs/bootstrap-select/defaults-fi.min.js @@ -0,0 +1,8 @@ +/*! + * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) + * + * Copyright 2012-2020 SnapAppointments, LLC + * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) + */ + +!function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"Ei valintoja",noneResultsText:"Ei hakutuloksia {0}",countSelectedText:function(e,t){return 1==e?"{0} valittu":"{0} valitut"},maxOptionsText:function(e,t){return["Valintojen maksimim\xe4\xe4r\xe4 ({n} saavutettu)","Ryhm\xe4n maksimim\xe4\xe4r\xe4 ({n} saavutettu)"]},selectAllText:"Valitse kaikki",deselectAllText:"Poista kaikki",multipleSeparator:", "}}); \ No newline at end of file diff --git a/cps/static/js/libs/bootstrap-select/defaults-fr.min.js b/cps/static/js/libs/bootstrap-select/defaults-fr.min.js new file mode 100644 index 00000000..d8931590 --- /dev/null +++ b/cps/static/js/libs/bootstrap-select/defaults-fr.min.js @@ -0,0 +1,8 @@ +/*! + * Bootstrap-select v1.13.14 (https://developer.snapappointments.com/bootstrap-select) + * + * Copyright 2012-2020 SnapAppointments, LLC + * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) + */ + +!function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"Aucune s\xe9lection",noneResultsText:"Aucun r\xe9sultat pour {0}",countSelectedText:function(e,t){return 1{{_('Yes')}} -
- -
-
- {% for tag in tags %} - - {% endfor %} +
+
+
+
+ +
+
+
+
- -
-
- {% for tag in tags %} - - {% endfor %} +
+
+
+
-
- -
-
- {% for serie in series %} - - {% endfor %} -
-
- -
-
- {% for serie in series %} - - {% endfor %} +
+
+
{% if languages %} - -
-
+
+
+
+ {{language.name}} - + {% endfor %} -
+
- -
-
+
+
+ {{language.name}} - + {% endfor %} -
-
- {% endif%} - -
-
- {% for extension in extensions %} - - {% endfor %} +
- -
-
+ {% endif%} +
+
+
+ {{extension.format}} - - {% endfor %} -
+ + {% endfor %} + +
+
+
+ +
@@ -197,10 +189,13 @@ - + +{% if not g.user.locale == 'en' %} + +{% endif %} {% endblock %} {% block header %} + {% endblock %} From d33b0587cb20954d0fe4b629e89ec0a0da134d72 Mon Sep 17 00:00:00 2001 From: Ozzieisaacs Date: Mon, 28 Dec 2020 13:44:17 +0100 Subject: [PATCH 059/255] Advanced search tags are now multiselects (#1240) --- cps/static/js/edit_books.js | 18 +++++++++++++----- cps/templates/search_form.html | 20 ++++++++++---------- cps/web.py | 6 ++++-- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/cps/static/js/edit_books.js b/cps/static/js/edit_books.js index 35515aa1..5f9154fc 100644 --- a/cps/static/js/edit_books.js +++ b/cps/static/js/edit_books.js @@ -249,18 +249,26 @@ promisePublishers.done(function() { ); }); -$("#search").on("change input.typeahead:selected", function() { +$("#search").on("change input.typeahead:selected", function(event) { + if (event.target.type == "search" && event.target.tagName == "INPUT") { + return; + } var form = $("form").serialize(); $.getJSON( getPath() + "/get_matching_tags", form, function( data ) { $(".tags_click").each(function() { - if ($.inArray(parseInt($(this).children("input").first().val(), 10), data.tags) === -1 ) { - if (!($(this).hasClass("active"))) { - $(this).addClass("disabled"); + if ($.inArray(parseInt($(this).val(), 10), data.tags) === -1) { + if(!$(this).prop("selected")) { + $(this).prop("disabled", true); } } else { - $(this).removeClass("disabled"); + $(this).prop("disabled", false); } }); + $("#include_tag option:selected").each(function () { + $("#exclude_tag").find("[value="+$(this).val()+"]").prop("disabled", true); + }); + $('#include_tag').selectpicker("refresh"); + $('#exclude_tag').selectpicker("refresh"); }); }); diff --git a/cps/templates/search_form.html b/cps/templates/search_form.html index e39cf661..e61fe067 100644 --- a/cps/templates/search_form.html +++ b/cps/templates/search_form.html @@ -42,17 +42,17 @@
- {% for tag in tags %} - + {% endfor %}
- {% for tag in tags %} - + {% endfor %}
@@ -60,7 +60,7 @@
- {% for serie in series %} {% endfor %} @@ -68,7 +68,7 @@
- {% for serie in series %} {% endfor %} @@ -79,7 +79,7 @@
- {% for language in languages %} {% endfor %} @@ -87,7 +87,7 @@
- {% for language in languages %} {% endfor %} @@ -98,7 +98,7 @@
- {% for extension in extensions %} {% endfor %} @@ -106,7 +106,7 @@
- {% for extension in extensions %} {% endfor %} diff --git a/cps/web.py b/cps/web.py index 21bc41a0..6d993e29 100644 --- a/cps/web.py +++ b/cps/web.py @@ -335,8 +335,6 @@ def get_matching_tags(): title_input = request.args.get('book_title') or '' include_tag_inputs = request.args.getlist('include_tag') or '' exclude_tag_inputs = request.args.getlist('exclude_tag') or '' - # include_extension_inputs = request.args.getlist('include_extension') or '' - # exclude_extension_inputs = request.args.getlist('exclude_extension') or '' q = q.filter(db.Books.authors.any(func.lower(db.Authors.name).ilike("%" + author_input + "%")), func.lower(db.Books.title).ilike("%" + title_input + "%")) if len(include_tag_inputs) > 0: @@ -1067,8 +1065,12 @@ def render_adv_search_results(term, offset=None, order=None, limit=None): pub_start = u"" tag_names = calibre_db.session.query(db.Tags).filter(db.Tags.id.in_(include_tag_inputs)).all() searchterm.extend(tag.name for tag in tag_names) + tag_names = calibre_db.session.query(db.Tags).filter(db.Tags.id.in_(exclude_tag_inputs)).all() + searchterm.extend(tag.name for tag in tag_names) serie_names = calibre_db.session.query(db.Series).filter(db.Series.id.in_(include_series_inputs)).all() searchterm.extend(serie.name for serie in serie_names) + serie_names = calibre_db.session.query(db.Series).filter(db.Series.id.in_(exclude_series_inputs)).all() + searchterm.extend(serie.name for serie in serie_names) language_names = calibre_db.session.query(db.Languages).\ filter(db.Languages.id.in_(include_languages_inputs)).all() if language_names: From bde792101680b706ab79a6f7ffbf95c577b69e9d Mon Sep 17 00:00:00 2001 From: Ozzieisaacs Date: Wed, 30 Dec 2020 10:05:15 +0100 Subject: [PATCH 060/255] Fix modal path id for calibre db filepicker Fix SyncToken last-Book-id missing --- cps/services/SyncToken.py | 2 ++ cps/templates/config_edit.html | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cps/services/SyncToken.py b/cps/services/SyncToken.py index 4ad5fa2c..26eb396c 100644 --- a/cps/services/SyncToken.py +++ b/cps/services/SyncToken.py @@ -144,6 +144,8 @@ class SyncToken: except TypeError: log.error("SyncToken timestamps don't parse to a datetime.") return SyncToken(raw_kobo_store_token=raw_kobo_store_token) + except KeyError: + books_last_id = -1 return SyncToken( raw_kobo_store_token=raw_kobo_store_token, diff --git a/cps/templates/config_edit.html b/cps/templates/config_edit.html index cf3c7bcd..ba8d4f9e 100644 --- a/cps/templates/config_edit.html +++ b/cps/templates/config_edit.html @@ -20,7 +20,7 @@ {% if filepicker %} - + {% endif %}
From b35ecddde37b8731da6eb428576f3a67ca3a2169 Mon Sep 17 00:00:00 2001 From: Ozzieisaacs Date: Thu, 31 Dec 2020 09:54:40 +0100 Subject: [PATCH 061/255] Added Id on Filechooser dialog for testability --- cps/templates/modal_dialogs.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cps/templates/modal_dialogs.html b/cps/templates/modal_dialogs.html index da83649a..da00834c 100644 --- a/cps/templates/modal_dialogs.html +++ b/cps/templates/modal_dialogs.html @@ -96,7 +96,7 @@
From 7849f2fb4b774b1b6a6d8a7fc43d884f877e317d Mon Sep 17 00:00:00 2001 From: Ozzieisaacs Date: Thu, 31 Dec 2020 15:08:56 +0100 Subject: [PATCH 062/255] Remove relate to referrer for tag/custom column allow / deny dialog --- cps/admin.py | 67 +++++++++++++++++------------------- cps/static/js/table.js | 22 ++++++------ cps/templates/user_edit.html | 5 +-- 3 files changed, 46 insertions(+), 48 deletions(-) diff --git a/cps/admin.py b/cps/admin.py index 531d855d..65327e1a 100644 --- a/cps/admin.py +++ b/cps/admin.py @@ -250,10 +250,11 @@ def list_domain(allow): response.headers["Content-Type"] = "application/json; charset=utf-8" return response -@admi.route("/ajax/editrestriction/", methods=['POST']) +@admi.route("/ajax/editrestriction/", defaults={"user":0}, methods=['POST']) +@admi.route("/ajax/editrestriction//", methods=['POST']) @login_required @admin_required -def edit_restriction(res_type): +def edit_restriction(res_type, user): element = request.form.to_dict() if element['id'].startswith('a'): if res_type == 0: # Tags as template @@ -267,8 +268,8 @@ def edit_restriction(res_type): config.config_allowed_column_value = ','.join(elementlist) config.save() if res_type == 2: # Tags per user - usr_id = os.path.split(request.referrer)[-1] - if usr_id.isdigit() == True: + usr_id = user + if isinstance(usr_id, int): usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first() else: usr = current_user @@ -277,8 +278,8 @@ def edit_restriction(res_type): usr.allowed_tags = ','.join(elementlist) ub.session.commit() if res_type == 3: # CColumn per user - usr_id = os.path.split(request.referrer)[-1] - if usr_id.isdigit() == True: + usr_id = user + if isinstance(usr_id, int): usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first() else: usr = current_user @@ -298,8 +299,8 @@ def edit_restriction(res_type): config.config_denied_column_value = ','.join(elementlist) config.save() if res_type == 2: # Tags per user - usr_id = os.path.split(request.referrer)[-1] - if usr_id.isdigit() == True: + usr_id = user + if isinstance(usr_id, int): usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first() else: usr = current_user @@ -308,8 +309,8 @@ def edit_restriction(res_type): usr.denied_tags = ','.join(elementlist) ub.session.commit() if res_type == 3: # CColumn per user - usr_id = os.path.split(request.referrer)[-1] - if usr_id.isdigit() == True: + usr_id = user + if isinstance(usr_id, int): usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first() else: usr = current_user @@ -335,10 +336,11 @@ def restriction_deletion(element, list_func): return ','.join(elementlist) -@admi.route("/ajax/addrestriction/", methods=['POST']) +@admi.route("/ajax/addrestriction/", defaults={"user_id":0}, methods=['POST']) +@admi.route("/ajax/addrestriction//", methods=['POST']) @login_required @admin_required -def add_restriction(res_type): +def add_restriction(res_type, user_id): element = request.form.to_dict() if res_type == 0: # Tags as template if 'submit_allow' in element: @@ -355,9 +357,8 @@ def add_restriction(res_type): config.config_denied_column_value = restriction_addition(element, config.list_allowed_column_values) config.save() if res_type == 2: # Tags per user - usr_id = os.path.split(request.referrer)[-1] - if usr_id.isdigit() == True: - usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first() + if isinstance(user_id, int): + usr = ub.session.query(ub.User).filter(ub.User.id == int(user_id)).first() else: usr = current_user if 'submit_allow' in element: @@ -367,9 +368,8 @@ def add_restriction(res_type): usr.denied_tags = restriction_addition(element, usr.list_denied_tags) ub.session.commit() if res_type == 3: # CustomC per user - usr_id = os.path.split(request.referrer)[-1] - if usr_id.isdigit() == True: - usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first() + if isinstance(user_id, int): + usr = ub.session.query(ub.User).filter(ub.User.id == int(user_id)).first() else: usr = current_user if 'submit_allow' in element: @@ -380,10 +380,11 @@ def add_restriction(res_type): ub.session.commit() return "" -@admi.route("/ajax/deleterestriction/", methods=['POST']) +@admi.route("/ajax/deleterestriction/", defaults={"user_id":0}, methods=['POST']) +@admi.route("/ajax/deleterestriction//", methods=['POST']) @login_required @admin_required -def delete_restriction(res_type): +def delete_restriction(res_type, user_id): element = request.form.to_dict() if res_type == 0: # Tags as template if element['id'].startswith('a'): @@ -400,9 +401,8 @@ def delete_restriction(res_type): config.config_denied_column_value = restriction_deletion(element, config.list_denied_column_values) config.save() elif res_type == 2: # Tags per user - usr_id = os.path.split(request.referrer)[-1] - if usr_id.isdigit() == True: - usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first() + if isinstance(user_id, int): + usr = ub.session.query(ub.User).filter(ub.User.id == int(user_id)).first() else: usr = current_user if element['id'].startswith('a'): @@ -412,9 +412,8 @@ def delete_restriction(res_type): usr.denied_tags = restriction_deletion(element, usr.list_denied_tags) ub.session.commit() elif res_type == 3: # Columns per user - usr_id = os.path.split(request.referrer)[-1] - if usr_id.isdigit() == True: # select current user if admins are editing their own rights - usr = ub.session.query(ub.User).filter(ub.User.id == int(usr_id)).first() + if isinstance(user_id, int): + usr = ub.session.query(ub.User).filter(ub.User.id == int(user_id)).first() else: usr = current_user if element['id'].startswith('a'): @@ -425,11 +424,11 @@ def delete_restriction(res_type): ub.session.commit() return "" - -@admi.route("/ajax/listrestriction/") +@admi.route("/ajax/listrestriction/", defaults={"user_id":0}) +@admi.route("/ajax/listrestriction//") @login_required @admin_required -def list_restriction(res_type): +def list_restriction(res_type, user_id): if res_type == 0: # Tags as template restrict = [{'Element': x, 'type':_('Deny'), 'id': 'd'+str(i) } for i,x in enumerate(config.list_denied_tags()) if x != '' ] @@ -443,9 +442,8 @@ def list_restriction(res_type): for i,x in enumerate(config.list_allowed_column_values()) if x != ''] json_dumps = restrict + allow elif res_type == 2: # Tags per user - usr_id = os.path.split(request.referrer)[-1] - if usr_id.isdigit() == True: - usr = ub.session.query(ub.User).filter(ub.User.id == usr_id).first() + if isinstance(user_id, int): + usr = ub.session.query(ub.User).filter(ub.User.id == user_id).first() else: usr = current_user restrict = [{'Element': x, 'type':_('Deny'), 'id': 'd'+str(i) } @@ -454,9 +452,8 @@ def list_restriction(res_type): for i,x in enumerate(usr.list_allowed_tags()) if x != ''] json_dumps = restrict + allow elif res_type == 3: # CustomC per user - usr_id = os.path.split(request.referrer)[-1] - if usr_id.isdigit() == True: - usr = ub.session.query(ub.User).filter(ub.User.id==usr_id).first() + if isinstance(user_id, int): + usr = ub.session.query(ub.User).filter(ub.User.id==user_id).first() else: usr = current_user restrict = [{'Element': x, 'type':_('Deny'), 'id': 'd'+str(i) } diff --git a/cps/static/js/table.js b/cps/static/js/table.js index 62f7e220..16814dd2 100644 --- a/cps/static/js/table.js +++ b/cps/static/js/table.js @@ -253,14 +253,14 @@ $(function() { $("#h3").addClass("hidden"); $("#h4").addClass("hidden"); }); - function startTable(type) { + function startTable(type, user_id) { var pathname = document.getElementsByTagName("script"), src = pathname[pathname.length - 1].src; var path = src.substring(0, src.lastIndexOf("/")); $("#restrict-elements-table").bootstrapTable({ formatNoMatches: function () { return ""; }, - url: path + "/../../ajax/listrestriction/" + type, + url: path + "/../../ajax/listrestriction/" + type + "/" + user_id, rowStyle: function(row) { // console.log('Reihe :' + row + " Index :" + index); if (row.id.charAt(0) === "a") { @@ -274,13 +274,13 @@ $(function() { $.ajax ({ type: "Post", data: "id=" + row.id + "&type=" + row.type + "&Element=" + encodeURIComponent(row.Element), - url: path + "/../../ajax/deleterestriction/" + type, + url: path + "/../../ajax/deleterestriction/" + type + "/" + user_id, async: true, timeout: 900, success:function() { $.ajax({ method:"get", - url: path + "/../../ajax/listrestriction/" + type, + url: path + "/../../ajax/listrestriction/" + type + "/" + user_id, async: true, timeout: 900, success:function(data) { @@ -296,7 +296,7 @@ $(function() { $("#restrict-elements-table").removeClass("table-hover"); $("#restrict-elements-table").on("editable-save.bs.table", function (e, field, row) { $.ajax({ - url: path + "/../../ajax/editrestriction/" + type, + url: path + "/../../ajax/editrestriction/" + type + "/" + user_id, type: "Post", data: row }); @@ -304,13 +304,13 @@ $(function() { $("[id^=submit_]").click(function() { $(this)[0].blur(); $.ajax({ - url: path + "/../../ajax/addrestriction/" + type, + url: path + "/../../ajax/addrestriction/" + type + "/" + user_id, type: "Post", data: $(this).closest("form").serialize() + "&" + $(this)[0].name + "=", success: function () { $.ajax ({ method:"get", - url: path + "/../../ajax/listrestriction/" + type, + url: path + "/../../ajax/listrestriction/" + type + "/" + user_id, async: true, timeout: 900, success:function(data) { @@ -323,21 +323,21 @@ $(function() { }); } $("#get_column_values").on("click", function() { - startTable(1); + startTable(1, 0); $("#h2").removeClass("hidden"); }); $("#get_tags").on("click", function() { - startTable(0); + startTable(0, 0); $("#h1").removeClass("hidden"); }); $("#get_user_column_values").on("click", function() { - startTable(3); + startTable(3, $(this).data('id')); $("#h4").removeClass("hidden"); }); $("#get_user_tags").on("click", function() { - startTable(2); + startTable(2, $(this).data('id')); $(this)[0].blur(); $("#h3").removeClass("hidden"); }); diff --git a/cps/templates/user_edit.html b/cps/templates/user_edit.html index 9a186eb0..114dd163 100644 --- a/cps/templates/user_edit.html +++ b/cps/templates/user_edit.html @@ -11,6 +11,7 @@
{% endif %}
+
@@ -82,8 +83,8 @@
{% if ( g.user and g.user.role_admin() and not new_user ) %} - {{_('Add Allowed/Denied Tags')}} - {{_('Add allowed/Denied Custom Column Values')}} + {{_('Add Allowed/Denied Tags')}} + {{_('Add allowed/Denied Custom Column Values')}} {% endif %}
From 9b5011485285575b4d12e2aac7e7e6d0944a4aa7 Mon Sep 17 00:00:00 2001 From: OzzieIsaacs Date: Sat, 2 Jan 2021 07:51:48 +0100 Subject: [PATCH 063/255] Fixes from testrun --- cps/render_template.py | 2 +- cps/web.py | 5 +- test/Calibre-Web TestSummary_Linux.html | 9063 +++-------------------- 3 files changed, 1188 insertions(+), 7882 deletions(-) diff --git a/cps/render_template.py b/cps/render_template.py index fb0b5067..16fdab13 100644 --- a/cps/render_template.py +++ b/cps/render_template.py @@ -104,7 +104,7 @@ def get_readbooks_ids(): readBooks = calibre_db.session.query(db.cc_classes[config.config_read_column])\ .filter(db.cc_classes[config.config_read_column].value == True).all() return frozenset([x.book for x in readBooks]) - except KeyError: + except (KeyError, AttributeError): log.error("Custom Column No.%d is not existing in calibre database", config.config_read_column) return [] diff --git a/cps/web.py b/cps/web.py index 6d993e29..8a52f97a 100644 --- a/cps/web.py +++ b/cps/web.py @@ -616,13 +616,12 @@ def render_read_books(page, are_read, as_xml=False, order=None): db_filter = and_(ub.ReadBook.user_id == int(current_user.id), ub.ReadBook.read_status == ub.ReadBook.STATUS_FINISHED) else: - db_filter = and_(ub.ReadBook.user_id == int(current_user.id), - coalesce(ub.ReadBook.read_status, 0) != ub.ReadBook.STATUS_FINISHED) + db_filter = coalesce(ub.ReadBook.read_status, 0) != ub.ReadBook.STATUS_FINISHED entries, random, pagination = calibre_db.fill_indexpage(page, 0, db.Books, db_filter, order, - ub.ReadBook, db.Books.id==ub.ReadBook.book_id) + ub.ReadBook, db.Books.id == ub.ReadBook.book_id) else: try: if are_read: diff --git a/test/Calibre-Web TestSummary_Linux.html b/test/Calibre-Web TestSummary_Linux.html index dde602ab..a2fbfe1a 100644 --- a/test/Calibre-Web TestSummary_Linux.html +++ b/test/Calibre-Web TestSummary_Linux.html @@ -37,20 +37,20 @@
-

Start Time: 2020-12-12 12:19:43

+

Start Time: 2021-01-01 20:50:20

-

Stop Time: 2020-12-12 14:23:09

+

Stop Time: 2021-01-02 02:07:39

-

Duration: 1h 33 min

+

Duration: 4h 51 min

@@ -234,44 +234,82 @@ - - _ErrorHolder - 29 + + TestCli + 8 + 7 0 0 - 29 - 0 + 1 - Detail + Detail - + -
tearDownClass (test_anonymous)
+
TestCli - test_already_started
+ + PASS + + + + + + +
TestCli - test_bind_to_single_interface
+ + PASS + + + + + + +
TestCli - test_cli_SSL_files
+ + PASS + + + + + + +
TestCli - test_cli_different_folder
+ + PASS + + + + + + +
TestCli - test_cli_different_settings_database
+ + PASS + + + + + + +
TestCli - test_cli_gdrive_location
- ERROR + SKIP
-