Commit f29088e8 authored by Ozzie Isaacs's avatar Ozzie Isaacs

Merge branch 'master' into Develop

# Conflicts:
#	cps/kobo.py
parents eb227324 b009dfe4
...@@ -59,7 +59,7 @@ except ImportError: ...@@ -59,7 +59,7 @@ except ImportError:
log = logger.create() log = logger.create()
cc_exceptions = ['datetime', 'comments', 'composite', 'series'] cc_exceptions = ['composite', 'series']
cc_classes = {} cc_classes = {}
Base = declarative_base() Base = declarative_base()
...@@ -473,7 +473,7 @@ class CalibreDB(): ...@@ -473,7 +473,7 @@ class CalibreDB():
} }
books_custom_column_links[row.id] = type(str('books_custom_column_' + str(row.id) + '_link'), books_custom_column_links[row.id] = type(str('books_custom_column_' + str(row.id) + '_link'),
(Base,), dicttable) (Base,), dicttable)
else: if row.datatype in ['rating', 'text', 'enumeration']:
books_custom_column_links[row.id] = Table('books_custom_column_' + str(row.id) + '_link', books_custom_column_links[row.id] = Table('books_custom_column_' + str(row.id) + '_link',
Base.metadata, Base.metadata,
Column('book', Integer, ForeignKey('books.id'), Column('book', Integer, ForeignKey('books.id'),
...@@ -491,23 +491,25 @@ class CalibreDB(): ...@@ -491,23 +491,25 @@ class CalibreDB():
ccdict['value'] = Column(Float) ccdict['value'] = Column(Float)
elif row.datatype == 'int': elif row.datatype == 'int':
ccdict['value'] = Column(Integer) ccdict['value'] = Column(Integer)
elif row.datatype == 'datetime':
ccdict['value'] = Column(TIMESTAMP)
elif row.datatype == 'bool': elif row.datatype == 'bool':
ccdict['value'] = Column(Boolean) ccdict['value'] = Column(Boolean)
else: else:
ccdict['value'] = Column(String) ccdict['value'] = Column(String)
if row.datatype in ['float', 'int', 'bool']: if row.datatype in ['float', 'int', 'bool', 'datetime', 'comments']:
ccdict['book'] = Column(Integer, ForeignKey('books.id')) ccdict['book'] = Column(Integer, ForeignKey('books.id'))
cc_classes[row.id] = type(str('custom_column_' + str(row.id)), (Base,), ccdict) cc_classes[row.id] = type(str('custom_column_' + str(row.id)), (Base,), ccdict)
for cc_id in cc_ids: for cc_id in cc_ids:
if (cc_id[1] == 'bool') or (cc_id[1] == 'int') or (cc_id[1] == 'float'): if cc_id[1] in ['bool', 'int', 'float', 'datetime', 'comments']:
setattr(Books, setattr(Books,
'custom_column_' + str(cc_id[0]), 'custom_column_' + str(cc_id[0]),
relationship(cc_classes[cc_id[0]], relationship(cc_classes[cc_id[0]],
primaryjoin=( primaryjoin=(
Books.id == cc_classes[cc_id[0]].book), Books.id == cc_classes[cc_id[0]].book),
backref='books')) backref='books'))
elif (cc_id[1] == 'series'): elif cc_id[1] == 'series':
setattr(Books, setattr(Books,
'custom_column_' + str(cc_id[0]), 'custom_column_' + str(cc_id[0]),
relationship(books_custom_column_links[cc_id[0]], relationship(books_custom_column_links[cc_id[0]],
......
...@@ -495,12 +495,17 @@ def edit_book_publisher(publishers, book): ...@@ -495,12 +495,17 @@ def edit_book_publisher(publishers, book):
return changed return changed
def edit_cc_data_number(book_id, book, c, to_save, cc_db_value, cc_string): def edit_cc_data_value(book_id, book, c, to_save, cc_db_value, cc_string):
changed = False changed = False
if to_save[cc_string] == 'None': if to_save[cc_string] == 'None':
to_save[cc_string] = None to_save[cc_string] = None
elif c.datatype == 'bool': elif c.datatype == 'bool':
to_save[cc_string] = 1 if to_save[cc_string] == 'True' else 0 to_save[cc_string] = 1 if to_save[cc_string] == 'True' else 0
elif c.datatype == 'datetime':
try:
to_save[cc_string] = datetime.strptime(to_save[cc_string], "%Y-%m-%d")
except ValueError:
to_save[cc_string] = db.Books.DEFAULT_PUBDATE
if to_save[cc_string] != cc_db_value: if to_save[cc_string] != cc_db_value:
if cc_db_value is not None: if cc_db_value is not None:
...@@ -559,8 +564,8 @@ def edit_cc_data(book_id, book, to_save): ...@@ -559,8 +564,8 @@ def edit_cc_data(book_id, book, to_save):
else: else:
cc_db_value = None cc_db_value = None
if to_save[cc_string].strip(): if to_save[cc_string].strip():
if c.datatype == 'int' or c.datatype == 'bool' or c.datatype == 'float': if c.datatype in ['int', 'bool', 'float', "datetime", "comments"]:
changed, to_save = edit_cc_data_number(book_id, book, c, to_save, cc_db_value, cc_string) changed, to_save = edit_cc_data_value(book_id, book, c, to_save, cc_db_value, cc_string)
else: else:
changed, to_save = edit_cc_data_string(book, c, to_save, cc_db_value, cc_string) changed, to_save = edit_cc_data_string(book, c, to_save, cc_db_value, cc_string)
else: else:
......
...@@ -10,58 +10,38 @@ if ($("#description").length) { ...@@ -10,58 +10,38 @@ if ($("#description").length) {
menubar: "edit view format", menubar: "edit view format",
language: language language: language
}); });
if (!Modernizr.inputtypes.date) {
$("#pubdate").datepicker({
format: "yyyy-mm-dd",
language: language
}).on("change", function () {
// Show localized date over top of the standard YYYY-MM-DD date
var pubDate;
var results = /(\d{4})[-\/\\](\d{1,2})[-\/\\](\d{1,2})/.exec(this.value); // YYYY-MM-DD
if (results) {
pubDate = new Date(results[1], parseInt(results[2], 10) - 1, results[3]) || new Date(this.value);
$("#fake_pubdate")
.val(pubDate.toLocaleDateString(language))
.removeClass("hidden");
}
}).trigger("change");
}
} }
if (!Modernizr.inputtypes.date) { if ($(".tiny_editor").length) {
$("#Publishstart").datepicker({ tinymce.init({
format: "yyyy-mm-dd", selector: ".tiny_editor",
branding: false,
menubar: "edit view format",
language: language language: language
}).on("change", function () { });
// Show localized date over top of the standard YYYY-MM-DD date
var pubDate;
var results = /(\d{4})[-\/\\](\d{1,2})[-\/\\](\d{1,2})/.exec(this.value); // YYYY-MM-DD
if (results) {
pubDate = new Date(results[1], parseInt(results[2], 10) - 1, results[3]) || new Date(this.value);
$("#fake_Publishstart")
.val(pubDate.toLocaleDateString(language))
.removeClass("hidden");
}
}).trigger("change");
} }
if (!Modernizr.inputtypes.date) { $(".datepicker").datepicker({
$("#Publishend").datepicker({ format: "yyyy-mm-dd",
format: "yyyy-mm-dd", language: language
language: language }).on("change", function () {
}).on("change", function () { // Show localized date over top of the standard YYYY-MM-DD date
// Show localized date over top of the standard YYYY-MM-DD date var pubDate;
var pubDate; var results = /(\d{4})[-\/\\](\d{1,2})[-\/\\](\d{1,2})/.exec(this.value); // YYYY-MM-DD
var results = /(\d{4})[-\/\\](\d{1,2})[-\/\\](\d{1,2})/.exec(this.value); // YYYY-MM-DD if (results) {
if (results) { pubDate = new Date(results[1], parseInt(results[2], 10) - 1, results[3]) || new Date(this.value);
pubDate = new Date(results[1], parseInt(results[2], 10) - 1, results[3]) || new Date(this.value); $(this).next('input')
$("#fake_Publishend") .val(pubDate.toLocaleDateString(language))
.val(pubDate.toLocaleDateString(language)) .removeClass("hidden");
.removeClass("hidden"); }
} }).trigger("change");
}).trigger("change");
} $(".datepicker_delete").click(function() {
var inputs = $(this).parent().siblings('input');
$(inputs[0]).data('datepicker').clearDates();
$(inputs[1]).addClass('hidden');
});
/* /*
Takes a prefix, query typeahead callback, Bloodhound typeahead adapter Takes a prefix, query typeahead callback, Bloodhound typeahead adapter
...@@ -78,11 +58,6 @@ function prefixedSource(prefix, query, cb, bhAdapter) { ...@@ -78,11 +58,6 @@ function prefixedSource(prefix, query, cb, bhAdapter) {
}); });
} }
/*function getPath() {
var jsFileLocation = $("script[src*=edit_books]").attr("src"); // the js file path
return jsFileLocation.substr(0, jsFileLocation.search("/static/js/edit_books.js")); // the js folder path
}*/
var authors = new Bloodhound({ var authors = new Bloodhound({
name: "authors", name: "authors",
datumTokenizer: function datumTokenizer(datum) { datumTokenizer: function datumTokenizer(datum) {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*!
* context.js Library associated with > v0.9.6.2 of intention.js
* http://intentionjs.com/
*
* Copyright 2011, 2013 Dowjones and other contributors
* Released under the MIT license
*
*/
(function () {
'use strict';
var context = function($, Intention){
// create a brand spankin new intention object
var intent=new Intention(),
// placeholder for the horizontal axis
horizontal_axis,
orientation_axis;
// throttle funtion used for keeping calls to the resize responive
// callback to a minimum
function throttle(callback, interval){
var lastExec = new Date(),
timer = null;
return function(e){
var d = new Date();
if (d-lastExec < interval) {
if (timer) {
window.clearTimeout(timer);
}
var callbackWrapper = function(event){
return function(){
callback(event);
};
};
timer = window.setTimeout(callbackWrapper(e), interval);
return false;
}
callback(e);
lastExec = d;
};
}
// catchall
// =======================================================================
intent.responsive([{name:'base'}]).respond('base');
// width context?
// =======================================================================
horizontal_axis = intent.responsive({
ID:'width',
contexts: [
{name:'standard', min:840},
{name:'tablet', min:510},
{name:'mobile', min:0}],
// compare the return value of the callback to each context
// return true for a match
matcher: function(test, context){
if(typeof test === 'string'){
return test === context.name;
}
return test>=context.min;
},
// callback, return value is passed to matcher()
// to compare against current context
measure: function(arg){
if(typeof arg === 'string'){
return arg;
}
return $(window).width();
}});
// orientation context?
// =======================================================================
orientation_axis = intent.responsive({
ID:'orientation',
contexts: [{name:'portrait', rotation: 0},
{name:'landscape', rotation:90}],
matcher: function(measure, ctx){
return measure === ctx.rotation;
},
measure: function(){
var test = Math.abs(window.orientation);
if(test > 0) {
test = 180 - test;
}
return test;
}
});
// ONE TIME CHECK AXES:
// touch device?
// =======================================================================
intent.responsive({
ID:'touch',
contexts:[{name:'touch'}],
matcher: function() {
return "ontouchstart" in window;
}}).respond();
// retina display?
// =======================================================================
intent.responsive({
ID: 'highres',
// contexts
contexts:[{name:'highres'}],
// matching:
matcher: function(){
return window.devicePixelRatio > 1;
}}).respond();
// bind events to the window
$(window).on('resize', throttle(horizontal_axis.respond, 100))
.on('orientationchange', horizontal_axis.respond)
.on('orientationchange', orientation_axis.respond);
// register the current width and orientation without waiting for a window
// resize
horizontal_axis.respond();
orientation_axis.respond();
$(function(){
// at doc ready grab all of the elements in the doc
intent.elements(document);
});
// return the intention object so that it can be extended by other plugins
return intent;
};
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define('context', ['jquery', 'intention'], factory);
} else {
// Browser globals
root.intent = factory(root.jQuery, root.Intention);
}
}(this, function ($, Intention) {
return context($, Intention);
}));
}).call(this);
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
/* Function to select for custom build: form input types
/*! modernizr 3.6.0 (Custom Build) | MIT *
* https://modernizr.com/download/?-inputtypes-setclasses !*/
!function(e,t,n){function a(e,t){return typeof e===t}function s(){var e,t,n,s,i,o,c;for(var u in r)if(r.hasOwnProperty(u)){if(e=[],t=r[u],t.name&&(e.push(t.name.toLowerCase()),t.options&&t.options.aliases&&t.options.aliases.length))for(n=0;n<t.options.aliases.length;n++)e.push(t.options.aliases[n].toLowerCase());for(s=a(t.fn,"function")?t.fn():t.fn,i=0;i<e.length;i++)o=e[i],c=o.split("."),1===c.length?Modernizr[c[0]]=s:(!Modernizr[c[0]]||Modernizr[c[0]]instanceof Boolean||(Modernizr[c[0]]=new Boolean(Modernizr[c[0]])),Modernizr[c[0]][c[1]]=s),l.push((s?"":"no-")+c.join("-"))}}function i(e){var t=u.className,n=Modernizr._config.classPrefix||"";if(f&&(t=t.baseVal),Modernizr._config.enableJSClass){var a=new RegExp("(^|\\s)"+n+"no-js(\\s|$)");t=t.replace(a,"$1"+n+"js$2")}Modernizr._config.enableClasses&&(t+=" "+n+e.join(" "+n),f?u.className.baseVal=t:u.className=t)}function o(){return"function"!=typeof t.createElement?t.createElement(arguments[0]):f?t.createElementNS.call(t,"http://www.w3.org/2000/svg",arguments[0]):t.createElement.apply(t,arguments)}var l=[],r=[],c={_version:"3.6.0",_config:{classPrefix:"",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,t){var n=this;setTimeout(function(){t(n[e])},0)},addTest:function(e,t,n){r.push({name:e,fn:t,options:n})},addAsyncTest:function(e){r.push({name:null,fn:e})}},Modernizr=function(){};Modernizr.prototype=c,Modernizr=new Modernizr;var u=t.documentElement,f="svg"===u.nodeName.toLowerCase(),p=o("input"),d="search tel url email datetime date month week time datetime-local number range color".split(" "),m={};Modernizr.inputtypes=function(e){for(var a,s,i,o=e.length,l="1)",r=0;o>r;r++)p.setAttribute("type",a=e[r]),i="text"!==p.type&&"style"in p,i&&(p.value=l,p.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(a)&&p.style.WebkitAppearance!==n?(u.appendChild(p),s=t.defaultView,i=s.getComputedStyle&&"textfield"!==s.getComputedStyle(p,null).WebkitAppearance&&0!==p.offsetHeight,u.removeChild(p)):/^(search|tel)$/.test(a)||(i=/^(url|email)$/.test(a)?p.checkValidity&&p.checkValidity()===!1:p.value!=l)),m[e[r]]=!!i;return m}(d),s(),i(l),delete c.addTest,delete c.addAsyncTest;for(var h=0;h<Modernizr._q.length;h++)Modernizr._q[h]();e.Modernizr=Modernizr}(window,document);
/*! /*!
* @fileOverview TouchSwipe - jQuery Plugin * @fileOverview TouchSwipe - jQuery Plugin
* @version 1.6.18 * @version 1.6.18
......
/*! /*!
* screenfull * screenfull
* v4.2.0 - 2019-04-01 * v5.1.0 - 2020-12-24
* (c) Sindre Sorhus; MIT License * (c) Sindre Sorhus; MIT License
*/ */
!function(){"use strict";var u="undefined"!=typeof window&&void 0!==window.document?window.document:{},e="undefined"!=typeof module&&module.exports,t="undefined"!=typeof Element&&"ALLOW_KEYBOARD_INPUT"in Element,c=function(){for(var e,n=[["requestFullscreen","exitFullscreen","fullscreenElement","fullscreenEnabled","fullscreenchange","fullscreenerror"],["webkitRequestFullscreen","webkitExitFullscreen","webkitFullscreenElement","webkitFullscreenEnabled","webkitfullscreenchange","webkitfullscreenerror"],["webkitRequestFullScreen","webkitCancelFullScreen","webkitCurrentFullScreenElement","webkitCancelFullScreen","webkitfullscreenchange","webkitfullscreenerror"],["mozRequestFullScreen","mozCancelFullScreen","mozFullScreenElement","mozFullScreenEnabled","mozfullscreenchange","mozfullscreenerror"],["msRequestFullscreen","msExitFullscreen","msFullscreenElement","msFullscreenEnabled","MSFullscreenChange","MSFullscreenError"]],l=0,r=n.length,t={};l<r;l++)if((e=n[l])&&e[1]in u){for(l=0;l<e.length;l++)t[n[0][l]]=e[l];return t}return!1}(),r={change:c.fullscreenchange,error:c.fullscreenerror},n={request:function(r){return new Promise(function(e){var n=c.requestFullscreen,l=function(){this.off("change",l),e()}.bind(this);r=r||u.documentElement,/ Version\/5\.1(?:\.\d+)? Safari\//.test(navigator.userAgent)?r[n]():r[n](t?Element.ALLOW_KEYBOARD_INPUT:{}),this.on("change",l)}.bind(this))},exit:function(){return new Promise(function(e){if(this.isFullscreen){var n=function(){this.off("change",n),e()}.bind(this);u[c.exitFullscreen](),this.on("change",n)}else e()}.bind(this))},toggle:function(e){return this.isFullscreen?this.exit():this.request(e)},onchange:function(e){this.on("change",e)},onerror:function(e){this.on("error",e)},on:function(e,n){var l=r[e];l&&u.addEventListener(l,n,!1)},off:function(e,n){var l=r[e];l&&u.removeEventListener(l,n,!1)},raw:c};c?(Object.defineProperties(n,{isFullscreen:{get:function(){return Boolean(u[c.fullscreenElement])}},element:{enumerable:!0,get:function(){return u[c.fullscreenElement]}},enabled:{enumerable:!0,get:function(){return Boolean(u[c.fullscreenEnabled])}}}),e?(module.exports=n,module.exports.default=n):window.screenfull=n):e?module.exports=!1:window.screenfull=!1}(); !function(){"use strict";var c="undefined"!=typeof window&&void 0!==window.document?window.document:{},e="undefined"!=typeof module&&module.exports,s=function(){for(var e,n=[["requestFullscreen","exitFullscreen","fullscreenElement","fullscreenEnabled","fullscreenchange","fullscreenerror"],["webkitRequestFullscreen","webkitExitFullscreen","webkitFullscreenElement","webkitFullscreenEnabled","webkitfullscreenchange","webkitfullscreenerror"],["webkitRequestFullScreen","webkitCancelFullScreen","webkitCurrentFullScreenElement","webkitCancelFullScreen","webkitfullscreenchange","webkitfullscreenerror"],["mozRequestFullScreen","mozCancelFullScreen","mozFullScreenElement","mozFullScreenEnabled","mozfullscreenchange","mozfullscreenerror"],["msRequestFullscreen","msExitFullscreen","msFullscreenElement","msFullscreenEnabled","MSFullscreenChange","MSFullscreenError"]],l=0,r=n.length,t={};l<r;l++)if((e=n[l])&&e[1]in c){for(l=0;l<e.length;l++)t[n[0][l]]=e[l];return t}return!1}(),l={change:s.fullscreenchange,error:s.fullscreenerror},n={request:function(t,u){return new Promise(function(e,n){var l=function(){this.off("change",l),e()}.bind(this);this.on("change",l);var r=(t=t||c.documentElement)[s.requestFullscreen](u);r instanceof Promise&&r.then(l).catch(n)}.bind(this))},exit:function(){return new Promise(function(e,n){var l,r;this.isFullscreen?(l=function(){this.off("change",l),e()}.bind(this),this.on("change",l),(r=c[s.exitFullscreen]())instanceof Promise&&r.then(l).catch(n)):e()}.bind(this))},toggle:function(e,n){return this.isFullscreen?this.exit():this.request(e,n)},onchange:function(e){this.on("change",e)},onerror:function(e){this.on("error",e)},on:function(e,n){e=l[e];e&&c.addEventListener(e,n,!1)},off:function(e,n){e=l[e];e&&c.removeEventListener(e,n,!1)},raw:s};s?(Object.defineProperties(n,{isFullscreen:{get:function(){return Boolean(c[s.fullscreenElement])}},element:{enumerable:!0,get:function(){return c[s.fullscreenElement]}},isEnabled:{enumerable:!0,get:function(){return Boolean(c[s.fullscreenEnabled])}}}),e?module.exports=n:window.screenfull=n):e?module.exports={isEnabled:!1}:window.screenfull={isEnabled:!1}}();
\ No newline at end of file \ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -533,7 +533,7 @@ $(function() { ...@@ -533,7 +533,7 @@ $(function() {
$("#pub_new").toggleClass("disabled"); $("#pub_new").toggleClass("disabled");
$("#pub_old").toggleClass("disabled"); $("#pub_old").toggleClass("disabled");
var alternative_text = $("#toggle_order_shelf").data('alt-text'); var alternative_text = $("#toggle_order_shelf").data('alt-text');
$("#toggle_order_shelf")[0].attributes['data-alt-text'].value = $("#toggle_order_shelf").html(); $("#toggle_order_shelf").data('alt-text', $("#toggle_order_shelf").html());
$("#toggle_order_shelf").html(alternative_text); $("#toggle_order_shelf").html(alternative_text);
}); });
......
...@@ -105,12 +105,13 @@ ...@@ -105,12 +105,13 @@
</div> </div>
{% endif %} {% endif %}
{% endif %} {% endif %}
<div class="form-group"> <label for="pubdate">{{_('Published Date')}}</label>
<label for="pubdate">{{_('Published Date')}}</label> <div class="form-group input-group">
<div style="position: relative"> <input type="text" style="position: static;" class="datepicker form-control" name="pubdate" id="pubdate" value="{% if book.pubdate %}{{book.pubdate|formatdateinput}}{% endif %}">
<input type="date" class="form-control" name="pubdate" id="pubdate" value="{% if book.pubdate %}{{book.pubdate|formatdateinput}}{% endif %}"> <input type="text" style="position: absolute;" class="form-control fake-input hidden" id="fake_pubdate" value="{% if book.pubdate %}{{book.pubdate|formatdate}}{% endif %}">
<input type="text" class="form-control fake-input hidden" id="fake_pubdate" value="{% if book.pubdate %}{{book.pubdate|formatdate}}{% endif %}"> <span class="input-group-btn">
</div> <button type="button" id="pubdate_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button>
</span>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="publisher">{{_('Publisher')}}</label> <label for="publisher">{{_('Publisher')}}</label>
...@@ -149,7 +150,25 @@ ...@@ -149,7 +150,25 @@
{% endif %}> {% endif %}>
{% endif %} {% endif %}
{% if c.datatype == 'datetime' %}
<div class="input-group">
<input type="text" style="position: static;" class="datepicker form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}"
{% if book['custom_column_' ~ c.id]|length > 0 %}
value="{% if book['custom_column_' ~ c.id][0].value %}{{ book['custom_column_' ~ c.id][0].value|formatdateinput}}{% endif %}"
{% endif %}>
<input type="text" style="position: absolute;" class="fake_custom_column_{{ c.id }} form-control fake-input hidden" id="fake_pubdate"
{% if book['custom_column_' ~ c.id]|length > 0 %}
value="{% if book['custom_column_' ~ c.id][0].value %}{{book['custom_column_' ~ c.id][0].value|formatdate}}{% endif %}"
{% endif %}>
<span class="input-group-btn">
<button type="button" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button>
</span>
</div>
{% endif %}
{% if c.datatype == 'comments' %}
<textarea class="form-control tiny_editor" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}" rows="7">{% if book['custom_column_' ~ c.id]|length > 0 %}{{book['custom_column_' ~ c.id][0].value}}{%endif%}</textarea>
{% endif %}
{% if c.datatype == 'enumeration' %} {% if c.datatype == 'enumeration' %}
<select class="form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}"> <select class="form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}">
<option></option> <option></option>
......
...@@ -100,7 +100,7 @@ ...@@ -100,7 +100,7 @@
<h2 id="title">{{entry.title}}</h2> <h2 id="title">{{entry.title}}</h2>
<p class="author"> <p class="author">
{% for author in entry.authors %} {% for author in entry.authors %}
<a href="{{url_for('web.books_list', data='author', sort_param='new', book_id=author.id ) }}">{{author.name.replace('|',',')}}</a> <a href="{{url_for('web.books_list', data='author', sort_param='stored', book_id=author.id ) }}">{{author.name.replace('|',',')}}</a>
{% if not loop.last %} {% if not loop.last %}
&amp; &amp;
{% endif %} {% endif %}
...@@ -122,7 +122,7 @@ ...@@ -122,7 +122,7 @@
{% endif %} {% endif %}
{% if entry.series|length > 0 %} {% if entry.series|length > 0 %}
<p>{{_('Book')}} {{entry.series_index}} {{_('of')}} <a href="{{url_for('web.books_list', data='series', sort_param='abc', book_id=entry.series[0].id)}}">{{entry.series[0].name}}</a></p> <p>{{_('Book')}} {{entry.series_index}} {{_('of')}} <a href="{{url_for('web.books_list', data='series', sort_param='stored', book_id=entry.series[0].id)}}">{{entry.series[0].name}}</a></p>
{% endif %} {% endif %}
{% if entry.languages.__len__() > 0 %} {% if entry.languages.__len__() > 0 %}
...@@ -151,7 +151,7 @@ ...@@ -151,7 +151,7 @@
<span class="glyphicon glyphicon-tags"></span> <span class="glyphicon glyphicon-tags"></span>
{% for tag in entry.tags %} {% for tag in entry.tags %}
<a href="{{ url_for('web.books_list', data='category', sort_param='new', book_id=tag.id) }}" class="btn btn-xs btn-info" role="button">{{tag.name}}</a> <a href="{{ url_for('web.books_list', data='category', sort_param='stored', book_id=tag.id) }}" class="btn btn-xs btn-info" role="button">{{tag.name}}</a>
{%endfor%} {%endfor%}
</p> </p>
...@@ -162,7 +162,7 @@ ...@@ -162,7 +162,7 @@
<div class="publishers"> <div class="publishers">
<p> <p>
<span>{{_('Publisher')}}: <span>{{_('Publisher')}}:
<a href="{{url_for('web.books_list', data='publisher', sort_param='new', book_id=entry.publishers[0].id ) }}">{{entry.publishers[0].name}}</a> <a href="{{url_for('web.books_list', data='publisher', sort_param='stored', book_id=entry.publishers[0].id ) }}">{{entry.publishers[0].name}}</a>
</span> </span>
</p> </p>
</div> </div>
...@@ -193,14 +193,16 @@ ...@@ -193,14 +193,16 @@
{% else %} {% else %}
{% if c.datatype == 'float' %} {% if c.datatype == 'float' %}
{{ column.value|formatfloat(2) }} {{ column.value|formatfloat(2) }}
{% else %} {% elif c.datatype == 'datetime' %}
{% if c.datatype == 'series' %} {{ column.value|formatdate }}
{% elif c.datatype == 'comments' %}
{{column.value|safe}}
{% elif c.datatype == 'series' %}
{{ '%s [%s]' % (column.value, column.extra|formatfloat(2)) }} {{ '%s [%s]' % (column.value, column.extra|formatfloat(2)) }}
{% else %} {% else %}
{{ column.value }} {{ column.value }}
{% endif %} {% endif %}
{% endif %} {% endif %}
{% endif %}
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% endif %} {% endif %}
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
{% for entry in entries %} {% for entry in entries %}
<div class="col-sm-3 col-lg-2 col-xs-6 book sortable" {% if entry[0].sort %}data-name="{{entry[0].series[0].name}}"{% endif %} data-id="{% if entry[0].series[0].name %}{{entry[0].series[0].name}}{% endif %}"> <div class="col-sm-3 col-lg-2 col-xs-6 book sortable" {% if entry[0].sort %}data-name="{{entry[0].series[0].name}}"{% endif %} data-id="{% if entry[0].series[0].name %}{{entry[0].series[0].name}}{% endif %}">
<div class="cover"> <div class="cover">
<a href="{{url_for('web.books_list', data=data, sort_param='new', book_id=entry[0].series[0].id )}}"> <a href="{{url_for('web.books_list', data=data, sort_param='stored', book_id=entry[0].series[0].id )}}">
<span class="img"> <span class="img">
<img src="{{ url_for('web.get_cover', book_id=entry[0].id) }}" alt="{{ entry[0].name }}"/> <img src="{{ url_for('web.get_cover', book_id=entry[0].id) }}" alt="{{ entry[0].name }}"/>
<span class="badge">{{entry.count}}</span> <span class="badge">{{entry.count}}</span>
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
</a> </a>
</div> </div>
<div class="meta"> <div class="meta">
<a href="{{url_for('web.books_list', data=data, sort_param='new', book_id=entry[0].series[0].id )}}"> <a href="{{url_for('web.books_list', data=data, sort_param='stored', book_id=entry[0].series[0].id )}}">
<p class="title">{{entry[0].series[0].name|shortentitle}}</p> <p class="title">{{entry[0].series[0].name|shortentitle}}</p>
</a> </a>
</div> </div>
......
...@@ -193,11 +193,11 @@ ...@@ -193,11 +193,11 @@
<script src="{{ url_for('static', filename='js/libs/jquery.min.js') }}"></script> <script src="{{ url_for('static', filename='js/libs/jquery.min.js') }}"></script>
<!-- Include all compiled plugins (below), or include individual files as needed --> <!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="{{ url_for('static', filename='js/libs/bootstrap.min.js') }}"></script> <script src="{{ url_for('static', filename='js/libs/bootstrap.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/libs/underscore-min.js') }}"></script> <script src="{{ url_for('static', filename='js/libs/underscore-umd-min.js') }}"></script>
<script src="{{ url_for('static', filename='js/libs/intention.min.js') }}"></script> <script src="{{ url_for('static', filename='js/libs/intention.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/libs/context.min.js') }}"></script> <script src="{{ url_for('static', filename='js/libs/context.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/libs/plugins.js') }}"></script> <script src="{{ url_for('static', filename='js/libs/plugins.js') }}"></script>
<script src="{{ url_for('static', filename='js/libs/jquery.form.js') }}"></script> <script src="{{ url_for('static', filename='js/libs/jquery.form.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/uploadprogress.js') }}"> </script> <script src="{{ url_for('static', filename='js/uploadprogress.js') }}"> </script>
<script type="text/javascript"> <script type="text/javascript">
$(function() { $(function() {
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
{% endif %} {% endif %}
<div class="row" {% if entry[0].sort %}data-name="{{entry[0].name}}"{% endif %} data-id="{% if entry[0].sort %}{{entry[0].sort}}{% else %}{% if entry.name %}{{entry.name}}{% else %}{{entry[0].name}}{% endif %}{% endif %}"> <div class="row" {% if entry[0].sort %}data-name="{{entry[0].name}}"{% endif %} data-id="{% if entry[0].sort %}{{entry[0].sort}}{% else %}{% if entry.name %}{{entry.name}}{% else %}{{entry[0].name}}{% endif %}{% endif %}">
<div class="col-xs-2 col-sm-2 col-md-1" align="left"><span class="badge">{{entry.count}}</span></div> <div class="col-xs-2 col-sm-2 col-md-1" align="left"><span class="badge">{{entry.count}}</span></div>
<div class="col-xs-10 col-sm-10 col-md-11"><a id="list_{{loop.index0}}" href="{% if entry.format %}{{url_for('web.books_list', data=data, sort_param='new', book_id=entry.format )}}{% else %}{{url_for('web.books_list', data=data, sort_param='new', book_id=entry[0].id )}}{% endif %}"> <div class="col-xs-10 col-sm-10 col-md-11"><a id="list_{{loop.index0}}" href="{% if entry.format %}{{url_for('web.books_list', data=data, sort_param='stored', book_id=entry.format )}}{% else %}{{url_for('web.books_list', data=data, sort_param='stored', book_id=entry[0].id )}}{% endif %}">
{% if entry.name %} {% if entry.name %}
<div class="rating"> <div class="rating">
{% for number in range(entry.name) %} {% for number in range(entry.name) %}
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
{% block body %} {% block body %}
<div class="discover"> <div class="discover">
{% if entries|length < 1 %} {% if entries|length < 1 %}
<h2>{{_('No Results Found')}} {{adv_searchterm}}</h2> <h2>{{_('No Results Found')}}</h2>
<p>{{_('Search Term:')}} {{adv_searchterm}}</p> <p>{{_('Search Term:')}} {{adv_searchterm}}</p>
{% else %} {% else %}
<h2>{{result_count}} {{_('Results for:')}} {{adv_searchterm}}</h2> <h2>{{result_count}} {{_('Results for:')}} {{adv_searchterm}}</h2>
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
</button> </button>
<ul id="add-to-shelves" class="dropdown-menu" aria-labelledby="add-to-shelf"> <ul id="add-to-shelves" class="dropdown-menu" aria-labelledby="add-to-shelf">
{% for shelf in g.shelves_access %} {% for shelf in g.shelves_access %}
{% if not shelf.id in books_shelfs and ( not shelf.is_public or g.user.role_edit_shelfs() ) %} {% if not shelf.is_public or g.user.role_edit_shelfs() %}
<li><a href="{{ url_for('shelf.search_to_shelf', shelf_id=shelf.id) }}"> {{shelf.name}}{% if shelf.is_public == 1 %} {{_('(Public)')}}{% endif %}</a></li> <li><a href="{{ url_for('shelf.search_to_shelf', shelf_id=shelf.id) }}"> {{shelf.name}}{% if shelf.is_public == 1 %} {{_('(Public)')}}{% endif %}</a></li>
{% endif %} {% endif %}
{%endfor%} {%endfor%}
......
...@@ -18,16 +18,22 @@ ...@@ -18,16 +18,22 @@
<div class="row"> <div class="row">
<div class="form-group col-sm-6"> <div class="form-group col-sm-6">
<label for="Publishstart">{{_('Published Date From')}}</label> <label for="Publishstart">{{_('Published Date From')}}</label>
<div style="position: relative"> <div class="input-group">
<input type="date" class="form-control" name="Publishstart" id="Publishstart" value=""> <input type="text" style="position: static;" class="datepicker form-control" name="Publishstart" id="Publishstart" value="">
<input type="text" class="form-control fake-input hidden" id="fake_Publishstart" value=""> <input type="text" style="position: absolute;" class="form-control fake-input hidden" id="fake_Publishstart" value="">
<span class="input-group-btn">
<button type="button" id="pubstart_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button>
</span>
</div> </div>
</div> </div>
<div class="form-group col-sm-6"> <div class="form-group col-sm-6">
<label for="Publishend">{{_('Published Date To')}}</label> <label for="Publishend">{{_('Published Date To')}}</label>
<div style="position: relative"> <div class="input-group ">
<input type="date" class="form-control" name="Publishend" id="Publishend" value=""> <input type="text" style="position: static;" class="datepicker form-control" name="Publishend" id="Publishend" value="">
<input type="text" class="form-control fake-input hidden" id="fake_Publishend" value=""> <input type="text" style="position: absolute;" class="form-control fake-input hidden" id="fake_Publishend" value="">
<span class="input-group-btn">
<button type="button" id="pubend_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button>
</span>
</div> </div>
</div> </div>
</div> </div>
...@@ -167,7 +173,32 @@ ...@@ -167,7 +173,32 @@
<input type="number" step="0.01" class="form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}" value=""> <input type="number" step="0.01" class="form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}" value="">
{% endif %} {% endif %}
{% if c.datatype in ['text', 'series'] and not c.is_multiple %} {% if c.datatype == 'datetime' %}
<div class="row">
<div class="form-group col-sm-6">
<label for="{{ 'custom_column_' ~ c.id }}">{{_('From:')}}</label>
<div class="input-group">
<input type="text" style="position: static;" class="datepicker form-control" name="{{ 'custom_column_' ~ c.id }}_start" id="{{ 'custom_column_' ~ c.id }}_start" value="">
<input type="text" style="position: absolute;" class="form-control fake-input hidden" id="fake_{{ 'custom_column_' ~ c.id }}_start" value="">
<span class="input-group-btn">
<button type="button" id="pubstart_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button>
</span>
</div>
</div>
<div class="form-group col-sm-6">
<label for="{{ 'custom_column_' ~ c.id }}">{{_('To:')}}</label>
<div class="input-group ">
<input type="text" style="position: static;" class="datepicker form-control" name="{{ 'custom_column_' ~ c.id }}_end" id="{{ 'custom_column_' ~ c.id }}_end" value="">
<input type="text" style="position: absolute;" class="form-control fake-input hidden" id="fake_{{ 'custom_column_' ~ c.id }}_end" value="">
<span class="input-group-btn">
<button type="button" id="pubend_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button>
</span>
</div>
</div>
</div>
{% endif %}
{% if c.datatype in ['text', 'series', 'comments'] and not c.is_multiple %}
<input type="text" class="form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}" value=""> <input type="text" class="form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}" value="">
{% endif %} {% endif %}
......
...@@ -123,8 +123,8 @@ ...@@ -123,8 +123,8 @@
{{ user_table_row('kindle_mail', _('Enter Kindle E-mail Address'), _('Kindle E-mail'), false) }} {{ user_table_row('kindle_mail', _('Enter Kindle E-mail Address'), _('Kindle E-mail'), false) }}
{{ user_select_translations('locale', url_for('admin.table_get_locale'), _('Locale'), true) }} {{ user_select_translations('locale', url_for('admin.table_get_locale'), _('Locale'), true) }}
{{ user_select_languages('default_language', url_for('admin.table_get_default_lang'), _('Visible Book Languages'), true) }} {{ user_select_languages('default_language', url_for('admin.table_get_default_lang'), _('Visible Book Languages'), true) }}
{{ user_table_row('denied_tags', _("Edit Denied Tags"), _("Denied Tags"), false, tags) }}
{{ user_table_row('allowed_tags', _("Edit Allowed Tags"), _("Allowed Tags"), false, tags) }} {{ user_table_row('allowed_tags', _("Edit Allowed Tags"), _("Allowed Tags"), false, tags) }}
{{ user_table_row('denied_tags', _("Edit Denied Tags"), _("Denied Tags"), false, tags) }}
{{ user_table_row('allowed_column_value', _("Edit Allowed Column Values"), _("Allowed Column Values"), false, custom_values) }} {{ user_table_row('allowed_column_value', _("Edit Allowed Column Values"), _("Allowed Column Values"), false, custom_values) }}
{{ user_table_row('denied_column_value', _("Edit Denied Column Values"), _("Denied Columns Values"), false, custom_values) }} {{ user_table_row('denied_column_value', _("Edit Denied Column Values"), _("Denied Columns Values"), false, custom_values) }}
{{ user_checkbox_row("role", "admin_role", _('Admin'), visiblility, all_roles)}} {{ user_checkbox_row("role", "admin_role", _('Admin'), visiblility, all_roles)}}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -1052,9 +1052,7 @@ def reconnect(): ...@@ -1052,9 +1052,7 @@ def reconnect():
def search(): def search():
term = request.args.get("query") term = request.args.get("query")
if term: if term:
# flask_session['query'] = json.dumps(request.form)
return redirect(url_for('web.books_list', data="search", sort_param='stored', query=term)) return redirect(url_for('web.books_list', data="search", sort_param='stored', query=term))
# return render_search_results(term, 0, None, config.config_books_per_page)
else: else:
return render_title_template('search.html', return render_title_template('search.html',
searchterm="", searchterm="",
...@@ -1067,8 +1065,8 @@ def search(): ...@@ -1067,8 +1065,8 @@ def search():
@login_required_if_no_ano @login_required_if_no_ano
def advanced_search(): def advanced_search():
values = dict(request.form) values = dict(request.form)
params = ['include_tag', 'exclude_tag', 'include_serie', 'exclude_serie', 'include_shelf','exclude_shelf','include_language', params = ['include_tag', 'exclude_tag', 'include_serie', 'exclude_serie', 'include_shelf', 'exclude_shelf',
'exclude_language', 'include_extension', 'exclude_extension'] 'include_language', 'exclude_language', 'include_extension', 'exclude_extension']
for param in params: for param in params:
values[param] = list(request.form.getlist(param)) values[param] = list(request.form.getlist(param))
flask_session['query'] = json.dumps(values) flask_session['query'] = json.dumps(values)
...@@ -1077,20 +1075,30 @@ def advanced_search(): ...@@ -1077,20 +1075,30 @@ def advanced_search():
def adv_search_custom_columns(cc, term, q): def adv_search_custom_columns(cc, term, q):
for c in cc: for c in cc:
custom_query = term.get('custom_column_' + str(c.id)) if c.datatype == "datetime":
if custom_query != '' and custom_query is not None: custom_start = term.get('custom_column_' + str(c.id) + '_start')
if c.datatype == 'bool': custom_end = term.get('custom_column_' + str(c.id) + '_end')
if custom_start:
q = q.filter(getattr(db.Books, 'custom_column_' + str(c.id)).any( q = q.filter(getattr(db.Books, 'custom_column_' + str(c.id)).any(
db.cc_classes[c.id].value == (custom_query == "True"))) db.cc_classes[c.id].value >= custom_start))
elif c.datatype == 'int' or c.datatype == 'float': if custom_end:
q = q.filter(getattr(db.Books, 'custom_column_' + str(c.id)).any( q = q.filter(getattr(db.Books, 'custom_column_' + str(c.id)).any(
db.cc_classes[c.id].value == custom_query)) db.cc_classes[c.id].value <= custom_end))
elif c.datatype == 'rating': else:
q = q.filter(getattr(db.Books, 'custom_column_' + str(c.id)).any( custom_query = term.get('custom_column_' + str(c.id))
db.cc_classes[c.id].value == int(float(custom_query) * 2))) if custom_query != '' and custom_query is not None:
else: if c.datatype == 'bool':
q = q.filter(getattr(db.Books, 'custom_column_' + str(c.id)).any( q = q.filter(getattr(db.Books, 'custom_column_' + str(c.id)).any(
func.lower(db.cc_classes[c.id].value).ilike("%" + custom_query + "%"))) db.cc_classes[c.id].value == (custom_query == "True")))
elif c.datatype == 'int' or c.datatype == 'float':
q = q.filter(getattr(db.Books, 'custom_column_' + str(c.id)).any(
db.cc_classes[c.id].value == custom_query))
elif c.datatype == 'rating':
q = q.filter(getattr(db.Books, 'custom_column_' + str(c.id)).any(
db.cc_classes[c.id].value == int(float(custom_query) * 2)))
else:
q = q.filter(getattr(db.Books, 'custom_column_' + str(c.id)).any(
func.lower(db.cc_classes[c.id].value).ilike("%" + custom_query + "%")))
return q return q
...@@ -1262,10 +1270,28 @@ def render_adv_search_results(term, offset=None, order=None, limit=None): ...@@ -1262,10 +1270,28 @@ def render_adv_search_results(term, offset=None, order=None, limit=None):
searchterm = [] searchterm = []
cc_present = False cc_present = False
for c in cc: for c in cc:
if term.get('custom_column_' + str(c.id)): if c.datatype == "datetime":
searchterm.extend([(u"%s: %s" % (c.name, term.get('custom_column_' + str(c.id))))]) column_start = term.get('custom_column_' + str(c.id) + '_start')
column_end = term.get('custom_column_' + str(c.id) + '_end')
if column_start:
searchterm.extend([u"{} >= {}".format(c.name,
format_date(datetime.strptime(column_start, "%Y-%m-%d"),
format='medium',
locale=get_locale())
)])
cc_present = True
if column_end:
searchterm.extend([u"{} <= {}".format(c.name,
format_date(datetime.strptime(column_end, "%Y-%m-%d").date(),
format='medium',
locale=get_locale())
)])
cc_present = True
elif term.get('custom_column_' + str(c.id)):
searchterm.extend([(u"{}: {}".format(c.name, term.get('custom_column_' + str(c.id))))])
cc_present = True cc_present = True
if any(tags.values()) or author_name or book_title or publisher or pub_start or pub_end or rating_low \ if any(tags.values()) 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 read_status: or rating_high or description or cc_present or read_status:
searchterm, pub_start, pub_end = extend_search_term(searchterm, searchterm, pub_start, pub_end = extend_search_term(searchterm,
......
This diff is collapsed.
...@@ -2,7 +2,6 @@ Babel>=1.3, <2.9 ...@@ -2,7 +2,6 @@ Babel>=1.3, <2.9
Flask-Babel>=0.11.1,<2.1.0 Flask-Babel>=0.11.1,<2.1.0
Flask-Login>=0.3.2,<0.5.1 Flask-Login>=0.3.2,<0.5.1
Flask-Principal>=0.3.2,<0.5.1 Flask-Principal>=0.3.2,<0.5.1
singledispatch>=3.4.0.0,<3.5.0.0
backports_abc>=0.4 backports_abc>=0.4
Flask>=1.0.2,<1.2.0 Flask>=1.0.2,<1.2.0
iso-639>=0.4.5,<0.5.0 iso-639>=0.4.5,<0.5.0
......
...@@ -38,7 +38,6 @@ install_requires = ...@@ -38,7 +38,6 @@ install_requires =
Flask-Babel>=0.11.1,<2.1.0 Flask-Babel>=0.11.1,<2.1.0
Flask-Login>=0.3.2,<0.5.1 Flask-Login>=0.3.2,<0.5.1
Flask-Principal>=0.3.2,<0.5.1 Flask-Principal>=0.3.2,<0.5.1
singledispatch>=3.4.0.0,<3.5.0.0
backports_abc>=0.4 backports_abc>=0.4
Flask>=1.0.2,<1.2.0 Flask>=1.0.2,<1.2.0
iso-639>=0.4.5,<0.5.0 iso-639>=0.4.5,<0.5.0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment