Commit 6d99b9bc authored by Ethan Lin's avatar Ethan Lin Committed by GitHub

Merge pull request #1 from janeczku/master

update from janeczku/calibre-web
parents 9f65eae0 e5d881ed
...@@ -53,10 +53,9 @@ DB_ROOT = check_setting_str(CFG, 'General', 'DB_ROOT', "") ...@@ -53,10 +53,9 @@ DB_ROOT = check_setting_str(CFG, 'General', 'DB_ROOT', "")
APP_DB_ROOT = check_setting_str(CFG, 'General', 'APP_DB_ROOT', os.getcwd()) APP_DB_ROOT = check_setting_str(CFG, 'General', 'APP_DB_ROOT', os.getcwd())
MAIN_DIR = check_setting_str(CFG, 'General', 'MAIN_DIR', os.getcwd()) MAIN_DIR = check_setting_str(CFG, 'General', 'MAIN_DIR', os.getcwd())
LOG_DIR = check_setting_str(CFG, 'General', 'LOG_DIR', os.getcwd()) LOG_DIR = check_setting_str(CFG, 'General', 'LOG_DIR', os.getcwd())
PORT = check_setting_int(CFG, 'General', 'PORT', 8083) PORT = check_setting_int(CFG, 'General', 'PORT', 8083)
NEWEST_BOOKS = check_setting_str(CFG, 'General', 'NEWEST_BOOKS', 60) NEWEST_BOOKS = check_setting_str(CFG, 'General', 'NEWEST_BOOKS', 60)
RANDOM_BOOKS = check_setting_int(CFG, 'General', 'RANDOM_BOOKS', 4) RANDOM_BOOKS = check_setting_int(CFG, 'General', 'RANDOM_BOOKS', 4)
DEFAULT_LANG = check_setting_str(CFG, 'General', 'DEFAULT_LANG', "")
CheckSection('Advanced') CheckSection('Advanced')
TITLE_REGEX = check_setting_str(CFG, 'Advanced', 'TITLE_REGEX', '^(A|The|An|Der|Die|Das|Den|Ein|Eine|Einen|Dem|Des|Einem|Eines)\s+') TITLE_REGEX = check_setting_str(CFG, 'Advanced', 'TITLE_REGEX', '^(A|The|An|Der|Die|Das|Den|Ein|Eine|Einen|Dem|Des|Einem|Eines)\s+')
...@@ -73,7 +72,7 @@ if DB_ROOT == "": ...@@ -73,7 +72,7 @@ if DB_ROOT == "":
configval = {"DB_ROOT": DB_ROOT, "APP_DB_ROOT": APP_DB_ROOT, "MAIN_DIR": MAIN_DIR, "LOG_DIR": LOG_DIR, "PORT": PORT, configval = {"DB_ROOT": DB_ROOT, "APP_DB_ROOT": APP_DB_ROOT, "MAIN_DIR": MAIN_DIR, "LOG_DIR": LOG_DIR, "PORT": PORT,
"NEWEST_BOOKS": NEWEST_BOOKS, "DEVELOPMENT": DEVELOPMENT, "TITLE_REGEX": TITLE_REGEX, "NEWEST_BOOKS": NEWEST_BOOKS, "DEVELOPMENT": DEVELOPMENT, "TITLE_REGEX": TITLE_REGEX,
"PUBLIC_REG": PUBLIC_REG, "UPLOADING": UPLOADING, "ANON_BROWSE": ANON_BROWSE, "DEFAULT_LANG": DEFAULT_LANG} "PUBLIC_REG": PUBLIC_REG, "UPLOADING": UPLOADING, "ANON_BROWSE": ANON_BROWSE}
def save_config(configval): def save_config(configval):
...@@ -86,7 +85,6 @@ def save_config(configval): ...@@ -86,7 +85,6 @@ def save_config(configval):
new_config['General']['LOG_DIR'] = configval["LOG_DIR"] new_config['General']['LOG_DIR'] = configval["LOG_DIR"]
new_config['General']['PORT'] = configval["PORT"] new_config['General']['PORT'] = configval["PORT"]
new_config['General']['NEWEST_BOOKS'] = configval["NEWEST_BOOKS"] new_config['General']['NEWEST_BOOKS'] = configval["NEWEST_BOOKS"]
new_config['General']['DEFAULT_LANG'] = configval["DEFAULT_LANG"]
new_config['Advanced'] = {} new_config['Advanced'] = {}
new_config['Advanced']['TITLE_REGEX'] = configval["TITLE_REGEX"] new_config['Advanced']['TITLE_REGEX'] = configval["TITLE_REGEX"]
new_config['Advanced']['DEVELOPMENT'] = int(configval["DEVELOPMENT"]) new_config['Advanced']['DEVELOPMENT'] = int(configval["DEVELOPMENT"])
......
.annotator-adder {
width: 80px;
}
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 diff is collapsed.
@font-face {
font-family: 'Libre Baskerville';
font-style: normal;
font-weight: 400;
src: local('Libre Baskerville'), local('LibreBaskerville-Regular'), url("../fonts/LibreBaskerville-Regular.ttf") format('truetype');
}
@font-face {
font-family: 'Libre Baskerville';
font-style: normal;
font-weight: 700;
src: local('Libre Baskerville Bold'), local('LibreBaskerville-Bold'), url("../fonts/LibreBaskerville-Bold") format('truetype');
}
body{
color: #444;
line-height: 21px;
font-size: 14px;
}
h1, h2, h3, h4, h5, h6{
font-family: 'Libre Baskerville';
color: #45b29d !important;
font-size: 20px !important;
}
This diff is collapsed.
@font-face{font-family:Lato;font-style:normal;font-weight:100;src:local('Lato Hairline'),local('Lato-Hairline'),url(../fonts/Lato-Hairline.ttf) format('truetype')}@font-face{font-family:Lato;font-style:normal;font-weight:300;src:local('Lato Light'),local('Lato-Light'),url(../fonts/Lato-Light.ttf) format('truetype')}@font-face{font-family:Lato;font-style:normal;font-weight:400;src:local('Lato Regular'),local('Lato-Regular'),url(../fonts/Lato-Regular.ttf) format('truetype')}@font-face{font-family:Lato;font-style:normal;font-weight:700;src:local('Lato Bold'),local('Lato-Bold'),url(../fonts/Lato-Bold.ttf) format('truetype')}@font-face{font-family:Montserrat;font-style:normal;font-weight:400;src:local('Montserrat-Regular'),url(../fonts/Montserrat-Regular.ttf) format('truetype')}@font-face{font-family:Montserrat;font-style:normal;font-weight:700;src:local('Montserrat-Bold'),url(../fonts/Montserrat-Bold.ttf) format('truetype')}@font-face{font-family:Lobster;font-style:normal;font-weight:400;src:local('Lobster'),local('Lobster-Regular'),url(../fonts/Lobster.ttf) format('truetype')}
@font-face{font-family:'Gotham-Light';src:url('../fonts/itc/Gotham-Light.eot');src:url('../fonts/itc/Gotham-Light.woff') format('woff'),url('../fonts/itc/Gotham-Light.svg#Gotham-Light') format('svg')}@font-face{font-family:'Gotham-Medium';src:url('../fonts/itc/Gotham-Medium.eot');src:url('../fonts/itc/Gotham-Medium.woff') format('woff'),url('../fonts/itc/Gotham-Medium.svg#Gotham-Medium') format('svg')}@font-face{font-family:'Gotham-Book';src:url('../fonts/itc/Gotham-Book.eot');src:url('../fonts/itc/Gotham-Book.woff') format('woff'),url('../fonts/itc/Gotham-Book.svg#Gotham-Book') format('svg')}
.fraction-slider{
position:relative;
width:100%; height:100%;
overflow:visible;
}
.fraction-slider .slide{
display:none; width:100%; height:100%;
position:absolute;
z-index:5000;
}
.fraction-slider .active-slide{
z-index:9999;
}
.fraction-slider .fs_obj{
display:block; display:none;
position:absolute;
top:0px; left:100%;
z-index:7000;
}
.fraction-slider .fs_fixed_obj{
z-index:6000;
left:0;
}
.fraction-slider .fs_obj *{
display:inline-block;
position:relative;
top:0px; left:0px;
}
.fs_loader{
width:100%; height:400px;
background:url(images/fs.spinner.gif) center center no-repeat transparent;
}
/** CONTROLS **/
.fraction-slider .prev,
.fraction-slider .next{
display:none;
position:absolute;
width:45px; height:45px;
z-index:9999;
}
.fraction-slider .prev{
left:10px; top:48%;
background:url(images/fs.prevnext.png) 0px 0px no-repeat transparent;
}
.fraction-slider .prev:hover{
background:url(images/fs.prevnext.png) 0px -45px no-repeat transparent;
}
.fraction-slider .next{
right:10px; top:48%;
background:url(images/fs.prevnext.png) -45px 0px no-repeat transparent;
}
.fraction-slider .next:hover{
background:url(images/fs.prevnext.png) -45px -45px no-repeat transparent;
}
.fraction-slider:hover .prev,
.fraction-slider:hover .next{
display:block;
}
/** PAGER **/
.fs-pager-wrapper{
position:absolute;
left:10px; bottom:10px;
z-index:9999;
}
.fs-pager-wrapper a,
.fs-custom-pager-wrapper a{
display:inline-block;
width:14px; height:14px;
margin:0 5px 0 0;
background:url(images/fs.pager.png) 0px -14px no-repeat transparent;
}
.fs-pager-wrapper .active,
.fs-custom-pager-wrapper .active{
background:url(images/fs.pager.png) 0px 0px no-repeat transparent;
}
\ No newline at end of file
.vegas-loading {
border-radius: 10px;
background: #000;
background: rgba(0,0,0,0.7);
background: url(images/loading.gif) no-repeat center center; /* Loading Gif by http://preloaders.net/ */
height: 32px;
left: 20px;
position: fixed;
top: 20px;
width: 32px;
z-index: 0;
}
.vegas-overlay {
background: transparent url(overlays/01.png);
opacity: 0.5;
z-index: -1;
}
.vegas-background {
-ms-interpolation-mode: bicubic;
image-rendering: optimizeQuality;
max-width: none !important; /* counteracts global img modification by twitter bootstrap library */
z-index: -2;
}
.vegas-overlay,
.vegas-background {
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
\ No newline at end of file
/* Magnific Popup CSS */
.mfp-bg {
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1042;
overflow: hidden;
position: fixed;
background: #0b0b0b;
opacity: 0.8;
filter: alpha(opacity=80); }
.mfp-wrap {
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1043;
position: fixed;
outline: none !important;
-webkit-backface-visibility: hidden; }
.mfp-container {
text-align: center;
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
padding: 0 8px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box; }
.mfp-container:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle; }
.mfp-align-top .mfp-container:before {
display: none; }
.mfp-content {
position: relative;
display: inline-block;
vertical-align: middle;
margin: 0 auto;
text-align: left;
z-index: 1045; }
.mfp-inline-holder .mfp-content, .mfp-ajax-holder .mfp-content {
width: 100%;
cursor: auto; }
.mfp-ajax-cur {
cursor: progress; }
.mfp-zoom-out-cur, .mfp-zoom-out-cur .mfp-image-holder .mfp-close {
cursor: -moz-zoom-out;
cursor: -webkit-zoom-out;
cursor: zoom-out; }
.mfp-zoom {
cursor: pointer;
cursor: -webkit-zoom-in;
cursor: -moz-zoom-in;
cursor: zoom-in; }
.mfp-auto-cursor .mfp-content {
cursor: auto; }
.mfp-close, .mfp-arrow, .mfp-preloader, .mfp-counter {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none; }
.mfp-loading.mfp-figure {
display: none; }
.mfp-hide {
display: none !important; }
.mfp-preloader {
color: #cccccc;
position: absolute;
top: 50%;
width: auto;
text-align: center;
margin-top: -0.8em;
left: 8px;
right: 8px;
z-index: 1044; }
.mfp-preloader a {
color: #cccccc; }
.mfp-preloader a:hover {
color: white; }
.mfp-s-ready .mfp-preloader {
display: none; }
.mfp-s-error .mfp-content {
display: none; }
button.mfp-close, button.mfp-arrow {
overflow: visible;
cursor: pointer;
background: transparent;
border: 0;
-webkit-appearance: none;
display: block;
outline: none;
padding: 0;
z-index: 1046;
-webkit-box-shadow: none;
box-shadow: none; }
button::-moz-focus-inner {
padding: 0;
border: 0; }
.mfp-close {
width: 44px;
height: 44px;
line-height: 44px;
position: absolute;
right: 0;
top: 0;
text-decoration: none;
text-align: center;
opacity: 0.65;
padding: 0 0 18px 10px;
color: white;
font-style: normal;
font-size: 28px;
font-family: Arial, Baskerville, monospace; }
.mfp-close:hover, .mfp-close:focus {
opacity: 1; }
.mfp-close:active {
top: 1px; }
.mfp-close-btn-in .mfp-close {
color: #333333; }
.mfp-image-holder .mfp-close, .mfp-iframe-holder .mfp-close {
color: white;
right: -6px;
text-align: right;
padding-right: 6px;
width: 100%; }
.mfp-counter {
position: absolute;
top: 0;
right: 0;
color: #cccccc;
font-size: 12px;
line-height: 18px; }
.mfp-arrow {
position: absolute;
opacity: 0.65;
margin: 0;
top: 50%;
margin-top: -55px;
padding: 0;
width: 90px;
height: 110px;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0); }
.mfp-arrow:active {
margin-top: -54px; }
.mfp-arrow:hover, .mfp-arrow:focus {
opacity: 1; }
.mfp-arrow:before, .mfp-arrow:after, .mfp-arrow .mfp-b, .mfp-arrow .mfp-a {
content: '';
display: block;
width: 0;
height: 0;
position: absolute;
left: 0;
top: 0;
margin-top: 35px;
margin-left: 35px;
border: medium inset transparent; }
.mfp-arrow:after, .mfp-arrow .mfp-a {
border-top-width: 13px;
border-bottom-width: 13px;
top: 8px; }
.mfp-arrow:before, .mfp-arrow .mfp-b {
border-top-width: 21px;
border-bottom-width: 21px; }
.mfp-arrow-left {
left: 0; }
.mfp-arrow-left:after, .mfp-arrow-left .mfp-a {
border-right: 17px solid white;
margin-left: 31px; }
.mfp-arrow-left:before, .mfp-arrow-left .mfp-b {
margin-left: 25px;
border-right: 27px solid #3f3f3f; }
.mfp-arrow-right {
right: 0; }
.mfp-arrow-right:after, .mfp-arrow-right .mfp-a {
border-left: 17px solid white;
margin-left: 39px; }
.mfp-arrow-right:before, .mfp-arrow-right .mfp-b {
border-left: 27px solid #3f3f3f; }
.mfp-iframe-holder {
padding-top: 40px;
padding-bottom: 40px; }
.mfp-iframe-holder .mfp-content {
line-height: 0;
width: 100%;
max-width: 900px; }
.mfp-iframe-holder .mfp-close {
top: -40px; }
.mfp-iframe-scaler {
width: 100%;
height: 0;
overflow: hidden;
padding-top: 56.25%; }
.mfp-iframe-scaler iframe {
position: absolute;
display: block;
top: 0;
left: 0;
width: 100%;
height: 100%;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
background: black; }
/* Main image in popup */
img.mfp-img {
width: auto;
max-width: 100%;
height: auto;
display: block;
line-height: 0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding: 40px 0 40px;
margin: 0 auto; }
/* The shadow behind the image */
.mfp-figure {
line-height: 0; }
.mfp-figure:after {
content: '';
position: absolute;
left: 0;
top: 40px;
bottom: 40px;
display: block;
right: 0;
width: auto;
height: auto;
z-index: -1;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
background: #444444; }
.mfp-figure small {
color: #bdbdbd;
display: block;
font-size: 12px;
line-height: 14px; }
.mfp-bottom-bar {
margin-top: -36px;
position: absolute;
top: 100%;
left: 0;
width: 100%;
cursor: auto; }
.mfp-title {
text-align: left;
line-height: 18px;
color: #f3f3f3;
word-wrap: break-word;
padding-right: 36px; }
.mfp-image-holder .mfp-content {
max-width: 100%; }
.mfp-gallery .mfp-image-holder .mfp-figure {
cursor: pointer; }
@media screen and (max-width: 800px) and (orientation: landscape), screen and (max-height: 300px) {
/**
* Remove all paddings around the image on small screen
*/
.mfp-img-mobile .mfp-image-holder {
padding-left: 0;
padding-right: 0; }
.mfp-img-mobile img.mfp-img {
padding: 0; }
.mfp-img-mobile .mfp-figure {
/* The shadow behind the image */ }
.mfp-img-mobile .mfp-figure:after {
top: 0;
bottom: 0; }
.mfp-img-mobile .mfp-figure small {
display: inline;
margin-left: 5px; }
.mfp-img-mobile .mfp-bottom-bar {
background: rgba(0, 0, 0, 0.6);
bottom: 0;
margin: 0;
top: auto;
padding: 3px 5px;
position: fixed;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box; }
.mfp-img-mobile .mfp-bottom-bar:empty {
padding: 0; }
.mfp-img-mobile .mfp-counter {
right: 5px;
top: 3px; }
.mfp-img-mobile .mfp-close {
top: 0;
right: 0;
width: 35px;
height: 35px;
line-height: 35px;
background: rgba(0, 0, 0, 0.6);
position: fixed;
text-align: center;
padding: 0; } }
@media all and (max-width: 900px) {
.mfp-arrow {
-webkit-transform: scale(0.75);
transform: scale(0.75); }
.mfp-arrow-left {
-webkit-transform-origin: 0;
transform-origin: 0; }
.mfp-arrow-right {
-webkit-transform-origin: 100%;
transform-origin: 100%; }
.mfp-container {
padding-left: 6px;
padding-right: 6px; } }
.mfp-ie7 .mfp-img {
padding: 0; }
.mfp-ie7 .mfp-bottom-bar {
width: 600px;
left: 50%;
margin-left: -300px;
margin-top: 5px;
padding-bottom: 5px; }
.mfp-ie7 .mfp-container {
padding: 0; }
.mfp-ie7 .mfp-content {
padding-top: 44px; }
.mfp-ie7 .mfp-close {
top: 0;
right: 0;
padding-top: 0; }
<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd" > <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
<defs >
<font id="entypo-social" horiz-adv-x="555" ><font-face
font-family="Entypo Social"
units-per-em="1000"
panose-1="0 0 0 0 0 0 0 0 0 0"
ascent="750"
descent="-250"
alphabetic="0" />
<missing-glyph horiz-adv-x="500" />
</font>
</defs>
</svg>
<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd" > <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
<defs >
<font id="entypo" horiz-adv-x="508" ><font-face
font-family="Entypo"
units-per-em="1000"
panose-1="0 0 0 0 0 0 0 0 0 0"
ascent="750"
descent="-250"
alphabetic="0" />
<missing-glyph horiz-adv-x="500" />
</font>
</defs>
</svg>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*! intention.js v0.9.7.3
* http://intentionjs.com/
*
* context.js
*
* Copyright 2011, 2013 Dowjones and other contributors
* Released under the MIT license
*
*/
!function(){"use strict";var a=function(a,b){function c(a,b){var c=new Date,d=null;return function(e){var f=new Date;if(b>f-c){d&&window.clearTimeout(d);var g=function(b){return function(){a(b)}};return d=window.setTimeout(g(e),b),!1}a(e),c=f}}var d,e,f=new b;return f.responsive([{name:"base"}]).respond("base"),d=f.responsive({ID:"width",contexts:[{name:"standard",min:840},{name:"tablet",min:510},{name:"mobile",min:0}],matcher:function(a,b){return"string"==typeof a?a===b.name:a>=b.min},measure:function(b){return"string"==typeof b?b:a(window).width()}}),e=f.responsive({ID:"orientation",contexts:[{name:"portrait",rotation:0},{name:"landscape",rotation:90}],matcher:function(a,b){return a===b.rotation},measure:function(){var a=Math.abs(window.orientation);return a>0&&(a=180-a),a}}),f.responsive({ID:"touch",contexts:[{name:"touch"}],matcher:function(){return"ontouchstart"in window}}).respond(),f.responsive({ID:"highres",contexts:[{name:"highres"}],matcher:function(){return window.devicePixelRatio>1}}).respond(),a(window).on("resize",c(d.respond,100)).on("orientationchange",d.respond).on("orientationchange",e.respond),d.respond(),e.respond(),a(function(){f.elements(document)}),f};!function(a,b){"function"==typeof define&&define.amd?define("context",["jquery","intention"],b):a.intent=b(a.jQuery,a.Intention)}(this,function(b,c){return a(b,c)})}.call(this);
\ No newline at end of file
EPUBJS.Hooks.register("beforeChapterDisplay").highlight = function(callback, renderer){
// EPUBJS.core.addScript("js/libs/jquery.highlight.js", null, renderer.doc.head);
var s = document.createElement("style");
s.innerHTML =".highlight { background: yellow; font-weight: normal; }";
renderer.render.document.head.appendChild(s);
if(callback) callback();
}
This diff is collapsed.
/*! intention.js v0.9.7.3
* http://intentionjs.com/
*
* intention.js
*
* Copyright 2011, 2013 Dowjones and other contributors
* Released under the MIT license
*
*/
!function(a,b){"use strict";"function"==typeof define&&define.amd?define("intention",["jquery","underscore"],b):a.Intention=b(a.jQuery,a._)}(this,function(a,b){"use strict";var c=function(c){var d=b.extend(this,c,{_listeners:{},contexts:[],elms:a(),axes:{},priority:[]});return d};return c.prototype={responsive:function d(a,c){var e,f="abcdefghijklmnopqrstuvwxyz0123456789",g="";for(e=0;5>e;e++)g+=f[Math.floor(Math.random()*f.length)];var h={matcher:function(a,b){return a===b.name},measure:b.identity,ID:g};if(b.isObject(c)===!1&&(c={}),b.isArray(a)&&b.isArray(a[0].contexts))return b.each(a,function(a){d.apply(this,a)},this),void 0;b.isArray(a)===!1&&b.isObject(a)?c=a:c.contexts=a,c=b.extend({},h,c),this.on("_"+c.ID+":",b.bind(function(a){this.axes=this._contextualize(c.ID,a.context,this.axes),this._respond(this.axes,this.elms)},this));var i={ID:c.ID,current:null,contexts:c.contexts,respond:b.bind(this._responder(c.ID,c.contexts,c.matcher,c.measure),this)};return this.axes[c.ID]=i,this.axes.__keys__=this.priority,this.priority.unshift(c.ID),i},elements:function(c){return c||(c=document),a("[data-intent],[intent],[data-in],[in]",c).each(b.bind(function(b,c){this.add(a(c))},this)),this},add:function(c,d){var e;return d||(d={}),c.each(b.bind(function(c,f){var g=!1;this.elms.each(function(a,b){return f===b?(g=!0,!1):!0}),g===!1&&(e=this._fillSpec(b.extend(d,this._attrsToSpec(f.attributes,this.axes))),this._makeChanges(a(f),e,this.axes),this.elms.push({elm:f,spec:e}))},this)),this},remove:function(a){var b=this.elms;return a.each(function(a,c){b.each(function(a,d){return c===d.elm?(b.splice(a,1),!1):!0})}),this},is:function(a){var c=this.axes;return b.some(c.__keys__,function(b){return a===c[b].current})},current:function(a){return this.axes.hasOwnProperty(a)?this.axes[a].current:!1},on:function(a,b){var c=a.split(" "),d=0;for(d;d<c.length;d++)void 0===this._listeners[c[d]]&&(this._listeners[c[d]]=[]),this._listeners[c[d]].push(b);return this},off:function(a,c){if(b.isArray(this._listeners[a])){var d,e=this._listeners[a];for(d=0;e.length;d++)if(e[d]===c){e.splice(d,1);break}}return this},_responder:function(a,c,d,e){var f;return function(){var g=e.apply(this,arguments);return b.every(c,function(c){return d(g,c)?void 0===f||c.name!==f.name?(f=c,this._emitter({_type:"_"+a+":",context:f.name},f,this)._emitter({_type:a+":",context:f.name},f,this)._emitter(b.extend({},{_type:a+":"+f.name},f),f,this)._emitter(b.extend({},{_type:f.name},f),f,this),!1):!1:!0},this),this}},_emitter:function(a){if("string"==typeof a&&(a={_type:a}),a.target||(a.target=this),!a._type)throw new Error(a._type+" is not a supported event.");if(b.isArray(this._listeners[a._type])){var c,d=this._listeners[a._type];for(c=0;c<d.length;c++)d[c].apply(this,arguments)}return this},_fillSpec:function(a){var c=function(c){b.each(a,function(a,d){b.each(a,function(a,b){c(a,b,d)})})},d={};return c(function(a){b.isObject(a)&&b.each(a,function(a,b){d[b]=""})}),c(function(c,e,f){b.isObject(c)&&(a[f][e]=b.extend({},d,c))}),a},_assocAxis:function(a,c){var d=!1;return b.every(c.__keys__,function(e){return d===!1?(b.every(c[e].contexts,function(b){return b.name===a?(d=e,!1):!0}),!0):!1}),d},_makeSpec:function(a,b,c,d,e){var f;return void 0!==e[a]?(f=e[a],void 0===f[b]&&(f[b]={})):(f={},f[b]={},e[a]=f),f[b][c]=d,e},_attrsToSpec:function(a,c){var d={},e=new RegExp("^(data-)?(in|intent)-(([a-zA-Z0-9][a-zA-Z0-9]*:)?([a-zA-Z0-9]*))-([A-Za-z:-]+)"),f=new RegExp("^(data-)?(in|intent)-([a-zA-Z0-9][_a-zA-Z0-9]*):$");return b.each(a,function(a){var g,h=a.name.match(e);if(null!==h){if(h=h.slice(-3),g=h[0],void 0===h[0]){if(h[0]=this._assocAxis(h[1],c),h[0]===!1)return}else h[0]=h[0].replace(/:$/,"");h.push(a.value),h.push(d),d=this._makeSpec.apply(this,h)}else f.test(a.name)&&(g=a.name.match(f)[3],b.each(c[g].contexts,function(b){this._makeSpec(g,b.name,"class",b.name+" "+a.value,d)},this))},this),d},_contextSpec:function(a,b){return b.hasOwnProperty(a.axis)&&b[a.axis].hasOwnProperty(a.ctx)?b[a.axis][a.ctx]:{}},_resolveSpecs:function(c,d){var e={},f=["append","prepend","before","after"];return b.each(c,function(c){b.each(this._contextSpec(c,d),function(c,d){"class"===d?(e[d]||(e[d]=[]),e[d]=b.union(e[d],c.split(" "))):void 0!==e.move&&""!==e.move.value||-1===a.inArray(d,f)?(void 0===e[d]||""===e[d])&&(e[d]=c):e.move={value:c,placement:d}},this)},this),e},_currentContexts:function(a){var c=[];return b.each(a.__keys__,function(b){return null!==a[b].current?(c.push({ctx:a[b].current,axis:b}),void 0):void 0}),c},_removeClasses:function(a,c){var d=[];return b.each(c.__keys__,function(e){var f=c[e];b.each(f.contexts,function(c){if(c.name!==f.current){var e,g=this._contextSpec({axis:f.ID,ctx:c.name},a);void 0!==g&&void 0!==g["class"]&&(e=g["class"].split(" "),void 0!==e&&(d=b.union(d,e)))}},this)},this),d},_contextConfig:function(a,b){return this._resolveSpecs(this._currentContexts(b),a,b)},_makeChanges:function(c,d,e){if(b.isEmpty(e)===!1){var f=this._contextConfig(d,e);b.each(f,function(f,g){if("move"===g)(d.__placement__!==f.placement||d.__move__!==f.value)&&(a(f.value)[f.placement](c),d.__placement__=f.placement,d.__move__=f.value);else if("class"===g){var h=c.attr("class")||"";h=b.union(f,b.difference(h.split(" "),this._removeClasses(d,e))),c.attr("class",h.join(" "))}else c.attr(g,f)},this)}return c},_respond:function(c,d){d.each(b.bind(function(b,d){var e=a(d.elm);this._makeChanges(e,d.spec,c),e.trigger("intent",this)},this))},_contextualize:function(a,b,c){return c[a].current=b,c},_axis_test_pattern:new RegExp("^_[a-zA-Z0-9]"),_axis_match_pattern:new RegExp("^_([a-zA-Z0-9][_a-zA-Z0-9]*)"),_trim_pattern:new RegExp("^s+|s+$","g")},c});
\ No newline at end of file
This diff is collapsed.
// ----------------------------------------------------------------------------
// Vegas – Fullscreen Backgrounds and Slideshows with jQuery.
// v1.3.3 - released 2013-09-03 13:27
// Licensed under the MIT license.
// http://vegas.jaysalvat.com/
// ----------------------------------------------------------------------------
// Copyright (C) 2010-2013 Jay Salvat
// http://jaysalvat.com/
// ----------------------------------------------------------------------------
(function(e){function t(a,n){var r={align:"center",valign:"center"};if(e.extend(r,n),0===a.height())return a.load(function(){t(e(this),n)}),void 0;var i,s,g,d=o(),l=d.width,u=d.height,v=a.width(),c=a.height(),p=u/l,f=c/v;p>f?(i=u/f,s=u):(i=l,s=l*f),g={width:i+"px",height:s+"px",top:"auto",bottom:"auto",left:"auto",right:"auto"},isNaN(parseInt(r.valign,10))?"top"==r.valign?g.top=0:"bottom"==r.valign?g.bottom=0:g.top=(u-s)/2:g.top=0-(s-u)/100*parseInt(r.valign,10)+"px",isNaN(parseInt(r.align,10))?"left"==r.align?g.left=0:"right"==r.align?g.right=0:g.left=(l-i)/2:g.left=0-(i-l)/100*parseInt(r.align,10)+"px",a.css(g)}function a(){d.prependTo("body").fadeIn()}function n(){d.fadeOut("fast",function(){e(this).remove()})}function r(){return e("body").css("backgroundImage")?e("body").css("backgroundImage").replace(/url\("?(.*?)"?\)/i,"$1"):void 0}function o(){var e=window,t="inner";return"innerWidth"in window||(e=document.documentElement||document.body,t="client"),{width:e[t+"Width"],height:e[t+"Height"]}}var i,s=e("<img />").addClass("vegas-background"),g=e("<div />").addClass("vegas-overlay"),d=e("<div />").addClass("vegas-loading"),l=e(),u=null,v=[],c=0,p=5e3,f=function(){},h={init:function(o){var i={src:r(),align:"center",valign:"center",fade:0,loading:!0,load:function(){},complete:function(){}};e.extend(i,e.vegas.defaults.background,o),i.loading&&a();var g=s.clone();return g.css({position:"fixed",left:"0px",top:"0px"}).bind("load",function(){g!=l&&(e(window).bind("load resize.vegas",function(){t(g,i)}),l.is("img")?(l.stop(),g.hide().insertAfter(l).fadeIn(i.fade,function(){e(".vegas-background").not(this).remove(),e("body").trigger("vegascomplete",[this,c-1]),i.complete.apply(g,[c-1])})):g.hide().prependTo("body").fadeIn(i.fade,function(){e("body").trigger("vegascomplete",[this,c-1]),i.complete.apply(this,[c-1])}),l=g,t(l,i),i.loading&&n(),e("body").trigger("vegasload",[l.get(0),c-1]),i.load.apply(l.get(0),[c-1]),c&&(e("body").trigger("vegaswalk",[l.get(0),c-1]),i.walk.apply(l.get(0),[c-1])))}).attr("src",i.src),e.vegas},destroy:function(t){return t&&"background"!=t||(e(".vegas-background, .vegas-loading").remove(),e(window).unbind("*.vegas"),l=e()),t&&"overlay"!=t||e(".vegas-overlay").remove(),clearInterval(i),e.vegas},overlay:function(t){var a={src:null,opacity:null};return e.extend(a,e.vegas.defaults.overlay,t),g.remove(),g.css({margin:"0",padding:"0",position:"fixed",left:"0px",top:"0px",width:"100%",height:"100%"}),a.src&&g.css("backgroundImage","url("+a.src+")"),a.opacity&&g.css("opacity",a.opacity),g.prependTo("body"),e.vegas},slideshow:function(t,a){var n={step:c,delay:p,preload:!1,backgrounds:v,walk:f};if(e.extend(n,e.vegas.defaults.slideshow,t),n.backgrounds!=v&&(t.step||(n.step=0),t.walk||(n.walk=function(){}),n.preload&&e.vegas("preload",n.backgrounds)),v=n.backgrounds,p=n.delay,c=n.step,f=n.walk,clearInterval(i),!v.length)return e.vegas;var r=function(){0>c&&(c=v.length-1),(c>=v.length||!v[c-1])&&(c=0);var t=v[c++];t.walk=n.walk,t.fade===void 0&&(t.fade=n.fade),t.fade>n.delay&&(t.fade=n.delay),e.vegas(t)};return r(),a||(u=!1,e("body").trigger("vegasstart",[l.get(0),c-1])),u||(i=setInterval(r,n.delay)),e.vegas},next:function(){var t=c;return c&&(e.vegas("slideshow",{step:c},!0),e("body").trigger("vegasnext",[l.get(0),c-1,t-1])),e.vegas},previous:function(){var t=c;return c&&(e.vegas("slideshow",{step:c-2},!0),e("body").trigger("vegasprevious",[l.get(0),c-1,t-1])),e.vegas},jump:function(t){var a=c;return c&&(e.vegas("slideshow",{step:t},!0),e("body").trigger("vegasjump",[l.get(0),c-1,a-1])),e.vegas},stop:function(){var t=c;return c=0,u=null,clearInterval(i),e("body").trigger("vegasstop",[l.get(0),t-1]),e.vegas},pause:function(){return u=!0,clearInterval(i),e("body").trigger("vegaspause",[l.get(0),c-1]),e.vegas},get:function(e){return null===e||"background"==e?l.get(0):"overlay"==e?g.get(0):"step"==e?c-1:"paused"==e?u:void 0},preload:function(t){var a=[];for(var n in t)if(t[n].src){var r=document.createElement("img");r.src=t[n].src,a.push(r)}return e.vegas}};e.vegas=function(t){return h[t]?h[t].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof t&&t?(e.error("Method "+t+" does not exist"),void 0):h.init.apply(this,arguments)},e.vegas.defaults={background:{},slideshow:{},overlay:{}}})(jQuery);
\ No newline at end of file
/*!
* screenfull
* v2.0.0 - 2014-12-22
* (c) Sindre Sorhus; MIT License
*/
(function () {
'use strict';
var isCommonjs = typeof module !== 'undefined' && module.exports;
var keyboardAllowed = typeof Element !== 'undefined' && 'ALLOW_KEYBOARD_INPUT' in Element;
var fn = (function () {
var val;
var valLength;
var fnMap = [
[
'requestFullscreen',
'exitFullscreen',
'fullscreenElement',
'fullscreenEnabled',
'fullscreenchange',
'fullscreenerror'
],
// new WebKit
[
'webkitRequestFullscreen',
'webkitExitFullscreen',
'webkitFullscreenElement',
'webkitFullscreenEnabled',
'webkitfullscreenchange',
'webkitfullscreenerror'
],
// old WebKit (Safari 5.1)
[
'webkitRequestFullScreen',
'webkitCancelFullScreen',
'webkitCurrentFullScreenElement',
'webkitCancelFullScreen',
'webkitfullscreenchange',
'webkitfullscreenerror'
],
[
'mozRequestFullScreen',
'mozCancelFullScreen',
'mozFullScreenElement',
'mozFullScreenEnabled',
'mozfullscreenchange',
'mozfullscreenerror'
],
[
'msRequestFullscreen',
'msExitFullscreen',
'msFullscreenElement',
'msFullscreenEnabled',
'MSFullscreenChange',
'MSFullscreenError'
]
];
var i = 0;
var l = fnMap.length;
var ret = {};
for (; i < l; i++) {
val = fnMap[i];
if (val && val[1] in document) {
for (i = 0, valLength = val.length; i < valLength; i++) {
ret[fnMap[0][i]] = val[i];
}
return ret;
}
}
return false;
})();
var screenfull = {
request: function (elem) {
var request = fn.requestFullscreen;
elem = elem || document.documentElement;
// Work around Safari 5.1 bug: reports support for
// keyboard in fullscreen even though it doesn't.
// Browser sniffing, since the alternative with
// setTimeout is even worse.
if (/5\.1[\.\d]* Safari/.test(navigator.userAgent)) {
elem[request]();
} else {
elem[request](keyboardAllowed && Element.ALLOW_KEYBOARD_INPUT);
}
},
exit: function () {
document[fn.exitFullscreen]();
},
toggle: function (elem) {
if (this.isFullscreen) {
this.exit();
} else {
this.request(elem);
}
},
raw: fn
};
if (!fn) {
if (isCommonjs) {
module.exports = false;
} else {
window.screenfull = false;
}
return;
}
Object.defineProperties(screenfull, {
isFullscreen: {
get: function () {
return !!document[fn.fullscreenElement];
}
},
element: {
enumerable: true,
get: function () {
return document[fn.fullscreenElement];
}
},
enabled: {
enumerable: true,
get: function () {
// Coerce to boolean in case of old WebKit
return !!document[fn.fullscreenEnabled];
}
}
});
if (isCommonjs) {
module.exports = screenfull;
} else {
window.screenfull = screenfull;
}
})();
/*!
* screenfull
* v1.1.0 - 2013-09-06
* https://github.com/sindresorhus/screenfull.js
* (c) Sindre Sorhus; MIT License
*/
!function(a,b){"use strict";var c="undefined"!=typeof Element&&"ALLOW_KEYBOARD_INPUT"in Element,d=function(){for(var a,c,d=[["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"]],e=0,f=d.length,g={};f>e;e++)if(a=d[e],a&&a[1]in b){for(e=0,c=a.length;c>e;e++)g[d[0][e]]=a[e];return g}return!1}(),e={request:function(a){var e=d.requestFullscreen;a=a||b.documentElement,/5\.1[\.\d]* Safari/.test(navigator.userAgent)?a[e]():a[e](c&&Element.ALLOW_KEYBOARD_INPUT)},exit:function(){b[d.exitFullscreen]()},toggle:function(a){this.isFullscreen?this.exit():this.request(a)},onchange:function(){},onerror:function(){},raw:d};return d?(Object.defineProperties(e,{isFullscreen:{get:function(){return!!b[d.fullscreenElement]}},element:{enumerable:!0,get:function(){return b[d.fullscreenElement]}},enabled:{enumerable:!0,get:function(){return!!b[d.fullscreenEnabled]}}}),b.addEventListener(d.fullscreenchange,function(a){e.onchange.call(e,a)}),b.addEventListener(d.fullscreenerror,function(a){e.onerror.call(e,a)}),a.screenfull=e,void 0):(a.screenfull=!1,void 0)}(window,document);
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
// Hypothesis Customized embedding
// This hypothesis config function returns a new constructor which modifies
// annotator for a better integration. Below we create our own EpubAnnotationSidebar
// Constructor, customizing the show and hide function to take acount for the reader UI.
window.hypothesisConfig = function() {
var Annotator = window.Annotator;
var $main = $("#main");
function EpubAnnotationSidebar(elem, options) {
options = {
server: true,
origin: true,
showHighlights: true,
Toolbar: {container: '#annotation-controls'}
}
Annotator.Host.call(this, elem, options);
}
EpubAnnotationSidebar.prototype = Object.create(Annotator.Host.prototype);
EpubAnnotationSidebar.prototype.show = function() {
this.frame.css({
'margin-left': (-1 * this.frame.width()) + "px"
});
this.frame.removeClass('annotator-collapsed');
if (!$main.hasClass('single')) {
$main.addClass("single");
this.toolbar.find('[name=sidebar-toggle]').removeClass('h-icon-chevron-left').addClass('h-icon-chevron-right');
this.setVisibleHighlights(true);
}
};
EpubAnnotationSidebar.prototype.hide = function() {
this.frame.css({
'margin-left': ''
});
this.frame.addClass('annotator-collapsed');
if ($main.hasClass('single')) {
$main.removeClass("single");
this.toolbar.find('[name=sidebar-toggle]').removeClass('h-icon-chevron-right').addClass('h-icon-chevron-left');
this.setVisibleHighlights(false);
}
};
return {
constructor: EpubAnnotationSidebar,
}
};
// This is the Epub.js plugin. Annotations are updated on location change.
EPUBJS.reader.plugins.HypothesisController = function (Book) {
var reader = this;
var $main = $("#main");
var updateAnnotations = function () {
var annotator = Book.renderer.render.window.annotator;
if (annotator && annotator.constructor.$) {
var annotations = getVisibleAnnotations(annotator.constructor.$);
annotator.showAnnotations(annotations)
}
};
var getVisibleAnnotations = function ($) {
var width = Book.renderer.render.iframe.clientWidth;
return $('.annotator-hl').map(function() {
var $this = $(this),
left = this.getBoundingClientRect().left;
if (left >= 0 && left <= width) {
return $this.data('annotation');
}
}).get();
};
Book.on("renderer:locationChanged", updateAnnotations);
return {}
};
EPUBJS.reader.search = {};
// Search Server -- https://github.com/futurepress/epubjs-search
EPUBJS.reader.search.SERVER = "";
EPUBJS.reader.search.request = function(q, callback) {
var fetch = $.ajax({
dataType: "json",
url: EPUBJS.reader.search.SERVER + "/search?q=" + encodeURIComponent(q)
});
fetch.fail(function(err) {
console.error(err);
});
fetch.done(function(results) {
callback(results);
});
};
EPUBJS.reader.plugins.SearchController = function(Book) {
var reader = this;
var $searchBox = $("#searchBox"),
$searchResults = $("#searchResults"),
$searchView = $("#searchView"),
iframeDoc;
var searchShown = false;
var onShow = function() {
query();
searchShown = true;
$searchView.addClass("shown");
};
var onHide = function() {
searchShown = false;
$searchView.removeClass("shown");
};
var query = function() {
var q = $searchBox.val();
if(q == '') {
return;
}
$searchResults.empty();
$searchResults.append("<li><p>Searching...</p></li>");
EPUBJS.reader.search.request(q, function(data) {
var results = data.results;
$searchResults.empty();
if(iframeDoc) {
$(iframeDoc).find('body').unhighlight();
}
if(results.length == 0) {
$searchResults.append("<li><p>No Results Found</p></li>");
return;
}
iframeDoc = $("#viewer iframe")[0].contentDocument;
$(iframeDoc).find('body').highlight(q, { element: 'span' });
results.forEach(function(result) {
var $li = $("<li></li>");
var $item = $("<a href='"+result.href+"' data-cfi='"+result.cfi+"'><span>"+result.title+"</span><p>"+result.highlight+"</p></a>");
$item.on("click", function(e) {
var $this = $(this),
cfi = $this.data("cfi");
e.preventDefault();
Book.gotoCfi(cfi+"/1:0");
Book.on("renderer:chapterDisplayed", function() {
iframeDoc = $("#viewer iframe")[0].contentDocument;
$(iframeDoc).find('body').highlight(q, { element: 'span' });
})
});
$li.append($item);
$searchResults.append($li);
});
});
};
$searchBox.on("search", function(e) {
var q = $searchBox.val();
//-- SearchBox is empty or cleared
if(q == '') {
$searchResults.empty();
if(reader.SidebarController.getActivePanel() == "Search") {
reader.SidebarController.changePanelTo("Toc");
}
$(iframeDoc).find('body').unhighlight();
iframeDoc = false;
return;
}
reader.SidebarController.changePanelTo("Search");
e.preventDefault();
});
return {
"show" : onShow,
"hide" : onHide
};
};
document.ontouchmove = function(e){
return true;
};
Sortable.create(sortTrue, {
group: "sorting",
sort: true
});
function sendData(path){
var elements;
var counter;
var maxElements;
var tmp=[];
elements=Sortable.utils.find(sortTrue,"div");
maxElements=elements.length;
var form = document.createElement("form");
form.setAttribute("method", "post");
form.setAttribute("action", path);
for(counter=0;counter<maxElements;counter++){
tmp[counter]=elements[counter].getAttribute("id");
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", elements[counter].getAttribute("id"));
hiddenField.setAttribute("value", counter+1);
form.appendChild(hiddenField);
}
document.body.appendChild(form);
form.submit();
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -13,9 +13,9 @@ ...@@ -13,9 +13,9 @@
<th>{{_('Upload')}}</th> <th>{{_('Upload')}}</th>
<th>{{_('Edit')}}</th> <th>{{_('Edit')}}</th>
<th>{{_('Passwd')}}</th> <th>{{_('Passwd')}}</th>
</tr> </tr>
{% for user in content %} {% for user in content %}
{% if not user.role_anonymous() or config.ANON_BROWSE %}
<tr> <tr>
<td><a href="{{url_for('edit_user', user_id=user.id)}}">{{user.nickname}}</a></td> <td><a href="{{url_for('edit_user', user_id=user.id)}}">{{user.nickname}}</a></td>
<td>{{user.email}}</td> <td>{{user.email}}</td>
...@@ -26,7 +26,8 @@ ...@@ -26,7 +26,8 @@
<td>{% if user.role_upload() %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td> <td>{% if user.role_upload() %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td>
<td>{% if user.role_edit() %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td> <td>{% if user.role_edit() %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td>
<td>{% if user.role_passwd() %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td> <td>{% if user.role_passwd() %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td>
</tr>
{% endif %}
{% endfor %} {% endfor %}
</table> </table>
<div class="btn btn-default"><a href="{{url_for('new_user')}}">{{_('Add new user')}}</a></div> <div class="btn btn-default"><a href="{{url_for('new_user')}}">{{_('Add new user')}}</a></div>
......
...@@ -104,11 +104,11 @@ ...@@ -104,11 +104,11 @@
{{entry.comments[0].text|safe}} {{entry.comments[0].text|safe}}
{% endif %} {% endif %}
{% if g.user.is_authenticated %}
<div class="more-stuff"> <div class="more-stuff">
<div class="btn-toolbar" role="toolbar"> <div class="btn-toolbar" role="toolbar">
<div class="btn-group" role="group" aria-label="Download, send to Kindle, reading"> <div class="btn-group" role="group" aria-label="Download, send to Kindle, reading">
{% if g.user.role_download() %}
<div class="btn-group" role="group"> <div class="btn-group" role="group">
<button id="btnGroupDrop1" type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <button id="btnGroupDrop1" type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-download"></span> {{_('Download')}} <span class="glyphicon glyphicon-download"></span> {{_('Download')}}
...@@ -120,6 +120,9 @@ ...@@ -120,6 +120,9 @@
{%endfor%} {%endfor%}
</ul> </ul>
</div> </div>
{% endif %}
{% if g.user.is_authenticated %}
{% if g.user.kindle_mail %} {% if g.user.kindle_mail %}
<a href="{{url_for('send_to_kindle', book_id=entry.id)}}" id="sendbtn" class="btn btn-primary" role="button"><span class="glyphicon glyphicon-send"></span> {{_('Send to Kindle')}}</a> <a href="{{url_for('send_to_kindle', book_id=entry.id)}}" id="sendbtn" class="btn btn-primary" role="button"><span class="glyphicon glyphicon-send"></span> {{_('Send to Kindle')}}</a>
{% endif %} {% endif %}
...@@ -136,10 +139,11 @@ ...@@ -136,10 +139,11 @@
{%endfor%} {%endfor%}
</ul> </ul>
</div> </div>
{% endif %}
</div> </div>
</div> </div>
</br> </br>
{% if g.user.is_authenticated %}
{% if g.user.shelf.all() or g.public_shelfes %} {% if g.user.shelf.all() or g.public_shelfes %}
<div class="btn-toolbar" role="toolbar"> <div class="btn-toolbar" role="toolbar">
<div class="btn-group" role="group" aria-label="Add to shelves"> <div class="btn-group" role="group" aria-label="Add to shelves">
...@@ -180,7 +184,7 @@ ...@@ -180,7 +184,7 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
{% endif %}
{% if g.user.role_edit() %} {% if g.user.role_edit() %}
<div class="btn-toolbar" role="toolbar"> <div class="btn-toolbar" role="toolbar">
<div class="btn-group" role="group" aria-label="Edit/Delete book"> <div class="btn-group" role="group" aria-label="Edit/Delete book">
...@@ -189,7 +193,7 @@ ...@@ -189,7 +193,7 @@
</div> </div>
{% endif %} {% endif %}
{% endif %}
</div> </div>
</div> </div>
</div> </div>
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
<!-- <p><a href="{{ url_for('edit_book', book_id=entry.id) }}">{{entry.authors[0].name}}: {{entry.title}}</a></p> -->
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
......
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
<input type="text" class="form-control" name="mail_port" id="mail_port" value="{{content.mail_port}}"> <input type="text" class="form-control" name="mail_port" id="mail_port" value="{{content.mail_port}}">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="mail_use_ssl">{{_('Server uses SSL (StartTLS)')}}</label>
<input type="checkbox" name="mail_use_ssl" id="mail_use_ssl" {% if content.mail_use_ssl %}checked{% endif %}> <input type="checkbox" name="mail_use_ssl" id="mail_use_ssl" {% if content.mail_use_ssl %}checked{% endif %}>
<label for="mail_use_ssl">{{_('Server uses SSL (StartTLS)')}}</label>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="mail_login">{{_('SMTP login')}}</label> <label for="mail_login">{{_('SMTP login')}}</label>
......
...@@ -2,18 +2,30 @@ ...@@ -2,18 +2,30 @@
<feed xmlns="http://www.w3.org/2005/Atom"> <feed xmlns="http://www.w3.org/2005/Atom">
<id>urn:uuid:2853dacf-ed79-42f5-8e8a-a7bb3d1ae6a2</id> <id>urn:uuid:2853dacf-ed79-42f5-8e8a-a7bb3d1ae6a2</id>
<link rel="self" <link rel="self"
href="{{url_for('feed_index')}}" href="{{request.script_root + request.full_path}}"
type="application/atom+xml;profile=opds-catalog;kind=navigation"/> type="application/atom+xml;profile=opds-catalog;type=feed;kind=navigation"/>
<link rel="start" <link rel="start"
href="{{url_for('feed_index')}}" href="{{url_for('feed_index')}}"
type="application/atom+xml;profile=opds-catalog;kind=navigation"/> type="application/atom+xml;profile=opds-catalog;type=feed;kind=navigation"/>
<link rel="up" <link rel="up"
href="{{url_for('feed_index')}}" href="{{url_for('feed_index')}}"
type="application/atom+xml;profile=opds-catalog;kind=navigation"/> type="application/atom+xml;profile=opds-catalog;type=feed;kind=navigation"/>
{% if pagination.has_prev %}
<link rel="first"
href="{{request.script_root + request.path}}"
type="application/atom+xml;profile=opds-catalog;type=feed;kind=navigation"/>
{% endif %}
{% if pagination.has_next %}
<link rel="next" <link rel="next"
title="{{_('Next')}}" title="{{_('Next')}}"
href="{{ next_url }}" href="{{ request.script_root + request.path }}?offset={{ pagination.next_offset }}"
type="application/atom+xml;profile=opds-catalog;kind=navigation"/> type="application/atom+xml;profile=opds-catalog;type=feed;kind=navigation"/>
{% endif %}
{% if pagination.has_prev %}
<link rel="previous"
href="{{request.script_root + request.path}}?offset={{ pagination.previous_offset }}"
type="application/atom+xml;profile=opds-catalog;type=feed;kind=navigation"/>
{% endif %}
<link rel="search" <link rel="search"
href="{{url_for('feed_osd')}}" href="{{url_for('feed_osd')}}"
type="application/opensearchdescription+xml"/> type="application/opensearchdescription+xml"/>
...@@ -30,7 +42,6 @@ ...@@ -30,7 +42,6 @@
<updated>{{entry.timestamp}}</updated> <updated>{{entry.timestamp}}</updated>
<author> <author>
<name>{{entry.authors[0].name}}</name> <name>{{entry.authors[0].name}}</name>
<uri>{{entry.authors[0].name}}</uri>
</author> </author>
<language>{{entry.language}}</language> <language>{{entry.language}}</language>
{% for tag in entry.tags %} {% for tag in entry.tags %}
...@@ -38,45 +49,39 @@ ...@@ -38,45 +49,39 @@
term="{{tag.name}}" term="{{tag.name}}"
label="{{tag.name}}"/> label="{{tag.name}}"/>
{% endfor %} {% endfor %}
<summary>{% if entry.comments[0] %}{{entry.comments[0].text|striptags}}{% endif %}</summary> {% if entry.comments[0] %}<summary>{{entry.comments[0].text|striptags}}</summary>{% endif %}
{% if entry.has_cover %} {% if entry.has_cover %}
<link rel="http://opds-spec.org/image" href="{{ url_for('feed_get_cover', cover_path=entry.path) }}" type="image/jpg"/> <link type="image/jpeg" href="{{url_for('feed_get_cover', book_id=entry.id)}}" rel="http://opds-spec.org/image"/>
<link rel="http://opds-spec.org/cover" href="{{ url_for('feed_get_cover', cover_path=entry.path) }}" type="image/jpg"/> <link type="image/jpeg" href="{{url_for('feed_get_cover', book_id=entry.id)}}" rel="http://opds-spec.org/image/thumbnail"/>
<link rel="http://opds-spec.org/image/thumbnail" href="{{ url_for('feed_get_cover', cover_path=entry.path) }}" type="image/jpg"/>
{% endif %} {% endif %}
{% for format in entry.data %} {% for format in entry.data %}
<link rel="http://opds-spec.org/acquisition" href="{{ url_for('get_opds_download_link', book_id=entry.id, format=format.format|lower)}}" <link rel="http://opds-spec.org/acquisition" href="{{ url_for('get_opds_download_link', book_id=entry.id, format=format.format|lower)}}"
length="{{format.uncompressed_size}}" mtime="{{entry.timestamp}}" length="{{format.uncompressed_size}}" mtime="{{entry.timestamp}}" type="{{format.format|lower|mimetype}}"/>
{% if format.format|lower == "epub" %}
type="application/epub+zip"/>
{% else %}
type="application/x-mobipocket-ebook"/>
{% endif %}
{% endfor %} {% endfor %}
</entry> </entry>
{% endfor %} {% endfor %}
{% for author in authors %} {% for author in authors %}
<entry> <entry>
<title>{{author.name}}</title> <title>{{author.name}}</title>
<id>{{ url_for('feed_author', name=author.name) }}</id> <id>{{ url_for('feed_author', id=author.id) }}</id>
<link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_author', name=author.name)}}" /> <link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_author', id=author.id)}}"/>
<link type="application/atom+xml" href="{{url_for('feed_author', name=author.name)}}" rel="subsection"/> <link type="application/atom+xml" href="{{url_for('feed_author', id=author.id)}}" rel="subsection"/>
</entry> </entry>
{% endfor %} {% endfor %}
{% for entry in categorys %} {% for entry in categorys %}
<entry> <entry>
<title>{{entry.name}}</title> <title>{{entry.name}}</title>
<id>{{ url_for('feed_category', name=entry.name) }}</id> <id>{{ url_for('feed_category', id=entry.id) }}</id>
<link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_category', name=entry.name)}}" /> <link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_category', id=entry.id)}}"/>
<link type="application/atom+xml" href="{{url_for('feed_category', name=entry.name)}}" rel="subsection"/> <link type="application/atom+xml" href="{{url_for('feed_category', id=entry.id)}}" rel="subsection"/>
</entry> </entry>
{% endfor %} {% endfor %}
{% for entry in series %} {% for entry in series %}
<entry> <entry>
<title>{{entry.name}}</title> <title>{{entry.name}}</title>
<id>{{ url_for('feed_series', name=entry.name) }}</id> <id>{{ url_for('feed_series', id=entry.id) }}</id>
<link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_series', name=entry.name)}}" /> <link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_series', id=entry.id)}}" />
<link type="application/atom+xml" href="{{url_for('feed_series', name=entry.name)}}" rel="subsection"/> <link type="application/atom+xml" href="{{url_for('feed_series', id=entry.id)}}" rel="subsection"/>
</entry> </entry>
{% endfor %} {% endfor %}
</feed> </feed>
...@@ -27,28 +27,28 @@ ...@@ -27,28 +27,28 @@
</entry> </entry>
<entry> <entry>
<title>{{_('Random Books')}}</title> <title>{{_('Random Books')}}</title>
<link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_discover')}}" /> <link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_discover')}}"/>
<link rel="http://opds-spec.org/featured" href="{{url_for('feed_discover')}}" type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition"/> <link rel="http://opds-spec.org/featured" href="{{url_for('feed_discover')}}" type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition"/>
<id>{{url_for('feed_discover')}}</id> <id>{{url_for('feed_discover')}}</id>
<content type="text">{{_('Show Random Books')}}</content> <content type="text">{{_('Show Random Books')}}</content>
</entry> </entry>
<entry> <entry>
<title>{{_('Authors')}}</title> <title>{{_('Authors')}}</title>
<link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_authorindex')}}" /> <link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_authorindex')}}"/>
<link rel="subsection" href="{{url_for('feed_authorindex')}}" type="application/atom+xml;profile=opds-catalog;type=feed;kind=navigation"/> <link rel="subsection" href="{{url_for('feed_authorindex')}}" type="application/atom+xml;profile=opds-catalog;type=feed;kind=navigation"/>
<id>{{url_for('feed_authorindex')}}</id> <id>{{url_for('feed_authorindex')}}</id>
<content type="text">{{_('Books ordered by Author')}}</content> <content type="text">{{_('Books ordered by Author')}}</content>
</entry> </entry>
<entry> <entry>
<title>{{_('Category list')}}</title> <title>{{_('Category list')}}</title>
<link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_categoryindex')}}" /> <link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_categoryindex')}}"/>
<link rel="subsection" href="{{url_for('feed_categoryindex')}}" type="application/atom+xml;profile=opds-catalog;type=feed;kind=navigation"/> <link rel="subsection" href="{{url_for('feed_categoryindex')}}" type="application/atom+xml;profile=opds-catalog;type=feed;kind=navigation"/>
<id>{{url_for('feed_categoryindex')}}</id> <id>{{url_for('feed_categoryindex')}}</id>
<content type="text">{{_('Books ordered by category')}}</content> <content type="text">{{_('Books ordered by category')}}</content>
</entry> </entry>
<entry> <entry>
<title>{{_('Series list')}}</title> <title>{{_('Series list')}}</title>
<link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_seriesindex')}}" /> <link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_seriesindex')}}"/>
<link rel="subsection" href="{{url_for('feed_seriesindex')}}" type="application/atom+xml;profile=opds-catalog;type=feed;kind=navigation"/> <link rel="subsection" href="{{url_for('feed_seriesindex')}}" type="application/atom+xml;profile=opds-catalog;type=feed;kind=navigation"/>
<id>{{url_for('feed_seriesindex')}}</id> <id>{{url_for('feed_seriesindex')}}</id>
<content type="text">{{_('Books ordered by series')}}</content> <content type="text">{{_('Books ordered by series')}}</content>
......
{
"pubdate": "{{entry.pubdate}}",
"title": "{{entry.title}}",
"format_metadata": {
{% for format in entry.data %}
"{{format.format}}": {
"mtime": "{{entry.last_modified}}",
"size": {{format.uncompressed_size}},
"path": ""
}{% if not loop.last %},{% endif %}
{% endfor %}
},
"formats": [
{% for format in entry.data %}
"{{format.format}}"{% if not loop.last %},{% endif %}
{% endfor %}
],
"series": null,
"cover": "/opds/cover/{{entry.id}}",
"languages": [
{% for lang in entry.languages %}
"{{lang.lang_code}}"{% if not loop.last %},{% endif %}
{% endfor %}
],
"comments": "{% if entry.comments|length > 0 %}{{entry.comments[0].text.replace('"', '\\"')|safe}}{% endif %}",
"tags": [
{% for tag in entry.tags %}
"{{tag.name}}"{% if not loop.last %},{% endif %}
{% endfor %}
],
"application_id": {{entry.id}},
"series_index": {% if entry.series|length > 0 %}"{{entry.series_index}}"{% else %}null{% endif %},
"last_modified": "{{entry.last_modified}}",
"author_sort": "{{entry.author_sort}}",
"uuid": "{{entry.uuid}}",
"timestamp": "{{entry.timestamp}}",
"thumbnail": "/opds/cover/{{entry.id}}",
"main_format": {
"{{entry.data[0].format|lower}}": "/download/{{entry.id}}/{{entry.data[0].format|lower}}"
},
"rating":{% if entry.ratings.__len__() > 0 %} "{{entry.ratings[0].rating}}.0"{% else %}0.0{% endif %},
"authors": [
{% for author in entry.authors %}
"{{author.name}}"{% if not loop.last %},{% endif %}
{% endfor %}
],
"other_formats": {
{% if entry.data.__len__() > 1 %}
{% for format in entry.data[1:] %}
"{{format.format|lower}}": "/download/{{entry.id}}/{{format.format|lower}}"{% if not loop.last %},{% endif %}
{% endfor %}
{% endif %} },
"title_sort": "{{entry.sort}}"
}
\ No newline at end of file
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
<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/bootstrap.min.js') }}"></script> <script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/underscore.min.js') }}"></script> <script src="{{ url_for('static', filename='js/underscore-min.js') }}"></script>
<script src="{{ url_for('static', filename='js/intention.js') }}"></script> <script src="{{ url_for('static', filename='js/intention.js') }}"></script>
<script src="{{ url_for('static', filename='js/context.js') }}"></script> <script src="{{ url_for('static', filename='js/context.js') }}"></script>
<script src="{{ url_for('static', filename='js/plugins.js') }}"></script> <script src="{{ url_for('static', filename='js/plugins.js') }}"></script>
...@@ -146,10 +146,11 @@ ...@@ -146,10 +146,11 @@
<li><a href="{{url_for('show_shelf', shelf_id=shelf.id)}}"><span class="glyphicon glyphicon-list"></span> {{shelf.name}}</a></li> <li><a href="{{url_for('show_shelf', shelf_id=shelf.id)}}"><span class="glyphicon glyphicon-list"></span> {{shelf.name}}</a></li>
{% endfor %} {% endfor %}
{% if not g.user.is_anonymous() %} {% if not g.user.is_anonymous() %}
<li class="create-shelf"><a href="{{url_for('create_shelf')}}">{{_('Create a Shelf')}}</a></li> <li id="nav_createshelf" class="create-shelf"><a href="{{url_for('create_shelf')}}">{{_('Create a Shelf')}}</a></li>
<li id="nav_about"><a href="{{url_for('stats')}}"><span class="glyphicon glyphicon-info-sign"></span> {{_('About')}}</a></li>
{% endif %} {% endif %}
{% endif %} {% endif %}
<li><a href="{{url_for('stats')}}"><span class="glyphicon glyphicon-info-sign"></span> {{_('About')}}</a></li>
</ul> </ul>
</nav> </nav>
</div> </div>
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
<label for="email">{{_('Email address')}}</label> <label for="email">{{_('Email address')}}</label>
<input type="email" class="form-control" name="email" id="email" value="{{ content.email if content.email != None }}" autocomplete="off" required> <input type="email" class="form-control" name="email" id="email" value="{{ content.email if content.email != None }}" autocomplete="off" required>
</div> </div>
{% if g.user and g.user.role_passwd() or g.user.role_admin()%} {% if ( g.user and g.user.role_passwd() or g.user.role_admin() ) and not content.role_anonymous() %}
<div class="form-group"> <div class="form-group">
<label for="password">{{_('Password')}}</label> <label for="password">{{_('Password')}}</label>
<input type="password" class="form-control" name="password" id="password" value="" autocomplete="off"> <input type="password" class="form-control" name="password" id="password" value="" autocomplete="off">
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
<label for="locale">{{_('Language')}}</label> <label for="locale">{{_('Language')}}</label>
<select name="locale" id="locale" class="form-control"> <select name="locale" id="locale" class="form-control">
{% for translation in translations %} {% for translation in translations %}
<option value="{{translation.language}}" {% if translation.language == content.locale %}selected{% endif %}>{{ translation.display_name }}</option> <option value="{{translation}}" {% if translation|string == content.locale %}selected{% endif %}>{{ translation.display_name }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
...@@ -62,11 +62,12 @@ ...@@ -62,11 +62,12 @@
</div> </div>
{% if g.user and g.user.role_admin() and not profile %} {% if g.user and g.user.role_admin() and not profile %}
{% if not content.role_anonymous() %}
<div class="form-group"> <div class="form-group">
<input type="checkbox" name="admin_role" id="admin_role" {% if content.role_admin() %}checked{% endif %}> <input type="checkbox" name="admin_role" id="admin_role" {% if content.role_admin() %}checked{% endif %}>
<label for="admin_role">{{_('Admin user')}}</label> <label for="admin_role">{{_('Admin user')}}</label>
</div> </div>
{% endif %}
<div class="form-group"> <div class="form-group">
<input type="checkbox" name="download_role" id="download_role" {% if content.role_download() %}checked{% endif %}> <input type="checkbox" name="download_role" id="download_role" {% if content.role_download() %}checked{% endif %}>
<label for="download_role">{{_('Allow Downloads')}}</label> <label for="download_role">{{_('Allow Downloads')}}</label>
...@@ -79,19 +80,21 @@ ...@@ -79,19 +80,21 @@
<input type="checkbox" name="edit_role" id="edit_role" {% if content.role_edit() %}checked{% endif %}> <input type="checkbox" name="edit_role" id="edit_role" {% if content.role_edit() %}checked{% endif %}>
<label for="edit_role">{{_('Allow Edit')}}</label> <label for="edit_role">{{_('Allow Edit')}}</label>
</div> </div>
<div class="form-group"> {% if not content.role_anonymous() %}
<input type="checkbox" name="passwd_role" id="passwd_role" {% if content.role_passwd() %}checked{% endif %}> <div class="form-group">
<label for="passwd_role">{{_('Allow Changing Password')}}</label> <input type="checkbox" name="passwd_role" id="passwd_role" {% if content.role_passwd() %}checked{% endif %}>
</div> <label for="passwd_role">{{_('Allow Changing Password')}}</label>
</div>
{% endif %}
{% endif %} {% endif %}
{% if g.user and g.user.role_admin() and not profile and not new_user %} {% if g.user and g.user.role_admin() and not profile and not new_user and not content.role_anonymous() %}
<div class="checkbox"> <div class="checkbox">
<label> <label>
<input type="checkbox" name="delete"> {{_('Delete this user')}} <input type="checkbox" name="delete"> {{_('Delete this user')}}
</label> </label>
</div> </div>
{% endif %} {% endif %}
<button type="submit" class="btn btn-default">{{_('Submit')}}</button> <button type="submit" id="submit" class="btn btn-default">{{_('Submit')}}</button>
{% if not profile %} {% if not profile %}
<a href="{{ url_for('admin') }}" class="btn btn-default">{{_('Back')}}</a> <a href="{{ url_for('admin') }}" class="btn btn-default">{{_('Back')}}</a>
{% endif %} {% endif %}
......
...@@ -5,9 +5,12 @@ from sqlalchemy import * ...@@ -5,9 +5,12 @@ from sqlalchemy import *
from sqlalchemy import exc from sqlalchemy import exc
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import * from sqlalchemy.orm import *
from flask_login import AnonymousUserMixin
import os import os
import config import config
import traceback
from werkzeug.security import generate_password_hash from werkzeug.security import generate_password_hash
from flask_babel import gettext as _
dbpath = os.path.join(config.APP_DB_ROOT, "app.db") dbpath = os.path.join(config.APP_DB_ROOT, "app.db")
engine = create_engine('sqlite:///{0}'.format(dbpath), echo=False) engine = create_engine('sqlite:///{0}'.format(dbpath), echo=False)
...@@ -19,28 +22,11 @@ ROLE_DOWNLOAD = 2 ...@@ -19,28 +22,11 @@ ROLE_DOWNLOAD = 2
ROLE_UPLOAD = 4 ROLE_UPLOAD = 4
ROLE_EDIT = 8 ROLE_EDIT = 8
ROLE_PASSWD = 16 ROLE_PASSWD = 16
ROLE_ANONYMOUS = 32
DEFAULT_PASS = "admin123" DEFAULT_PASS = "admin123"
class User(Base): class UserBase():
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
nickname = Column(String(64), unique=True)
email = Column(String(120), unique=True, default="")
role = Column(SmallInteger, default=ROLE_USER)
password = Column(String)
kindle_mail = Column(String(120), default="")
shelf = relationship('Shelf', backref='user', lazy='dynamic')
downloads = relationship('Downloads', backref='user', lazy='dynamic')
locale = Column(String(2), default="en")
random_books = Column(Integer, default=1)
language_books = Column(Integer, default=1)
series_books = Column(Integer, default=1)
category_books = Column(Integer, default=1)
hot_books = Column(Integer, default=1)
default_language = Column(String(3), default="all")
def is_authenticated(self): def is_authenticated(self):
return True return True
...@@ -74,6 +60,12 @@ class User(Base): ...@@ -74,6 +60,12 @@ class User(Base):
else: else:
return False return False
def role_anonymous(self):
if self.role is not None:
return True if self.role & ROLE_ANONYMOUS == ROLE_ANONYMOUS else False
else:
return False
def is_active(self): def is_active(self):
return True return True
...@@ -105,6 +97,53 @@ class User(Base): ...@@ -105,6 +97,53 @@ class User(Base):
return '<User %r>' % self.nickname return '<User %r>' % self.nickname
class User(UserBase,Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
nickname = Column(String(64), unique=True)
email = Column(String(120), unique=True, default="")
role = Column(SmallInteger, default=ROLE_USER)
password = Column(String)
kindle_mail = Column(String(120), default="")
shelf = relationship('Shelf', backref='user', lazy='dynamic')
downloads = relationship('Downloads', backref='user', lazy='dynamic')
locale = Column(String(2), default="en")
random_books = Column(Integer, default=1)
language_books = Column(Integer, default=1)
series_books = Column(Integer, default=1)
category_books = Column(Integer, default=1)
hot_books = Column(Integer, default=1)
default_language = Column(String(3), default="all")
class Anonymous(AnonymousUserMixin,UserBase):
def __init__(self):
self.loadSettings()
def loadSettings(self):
data=session.query(User).filter(User.role.op('&')(ROLE_ANONYMOUS) == ROLE_ANONYMOUS).first()
self.nickname = data.nickname
self.role = data.role
self.random_books = data.random_books
self.default_language = data.default_language
self.language_books = data.language_books
self.series_books = data.series_books
self.category_books = data.category_books
self.hot_books = data.hot_books
self.default_language = data.default_language
self.locale = data.locale
def role_admin(self):
return False
def is_active(self):
return False
def is_anonymous(self):
return config.ANON_BROWSE
class Shelf(Base): class Shelf(Base):
__tablename__ = 'shelf' __tablename__ = 'shelf'
...@@ -155,6 +194,8 @@ class Settings(Base): ...@@ -155,6 +194,8 @@ class Settings(Base):
def migrate_Database(): def migrate_Database():
if session.query(User).filter(User.role.op('&')(ROLE_ANONYMOUS) == ROLE_ANONYMOUS).first() is None:
create_anonymous_user()
try: try:
session.query(exists().where(User.random_books)).scalar() session.query(exists().where(User.random_books)).scalar()
session.commit() session.commit()
...@@ -213,6 +254,20 @@ def get_mail_settings(): ...@@ -213,6 +254,20 @@ def get_mail_settings():
return data return data
def create_anonymous_user():
user = User()
user.nickname = _("Guest")
user.email='no@email'
user.role = ROLE_ANONYMOUS
user.password = generate_password_hash('1')
session.add(user)
try:
session.commit()
except:
session.rollback()
pass
def create_admin_user(): def create_admin_user():
user = User() user = User()
...@@ -236,6 +291,7 @@ if not os.path.exists(dbpath): ...@@ -236,6 +291,7 @@ if not os.path.exists(dbpath):
Base.metadata.create_all(engine) Base.metadata.create_all(engine)
create_default_config() create_default_config()
create_admin_user() create_admin_user()
create_anonymous_user()
except Exception: except Exception:
pass pass
else: else:
......
This diff is collapsed.
This diff is collapsed.
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