Merge branch 'master' of git.xpub.nl:/var/www/git.xpub.nl/repos/xpub-lib
This commit is contained in:
commit
a0558a6115
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,6 +3,7 @@ __pycache__/
|
||||
*~
|
||||
app/uploads/**
|
||||
!app/uploads/cover
|
||||
/cover/**
|
||||
app/mydatabase.db
|
||||
pyrqlite/
|
||||
whoosh/
|
||||
|
@ -15,7 +15,7 @@ registry.register("rqlite.pyrqlite", "sqlalchemy_rqlite.pyrqlite", "dialect")
|
||||
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
UPLOAD_FOLDER = os.path.join(basedir, 'uploads')
|
||||
UPLOAD_FOLDER_COVER = os.path.join(basedir, 'uploads/cover')
|
||||
UPLOAD_FOLDER_COVER = os.path.join(basedir, 'cover')
|
||||
#ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])
|
||||
load_dotenv(find_dotenv())
|
||||
app = Flask(__name__)
|
||||
@ -29,7 +29,7 @@ app.config['PORT'] = 80
|
||||
|
||||
#app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'mydatabase.db')
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
light = not os.path.isdir(UPLOAD_FOLDER)
|
||||
DOMAIN = environ.get('DOMAIN')
|
||||
socketio = SocketIO(app)
|
||||
|
||||
|
@ -37,8 +37,8 @@ def get_cover(file_path, filename):
|
||||
|
||||
# Convert each page to a png image.
|
||||
for page in pages:
|
||||
big_filename = "app/uploads/cover/"+page["filename"] + "_cover.png"
|
||||
small_filename = "app/uploads/cover/"+page["filename"] + "cover_small" + ".png"
|
||||
big_filename = "app/cover/"+page["filename"] + "_cover.png"
|
||||
small_filename = "app/cover/"+page["filename"] + "cover_small" + ".png"
|
||||
|
||||
img = pdf_page_to_png(src_pdf, pagenum = page["pagenum"], resolution = 200)
|
||||
img.save(filename = big_filename)
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
Binary file not shown.
After Width: | Height: | Size: 94 KiB |
Binary file not shown.
After Width: | Height: | Size: 131 KiB |
15
app/forms.py
15
app/forms.py
@ -25,7 +25,6 @@ class UploadForm(FlaskForm):
|
||||
sameness = DecimalRangeField('sameness', default=0)
|
||||
diversity = DecimalRangeField('diversity', default=0)
|
||||
gender = DecimalRangeField('gender', default=50)
|
||||
time = StringField('time', [validators.Length(max=5)],default=None)
|
||||
choices = [('Student', 'Student'),
|
||||
('Librarian', 'Librarian'),
|
||||
('Pirate', 'Pirate'),
|
||||
@ -43,6 +42,17 @@ class EditForm(FlaskForm):
|
||||
year_published = StringField('year published', [validators.Length(max=4)],default=None)
|
||||
file = FileField()
|
||||
message = StringField('message')
|
||||
sameness = DecimalRangeField('sameness', default=0)
|
||||
diversity = DecimalRangeField('diversity', default=0)
|
||||
gender = DecimalRangeField('gender', default=50)
|
||||
choices = [('Student', 'Student'),
|
||||
('Librarian', 'Librarian'),
|
||||
('Pirate', 'Pirate'),
|
||||
('Teacher', 'Teacher'),
|
||||
('Institution', 'Institution'),
|
||||
('All of the above', 'All of the above'),
|
||||
('None of the above', 'None of the above')]
|
||||
who = SelectField('', choices=choices, default='Student')
|
||||
|
||||
class ChatForm(FlaskForm):
|
||||
message = StringField('message', validators=[InputRequired()])
|
||||
@ -66,7 +76,8 @@ class SearchForm(FlaskForm):
|
||||
('Title', 'Title'),
|
||||
('Author', 'Author'),
|
||||
('Category', 'Category'),
|
||||
('Stack', 'Stack')]
|
||||
('Stack', 'Stack'),
|
||||
('Outliers', 'Outliers')]
|
||||
select = SelectField('', choices=choices, default='All')
|
||||
search = StringField('', validators=[InputRequired()])
|
||||
grid = SubmitField('Grid')
|
||||
|
@ -46,10 +46,9 @@ class Book(db.Model):
|
||||
diversity = db.Column(db.Numeric())
|
||||
gender = db.Column(db.Numeric())
|
||||
who = db.Column(db.String(255))
|
||||
time = db.Column(db.Numeric())
|
||||
|
||||
|
||||
def __init__(self, title, file, cover, fileformat, category, year_published, message, sameness, diversity, gender, who, time):
|
||||
def __init__(self, title, file, cover, fileformat, category, year_published, message, sameness, diversity, gender, who):
|
||||
self.title = title
|
||||
self.file = file
|
||||
self.cover = cover
|
||||
@ -64,7 +63,6 @@ class Book(db.Model):
|
||||
self.diversity = diversity
|
||||
self.gender = gender
|
||||
self.who = who
|
||||
self.time = time
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -5,14 +5,14 @@ font-family: "Archivo Narrow";
|
||||
}
|
||||
|
||||
p{
|
||||
font-size: 18px;
|
||||
font-size: 20px;
|
||||
|
||||
|
||||
}
|
||||
|
||||
a{
|
||||
|
||||
text-decoration: none;
|
||||
text-decoration: underline;
|
||||
color: black;
|
||||
}
|
||||
a:hover{
|
||||
@ -68,7 +68,7 @@ padding: 0px 10px;
|
||||
}
|
||||
|
||||
.about{
|
||||
font-size: 16px;
|
||||
font-size: 18px;
|
||||
|
||||
}
|
||||
.library_table{
|
||||
@ -106,7 +106,7 @@ background-color: #E8E8E8!important;
|
||||
}
|
||||
|
||||
.library_table .author_col{
|
||||
font-size: 15px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.library_table li{
|
||||
@ -121,6 +121,10 @@ display: inline-block;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
#ascii {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
.library_table tr:nth-child(even){
|
||||
background-color: #fafafa;
|
||||
@ -129,7 +133,6 @@ background-color: #fafafa;
|
||||
#title_xppl{
|
||||
font-size: 46px;
|
||||
cursor: pointer;
|
||||
|
||||
}
|
||||
|
||||
.header input{
|
||||
@ -142,7 +145,7 @@ font-weight: bold;
|
||||
.author input{
|
||||
height:20px;
|
||||
width: 500px;
|
||||
font-size: 16px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.search input{
|
||||
@ -242,7 +245,7 @@ div.marquee > div.marquee-text {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 30%;
|
||||
width: 25%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@ -254,7 +257,7 @@ div.marquee > div.marquee-text {
|
||||
padding: 10px;
|
||||
margin: 0px;
|
||||
height: 100%;
|
||||
background-color: #b4b9be;
|
||||
/*background-color: #b4b9be;*/
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
color: white;
|
||||
@ -265,6 +268,43 @@ div.marquee > div.marquee-text {
|
||||
z-index: -100000;
|
||||
}
|
||||
|
||||
.messageback1{
|
||||
|
||||
position: absolute;
|
||||
bottom: 40px;
|
||||
display: block;
|
||||
width:100%;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
height: 100%;
|
||||
background-color: #b4b9be;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
color: white;
|
||||
word-wrap:break-word;
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
z-index: -100000;}
|
||||
|
||||
.messageback2{
|
||||
position: absolute;
|
||||
bottom: 40px;
|
||||
display: block;
|
||||
width:100%;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
height: 100%;
|
||||
background-color: #b4b9be;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
color: white;
|
||||
word-wrap:break-word;
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
z-index: -100000;}
|
||||
|
||||
.new-message {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
@ -273,6 +313,7 @@ width:100%;
|
||||
margin:0;
|
||||
padding:0;
|
||||
z-index: 100000;
|
||||
opacity: 1!important;
|
||||
}
|
||||
.control{
|
||||
display: block;
|
||||
@ -353,7 +394,7 @@ box-sizing: border-box;
|
||||
justify-items: center;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
@media screen and (max-width: 1000px) {
|
||||
.grid{
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
@ -362,11 +403,13 @@ box-sizing: border-box;
|
||||
justify-items: center;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 400px) {
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
.grid{
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
align-items: center;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-gap: 2px;
|
||||
align-items: top;
|
||||
justify-items: center;
|
||||
}
|
||||
}
|
||||
@ -377,6 +420,7 @@ box-sizing: border-box;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
}
|
||||
|
||||
.gridbox:hover{
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
@ -63,13 +63,34 @@ function generateTitle(elem) {
|
||||
}
|
||||
|
||||
$(function() {
|
||||
$("#tabs").tabs().addClass("ui-tabs-vertical ui-helper-clearfix");
|
||||
var index = 'ui-tabs-active';
|
||||
// Define friendly data store name
|
||||
var dataStore = window.sessionStorage;
|
||||
var oldIndex = 0;
|
||||
// Start magic!
|
||||
try {
|
||||
// getter: Fetch previous value
|
||||
oldIndex = dataStore.getItem(index);
|
||||
} catch(e) {}
|
||||
|
||||
$("#tabs").tabs({
|
||||
active: oldIndex,
|
||||
activate: function(event, ui) {
|
||||
// Get future value
|
||||
var newIndex = ui.newTab.parent().children().index(ui.newTab);
|
||||
// Set future value
|
||||
try {
|
||||
dataStore.setItem( index, newIndex );
|
||||
} catch(e) {}
|
||||
}
|
||||
});
|
||||
|
||||
$("#tabs").addClass("ui-tabs-vertical ui-helper-clearfix");
|
||||
$("#tabs li").removeClass("ui-corner-top").addClass("ui-corner-left");
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
$(".no_cover").each(function() {
|
||||
var string = $(this).attr('id')
|
||||
var randomColor = colorHash(string).rgb
|
||||
|
2
app/static/js/jquery-3.3.1.min.js
vendored
Normal file
2
app/static/js/jquery-3.3.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
486
app/static/js/jquery.marquee.js
Executable file
486
app/static/js/jquery.marquee.js
Executable file
@ -0,0 +1,486 @@
|
||||
/**
|
||||
* jQuery.marquee - scrolling text like old marquee element
|
||||
* @author Aamir Afridi - aamirafridi(at)gmail(dot)com / http://aamirafridi.com/jquery/jquery-marquee-plugin
|
||||
*/;
|
||||
(function($) {
|
||||
$.fn.marquee = function(options) {
|
||||
return this.each(function() {
|
||||
// Extend the options if any provided
|
||||
var o = $.extend({}, $.fn.marquee.defaults, options),
|
||||
$this = $(this),
|
||||
$marqueeWrapper, containerWidth, animationCss, verticalDir, elWidth,
|
||||
loopCount = 3,
|
||||
playState = 'animation-play-state',
|
||||
css3AnimationIsSupported = false,
|
||||
|
||||
// Private methods
|
||||
_prefixedEvent = function(element, type, callback) {
|
||||
var pfx = ["webkit", "moz", "MS", "o", ""];
|
||||
for (var p = 0; p < pfx.length; p++) {
|
||||
if (!pfx[p]) type = type.toLowerCase();
|
||||
element.addEventListener(pfx[p] + type, callback, false);
|
||||
}
|
||||
},
|
||||
|
||||
_objToString = function(obj) {
|
||||
var tabjson = [];
|
||||
for (var p in obj) {
|
||||
if (obj.hasOwnProperty(p)) {
|
||||
tabjson.push(p + ':' + obj[p]);
|
||||
}
|
||||
}
|
||||
tabjson.push();
|
||||
return '{' + tabjson.join(',') + '}';
|
||||
},
|
||||
|
||||
_startAnimationWithDelay = function() {
|
||||
$this.timer = setTimeout(animate, o.delayBeforeStart);
|
||||
},
|
||||
|
||||
// Public methods
|
||||
methods = {
|
||||
pause: function() {
|
||||
if (css3AnimationIsSupported && o.allowCss3Support) {
|
||||
$marqueeWrapper.css(playState, 'paused');
|
||||
} else {
|
||||
// pause using pause plugin
|
||||
if ($.fn.pause) {
|
||||
$marqueeWrapper.pause();
|
||||
}
|
||||
}
|
||||
// save the status
|
||||
$this.data('runningStatus', 'paused');
|
||||
// fire event
|
||||
$this.trigger('paused');
|
||||
},
|
||||
|
||||
resume: function() {
|
||||
// resume using css3
|
||||
if (css3AnimationIsSupported && o.allowCss3Support) {
|
||||
$marqueeWrapper.css(playState, 'running');
|
||||
} else {
|
||||
// resume using pause plugin
|
||||
if ($.fn.resume) {
|
||||
$marqueeWrapper.resume();
|
||||
}
|
||||
}
|
||||
// save the status
|
||||
$this.data('runningStatus', 'resumed');
|
||||
// fire event
|
||||
$this.trigger('resumed');
|
||||
},
|
||||
|
||||
toggle: function() {
|
||||
methods[$this.data('runningStatus') == 'resumed' ? 'pause' : 'resume']();
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
// Clear timer
|
||||
clearTimeout($this.timer);
|
||||
// Unbind all events
|
||||
$this.find("*").addBack().unbind();
|
||||
// Just unwrap the elements that has been added using this plugin
|
||||
$this.html($this.find('.js-marquee:first').html());
|
||||
}
|
||||
};
|
||||
|
||||
// Check for methods
|
||||
if (typeof options === 'string') {
|
||||
if ($.isFunction(methods[options])) {
|
||||
// Following two IF statements to support public methods
|
||||
if (!$marqueeWrapper) {
|
||||
$marqueeWrapper = $this.find('.js-marquee-wrapper');
|
||||
}
|
||||
if ($this.data('css3AnimationIsSupported') === true) {
|
||||
css3AnimationIsSupported = true;
|
||||
}
|
||||
methods[options]();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if element has data attributes. They have top priority
|
||||
For details https://twitter.com/aamirafridi/status/403848044069679104 - Can't find a better solution :/
|
||||
jQuery 1.3.2 doesn't support $.data().KEY hence writting the following */
|
||||
var dataAttributes = {},
|
||||
attr;
|
||||
$.each(o, function(key, value) {
|
||||
// Check if element has this data attribute
|
||||
attr = $this.attr('data-' + key);
|
||||
if (typeof attr !== 'undefined') {
|
||||
// Now check if value is boolean or not
|
||||
switch (attr) {
|
||||
case 'true':
|
||||
attr = true;
|
||||
break;
|
||||
case 'false':
|
||||
attr = false;
|
||||
break;
|
||||
}
|
||||
o[key] = attr;
|
||||
}
|
||||
});
|
||||
|
||||
// Reintroduce speed as an option. It calculates duration as a factor of the container width
|
||||
// measured in pixels per second.
|
||||
if (o.speed) {
|
||||
o.duration = parseInt($this.width(), 10) / o.speed * 1000;
|
||||
}
|
||||
|
||||
// Shortcut to see if direction is upward or downward
|
||||
verticalDir = o.direction == 'up' || o.direction == 'down';
|
||||
|
||||
// no gap if not duplicated
|
||||
o.gap = o.duplicated ? parseInt(o.gap) : 0;
|
||||
|
||||
// wrap inner content into a div
|
||||
$this.wrapInner('<div class="js-marquee"></div>');
|
||||
|
||||
// Make copy of the element
|
||||
var $el = $this.find('.js-marquee').css({
|
||||
'margin-right': o.gap,
|
||||
'float': 'left'
|
||||
});
|
||||
|
||||
if (o.duplicated) {
|
||||
$el.clone(true).appendTo($this);
|
||||
}
|
||||
|
||||
// wrap both inner elements into one div
|
||||
$this.wrapInner('<div style="width:100000px" class="js-marquee-wrapper"></div>');
|
||||
|
||||
// Save the reference of the wrapper
|
||||
$marqueeWrapper = $this.find('.js-marquee-wrapper');
|
||||
|
||||
// If direction is up or down, get the height of main element
|
||||
if (verticalDir) {
|
||||
var containerHeight = $this.height();
|
||||
$marqueeWrapper.removeAttr('style');
|
||||
$this.height(containerHeight);
|
||||
|
||||
// Change the CSS for js-marquee element
|
||||
$this.find('.js-marquee').css({
|
||||
'float': 'none',
|
||||
'margin-bottom': o.gap,
|
||||
'margin-right': 0
|
||||
});
|
||||
|
||||
// Remove bottom margin from 2nd element if duplicated
|
||||
if (o.duplicated) $this.find('.js-marquee:last').css({
|
||||
'margin-bottom': 0
|
||||
});
|
||||
|
||||
var elHeight = $this.find('.js-marquee:first').height() + o.gap;
|
||||
|
||||
// adjust the animation duration according to the text length
|
||||
if (o.startVisible && !o.duplicated) {
|
||||
// Compute the complete animation duration and save it for later reference
|
||||
// formula is to: (Height of the text node + height of the main container / Height of the main container) * duration;
|
||||
o._completeDuration = ((parseInt(elHeight, 10) + parseInt(containerHeight, 10)) / parseInt(containerHeight, 10)) * o.duration;
|
||||
|
||||
// formula is to: (Height of the text node / height of the main container) * duration
|
||||
o.duration = (parseInt(elHeight, 10) / parseInt(containerHeight, 10)) * o.duration;
|
||||
} else {
|
||||
// formula is to: (Height of the text node + height of the main container / Height of the main container) * duration;
|
||||
o.duration = ((parseInt(elHeight, 10) + parseInt(containerHeight, 10)) / parseInt(containerHeight, 10)) * o.duration;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Save the width of the each element so we can use it in animation
|
||||
elWidth = $this.find('.js-marquee:first').width() + o.gap;
|
||||
|
||||
// container width
|
||||
containerWidth = $this.width();
|
||||
|
||||
// adjust the animation duration according to the text length
|
||||
if (o.startVisible && !o.duplicated) {
|
||||
// Compute the complete animation duration and save it for later reference
|
||||
// formula is to: (Width of the text node + width of the main container / Width of the main container) * duration;
|
||||
o._completeDuration = ((parseInt(elWidth, 10) + parseInt(containerWidth, 10)) / parseInt(containerWidth, 10)) * o.duration;
|
||||
|
||||
// (Width of the text node / width of the main container) * duration
|
||||
o.duration = (parseInt(elWidth, 10) / parseInt(containerWidth, 10)) * o.duration;
|
||||
} else {
|
||||
// formula is to: (Width of the text node + width of the main container / Width of the main container) * duration;
|
||||
o.duration = ((parseInt(elWidth, 10) + parseInt(containerWidth, 10)) / parseInt(containerWidth, 10)) * o.duration;
|
||||
}
|
||||
}
|
||||
|
||||
// if duplicated then reduce the duration
|
||||
if (o.duplicated) {
|
||||
o.duration = o.duration / 2;
|
||||
}
|
||||
|
||||
if (o.allowCss3Support) {
|
||||
var
|
||||
elm = document.body || document.createElement('div'),
|
||||
animationName = 'marqueeAnimation-' + Math.floor(Math.random() * 10000000),
|
||||
domPrefixes = 'Webkit Moz O ms Khtml'.split(' '),
|
||||
animationString = 'animation',
|
||||
animationCss3Str = '',
|
||||
keyframeString = '';
|
||||
|
||||
// Check css3 support
|
||||
if (elm.style.animation !== undefined) {
|
||||
keyframeString = '@keyframes ' + animationName + ' ';
|
||||
css3AnimationIsSupported = true;
|
||||
}
|
||||
|
||||
if (css3AnimationIsSupported === false) {
|
||||
for (var i = 0; i < domPrefixes.length; i++) {
|
||||
if (elm.style[domPrefixes[i] + 'AnimationName'] !== undefined) {
|
||||
var prefix = '-' + domPrefixes[i].toLowerCase() + '-';
|
||||
animationString = prefix + animationString;
|
||||
playState = prefix + playState;
|
||||
keyframeString = '@' + prefix + 'keyframes ' + animationName + ' ';
|
||||
css3AnimationIsSupported = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (css3AnimationIsSupported) {
|
||||
animationCss3Str = animationName + ' ' + o.duration / 1000 + 's ' + o.delayBeforeStart / 1000 + 's infinite ' + o.css3easing;
|
||||
$this.data('css3AnimationIsSupported', true);
|
||||
}
|
||||
}
|
||||
|
||||
var _rePositionVertically = function() {
|
||||
$marqueeWrapper.css('transform', 'translateY(' + (o.direction == 'up' ? containerHeight + 'px' : '-' + elHeight + 'px') + ')');
|
||||
},
|
||||
_rePositionHorizontally = function() {
|
||||
$marqueeWrapper.css('transform', 'translateX(' + (o.direction == 'left' ? containerWidth + 'px' : '-' + elWidth + 'px') + ')');
|
||||
};
|
||||
|
||||
// if duplicated option is set to true than position the wrapper
|
||||
if (o.duplicated) {
|
||||
if (verticalDir) {
|
||||
if (o.startVisible) {
|
||||
$marqueeWrapper.css('transform', 'translateY(0)');
|
||||
} else {
|
||||
$marqueeWrapper.css('transform', 'translateY(' + (o.direction == 'up' ? containerHeight + 'px' : '-' + ((elHeight * 2) - o.gap) + 'px') + ')');
|
||||
}
|
||||
} else {
|
||||
if (o.startVisible) {
|
||||
$marqueeWrapper.css('transform', 'translateX(0)');
|
||||
} else {
|
||||
$marqueeWrapper.css('transform', 'translateX(' + (o.direction == 'left' ? containerWidth + 'px' : '-' + ((elWidth * 2) - o.gap) + 'px') + ')');
|
||||
}
|
||||
}
|
||||
|
||||
// If the text starts out visible we can skip the two initial loops
|
||||
if (!o.startVisible) {
|
||||
loopCount = 1;
|
||||
}
|
||||
} else if (o.startVisible) {
|
||||
// We only have two different loops if marquee is duplicated and starts visible
|
||||
loopCount = 2;
|
||||
} else {
|
||||
if (verticalDir) {
|
||||
_rePositionVertically();
|
||||
} else {
|
||||
_rePositionHorizontally();
|
||||
}
|
||||
}
|
||||
|
||||
// Animate recursive method
|
||||
var animate = function() {
|
||||
if (o.duplicated) {
|
||||
// When duplicated, the first loop will be scroll longer so double the duration
|
||||
if (loopCount === 1) {
|
||||
o._originalDuration = o.duration;
|
||||
if (verticalDir) {
|
||||
o.duration = o.direction == 'up' ? o.duration + (containerHeight / ((elHeight) / o.duration)) : o.duration * 2;
|
||||
} else {
|
||||
o.duration = o.direction == 'left' ? o.duration + (containerWidth / ((elWidth) / o.duration)) : o.duration * 2;
|
||||
}
|
||||
// Adjust the css3 animation as well
|
||||
if (animationCss3Str) {
|
||||
animationCss3Str = animationName + ' ' + o.duration / 1000 + 's ' + o.delayBeforeStart / 1000 + 's ' + o.css3easing;
|
||||
}
|
||||
loopCount++;
|
||||
}
|
||||
// On 2nd loop things back to normal, normal duration for the rest of animations
|
||||
else if (loopCount === 2) {
|
||||
o.duration = o._originalDuration;
|
||||
// Adjust the css3 animation as well
|
||||
if (animationCss3Str) {
|
||||
animationName = animationName + '0';
|
||||
keyframeString = $.trim(keyframeString) + '0 ';
|
||||
animationCss3Str = animationName + ' ' + o.duration / 1000 + 's 0s infinite ' + o.css3easing;
|
||||
}
|
||||
loopCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (verticalDir) {
|
||||
if (o.duplicated) {
|
||||
|
||||
// Adjust the starting point of animation only when first loops finishes
|
||||
if (loopCount > 2) {
|
||||
$marqueeWrapper.css('transform', 'translateY(' + (o.direction == 'up' ? 0 : '-' + elHeight + 'px') + ')');
|
||||
}
|
||||
|
||||
animationCss = {
|
||||
'transform': 'translateY(' + (o.direction == 'up' ? '-' + elHeight + 'px' : 0) + ')'
|
||||
};
|
||||
} else if (o.startVisible) {
|
||||
// This loop moves the marquee out of the container
|
||||
if (loopCount === 2) {
|
||||
// Adjust the css3 animation as well
|
||||
if (animationCss3Str) {
|
||||
animationCss3Str = animationName + ' ' + o.duration / 1000 + 's ' + o.delayBeforeStart / 1000 + 's ' + o.css3easing;
|
||||
}
|
||||
animationCss = {
|
||||
'transform': 'translateY(' + (o.direction == 'up' ? '-' + elHeight + 'px' : containerHeight + 'px') + ')'
|
||||
};
|
||||
loopCount++;
|
||||
} else if (loopCount === 3) {
|
||||
// Set the duration for the animation that will run forever
|
||||
o.duration = o._completeDuration;
|
||||
// Adjust the css3 animation as well
|
||||
if (animationCss3Str) {
|
||||
animationName = animationName + '0';
|
||||
keyframeString = $.trim(keyframeString) + '0 ';
|
||||
animationCss3Str = animationName + ' ' + o.duration / 1000 + 's 0s infinite ' + o.css3easing;
|
||||
}
|
||||
_rePositionVertically();
|
||||
}
|
||||
} else {
|
||||
_rePositionVertically();
|
||||
animationCss = {
|
||||
'transform': 'translateY(' + (o.direction == 'up' ? '-' + ($marqueeWrapper.height()) + 'px' : containerHeight + 'px') + ')'
|
||||
};
|
||||
}
|
||||
} else {
|
||||
if (o.duplicated) {
|
||||
|
||||
// Adjust the starting point of animation only when first loops finishes
|
||||
if (loopCount > 2) {
|
||||
$marqueeWrapper.css('transform', 'translateX(' + (o.direction == 'left' ? 0 : '-' + elWidth + 'px') + ')');
|
||||
}
|
||||
|
||||
animationCss = {
|
||||
'transform': 'translateX(' + (o.direction == 'left' ? '-' + elWidth + 'px' : 0) + ')'
|
||||
};
|
||||
|
||||
} else if (o.startVisible) {
|
||||
// This loop moves the marquee out of the container
|
||||
if (loopCount === 2) {
|
||||
// Adjust the css3 animation as well
|
||||
if (animationCss3Str) {
|
||||
animationCss3Str = animationName + ' ' + o.duration / 1000 + 's ' + o.delayBeforeStart / 1000 + 's ' + o.css3easing;
|
||||
}
|
||||
animationCss = {
|
||||
'transform': 'translateX(' + (o.direction == 'left' ? '-' + elWidth + 'px' : containerWidth + 'px') + ')'
|
||||
};
|
||||
loopCount++;
|
||||
} else if (loopCount === 3) {
|
||||
// Set the duration for the animation that will run forever
|
||||
o.duration = o._completeDuration;
|
||||
// Adjust the css3 animation as well
|
||||
if (animationCss3Str) {
|
||||
animationName = animationName + '0';
|
||||
keyframeString = $.trim(keyframeString) + '0 ';
|
||||
animationCss3Str = animationName + ' ' + o.duration / 1000 + 's 0s infinite ' + o.css3easing;
|
||||
}
|
||||
_rePositionHorizontally();
|
||||
}
|
||||
} else {
|
||||
_rePositionHorizontally();
|
||||
animationCss = {
|
||||
'transform': 'translateX(' + (o.direction == 'left' ? '-' + elWidth + 'px' : containerWidth + 'px') + ')'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// fire event
|
||||
$this.trigger('beforeStarting');
|
||||
|
||||
// If css3 support is available than do it with css3, otherwise use jQuery as fallback
|
||||
if (css3AnimationIsSupported) {
|
||||
// Add css3 animation to the element
|
||||
$marqueeWrapper.css(animationString, animationCss3Str);
|
||||
var keyframeCss = keyframeString + ' { 100% ' + _objToString(animationCss) + '}',
|
||||
$styles = $marqueeWrapper.find('style');
|
||||
|
||||
// Now add the keyframe animation to the marquee element
|
||||
if ($styles.length !== 0) {
|
||||
// Bug fixed for jQuery 1.3.x - Instead of using .last(), use following
|
||||
$styles.filter(":last").html(keyframeCss);
|
||||
} else {
|
||||
$('head').append('<style>' + keyframeCss + '</style>');
|
||||
}
|
||||
|
||||
// Animation iteration event
|
||||
_prefixedEvent($marqueeWrapper[0], "AnimationIteration", function() {
|
||||
$this.trigger('finished');
|
||||
});
|
||||
// Animation stopped
|
||||
_prefixedEvent($marqueeWrapper[0], "AnimationEnd", function() {
|
||||
animate();
|
||||
$this.trigger('finished');
|
||||
});
|
||||
|
||||
} else {
|
||||
// Start animating
|
||||
$marqueeWrapper.animate(animationCss, o.duration, o.easing, function() {
|
||||
// fire event
|
||||
$this.trigger('finished');
|
||||
// animate again
|
||||
if (o.pauseOnCycle) {
|
||||
_startAnimationWithDelay();
|
||||
} else {
|
||||
animate();
|
||||
}
|
||||
});
|
||||
}
|
||||
// save the status
|
||||
$this.data('runningStatus', 'resumed');
|
||||
};
|
||||
|
||||
// bind pause and resume events
|
||||
$this.bind('pause', methods.pause);
|
||||
$this.bind('resume', methods.resume);
|
||||
|
||||
if (o.pauseOnHover) {
|
||||
$this.bind('mouseenter', methods.pause);
|
||||
$this.bind('mouseleave', methods.resume);
|
||||
}
|
||||
|
||||
// If css3 animation is supported than call animate method at once
|
||||
if (css3AnimationIsSupported && o.allowCss3Support) {
|
||||
animate();
|
||||
} else {
|
||||
// Starts the recursive method
|
||||
_startAnimationWithDelay();
|
||||
}
|
||||
|
||||
});
|
||||
}; // End of Plugin
|
||||
// Public: plugin defaults options
|
||||
$.fn.marquee.defaults = {
|
||||
// If you wish to always animate using jQuery
|
||||
allowCss3Support: true,
|
||||
// works when allowCss3Support is set to true - for full list see http://www.w3.org/TR/2013/WD-css3-transitions-20131119/#transition-timing-function
|
||||
css3easing: 'linear',
|
||||
// requires jQuery easing plugin. Default is 'linear'
|
||||
easing: 'linear',
|
||||
// pause time before the next animation turn in milliseconds
|
||||
delayBeforeStart: 1000,
|
||||
// 'left', 'right', 'up' or 'down'
|
||||
direction: 'left',
|
||||
// true or false - should the marquee be duplicated to show an effect of continues flow
|
||||
duplicated: false,
|
||||
// duration in milliseconds of the marquee in milliseconds
|
||||
duration: 5000,
|
||||
// gap in pixels between the tickers
|
||||
gap: 20,
|
||||
// on cycle pause the marquee
|
||||
pauseOnCycle: false,
|
||||
// on hover pause the marquee - using jQuery plugin https://github.com/tobia/Pause
|
||||
pauseOnHover: false,
|
||||
// the marquee is visible initially positioned next to the border towards it will be moving
|
||||
startVisible: false
|
||||
};
|
||||
})(jQuery);
|
16
app/static/js/jquery.marquee.min.js
vendored
Executable file
16
app/static/js/jquery.marquee.min.js
vendored
Executable file
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* jQuery.marquee - scrolling text like old marquee element
|
||||
* @author Aamir Afridi - aamirafridi(at)gmail(dot)com / http://aamirafridi.com/jquery/jquery-marquee-plugin
|
||||
*/
|
||||
(function(f){f.fn.marquee=function(x){return this.each(function(){var a=f.extend({},f.fn.marquee.defaults,x),b=f(this),c,t,e=3,y="animation-play-state",p=!1,E=function(a,b,c){for(var e=["webkit","moz","MS","o",""],d=0;d<e.length;d++)e[d]||(b=b.toLowerCase()),a.addEventListener(e[d]+b,c,!1)},F=function(a){var b=[],c;for(c in a)a.hasOwnProperty(c)&&b.push(c+":"+a[c]);b.push();return"{"+b.join(",")+"}"},l={pause:function(){p&&a.allowCss3Support?c.css(y,"paused"):f.fn.pause&&c.pause();b.data("runningStatus",
|
||||
"paused");b.trigger("paused")},resume:function(){p&&a.allowCss3Support?c.css(y,"running"):f.fn.resume&&c.resume();b.data("runningStatus","resumed");b.trigger("resumed")},toggle:function(){l["resumed"==b.data("runningStatus")?"pause":"resume"]()},destroy:function(){clearTimeout(b.timer);b.find("*").addBack().unbind();b.html(b.find(".js-marquee:first").html())}};if("string"===typeof x)f.isFunction(l[x])&&(c||(c=b.find(".js-marquee-wrapper")),!0===b.data("css3AnimationIsSupported")&&(p=!0),l[x]());else{var u;
|
||||
f.each(a,function(c,d){u=b.attr("data-"+c);if("undefined"!==typeof u){switch(u){case "true":u=!0;break;case "false":u=!1}a[c]=u}});a.speed&&(a.duration=parseInt(b.width(),10)/a.speed*1E3);var v="up"==a.direction||"down"==a.direction;a.gap=a.duplicated?parseInt(a.gap):0;b.wrapInner('<div class="js-marquee"></div>');var h=b.find(".js-marquee").css({"margin-right":a.gap,"float":"left"});a.duplicated&&h.clone(!0).appendTo(b);b.wrapInner('<div style="width:100000px" class="js-marquee-wrapper"></div>');
|
||||
c=b.find(".js-marquee-wrapper");if(v){var k=b.height();c.removeAttr("style");b.height(k);b.find(".js-marquee").css({"float":"none","margin-bottom":a.gap,"margin-right":0});a.duplicated&&b.find(".js-marquee:last").css({"margin-bottom":0});var q=b.find(".js-marquee:first").height()+a.gap;a.startVisible&&!a.duplicated?(a._completeDuration=(parseInt(q,10)+parseInt(k,10))/parseInt(k,10)*a.duration,a.duration*=parseInt(q,10)/parseInt(k,10)):a.duration*=(parseInt(q,10)+parseInt(k,10))/parseInt(k,10)}else{var m=
|
||||
b.find(".js-marquee:first").width()+a.gap;var n=b.width();a.startVisible&&!a.duplicated?(a._completeDuration=(parseInt(m,10)+parseInt(n,10))/parseInt(n,10)*a.duration,a.duration*=parseInt(m,10)/parseInt(n,10)):a.duration*=(parseInt(m,10)+parseInt(n,10))/parseInt(n,10)}a.duplicated&&(a.duration/=2);if(a.allowCss3Support){h=document.body||document.createElement("div");var g="marqueeAnimation-"+Math.floor(1E7*Math.random()),A=["Webkit","Moz","O","ms","Khtml"],B="animation",d="",r="";h.style.animation&&
|
||||
(r="@keyframes "+g+" ",p=!0);if(!1===p)for(var z=0;z<A.length;z++)if(void 0!==h.style[A[z]+"AnimationName"]){h="-"+A[z].toLowerCase()+"-";B=h+B;y=h+y;r="@"+h+"keyframes "+g+" ";p=!0;break}p&&(d=g+" "+a.duration/1E3+"s "+a.delayBeforeStart/1E3+"s infinite "+a.css3easing,b.data("css3AnimationIsSupported",!0))}var C=function(){c.css("transform","translateY("+("up"==a.direction?k+"px":"-"+q+"px")+")")},D=function(){c.css("transform","translateX("+("left"==a.direction?n+"px":"-"+m+"px")+")")};a.duplicated?
|
||||
(v?a.startVisible?c.css("transform","translateY(0)"):c.css("transform","translateY("+("up"==a.direction?k+"px":"-"+(2*q-a.gap)+"px")+")"):a.startVisible?c.css("transform","translateX(0)"):c.css("transform","translateX("+("left"==a.direction?n+"px":"-"+(2*m-a.gap)+"px")+")"),a.startVisible||(e=1)):a.startVisible?e=2:v?C():D();var w=function(){a.duplicated&&(1===e?(a._originalDuration=a.duration,a.duration=v?"up"==a.direction?a.duration+k/(q/a.duration):2*a.duration:"left"==a.direction?a.duration+n/
|
||||
(m/a.duration):2*a.duration,d&&(d=g+" "+a.duration/1E3+"s "+a.delayBeforeStart/1E3+"s "+a.css3easing),e++):2===e&&(a.duration=a._originalDuration,d&&(g+="0",r=f.trim(r)+"0 ",d=g+" "+a.duration/1E3+"s 0s infinite "+a.css3easing),e++));v?a.duplicated?(2<e&&c.css("transform","translateY("+("up"==a.direction?0:"-"+q+"px")+")"),t={transform:"translateY("+("up"==a.direction?"-"+q+"px":0)+")"}):a.startVisible?2===e?(d&&(d=g+" "+a.duration/1E3+"s "+a.delayBeforeStart/1E3+"s "+a.css3easing),t={transform:"translateY("+
|
||||
("up"==a.direction?"-"+q+"px":k+"px")+")"},e++):3===e&&(a.duration=a._completeDuration,d&&(g+="0",r=f.trim(r)+"0 ",d=g+" "+a.duration/1E3+"s 0s infinite "+a.css3easing),C()):(C(),t={transform:"translateY("+("up"==a.direction?"-"+c.height()+"px":k+"px")+")"}):a.duplicated?(2<e&&c.css("transform","translateX("+("left"==a.direction?0:"-"+m+"px")+")"),t={transform:"translateX("+("left"==a.direction?"-"+m+"px":0)+")"}):a.startVisible?2===e?(d&&(d=g+" "+a.duration/1E3+"s "+a.delayBeforeStart/1E3+"s "+a.css3easing),
|
||||
t={transform:"translateX("+("left"==a.direction?"-"+m+"px":n+"px")+")"},e++):3===e&&(a.duration=a._completeDuration,d&&(g+="0",r=f.trim(r)+"0 ",d=g+" "+a.duration/1E3+"s 0s infinite "+a.css3easing),D()):(D(),t={transform:"translateX("+("left"==a.direction?"-"+m+"px":n+"px")+")"});b.trigger("beforeStarting");if(p){c.css(B,d);var h=r+" { 100% "+F(t)+"}",l=c.find("style");0!==l.length?l.filter(":last").html(h):f("head").append("<style>"+h+"</style>");E(c[0],"AnimationIteration",function(){b.trigger("finished")});
|
||||
E(c[0],"AnimationEnd",function(){w();b.trigger("finished")})}else c.animate(t,a.duration,a.easing,function(){b.trigger("finished");a.pauseOnCycle?b.timer=setTimeout(w,a.delayBeforeStart):w()});b.data("runningStatus","resumed")};b.bind("pause",l.pause);b.bind("resume",l.resume);a.pauseOnHover&&(b.bind("mouseenter",l.pause),b.bind("mouseleave",l.resume));p&&a.allowCss3Support?w():b.timer=setTimeout(w,a.delayBeforeStart)}})};f.fn.marquee.defaults={allowCss3Support:!0,css3easing:"linear",easing:"linear",
|
||||
delayBeforeStart:1E3,direction:"left",duplicated:!1,duration:5E3,gap:20,pauseOnCycle:!1,pauseOnHover:!1,startVisible:!1}})(jQuery);
|
@ -2,29 +2,27 @@
|
||||
|
||||
{% block main %}
|
||||
<h1 class="page-header">About</h1>
|
||||
<div style="width: 900px;">
|
||||
<p class='about'>
|
||||
XPPL is a project aimed at people who are studying the field of media culture, or as we like to call them: knowledge comrades.
|
||||
<br>
|
||||
<br>
|
||||
This digital library gathers all the books and articles floating around on the shelves of the Piet Zwart Institute, and our hard drives and memory sticks, so that they can be shared, annotated and grouped together into stacks...
|
||||
This digital library gathers all the books and articles floating around on the shelves of the Piet Zwart Institute, and our hard drives and memory sticks, so that they can be shared, annotated and grouped together into stacks... Its web interface hosts a curated catalogue of books and articles, and its distributed architecture provides instances for uploading and downloading.
|
||||
<br>
|
||||
<br>
|
||||
Its web interface hosts a curated catalogue of books and articles, and its distributed architecture provides instances for uploading and downloading.
|
||||
It starts at XPUB, but can go anywhere we want it to.
|
||||
<br>
|
||||
<br>
|
||||
It starts at XPUB, but can go anywhere we want it to.</p>
|
||||
|
||||
|
||||
Are you interested in how this library works? Have a look at the source code in <a href 'https://git.xpub.nl/xpub-lib/log.html'> our git. </a>
|
||||
</p>
|
||||
<h2> What's the deal with the stacks? </h2>
|
||||
<p class='about'>
|
||||
A stack is a number of books that are read at a certain point in time, alternating between them. They usually have a topic in common, or follow a certain study path that can bring you to a point of knowledge. Rather than a bookshelf, where books are lined up and often forgotten, the stack on your table/nightstand/toilet consists of books prone to be opened and reopened at any time.
|
||||
</p>
|
||||
|
||||
<h2>Who's behind this?</h2>
|
||||
<p class='about'>
|
||||
We're Angeliki, Alex, Alice, Joca, Natasha and Zalán, helped and supported by Femke, Aymeric, Michael, Steve, Andre, Leslie and many more.
|
||||
<br>
|
||||
<br>
|
||||
XPUB is a study path within the Piet Zwart Institute masters program.
|
||||
We're Angeliki, Alex, Alice, Joca, Natasha and Zalán, helped and supported by Femke, Aymeric, Michael, Steve, Andre, Leslie and many more. XPUB is a study path within the Piet Zwart Institute masters program.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
@ -36,7 +36,7 @@ function outputUpdate3(gender) {
|
||||
<div class="form-group">Title:* <br> {{ form.title (size=50, class="form-control") }}</div>
|
||||
<br>
|
||||
<div data-toggle="fieldset" id="phone-fieldset">
|
||||
Author(s):* <button type="button" data-toggle="fieldset-add-row data-target="#phone-fieldset">+</button>
|
||||
Author(s):* <button type="button" data-toggle="fieldset-add-row" data-target="#phone-fieldset">+</button>
|
||||
<table>
|
||||
<tr>
|
||||
<th></th>
|
||||
@ -68,17 +68,12 @@ Check the bibliography. How diverse are the references in this book? <br>
|
||||
<br><hr align="left" style="width:96%;"><br>
|
||||
|
||||
Check the writing. Who is speaking? Is the voice more often male or female? <br>
|
||||
{{ form.diversity(min=1, max=100, oninput="outputUpdate3(value)") }}
|
||||
{{ form.gender(min=1, max=100, oninput="outputUpdate3(value)") }}
|
||||
<span style="color: #d3d3d3;"><output for="diversity" id="selected-gender">{{ form.gender.data }} </output> % female</span>
|
||||
|
||||
<br><hr align="left" style="width:96%;"><br>
|
||||
Who are you? {{ render_field(form.who) }}
|
||||
|
||||
<br><hr align="left" style="width:96%;"><br>
|
||||
How much time have you spent with this item?
|
||||
Include the time spent looking for it, and uploading it.<br>
|
||||
{{ form.time (size = 50, class="form-control")}} <span style="color: #d3d3d3;">hours</span>
|
||||
<br>
|
||||
<br><hr align="left" style="width:96%;"><br>
|
||||
|
||||
<div style="width: 40%;">
|
||||
|
@ -22,12 +22,26 @@
|
||||
{{form.hidden_tag()}}
|
||||
<br>
|
||||
{{ render_field(form.stack_name)}}
|
||||
{{ render_field(form.stack_description)}}
|
||||
<div style="width: 40%;">
|
||||
Add a nice description: {{ form.stack_description(size=90, class="form-control") }}
|
||||
</div>
|
||||
{{ render_field(form.stack_author)}}
|
||||
<br>
|
||||
<button type="submit" class='button'>Create</button>
|
||||
</form>
|
||||
<br>
|
||||
<hr>
|
||||
<br>
|
||||
<h1> Stacks currently in the library </h1>
|
||||
<ul>
|
||||
{% for stack in stacks %}
|
||||
|
||||
<li> <a href="stacks/tab/{{ stack.id }}">
|
||||
|
||||
</form>
|
||||
{{ stack.stack_name }}
|
||||
</a></td>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
<div> Chosen book:
|
||||
|
||||
<h1 class="header">{{ book.title }}</h1>
|
||||
<img class="no_cover" id="{{ book.title }}" src="../uploads/cover/{{ book.cover }}" width="150" onerror="if (this.src != '../static/img/{{ book.cover }}') this.src = '../static/img/default_cover.gif';">
|
||||
<img class="no_cover" id="{{ book.title }}" src="../cover/{{ book.cover }}" width="150" onerror="if (this.src != '../static/img/{{ book.cover }}') this.src = '../static/img/default_cover.gif';">
|
||||
|
||||
</div>
|
||||
<p>These are all the stacks that have been built so far.</p>
|
||||
|
@ -43,15 +43,22 @@
|
||||
|
||||
{% block js %} {% endblock%}
|
||||
|
||||
<<<<<<< HEAD
|
||||
<script type="text/javascript" src="http://code.jquery.com/jquery-2.2.4.js"></script>
|
||||
<script type="text/javascript" src="http://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>
|
||||
<script type='text/javascript' src='//cdn.jsdelivr.net/jquery.marquee/1.4.0/jquery.marquee.min.js'></script>
|
||||
=======
|
||||
<script src="{{ url_for("static", filename="js/jquery-3.3.1.min.js") }}"></script>
|
||||
<script src="{{ url_for("static", filename="js/jquery-ui-1.12.1.custom/jquery-ui.js") }}"></script>
|
||||
<script src="{{ url_for("static", filename="js/jquery.marquee.min.js") }}"></script>
|
||||
>>>>>>> 0f5e5606ab9152e9d27e7081e251e12a7f33824b
|
||||
<script type="text/javascript" src="{{ url_for("static", filename="js/jquery.tablesorter.js") }}"></script>
|
||||
<script src="{{ url_for("static", filename="js/app.js") }}"></script>
|
||||
|
||||
<script src="{{ url_for("static", filename="js/vendor/socket.io.slim.js") }}"></script>
|
||||
<script src="{{ url_for("static", filename="js/vendor/vue.min.js") }}"></script>
|
||||
<script>
|
||||
|
||||
function convertTime(inTime){
|
||||
var time = inTime;
|
||||
time = time.match(/(\d+)\-(\d+)\-(\d+)\s*(\d+):(\d+):(\d+)/);
|
||||
@ -98,6 +105,28 @@ socket.on('connect', function() {
|
||||
});
|
||||
|
||||
socket.on('channel-' + app.channel, function(msg) {
|
||||
console.log("new: "+msg.text)
|
||||
|
||||
|
||||
$(".messageback1").each(function() {
|
||||
var oldColor = $(this).css("background-color");
|
||||
var randomColor = colorHash(msg.text).rgb;
|
||||
console.log("old: "+oldColor)
|
||||
console.log("new: "+randomColor)
|
||||
$(this).css({
|
||||
background: "-webkit-gradient(linear, left top, left bottom, from("+oldColor+"), to("+randomColor+"))",
|
||||
backgroundColor: randomColor
|
||||
});
|
||||
|
||||
$('.messageback2').animate({
|
||||
opacity: 0
|
||||
}, 1000, function() {
|
||||
$('.messageback2').css({background: "-webkit-gradient(linear, left top, left bottom, from("+oldColor+"), to("+randomColor+"))", opacity: 1})
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
// Add new message to HTML
|
||||
let my_messages = app.messages;
|
||||
my_messages.push({
|
||||
|
@ -1,22 +1,36 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block main %}
|
||||
{% from "_formhelpers.html" import render_field %}
|
||||
|
||||
<head>
|
||||
<script>
|
||||
function outputUpdate(sameness) {
|
||||
document.querySelector('#selected-sameness').value = sameness;
|
||||
}
|
||||
function outputUpdate2(diversity) {
|
||||
document.querySelector('#selected-diversity').value = diversity;
|
||||
}
|
||||
function outputUpdate3(gender) {
|
||||
document.querySelector('#selected-gender').value = gender;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<div class="container">
|
||||
|
||||
<a href="{{ url_for('show_book_by_id', id=book.id )}}">back</a>
|
||||
|
||||
|
||||
|
||||
<form method="POST" action="{{ url_for('edit_book_by_id', id=book.id )}}" enctype=multipart/form-data>
|
||||
{{ form.csrf_token }}
|
||||
|
||||
<div class="form-group"><h1 class="header">{{ form.title.label }} {{ form.title(size=20, class="form-control") }}</h1></div>
|
||||
|
||||
<img class="no_cover" id="{{ book.title }}" src="/uploads/cover/{{ book.cover }}" width="150" onerror="if (this.src != '/uploads/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';">
|
||||
<div style="float:right; padding-right: 300px;">
|
||||
<img class="no_cover" id="{{ book.title }}" src="../uploads/cover/{{ book.cover }}" width="280px" onerror="if (this.src != '/uploads/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';"></div>
|
||||
|
||||
<br> <br>
|
||||
<br>
|
||||
<div data-toggle="fieldset" id="phone-fieldset">
|
||||
{{ form.author.label }} <button type="button" data-toggle="fieldset-add-row"
|
||||
{{ form.author.label }}*: <button type="button" data-toggle="fieldset-add-row"
|
||||
data-target="#phone-fieldset">+</button>
|
||||
<table>
|
||||
<tr>
|
||||
@ -25,28 +39,45 @@
|
||||
</tr>
|
||||
{% for author in form.author %}
|
||||
<tr data-toggle="fieldset-entry">
|
||||
<td>{{ author.author_name }}</td>
|
||||
<td>{{ author.author_name (size=50, class="form-control") }}</td>
|
||||
<td><button type="button" data-toggle="fieldset-remove-row" id="phone-{{loop.index0}}-remove">-</button></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div><br>
|
||||
<div class="form-group" style="padding-bottom: 10px;">
|
||||
Category: {{ form.category(size=20,
|
||||
class="form-control") }}
|
||||
</div>
|
||||
<div class="form-group" style="padding-bottom: 10px;">
|
||||
Year published: {{ form.year_published(size=8, class="form-control") }}
|
||||
</table><br>
|
||||
<br>
|
||||
Category:* <br> {{ form.category(size=50, class="form-control") }} <br><br>
|
||||
Year published: <br> {{ form.year_published(size=8, class="form-control") }} <br><br>
|
||||
|
||||
How different is this item to the rest of the collection?
|
||||
Or is it more of the same? <br>
|
||||
{{ form.sameness(min=0, max=100, oninput="outputUpdate(value)") }}
|
||||
<span style="color: #d3d3d3;"><output for="sameness" id="selected-sameness">{{ form.sameness.data }} </output> % different</span>
|
||||
|
||||
<br><hr align="left" style="width:40%;"><br>
|
||||
|
||||
Check the bibliography. How diverse are the references in this book? <br>
|
||||
{{ form.diversity(min=0, max=100, oninput="outputUpdate2(value)") }}
|
||||
<span style="color: #d3d3d3;"><output for="diversity" id="selected-diversity">{{ form.diversity.data }} </output> % diverse</span>
|
||||
|
||||
<br><hr align="left" style="width:40%;"><br>
|
||||
|
||||
Check the writing. Who is speaking? Is the voice more often male or female? <br>
|
||||
{{ form.gender(min=1, max=100, oninput="outputUpdate3(value)") }}
|
||||
<span style="color: #d3d3d3;"><output for="diversity" id="selected-gender">{{ form.gender.data }} </output> % female</span>
|
||||
|
||||
<br><hr align="left" style="width:40%;"><br>
|
||||
Who are you? {{ render_field(form.who)}}
|
||||
<br><hr align="left" style="width:40%;"><br>
|
||||
|
||||
<div class="form-group" style="padding-bottom: 10px;">
|
||||
Current file: {{ book.file }} Upload new file: {{form.file}}
|
||||
</div>
|
||||
<div class="form-group" style="padding-bottom: 10px;">
|
||||
Current file: {{ book.file }}
|
||||
</div>
|
||||
<div class="form-group" style="padding-bottom: 10px;">
|
||||
Upload new file: {{form.file}}
|
||||
|
||||
</div>
|
||||
<div class="form-group" style="padding-bottom: 10px;">
|
||||
|
||||
If uploading, write a new message: {{form.message(size=150, class="form-control") }}
|
||||
If uploading, write a new message: <br>{{form.message(size=135, class="form-control") }}
|
||||
|
||||
</div>
|
||||
<br>
|
||||
|
@ -3,10 +3,16 @@
|
||||
<li><a href="{{ url_for('home') }}">Home</a></li>
|
||||
<li><a href="{{ url_for('show_books') }}">Catalogue</a></li>
|
||||
<li><a href="{{ url_for('show_stacks') }}">Stacks</a></li>
|
||||
{%if light%}
|
||||
{%else%}
|
||||
<li><a href="{{ url_for('add_book') }}">Add Book</a></li>
|
||||
<li><a href="{{ url_for ('add_stack') }}">Add Stack</a></li>
|
||||
{%endif%}
|
||||
<li><a href="{{ url_for('about') }}">About</a></li>
|
||||
{%if light%}
|
||||
{%else%}
|
||||
<li><a href="{{ url_for('show_instances') }}">Instances</a></li>
|
||||
{%endif%}
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
</nav>
|
||||
|
@ -3,10 +3,10 @@
|
||||
{% block main %}
|
||||
<div id="home_content">
|
||||
<h1 class="header" id="title_xppl">XPPL</h1>
|
||||
<p class="lead">This is the awesome library of Experimental Publishing. <br>
|
||||
<p class="lead"> Welcome to our digital library. <br>
|
||||
On instance: {{server}} / From: {{client}}
|
||||
<br>
|
||||
This might only be one interface to this library:
|
||||
Feel free to browse our catalogue, interfaced in many different ways.
|
||||
</p>
|
||||
|
||||
<a href="{{url_for('scape')}}">Scape</a>
|
||||
@ -15,6 +15,8 @@ This might only be one interface to this library:
|
||||
|
||||
<br><br><br>
|
||||
|
||||
{%if light%}
|
||||
{%else%}
|
||||
<form method="GET" action="/export/csv">
|
||||
<button type="submit">Export Catalogue (.CSV)</button>
|
||||
</form>
|
||||
@ -23,9 +25,13 @@ This might only be one interface to this library:
|
||||
<button type = "button" onclick="document.getElementById('file_import_csv').click()">Import Catalogue (.CSV)</button>
|
||||
</form>
|
||||
</div>
|
||||
{%endif%}
|
||||
|
||||
<div id="app" class="container">
|
||||
<div class="messageback1"></div>
|
||||
<div class="messageback2"></div>
|
||||
<section class="messages">
|
||||
|
||||
<div v-for="message in messages" class="box">
|
||||
<article class="media">
|
||||
<div class="media-content">
|
||||
@ -38,6 +44,7 @@ This might only be one interface to this library:
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
<section class="new-message">
|
||||
<div class="field has-addons">
|
||||
|
@ -32,10 +32,13 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
{%if light%}
|
||||
{%else%}
|
||||
<div style="width: 220px; float: left; padding-right: 40px;">
|
||||
<img class="no_cover" width="220" src = '/static/img/default_cover.gif';>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div>
|
||||
<h2>Add this book:</h2>
|
||||
|
||||
@ -60,21 +63,19 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding-left:10px; padding-bottom: 50px;">
|
||||
<div style="padding-left:10px; padding-bottom: 100px;">
|
||||
<br>
|
||||
Category: {{ form.category(size=27, class="form-control") }}
|
||||
<br>
|
||||
<br>
|
||||
Year published: {{ form.year_published(size=8, class="form-control") }}
|
||||
<br>
|
||||
<br>
|
||||
{{ form.file }}
|
||||
{{ form.upload }}
|
||||
{{ form.wish }}
|
||||
</form>
|
||||
<br>
|
||||
<p><a href="{{ url_for('home') }}" style="font-size: 9pt;">go back home</a></p>
|
||||
<br>
|
||||
</div>
|
||||
{%endif%}
|
||||
<div class= "Container" style= "border-top: dashed; border-width: 1px;">
|
||||
<h2> More potential books </h2>
|
||||
<table class="library_table" id="table" style="width:100%">
|
||||
@ -86,7 +87,10 @@
|
||||
<th width="100px;">Year</th>
|
||||
<th width="100px;">Category</th>
|
||||
<th width="100px;">Stack</th>
|
||||
{%if light%}
|
||||
{%else%}
|
||||
<th width="100px;">Add to a stack</th>
|
||||
{%endif%}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -94,7 +98,7 @@
|
||||
<tr>
|
||||
<td style= "padding: 5px;">
|
||||
|
||||
<img class="no_cover" id="{{ book.title }}" src="/uploads/cover/{{ book.cover }}" width="70" onerror="if (this.src != '//uploads/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';">
|
||||
<img class="no_cover" id="{{ book.title }}" src="/cover/{{ book.cover }}" width="70" onerror="if (this.src != '/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';">
|
||||
<!-- <object class="no_cover" data="../static/img/default_cover.png" type="image/png" width="65">
|
||||
<p hidden="True"></p>
|
||||
|
||||
@ -121,10 +125,13 @@
|
||||
|
||||
|
||||
</td>
|
||||
{%if light%}
|
||||
{%else%}
|
||||
<td id='plus'><a href="{{url_for('add_to_stack', id=book.id)}}">
|
||||
|
||||
===>
|
||||
</a></td>
|
||||
{%endif%}
|
||||
</tr>
|
||||
|
||||
{% endfor %}
|
||||
|
@ -9,12 +9,12 @@
|
||||
{{ render_field(form.search) }} </div>
|
||||
<button type="submit" class="button">browse</button>
|
||||
<p><br>
|
||||
{{ form.grid(style="font-size:20px")}}{{ form.listview(style="font-size:20px")}}</p>
|
||||
{{ form.grid(style="font-size:20px")}}{{ form.listview(style="font-size:20px")}}</p>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<h3 style="line-height:0px;"">Results: "{{ query }}" included in {{ count }} out of {{ whole }} items </h3>
|
||||
<h3 style="line-height:0px;">Results: "{{ query }}" included in {{ count }} out of {{ whole }} items </h3>
|
||||
<div style="height: 20px; background-color: yellow; line-height:4px;">
|
||||
<div style="background-color: black; width: {{ percentage }}%; height: 100%;"></div>
|
||||
</div>
|
||||
@ -39,13 +39,15 @@
|
||||
<th width="100px;">Year</th>
|
||||
<th width="100px;">Category</th>
|
||||
<th width="100px;">Stack</th>
|
||||
{%if light%}
|
||||
{%else%}
|
||||
<th width="100px;">Add to stack</th>
|
||||
|
||||
{%endif%}
|
||||
</tr>
|
||||
{% for book in books %}
|
||||
<tr>
|
||||
<td style= "padding: 5px;">
|
||||
<img class="no_cover" id="{{ book.title }}" src="/uploads/cover/{{ book.cover }}" width="70" onerror="if (this.src != '//uploads/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';"></td>
|
||||
<img class="no_cover" id="{{ book.title }}" src="/cover/{{ book.cover }}" width="70" onerror="if (this.src != '/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';"></td>
|
||||
<td><a href="{{url_for('show_book_by_id', id=book.id)}}">{{ book.title }}</a></td>
|
||||
|
||||
<td> {% for author in book.authors %}
|
||||
@ -60,9 +62,12 @@
|
||||
<li><a href="{{url_for('show_stack_by_id', id=stack.id)}}">{{ stack.stack_name }}</a> </li>
|
||||
{% endfor %}
|
||||
</td>
|
||||
{%if light%}
|
||||
{%else%}
|
||||
<td id='plus'><a href="{{url_for('add_to_stack', id=book.id)}}">
|
||||
==>
|
||||
</a></td>
|
||||
{%endif%}
|
||||
{% endfor %}
|
||||
|
||||
</table>
|
||||
@ -81,12 +86,14 @@
|
||||
<th width="100px;">Year</th>
|
||||
<th width="100px;">Category</th>
|
||||
<th width="100px;">Stack</th>
|
||||
{%if light%}
|
||||
{%else%}
|
||||
<th width="100px;">Add to stack</th>
|
||||
|
||||
{%endif%}
|
||||
</tr>
|
||||
{% for book in books_all %}
|
||||
<tr>
|
||||
<td style= "padding: 5px;"><img class="no_cover" id="{{ book.title }}" src="/uploads/cover/{{ book.cover }}" width="80" onerror="if (this.src != '//uploads/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';"></td>
|
||||
<td style= "padding: 5px;"><img class="no_cover" id="{{ book.title }}" src="/cover/{{ book.cover }}" width="80" onerror="if (this.src != '/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';"></td>
|
||||
<td><a href="{{url_for('show_book_by_id', id=book.id)}}">{{ book.title }}</a></td>
|
||||
|
||||
<td> {% for author in book.authors %}
|
||||
@ -102,10 +109,12 @@
|
||||
{% endfor %}
|
||||
|
||||
</td>
|
||||
{%if light%}
|
||||
{%else%}
|
||||
<td id='plus'><a href="{{url_for('add_to_stack', id=book.id)}}">
|
||||
==>
|
||||
</a></td>
|
||||
|
||||
{%endif%}
|
||||
{% endfor %}
|
||||
</table>
|
||||
<p>
|
||||
|
@ -9,12 +9,12 @@
|
||||
{{ render_field(form.search) }} </div>
|
||||
<button type="submit" class="button">browse</button>
|
||||
<p><br>
|
||||
{{ form.grid(style="font-size:20px")}}{{ form.listview(style="font-size:20px")}}</p>
|
||||
{{ form.grid(style="font-size:20px")}}{{ form.listview(style="font-size:20px")}}</p>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<h3 style="line-height:0px;"">Results: "{{ query }}" included in {{ count }} out of {{ whole }} items </h3>
|
||||
<h3 style="line-height:0px;">Results: "{{ query }}" included in {{ count }} out of {{ whole }} items </h3>
|
||||
<div style="height: 20px; background-color: yellow; line-height:4px;">
|
||||
<div style="background-color: black; width: {{ percentage }}%; height: 100%;"></div>
|
||||
</div>
|
||||
@ -37,7 +37,7 @@
|
||||
|
||||
<div class="gridbox">
|
||||
<a href="/books/{{ book.id }}">
|
||||
<img class="no_cover" id="{{ book.title }}" src="/uploads/cover/{{ book.cover }}" width="100%" onerror="if (this.src != '//uploads/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';"></a>
|
||||
<img class="no_cover" id="{{ book.title }}" src="/cover/{{ book.cover }}" width="100%" onerror="if (this.src != '/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';"></a>
|
||||
<p>
|
||||
<tbody>
|
||||
<th>
|
||||
@ -58,10 +58,10 @@
|
||||
<div class="grid">
|
||||
|
||||
{% for book in books_all|sort(attribute='title', reverse = False) %}
|
||||
|
||||
|
||||
<div class="gridbox">
|
||||
<a href="books/{{ book.id }}">
|
||||
<img class="no_cover" id="{{ book.title }}" src="/uploads/cover/{{ book.cover }}" width="100%" onerror="if (this.src != '//uploads/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';"></a>
|
||||
<img class="no_cover" id="{{ book.title }}" src="/cover/{{ book.cover }}" width="100%" onerror="if (this.src != '/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';"></a>
|
||||
<p>
|
||||
<tbody>
|
||||
<th>
|
||||
|
@ -74,7 +74,7 @@
|
||||
<div class = "drag" id = "{{ book.id }}" style="position: absolute;width:70px;height:auto; top:{{ book.scapeY }}px; left:{{ book.scapeX }}px;">
|
||||
|
||||
|
||||
<img class="no_cover" id="{{ book.title }}" src="../uploads/cover/{{ book.cover }}" style="width:100%;height:auto;" onerror="if (this.src != '../static/img/default_cover.png') this.src = '../static/img/default_cover.png';">
|
||||
<img class="no_cover" id="{{ book.title }}" src="../cover/{{ book.cover }}" style="width:100%;height:auto;" onerror="if (this.src != '../static/img/default_cover.gif') this.src = '../static/img/default_cover.gif';">
|
||||
<p class="booktitle" style="font-size:7px;"><a href="books/{{ book.id }}">{{ book.title }}</a></p>
|
||||
|
||||
{% set got = {} %}
|
||||
@ -104,7 +104,7 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
|
||||
<script src="{{ url_for("static", filename="js/jquery-3.3.1.min.js") }}"></script>
|
||||
<script src="{{ url_for("static", filename="js/app.js") }}"></script>
|
||||
<script>
|
||||
|
||||
@ -150,8 +150,8 @@
|
||||
}
|
||||
|
||||
</script>
|
||||
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
|
||||
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
|
||||
|
||||
<script src="{{ url_for("static", filename="js/jquery-ui-1.12.1.custom/jquery-ui.js") }}"></script>
|
||||
<script>
|
||||
$( function() {
|
||||
var currentZoom = $('#scape_container').css('zoom');
|
||||
|
@ -2,11 +2,12 @@
|
||||
|
||||
{% block main %}
|
||||
<div class="container">
|
||||
|
||||
<h1 class="header">{{ book.title }}</h1>
|
||||
<div style="float:right; padding-right: 140px;">
|
||||
<img class="no_cover" id="{{ book.title }}" src="../uploads/cover/{{ book.cover }}" width="280px" onerror="if (this.src != '../uploads/cover/{{ book.cover }}') this.src = '../static/img/default_cover.gif';"></div>
|
||||
<img class="no_cover" id="{{ book.title }}" src="../cover/{{ book.cover }}" width="280px" onerror="if (this.src != '../cover/{{ book.cover }}') this.src = '../static/img/default_cover.gif';"></div>
|
||||
|
||||
<table class="library_table" id="table" style="width:50%; padding-bottom: 80px;">
|
||||
<table class="library_table" id="table" style="width:50%; padding-bottom: 180px;">
|
||||
<thead>
|
||||
<tr id="header">
|
||||
<th style="width: 150px;"></th>
|
||||
@ -58,58 +59,57 @@
|
||||
<td>Who is uploading<br></td>
|
||||
<td>{{ book.who or '?' }} </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>How much time has been spent with this item?<br></td>
|
||||
<td>{{ book.time or '?' }} </td>
|
||||
</tr>
|
||||
<td>Instances:</td>
|
||||
<td>{% set got = {} %}
|
||||
{% set all = 1 %}
|
||||
{% for instance in book.instances %}
|
||||
|
||||
{% if instance.name in got %}
|
||||
{% set x=got.__setitem__(instance.name, got[instance.name]+1) %}
|
||||
{% else %}
|
||||
{% set x=got.__setitem__(instance.name, 1) %}
|
||||
{% endif %}
|
||||
{% set all = loop.index %}
|
||||
{% endfor %}
|
||||
|
||||
{% for instance, value in got.items() %}
|
||||
{% set result = value/(book.instances|length) %}
|
||||
{{ instance }}: {{ (result*100)|round|int }}%<br>
|
||||
{% endfor %}</td>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="../uploads/{{ book.file }}">download {{ book.fileformat }}</a>
|
||||
{%if light%}
|
||||
{%else%}
|
||||
<br>
|
||||
<br>
|
||||
<p>Instances:</p>
|
||||
{% set got = {} %}
|
||||
{% set all = 1 %}
|
||||
{% for instance in book.instances %}
|
||||
|
||||
{% if instance.name in got %}
|
||||
{% set x=got.__setitem__(instance.name, got[instance.name]+1) %}
|
||||
{% else %}
|
||||
{% set x=got.__setitem__(instance.name, 1) %}
|
||||
{% endif %}
|
||||
{% set all = loop.index %}
|
||||
{% endfor %}
|
||||
|
||||
{% for instance, value in got.items() %}
|
||||
{% set result = value/(book.instances|length) %}
|
||||
{{ instance }}: {{ (result*100)|round|int }}%<br>
|
||||
{% endfor %}
|
||||
<a href="{{url_for('add_to_stack', id=book.id)}}">Add book to Stack ===></a> <br><br>
|
||||
<br>
|
||||
|
||||
{% if book.file %}
|
||||
<button id="myBtn" style= "width: 180px; font-size: 10pt;"><a> Download this {{ book.fileformat }}</a></button>
|
||||
<div id="myModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<span class="close">×</span>
|
||||
<h3>A message from the uploading librarian:</h3>
|
||||
<span style="font-style: italic;">"{{book.message or '...'}}" </span><br>
|
||||
<h4><a href="../uploads/{{ book.file }}"> >>>> Link to file <<<<</h4></a>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
{% endif %}
|
||||
|
||||
{% if book.file %}
|
||||
<button id="myBtn" style= "width: 180px; font-size: 10pt;"><a> Download this {{ book.fileformat }}</a></button>
|
||||
<div id="myModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<span class="close">×</span>
|
||||
<h3>A message from the uploading librarian:</h3>
|
||||
<span style="font-style: italic;">"{{book.message or 'Happy reading.'}}" </span><br>
|
||||
<h4><a href="../uploads/{{ book.file }}"> >>>> Link to file <<<<</h4></a></div>
|
||||
</div>
|
||||
{% else %}
|
||||
{% endif %}
|
||||
|
||||
<button style= "font-size: 10pt;"> <a href="{{ url_for('edit_book_by_id', id=book.id )}}">edit</a></button>
|
||||
<button style= "font-size: 10pt;"> <a href="{{ url_for('remove_book_by_id', id=book.id)}}">delete</a></button>
|
||||
<a href="{{ url_for('edit_book_by_id', id=book.id )}}"><button style= "font-size: 10pt;"> edit</button></a>
|
||||
<a href="{{ url_for('remove_book_by_id', id=book.id)}}"><button style= "font-size: 10pt;"> delete</button></a>
|
||||
<br><br>
|
||||
|
||||
<br><br>
|
||||
{%endif%}
|
||||
<hr>
|
||||
{% if previousbook %}
|
||||
<a href="{{ url_for('show_book_by_id', id=previousbook.id )}}" style="font-size: 9pt;"> < see the previous book added to XPPL: <i>{{ previousbook.title |truncate(40,True,'...') }} </i></a> {% endif %}
|
||||
<a href="{{ url_for('show_book_by_id', id=previousbook.id )}}" style="font-size: 10pt;"> < see the previous book added to XPPL: <i>{{ previousbook.title |truncate(40,True,'...') }} </i></a> {% endif %}
|
||||
{% if nextbook %}
|
||||
<a href="{{ url_for('show_book_by_id', id=nextbook.id )}}" style="float:right; font-size: 9pt;"> see the next book added to XPPL: <i>{{ nextbook.title|truncate(40,True,'...')}} </i>> </a>{% endif %}
|
||||
<a href="{{ url_for('show_book_by_id', id=nextbook.id )}}" style="float:right; font-size: 10pt;"> see the next book added to XPPL: <i>{{ nextbook.title|truncate(40,True,'...')}} </i>> </a>{% endif %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
@ -3,7 +3,7 @@
|
||||
{% block main %}
|
||||
<div class="container">
|
||||
{% from "_formhelpers.html" import render_field %}
|
||||
|
||||
|
||||
<form method="POST">
|
||||
<div>{{ form.select(style="width: 100px; margin: 10px; float: left; font-size: 20px") }}</div>
|
||||
<div class="search">
|
||||
@ -36,7 +36,10 @@
|
||||
<th width="100px;">Year</th>
|
||||
<th width="100px;">Category</th>
|
||||
<th width="100px;">Stack</th>
|
||||
{%if light%}
|
||||
{%else%}
|
||||
<th width="100px;">Add to a stack</th>
|
||||
{%endif%}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -44,7 +47,7 @@
|
||||
<tr>
|
||||
<td style= "padding: 5px;">
|
||||
|
||||
<img class="no_cover" id="{{ book.title }}" src="/uploads/cover/{{ book.cover }}" width="70" onerror="if (this.src != '//uploads/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';">
|
||||
<img class="no_cover" id="{{ book.title }}" src="/cover/{{ book.cover }}" width="70" onerror="if (this.src != '/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';">
|
||||
<!-- <object class="no_cover" data="../static/img/default_cover.png" type="image/png" width="65">
|
||||
<p hidden="True"></p>
|
||||
|
||||
@ -59,19 +62,29 @@
|
||||
{% endfor %}</td>
|
||||
<td id='fileformat'>{{ book.year_published or '––'}}</td>
|
||||
<td>{{ book.category}}</td>
|
||||
<td>
|
||||
<td id='ascii'>
|
||||
{% for stack in book.stacks %}
|
||||
|
||||
<li><a href="{{url_for('show_stack_by_id', id=stack.id)}}"> {{ stack.stack_name }} </a></li>
|
||||
{% else %}
|
||||
<li style='font-size:10px;'>
|
||||
|
||||
XXXXXXXXXX <br>
|
||||
XXXXXXXXXX <br>
|
||||
XXXXXXXXXX <br>
|
||||
|
||||
|
||||
{% endfor %}
|
||||
|
||||
|
||||
</td>
|
||||
{%if light%}
|
||||
{%else%}
|
||||
|
||||
<td id='plus'><a href="{{url_for('add_to_stack', id=book.id)}}">
|
||||
|
||||
===>
|
||||
</a></td>
|
||||
</a></td>{%endif%}
|
||||
</tr>
|
||||
|
||||
{% endfor %}
|
||||
|
@ -9,7 +9,7 @@
|
||||
{{ render_field(form.search) }} </div>
|
||||
<button type="submit" class="button">browse</button>
|
||||
<p><br>
|
||||
{{ form.grid(style="font-size:20px")}}{{ form.listview(style="font-size:20px")}}</p>
|
||||
{{ form.grid(style="font-size:20px")}}{{ form.listview(style="font-size:20px")}}</p>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
|
||||
<div class="gridbox">
|
||||
<a href="books/{{ book.id }}">
|
||||
<img class="no_cover" id="{{ book.title }}" src="/uploads/cover/{{ book.cover }}" width="100%" onerror="if (this.src != '//uploads/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';"></a>
|
||||
<img class="no_cover" id="{{ book.title }}" src="/cover/{{ book.cover }}" width="100%" onerror="if (this.src != '/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';"></a>
|
||||
<p>
|
||||
<tbody>
|
||||
<th>
|
||||
|
@ -6,33 +6,46 @@
|
||||
<h1 class="header">{{ stack.stack_name }}</h1>
|
||||
|
||||
<p>{{ stack.stack_description }} </p>
|
||||
<p id='creator'>Created by:
|
||||
<p id='creator'>Created by:
|
||||
{% if stack.stack_author == None %} anon</p>
|
||||
{% else %}
|
||||
|
||||
{{ stack.stack_author }}
|
||||
{% endif %}
|
||||
<h2>Books in this stack:</h2>
|
||||
|
||||
<p>
|
||||
|
||||
{% for book in stack.books %}
|
||||
{% if loop.length >= 5 %}
|
||||
{% if loop.index == 6 %}
|
||||
<p style='color:red;'>Your stack is getting a little too big. Are these next books really relevant?</p>
|
||||
<br>
|
||||
<br>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<li> <a href="{{url_for('show_book_by_id', id=book.id)}}">{{book.title}}</a> </li>
|
||||
<img class="no_cover" id="{{ book.title }}" src="../uploads/cover/{{ book.cover }}" width="150" onerror="if (this.src != '../uploads/cover/{{ book.cover }}') this.src = '../static/img/default_cover.gif';">
|
||||
<img class="no_cover" id="{{ book.title }}" src="../cover/{{ book.cover }}" width="150" onerror="if (this.src != '../cover/{{ book.cover }}') this.src = '../static/img/default_cover.gif';">
|
||||
<div class='widget'>
|
||||
{%if light%}
|
||||
{%else%}
|
||||
<iframe src="../uploads/{{ book.file }}" width="50%" ></iframe>
|
||||
{%endif%}
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
{% endfor %}</p>
|
||||
|
||||
|
||||
<br>
|
||||
<br>
|
||||
<p>
|
||||
<a href="{{ url_for('remove_stack_by_id', id=stack.id )}}">Remove stack</a> </p>
|
||||
<p>
|
||||
<a href="{{ url_for('edit_stack_by_id', id=stack.id )}}">Edit title and/or description</a> </p>
|
||||
|
||||
|
||||
|
||||
{%if light%}
|
||||
{%else%}
|
||||
<p><a href="{{url_for('show_books')}}">Add some more books</a></p>
|
||||
<p><a href="{{ url_for('edit_stack_by_id', id=stack.id )}}">Edit title and/or description</a> </p>
|
||||
<p><a href="{{ url_for('remove_stack_by_id', id=stack.id )}}">Remove stack</a> </p>
|
||||
{%endif%}
|
||||
<p><a href="{{url_for('show_stacks')}}">Go back to the other stacks</p>
|
||||
|
||||
</div>
|
||||
|
@ -17,17 +17,12 @@
|
||||
{{ stack.stack_author }}
|
||||
{% endif %}
|
||||
|
||||
|
||||
<p style='font-weight:bold;'>Books in this stack: {% for book in stack.books %}
|
||||
|
||||
<p style='font-weight:bold;'>Books in this stack: {% for book in stack.books %} </p>
|
||||
<li style="font-size: 18px;"> <a href="{{url_for('show_book_by_id', id=book.id)}}">{{book.title}}</a> </li>
|
||||
|
||||
<p style="font-size: 10px;"><a href='{{url_for('add_to_stack', id=book.id)}}'>
|
||||
|
||||
Add to another stack
|
||||
</a></p>
|
||||
{% endfor %}</p>
|
||||
<p style="font-size: 10px;"><a href='{{url_for('add_to_stack', id=book.id)}}'> Add to another stack </a></p>
|
||||
|
||||
{% endfor %}
|
||||
|
||||
|
||||
</div>
|
||||
|
156
app/views.py
156
app/views.py
@ -5,9 +5,10 @@ Werkzeug Documentation: http://werkzeug.pocoo.org/documentation/
|
||||
This file creates your application.
|
||||
"""
|
||||
|
||||
from app import app, db, socketio, DOMAIN
|
||||
from app import app, db, socketio, DOMAIN, light
|
||||
from flask import Flask, Response, session, render_template, request, redirect, url_for, flash, send_from_directory, jsonify, abort
|
||||
import json
|
||||
from functools import wraps
|
||||
from sqlalchemy.sql.expression import func, select
|
||||
from sqlalchemy.sql import except_
|
||||
from app.forms import UploadForm, EditForm, SearchForm, ChatForm, StackForm, AddtoStackForm, EditStackForm
|
||||
@ -48,26 +49,34 @@ def allowed_file(filename):
|
||||
# Routing for your application.
|
||||
###
|
||||
|
||||
|
||||
|
||||
def check_light(func):
|
||||
@wraps(func)
|
||||
def decorated_function(*args, **kwargs):
|
||||
if not light:
|
||||
return func(*args, **kwargs)
|
||||
else:
|
||||
flash("Your account has expired. Update your billing info.")
|
||||
return redirect(url_for('home'))
|
||||
|
||||
return decorated_function
|
||||
|
||||
|
||||
@app.route('/', methods= ['POST','GET'])
|
||||
def home():
|
||||
print("/////////////")
|
||||
print(light)
|
||||
chat_form = ChatForm()
|
||||
chat_messages = db.session.query(Chat).all()
|
||||
username = 'librarian'
|
||||
|
||||
# if request.method == 'POST':
|
||||
# if chat_form.validate_on_submit():
|
||||
# message = chat_form.message.data
|
||||
# msg = Chat(message)
|
||||
# db.session.add(msg)
|
||||
# db.session.commit()
|
||||
#client = request.remote_addr
|
||||
server = request.host
|
||||
if request.environ.get('HTTP_X_FORWARDED_FOR') is None:
|
||||
client =request.environ['REMOTE_ADDR']
|
||||
else:
|
||||
client = request.environ['HTTP_X_FORWARDED_FOR']
|
||||
|
||||
return render_template('home.html',domain=DOMAIN,chat=chat_messages, channel = 1, username=username, client=client, server=server)
|
||||
return render_template('home.html',domain=DOMAIN,chat=chat_messages, channel = 1, username=username, client=client, server=server, light=light)
|
||||
|
||||
@app.route('/hello/<name>')
|
||||
def hello(name):
|
||||
@ -76,9 +85,10 @@ def hello(name):
|
||||
@app.route('/about/')
|
||||
def about():
|
||||
"""Render the website's about page."""
|
||||
return render_template('about.html', name="Mary Jane")
|
||||
return render_template('about.html', light=light)
|
||||
|
||||
@app.route('/uploads/<filename>')
|
||||
@check_light
|
||||
def uploaded_file(filename):
|
||||
book = Book.query.filter_by(file=filename).first()
|
||||
i = Instance(request.host, "download")
|
||||
@ -90,7 +100,7 @@ def uploaded_file(filename):
|
||||
return send_from_directory(app.config['UPLOAD_FOLDER'],
|
||||
filename)
|
||||
|
||||
@app.route('/uploads/cover/<filename>')
|
||||
@app.route('/cover/<filename>')
|
||||
def uploaded_file_cover(filename):
|
||||
return send_from_directory(app.config['UPLOAD_FOLDER_COVER'],
|
||||
filename)
|
||||
@ -131,7 +141,7 @@ def scape():
|
||||
@app.route('/books_grid')
|
||||
def show_books_grid():
|
||||
books = db.session.query(Book).all() # or you could have used User.query.all()
|
||||
return render_template('show_books_grid.html', books=books)
|
||||
return render_template('show_books_grid.html', books=books, light=light)
|
||||
|
||||
@app.route('/books/<int:id>')
|
||||
def show_book_by_id(id):
|
||||
@ -155,12 +165,13 @@ def show_book_by_id(id):
|
||||
db.session.add(user_info)
|
||||
db.session.commit()
|
||||
if not book:
|
||||
return render_template('red_link.html', id=id)
|
||||
return render_template('red_link.html', id=id, light=light)
|
||||
else:
|
||||
return render_template('show_book_detail.html', book=book, previousbook = previousbook, nextbook = nextbook, all_instances=all_instances)
|
||||
return render_template('show_book_detail.html', book=book, previousbook = previousbook, nextbook = nextbook, all_instances=all_instances, light=light)
|
||||
|
||||
|
||||
@app.route('/books/<int:id>/delete', methods=['POST', 'GET'])
|
||||
@check_light
|
||||
def remove_book_by_id(id):
|
||||
book_to_edit = Book.query.filter_by(id=id).first()
|
||||
title = book_to_edit.title
|
||||
@ -171,9 +182,10 @@ def remove_book_by_id(id):
|
||||
return redirect(url_for('show_books'))
|
||||
|
||||
@app.route('/books/<int:id>/edit', methods=['POST', 'GET'])
|
||||
@check_light
|
||||
def edit_book_by_id(id):
|
||||
book_to_edit = Book.query.filter_by(id=id).first()
|
||||
user_form = EditForm(title = book_to_edit.title, author =book_to_edit.authors, category = book_to_edit.category, year_published= book_to_edit.year_published, message= book_to_edit.message)
|
||||
user_form = EditForm(title = book_to_edit.title, author =book_to_edit.authors, category = book_to_edit.category, year_published= book_to_edit.year_published, message= book_to_edit.message, sameness=book_to_edit.sameness, gender=book_to_edit.gender, diversity=book_to_edit.diversity, who=book_to_edit.who)
|
||||
|
||||
if request.method == 'POST':
|
||||
if user_form.validate_on_submit():
|
||||
@ -183,6 +195,11 @@ def edit_book_by_id(id):
|
||||
category = user_form.category.data
|
||||
year_published = user_form.year_published.data
|
||||
message = user_form.message.data
|
||||
sameness = user_form.sameness.data
|
||||
gender = user_form.gender.data
|
||||
diversity = user_form.diversity.data
|
||||
who = user_form.who.data
|
||||
|
||||
if year_published=="":
|
||||
year_published = None
|
||||
book = Book.query.filter_by(id=id).first()
|
||||
@ -190,6 +207,10 @@ def edit_book_by_id(id):
|
||||
book.category = category
|
||||
book.year_published = year_published
|
||||
book.message = message
|
||||
book.sameness = sameness
|
||||
book.gender = gender
|
||||
book.diversity = diversity
|
||||
book.who = who
|
||||
|
||||
#authors update
|
||||
book.authors.clear()
|
||||
@ -230,10 +251,11 @@ def edit_book_by_id(id):
|
||||
flash("%s updated" % (title))
|
||||
return redirect(url_for('show_book_by_id', id=id))
|
||||
|
||||
return render_template('edit_book_detail.html', book=book_to_edit, form=user_form)
|
||||
return render_template('edit_book_detail.html', book=book_to_edit, form=user_form, light=light)
|
||||
|
||||
|
||||
@app.route('/add-book', methods=['POST', 'GET'])
|
||||
@check_light
|
||||
def add_book():
|
||||
upload_form = UploadForm()
|
||||
allbooks = db.session.query(Book).all()
|
||||
@ -259,7 +281,6 @@ def add_book():
|
||||
sameness = upload_form.sameness.data
|
||||
gender = upload_form.gender.data
|
||||
diversity = upload_form.diversity.data
|
||||
time = upload_form.time.data
|
||||
who = upload_form.who.data
|
||||
|
||||
if year_published=="":
|
||||
@ -309,9 +330,8 @@ def add_book():
|
||||
html_string = render_template('potential_pdf.html', pbooks = pbooks)
|
||||
html = HTML(string=html_string)
|
||||
html.write_pdf(target='app/uploads/potential.pdf');
|
||||
print ('potential_pdf')
|
||||
|
||||
book = Book(title, filename, cover, file_extension, category, year_published, message, sameness, diversity, gender, who, time)
|
||||
book = Book(title, filename, cover, file_extension, category, year_published, message, sameness, diversity, gender, who)
|
||||
db.session.add(book)
|
||||
for author in authors:
|
||||
author_name = author.get("author_name")
|
||||
@ -332,7 +352,7 @@ def add_book():
|
||||
return redirect(url_for('show_books'))
|
||||
|
||||
flash_errors(upload_form)
|
||||
return render_template('add_book.html', form=upload_form, books_all=books_all, authors_all=authors_all, categories=categories, stacks_all=stacks_all, books_potential=books_potential, earliest=earliest, latest=latest)
|
||||
return render_template('add_book.html', form=upload_form, books_all=books_all, authors_all=authors_all, categories=categories, stacks_all=stacks_all, books_potential=books_potential, earliest=earliest, latest=latest, light=light)
|
||||
|
||||
|
||||
# Flash errors from the form if validation fails
|
||||
@ -352,10 +372,11 @@ def show_author_by_id(id):
|
||||
if not author:
|
||||
abort (404)
|
||||
else:
|
||||
return render_template('show_author_detail.html', author=author)
|
||||
return render_template('show_author_detail.html', author=author, light=light)
|
||||
|
||||
|
||||
@app.route('/authors/<int:id>/edit', methods=['POST', 'GET'])
|
||||
@check_light
|
||||
def edit_author_by_id(id):
|
||||
return "Ask the programmer."
|
||||
|
||||
@ -364,9 +385,10 @@ def edit_author_by_id(id):
|
||||
@app.route('/stacks')
|
||||
def show_stacks():
|
||||
stacks = db.session.query(Stack).all()
|
||||
return render_template('show_stacks.html', stacks=stacks)
|
||||
return render_template('show_stacks.html', stacks=stacks, light=light)
|
||||
|
||||
@app.route('/stacks/add_stack', methods=['POST', 'GET'])
|
||||
@check_light
|
||||
def add_stack():
|
||||
form = StackForm()
|
||||
stacks = db.session.query(Stack).all()
|
||||
@ -382,7 +404,7 @@ def add_stack():
|
||||
stacks = db.session.query(Stack).all()
|
||||
return redirect(url_for('show_stacks'))
|
||||
flash("%s stack created" % (stack_name))
|
||||
return render_template('add_stack.html', stacks=stacks, form=form)
|
||||
return render_template('add_stack.html', stacks=stacks, form=form, light=light)
|
||||
|
||||
@app.route('/stacks/tab/<int:id>', methods=['POST', 'GET'])
|
||||
def show_stack_in_tab(id):
|
||||
@ -394,20 +416,22 @@ def show_stack_by_id(id, is_tab=False):
|
||||
|
||||
stack = Stack.query.get(id)
|
||||
if not stack:
|
||||
abort (404)
|
||||
return render_template('add_stack.html', stacks=stacks, form=form, light=light)
|
||||
else:
|
||||
if is_tab == False:
|
||||
return render_template('show_stack_detail.html', stack=stack)
|
||||
return render_template('show_stack_detail.html', stack=stack, light=light)
|
||||
else:
|
||||
return render_template('show_stack_detail_tab.html', stack=stack)
|
||||
return render_template('show_stack_detail_tab.html', stack=stack, light=light)
|
||||
|
||||
@app.route('/stacks/<int:id>/delete', methods=['POST', 'GET'])
|
||||
@check_light
|
||||
def remove_stack_by_id(id):
|
||||
Stack.query.filter_by(id=id).delete()
|
||||
db.session.commit()
|
||||
return redirect(url_for('show_stacks'))
|
||||
|
||||
@app.route('/stacks/<int:id>/edit', methods=['POST', 'GET'])
|
||||
@check_light
|
||||
def edit_stack_by_id(id):
|
||||
stack = Stack.query.filter_by(id=id).first()
|
||||
form = EditStackForm(edit_stack_name = stack.stack_name, edit_stack_description = stack.stack_description)
|
||||
@ -420,9 +444,10 @@ def edit_stack_by_id(id):
|
||||
stack.stack_description = stack_description
|
||||
db.session.commit()
|
||||
return redirect(url_for('show_stack_by_id', id=id))
|
||||
return render_template('edit_stack_detail.html', stack=stack, form=form)
|
||||
return render_template('edit_stack_detail.html', stack=stack, form=form, light=light)
|
||||
|
||||
@app.route('/instances', methods=['POST', 'GET'])
|
||||
@check_light
|
||||
def show_instances():
|
||||
all_instances = db.session.query(Instance).all()
|
||||
instances = []
|
||||
@ -451,17 +476,18 @@ def show_instances():
|
||||
print(oldname)
|
||||
print(name)
|
||||
db.session.commit()
|
||||
return render_template('show_instances.html', instances=instances)
|
||||
return render_template('show_instances.html', instances=instances, light=light)
|
||||
|
||||
@app.route('/stacks/<int:stackid>/remove/<int:bookid>', methods=['POST', 'GET'])
|
||||
@check_light
|
||||
def remove_from_stack(bookid, stackid):
|
||||
book = Book.query.get(bookid)
|
||||
stack = Stack.query.get(stackid)
|
||||
if book not in stack.books:
|
||||
return render_template('show_book_detail.html', book=book)
|
||||
return render_template('show_book_detail.html', book=book, light=light)
|
||||
stack.books.remove(book)
|
||||
db.session.commit()
|
||||
return render_template('show_book_detail.html', book=book)
|
||||
return render_template('show_book_detail.html', book=book, light=light)
|
||||
|
||||
## search
|
||||
view = ['1']
|
||||
@ -476,12 +502,12 @@ def show_books():
|
||||
if search.grid.data:
|
||||
viewby = '2'
|
||||
view.append('2')
|
||||
return render_template ('show_books_grid.html', books=books, form=search)
|
||||
return render_template ('show_books_grid.html', books=books, form=search, light=light)
|
||||
|
||||
if search.listview.data:
|
||||
viewby = '1'
|
||||
view.append('1')
|
||||
return render_template ('show_books.html', books=books, form=search)
|
||||
return render_template ('show_books.html', books=books, form=search, light=light)
|
||||
|
||||
if request.method == 'POST':
|
||||
newmsg = 'searched for: ' + search.search.data
|
||||
@ -498,7 +524,7 @@ def show_books():
|
||||
db.session.rollback()
|
||||
return redirect((url_for('search_results', searchtype=search.select.data, query=search.search.data, viewby=viewby)))
|
||||
|
||||
return render_template('show_books.html', books=books, form=search)
|
||||
return render_template('show_books.html', books=books, form=search, light=light)
|
||||
|
||||
@app.route('/search/<searchtype>/<viewby>/<query>', methods=['POST', 'GET'])
|
||||
def search_results(searchtype, query, viewby):
|
||||
@ -519,19 +545,21 @@ def search_results(searchtype, query, viewby):
|
||||
if searchtype== 'Stack':
|
||||
results=db.session.query(Book).join(Book.stacks).filter(Stack.stack_name.contains(query)).order_by(Book.title)
|
||||
|
||||
if searchtype== 'Outliers':
|
||||
results=Book.query.filter(Book.sameness > 50).order_by(Book.title)
|
||||
|
||||
if searchtype== 'All':
|
||||
# results=Book.query.whoosh_search(query)
|
||||
results=Book.query.filter(Book.title.contains(query))
|
||||
results=results.union(Book.query.filter(Book.category.contains(query)))
|
||||
results=results.union(Book.query.filter(Book.year_published.contains(query)))
|
||||
results=results.union(db.session.query(Book).join(Book.authors).filter(Author.author_name.contains(query)))
|
||||
results=results.union(db.session.query(Book).join(Book.stacks).filter(Stack.stack_name.contains(query)))
|
||||
results=results.union(db.session.query(Book).join(Book.stacks).filter(Stack.stack_description.contains(query))).order_by(Book.title)
|
||||
results=results.union(db.session.query(Book).join(Book.stacks).filter(Stack.stack_name.contains(query))).order_by(Book.title)
|
||||
|
||||
if results.count() == 0:
|
||||
books = Book.query.filter(Book.file.like('potential.pdf'))
|
||||
upload_form = UploadForm(title= query, author='')
|
||||
return render_template('red_link.html', form=upload_form, title=query, books=books)
|
||||
return render_template('red_link.html', form=upload_form, title=query, books=books, light=light)
|
||||
|
||||
count = results.count()
|
||||
whole = Book.query.count()
|
||||
@ -541,11 +569,11 @@ def search_results(searchtype, query, viewby):
|
||||
|
||||
if search.listview.data:
|
||||
view.append('1')
|
||||
return render_template('results.html', books=results, form=search, query=query, books_all=books_all, searchtype=search.select.data, count = count, whole = whole, percentage = percentage)
|
||||
return render_template('results.html', books=results, form=search, query=query, books_all=books_all, searchtype=search.select.data, count = count, whole = whole, percentage = percentage, light=light)
|
||||
|
||||
if search.grid.data:
|
||||
view.append('2')
|
||||
return render_template('results_grid.html', books=results, form=search, query=query, books_all=books_all, searchtype=search.select.data, count = count, whole = whole, percentage = percentage)
|
||||
return render_template('results_grid.html', books=results, form=search, query=query, books_all=books_all, searchtype=search.select.data, count = count, whole = whole, percentage = percentage, light=light)
|
||||
|
||||
if request.method == 'POST':
|
||||
newmsg = 'searched for: ' + search.search.data
|
||||
@ -570,10 +598,10 @@ def search_results(searchtype, query, viewby):
|
||||
return redirect((url_for('search_results', searchtype=search.select.data, query=search.search.data, viewby=viewby)))
|
||||
|
||||
if viewby == '2':
|
||||
return render_template('results_grid.html', form=search, books=results, books_all=books_all, searchtype=search.select.data, query=query, count = count, whole = whole, percentage = percentage)
|
||||
return render_template('results_grid.html', form=search, books=results, books_all=books_all, searchtype=search.select.data, query=query, count = count, whole = whole, percentage = percentage, light=light)
|
||||
|
||||
else:
|
||||
return render_template('results.html', form=search, books=results, books_all=books_all, searchtype=search.select.data, query=query, count = count, whole = whole, percentage = percentage)
|
||||
return render_template('results.html', form=search, books=results, books_all=books_all, searchtype=search.select.data, query=query, count = count, whole = whole, percentage = percentage, light=light)
|
||||
|
||||
autocomplete_suggestions = []
|
||||
autocomplete.load()
|
||||
@ -599,22 +627,24 @@ def autocomplete_search():
|
||||
## STACKS!
|
||||
|
||||
@app.route('/add_to_stack/<int:id>', methods=['GET', 'POST'])
|
||||
@check_light
|
||||
def add_to_stack(id):
|
||||
stacks = db.session.query(Stack).all()
|
||||
add_form = AddtoStackForm(request.form)
|
||||
add_form.select_stack.choices = [(stack.id, stack.stack_name) for stack in stacks]
|
||||
if request.method == 'GET':
|
||||
book = Book.query.get(id)
|
||||
return render_template('add_to_stacks.html', id=id, stacks=stacks, book=book, add_form=add_form)
|
||||
return render_template('add_to_stacks.html', id=id, stacks=stacks, book=book, add_form=add_form, light=light)
|
||||
else:
|
||||
stack = Stack.query.get(int(add_form.select_stack.data))
|
||||
book = Book.query.get(id)
|
||||
stack.books.append(book)
|
||||
db.session.commit()
|
||||
return render_template('show_stack_detail.html', stack=stack)
|
||||
return render_template('show_stack_detail.html', stack=stack, light=light)
|
||||
|
||||
|
||||
@app.route('/export/csv', methods=['GET'])
|
||||
@check_light
|
||||
def export_csv():
|
||||
output = io.StringIO()
|
||||
#fieldnames = ['title', 'authors', 'file', 'fileformat', 'category', 'year_published', 'description' ]
|
||||
@ -650,6 +680,7 @@ def export_csv():
|
||||
|
||||
import codecs
|
||||
@app.route('/import/csv', methods= ['POST','GET'])
|
||||
@check_light
|
||||
def import_csv():
|
||||
if request.method == 'POST':
|
||||
if 'file' not in request.files:
|
||||
@ -664,19 +695,35 @@ def import_csv():
|
||||
print("allreadyexists")
|
||||
else:
|
||||
cover = ''
|
||||
if row['file']:
|
||||
if row['file'] == '':
|
||||
file = 'potential.pdf'
|
||||
file_extension = '.pdf'
|
||||
ptitle = row['title']
|
||||
pbook = Potential(ptitle)
|
||||
db.session.add(pbook)
|
||||
db.session.commit()
|
||||
pbooks = Potential.query.all()
|
||||
template = 'app/templates/potential_pdf.html'
|
||||
html_string = render_template('potential_pdf.html', pbooks = pbooks)
|
||||
html = HTML(string=html_string)
|
||||
html.write_pdf(target='app/uploads/potential.pdf')
|
||||
|
||||
else:
|
||||
fullpath = os.path.join(app.config['UPLOAD_FOLDER'], row['file'])
|
||||
name, file_extension = os.path.splitext(row['file'])
|
||||
print ('get_cover', fullpath, name)
|
||||
cover = get_cover(fullpath, name)
|
||||
file = str(id) + "_" + row['file']
|
||||
|
||||
if row['year_published']:
|
||||
year_published = int(row['year_published'])
|
||||
else:
|
||||
year_published = None;
|
||||
book = Book(row['title'], row['file'], cover, row['fileformat'], row['category'],year_published, None, None, None, None, None, None)
|
||||
book.scapeX = float(row['scapeX'])
|
||||
book.scapeY = float(row['scapeY'])
|
||||
book = Book(row['title'], file, cover, row['fileformat'], row['category'],year_published, None, None, None, None, None)
|
||||
if row['scapeX']:
|
||||
book.scapeX = float(row['scapeX'])
|
||||
if row['scapeY']:
|
||||
book.scapeY = float(row['scapeY'])
|
||||
|
||||
db.session.add(book)
|
||||
numberadded = numberadded+1
|
||||
@ -690,10 +737,11 @@ def import_csv():
|
||||
db.session.add(a)
|
||||
book.authors.append(a)
|
||||
db.session.commit()
|
||||
return render_template('import_csv.html', numberadded=numberadded)
|
||||
return render_template('import_csv.html', numberadded=numberadded, light=light)
|
||||
|
||||
|
||||
@app.route('/empty_catalogue487352698237465', methods= ['POST','GET'])
|
||||
@app.route('/emptycataloguexpubxpubfuck', methods= ['POST','GET'])
|
||||
@check_light
|
||||
def empty_catalogue():
|
||||
meta = db.metadata
|
||||
for table in reversed(meta.sorted_tables):
|
||||
@ -737,12 +785,6 @@ def get_chat():
|
||||
# The functions below should be applicable to all Flask apps.
|
||||
###
|
||||
|
||||
@app.route('/<file_name>.txt')
|
||||
def send_text_file(file_name):
|
||||
"""Send your static text file."""
|
||||
file_dot_text = file_name + '.txt'
|
||||
return app.send_static_file(file_dot_text)
|
||||
|
||||
|
||||
@app.after_request
|
||||
def add_header(response):
|
||||
@ -751,14 +793,14 @@ def add_header(response):
|
||||
and also to cache the rendered page for 10 minutes.
|
||||
"""
|
||||
response.headers['X-UA-Compatible'] = 'IE=Edge,chrome=1'
|
||||
response.headers['Cache-Control'] = 'public, max-age=600'
|
||||
response.headers['Cache-Control'] = 'no-cache'
|
||||
return response
|
||||
|
||||
|
||||
@app.errorhandler(404)
|
||||
def page_not_found(error):
|
||||
"""Custom 404 page."""
|
||||
return render_template('404.html'), 404
|
||||
return render_template('404.html', light=light), 404
|
||||
|
||||
|
||||
### SOCKET for the chat
|
||||
|
@ -20,7 +20,7 @@ with open(args.csv) as f:
|
||||
print ('get_cover', fullpath, name)
|
||||
cover = get_cover(fullpath, name)
|
||||
|
||||
book = Book(row['Title'], row['Filename'], cover, row['Format'], row['Category'], None, None, None, None, None, None, None)
|
||||
book = Book(row['Title'], row['Filename'], cover, row['Format'], row['Category'], None, None, None, None, None, None)
|
||||
|
||||
db.session.add(book)
|
||||
authors = row['Author'].split(',')
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
rm app/mydatabase.db
|
||||
#rm app/mydatabase.db
|
||||
mkdir -p app/uploads/cover
|
||||
chmod 777 app/uploads/
|
||||
chmod 777 app/uploads/cover
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user