diff --git a/README.md b/README.md index bddc4257..0fc6447d 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ Please note that running the above install command can fail on some versions of ## Requirements -python 3.x+ +python 3.5+ Optionally, to enable on-the-fly conversion from one ebook format to another when using the send-to-kindle feature, or during editing of ebooks metadata: diff --git a/cps.py b/cps.py index 46eb1440..e4b1ede8 100755 --- a/cps.py +++ b/cps.py @@ -42,6 +42,7 @@ from cps.admin import admi from cps.gdrive import gdrive from cps.editbooks import editbook from cps.remotelogin import remotelogin +from cps.search_metadata import meta from cps.error_handler import init_errorhandler try: @@ -70,6 +71,7 @@ def main(): app.register_blueprint(shelf) app.register_blueprint(admi) app.register_blueprint(remotelogin) + app.register_blueprint(meta) app.register_blueprint(gdrive) app.register_blueprint(editbook) if kobo_available: diff --git a/cps/__init__.py b/cps/__init__.py index 3b100907..517358c5 100644 --- a/cps/__init__.py +++ b/cps/__init__.py @@ -139,7 +139,6 @@ def create_app(): def get_locale(): # if a user is logged in, use the locale from the user settings user = getattr(g, 'user', None) - # user = None if user is not None and hasattr(user, "locale"): if user.name != 'Guest': # if the account is the guest account bypass the config lang settings return user.locale @@ -160,6 +159,7 @@ def get_timezone(): user = getattr(g, 'user', None) return user.timezone if user else None + from .updater import Updater updater_thread = Updater() updater_thread.start() diff --git a/cps/admin.py b/cps/admin.py index 7d2a1e8b..0a0b362d 100644 --- a/cps/admin.py +++ b/cps/admin.py @@ -1208,6 +1208,7 @@ def _configuration_update_helper(): return _configuration_result(_('Certfile Location is not Valid, Please Enter Correct Path')) _config_checkbox_int(to_save, "config_uploading") + _config_checkbox_int(to_save, "config_unicode_filename") # Reboot on config_anonbrowse with enabled ldap, as decoraters are changed in this case reboot_required |= (_config_checkbox_int(to_save, "config_anonbrowse") and config.config_login_type == constants.LOGIN_LDAP) @@ -1310,6 +1311,8 @@ def _db_configuration_result(error_flash=None, gdrive_error=None): log.error(error_flash) config.load() flash(error_flash, category="error") + elif request.method == "POST" and not gdrive_error: + flash(_("Database Settings updated"), category="success") return render_title_template("config_db.html", config=config, @@ -1682,7 +1685,8 @@ def get_updater_status(): "9": _(u'Update failed:') + u' ' + _(u'Connection error'), "10": _(u'Update failed:') + u' ' + _(u'Timeout while establishing connection'), "11": _(u'Update failed:') + u' ' + _(u'General error'), - "12": _(u'Update failed:') + u' ' + _(u'Update File Could Not be Saved in Temp Dir') + "12": _(u'Update failed:') + u' ' + _(u'Update file could not be saved in temp dir'), + "13": _(u'Update failed:') + u' ' + _(u'Files could not be replaced during update') } status['text'] = text updater_thread.status = 0 diff --git a/cps/config_sql.py b/cps/config_sql.py index f3e82e7e..88107f9b 100644 --- a/cps/config_sql.py +++ b/cps/config_sql.py @@ -133,6 +133,7 @@ class _Settings(_Base): config_calibre = Column(String) config_rarfile_location = Column(String, default=None) config_upload_formats = Column(String, default=','.join(constants.EXTENSIONS_UPLOAD)) + config_unicode_filename =Column(Boolean, default=False) config_updatechannel = Column(Integer, default=constants.UPDATE_STABLE) diff --git a/cps/constants.py b/cps/constants.py index 5aaf6cc8..bfdee6da 100644 --- a/cps/constants.py +++ b/cps/constants.py @@ -157,7 +157,7 @@ def selected_roles(dictionary): BookMeta = namedtuple('BookMeta', 'file_path, extension, title, author, cover, description, tags, series, ' 'series_id, languages, publisher') -STABLE_VERSION = {'version': '0.6.13'} +STABLE_VERSION = {'version': '0.6.14 Beta'} NIGHTLY_VERSION = {} NIGHTLY_VERSION[0] = '$Format:%H$' diff --git a/cps/helper.py b/cps/helper.py index d3e0dbbb..f7b72a8d 100644 --- a/cps/helper.py +++ b/cps/helper.py @@ -234,16 +234,14 @@ def get_valid_filename(value, replace_whitespace=True): value = value[:-1]+u'_' value = value.replace("/", "_").replace(":", "_").strip('\0') if use_unidecode: - value = (unidecode.unidecode(value)) + if not config.config_unicode_filename: + value = (unidecode.unidecode(value)) else: value = value.replace(u'§', u'SS') value = value.replace(u'ß', u'ss') value = unicodedata.normalize('NFKD', value) re_slugify = re.compile(r'[\W\s-]', re.UNICODE) - if isinstance(value, str): # Python3 str, Python2 unicode - value = re_slugify.sub('', value) - else: - value = unicode(re_slugify.sub('', value)) + value = re_slugify.sub('', value) if replace_whitespace: # *+:\"/<>? are replaced by _ value = re.sub(r'[*+:\\\"/<>?]+', u'_', value, flags=re.U) @@ -252,10 +250,7 @@ def get_valid_filename(value, replace_whitespace=True): value = value[:128].strip() if not value: raise ValueError("Filename cannot be empty") - if sys.version_info.major == 3: - return value - else: - return value.decode('utf-8') + return value def split_authors(values): @@ -842,8 +837,8 @@ def get_download_link(book_id, book_format, client): ub.update_download(book_id, int(current_user.id)) file_name = book.title if len(book.authors) > 0: - file_name = book.authors[0].name + '_' + file_name - file_name = get_valid_filename(file_name) + file_name = file_name + ' - ' + book.authors[0].name + file_name = get_valid_filename(file_name, replace_whitespace=False) headers = Headers() headers["Content-Type"] = mimetypes.types_map.get('.' + book_format, "application/octet-stream") headers["Content-Disposition"] = "attachment; filename=%s.%s; filename*=UTF-8''%s.%s" % ( diff --git a/cps/metadata_provider/comicvine.py b/cps/metadata_provider/comicvine.py new file mode 100644 index 00000000..8f496608 --- /dev/null +++ b/cps/metadata_provider/comicvine.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- + +# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) +# Copyright (C) 2021 OzzieIsaacs +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ComicVine api document: https://comicvine.gamespot.com/api/documentation + +import requests +from cps.services.Metadata import Metadata + + +class ComicVine(Metadata): + __name__ = "ComicVine" + __id__ = "comicvine" + + def search(self, query, __): + val = list() + apikey = "57558043c53943d5d1e96a9ad425b0eb85532ee6" + if self.active: + headers = { + 'User-Agent': 'Not Evil Browser' + } + + result = requests.get("https://comicvine.gamespot.com/api/search?api_key=" + + apikey + "&resources=issue&query=" + query + "&sort=name:desc&format=json", headers=headers) + for r in result.json()['results']: + seriesTitle = r['volume'].get('name', "") + if r.get('store_date'): + dateFomers = r.get('store_date') + else: + dateFomers = r.get('date_added') + v = dict() + v['id'] = r['id'] + v['title'] = seriesTitle + " #" + r.get('issue_number', "0") + " - " + ( r.get('name', "") or "") + v['authors'] = r.get('authors', []) + v['description'] = r.get('description', "") + v['publisher'] = "" + v['publishedDate'] = dateFomers + v['tags'] = ["Comics", seriesTitle] + v['rating'] = 0 + v['series'] = seriesTitle + v['cover'] = r['image'].get('original_url') + v['source'] = { + "id": self.__id__, + "description": "ComicVine Books", + "link": "https://comicvine.gamespot.com/" + } + v['url'] = r.get('site_detail_url', "") + val.append(v) + return val + + diff --git a/cps/metadata_provider/google.py b/cps/metadata_provider/google.py new file mode 100644 index 00000000..f3d02d8e --- /dev/null +++ b/cps/metadata_provider/google.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- + +# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) +# Copyright (C) 2021 OzzieIsaacs +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Google Books api document: https://developers.google.com/books/docs/v1/using + + +import requests +from cps.services.Metadata import Metadata + +class Google(Metadata): + __name__ = "Google" + __id__ = "google" + + def search(self, query, __): + if self.active: + val = list() + result = requests.get("https://www.googleapis.com/books/v1/volumes?q="+query.replace(" ","+")) + for r in result.json()['items']: + v = dict() + v['id'] = r['id'] + v['title'] = r['volumeInfo']['title'] + v['authors'] = r['volumeInfo'].get('authors', []) + v['description'] = r['volumeInfo'].get('description', "") + v['publisher'] = r['volumeInfo'].get('publisher', "") + v['publishedDate'] = r['volumeInfo'].get('publishedDate', "") + v['tags'] = r['volumeInfo'].get('categories', []) + v['rating'] = r['volumeInfo'].get('averageRating', 0) + if r['volumeInfo'].get('imageLinks'): + v['cover'] = r['volumeInfo']['imageLinks']['thumbnail'].replace("http://", "https://") + else: + v['cover'] = "/../../../static/generic_cover.jpg" + v['source'] = { + "id": self.__id__, + "description": "Google Books", + "link": "https://books.google.com/"} + v['url'] = "https://books.google.com/books?id=" + r['id'] + val.append(v) + return val + + diff --git a/cps/metadata_provider/scholar.py b/cps/metadata_provider/scholar.py new file mode 100644 index 00000000..6e13c768 --- /dev/null +++ b/cps/metadata_provider/scholar.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- + +# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) +# Copyright (C) 2021 OzzieIsaacs +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from scholarly import scholarly + +from cps.services.Metadata import Metadata + + +class scholar(Metadata): + __name__ = "Google Scholar" + __id__ = "googlescholar" + + def search(self, query, generic_cover=""): + val = list() + if self.active: + scholar_gen = scholarly.search_pubs(' '.join(query.split('+'))) + i = 0 + for publication in scholar_gen: + v = dict() + v['id'] = "1234" # publication['bib'].get('title') + v['title'] = publication['bib'].get('title') + v['authors'] = publication['bib'].get('author', []) + v['description'] = publication['bib'].get('abstract', "") + v['publisher'] = publication['bib'].get('venue', "") + if publication['bib'].get('pub_year'): + v['publishedDate'] = publication['bib'].get('pub_year')+"-01-01" + else: + v['publishedDate'] = "" + v['tags'] = "" + v['ratings'] = 0 + v['series'] = "" + v['cover'] = generic_cover + v['url'] = publication.get('pub_url') or publication.get('eprint_url') or "", + v['source'] = { + "id": self.__id__, + "description": "Google Scholar", + "link": "https://scholar.google.com/" + } + val.append(v) + i += 1 + if (i >= 10): + break + return val + + + diff --git a/cps/search_metadata.py b/cps/search_metadata.py new file mode 100644 index 00000000..72e77cdd --- /dev/null +++ b/cps/search_metadata.py @@ -0,0 +1,118 @@ +# -*- coding: utf-8 -*- + +# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) +# Copyright (C) 2021 OzzieIsaacs +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from __future__ import division, print_function, unicode_literals +import os +import json +import importlib +import sys +import inspect +import datetime +import concurrent.futures + +from flask import Blueprint, request, Response, url_for +from flask_login import current_user +from flask_login import login_required +from sqlalchemy.orm.attributes import flag_modified +from sqlalchemy.exc import OperationalError, InvalidRequestError + +from . import constants, logger, ub +from cps.services.Metadata import Metadata + + +meta = Blueprint('metadata', __name__) + +log = logger.create() + +new_list = list() +meta_dir = os.path.join(constants.BASE_DIR, "cps", "metadata_provider") +modules = os.listdir(os.path.join(constants.BASE_DIR, "cps", "metadata_provider")) +for f in modules: + if os.path.isfile(os.path.join(meta_dir, f)) and not f.endswith('__init__.py'): + a = os.path.basename(f)[:-3] + try: + importlib.import_module("cps.metadata_provider." + a) + new_list.append(a) + except ImportError: + log.error("Import error for metadata source: {}".format(a)) + pass + +def list_classes(provider_list): + classes = list() + for element in provider_list: + for name, obj in inspect.getmembers(sys.modules["cps.metadata_provider." + element]): + if inspect.isclass(obj) and name != "Metadata" and issubclass(obj, Metadata): + classes.append(obj()) + return classes + +cl = list_classes(new_list) + +@meta.route("/metadata/provider") +@login_required +def metadata_provider(): + active = current_user.view_settings.get('metadata', {}) + provider = list() + for c in cl: + ac = active.get(c.__id__, True) + provider.append({"name": c.__name__, "active": ac, "initial": ac, "id": c.__id__}) + return Response(json.dumps(provider), mimetype='application/json') + +@meta.route("/metadata/provider", methods=['POST']) +@meta.route("/metadata/provider/", methods=['POST']) +@login_required +def metadata_change_active_provider(prov_name): + new_state = request.get_json() + active = current_user.view_settings.get('metadata', {}) + active[new_state['id']] = new_state['value'] + current_user.view_settings['metadata'] = active + try: + try: + flag_modified(current_user, "view_settings") + except AttributeError: + pass + ub.session.commit() + except (InvalidRequestError, OperationalError): + log.error("Invalid request received: {}".format(request)) + return "Invalid request", 400 + if "initial" in new_state and prov_name: + for c in cl: + if c.__id__ == prov_name: + data = c.search(new_state.get('query', "")) + break + return Response(json.dumps(data), mimetype='application/json') + return "" + +@meta.route("/metadata/search", methods=['POST']) +@login_required +def metadata_search(): + query = request.form.to_dict().get('query') + data = list() + active = current_user.view_settings.get('metadata', {}) + if query: + static_cover = url_for('static', filename='generic_cover.jpg') + with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: + meta = {executor.submit(c.search, query, static_cover): c for c in cl if active.get(c.__id__, True)} + for future in concurrent.futures.as_completed(meta): + data.extend(future.result()) + return Response(json.dumps(data), mimetype='application/json') + + + + + + diff --git a/cps/services/Metadata.py b/cps/services/Metadata.py new file mode 100644 index 00000000..d6e4e7d5 --- /dev/null +++ b/cps/services/Metadata.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- + +# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) +# Copyright (C) 2021 OzzieIsaacs +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +class Metadata(): + __name__ = "Generic" + + def __init__(self): + self.active = True + + def set_status(self, state): + self.active = state diff --git a/cps/services/worker.py b/cps/services/worker.py index 1baf25fe..238c8dbf 100644 --- a/cps/services/worker.py +++ b/cps/services/worker.py @@ -205,10 +205,13 @@ class CalibreTask: # By default, we're good to clean a task if it's "Done" return self.stat in (STAT_FINISH_SUCCESS, STAT_FAIL) - @progress.setter - def progress(self, x): - # todo: throw error if outside of [0,1] - self._progress = x + '''@progress.setter + def progress(self, x): + if x > 1: + x = 1 + if x < 0: + x = 0 + self._progress = x''' def _handleError(self, error_message): self.stat = STAT_FAIL diff --git a/cps/static/css/style.css b/cps/static/css/style.css index 5b7715fd..2bbdf370 100644 --- a/cps/static/css/style.css +++ b/cps/static/css/style.css @@ -123,6 +123,10 @@ table .bg-dark-danger a { color: #fff; } flex-wrap: wrap; } +.row-fluid.text-center { + margin-top: -20px; +} + .container-fluid img { display: block; max-width: 100%; @@ -166,6 +170,10 @@ table .bg-dark-danger a { color: #fff; } box-shadow: 0 5px 8px -6px #777; } +.datepicker.form-control { + position: static; +} + .container-fluid .book .cover span img { position: relative; top: 0; @@ -322,7 +330,7 @@ table .bg-dark-danger:hover { background-color: #c9302c; } table .bg-primary:hover { background-color: #1c5484; } .block-label { display: block; } -.fake-input { +.form-control.fake-input { position: absolute; pointer-events: none; top: 0; diff --git a/cps/static/js/details.js b/cps/static/js/details.js index 951e404a..3487b901 100644 --- a/cps/static/js/details.js +++ b/cps/static/js/details.js @@ -30,7 +30,7 @@ $("#have_read_cb").on("change", function() { $("#flash_danger").remove(); if (!jQuery.isEmptyObject(data)) { data.forEach(function (item) { - $(".navbar").after('
' + + $(".navbar").after('
' + '
' + item.message + '
' + '
'); }); diff --git a/cps/static/js/edit_books.js b/cps/static/js/edit_books.js index 7c812ae9..00c971d3 100644 --- a/cps/static/js/edit_books.js +++ b/cps/static/js/edit_books.js @@ -269,3 +269,4 @@ $("#xchange").click(function () { $("#book_title").val($("#bookAuthor").val()); $("#bookAuthor").val(title); }); + diff --git a/cps/static/js/get_meta.js b/cps/static/js/get_meta.js index 19f8e929..f64be699 100644 --- a/cps/static/js/get_meta.js +++ b/cps/static/js/get_meta.js @@ -14,380 +14,134 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -/* - * Get Metadata from Douban Books api and Google Books api and ComicVine - * Google Books api document: https://developers.google.com/books/docs/v1/using - * Douban Books api document: https://developers.douban.com/wiki/?title=book_v2 (Chinese Only) - * ComicVine api document: https://comicvine.gamespot.com/api/documentation - */ -/* global _, i18nMsg, tinymce */ -var dbResults = []; -var ggResults = []; -var cvResults = []; -var gsResults = []; +/* global _, i18nMsg, tinymce, getPath */ $(function () { - var msg = i18nMsg; - var douban = "https://api.douban.com"; - var dbSearch = "/v2/book/search"; - var dbDone = 0; + var msg = i18nMsg; + var keyword = "" - var google = "https://www.googleapis.com"; - var ggSearch = "/books/v1/volumes"; - var ggDone = 0; + var templates = { + bookResult: _.template( + $("#template-book-result").html() + ) + }; - var comicvine = "https://comicvine.gamespot.com"; - var cvSearch = "/api/search/"; - var cvDone = 0; - - var googlescholar = window.location.href.split('/admin/book')[0]; - var gsSearch = "/scholarsearch/" - var gsDone = 0; - - var showFlag = 0; - - var templates = { - bookResult: _.template( - $("#template-book-result").html() - ) - }; - - function populateForm (book) { - tinymce.get("description").setContent(book.description); - var uniqueTags = []; - $.each(book.tags, function(i, el) { - if ($.inArray(el, uniqueTags) === -1) uniqueTags.push(el); - }); - - var ampSeparatedAuthors = (book.authors || []).join(" & "); - $("#bookAuthor").val(ampSeparatedAuthors); - $("#book_title").val(book.title); - $("#tags").val(uniqueTags.join(",")); - $("#rating").data("rating").setValue(Math.round(book.rating)); - if(book.cover !== null){ - $(".cover img").attr("src", book.cover); - $("#cover_url").val(book.cover); - } - $("#pubdate").val(book.publishedDate); - $("#publisher").val(book.publisher); - if (typeof book.series !== "undefined") { - $("#series").val(book.series); - } - } - - function showResult () { - showFlag++; - if (showFlag === 1) { - $("#meta-info").html("
    "); - } - if ((ggDone === 3 || (ggDone === 1 && ggResults.length === 0)) && - (dbDone === 3 || (dbDone === 1 && dbResults.length === 0)) && - (cvDone === 3 || (cvDone === 1 && cvResults.length === 0)) && - (gsDone === 3 || (gsDone === 1 && gsResults.length === 0))) { - $("#meta-info").html("

    " + msg.no_result + "

    "); - return; - } - function formatDate (date) { - var d = new Date(date), - month = "" + (d.getMonth() + 1), - day = "" + d.getDate(), - year = d.getFullYear(); - - if (month.length < 2) { - month = "0" + month; - } - if (day.length < 2) { - day = "0" + day; - } - - return [year, month, day].join("-"); - } - function generateID (title) { - return title.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0).toString().substr(0,12); - } - - if (ggResults.length > 0) { - if (ggDone < 2) { - ggResults.forEach(function(result) { - var book = { - id: result.id, - title: result.volumeInfo.title, - authors: result.volumeInfo.authors || [], - description: result.volumeInfo.description || "", - publisher: result.volumeInfo.publisher || "", - publishedDate: result.volumeInfo.publishedDate || "", - tags: result.volumeInfo.categories || [], - rating: result.volumeInfo.averageRating || 0, - cover: result.volumeInfo.imageLinks ? - result.volumeInfo.imageLinks.thumbnail : location + "/../../../static/generic_cover.jpg", - url: "https://books.google.com/books?id=" + result.id, - source: { - id: "google", - description: "Google Books", - url: "https://books.google.com/" - } - }; - - var $book = $(templates.bookResult(book)); - $book.find("img").on("click", function () { - populateForm(book); - }); - - $("#book-list").append($book); + function populateForm (book) { + tinymce.get("description").setContent(book.description); + var uniqueTags = []; + $.each(book.tags, function(i, el) { + if ($.inArray(el, uniqueTags) === -1) uniqueTags.push(el); }); - ggDone = 2; - } else { - ggDone = 3; - } - } - - if (gsResults.length > 0) { - if (gsDone < 2) { - gsResults.forEach(function(result) { - var book = { - id: generateID(result.bib.title), - title: result.bib.title, - authors: result.bib.author || [], - description: result.bib.abstract || "", - publisher: result.bib.venue || "", - publishedDate: result.bib.pub_year ? result.bib.pub_year+"-01-01" : "", - tags: [], - rating: 0, - series: "", - cover: null, - url: result.pub_url || result.eprint_url || "", - source: { - id: "googlescholar", - description: "Google Scholar", - link: "https://scholar.google.com/" - } - } - var $book = $(templates.bookResult(book)); - $book.find("img").on("click", function () { - populateForm(book); - }); - - $("#book-list").append($book); - - }); - gsDone = 2; - } - else { - gsDone = 3; - } - } - - if (dbResults.length > 0) { - if (dbDone < 2) { - dbResults.forEach(function(result) { - var seriesTitle = ""; - if (result.series) { - seriesTitle = result.series.title; - } - var dateFomers = result.pubdate.split("-"); - var publishedYear = parseInt(dateFomers[0], 10); - var publishedMonth = parseInt(dateFomers[1], 10); - var publishedDate = new Date(publishedYear, publishedMonth - 1, 1); - - publishedDate = formatDate(publishedDate); - - var book = { - id: result.id, - title: result.title, - authors: result.author || [], - description: result.summary, - publisher: result.publisher || "", - publishedDate: publishedDate || "", - tags: result.tags.map(function(tag) { - return tag.title.toLowerCase().replace(/,/g, "_"); - }), - rating: result.rating.average || 0, - series: seriesTitle || "", - cover: result.image, - url: "https://book.douban.com/subject/" + result.id, - source: { - id: "douban", - description: "Douban Books", - url: "https://book.douban.com/" - } - }; - - if (book.rating > 0) { - book.rating /= 2; - } - - var $book = $(templates.bookResult(book)); - $book.find("img").on("click", function () { - populateForm(book); - }); - - $("#book-list").append($book); - }); - dbDone = 2; - } else { - dbDone = 3; - } - } - if (cvResults.length > 0) { - if (cvDone < 2) { - cvResults.forEach(function(result) { - var seriesTitle = ""; - if (result.volume.name) { - seriesTitle = result.volume.name; - } - var dateFomers = ""; - if (result.store_date) { - dateFomers = result.store_date.split("-"); - } else { - dateFomers = result.date_added.split("-"); - } - var publishedYear = parseInt(dateFomers[0], 10); - var publishedMonth = parseInt(dateFomers[1], 10); - var publishedDate = new Date(publishedYear, publishedMonth - 1, 1); - - publishedDate = formatDate(publishedDate); - - var book = { - id: result.id, - title: seriesTitle + " #" + ("00" + result.issue_number).slice(-3) + " - " + result.name, - authors: result.author || [], - description: result.description, - publisher: "", - publishedDate: publishedDate || "", - tags: ["Comics", seriesTitle], - rating: 0, - series: seriesTitle || "", - cover: result.image.original_url, - url: result.site_detail_url, - source: { - id: "comicvine", - description: "ComicVine Books", - url: "https://comicvine.gamespot.com/" - } - }; - - var $book = $(templates.bookResult(book)); - $book.find("img").on("click", function () { - populateForm(book); - }); - - $("#book-list").append($book); - }); - cvDone = 2; - } else { - cvDone = 3; - } - } - } - - function ggSearchBook (title) { - $.ajax({ - url: google + ggSearch + "?q=" + title.replace(/\s+/gm, "+"), - type: "GET", - dataType: "jsonp", - jsonp: "callback", - success: function success(data) { - if ("items" in data) { - ggResults = data.items; + var ampSeparatedAuthors = (book.authors || []).join(" & "); + $("#bookAuthor").val(ampSeparatedAuthors); + $("#book_title").val(book.title); + $("#tags").val(uniqueTags.join(",")); + $("#rating").data("rating").setValue(Math.round(book.rating)); + if(book.cover !== null){ + $(".cover img").attr("src", book.cover); + $("#cover_url").val(book.cover); + } + $("#pubdate").val(book.publishedDate); + $("#publisher").val(book.publisher); + if (typeof book.series !== "undefined") { + $("#series").val(book.series); } - }, - complete: function complete() { - ggDone = 1; - showResult(); - $("#show-google").trigger("change"); - } - }); - } - - function dbSearchBook (title) { - var apikey = "054022eaeae0b00e0fc068c0c0a2102a"; - $.ajax({ - url: douban + dbSearch + "?apikey=" + apikey + "&q=" + title + "&fields=all&count=10", - type: "GET", - dataType: "jsonp", - jsonp: "callback", - success: function success(data) { - dbResults = data.books; - }, - error: function error() { - $("#meta-info").html("

    " + msg.search_error + "!

    " + $("#meta-info")[0].innerHTML); - }, - complete: function complete() { - dbDone = 1; - showResult(); - $("#show-douban").trigger("change"); - } - }); - } - - function cvSearchBook (title) { - var apikey = "57558043c53943d5d1e96a9ad425b0eb85532ee6"; - title = encodeURIComponent(title); - $.ajax({ - url: comicvine + cvSearch + "?api_key=" + apikey + "&resources=issue&query=" + title + "&sort=name:desc&format=jsonp", - type: "GET", - dataType: "jsonp", - jsonp: "json_callback", - success: function success(data) { - cvResults = data.results; - }, - error: function error() { - $("#meta-info").html("

    " + msg.search_error + "!

    " + $("#meta-info")[0].innerHTML); - }, - complete: function complete() { - cvDone = 1; - showResult(); - $("#show-comics").trigger("change"); - } - }); - } - - function gsSearchBook (title) { - $.ajax({ - url: googlescholar + gsSearch + title.replace(/\s+/gm,'+'), - type: "GET", - dataType: "json", - success: function success(data) { - gsResults = data; - }, - complete: function complete() { - gsDone = 1; - showResult(); - $("#show-googlescholar").trigger("change"); - } - }) - } - - function doSearch (keyword) { - showFlag = 0; - dbDone = ggDone = cvDone = 0; - dbResults = []; - ggResults = []; - cvResults = []; - gsResults = []; - $("#meta-info").text(msg.loading); - if (keyword) { - dbSearchBook(keyword); - ggSearchBook(keyword); - cvSearchBook(keyword); - gsSearchBook(keyword); } - } - $("#meta-search").on("submit", function (e) { - e.preventDefault(); - var keyword = $("#keyword").val(); - if (keyword) { - doSearch(keyword); + function doSearch (keyword) { + if (keyword) { + $("#meta-info").text(msg.loading); + $.ajax({ + url: getPath() + "/metadata/search", + type: "POST", + data: {"query": keyword}, + dataType: "json", + success: function success(data) { + $("#meta-info").html("
      "); + data.forEach(function(book) { + var $book = $(templates.bookResult(book)); + $book.find("img").on("click", function () { + populateForm(book); + }); + $("#book-list").append($book); + }); + }, + error: function error() { + $("#meta-info").html("

      " + msg.search_error + "!

      " + $("#meta-info")[0].innerHTML); + }, + }); + } } - }); - $("#get_meta").click(function () { - var bookTitle = $("#book_title").val(); - if (bookTitle) { - $("#keyword").val(bookTitle); - doSearch(bookTitle); + function populate_provider() { + $("#metadata_provider").empty(); + $.ajax({ + url: getPath() + "/metadata/provider", + type: "get", + dataType: "json", + success: function success(data) { + data.forEach(function(provider) { + var checked = ""; + if (provider.active) { + checked = "checked"; + } + var $provider_button = '' + $("#metadata_provider").append($provider_button); + }); + }, + }); } - }); + $(document).on("change", ".pill", function () { + var element = $(this); + var id = element.data("control"); + var initial = element.data("initial"); + var val = element.prop('checked'); + var params = {id : id, value: val}; + if (!initial) { + params['initial'] = initial; + params['query'] = keyword; + } + $.ajax({ + method:"post", + contentType: "application/json; charset=utf-8", + dataType: "json", + url: getPath() + "/metadata/provider/" + id, + data: JSON.stringify(params), + success: function success(data) { + element.data("initial", "true"); + data.forEach(function(book) { + var $book = $(templates.bookResult(book)); + $book.find("img").on("click", function () { + populateForm(book); + }); + $("#book-list").append($book); + }); + } + }); + }); + + $("#meta-search").on("submit", function (e) { + e.preventDefault(); + keyword = $("#keyword").val(); + $('.pill').each(function(){ + // console.log($(this).data('control')); + $(this).data("initial", $(this).prop('checked')); + // console.log($(this).data('initial')); + }); + doSearch(keyword); + }); + + $("#get_meta").click(function () { + populate_provider(); + var bookTitle = $("#book_title").val(); + $("#keyword").val(bookTitle); + keyword = bookTitle; + doSearch(bookTitle); + }); + $("#metaModal").on("show.bs.modal", function(e) { + $(e.relatedTarget).one('focus', function (e) { + $(this).blur(); + }); + }); }); diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-af-ZA.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-af.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-af-ZA.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-af.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ar-SA.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ar.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ar-SA.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ar.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-bg-BG.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-bg.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-bg-BG.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-bg.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ca-ES.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ca.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ca-ES.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ca.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-cs-CZ.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-cs.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-cs-CZ.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-cs.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-da-DK.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-da.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-da-DK.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-da.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-de-DE.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-de.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-de-DE.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-de.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-el-GR.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-el.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-el-GR.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-el.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-es-ES.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-es.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-es-ES.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-es.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-et-EE.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-et.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-et-EE.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-et.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-eu-EU.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-eu.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-eu-EU.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-eu.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-fa-IR.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-fa.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-fa-IR.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-fa.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-fi-FI.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-fi.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-fi-FI.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-fi.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-fr-FR.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-fr.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-fr-FR.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-fr.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-he-IL.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-he.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-he-IL.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-he.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-hr-HR.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-hr.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-hr-HR.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-hr.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-hu-HU.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-hu.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-hu-HU.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-hu.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-id-ID.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-id.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-id-ID.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-id.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-it-IT.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-it.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-it-IT.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-it.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ja-JP.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ja.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ja-JP.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ja.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ka-GE.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ka.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ka-GE.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ka.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ko-KR.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ko.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ko-KR.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ko.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-nl-NL.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-nl.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-nl-NL.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-nl.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-pl-PL.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-pl.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-pl-PL.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-pl.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-pt-BR.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-pt_BR.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-pt-BR.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-pt_BR.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ro-RO.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ro.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ro-RO.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ro.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ru-RU.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ru.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ru-RU.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-ru.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-sk-SK.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-sk.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-sk-SK.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-sk.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-sv-SE.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-sv.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-sv-SE.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-sv.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-tr-TR.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-tr.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-tr-TR.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-tr.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-uk-UA.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-uk.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-uk-UA.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-uk.min.js diff --git a/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-zh-CN.min.js b/cps/static/js/libs/bootstrap-table/locale/bootstrap-table-zh_Hans_CN.min.js similarity index 100% rename from cps/static/js/libs/bootstrap-table/locale/bootstrap-table-zh-CN.min.js rename to cps/static/js/libs/bootstrap-table/locale/bootstrap-table-zh_Hans_CN.min.js diff --git a/cps/static/js/main.js b/cps/static/js/main.js index d8641c3e..988e3b9f 100644 --- a/cps/static/js/main.js +++ b/cps/static/js/main.js @@ -181,7 +181,7 @@ $("#delete_confirm").click(function() { if (item.format != "") { $("button[data-delete-format='"+item.format+"']").addClass('hidden'); } - $( ".navbar" ).after( '
      ' + + $( ".navbar" ).after( '
      ' + '
      '+item.message+'
      ' + '
      '); @@ -248,14 +248,13 @@ $(function() { dataType: "json", url: window.location.pathname + "/../../get_updater_status", success: function success(data) { - // console.log(data.status); $("#DialogContent").html(updateText[data.status]); if (data.status > 6) { cleanUp(); } }, error: function error() { - $("#DialogContent").html(updateText[7]); + $("#DialogContent").html(updateText[11]); cleanUp(); }, timeout: 2000 @@ -451,7 +450,6 @@ $(function() { success: function success(data) { updateText = data.text; $("#DialogContent").html(updateText[data.status]); - // console.log(data.status); updateTimerID = setInterval(updateTimer, 2000); } }); @@ -554,7 +552,7 @@ $(function() { function handle_response(data) { if (!jQuery.isEmptyObject(data)) { data.forEach(function (item) { - $(".navbar").after('
      ' + + $(".navbar").after('
      ' + '
      ' + item.message + '
      ' + '
      '); }); diff --git a/cps/static/js/table.js b/cps/static/js/table.js index 9fa28281..a55ec5d1 100644 --- a/cps/static/js/table.js +++ b/cps/static/js/table.js @@ -85,7 +85,7 @@ $(function() { method:"post", contentType: "application/json; charset=utf-8", dataType: "json", - url: window.location.pathname + "/../../ajax/mergebooks", + url: window.location.pathname + "/../ajax/mergebooks", data: JSON.stringify({"Merge_books":selections}), success: function success() { $("#books-table").bootstrapTable("refresh"); @@ -104,7 +104,7 @@ $(function() { method:"post", contentType: "application/json; charset=utf-8", dataType: "json", - url: window.location.pathname + "/../../ajax/simulatemerge", + url: window.location.pathname + "/../ajax/simulatemerge", data: JSON.stringify({"Merge_books":selections}), success: function success(booTitles) { $.each(booTitles.from, function(i, item) { @@ -121,7 +121,7 @@ $(function() { method:"post", contentType: "application/json; charset=utf-8", dataType: "json", - url: window.location.pathname + "/../../ajax/xchange", + url: window.location.pathname + "/../ajax/xchange", data: JSON.stringify({"xchange":selections}), success: function success() { $("#books-table").bootstrapTable("refresh"); @@ -161,10 +161,11 @@ $(function() { $("#books-table").bootstrapTable({ sidePagination: "server", + pageList: "[10, 25, 50, 100]", queryParams: queryParams, pagination: true, paginationLoop: false, - paginationDetailHAlign: " hidden", + paginationDetailHAlign: "right", paginationHAlign: "left", idField: "id", uniqueId: "id", @@ -187,7 +188,7 @@ $(function() { $.ajax({ method:"get", dataType: "json", - url: window.location.pathname + "/../../ajax/sort_value/" + field + "/" + row.id, + url: window.location.pathname + "/../ajax/sort_value/" + field + "/" + row.id, success: function success(data) { var key = Object.keys(data)[0]; $("#books-table").bootstrapTable("updateCellByUniqueId", { @@ -215,7 +216,7 @@ $(function() { method:"post", contentType: "application/json; charset=utf-8", dataType: "json", - url: window.location.pathname + "/../../ajax/table_settings", + url: window.location.pathname + "/../ajax/table_settings", data: "{" + st + "}", }); }, @@ -769,7 +770,7 @@ function handleListServerResponse (data) { $("#flash_danger").remove(); if (!jQuery.isEmptyObject(data)) { data.forEach(function(item) { - $(".navbar").after('
      ' + + $(".navbar").after('
      ' + '
      ' + item.message + '
      ' + '
      '); }); diff --git a/cps/templates/book_edit.html b/cps/templates/book_edit.html index 2da7b09b..78a5cdc1 100644 --- a/cps/templates/book_edit.html +++ b/cps/templates/book_edit.html @@ -111,8 +111,8 @@ {% endif %}
      - - + + @@ -156,11 +156,11 @@ {% if c.datatype == 'datetime' %}
      - 0 %} value="{% if book['custom_column_' ~ c.id][0].value %}{{ book['custom_column_' ~ c.id][0].value|formatdateinput}}{% endif %}" {% endif %}> - 0 %} value="{% if book['custom_column_' ~ c.id][0].value %}{{book['custom_column_' ~ c.id][0].value|formatdate}}{% endif %}" {% endif %}> @@ -232,7 +232,7 @@