commit
93720c9fdf
@ -1,4 +1,4 @@
|
||||
helper.py ident export-subst
|
||||
updater.py ident export-subst
|
||||
/test export-ignore
|
||||
cps/static/css/libs/* linguist-vendored
|
||||
cps/static/js/libs/* linguist-vendored
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
Binary file not shown.
After Width: | Height: | Size: 92 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,505 +1,349 @@
|
||||
/*! normalize.css v1.0.1 | MIT License | git.io/normalize */
|
||||
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
|
||||
|
||||
/* ==========================================================================
|
||||
HTML5 display definitions
|
||||
/* Document
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Corrects `block` display not defined in IE 6/7/8/9 and Firefox 3.
|
||||
*/
|
||||
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
nav,
|
||||
section,
|
||||
summary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Corrects `inline-block` display not defined in IE 6/7/8/9 and Firefox 3.
|
||||
*/
|
||||
|
||||
audio,
|
||||
canvas,
|
||||
video {
|
||||
display: inline-block;
|
||||
*display: inline;
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevents modern browsers from displaying `audio` without controls.
|
||||
* Remove excess height in iOS 5 devices.
|
||||
/**
|
||||
* 1. Correct the line height in all browsers.
|
||||
* 2. Prevent adjustments of font size after orientation changes in iOS.
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses styling for `hidden` attribute not present in IE 7/8/9, Firefox 3,
|
||||
* and Safari 4.
|
||||
* Known issue: no IE 6 support.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
html {
|
||||
line-height: 1.15; /* 1 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Base
|
||||
/* Sections
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* 1. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using
|
||||
* `em` units.
|
||||
* 2. Prevents iOS text size adjust after orientation change, without disabling
|
||||
* user zoom.
|
||||
/**
|
||||
* Remove the margin in all browsers.
|
||||
*/
|
||||
|
||||
html {
|
||||
font-size: 100%; /* 1 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
-ms-text-size-adjust: 100%; /* 2 */
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses `font-family` inconsistency between `textarea` and other form
|
||||
* elements.
|
||||
/**
|
||||
* Render the `main` element consistently in IE.
|
||||
*/
|
||||
|
||||
html,
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
font-family: sans-serif;
|
||||
main {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses margins handled incorrectly in IE 6/7.
|
||||
/**
|
||||
* Correct the font size and margin on `h1` elements within `section` and
|
||||
* `article` contexts in Chrome, Firefox, and Safari.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Links
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Addresses `outline` inconsistency between Chrome and other browsers.
|
||||
/**
|
||||
* 1. Add the correct box sizing in Firefox.
|
||||
* 2. Show the overflow in Edge and IE.
|
||||
*/
|
||||
|
||||
a:focus {
|
||||
outline: thin dotted;
|
||||
hr {
|
||||
box-sizing: content-box; /* 1 */
|
||||
height: 0; /* 1 */
|
||||
overflow: visible; /* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
* Improves readability when focused and also mouse hovered in all browsers.
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
a:active,
|
||||
a:hover {
|
||||
outline: 0;
|
||||
pre {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Typography
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Addresses font sizes and margins set differently in IE 6/7.
|
||||
* Addresses font sizes within `section` and `article` in Firefox 4+, Safari 5,
|
||||
* and Chrome.
|
||||
/**
|
||||
* Remove the gray background on active links in IE 10.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.5em;
|
||||
margin: 0.83em 0;
|
||||
a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.17em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1em;
|
||||
margin: 1.33em 0;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 0.83em;
|
||||
margin: 1.67em 0;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 0.75em;
|
||||
margin: 2.33em 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses styling not present in IE 7/8/9, Safari 5, and Chrome.
|
||||
/**
|
||||
* 1. Remove the bottom border in Chrome 57-
|
||||
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: 1px dotted;
|
||||
border-bottom: none; /* 1 */
|
||||
text-decoration: underline; /* 2 */
|
||||
text-decoration: underline dotted; /* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses style set to `bolder` in Firefox 3+, Safari 4/5, and Chrome.
|
||||
/**
|
||||
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 1em 40px;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses styling not present in Safari 5 and Chrome.
|
||||
*/
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses styling not present in IE 6/7/8/9.
|
||||
*/
|
||||
|
||||
mark {
|
||||
background: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses margins set differently in IE 6/7.
|
||||
*/
|
||||
|
||||
p,
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Corrects font family set oddly in IE 6, Safari 4/5, and Chrome.
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: monospace, serif;
|
||||
_font-family: 'courier new', monospace;
|
||||
font-size: 1em;
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
* Improves readability of pre-formatted text in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
white-space: pre;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses CSS quotes not supported in IE 6/7.
|
||||
*/
|
||||
|
||||
q {
|
||||
quotes: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses `quotes` property not supported in Safari 4.
|
||||
*/
|
||||
|
||||
q:before,
|
||||
q:after {
|
||||
content: '';
|
||||
content: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses inconsistent and variable font size in all browsers.
|
||||
/**
|
||||
* Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevents `sub` and `sup` affecting `line-height` in all browsers.
|
||||
/**
|
||||
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||
* all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Lists
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Addresses margins set differently in IE 6/7.
|
||||
/**
|
||||
* Remove the border on images inside links in IE 10.
|
||||
*/
|
||||
|
||||
dl,
|
||||
menu,
|
||||
ol,
|
||||
ul {
|
||||
margin: 1em 0;
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin: 0 0 0 40px;
|
||||
}
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Addresses paddings set differently in IE 6/7.
|
||||
/**
|
||||
* 1. Change the font styles in all browsers.
|
||||
* 2. Remove the margin in Firefox and Safari.
|
||||
*/
|
||||
|
||||
menu,
|
||||
ol,
|
||||
ul {
|
||||
padding: 0 0 0 40px;
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit; /* 1 */
|
||||
font-size: 100%; /* 1 */
|
||||
line-height: 1.15; /* 1 */
|
||||
margin: 0; /* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
* Corrects list images handled incorrectly in IE 7.
|
||||
/**
|
||||
* Show the overflow in IE.
|
||||
* 1. Show the overflow in Edge.
|
||||
*/
|
||||
|
||||
nav ul,
|
||||
nav ol {
|
||||
list-style: none;
|
||||
list-style-image: none;
|
||||
button,
|
||||
input { /* 1 */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* 1. Removes border when inside `a` element in IE 6/7/8/9 and Firefox 3.
|
||||
* 2. Improves image quality when scaled in IE 7.
|
||||
/**
|
||||
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||
* 1. Remove the inheritance of text transform in Firefox.
|
||||
*/
|
||||
|
||||
img {
|
||||
border: 0; /* 1 */
|
||||
-ms-interpolation-mode: bicubic; /* 2 */
|
||||
button,
|
||||
select { /* 1 */
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* Corrects overflow displayed oddly in IE 9.
|
||||
/**
|
||||
* Correct the inability to style clickable types in iOS and Safari.
|
||||
*/
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
button,
|
||||
[type="button"],
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Figures
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Addresses margin not present in IE 6/7/8/9, Safari 5, and Opera 11.
|
||||
/**
|
||||
* Remove the inner border and padding in Firefox.
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 0;
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Forms
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Corrects margin displayed oddly in IE 6/7.
|
||||
/**
|
||||
* Restore the focus styles unset by the previous rule.
|
||||
*/
|
||||
|
||||
form {
|
||||
margin: 0;
|
||||
button:-moz-focusring,
|
||||
[type="button"]:-moz-focusring,
|
||||
[type="reset"]:-moz-focusring,
|
||||
[type="submit"]:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
/*
|
||||
* Define consistent border, margin, and padding.
|
||||
/**
|
||||
* Correct the padding in Firefox.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
border: 1px solid #c0c0c0;
|
||||
margin: 0 2px;
|
||||
padding: 0.35em 0.625em 0.75em;
|
||||
padding: 0.35em 0.75em 0.625em;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Corrects color not being inherited in IE 6/7/8/9.
|
||||
* 2. Corrects text not wrapping in Firefox 3.
|
||||
* 3. Corrects alignment displayed oddly in IE 6/7.
|
||||
/**
|
||||
* 1. Correct the text wrapping in Edge and IE.
|
||||
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
* 3. Remove the padding so developers are not caught out when they zero out
|
||||
* `fieldset` elements in all browsers.
|
||||
*/
|
||||
|
||||
legend {
|
||||
border: 0; /* 1 */
|
||||
padding: 0;
|
||||
white-space: normal; /* 2 */
|
||||
*margin-left: -7px; /* 3 */
|
||||
box-sizing: border-box; /* 1 */
|
||||
color: inherit; /* 2 */
|
||||
display: table; /* 1 */
|
||||
max-width: 100%; /* 1 */
|
||||
padding: 0; /* 3 */
|
||||
white-space: normal; /* 1 */
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Corrects font size not being inherited in all browsers.
|
||||
* 2. Addresses margins set differently in IE 6/7, Firefox 3+, Safari 5,
|
||||
* and Chrome.
|
||||
* 3. Improves appearance and consistency in all browsers.
|
||||
/**
|
||||
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
font-size: 100%; /* 1 */
|
||||
margin: 0; /* 2 */
|
||||
vertical-align: baseline; /* 3 */
|
||||
*vertical-align: middle; /* 3 */
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses Firefox 3+ setting `line-height` on `input` using `!important` in
|
||||
* the UA stylesheet.
|
||||
/**
|
||||
* Remove the default vertical scrollbar in IE 10+.
|
||||
*/
|
||||
|
||||
button,
|
||||
input {
|
||||
line-height: normal;
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
|
||||
* and `video` controls.
|
||||
* 2. Corrects inability to style clickable `input` types in iOS.
|
||||
* 3. Improves usability and consistency of cursor style between image-type
|
||||
* `input` and others.
|
||||
* 4. Removes inner spacing in IE 7 without affecting normal text inputs.
|
||||
* Known issue: inner spacing remains in IE 6.
|
||||
/**
|
||||
* 1. Add the correct box sizing in IE 10.
|
||||
* 2. Remove the padding in IE 10.
|
||||
*/
|
||||
|
||||
button,
|
||||
html input[type="button"], /* 1 */
|
||||
input[type="reset"],
|
||||
input[type="submit"] {
|
||||
-webkit-appearance: button; /* 2 */
|
||||
cursor: pointer; /* 3 */
|
||||
*overflow: visible; /* 4 */
|
||||
[type="checkbox"],
|
||||
[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
* Re-set default cursor for disabled elements.
|
||||
/**
|
||||
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||
*/
|
||||
|
||||
button[disabled],
|
||||
input[disabled] {
|
||||
cursor: default;
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Addresses box sizing set to content-box in IE 8/9.
|
||||
* 2. Removes excess padding in IE 8/9.
|
||||
* 3. Removes excess padding in IE 7.
|
||||
* Known issue: excess padding remains in IE 6.
|
||||
/**
|
||||
* 1. Correct the odd appearance in Chrome and Safari.
|
||||
* 2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
*height: 13px; /* 3 */
|
||||
*width: 13px; /* 3 */
|
||||
[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
outline-offset: -2px; /* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome.
|
||||
* 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome
|
||||
* (include `-moz` to future-proof).
|
||||
/**
|
||||
* Remove the inner padding in Chrome and Safari on macOS.
|
||||
*/
|
||||
/*
|
||||
input[type="search"] {
|
||||
-webkit-appearance: textfield;
|
||||
-moz-box-sizing: content-box;
|
||||
-webkit-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* Removes inner padding and search cancel button in Safari 5 and Chrome
|
||||
* on OS X.
|
||||
/**
|
||||
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
* 2. Change font properties to `inherit` in Safari.
|
||||
*/
|
||||
|
||||
/* input[type="search"]::-webkit-search-cancel-button,
|
||||
input[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
} */
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
}
|
||||
|
||||
/* Interactive
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Removes inner padding and border in Firefox 3+.
|
||||
* Add the correct display in Edge, IE 10+, and Firefox.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
input::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
details {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Removes default vertical scrollbar in IE 6/7/8/9.
|
||||
* 2. Improves readability and alignment in all browsers.
|
||||
* Add the correct display in all browsers.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto; /* 1 */
|
||||
vertical-align: top; /* 2 */
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Tables
|
||||
/* Misc
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Remove most spacing between table cells.
|
||||
/**
|
||||
* Add the correct display in IE 10+.
|
||||
*/
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
@media (min-device-width: 768px) {
|
||||
.upload-modal-dialog {
|
||||
position: absolute;
|
||||
top: 45%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%) !important;
|
||||
}
|
||||
}
|
@ -0,0 +1,708 @@
|
||||
/* This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
|
||||
* Copyright (C) 2018-2019 hexeth
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Move advanced search to side-menu
|
||||
$( 'a[href*="advanced"]' ).parent().insertAfter( '#nav_new' );
|
||||
$( 'body' ).addClass('blur');
|
||||
$( 'body.stat' ).addClass( 'stats' );
|
||||
$( 'body.config' ).addClass( 'admin');
|
||||
$( 'body.uiconfig' ).addClass( 'admin');
|
||||
$( 'body.advsearch' ).addClass( 'advanced_search' );
|
||||
$( 'body.newuser' ).addClass( 'admin' );
|
||||
$( 'body.mailset' ).addClass( 'admin' );
|
||||
|
||||
// Back button
|
||||
curHref = window.location.href.split('/');
|
||||
prevHref = document.referrer.split('/');
|
||||
$( '.navbar-form.navbar-left' )
|
||||
.before( '<div class="plexBack"><a href="' + document.referrer + '"></a></div>' );
|
||||
if ( history.length === 1 ||
|
||||
curHref[0] +
|
||||
curHref[1] +
|
||||
curHref[2] !=
|
||||
prevHref[0] +
|
||||
prevHref[1] +
|
||||
prevHref[2] ||
|
||||
$( 'body.root' )>length > 0 ) {
|
||||
$( '.plexBack' ).addClass( 'noBack' );
|
||||
}
|
||||
|
||||
//Weird missing a after pressing back from edit.
|
||||
setTimeout(function() {
|
||||
if ( $( '.plexBack a').length < 1 ) {
|
||||
$( '.plexBack' ).append('<a href="' + document.referrer + '"></a>');
|
||||
}
|
||||
},10);
|
||||
|
||||
// Home button
|
||||
$( '.plexBack' ).before( '<div class="home-btn"></div>' );
|
||||
$( 'a.navbar-brand' ).clone().appendTo( '.home-btn' ).empty().removeClass('navbar-brand');
|
||||
/////////////////////////////////
|
||||
// Start of Book Details Work //
|
||||
///////////////////////////////
|
||||
|
||||
// Wrap book description in div container
|
||||
if ( $( 'body.book' ).length > 0 ) {
|
||||
|
||||
description = $( '.comments' );
|
||||
bookInfo = $( '.author' ).nextUntil( 'h3:contains("Description")');
|
||||
$( 'h3:contains("Description")' ).detach();
|
||||
$( '.comments' ).detach();
|
||||
$( bookInfo ).wrapAll( '<div class="bookinfo"></div>' );
|
||||
// $( 'h3:contains("Description:")' ).after( '<div class="description"></div>' );
|
||||
$( '.languages' ).appendTo( '.bookinfo' );
|
||||
$('.hr').detach();
|
||||
if ( $( '.identifiers ').length > 0 ) {
|
||||
console.log(".identifiers length " + $( '.identifiers ').length );
|
||||
$( '.identifiers' ).before( '<div class="hr"></div>' );
|
||||
} else {
|
||||
if ( $( '.bookinfo > p:first-child' ).length > 0 ) {
|
||||
console.log(".bookinfo > p:first-child length " + $( '.bookinfo > p' ).length );
|
||||
$( '.bookinfo > p:first-child' ).first().after( '<div class="hr"></div>' );
|
||||
} else{
|
||||
if ( $( '.bookinfo a[href*="/series/"]' ).length > 0 ) {
|
||||
console.log( 'series text found; placing hr below series' );
|
||||
$( '.bookinfo a[href*="/series/"]' ).parent().after( '<div class="hr"></div>' );
|
||||
} else {
|
||||
console.log("prepending hr div to top of .bookinfo");
|
||||
$( '.bookinfo' ).prepend( '<div class="hr"></div>' );
|
||||
}
|
||||
}
|
||||
}
|
||||
$( '.rating' ).insertBefore( '.hr' );
|
||||
$( '#remove-from-shelves' ).insertAfter( '.hr' );
|
||||
$( description ).appendTo('.bookinfo')
|
||||
/* if book description is not in html format, Remove extra line breaks
|
||||
Remove blank lines/unnecessary spaces, split by line break to array
|
||||
Push array into .description div. If there is still a wall of text,
|
||||
find sentences and split wall into groups of three sentence paragraphs.
|
||||
If the book format is in html format, Keep html, but strip away inline
|
||||
styles and empty elements */
|
||||
|
||||
// If text is sitting in div as text node
|
||||
if ( $('.comments:has(p)' ).length === 0 ) {
|
||||
newdesc = description.text()
|
||||
.replace(/^(?=\n)$|^\s*|\s*$|\n\n+/gm,"").split(/\n/);
|
||||
$('.comments' ).empty();
|
||||
$.each(newdesc, function(i, val) {
|
||||
$( 'div.comments' ).append( '<p>' + newdesc[i] + '</p>' );
|
||||
});
|
||||
$( '.comments' ).fadeIn(100);
|
||||
} //If still a wall of text create 3 sentence paragraphs.
|
||||
if( $( '.comments p' ).length === 1 ) {
|
||||
if ( description.context != undefined ) {
|
||||
newdesc = description.text()
|
||||
.replace(/^(?=\n)$|^\s*|\s*$|\n\n+/gm,"").split(/\n/);
|
||||
}
|
||||
else {
|
||||
newdesc = description.text();
|
||||
}
|
||||
doc = nlp ( newdesc.toString() );
|
||||
sentences = doc.map((m)=> m.out( 'text' ));
|
||||
sentences[0] = sentences[0].replace(",","");
|
||||
$( '.comments p' ).remove();
|
||||
let size = 3; let sentenceChunks = [];
|
||||
for (var i=0; i<sentences.length; i+=size) {
|
||||
sentenceChunks.push(sentences.slice(i,i+size));
|
||||
}
|
||||
let output = '';
|
||||
$.each(sentenceChunks, function(i, val) {
|
||||
let preOutput = '';
|
||||
$.each(val, function(i, val) {
|
||||
preOutput += val;
|
||||
});
|
||||
output += '<p>' + preOutput + '</p>';
|
||||
});
|
||||
$( 'div.comments' ).append( output );
|
||||
}
|
||||
else {
|
||||
$.each(description, function(i, val) {
|
||||
// $( description[i].outerHTML ).appendTo( '.comments' );
|
||||
$( 'div.comments :empty' ).remove();
|
||||
$( 'div.comments ').attr( 'style', '' );
|
||||
});
|
||||
$( 'div.comments' ).fadeIn( 100 );
|
||||
}
|
||||
|
||||
// Sexy blurred backgrounds
|
||||
cover = $( '.cover img' ).attr( 'src' );
|
||||
$( '#loader + .container-fluid' )
|
||||
.prepend( '<div class="blur-wrapper"></div' );
|
||||
$( '.blur-wrapper' )
|
||||
.prepend( '<div><img class="bg-blur" src="' + cover + '"></div>' );
|
||||
|
||||
// Fix-up book detail headings
|
||||
publisher = $( '.publishers p span' ).text().split( ':' );
|
||||
$( '.publishers p span' ).remove();
|
||||
$.each(publisher, function(i, val) {
|
||||
$( '.publishers' ).append( '<span>' + publisher[i] + '</span>' );
|
||||
});
|
||||
$( '.publishers span:nth-child(3)' ).text(function() {
|
||||
return $(this).text().replace(/^\s+|^\t+|\t+|\s+$/g, "");
|
||||
});
|
||||
|
||||
published = $( '.publishing-date p' )
|
||||
.text().split(': ');
|
||||
$( '.publishing-date p' ).remove();
|
||||
$.each(published, function(i, val) {
|
||||
$( '.publishing-date' ).append( '<span>' + published[i] + '</span>' );
|
||||
});
|
||||
|
||||
languages = $( '.languages p span' ).text().split( ': ' );
|
||||
$( '.languages p span' ).remove();
|
||||
$.each(languages, function(i, val) {
|
||||
$( '.languages' ).append( '<span>' + languages[i] + '</span>' );
|
||||
});
|
||||
|
||||
$( '.book-meta h2:first' ).clone()
|
||||
.prependTo( '.book-meta > .btn-toolbar:first' );
|
||||
|
||||
// If only one download type exists still put the items into a drop-drown list.
|
||||
downloads = $( 'a[id^=btnGroupDrop]' ).get();
|
||||
if ( $( downloads ).length === 1 ) {
|
||||
$( '<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="caret"></span></button><ul class="dropdown-menu leramslist aria-labelledby="btnGroupDrop1"></ul>' ).insertBefore( downloads[downloads.length-1] );
|
||||
$( downloads ).detach();
|
||||
$.each(downloads, function(i, val) {
|
||||
$( '<li>' + downloads[i].outerHTML + '</li>' ).appendTo( '.leramslist' );
|
||||
});
|
||||
$( '.leramslist' ).find( 'span' ).remove();
|
||||
$( '.leramslist a' ).removeClass( 'btn btn-primary' ).removeAttr( 'role' );
|
||||
}
|
||||
|
||||
// Add classes to buttons
|
||||
$( '#sendbtn' ).parent().addClass( 'sendBtn' );
|
||||
$( '[id*=btnGroupDrop]' ).parent().addClass( 'downloadBtn' );
|
||||
$( 'read-in-browser' ).parent().addClass( 'readBtn' );
|
||||
$( '.downloadBtn button:first' ).addClass( 'download-text' );
|
||||
|
||||
// Move all options in book details page to the same group
|
||||
$( '[aria-label*="Delete book"]' )
|
||||
.prependTo( '[aria-label^="Download, send"]' )
|
||||
.children().removeClass( 'btn-sm' );
|
||||
$( '.custom_columns' )
|
||||
.addClass(' btn-group' )
|
||||
.attr('role', 'group' )
|
||||
.removeClass( 'custom_columns' )
|
||||
.prependTo( '[aria-label^="Download, send"]' );
|
||||
$( '#have_read_cb' )
|
||||
.after( '<label class="block-label readLbl" for="#have_read_cb"></label>' );
|
||||
$( '#shelf-actions' ).prependTo( '[aria-label^="Download, send"]' );
|
||||
|
||||
|
||||
// Move dropdown lists higher in dom, replace bootstrap toggle with own toggle.
|
||||
$( 'ul[aria-labelledby="read-in-browser"]' ).insertBefore( '.blur-wrapper' ).addClass('readinbrowser-drop');
|
||||
$( 'ul[aria-labelledby="send-to-kindle"]' ).insertBefore( '.blur-wrapper' ).addClass('sendtokindle-drop');
|
||||
$( '.leramslist' ).insertBefore( '.blur-wrapper' );
|
||||
$( 'ul[aria-labelledby="btnGroupDrop1"]' ).insertBefore( '.blur-wrapper' ).addClass('leramslist');
|
||||
$( '#add-to-shelves' ).insertBefore( '.blur-wrapper' );
|
||||
|
||||
$( '#read-in-browser' ).click( function() {
|
||||
$( '.readinbrowser-drop' ).toggle();
|
||||
});
|
||||
|
||||
$('.downloadBtn' ).click( function() {
|
||||
$( '.leramslist' ).toggle();
|
||||
});
|
||||
|
||||
$('#sendbtn2' ).click( function() {
|
||||
$( '.sendtokindle-drop' ).toggle();
|
||||
});
|
||||
|
||||
|
||||
$('div[aria-label="Add to shelves"]' ).click( function() {
|
||||
$( '#add-to-shelves' ).toggle();
|
||||
});
|
||||
|
||||
// Fix formatting error on book detail languages
|
||||
if ( !$( '.book-meta > .bookinfo > .languages > span:last-of-type' ).text().startsWith(" ") ) {
|
||||
$( '.book-meta > .bookinfo > .languages > span:last-of-type' ).prepend(" ");
|
||||
}
|
||||
|
||||
//Work to reposition dropdowns. Does not currently solve for
|
||||
//screen resizing
|
||||
function dropdownToggle() {
|
||||
|
||||
topPos = $( '.book-meta > .btn-toolbar:first' ).offset().top
|
||||
|
||||
if ( $( '#read-in-browser' ).length > 0 ) {
|
||||
position = $( '#read-in-browser' ).offset().left
|
||||
if ( position + $( '.readinbrowser-drop' ).width() > $( window ).width() ) {
|
||||
positionOff = position + $( '.readinbrowser-drop' ).width() - $( window ).width();
|
||||
ribPosition = position - positionOff - 5
|
||||
$( '.readinbrowser-drop' ).attr("style", "left: " + ribPosition + "px !important; right: auto; top: " + topPos + "px");
|
||||
} else {
|
||||
$( '.readinbrowser-drop' ).attr("style", "left: " + position + "px !important; right: auto; top: " + topPos + "px");
|
||||
}
|
||||
}
|
||||
|
||||
if ( $( '#sendbtn2' ).length > 0 ) {
|
||||
position = $( '#sendbtn2' ).offset().left
|
||||
if ( position + $( '.sendtokindle-drop' ).width() > $( window ).width() ) {
|
||||
positionOff = position + $( '.sendtokindle-drop' ).width() - $( window ).width();
|
||||
ribPosition = position - positionOff - 5
|
||||
$( '.sendtokindle-drop' ).attr("style", "left: " + ribPosition + "px !important; right: auto; top: " + topPos + "px");
|
||||
} else {
|
||||
$( '.sendtokindle-drop' ).attr("style", "left: " + position + "px !important; right: auto; top: " + topPos + "px");
|
||||
}
|
||||
}
|
||||
|
||||
if ( $( '.downloadBtn' ).length > 0 ) {
|
||||
|
||||
position = $( '#btnGroupDrop1' ).offset().left
|
||||
|
||||
if ( position + $( '.leramslist' ).width() > $( window ).width() ) {
|
||||
positionOff = position + $( '.leramslist' ).width() - $( window ).width();
|
||||
dlPosition = position - positionOff - 5
|
||||
$( '.leramslist' ).attr("style", "left: " + dlPosition + "px !important; right: auto; top: " + topPos + "px");
|
||||
} else {
|
||||
$( '.leramslist' ).attr("style", "left: " + position + "px !important; right: auto; top: " + topPos + "px");
|
||||
}
|
||||
}
|
||||
|
||||
if ( $( 'div[aria-label="Add to shelves"]' ).length > 0 ) {
|
||||
|
||||
position = $( 'div[aria-label="Add to shelves"]' ).offset().left
|
||||
|
||||
if ( position + $( '#add-to-shelves' ).width() > $( window ).width() ) {
|
||||
positionOff = position + $( '#add-to-shelves' ).width() - $( window ).width();
|
||||
adsPosition = position - positionOff - 5
|
||||
$( '#add-to-shelves' ).attr("style", "left: " + adsPosition + "px !important; right: auto; top: " + topPos + "px");
|
||||
} else {
|
||||
$( '#add-to-shelves' ).attr("style", "left: " + position + "px !important; right: auto; top: " + topPos + "px");
|
||||
}
|
||||
}
|
||||
}
|
||||
dropdownToggle();
|
||||
|
||||
$( window ).on( 'resize', function() {
|
||||
dropdownToggle();
|
||||
});
|
||||
|
||||
// Clone book rating for mobile view.
|
||||
$( '.book-meta > .bookinfo > .rating' ).clone().insertBefore( '.book-meta > .description' ).addClass('rating-mobile');
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
// End of Book Details Work //
|
||||
/////////////////////////////
|
||||
|
||||
/////////////////////////////////
|
||||
// Start of Global Work //
|
||||
///////////////////////////////
|
||||
|
||||
// Hide dropdown and collapse menus on click-off
|
||||
$(document).mouseup(function (e) {
|
||||
var container = new Array();
|
||||
container.push($('ul[aria-labelledby="read-in-browser"]'));
|
||||
container.push($('.sendtokindle-drop'));
|
||||
container.push($('.leramslist'));
|
||||
container.push($('#add-to-shelves'));
|
||||
container.push($('.navbar-collapse.collapse.in'));
|
||||
|
||||
$.each(container, function(key, value) {
|
||||
if (!$(value).is(e.target) // if the target of the click isn't the container...
|
||||
&& $(value).has(e.target).length === 0) // ... nor a descendant of the container
|
||||
{
|
||||
if ( $(value).hasClass('dropdown-menu') )
|
||||
{
|
||||
$(value).hide();
|
||||
} else
|
||||
{
|
||||
if ( $(value).hasClass('collapse') )
|
||||
{
|
||||
$(value).collapse('toggle');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Split path name to array and remove blanks
|
||||
url = window.location.pathname
|
||||
|
||||
// Move create shelf
|
||||
$( '#nav_createshelf' ).prependTo( '.your-shelves' );
|
||||
|
||||
// Create drop-down for profile and move elements to it
|
||||
$( '#main-nav' )
|
||||
.prepend( '<li class="dropdown"><a href="#" class="dropdown-toggle profileDrop" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-user"></span></a><ul class="dropdown-menu profileDropli"></ul></li>' );
|
||||
$( '#top_user' ).parent().addClass( 'dropdown' ).appendTo( '.profileDropli' );
|
||||
$( '#nav_about' ).addClass( 'dropdown' ).appendTo( '.profileDropli' );
|
||||
$( '#register' ).parent().addClass( 'dropdown' ).appendTo( '.profileDropli' );
|
||||
$( '#logout' ).parent().addClass( 'dropdown' ).appendTo( '.profileDropli' );
|
||||
|
||||
// Remove the modals except from some areas where they are needed
|
||||
bodyClass = $( 'body' ).attr( 'class' ).split(' ');
|
||||
modalWanted = ['admin', 'editbook', 'config', 'uiconfig'];
|
||||
|
||||
if ( $.inArray( bodyClass[0], modalWanted) != -1 ) {
|
||||
} else {
|
||||
$(' a:not(.dropdown-toggle) ')
|
||||
.removeAttr( 'data-toggle', 'data-target', 'data-remote' );
|
||||
}
|
||||
|
||||
|
||||
// Add classes to global buttons
|
||||
$( '#top_tasks' ).parent().addClass( 'top_tasks' );
|
||||
$( '#top_admin' ).parent().addClass( 'top_admin' );
|
||||
$( '#form-upload' ).parent().addClass( 'form-upload' );
|
||||
|
||||
// Search button work
|
||||
$( 'input#query' ).focus(function() {
|
||||
$( 'form[role="search"]' ).addClass( 'search-focus' );
|
||||
});
|
||||
$( 'input#query' ).focusout(function() {
|
||||
setTimeout(function() {
|
||||
$( 'form[role="search"]' ).removeClass( 'search-focus' );
|
||||
}, 100);
|
||||
});
|
||||
|
||||
// Check if dropdown goes out of viewport and add class
|
||||
|
||||
$(document).on('click','.dropdown-toggle',function() {
|
||||
// Add .offscreen if part of container not visible
|
||||
$('.dropdown-menu:visible').filter(function(){
|
||||
return $(this).visible() === false;
|
||||
}).each(function(){
|
||||
$(this).addClass('offscreen');
|
||||
});
|
||||
});
|
||||
|
||||
// Fade out content on page unload
|
||||
// delegate all clicks on "a" tag (links)
|
||||
/*$(document).on("click", "a:not(.btn-toolbar a, a[href*='shelf/remove'], .identifiers a, .bookinfo , .btn-group > a, #add-to-shelves a, #book-list a, .stat.blur a )", function () {
|
||||
|
||||
// get the href attribute
|
||||
var newUrl = $(this).attr("href");
|
||||
|
||||
// veryfy if the new url exists or is a hash
|
||||
if (!newUrl || newUrl[0] === "#") {
|
||||
// set that hash
|
||||
location.hash = newUrl;
|
||||
return;
|
||||
}
|
||||
|
||||
now, fadeout the html (whole page)
|
||||
$( '.blur-wrapper' ).fadeOut(250);
|
||||
$(".row-fluid .col-sm-10").fadeOut(500,function () {
|
||||
// when the animation is complete, set the new location
|
||||
location = newUrl;
|
||||
});
|
||||
|
||||
// prevent the default browser behavior.
|
||||
return false;
|
||||
});*/
|
||||
|
||||
// Collapse long text into read-more
|
||||
$( 'div.comments' ).readmore( {
|
||||
collapsedHeight: 134,
|
||||
heightMargin: 45,
|
||||
speed: 300,
|
||||
moreLink: '<a href="#">READ MORE</a>', // ToDo: make translateable
|
||||
lessLink: '<a href="#">READ LESS</a>', // ToDo: make translateable
|
||||
});
|
||||
/////////////////////////////////
|
||||
// End of Global Work //
|
||||
///////////////////////////////
|
||||
|
||||
// Author Page Background Blur
|
||||
if ( $( 'body.author' ).length >0 ) {
|
||||
cover = $( '.author-bio img' ).attr( 'src' );
|
||||
$( '#loader + .container-fluid' )
|
||||
.prepend( '<div class="blur-wrapper"></div>' );
|
||||
$( '.blur-wrapper' ).prepend( '<img class="bg-blur" src="' + cover + '">' );
|
||||
// Place undefined cover images inside container
|
||||
if ( $( '.bg-blur[src="undefined"]' ).length > 0 ) {
|
||||
$( '.bg-blur' ).before( '<div class="bg-blur undefined-img"></div>' );
|
||||
$( 'img.bg-blur' ).appendTo( '.undefined-img' );
|
||||
}
|
||||
}
|
||||
|
||||
// Ereader Page - add class to iframe body on ereader page after it loads.
|
||||
backurl = '../../book/' + url[2]
|
||||
$( 'body.epub #title-controls' )
|
||||
.append('<div class="epub-back"><input action="action" onclick="location.href=backurl; return false;" type="button" value="Back" /></div>')
|
||||
|
||||
$( 'body.stat .col-sm-10 p:first' ).insertAfter( '#libs' );
|
||||
|
||||
// Check if link is external and force _blank attribute
|
||||
$(function(){ // document ready
|
||||
$( 'a' ).filter(function () {
|
||||
return this.hostname && this.hostname !== location.hostname;
|
||||
}).each(function () {
|
||||
$(this).addClass("external").attr( 'target', '_blank' );
|
||||
});
|
||||
});
|
||||
|
||||
// Check if lists are empty and add class to buttons
|
||||
if ( $.trim( $('#add-to-shelves').html() ).length === 0 ) {
|
||||
$( '#add-to-shelf' ).addClass( 'empty-ul' );
|
||||
}
|
||||
|
||||
shelfLength = $('#add-to-shelves li').length
|
||||
emptyLength = 0
|
||||
|
||||
$('#add-to-shelves').on('click','li a',function(){
|
||||
console.log('#remove-from-shelves change registered' );
|
||||
emptyLength++
|
||||
|
||||
setTimeout(function() {
|
||||
if ( emptyLength >= shelfLength ) {
|
||||
console.log('list is empty; adding empty-ul class' );
|
||||
$( '#add-to-shelf' ).addClass( 'empty-ul' );
|
||||
} else {
|
||||
console.log('list is not empty; removing empty-ul class' );
|
||||
$( '#add-to-shelf' ).removeClass( 'empty-ul' );
|
||||
}
|
||||
},100);
|
||||
});
|
||||
|
||||
if ( $.trim( $( 'ul[aria-labelledby="read-in-browser"] li' ).html() ).length === 0 ) {
|
||||
$('#read-in-browser').addClass('empty-ul');
|
||||
}
|
||||
|
||||
// Shelf Buttons and Tooltips
|
||||
if ( $( 'body.shelf' ).length > 0 ) {
|
||||
$( 'div[data-target="#DeleteShelfDialog"]' )
|
||||
.before( '<div class=".btn-group shelf-btn-group"></div>' )
|
||||
.appendTo( '.shelf-btn-group' )
|
||||
.addClass( 'delete-shelf-btn' );
|
||||
|
||||
$( 'a[href*="edit"]' )
|
||||
.appendTo( '.shelf-btn-group' )
|
||||
.addClass( 'edit-shelf-btn' );
|
||||
|
||||
$( 'a[href*="order"]' )
|
||||
.appendTo( '.shelf-btn-group' )
|
||||
.addClass( 'order-shelf-btn' );
|
||||
$( '.delete-shelf-btn' ).attr({
|
||||
'data-toggle-two': 'tooltip',
|
||||
'title': $( '.delete-shelf-btn' ).text(), // 'Delete Shelf'
|
||||
'data-placement': 'bottom' })
|
||||
.addClass('delete-btn-tooltip');
|
||||
|
||||
$( '.edit-shelf-btn' ).attr({
|
||||
'data-toggle-two': 'tooltip',
|
||||
'title': $( '.edit-shelf-btn' ).text(), // 'Edit Shelf'
|
||||
'data-placement': 'bottom' })
|
||||
.addClass('edit-btn-tooltip');
|
||||
|
||||
$( '.order-shelf-btn' ).attr({
|
||||
'data-toggle-two': 'tooltip',
|
||||
'title': $( '.order-shelf-btn' ).text(), //'Reorder Shelf'
|
||||
'data-placement': 'bottom' })
|
||||
.addClass('order-btn-tooltip');
|
||||
}
|
||||
|
||||
// Rest of Tooltips
|
||||
$( '.home-btn > a' ).attr({
|
||||
'data-toggle': 'tooltip',
|
||||
'title': $(document.body).attr('data-text'), // Home
|
||||
'data-placement': 'bottom' })
|
||||
.addClass('home-btn-tooltip');
|
||||
|
||||
$( '.plexBack > a' ).attr({
|
||||
'data-toggle': 'tooltip',
|
||||
'title': $(document.body).attr('data-textback'), // Back
|
||||
'data-placement': 'bottom' })
|
||||
.addClass('back-btn-tooltip');
|
||||
|
||||
$( '#top_tasks' ).attr({
|
||||
'data-toggle': 'tooltip',
|
||||
'title': $( '#top_tasks' ).text(), // 'Tasks'
|
||||
'data-placement': 'bottom',
|
||||
'data-viewport': '#main-nav' })
|
||||
.addClass('tasks-btn-tooltip');
|
||||
|
||||
$( '#top_admin' ).attr({
|
||||
'data-toggle': 'tooltip',
|
||||
'title': $( '#top_admin' ).attr('data-text'), // Settings
|
||||
'data-placement': 'bottom',
|
||||
'data-viewport': '#main-nav' })
|
||||
.addClass('admin-btn-tooltip');
|
||||
|
||||
$( '.profileDrop' ).attr({
|
||||
'title': $( '#top_user' ).attr('data-text'), //Account
|
||||
'data-placement': 'bottom',
|
||||
'data-toggle-two': 'tooltip',
|
||||
'data-viewport': '#main-nav' })
|
||||
.addClass('send-btn-tooltip dropdown');
|
||||
|
||||
$( '#btn-upload' ).attr({
|
||||
'data-toggle': 'tooltip',
|
||||
'title': $( '#btn-upload' ).parent().text() , // 'Upload'
|
||||
'data-placement': 'bottom',
|
||||
'data-viewport': '#main-nav' })
|
||||
.addClass('upload-btn-tooltip');
|
||||
|
||||
$( '#add-to-shelf' ).attr({
|
||||
'data-toggle-two': 'tooltip',
|
||||
'title': $( '#add-to-shelf' ).text() , // 'Add to Shelf'
|
||||
'data-placement': 'bottom',
|
||||
'data-viewport': '.btn-toolbar' })
|
||||
.addClass('addtoshelf-btn-tooltip');
|
||||
|
||||
$( '#have_read_cb' ).attr({
|
||||
'data-toggle': 'tooltip',
|
||||
'title': $( '#have_read_cb').attr('data-unchecked'),
|
||||
'data-placement': 'bottom',
|
||||
'data-viewport': '.btn-toolbar' })
|
||||
.addClass('readunread-btn-tooltip');
|
||||
|
||||
$( '#have_read_cb:checked' ).attr({
|
||||
'data-toggle': 'tooltip',
|
||||
'title': $( '#have_read_cb').attr('data-checked'),
|
||||
'data-placement': 'bottom',
|
||||
'data-viewport': '.btn-toolbar' })
|
||||
.addClass('readunread-btn-tooltip');
|
||||
|
||||
$( 'button#delete' ).attr({
|
||||
'data-toggle-two': 'tooltip',
|
||||
'title': $( 'button#delete' ).text(), //'Delete'
|
||||
'data-placement': 'bottom',
|
||||
'data-viewport': '.btn-toolbar' })
|
||||
.addClass('delete-book-btn-tooltip');
|
||||
|
||||
$( '#have_read_cb' ).click(function() {
|
||||
if ( $( '#have_read_cb:checked' ).length > 0 ) {
|
||||
$( this ).attr('data-original-title', $('#have_read_cb').attr('data-checked'));
|
||||
} else {
|
||||
$( this).attr('data-original-title', $('#have_read_cb').attr('data-unchecked'));
|
||||
}
|
||||
});
|
||||
|
||||
$( '.btn-group[aria-label="Edit/Delete book"] a' ).attr({
|
||||
'data-toggle': 'tooltip',
|
||||
'title': $( '#edit_book' ).text(), // 'Edit'
|
||||
'data-placement': 'bottom',
|
||||
'data-viewport': '.btn-toolbar' })
|
||||
.addClass('edit-btn-tooltip');
|
||||
|
||||
$( '#sendbtn' ).attr({
|
||||
'data-toggle': 'tooltip',
|
||||
'title': $( '#sendbtn' ).attr('data-text'),
|
||||
'data-placement': 'bottom',
|
||||
'data-viewport': '.btn-toolbar' })
|
||||
.addClass('send-btn-tooltip');
|
||||
|
||||
$( '#sendbtn2' ).attr({
|
||||
'data-toggle-two': 'tooltip',
|
||||
'title': $( '#sendbtn2' ).text(), // 'Send to Kindle',
|
||||
'data-placement': 'bottom',
|
||||
'data-viewport': '.btn-toolbar' })
|
||||
.addClass('send-btn-tooltip');
|
||||
|
||||
$( '#read-in-browser' ).attr({
|
||||
'data-toggle-two': 'tooltip',
|
||||
'title': $( '#read-in-browser' ).text(),
|
||||
'data-placement': 'bottom',
|
||||
'data-viewport': '.btn-toolbar'})
|
||||
.addClass('send-btn-tooltip');
|
||||
|
||||
$( '#btnGroupDrop1' ).attr({
|
||||
'data-toggle-two': 'tooltip',
|
||||
'title': $( '#btnGroupDrop1' ).text(),
|
||||
'data-placement': 'bottom',
|
||||
'data-viewport': '.btn-toolbar' });
|
||||
|
||||
if ( $( 'body.epub').length === 0 ) {
|
||||
$(document).ready(function(){
|
||||
$('[data-toggle="tooltip"]').tooltip({container: 'body', trigger: 'hover'});
|
||||
$('[data-toggle-two="tooltip"]').tooltip({container: 'body', trigger: 'hover'});
|
||||
$( '#btn-upload' ).attr('title', " ");
|
||||
});
|
||||
|
||||
|
||||
$( '[data-toggle-two="tooltip"]' ).click(function(){
|
||||
$('[data-toggle-two="tooltip"]').tooltip('hide');
|
||||
});
|
||||
|
||||
$( '[data-toggle="tooltip"]' ).click(function(){
|
||||
$('[data-toggle="tooltip"]').tooltip('hide');
|
||||
});
|
||||
}
|
||||
|
||||
$( '#read-in-browser a' ).attr('target',"");
|
||||
|
||||
if ( $( '.edit-shelf-btn').length > 1 ) {
|
||||
$( '.edit-shelf-btn:first').remove();
|
||||
}
|
||||
if ( $( '.order-shelf-btn').length > 1 ) {
|
||||
$( '.order-shelf-btn:first').remove();
|
||||
}
|
||||
|
||||
$( '#top_user > span.hidden-sm' ).clone().insertBefore( '.profileDropli' );
|
||||
$( '.navbar-collapse.collapse.in').before('<div class="sidebar-backdrop"></div>');
|
||||
|
||||
// Get rid of leading white space
|
||||
recentlyAdded = $( '#nav_new a:contains("Recently")' ).text().trim();
|
||||
$('#nav_new a:contains("Recently")').contents().filter(function() {
|
||||
return this.nodeType == 3
|
||||
}).each(function(){
|
||||
this.textContent = this.textContent.replace(' Recently Added',recentlyAdded);
|
||||
});
|
||||
|
||||
// Change shelf textValue
|
||||
shelfText = $( '.shelf .discover h2:first' ).text().replace(':',' —').replace(/\'/g,'');
|
||||
$( '.shelf .discover h2:first' ).text(shelfText);
|
||||
|
||||
shelfText = $( '.shelforder .col-sm-10 .col-sm-6.col-lg-6.col-xs-6 h2:first' ).text().replace(':',' —').replace(/\'/g,'');
|
||||
$( '.shelforder .col-sm-10 .col-sm-6.col-lg-6.col-xs-6 h2:first' ).text(shelfText);
|
||||
|
||||
|
||||
function mobileSupport() {
|
||||
if ( $( window ).width() <= 768 ) {
|
||||
//Move menu to collapse
|
||||
$( '.row-fluid > .col-sm-2:first' ).appendTo( '.navbar-collapse.collapse:first');
|
||||
if ( $( '.sidebar-backdrop' ).length < 1 ) {
|
||||
$( '.navbar-collapse.collapse:first' ).after( '<div class="sidebar-backdrop"></div>' );
|
||||
}
|
||||
} else {
|
||||
//Move menu out of collapse
|
||||
$( '.col-sm-2:first' ).insertBefore( '.col-sm-10:first');
|
||||
$( '.sidebar-backdrop' ).remove();
|
||||
}
|
||||
}
|
||||
|
||||
// LayerCake plug
|
||||
if ( $(' body.stat p').length > 0 ) {
|
||||
$(' body.stat p').append(" and <a href='https://github.com/leram84/layer.Cake/tree/master/caliBlur' target='_blank'>layer.Cake</a>");
|
||||
str = $(' body.stat p').html().replace("</a>.","</a>");
|
||||
$(' body.stat p').html(str);
|
||||
}
|
||||
// Collect delete buttons in editbook to single dropdown
|
||||
$( '.editbook .text-center.more-stuff' ).prepend( '<button id="deleteButton" type="button" class="btn btn-danger dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-remove"></span>Delete Format<span class="caret"></span></button><ul class="dropdown-menu delete-dropdown"></ul>' );
|
||||
|
||||
deleteButtons = $( '.editbook .text-center.more-stuff a' ).removeClass('btn btn-danger' ).attr( 'type', '').get();
|
||||
|
||||
$( deleteButtons ).detach();
|
||||
$( '.editbook .text-center.more-stuff h4' ).remove();
|
||||
$.each(deleteButtons, function(i, val) {
|
||||
$( '<li>' + deleteButtons[i].outerHTML + '</li>' ).appendTo( '.delete-dropdown' );
|
||||
});
|
||||
|
||||
// Turn off bootstrap animations
|
||||
$(function() { $.support.transition = false; })
|
||||
|
||||
mobileSupport();
|
||||
|
||||
// Only call function once resize is complete
|
||||
//var id;
|
||||
$( window ).on('resize',function() {
|
||||
// clearTimeout(id);
|
||||
// id = setTimeout(mobileSupport, 500);
|
||||
mobileSupport();
|
||||
});
|
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.ja={days:["日曜","月曜","火曜","水曜","木曜","金曜","土曜"],daysShort:["日","月","火","水","木","金","土"],daysMin:["日","月","火","水","木","金","土"],months:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],monthsShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],today:"今日",format:"yyyy/mm/dd",titleFormat:"yyyy年mm月",clear:"クリア"}}(jQuery);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@
|
||||
!function(t){var i=t(window);t.fn.visible=function(t,e,o){if(!(this.length<1)){var r=this.length>1?this.eq(0):this,n=r.get(0),f=i.width(),h=i.height(),o=o?o:"both",l=e===!0?n.offsetWidth*n.offsetHeight:!0;if("function"==typeof n.getBoundingClientRect){var g=n.getBoundingClientRect(),u=g.top>=0&&g.top<h,s=g.bottom>0&&g.bottom<=h,c=g.left>=0&&g.left<f,a=g.right>0&&g.right<=f,v=t?u||s:u&&s,b=t?c||a:c&&a;if("both"===o)return l&&v&&b;if("vertical"===o)return l&&v;if("horizontal"===o)return l&&b}else{var d=i.scrollTop(),p=d+h,w=i.scrollLeft(),m=w+f,y=r.offset(),z=y.top,B=z+r.height(),C=y.left,R=C+r.width(),j=t===!0?B:z,q=t===!0?z:B,H=t===!0?R:C,L=t===!0?C:R;if("both"===o)return!!l&&p>=q&&j>=d&&m>=L&&H>=w;if("vertical"===o)return!!l&&p>=q&&j>=d;if("horizontal"===o)return!!l&&m>=L&&H>=w}}}}(jQuery);
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,11 @@
|
||||
/*!
|
||||
* @preserve
|
||||
*
|
||||
* Readmore.js jQuery plugin
|
||||
* Author: @jed_foster
|
||||
* Project home: http://jedfoster.github.io/Readmore.js
|
||||
* Licensed under the MIT license
|
||||
*
|
||||
* Debounce function from http://davidwalsh.name/javascript-debounce-function
|
||||
*/
|
||||
!function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof exports?module.exports=t(require("jquery")):t(jQuery)}(function(t){"use strict";function e(t,e,i){var o;return function(){var n=this,a=arguments,s=function(){o=null,i||t.apply(n,a)},r=i&&!o;clearTimeout(o),o=setTimeout(s,e),r&&t.apply(n,a)}}function i(t){var e=++h;return String(null==t?"rmjs-":t)+e}function o(t){var e=t.clone().css({height:"auto",width:t.width(),maxHeight:"none",overflow:"hidden"}).insertAfter(t),i=e.outerHeight(),o=parseInt(e.css({maxHeight:""}).css("max-height").replace(/[^-\d\.]/g,""),10),n=t.data("defaultHeight");e.remove();var a=o||t.data("collapsedHeight")||n;t.data({expandedHeight:i,maxHeight:o,collapsedHeight:a}).css({maxHeight:"none"})}function n(t){if(!d[t.selector]){var e=" ";t.embedCSS&&""!==t.blockCSS&&(e+=t.selector+" + [data-readmore-toggle], "+t.selector+"[data-readmore]{"+t.blockCSS+"}"),e+=t.selector+"[data-readmore]{transition: height "+t.speed+"ms;overflow: hidden;}",function(t,e){var i=t.createElement("style");i.type="text/css",i.styleSheet?i.styleSheet.cssText=e:i.appendChild(t.createTextNode(e)),t.getElementsByTagName("head")[0].appendChild(i)}(document,e),d[t.selector]=!0}}function a(e,i){this.element=e,this.options=t.extend({},r,i),n(this.options),this._defaults=r,this._name=s,this.init(),window.addEventListener?(window.addEventListener("load",c),window.addEventListener("resize",c)):(window.attachEvent("load",c),window.attachEvent("resize",c))}var s="readmore",r={speed:100,collapsedHeight:200,heightMargin:16,moreLink:'<a href="#">Read More</a>',lessLink:'<a href="#">Close</a>',embedCSS:!0,blockCSS:"display: block; width: 100%;",startOpen:!1,blockProcessed:function(){},beforeToggle:function(){},afterToggle:function(){}},d={},h=0,c=e(function(){t("[data-readmore]").each(function(){var e=t(this),i="true"===e.attr("aria-expanded");o(e),e.css({height:e.data(i?"expandedHeight":"collapsedHeight")})})},100);a.prototype={init:function(){var e=t(this.element);e.data({defaultHeight:this.options.collapsedHeight,heightMargin:this.options.heightMargin}),o(e);var n=e.data("collapsedHeight"),a=e.data("heightMargin");if(e.outerHeight(!0)<=n+a)return this.options.blockProcessed&&"function"==typeof this.options.blockProcessed&&this.options.blockProcessed(e,!1),!0;var s=e.attr("id")||i(),r=this.options.startOpen?this.options.lessLink:this.options.moreLink;e.attr({"data-readmore":"","aria-expanded":this.options.startOpen,id:s}),e.after(t(r).on("click",function(t){return function(i){t.toggle(this,e[0],i)}}(this)).attr({"data-readmore-toggle":s,"aria-controls":s})),this.options.startOpen||e.css({height:n}),this.options.blockProcessed&&"function"==typeof this.options.blockProcessed&&this.options.blockProcessed(e,!0)},toggle:function(e,i,o){o&&o.preventDefault(),e||(e=t('[aria-controls="'+this.element.id+'"]')[0]),i||(i=this.element);var n=t(i),a="",s="",r=!1,d=n.data("collapsedHeight");n.height()<=d?(a=n.data("expandedHeight")+"px",s="lessLink",r=!0):(a=d,s="moreLink"),this.options.beforeToggle&&"function"==typeof this.options.beforeToggle&&this.options.beforeToggle(e,n,!r),n.css({height:a}),n.on("transitionend",function(i){return function(){i.options.afterToggle&&"function"==typeof i.options.afterToggle&&i.options.afterToggle(e,n,r),t(this).attr({"aria-expanded":r}).off("transitionend")}}(this)),t(e).replaceWith(t(this.options[s]).on("click",function(t){return function(e){t.toggle(this,i,e)}}(this)).attr({"data-readmore-toggle":n.attr("id"),"aria-controls":n.attr("id")}))},destroy:function(){t(this.element).each(function(){var e=t(this);e.attr({"data-readmore":null,"aria-expanded":null}).css({maxHeight:"",height:""}).next("[data-readmore-toggle]").remove(),e.removeData()})}},t.fn.readmore=function(e){var i=arguments,o=this.selector;return e=e||{},"object"==typeof e?this.each(function(){if(t.data(this,"plugin_"+s)){var i=t.data(this,"plugin_"+s);i.destroy.apply(i)}e.selector=o,t.data(this,"plugin_"+s,new a(this,e))}):"string"==typeof e&&"_"!==e[0]&&"init"!==e?this.each(function(){var o=t.data(this,"plugin_"+s);o instanceof a&&"function"==typeof o[e]&&o[e].apply(o,Array.prototype.slice.call(i,1))}):void 0}});
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,199 @@
|
||||
/*
|
||||
* bootstrap-uploadprogress
|
||||
* github: https://github.com/jakobadam/bootstrap-uploadprogress
|
||||
*
|
||||
* Copyright (c) 2015 Jakob Aarøe Dam
|
||||
* Version 1.0.0
|
||||
* Licensed under the MIT license.
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
"use strict";
|
||||
|
||||
$.support.xhrFileUpload = !!(window.FileReader && window.ProgressEvent);
|
||||
$.support.xhrFormData = !!window.FormData;
|
||||
|
||||
if (!$.support.xhrFileUpload || !$.support.xhrFormData) {
|
||||
// skip decorating form
|
||||
return;
|
||||
}
|
||||
|
||||
var template = "<div class=\"modal fade\" id=\"file-progress-modal\">" +
|
||||
"<div class=\"modal-dialog upload-modal-dialog\">" +
|
||||
" <div class=\"modal-content\">" +
|
||||
" <div class=\"modal-header\">" +
|
||||
" <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">×</span></button>" +
|
||||
" <h4 class=\"modal-title\">Uploading</h4>" +
|
||||
" </div>" +
|
||||
" <div class=\"modal-body\">" +
|
||||
" <div class=\"modal-message\"></div>" +
|
||||
" <div class=\"progress\">" +
|
||||
" <div class=\"progress-bar progress-bar-striped active\" role=\"progressbar\" aria-valuenow=\"0\" aria-valuemin=\"0\"" +
|
||||
" aria-valuemax=\"100\" style=\"width: 0%;min-width: 2em;\">" +
|
||||
" 0%" +
|
||||
" </div>" +
|
||||
" </div>" +
|
||||
" </div>" +
|
||||
" <div class=\"modal-footer\" style=\"display:none\">" +
|
||||
" <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">Close</button>" +
|
||||
" </div>" +
|
||||
" </div>" +
|
||||
" </div>" +
|
||||
"</div>";
|
||||
|
||||
var UploadProgress = function(element, options) {
|
||||
this.options = options;
|
||||
this.$element = $(element);
|
||||
};
|
||||
|
||||
UploadProgress.prototype = {
|
||||
|
||||
constructor: function() {
|
||||
this.$form = this.$element;
|
||||
this.$form.on("submit", $.proxy(this.submit, this));
|
||||
this.$modal = $(this.options.template);
|
||||
this.$modalTitle = this.$modal.find(".modal-title");
|
||||
this.$modalFooter = this.$modal.find(".modal-footer");
|
||||
this.$modalBar = this.$modal.find(".progress-bar");
|
||||
|
||||
// Translate texts
|
||||
this.$modalTitle.text(this.options.modalTitle)
|
||||
this.$modalFooter.children("button").text(this.options.modalFooter);
|
||||
|
||||
this.$modal.on("hidden.bs.modal", $.proxy(this.reset, this));
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
this.$modalTitle.text(this.options.modalTitle);
|
||||
this.$modalFooter.hide();
|
||||
this.$modalBar.addClass("progress-bar-success");
|
||||
this.$modalBar.removeClass("progress-bar-danger");
|
||||
if (this.xhr) {
|
||||
this.xhr.abort();
|
||||
}
|
||||
},
|
||||
|
||||
submit: function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
this.$modal.modal({
|
||||
backdrop: "static",
|
||||
keyboard: false
|
||||
});
|
||||
|
||||
// We need the native XMLHttpRequest for the progress event
|
||||
var xhr = new XMLHttpRequest();
|
||||
this.xhr = xhr;
|
||||
|
||||
xhr.addEventListener("load", $.proxy(this.success, this, xhr));
|
||||
xhr.addEventListener("error", $.proxy(this.error, this, xhr));
|
||||
|
||||
xhr.upload.addEventListener("progress", $.proxy(this.progress, this));
|
||||
|
||||
var form = this.$form;
|
||||
|
||||
xhr.open(form.attr("method"), form.attr("action"));
|
||||
xhr.setRequestHeader("X-REQUESTED-WITH", "XMLHttpRequest");
|
||||
|
||||
var data = new FormData(form.get(0));
|
||||
xhr.send(data);
|
||||
},
|
||||
|
||||
success: function(xhr) {
|
||||
if (xhr.status === 0 || xhr.status >= 400) {
|
||||
// HTTP 500 ends up here!?!
|
||||
return this.error(xhr);
|
||||
}
|
||||
this.setProgress(100);
|
||||
var url;
|
||||
var contentType = xhr.getResponseHeader("Content-Type");
|
||||
|
||||
// make it possible to return the redirect URL in
|
||||
// a JSON response
|
||||
if (contentType.indexOf("application/json") !== -1) {
|
||||
var response = $.parseJSON(xhr.responseText);
|
||||
url = response.location;
|
||||
}
|
||||
else{
|
||||
url = this.options.redirect_url;
|
||||
}
|
||||
window.location.href = url;
|
||||
},
|
||||
|
||||
// handle form error
|
||||
// we replace the form with the returned one
|
||||
error: function(xhr) {
|
||||
this.$modalTitle.text(this.options.modalTitleFailed);
|
||||
|
||||
this.$modalBar.removeClass("progress-bar-success");
|
||||
this.$modalBar.addClass("progress-bar-danger");
|
||||
this.$modalFooter.show();
|
||||
|
||||
var contentType = xhr.getResponseHeader("Content-Type");
|
||||
// Write the error response to the document.
|
||||
if (contentType || xhr.status === 422) {
|
||||
var responseText = xhr.responseText;
|
||||
if (contentType.indexOf("text/plain") !== -1) {
|
||||
responseText = "<pre>" + responseText + "</pre>";
|
||||
document.write(responseText);
|
||||
}
|
||||
else {
|
||||
this.$modalBar.text(responseText);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.$modalBar.text(this.options.modalTitleFailed);
|
||||
}
|
||||
},
|
||||
|
||||
setProgress: function(percent) {
|
||||
var txt = percent + "%";
|
||||
if (percent === 100) {
|
||||
txt = this.options.uploadedMsg;
|
||||
}
|
||||
this.$modalBar.attr("aria-valuenow", percent);
|
||||
this.$modalBar.text(txt);
|
||||
this.$modalBar.css("width", percent + "%");
|
||||
},
|
||||
|
||||
progress: function(/*ProgressEvent*/e) {
|
||||
var percent = Math.round((e.loaded / e.total) * 100);
|
||||
this.setProgress(percent);
|
||||
},
|
||||
|
||||
// replaceForm replaces the contents of the current form
|
||||
// with the form in the html argument.
|
||||
// We use the id of the current form to find the new form in the html
|
||||
replaceForm: function(html) {
|
||||
var newForm;
|
||||
var formId = this.$form.attr("id");
|
||||
if ( typeof formId !== "undefined") {
|
||||
newForm = $(html).find("#" + formId);
|
||||
} else {
|
||||
newForm = $(html).find("form");
|
||||
}
|
||||
// add the filestyle again
|
||||
newForm.find(":file").filestyle({buttonBefore: true});
|
||||
this.$form.html(newForm.children());
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.uploadprogress = function(options) {
|
||||
return this.each(function() {
|
||||
var _options = $.extend({}, $.fn.uploadprogress.defaults, options);
|
||||
var fileProgress = new UploadProgress(this, _options);
|
||||
fileProgress.constructor();
|
||||
});
|
||||
};
|
||||
|
||||
$.fn.uploadprogress.defaults = {
|
||||
template: template,
|
||||
uploadedMsg: "Upload done, processing, please wait...",
|
||||
modalTitle: "Uploading",
|
||||
modalFooter: "Close",
|
||||
modalTitleFailed: "Upload failed"
|
||||
//redirect_url: ...
|
||||
// need to customize stuff? Add here, and change code accordingly.
|
||||
};
|
||||
|
||||
})(window.jQuery);
|
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="http-error" lang="{{ g.user.locale }}">
|
||||
<head>
|
||||
<title>{{ instance }} | HTTP Error ({{ error_code }})</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="apple-touch-icon" sizes="140x140" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||
<link href="{{ url_for('static', filename='css/libs/bootstrap.min.css') }}" rel="stylesheet" media="screen">
|
||||
<link href="{{ url_for('static', filename='css/style.css') }}" rel="stylesheet" media="screen">
|
||||
{% if g.current_theme == 1 %}
|
||||
<link href="{{ url_for('static', filename='css/caliBlur.min.css') }}" rel="stylesheet" media="screen">
|
||||
{% endif %}
|
||||
</head>
|
||||
<body>
|
||||
<div class="container text-center">
|
||||
<h1>{{ error_code }}</h1>
|
||||
<h3>{{ error_name }}</h3>
|
||||
<a href="{{url_for('index')}}" title="{{ _('Back to home') }}">{{_('Back to home')}}</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,514 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
|
||||
# Copyright (C) 2018-2019 OzzieIsaacs
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import threading
|
||||
import zipfile
|
||||
import requests
|
||||
import re
|
||||
import logging
|
||||
import server
|
||||
import time
|
||||
from io import BytesIO
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
from ub import config, UPDATE_STABLE
|
||||
from tempfile import gettempdir
|
||||
import datetime
|
||||
import json
|
||||
from flask_babel import gettext as _
|
||||
from babel.dates import format_datetime
|
||||
import web
|
||||
|
||||
|
||||
def is_sha1(sha1):
|
||||
if len(sha1) != 40:
|
||||
return False
|
||||
try:
|
||||
int(sha1, 16)
|
||||
except ValueError:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
class Updater(threading.Thread):
|
||||
|
||||
def __init__(self):
|
||||
threading.Thread.__init__(self)
|
||||
self.status = -1
|
||||
self.updateIndex = None
|
||||
|
||||
def get_current_version_info(self):
|
||||
if config.get_update_channel == UPDATE_STABLE:
|
||||
return self._stable_version_info()
|
||||
else:
|
||||
return self._nightly_version_info()
|
||||
|
||||
def get_available_updates(self, request_method):
|
||||
if config.get_update_channel == UPDATE_STABLE:
|
||||
return self._stable_available_updates(request_method)
|
||||
else:
|
||||
return self._nightly_available_updates(request_method)
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self.status = 1
|
||||
r = requests.get(self._get_request_path(), stream=True)
|
||||
r.raise_for_status()
|
||||
|
||||
self.status = 2
|
||||
z = zipfile.ZipFile(BytesIO(r.content))
|
||||
self.status = 3
|
||||
tmp_dir = gettempdir()
|
||||
z.extractall(tmp_dir)
|
||||
foldername = os.path.join(tmp_dir, z.namelist()[0])[:-1]
|
||||
if not os.path.isdir(foldername):
|
||||
self.status = 11
|
||||
logging.getLogger('cps.web').info(u'Extracted contents of zipfile not found in temp folder')
|
||||
return
|
||||
self.status = 4
|
||||
self.update_source(foldername, config.get_main_dir)
|
||||
self.status = 6
|
||||
time.sleep(2)
|
||||
server.Server.setRestartTyp(True)
|
||||
server.Server.stopServer()
|
||||
self.status = 7
|
||||
time.sleep(2)
|
||||
except requests.exceptions.HTTPError as ex:
|
||||
logging.getLogger('cps.web').info( u'HTTP Error' + ' ' + str(ex))
|
||||
self.status = 8
|
||||
except requests.exceptions.ConnectionError:
|
||||
logging.getLogger('cps.web').info(u'Connection error')
|
||||
self.status = 9
|
||||
except requests.exceptions.Timeout:
|
||||
logging.getLogger('cps.web').info(u'Timeout while establishing connection')
|
||||
self.status = 10
|
||||
except requests.exceptions.RequestException:
|
||||
self.status = 11
|
||||
logging.getLogger('cps.web').info(u'General error')
|
||||
|
||||
def get_update_status(self):
|
||||
return self.status
|
||||
|
||||
@classmethod
|
||||
def file_to_list(self, filelist):
|
||||
return [x.strip() for x in open(filelist, 'r') if not x.startswith('#EXT')]
|
||||
|
||||
@classmethod
|
||||
def one_minus_two(self, one, two):
|
||||
return [x for x in one if x not in set(two)]
|
||||
|
||||
@classmethod
|
||||
def reduce_dirs(self, delete_files, new_list):
|
||||
new_delete = []
|
||||
for filename in delete_files:
|
||||
parts = filename.split(os.sep)
|
||||
sub = ''
|
||||
for part in parts:
|
||||
sub = os.path.join(sub, part)
|
||||
if sub == '':
|
||||
sub = os.sep
|
||||
count = 0
|
||||
for song in new_list:
|
||||
if song.startswith(sub):
|
||||
count += 1
|
||||
break
|
||||
if count == 0:
|
||||
if sub != '\\':
|
||||
new_delete.append(sub)
|
||||
break
|
||||
return list(set(new_delete))
|
||||
|
||||
@classmethod
|
||||
def reduce_files(self, remove_items, exclude_items):
|
||||
rf = []
|
||||
for item in remove_items:
|
||||
if not item.startswith(exclude_items):
|
||||
rf.append(item)
|
||||
return rf
|
||||
|
||||
@classmethod
|
||||
def moveallfiles(self, root_src_dir, root_dst_dir):
|
||||
change_permissions = True
|
||||
if sys.platform == "win32" or sys.platform == "darwin":
|
||||
change_permissions = False
|
||||
else:
|
||||
logging.getLogger('cps.web').debug('Update on OS-System : ' + sys.platform)
|
||||
new_permissions = os.stat(root_dst_dir)
|
||||
# print new_permissions
|
||||
for src_dir, __, files in os.walk(root_src_dir):
|
||||
dst_dir = src_dir.replace(root_src_dir, root_dst_dir, 1)
|
||||
if not os.path.exists(dst_dir):
|
||||
os.makedirs(dst_dir)
|
||||
logging.getLogger('cps.web').debug('Create-Dir: '+dst_dir)
|
||||
if change_permissions:
|
||||
# print('Permissions: User '+str(new_permissions.st_uid)+' Group '+str(new_permissions.st_uid))
|
||||
os.chown(dst_dir, new_permissions.st_uid, new_permissions.st_gid)
|
||||
for file_ in files:
|
||||
src_file = os.path.join(src_dir, file_)
|
||||
dst_file = os.path.join(dst_dir, file_)
|
||||
if os.path.exists(dst_file):
|
||||
if change_permissions:
|
||||
permission = os.stat(dst_file)
|
||||
logging.getLogger('cps.web').debug('Remove file before copy: '+dst_file)
|
||||
os.remove(dst_file)
|
||||
else:
|
||||
if change_permissions:
|
||||
permission = new_permissions
|
||||
shutil.move(src_file, dst_dir)
|
||||
logging.getLogger('cps.web').debug('Move File '+src_file+' to '+dst_dir)
|
||||
if change_permissions:
|
||||
try:
|
||||
os.chown(dst_file, permission.st_uid, permission.st_gid)
|
||||
except (Exception) as e:
|
||||
# ex = sys.exc_info()
|
||||
old_permissions = os.stat(dst_file)
|
||||
logging.getLogger('cps.web').debug('Fail change permissions of ' + str(dst_file) + '. Before: '
|
||||
+ str(old_permissions.st_uid) + ':' + str(old_permissions.st_gid) + ' After: '
|
||||
+ str(permission.st_uid) + ':' + str(permission.st_gid) + ' error: '+str(e))
|
||||
return
|
||||
|
||||
def update_source(self, source, destination):
|
||||
# destination files
|
||||
old_list = list()
|
||||
exclude = (
|
||||
os.sep + 'app.db', os.sep + 'calibre-web.log1', os.sep + 'calibre-web.log2', os.sep + 'gdrive.db',
|
||||
os.sep + 'vendor', os.sep + 'calibre-web.log', os.sep + '.git', os.sep +'client_secrets.json',
|
||||
os.sep + 'gdrive_credentials', os.sep + 'settings.yaml')
|
||||
for root, dirs, files in os.walk(destination, topdown=True):
|
||||
for name in files:
|
||||
old_list.append(os.path.join(root, name).replace(destination, ''))
|
||||
for name in dirs:
|
||||
old_list.append(os.path.join(root, name).replace(destination, ''))
|
||||
# source files
|
||||
new_list = list()
|
||||
for root, dirs, files in os.walk(source, topdown=True):
|
||||
for name in files:
|
||||
new_list.append(os.path.join(root, name).replace(source, ''))
|
||||
for name in dirs:
|
||||
new_list.append(os.path.join(root, name).replace(source, ''))
|
||||
|
||||
delete_files = self.one_minus_two(old_list, new_list)
|
||||
|
||||
rf = self.reduce_files(delete_files, exclude)
|
||||
|
||||
remove_items = self.reduce_dirs(rf, new_list)
|
||||
|
||||
self.moveallfiles(source, destination)
|
||||
|
||||
for item in remove_items:
|
||||
item_path = os.path.join(destination, item[1:])
|
||||
if os.path.isdir(item_path):
|
||||
logging.getLogger('cps.web').debug("Delete dir " + item_path)
|
||||
shutil.rmtree(item_path, ignore_errors=True)
|
||||
else:
|
||||
try:
|
||||
logging.getLogger('cps.web').debug("Delete file " + item_path)
|
||||
# log_from_thread("Delete file " + item_path)
|
||||
os.remove(item_path)
|
||||
except Exception:
|
||||
logging.getLogger('cps.web').debug("Could not remove:" + item_path)
|
||||
shutil.rmtree(source, ignore_errors=True)
|
||||
|
||||
def _nightly_version_info(self):
|
||||
content = {}
|
||||
content[0] = '$Format:%H$'
|
||||
content[1] = '$Format:%cI$'
|
||||
# content[0] = 'bb7d2c6273ae4560e83950d36d64533343623a57'
|
||||
# content[1] = '2018-09-09T10:13:08+02:00'
|
||||
if is_sha1(content[0]) and len(content[1]) > 0:
|
||||
return {'version': content[0], 'datetime': content[1]}
|
||||
return False
|
||||
|
||||
def _stable_version_info(self):
|
||||
return {'version': '0.6.1'} # Current version
|
||||
|
||||
def _nightly_available_updates(self, request_method):
|
||||
tz = datetime.timedelta(seconds=time.timezone if (time.localtime().tm_isdst == 0) else time.altzone)
|
||||
if request_method == "GET":
|
||||
repository_url = 'https://api.github.com/repos/janeczku/calibre-web'
|
||||
status, commit = self._load_remote_data(repository_url +'/git/refs/heads/master')
|
||||
parents = []
|
||||
if status['message'] != '':
|
||||
return json.dumps(status)
|
||||
if 'object' not in commit:
|
||||
status['message'] = _(u'Unexpected data while reading update information')
|
||||
return json.dumps(status)
|
||||
|
||||
if commit['object']['sha'] == status['current_commit_hash']:
|
||||
status.update({
|
||||
'update': False,
|
||||
'success': True,
|
||||
'message': _(u'No update available. You already have the latest version installed')
|
||||
})
|
||||
return json.dumps(status)
|
||||
|
||||
# a new update is available
|
||||
status['update'] = True
|
||||
|
||||
try:
|
||||
r = requests.get(repository_url + '/git/commits/' + commit['object']['sha'])
|
||||
r.raise_for_status()
|
||||
update_data = r.json()
|
||||
except requests.exceptions.HTTPError as e:
|
||||
status['error'] = _(u'HTTP Error') + ' ' + str(e)
|
||||
except requests.exceptions.ConnectionError:
|
||||
status['error'] = _(u'Connection error')
|
||||
except requests.exceptions.Timeout:
|
||||
status['error'] = _(u'Timeout while establishing connection')
|
||||
except requests.exceptions.RequestException:
|
||||
status['error'] = _(u'General error')
|
||||
|
||||
if status['message'] != '':
|
||||
return json.dumps(status)
|
||||
|
||||
if 'committer' in update_data and 'message' in update_data:
|
||||
status['success'] = True
|
||||
status['message'] = _(
|
||||
u'A new update is available. Click on the button below to update to the latest version.')
|
||||
|
||||
new_commit_date = datetime.datetime.strptime(
|
||||
update_data['committer']['date'], '%Y-%m-%dT%H:%M:%SZ') - tz
|
||||
parents.append(
|
||||
[
|
||||
format_datetime(new_commit_date, format='short', locale=web.get_locale()),
|
||||
update_data['message'],
|
||||
update_data['sha']
|
||||
]
|
||||
)
|
||||
|
||||
# it only makes sense to analyze the parents if we know the current commit hash
|
||||
if status['current_commit_hash'] != '':
|
||||
try:
|
||||
parent_commit = update_data['parents'][0]
|
||||
# limit the maximum search depth
|
||||
remaining_parents_cnt = 10
|
||||
except IndexError:
|
||||
remaining_parents_cnt = None
|
||||
|
||||
if remaining_parents_cnt is not None:
|
||||
while True:
|
||||
if remaining_parents_cnt == 0:
|
||||
break
|
||||
|
||||
# check if we are more than one update behind if so, go up the tree
|
||||
if parent_commit['sha'] != status['current_commit_hash']:
|
||||
try:
|
||||
r = requests.get(parent_commit['url'])
|
||||
r.raise_for_status()
|
||||
parent_data = r.json()
|
||||
|
||||
parent_commit_date = datetime.datetime.strptime(
|
||||
parent_data['committer']['date'], '%Y-%m-%dT%H:%M:%SZ') - tz
|
||||
parent_commit_date = format_datetime(
|
||||
parent_commit_date, format='short', locale=web.get_locale())
|
||||
|
||||
parents.append([parent_commit_date,
|
||||
parent_data['message'].replace('\r\n','<p>').replace('\n','<p>')])
|
||||
parent_commit = parent_data['parents'][0]
|
||||
remaining_parents_cnt -= 1
|
||||
except Exception:
|
||||
# it isn't crucial if we can't get information about the parent
|
||||
break
|
||||
else:
|
||||
# parent is our current version
|
||||
break
|
||||
|
||||
else:
|
||||
status['success'] = False
|
||||
status['message'] = _(u'Could not fetch update information')
|
||||
|
||||
# a new update is available
|
||||
status['update'] = True
|
||||
if 'body' in commit:
|
||||
status['success'] = True
|
||||
status['message'] = _(
|
||||
u'A new update is available. Click on the button below to update to the latest version.')
|
||||
|
||||
new_commit_date = datetime.datetime.strptime(
|
||||
commit['committer']['date'], '%Y-%m-%dT%H:%M:%SZ') - tz
|
||||
parents.append(
|
||||
[
|
||||
format_datetime(new_commit_date, format='short', locale=web.get_locale()),
|
||||
commit['message'],
|
||||
commit['sha']
|
||||
]
|
||||
)
|
||||
|
||||
# it only makes sense to analyze the parents if we know the current commit hash
|
||||
if status['current_commit_hash'] != '':
|
||||
try:
|
||||
parent_commit = commit['parents'][0]
|
||||
# limit the maximum search depth
|
||||
remaining_parents_cnt = 10
|
||||
except IndexError:
|
||||
remaining_parents_cnt = None
|
||||
|
||||
if remaining_parents_cnt is not None:
|
||||
while True:
|
||||
if remaining_parents_cnt == 0:
|
||||
break
|
||||
|
||||
# check if we are more than one update behind if so, go up the tree
|
||||
if commit['sha'] != status['current_commit_hash']:
|
||||
try:
|
||||
r = requests.get(parent_commit['url'])
|
||||
r.raise_for_status()
|
||||
parent_data = r.json()
|
||||
|
||||
parent_commit_date = datetime.datetime.strptime(
|
||||
parent_data['committer']['date'], '%Y-%m-%dT%H:%M:%SZ') - tz
|
||||
parent_commit_date = format_datetime(
|
||||
parent_commit_date, format='short', locale=web.get_locale())
|
||||
|
||||
parents.append([parent_commit_date, parent_data['message'], parent_data['sha']])
|
||||
parent_commit = parent_data['parents'][0]
|
||||
remaining_parents_cnt -= 1
|
||||
except Exception:
|
||||
# it isn't crucial if we can't get information about the parent
|
||||
break
|
||||
else:
|
||||
# parent is our current version
|
||||
break
|
||||
status['history'] = parents[::-1]
|
||||
return json.dumps(status)
|
||||
return ''
|
||||
|
||||
def _stable_available_updates(self, request_method):
|
||||
if request_method == "GET":
|
||||
parents = []
|
||||
# repository_url = 'https://api.github.com/repos/flatpak/flatpak/releases' # test URL
|
||||
repository_url = 'https://api.github.com/repos/janeczku/calibre-web/releases'
|
||||
status, commit = self._load_remote_data(repository_url)
|
||||
if status['message'] != '':
|
||||
return json.dumps(status)
|
||||
if not commit:
|
||||
status['success'] = True
|
||||
status['message'] = _(u'No release information available')
|
||||
return json.dumps(status)
|
||||
version = status['current_commit_hash']
|
||||
current_version = status['current_commit_hash'].split('.')
|
||||
|
||||
# we are already on newest version, no update available
|
||||
if 'tag_name' not in commit[0]:
|
||||
status['message'] = _(u'Unexpected data while reading update information')
|
||||
return json.dumps(status)
|
||||
if commit[0]['tag_name'] == version:
|
||||
status.update({
|
||||
'update': False,
|
||||
'success': True,
|
||||
'message': _(u'No update available. You already have the latest version installed')
|
||||
})
|
||||
return json.dumps(status)
|
||||
|
||||
i = len(commit) - 1
|
||||
while i >= 0:
|
||||
if 'tag_name' not in commit[i] or 'body' not in commit[i]:
|
||||
status['message'] = _(u'Unexpected data while reading update information')
|
||||
return json.dumps(status)
|
||||
major_version_update = int(commit[i]['tag_name'].split('.')[0])
|
||||
minor_version_update = int(commit[i]['tag_name'].split('.')[1])
|
||||
patch_version_update = int(commit[i]['tag_name'].split('.')[2])
|
||||
|
||||
# Check if major versions are identical search for newest nonenqual commit and update to this one
|
||||
if major_version_update == int(current_version[0]):
|
||||
if (minor_version_update == int(current_version[1]) and
|
||||
patch_version_update > int(current_version[2])) or \
|
||||
minor_version_update > int(current_version[1]):
|
||||
parents.append([commit[i]['tag_name'],commit[i]['body'].replace('\r\n', '<p>')])
|
||||
i -= 1
|
||||
continue
|
||||
if major_version_update < int(current_version[0]):
|
||||
i -= 1
|
||||
continue
|
||||
if major_version_update > int(current_version[0]):
|
||||
# found update update to last version before major update, unless current version is on last version
|
||||
# before major update
|
||||
if commit[i+1]['tag_name'].split('.')[1] == current_version[1]:
|
||||
parents.append([commit[i]['tag_name'],
|
||||
commit[i]['body'].replace('\r\n', '<p>').replace('\n', '<p>')])
|
||||
status.update({
|
||||
'update': True,
|
||||
'success': True,
|
||||
'message': _(u'A new update is available. Click on the button below to '
|
||||
u'update to version: %(version)s', version=commit[i]['tag_name']),
|
||||
'history': parents
|
||||
})
|
||||
self.updateFile = commit[i]['zipball_url']
|
||||
else:
|
||||
status.update({
|
||||
'update': True,
|
||||
'success': True,
|
||||
'message': _(u'A new update is available. Click on the button below to '
|
||||
u'update to version: %(version)s', version=commit[i]['tag_name']),
|
||||
'history': parents
|
||||
})
|
||||
self.updateFile = commit[i +1]['zipball_url']
|
||||
break
|
||||
if i == -1:
|
||||
status.update({
|
||||
'update': True,
|
||||
'success': True,
|
||||
'message': _(
|
||||
u'A new update is available. Click on the button below to update to the latest version.'),
|
||||
'history': parents
|
||||
})
|
||||
self.updateFile = commit[0]['zipball_url']
|
||||
return json.dumps(status)
|
||||
|
||||
def _get_request_path(self):
|
||||
if config.get_update_channel == UPDATE_STABLE:
|
||||
return self.updateFile
|
||||
else:
|
||||
return 'https://api.github.com/repos/janeczku/calibre-web/zipball/master'
|
||||
|
||||
def _load_remote_data(self, repository_url):
|
||||
status = {
|
||||
'update': False,
|
||||
'success': False,
|
||||
'message': '',
|
||||
'current_commit_hash': ''
|
||||
}
|
||||
commit = None
|
||||
version = self.get_current_version_info()
|
||||
if version is False:
|
||||
status['current_commit_hash'] = _(u'Unknown')
|
||||
else:
|
||||
status['current_commit_hash'] = version['version']
|
||||
try:
|
||||
r = requests.get(repository_url)
|
||||
commit = r.json()
|
||||
r.raise_for_status()
|
||||
except requests.exceptions.HTTPError as e:
|
||||
if commit:
|
||||
if 'message' in commit:
|
||||
status['message'] = _(u'HTTP Error') + ': ' + commit['message']
|
||||
else:
|
||||
status['message'] = _(u'HTTP Error') + ': ' + str(e)
|
||||
except requests.exceptions.ConnectionError:
|
||||
status['message'] = _(u'Connection error')
|
||||
except requests.exceptions.Timeout:
|
||||
status['message'] = _(u'Timeout while establishing connection')
|
||||
except requests.exceptions.RequestException:
|
||||
status['message'] = _(u'General error')
|
||||
|
||||
return status, commit
|
||||
|
||||
|
||||
updater_thread = Updater()
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue