Merged and fixed conflicts
This commit is contained in:
commit
f8b2c7ec07
4
.gitignore
vendored
4
.gitignore
vendored
@ -4,3 +4,7 @@ __pycache__/
|
|||||||
app/uploads/**
|
app/uploads/**
|
||||||
!app/uploads/cover
|
!app/uploads/cover
|
||||||
app/mydatabase.db
|
app/mydatabase.db
|
||||||
|
pyrqlite/
|
||||||
|
whoosh/
|
||||||
|
sqlalchemy-rqlite/
|
||||||
|
rqlite*
|
||||||
|
0
1_Benjamin_Walter_Understanding_Brecht1.txt
Normal file
0
1_Benjamin_Walter_Understanding_Brecht1.txt
Normal file
10
README.md
10
README.md
@ -36,3 +36,13 @@ brew install imagemagick@6
|
|||||||
Create a symlink to this newly installed dylib file as mentioned in other answer to get things working.
|
Create a symlink to this newly installed dylib file as mentioned in other answer to get things working.
|
||||||
ln -s /usr/local/Cellar/imagemagick@6/<your specific 6 version>/lib/libMagickWand-6.Q16.dylib /usr/local/lib/libMagickWand.dylib
|
ln -s /usr/local/Cellar/imagemagick@6/<your specific 6 version>/lib/libMagickWand-6.Q16.dylib /usr/local/lib/libMagickWand.dylib
|
||||||
|
|
||||||
|
## install pyrqlite
|
||||||
|
|
||||||
|
git clone https://github.com/rqlite/pyrqlite.git
|
||||||
|
pip install ./pyrqlite
|
||||||
|
|
||||||
|
## install sqlalchemy-rqlite
|
||||||
|
|
||||||
|
git clone https://github.com/rqlite/sqlalchemy-rqlite.git
|
||||||
|
cd sqlalchemy-rqlite
|
||||||
|
sudo python3 ./setup.py install
|
||||||
|
@ -8,7 +8,7 @@ import os
|
|||||||
import click
|
import click
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
from sqlalchemy.dialects import registry
|
from sqlalchemy.dialects import registry
|
||||||
import flask_whooshalchemyplus
|
# import flask_whooshalchemyplus not using whoosh anymore
|
||||||
|
|
||||||
registry.register("rqlite.pyrqlite", "sqlalchemy_rqlite.pyrqlite", "dialect")
|
registry.register("rqlite.pyrqlite", "sqlalchemy_rqlite.pyrqlite", "dialect")
|
||||||
|
|
||||||
@ -27,9 +27,6 @@ app.config['SQLALCHEMY_DATABASE_URI'] = 'rqlite+pyrqlite://localhost:4001/'
|
|||||||
app.config['DEBUG'] = True
|
app.config['DEBUG'] = True
|
||||||
app.config['PORT'] = 80
|
app.config['PORT'] = 80
|
||||||
|
|
||||||
# set the location for the whoosh index
|
|
||||||
app.config['WHOOSH_BASE'] = 'whoosh'
|
|
||||||
|
|
||||||
#app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'mydatabase.db')
|
#app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'mydatabase.db')
|
||||||
db = SQLAlchemy(app)
|
db = SQLAlchemy(app)
|
||||||
|
|
||||||
@ -38,5 +35,3 @@ socketio = SocketIO(app)
|
|||||||
|
|
||||||
app.config.from_object(__name__)
|
app.config.from_object(__name__)
|
||||||
from app import views
|
from app import views
|
||||||
|
|
||||||
flask_whooshalchemyplus.init_app(app) # initialize
|
|
||||||
|
30
app/forms.py
30
app/forms.py
@ -3,8 +3,10 @@ from wtforms import StringField, FileField, validators
|
|||||||
from wtforms.validators import InputRequired, DataRequired
|
from wtforms.validators import InputRequired, DataRequired
|
||||||
from wtforms import FieldList
|
from wtforms import FieldList
|
||||||
from wtforms import Form as NoCsrfForm
|
from wtforms import Form as NoCsrfForm
|
||||||
from wtforms.fields import StringField, FormField, SubmitField, SelectField
|
from wtforms.fields import StringField, FormField, SubmitField, SelectField, RadioField
|
||||||
from app.models import Book, BookSchema, Author, Stack, StackSchema
|
from app.models import Book, BookSchema, Author, Stack, StackSchema
|
||||||
|
from wtforms.fields.html5 import DecimalRangeField
|
||||||
|
|
||||||
|
|
||||||
# - - - Forms - - -
|
# - - - Forms - - -
|
||||||
class AuthorForm(NoCsrfForm):
|
class AuthorForm(NoCsrfForm):
|
||||||
@ -19,12 +21,28 @@ class UploadForm(FlaskForm):
|
|||||||
file = FileField()
|
file = FileField()
|
||||||
upload = SubmitField(label='Upload')
|
upload = SubmitField(label='Upload')
|
||||||
wish = SubmitField(label='''I don't have the file, but wish I did.''')
|
wish = SubmitField(label='''I don't have the file, but wish I did.''')
|
||||||
|
message = StringField('message', default=None)
|
||||||
|
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'),
|
||||||
|
('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 EditForm(FlaskForm):
|
class EditForm(FlaskForm):
|
||||||
title = StringField('title', validators=[InputRequired()])
|
title = StringField('title', validators=[InputRequired()])
|
||||||
author = FieldList(FormField(AuthorForm, default=lambda: Author()), min_entries=1)
|
author = FieldList(FormField(AuthorForm, default=lambda: Author()), min_entries=1)
|
||||||
category = StringField('category', validators=[InputRequired()])
|
category = StringField('category', validators=[InputRequired()])
|
||||||
year_published = StringField('year published', [validators.Length(max=4)],default=None)
|
year_published = StringField('year published', [validators.Length(max=4)],default=None)
|
||||||
|
file = FileField()
|
||||||
|
message = StringField('message')
|
||||||
|
|
||||||
class ChatForm(FlaskForm):
|
class ChatForm(FlaskForm):
|
||||||
message = StringField('message', validators=[InputRequired()])
|
message = StringField('message', validators=[InputRequired()])
|
||||||
@ -33,6 +51,7 @@ class ChatForm(FlaskForm):
|
|||||||
class StackForm(FlaskForm):
|
class StackForm(FlaskForm):
|
||||||
stack_name = StringField('Stack', validators=[InputRequired()])
|
stack_name = StringField('Stack', validators=[InputRequired()])
|
||||||
stack_description = StringField('Description', validators=[InputRequired()])
|
stack_description = StringField('Description', validators=[InputRequired()])
|
||||||
|
stack_author = StringField('Who made this', validators=[InputRequired()])
|
||||||
create = SubmitField(label='Create')
|
create = SubmitField(label='Create')
|
||||||
|
|
||||||
class AddtoStackForm(FlaskForm):
|
class AddtoStackForm(FlaskForm):
|
||||||
@ -45,6 +64,11 @@ class EditStackForm(FlaskForm):
|
|||||||
class SearchForm(FlaskForm):
|
class SearchForm(FlaskForm):
|
||||||
choices = [('All', 'All'),
|
choices = [('All', 'All'),
|
||||||
('Title', 'Title'),
|
('Title', 'Title'),
|
||||||
('Category', 'Category')]
|
('Author', 'Author'),
|
||||||
select = SelectField('', choices=choices)
|
('Category', 'Category'),
|
||||||
|
('Stack', 'Stack')]
|
||||||
|
select = SelectField('', choices=choices, default='All')
|
||||||
search = StringField('', validators=[InputRequired()])
|
search = StringField('', validators=[InputRequired()])
|
||||||
|
grid = SubmitField('Grid')
|
||||||
|
listview = SubmitField('List')
|
||||||
|
randomize = SubmitField('Order differently')
|
||||||
|
@ -22,7 +22,6 @@ instances = db.Table('books_instances',
|
|||||||
|
|
||||||
class Book(db.Model):
|
class Book(db.Model):
|
||||||
__tablename__ = 'books'
|
__tablename__ = 'books'
|
||||||
__searchable__ = ['title', 'category', 'fileformat'] # these fields will be indexed by whoosh
|
|
||||||
|
|
||||||
id = db.Column(db.Integer, primary_key = True)
|
id = db.Column(db.Integer, primary_key = True)
|
||||||
title = db.Column(db.String(255))
|
title = db.Column(db.String(255))
|
||||||
@ -42,8 +41,15 @@ class Book(db.Model):
|
|||||||
backref=db.backref('books', lazy=True))
|
backref=db.backref('books', lazy=True))
|
||||||
scapeX = db.Column(db.Numeric(10,2))
|
scapeX = db.Column(db.Numeric(10,2))
|
||||||
scapeY = db.Column(db.Numeric(10,2))
|
scapeY = db.Column(db.Numeric(10,2))
|
||||||
|
message = db.Column(db.String(1000))
|
||||||
|
sameness = db.Column(db.Numeric())
|
||||||
|
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):
|
|
||||||
|
def __init__(self, title, file, cover, fileformat, category, year_published, message, sameness, diversity, gender, who, time):
|
||||||
self.title = title
|
self.title = title
|
||||||
self.file = file
|
self.file = file
|
||||||
self.cover = cover
|
self.cover = cover
|
||||||
@ -53,6 +59,12 @@ class Book(db.Model):
|
|||||||
self.download = None
|
self.download = None
|
||||||
self.scapeX = 0
|
self.scapeX = 0
|
||||||
self.scapeY = 0
|
self.scapeY = 0
|
||||||
|
self.message = message
|
||||||
|
self.sameness = sameness
|
||||||
|
self.diversity = diversity
|
||||||
|
self.gender = gender
|
||||||
|
self.who = who
|
||||||
|
self.time = time
|
||||||
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@ -107,20 +119,34 @@ class Chat(db.Model):
|
|||||||
self.message = message
|
self.message = message
|
||||||
self.time = datetime.datetime.utcnow()
|
self.time = datetime.datetime.utcnow()
|
||||||
|
|
||||||
|
|
||||||
class Stack(db.Model):
|
class Stack(db.Model):
|
||||||
__tablename__ = 'stacks'
|
__tablename__ = 'stacks'
|
||||||
id = db.Column(db.Integer, primary_key = True)
|
id = db.Column(db.Integer, primary_key = True)
|
||||||
stack_name = db.Column(db.String(50))
|
stack_name = db.Column(db.String(50))
|
||||||
stack_description = db.Column(db.String(500))
|
stack_description = db.Column(db.String(1000))
|
||||||
|
stack_author = db.Column(db.String(255))
|
||||||
|
|
||||||
def __init__(self, stack_name, stack_description):
|
|
||||||
|
def __init__(self, stack_name, stack_description, stack_author):
|
||||||
self.stack_name = stack_name
|
self.stack_name = stack_name
|
||||||
self.stack_description = stack_description
|
self.stack_description = stack_description
|
||||||
|
self.stack_author = stack_author
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<Stack %r>' % self.stack_name
|
return '<Stack %r>' % self.stack_name
|
||||||
|
|
||||||
|
|
||||||
|
class Potential(db.Model):
|
||||||
|
__tablename__ = 'potential'
|
||||||
|
id = db.Column(db.Integer, primary_key = True)
|
||||||
|
ptitle = db.Column(db.String(50))
|
||||||
|
time = db.Column(DateTime, default=datetime.datetime.utcnow())
|
||||||
|
|
||||||
|
def __init__(self, ptitle):
|
||||||
|
self.ptitle = ptitle
|
||||||
|
self.time = datetime.datetime.utcnow()
|
||||||
|
|
||||||
|
|
||||||
class AuthorSchema(Schema):
|
class AuthorSchema(Schema):
|
||||||
id = fields.Int(dump_only=True)
|
id = fields.Int(dump_only=True)
|
||||||
author_name = fields.Str()
|
author_name = fields.Str()
|
||||||
@ -148,7 +174,6 @@ class BookSchema(Schema):
|
|||||||
stacks = fields.Nested(StackSchema, many=True)
|
stacks = fields.Nested(StackSchema, many=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def must_not_be_blank(data):
|
def must_not_be_blank(data):
|
||||||
if not data:
|
if not data:
|
||||||
raise ValidationError('You forgot to write stuff.')
|
raise ValidationError('You forgot to write stuff.')
|
||||||
|
@ -1,15 +1,4 @@
|
|||||||
@import url("../fonts/fonts_style.css");
|
@import url("../fonts/fonts_style.css");
|
||||||
/*
|
|
||||||
Font-names:
|
|
||||||
junicoderegular
|
|
||||||
junicoderegularcondensed
|
|
||||||
junicodeitalic
|
|
||||||
junicodeitaliccondensed
|
|
||||||
junicodebold
|
|
||||||
junicodeboldcondensed
|
|
||||||
junicodebolditalic
|
|
||||||
junicodebolditaliccondensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
*{
|
*{
|
||||||
font-family: "Archivo Narrow";
|
font-family: "Archivo Narrow";
|
||||||
@ -18,6 +7,18 @@ font-family: "Archivo Narrow";
|
|||||||
p{
|
p{
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
a{
|
||||||
|
|
||||||
|
text-decoration: none;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
a:hover{
|
||||||
|
|
||||||
|
text-decoration: underline;
|
||||||
|
color: #0000FF;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigation ul{
|
.navigation ul{
|
||||||
@ -35,7 +36,7 @@ float: left;
|
|||||||
display: block;
|
display: block;
|
||||||
color: black;
|
color: black;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 14px 16px;
|
padding: 14px 18px;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
@ -52,14 +53,23 @@ font-style: italic;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.container{
|
.container{
|
||||||
padding: 0px 8px;
|
padding: 0px 10px;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#fileformat{
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.lead{
|
.lead{
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.about{
|
||||||
|
font-size: 16px;
|
||||||
|
|
||||||
}
|
}
|
||||||
.library_table{
|
.library_table{
|
||||||
border-spacing:0; /* Removes the cell spacing via CSS */
|
border-spacing:0; /* Removes the cell spacing via CSS */
|
||||||
@ -73,6 +83,9 @@ border-spacing:0; /* Removes the cell spacing via CSS */
|
|||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
.library_table td{
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
th.headerSortUp{
|
th.headerSortUp{
|
||||||
background-color: #E8E8E8!important;
|
background-color: #E8E8E8!important;
|
||||||
@ -88,7 +101,8 @@ background-color: #E8E8E8!important;
|
|||||||
|
|
||||||
.library_table .title_col{
|
.library_table .title_col{
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
padding-left: 10px;
|
padding-left: 90px;
|
||||||
|
padding-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.library_table .author_col{
|
.library_table .author_col{
|
||||||
@ -121,7 +135,7 @@ cursor: pointer;
|
|||||||
.header input{
|
.header input{
|
||||||
height:40px;
|
height:40px;
|
||||||
width: 500px;
|
width: 500px;
|
||||||
font-size: 30px;
|
font-size: 24px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,10 +150,10 @@ margin: 0;
|
|||||||
float: left;
|
float: left;
|
||||||
width: 320px;
|
width: 320px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
font-size: 20px;
|
font-size: 18px;
|
||||||
font-weight: regular;
|
font-weight: regular;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
background:rgba(50, 50, 50, 0.2);
|
background:rgb(240, 240, 240);
|
||||||
border:0px;
|
border:0px;
|
||||||
box-shadow: inset 0 0 5px rgba(000,000,000, 0.2);
|
box-shadow: inset 0 0 5px rgba(000,000,000, 0.2);
|
||||||
}
|
}
|
||||||
@ -150,7 +164,7 @@ font-size: 18px;
|
|||||||
padding:6px 15px;
|
padding:6px 15px;
|
||||||
left:0px;
|
left:0px;
|
||||||
border:0px solid #dbdbdb;
|
border:0px solid #dbdbdb;
|
||||||
background-color: grey;
|
background-color: #686d72;
|
||||||
color:#fafafa;
|
color:#fafafa;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,14 +198,18 @@ font-size: 12px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ui-tabs-vertical { width: 100em; border-top: 0;}
|
.ui-tabs-vertical { width: 100em; border-top: 0;}
|
||||||
.ui-tabs-vertical .ui-tabs-nav { padding: .2em .2em .2em .2em; float: left; width: 15em; }
|
.ui-tabs-vertical a { text-decoration: none; color: black;}
|
||||||
.ui-tabs-vertical .ui-tabs-nav li { clear: left; width: 100%; border-bottom-width: 0 !important; border-right-width: 0 !important; margin: 0 -1px .2em 0; }
|
.ui-tabs-vertical .ui-tabs-nav { padding: .2em .2em .2em .2em; float: left; width: 15em; -webkit-appearance: none;}
|
||||||
|
.ui-tabs-vertical .ui-tabs-nav li { clear: left; width: 100%; border-bottom-width: 0 !important; border-right-width: 0 !important; margin: 0 -1px .2em 0; list-style-type: none; }
|
||||||
.ui-tabs-vertical .ui-tabs-nav li a { display:block; }
|
.ui-tabs-vertical .ui-tabs-nav li a { display:block; }
|
||||||
.ui-tabs-vertical .ui-tabs-nav li.ui-tabs-active { padding-bottom: 0; padding-right: .1em; border-right-width: 0; background-color: #A9A9A9 !important;}
|
.ui-tabs-vertical .ui-tabs-nav li.ui-tabs-active { padding-bottom: 0; padding-right: .1em; border-right-width: 0; background-color: yellow !important; list-style-type: none;}
|
||||||
.ui-tabs-vertical .ui-tabs-panel { padding: 1em; float: left; width: 50em; font-size: 12px;}
|
.ui-tabs-vertical .ui-tabs-panel { padding: 1em; float: left; width: 50em; font-size: 12px; list-style-type: none;}
|
||||||
#draggable { width: 100px; height: 100px; padding: 0.5em; float: left; margin: 10px 10px 10px 0; }
|
|
||||||
#droppable { width: 150px; height: 150px; padding: 0.5em; float: left; margin: 10px; }
|
|
||||||
|
|
||||||
|
#creator{
|
||||||
|
font-size: 12px;
|
||||||
|
color: grey;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#newstext{
|
#newstext{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -200,7 +218,7 @@ font-size: 12px;
|
|||||||
top:0;
|
top:0;
|
||||||
left:0;
|
left:0;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
font-size: 20px;
|
font-size: 18px;
|
||||||
background-color: yellow;
|
background-color: yellow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,7 +254,7 @@ div.marquee > div.marquee-text {
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: #551A8B;
|
background-color: #b4b9be;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
color: white;
|
color: white;
|
||||||
@ -273,7 +291,7 @@ z-index: 100000;
|
|||||||
margin:0px!important;
|
margin:0px!important;
|
||||||
padding:0px!important;
|
padding:0px!important;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
font-size: 20px;
|
font-size: 16px;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
float: left;
|
float: left;
|
||||||
@ -298,7 +316,7 @@ box-sizing: border-box;
|
|||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
.messages .msg{
|
.messages .msg{
|
||||||
font-size: 30px;
|
font-size: 24px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
margin-top: -15px;
|
margin-top: -15px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
@ -312,9 +330,11 @@ box-sizing: border-box;
|
|||||||
.widget {
|
.widget {
|
||||||
resize: both;
|
resize: both;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 300px;
|
width: 800px;
|
||||||
height: 300px;
|
height: 200px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
left: 400px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,3 +344,77 @@ box-sizing: border-box;
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
|
||||||
|
grid-gap: 2px;
|
||||||
|
align-items: top;
|
||||||
|
justify-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
.grid{
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||||
|
grid-gap: 2px;
|
||||||
|
align-items: top;
|
||||||
|
justify-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 400px) {
|
||||||
|
.grid{
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
align-items: center;
|
||||||
|
justify-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.gridbox {
|
||||||
|
display: inline-block;
|
||||||
|
padding-left: 5px;
|
||||||
|
align-items: center;
|
||||||
|
justify-items: center;
|
||||||
|
}
|
||||||
|
.gridbox:hover{
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The Modal (background) */
|
||||||
|
.modal {
|
||||||
|
display: none; /* Hidden by default */
|
||||||
|
position: fixed; /* Stay in place */
|
||||||
|
z-index: 1; /* Sit on top */
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%; /* Full width */
|
||||||
|
height: 100%; /* Full height */
|
||||||
|
overflow: auto; /* Enable scroll if needed */
|
||||||
|
background-color: rgb(0,0,0); /* Fallback color */
|
||||||
|
background-color: rgba(0,0,0,0.5); /* Black w/ opacity */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modal Content/Box */
|
||||||
|
.modal-content {
|
||||||
|
background-color: yellow;
|
||||||
|
margin: 15% auto; /* 15% from the top and centered */
|
||||||
|
padding: 15px;
|
||||||
|
border: 1px solid #888;
|
||||||
|
width: 40%; /* Could be more or less, depending on screen size */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The Close Button */
|
||||||
|
.close {
|
||||||
|
color: grey;
|
||||||
|
float: right;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close:hover,
|
||||||
|
.close:focus {
|
||||||
|
color: red;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
BIN
app/static/img/default_cover.gif
Normal file
BIN
app/static/img/default_cover.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
@ -209,4 +209,30 @@ $(document).ready(function()
|
|||||||
this.value = terms.join( " " );
|
this.value = terms.join( " " );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Get the modal
|
||||||
|
var modal = document.getElementById('myModal');
|
||||||
|
|
||||||
|
// Get the button that opens the modal
|
||||||
|
var btn = document.getElementById("myBtn");
|
||||||
|
|
||||||
|
// Get the <span> element that closes the modal
|
||||||
|
var span = document.getElementsByClassName("close")[0];
|
||||||
|
|
||||||
|
// When the user clicks on the button, open the modal
|
||||||
|
btn.onclick = function() {
|
||||||
|
modal.style.display = "block";
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the user clicks on <span> (x), close the modal
|
||||||
|
span.onclick = function() {
|
||||||
|
modal.style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the user clicks anywhere outside of the modal, close it
|
||||||
|
window.onclick = function(event) {
|
||||||
|
if (event.target == modal) {
|
||||||
|
modal.style.display = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,12 +2,29 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<h1 class="page-header">About</h1>
|
<h1 class="page-header">About</h1>
|
||||||
<p>
|
<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.
|
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 PZI shelves and our hard drives and memory sticks, so that they can be shared.
|
<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...
|
||||||
|
<br>
|
||||||
<br>
|
<br>
|
||||||
Its web interface hosts a curated catalogue of books and articles, and its distributed architecture provides instances for uploading and downloading.
|
Its web interface hosts a curated catalogue of books and articles, and its distributed architecture provides instances for uploading and downloading.
|
||||||
|
<br>
|
||||||
<br>
|
<br>
|
||||||
It starts at XPUB, but can go anywhere we want it to.</p>
|
It starts at XPUB, but can go anywhere we want it to.</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.
|
||||||
|
</p>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -1,7 +1,24 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<div class="container">
|
{% 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" style="float: left; width:50%;">
|
||||||
|
<div style="width: 98%; border-right: dashed; border-width: 1px;">
|
||||||
|
|
||||||
<h1 class="page-header">Add Book</h1>
|
<h1 class="page-header">Add Book</h1>
|
||||||
{% with messages = get_flashed_messages() %}
|
{% with messages = get_flashed_messages() %}
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
@ -16,11 +33,10 @@
|
|||||||
{% endwith %}
|
{% endwith %}
|
||||||
<form method="POST" action="{{ url_for('add_book') }}" enctype=multipart/form-data>
|
<form method="POST" action="{{ url_for('add_book') }}" enctype=multipart/form-data>
|
||||||
{{ form.csrf_token }}
|
{{ form.csrf_token }}
|
||||||
<div class="form-group">{{ form.title.label }} {{ form.title(size=20, class="form-control") }}</div>
|
<div class="form-group">Title:* <br> {{ form.title (size=50, class="form-control") }}</div>
|
||||||
<br>
|
<br>
|
||||||
<div data-toggle="fieldset" id="phone-fieldset">
|
<div data-toggle="fieldset" id="phone-fieldset">
|
||||||
{{ form.author.label }} <button type="button" data-toggle="fieldset-add-row"
|
Author(s):* <button type="button" data-toggle="fieldset-add-row data-target="#phone-fieldset">+</button>
|
||||||
data-target="#phone-fieldset">+</button>
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th></th>
|
<th></th>
|
||||||
@ -28,21 +44,91 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{% for author in form.author %}
|
{% for author in form.author %}
|
||||||
<tr data-toggle="fieldset-entry">
|
<tr data-toggle="fieldset-entry">
|
||||||
<td>{{ author.author_name }}</td>
|
<td>{{ author.author_name (size=50)}}</td>
|
||||||
<td><button type="button" data-toggle="fieldset-remove-row" id="phone-{{loop.index0}}-remove">-</button></td>
|
<td><button type="button" data-toggle="fieldset-remove-row" id="phone-{{loop.index0}}-remove">-</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
<div class="form-group">{{ form.category.label }} {{ form.category(size=20, class="form-control") }}</div>
|
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:96%;"><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: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)") }}
|
||||||
|
<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>
|
||||||
<div class="form-group">{{ form.year_published.label }} {{ form.year_published(size=4, class="form-control") }}</div>
|
<br><hr align="left" style="width:96%;"><br>
|
||||||
|
|
||||||
|
<div style="width: 40%;">
|
||||||
|
Add a message for future readers: {{ form.message(size=90, class="form-control") }}
|
||||||
|
<br></div>
|
||||||
<br>
|
<br>
|
||||||
{{ form.file }}
|
{{ form.file }}
|
||||||
{{ form.upload }}
|
{{ form.upload }}
|
||||||
{{ form.wish }}
|
{{ form.wish }}
|
||||||
</form>
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<table class="library_table" id="table" style="width:30% padding:10px; padding-bottom: 400px;" >
|
||||||
|
<thead>
|
||||||
|
<tr id="header" style="height:15px;">
|
||||||
|
<th style="width: 10%;"> <h5> Currently in the library </h5></th>
|
||||||
|
<th style="width: 20%;"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td> Titles: </td>
|
||||||
|
<td> {{ books_all }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> Authors: </td>
|
||||||
|
<td> {{ authors_all }} </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> Categories: </td>
|
||||||
|
<td> {{ categories|replace('[', '')|replace(']', '') }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> Stacks: </td>
|
||||||
|
<td> {{ stacks_all|replace('[', '')|replace(']', '') }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> From the years: </td>
|
||||||
|
<td> {{earliest}} –– {{latest}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> Gaps in the collection: </td>
|
||||||
|
<td> At least {{ books_potential }} potential books missing</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<clear>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -16,14 +16,14 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
<form method="POST" action="{{ url_for('add_stack') }}" enctype=multipart/form-data>
|
<form method="POST" action="{{ url_for('add_stack') }}" enctype=multipart/form-data>
|
||||||
{{form.hidden_tag()}}
|
{{form.hidden_tag()}}
|
||||||
<br>
|
<br>
|
||||||
{{ render_field(form.stack_name)}}
|
{{ render_field(form.stack_name)}}
|
||||||
{{ render_field(form.stack_description)}}
|
{{ render_field(form.stack_description)}}
|
||||||
|
{{ render_field(form.stack_author)}}
|
||||||
<button type="submit" class='button'>Create</button>
|
<button type="submit" class='button'>Create</button>
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<div> Chosen book:
|
<div> Chosen book:
|
||||||
|
|
||||||
<h1 class="header">{{ book.title }}</h1>
|
<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.png';">
|
<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';">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<p>These are all the stacks that have been built so far.</p>
|
<p>These are all the stacks that have been built so far.</p>
|
||||||
|
@ -7,12 +7,12 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<form method="POST" action="{{ url_for('edit_book_by_id', id=book.id )}}">
|
<form method="POST" action="{{ url_for('edit_book_by_id', id=book.id )}}" enctype=multipart/form-data>
|
||||||
{{ form.csrf_token }}
|
{{ form.csrf_token }}
|
||||||
|
|
||||||
<div class="form-group"><h1 class="header">{{ form.title.label }} {{ form.title(size=20, class="form-control") }}</h1></div>
|
<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.png';">
|
<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';">
|
||||||
|
|
||||||
<br> <br>
|
<br> <br>
|
||||||
<div data-toggle="fieldset" id="phone-fieldset">
|
<div data-toggle="fieldset" id="phone-fieldset">
|
||||||
@ -31,11 +31,23 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
</div><br>
|
</div><br>
|
||||||
<div class="form-group">
|
<div class="form-group" style="padding-bottom: 10px;">
|
||||||
{{ form.category.label }} {{ form.category(size=20, class="form-control") }}
|
Category: {{ form.category(size=20,
|
||||||
</div><br>
|
class="form-control") }}
|
||||||
<div class="form-group">
|
</div>
|
||||||
{{ form.year_published.label }} {{ form.year_published(size=4, class="form-control") }}
|
<div class="form-group" style="padding-bottom: 10px;">
|
||||||
|
Year published: {{ form.year_published(size=8, class="form-control") }}
|
||||||
|
</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") }}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
<button type="submit" class="btn btn-primary">Update</button>
|
<button type="submit" class="btn btn-primary">Update</button>
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
<li><a href="{{ url_for('show_books') }}">Catalogue</a></li>
|
<li><a href="{{ url_for('show_books') }}">Catalogue</a></li>
|
||||||
<li><a href="{{ url_for('show_stacks') }}">Stacks</a></li>
|
<li><a href="{{ url_for('show_stacks') }}">Stacks</a></li>
|
||||||
<li><a href="{{ url_for('add_book') }}">Add Book</a></li>
|
<li><a href="{{ url_for('add_book') }}">Add Book</a></li>
|
||||||
|
<li><a href="{{ url_for ('add_stack') }}">Add Stack</a></li>
|
||||||
<li><a href="{{ url_for('about') }}">About</a></li>
|
<li><a href="{{ url_for('about') }}">About</a></li>
|
||||||
<li><a href="{{ url_for('show_instances') }}">Instances</a></li>
|
<li><a href="{{ url_for('show_instances') }}">Instances</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
43
app/templates/potential_pdf.html
Normal file
43
app/templates/potential_pdf.html
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
@import url("../fonts/fonts_style.css");
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<title>XPPL</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container" style="padding:10px;">
|
||||||
|
<h1 style='font-family: Archivo Narrow; text-align: center;'>A Potential PDF</h1>
|
||||||
|
|
||||||
|
<h3 style='font-family: Archivo Narrow; text-align: center;'>Every book ever requested in the XPPL library: </h3>
|
||||||
|
<div style='font-family: Courier New; text-align: center; font-size: 10pt;'>
|
||||||
|
<p> {% for pbook in pbooks %}"{{ pbook.ptitle }}" requested on: {{ pbook.time|string|truncate(17,true," ")}}
|
||||||
|
</p>{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div style=" font-family: Archivo Narrow; padding-left: 40%">
|
||||||
|
<pre>
|
||||||
|
, ,
|
||||||
|
/////|
|
||||||
|
///// |
|
||||||
|
|~~~| |
|
||||||
|
|===| |
|
||||||
|
|x | |
|
||||||
|
| p | |
|
||||||
|
|p l| /
|
||||||
|
|===|/
|
||||||
|
'---'
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
</html>
|
@ -1,18 +1,14 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}Red link page{% endblock %}
|
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
body{
|
|
||||||
padding-top: 40px;
|
|
||||||
}
|
|
||||||
h1, p{
|
h1, p{
|
||||||
text-align:center;
|
text-align:left;
|
||||||
}
|
}
|
||||||
h1{
|
h1{
|
||||||
font-size:44px;
|
font-size:44px;
|
||||||
margin:75px 0 50px;
|
margin:40px 0 30px;
|
||||||
}
|
}
|
||||||
p{
|
p{
|
||||||
font-size:14px;
|
font-size:14px;
|
||||||
@ -21,16 +17,10 @@
|
|||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block header %}{% endblock %}
|
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<h1>We don't have any results for: {{ title }}</h1>
|
<h1>Nothing in the library yet with: {{ title }}</h1>
|
||||||
<p><a href="{{ url_for('add_book') }}">upload</a>?</p>
|
<br>
|
||||||
<p><a href="{{ url_for('home') }}">go back home</a>?</p>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1 class="page-header">Add Book</h1>
|
|
||||||
{% with messages = get_flashed_messages() %}
|
{% with messages = get_flashed_messages() %}
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
<div class="alert alert-danger">
|
<div class="alert alert-danger">
|
||||||
@ -42,12 +32,19 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
<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>
|
||||||
|
|
||||||
<form method="POST" action="{{ url_for('add_book') }}" enctype=multipart/form-data>
|
<form method="POST" action="{{ url_for('add_book') }}" enctype=multipart/form-data>
|
||||||
{{ form.csrf_token }}
|
{{ form.csrf_token }}
|
||||||
<div class="form-group">{{ form.title.label }} {{ form.title(size=20, class="form-control") }}</div>
|
<div class="form-group">Title: {{ form.title (size=34, class="form-control") }}</div>
|
||||||
<br>
|
<br>
|
||||||
<div data-toggle="fieldset" id="phone-fieldset">
|
<div data-toggle="fieldset" id="phone-fieldset">
|
||||||
{{ form.author.label }} <button type="button" data-toggle="fieldset-add-row"
|
Author(s): <button type="button" data-toggle="fieldset-add-row"
|
||||||
data-target="#phone-fieldset">+</button>
|
data-target="#phone-fieldset">+</button>
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
@ -56,17 +53,83 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{% for author in form.author %}
|
{% for author in form.author %}
|
||||||
<tr data-toggle="fieldset-entry">
|
<tr data-toggle="fieldset-entry">
|
||||||
<td>{{ author.author_name }}</td>
|
<td>{{ author.author_name (size=40)}}</td>
|
||||||
<td><button type="button" data-toggle="fieldset-remove-row" id="phone-{{loop.index0}}-remove">-</button></td>
|
<td><button type="button" data-toggle="fieldset-remove-row" id="phone-{{loop.index0}}-remove">-</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="padding-left:10px; padding-bottom: 50px;">
|
||||||
|
Category: {{ form.category(size=27, class="form-control") }}
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Year published: {{ form.year_published(size=8, class="form-control") }}
|
||||||
|
<br>
|
||||||
<br>
|
<br>
|
||||||
<div class="form-group">{{ form.category.label }} {{ form.category(size=20, class="form-control") }}</div>
|
|
||||||
{{ form.file }}
|
{{ form.file }}
|
||||||
{{ form.upload }}
|
{{ form.upload }}
|
||||||
{{ form.wish }}
|
{{ form.wish }}
|
||||||
</form>
|
</form>
|
||||||
|
<br>
|
||||||
|
<p><a href="{{ url_for('home') }}" style="font-size: 9pt;">go back home</a></p>
|
||||||
|
<br>
|
||||||
</div>
|
</div>
|
||||||
|
<div class= "Container" style= "border-top: dashed; border-width: 1px;">
|
||||||
|
<h2> More potential books </h2>
|
||||||
|
<table class="library_table" id="table" style="width:100%">
|
||||||
|
<thead>
|
||||||
|
<tr id="header">
|
||||||
|
<th width="70px;">Cover</th>
|
||||||
|
<th>Title</th>
|
||||||
|
<th width="400px;">Author</th>
|
||||||
|
<th width="100px;">Year</th>
|
||||||
|
<th width="100px;">Category</th>
|
||||||
|
<th width="100px;">Stack</th>
|
||||||
|
<th width="100px;">Add to a stack</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% 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';">
|
||||||
|
<!-- <object class="no_cover" data="../static/img/default_cover.png" type="image/png" width="65">
|
||||||
|
<p hidden="True"></p>
|
||||||
|
|
||||||
|
</object>-->
|
||||||
|
</td>
|
||||||
|
<td class="title_col"><a href="/books/{{ book.id }}">{{ book.title }}</a></td>
|
||||||
|
|
||||||
|
<td class="author_col"> {% for author in book.authors %}
|
||||||
|
|
||||||
|
<li><a href="{{url_for('show_author_by_id', id=author.id)}}">{{ author.author_name }}</a> </li>
|
||||||
|
|
||||||
|
{% endfor %}</td>
|
||||||
|
<td id='fileformat'>{{ book.year_published }}</td>
|
||||||
|
<td>{{ book.category}}</td>
|
||||||
|
<td>
|
||||||
|
{% for stack in book.stacks %}
|
||||||
|
|
||||||
|
<li><a href="{{url_for('show_stack_by_id', id=stack.id)}}"> </a>
|
||||||
|
|
||||||
|
{{ stack.stack_name }}
|
||||||
|
</li>
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td id='plus'><a href="{{url_for('add_to_stack', id=book.id)}}">
|
||||||
|
|
||||||
|
===>
|
||||||
|
</a></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -1,18 +1,24 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{% from "_formhelpers.html" import render_field %}
|
{% from "_formhelpers.html" import render_field %}
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<div>{{ form.select(style="width: 100px; margin: 10px; float: left; font-size: 20px") }}</div>
|
<div>{{ form.select(style="width: 100px; margin: 10px; float: left; font-size: 20px") }}</div>
|
||||||
<div class="search">
|
<div class="search">
|
||||||
{{ render_field(form.search) }} </div>
|
{{ render_field(form.search) }} </div>
|
||||||
<button type="submit" class="button">Search</button>
|
<button type="submit" class="button">browse</button>
|
||||||
</form>
|
<p><br>
|
||||||
|
{{ form.grid(style="font-size:20px")}}{{ form.listview(style="font-size:20px")}}</p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="container">
|
<br>
|
||||||
<h1 class="page-header">Search Results for: {{ query }}</h1>
|
<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>
|
||||||
|
<br>
|
||||||
{% with messages = get_flashed_messages() %}
|
{% with messages = get_flashed_messages() %}
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
<div class="alert alert-success">
|
<div class="alert alert-success">
|
||||||
@ -25,20 +31,21 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
<table class="library_table" id="table" style="width:100%">
|
<table class="library_table" id="table" style="width:100%; padding-bottom:60px;">
|
||||||
<tr id="header">
|
<tr id="header">
|
||||||
<th>Cover</th>
|
<th width="70px;">Cover</th>
|
||||||
<th>Title</th>
|
<th>Title</th>
|
||||||
<th>Author</th>
|
<th width="400px;">Author</th>
|
||||||
<th>Filetype</th>
|
<th width="100px;">Year</th>
|
||||||
<th>Category</th>
|
<th width="100px;">Category</th>
|
||||||
<th>Stack</th>
|
<th width="100px;">Stack</th>
|
||||||
<th>Add to stack</th>
|
<th width="100px;">Add to stack</th>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
{% for book in books %}
|
{% for book in books %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><img class="no_cover" id="{{ book.title }}" src="/uploads/cover/{{ book.cover }}" width="80" onerror="if (this.src != '/static/img/default_cover.png') this.src = '/static/img/default_cover.png';"></td>
|
<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>
|
||||||
<td><a href="{{url_for('show_book_by_id', id=book.id)}}">{{ book.title }}</a></td>
|
<td><a href="{{url_for('show_book_by_id', id=book.id)}}">{{ book.title }}</a></td>
|
||||||
|
|
||||||
<td> {% for author in book.authors %}
|
<td> {% for author in book.authors %}
|
||||||
@ -46,40 +53,40 @@
|
|||||||
<li><a href="{{url_for('show_author_by_id', id=author.id)}}">{{ author.author_name }}</a> </li>
|
<li><a href="{{url_for('show_author_by_id', id=author.id)}}">{{ author.author_name }}</a> </li>
|
||||||
|
|
||||||
{% endfor %}</td>
|
{% endfor %}</td>
|
||||||
<td>{{ book.fileformat }}</td>
|
<td>{{ book.year_published or '––'}}</td>
|
||||||
<td>{{ book.category}}</td>
|
<td>{{ book.category}}</td>
|
||||||
<td> {% for stack in book.stacks %}
|
<td> {% for stack in book.stacks %}
|
||||||
|
|
||||||
<li><a href="{{url_for('show_stack_by_id', id=stack.id)}}">{{ stack.stack_name }}</a> </li>
|
<li><a href="{{url_for('show_stack_by_id', id=stack.id)}}">{{ stack.stack_name }}</a> </li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</td>
|
</td>
|
||||||
|
<td id='plus'><a href="{{url_for('add_to_stack', id=book.id)}}">
|
||||||
<td id='plus'><a href='{{url_for('add_to_stack', id=book.id)}}'>
|
|
||||||
==>
|
==>
|
||||||
</a></td>
|
</a></td>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<br>
|
||||||
|
|
||||||
<div class="container" >
|
<div class="container" style= "border-top: dashed; border-width: 1px;" >
|
||||||
<hr>
|
<h2> More books </h2>
|
||||||
<h2> Other books </h2>
|
|
||||||
|
|
||||||
<table class="library_table" id="table" style="width:100%">
|
<table class="library_table" id="table" style="width:100%">
|
||||||
<tr id="header">
|
<tr id="header">
|
||||||
<th>Cover</th>
|
<th width="70px;">Cover</th>
|
||||||
<th>Title</th>
|
<th>Title</th>
|
||||||
<th>Author</th>
|
<th width="400px;">Author</th>
|
||||||
<th>Filetype</th>
|
<th width="100px;">Year</th>
|
||||||
<th>Category</th>
|
<th width="100px;">Category</th>
|
||||||
<th>Stack</th>
|
<th width="100px;">Stack</th>
|
||||||
<th>Add to stack</th>
|
<th width="100px;">Add to stack</th>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
{% for book in books_all %}
|
{% for book in books_all %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><img class="no_cover" id="{{ book.title }}" src="/uploads/cover/{{ book.cover }}" width="80" onerror="if (this.src != '/static/img/default_cover.png') this.src = '/static/img/default_cover.png';"></td>
|
<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><a href="{{url_for('show_book_by_id', id=book.id)}}">{{ book.title }}</a></td>
|
<td><a href="{{url_for('show_book_by_id', id=book.id)}}">{{ book.title }}</a></td>
|
||||||
|
|
||||||
<td> {% for author in book.authors %}
|
<td> {% for author in book.authors %}
|
||||||
@ -87,16 +94,18 @@
|
|||||||
<li><a href="{{url_for('show_author_by_id', id=author.id)}}">{{ author.author_name }}</a> </li>
|
<li><a href="{{url_for('show_author_by_id', id=author.id)}}">{{ author.author_name }}</a> </li>
|
||||||
|
|
||||||
{% endfor %}</td>
|
{% endfor %}</td>
|
||||||
<td>{{ book.fileformat }}</td>
|
<td>{{ book.year_published or '––'}}</td>
|
||||||
<td>{{ book.category}}</td>
|
<td>{{ book.category}}</td>
|
||||||
<td> {% for stack in book.stacks %}
|
<td> {% for stack in book.stacks %}
|
||||||
|
|
||||||
<li><a href="{{url_for('show_stack_by_id', id=stack.id)}}">{{ stack.stack_name }}</a> </li>
|
<li><a href="{{url_for('show_stack_by_id', id=stack.id)}}">{{ stack.stack_name }}</a> </li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td id='plus'><a href='{{url_for('add_to_stack', id=book.id)}}'>
|
<td id='plus'><a href="{{url_for('add_to_stack', id=book.id)}}">
|
||||||
==>
|
==>
|
||||||
</a></td>
|
</a></td>
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
<p>
|
<p>
|
||||||
|
87
app/templates/results_grid.html
Normal file
87
app/templates/results_grid.html
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% 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">
|
||||||
|
{{ 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>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<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>
|
||||||
|
<br>
|
||||||
|
{% with messages = get_flashed_messages() %}
|
||||||
|
{% if messages %}
|
||||||
|
<div class="alert alert-success">
|
||||||
|
<ul>
|
||||||
|
{% for message in messages %}
|
||||||
|
<li>{{ message }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
<div class="grid" style="padding-bottom:60px;">
|
||||||
|
|
||||||
|
{% for book in books|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>
|
||||||
|
<p>
|
||||||
|
<tbody>
|
||||||
|
<th>
|
||||||
|
{{ book.title }} ({{ book.year_published or '?' }})</th>
|
||||||
|
<br>
|
||||||
|
<span style = "font-size: 14px;">
|
||||||
|
{% for author in book.authors %}
|
||||||
|
{{ author.author_name }}<br> {% endfor %} </span>
|
||||||
|
</tbody>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container" style= "border-top: dashed; border-width: 1px;">
|
||||||
|
<h2> More books </h2>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
<p>
|
||||||
|
<tbody>
|
||||||
|
<th>
|
||||||
|
{{ book.title }} ({{ book.year_published or '?' }})</th>
|
||||||
|
<br>
|
||||||
|
<span style = "font-size: 14px;">
|
||||||
|
{% for author in book.authors %}
|
||||||
|
{{ author.author_name }}<br> {% endfor %} </span>
|
||||||
|
</tbody>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a href="/books"> See all books </a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="stylesheet" type="text/css" href="http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css"/>
|
|
||||||
<style>
|
<style>
|
||||||
#scape_container {
|
#scape_container {
|
||||||
zoom: 1;
|
zoom: 1;
|
||||||
|
@ -2,22 +2,69 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
<h1 class="header">{{ book.title }}</h1>
|
<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.png';">
|
<div style="float:right; padding-right: 140px;">
|
||||||
<p>Author(s): <ul>{% for author in book.authors %}
|
<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>
|
||||||
|
|
||||||
<li><a href="{{url_for('show_author_by_id', id=author.id)}}">{{ author.author_name }}</a> </li>
|
<table class="library_table" id="table" style="width:50%; padding-bottom: 80px;">
|
||||||
|
<thead>
|
||||||
{% endfor %}</ul></p>
|
<tr id="header">
|
||||||
|
<th style="width: 150px;"></th>
|
||||||
<p>Category: {{ book.category }}</p>
|
<th style="width: 300px;"></th>
|
||||||
<p>Year published: {{ book.year_published }}</p>
|
</tr>
|
||||||
|
</thead>
|
||||||
<p>Stack(s): <ul>{% for stack in book.stacks %}
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Year published: </td>
|
||||||
|
<td>{{ book.year_published or '––'}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> Author(s): </td>
|
||||||
|
<td>{% for author in book.authors %}
|
||||||
|
<a href="{{url_for('show_author_by_id', id=author.id)}}">{{ author.author_name }}</a><br>
|
||||||
|
{% endfor %}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Category: </td>
|
||||||
|
<td>{{ book.category }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Included in stack(s): </td>
|
||||||
|
<td>{% for stack in book.stacks %}
|
||||||
<li><a href="{{url_for('show_stack_by_id', id=stack.id)}}">{{ stack.stack_name }}</a>
|
<li><a href="{{url_for('show_stack_by_id', id=stack.id)}}">{{ stack.stack_name }}</a>
|
||||||
|
<p style="font-size: 10px;"><a href="{{url_for('remove_from_stack', stackid=stack.id, bookid=book.id)}}"> – Remove from stack</a>{% endfor %}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="font-style: italic;">Notes from uploader</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>How different is this item to the rest of the collection?<br></td>
|
||||||
|
<td>{{ book.sameness or '?'}} % different</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>How diverse are the references in this book?<br></td>
|
||||||
|
<td>{{ book.diversity or '?' }} % diverse </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Who is speaking?<br></td>
|
||||||
|
<td>{{ book.gender or '?' }} % female </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<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>
|
||||||
|
|
||||||
{% endfor %}</ul></p>
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
<a href="../uploads/{{ book.file }}">download {{ book.fileformat }}</a>
|
<a href="../uploads/{{ book.file }}">download {{ book.fileformat }}</a>
|
||||||
<br>
|
<br>
|
||||||
@ -40,8 +87,29 @@
|
|||||||
{{ instance }}: {{ (result*100)|round|int }}%<br>
|
{{ instance }}: {{ (result*100)|round|int }}%<br>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<br>
|
<br>
|
||||||
<br>
|
|
||||||
<a href="{{ url_for('edit_book_by_id', id=book.id )}}">edit</a>
|
|
||||||
|
|
||||||
|
|
||||||
|
{% 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>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<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 %}
|
||||||
|
{% 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 %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -8,8 +8,11 @@
|
|||||||
<div>{{ form.select(style="width: 100px; margin: 10px; float: left; font-size: 20px") }}</div>
|
<div>{{ form.select(style="width: 100px; margin: 10px; float: left; font-size: 20px") }}</div>
|
||||||
<div class="search">
|
<div class="search">
|
||||||
{{ render_field(form.search) }} </div>
|
{{ render_field(form.search) }} </div>
|
||||||
<button type="submit" class="button">Search</button>
|
<button type="submit" @click="sendMessage" class="button is-info" >browse</button>
|
||||||
</form>
|
|
||||||
|
<p><br>
|
||||||
|
{{ form.grid(style="font-size:20px")}}{{ form.listview(style="font-size:20px")}}</p>
|
||||||
|
</form>
|
||||||
|
|
||||||
<h1 class="page-header">All Books</h1>
|
<h1 class="page-header">All Books</h1>
|
||||||
{% with messages = get_flashed_messages() %}
|
{% with messages = get_flashed_messages() %}
|
||||||
@ -27,21 +30,21 @@
|
|||||||
<table class="library_table" id="table" style="width:100%">
|
<table class="library_table" id="table" style="width:100%">
|
||||||
<thead>
|
<thead>
|
||||||
<tr id="header">
|
<tr id="header">
|
||||||
<th>Cover</th>
|
<th width="70px;">Cover</th>
|
||||||
<th>Title</th>
|
<th>Title</th>
|
||||||
<th>Author</th>
|
<th width="400px;">Author</th>
|
||||||
<th>Filetype</th>
|
<th width="100px;">Year</th>
|
||||||
<th>Category</th>
|
<th width="100px;">Category</th>
|
||||||
<th>Stack</th>
|
<th width="100px;">Stack</th>
|
||||||
<th>Add to stack</th>
|
<th width="100px;">Add to a stack</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for book in books|sort(attribute='title', reverse = False) %}
|
{% for book in books %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td style= "padding: 5px;">
|
||||||
|
|
||||||
<img class="no_cover" id="{{ book.title }}" src="/uploads/cover/{{ book.cover }}" width="40" onerror="if (this.src != '/static/img/default_cover.png') this.src = '/static/img/default_cover.png';">
|
<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';">
|
||||||
<!-- <object class="no_cover" data="../static/img/default_cover.png" type="image/png" width="65">
|
<!-- <object class="no_cover" data="../static/img/default_cover.png" type="image/png" width="65">
|
||||||
<p hidden="True"></p>
|
<p hidden="True"></p>
|
||||||
|
|
||||||
@ -54,16 +57,20 @@
|
|||||||
<li><a href="{{url_for('show_author_by_id', id=author.id)}}">{{ author.author_name }}</a> </li>
|
<li><a href="{{url_for('show_author_by_id', id=author.id)}}">{{ author.author_name }}</a> </li>
|
||||||
|
|
||||||
{% endfor %}</td>
|
{% endfor %}</td>
|
||||||
<td>{{ book.fileformat }}</td>
|
<td id='fileformat'>{{ book.year_published or '––'}}</td>
|
||||||
<td>{{ book.category}}</td>
|
<td>{{ book.category}}</td>
|
||||||
<td> {% for stack in book.stacks %}
|
<td>
|
||||||
|
{% for stack in book.stacks %}
|
||||||
|
|
||||||
|
<li><a href="{{url_for('show_stack_by_id', id=stack.id)}}"> {{ stack.stack_name }} </a></li>
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
<li><a href="{{url_for('show_stack_by_id', id=stack.id)}}">{{ stack.stack_name }}</a> </li>
|
|
||||||
{% endfor %}
|
|
||||||
</td>
|
</td>
|
||||||
<td id='plus'><a href='{{url_for('add_to_stack', id=book.id)}}'>
|
<td id='plus'><a href="{{url_for('add_to_stack', id=book.id)}}">
|
||||||
|
|
||||||
==>
|
===>
|
||||||
</a></td>
|
</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
@ -2,6 +2,18 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<div class="container">
|
<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">
|
||||||
|
{{ 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>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<h1 class="page-header">All Books</h1>
|
<h1 class="page-header">All Books</h1>
|
||||||
{% with messages = get_flashed_messages() %}
|
{% with messages = get_flashed_messages() %}
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
@ -15,14 +27,27 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
|
<div class="grid">
|
||||||
|
|
||||||
{% for book in books|sort(attribute='title', reverse = False) %}
|
{% for book in books %}
|
||||||
|
|
||||||
|
|
||||||
|
<div class="gridbox">
|
||||||
<a href="books/{{ book.id }}">
|
<a href="books/{{ book.id }}">
|
||||||
<img class="no_cover" id="{{ book.title }}" src="../uploads/cover/{{ book.cover }}" width="140" onerror="if (this.src != '../static/img/default_cover.png') this.src = '../static/img/default_cover.png';"><!--{{ book.title }}--></a>
|
<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>
|
||||||
|
<p>
|
||||||
|
<tbody>
|
||||||
|
<th>
|
||||||
|
{{ book.title }} ({{ book.year_published or '–' }})</th>
|
||||||
|
<br>
|
||||||
|
<span style = "font-size: 14px;">
|
||||||
|
{% for author in book.authors %}
|
||||||
|
{{ author.author_name }}<br> {% endfor %} </span>
|
||||||
|
</tbody>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -6,10 +6,18 @@
|
|||||||
<h1 class="header">{{ stack.stack_name }}</h1>
|
<h1 class="header">{{ stack.stack_name }}</h1>
|
||||||
|
|
||||||
<p>{{ stack.stack_description }} </p>
|
<p>{{ stack.stack_description }} </p>
|
||||||
<p>Books in this stack: {% for book in stack.books %}
|
<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 %}
|
||||||
|
|
||||||
<li> <a href="{{url_for('show_book_by_id', id=book.id)}}">{{book.title}}</a> </li>
|
<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 != '../static/img/{{ book.cover }}') this.src = '../static/img/default_cover.png';">
|
<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 class='widget'>
|
<div class='widget'>
|
||||||
<iframe src="../uploads/{{ book.file }}" width="50%" ></iframe>
|
<iframe src="../uploads/{{ book.file }}" width="50%" ></iframe>
|
||||||
</div>
|
</div>
|
||||||
@ -19,12 +27,13 @@
|
|||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
<p>
|
<p>
|
||||||
<a href="{{ url_for('remove_stack_by_id', id=stack.id )}}">Delete</a> </p>
|
<a href="{{ url_for('remove_stack_by_id', id=stack.id )}}">Remove stack</a> </p>
|
||||||
<a href="{{ url_for('edit_stack_by_id', id=stack.id )}}">Edit</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('show_stacks')}}">Go back to stacks</p>
|
<p><a href="{{url_for('show_stacks')}}">Go back to the other stacks</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -10,8 +10,15 @@
|
|||||||
|
|
||||||
|
|
||||||
<p>{{ stack.stack_description }} </p>
|
<p>{{ stack.stack_description }} </p>
|
||||||
|
<p id='creator'>Created by:
|
||||||
|
{% if stack.stack_author == None %} anon</p>
|
||||||
|
{% else %}
|
||||||
|
|
||||||
<p>Books in this stack: {% for book in stack.books %}
|
{{ stack.stack_author }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
<p style='font-weight:bold;'>Books in this stack: {% for book in stack.books %}
|
||||||
|
|
||||||
<li style="font-size: 18px;"> <a href="{{url_for('show_book_by_id', id=book.id)}}">{{book.title}}</a> </li>
|
<li style="font-size: 18px;"> <a href="{{url_for('show_book_by_id', id=book.id)}}">{{book.title}}</a> </li>
|
||||||
|
|
||||||
|
@ -4,8 +4,6 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<h1 class="page-header">Stacks</h1>
|
<h1 class="page-header">Stacks</h1>
|
||||||
<p>These are all the stacks that have been built so far.</p>
|
<p>These are all the stacks that have been built so far.</p>
|
||||||
<p><a href= {{ url_for('add_stack') }}>Add a new stack</a></p>
|
|
||||||
|
|
||||||
|
|
||||||
<table style="width:100%">
|
<table style="width:100%">
|
||||||
|
|
||||||
@ -25,6 +23,13 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
232
app/views.py
232
app/views.py
@ -9,12 +9,14 @@ from app import app, db, socketio, DOMAIN
|
|||||||
from flask import Flask, Response, session, render_template, request, redirect, url_for, flash, send_from_directory, jsonify, abort
|
from flask import Flask, Response, session, render_template, request, redirect, url_for, flash, send_from_directory, jsonify, abort
|
||||||
import json
|
import json
|
||||||
from sqlalchemy.sql.expression import func, select
|
from sqlalchemy.sql.expression import func, select
|
||||||
|
from sqlalchemy.sql import except_
|
||||||
from app.forms import UploadForm, EditForm, SearchForm, ChatForm, StackForm, AddtoStackForm, EditStackForm
|
from app.forms import UploadForm, EditForm, SearchForm, ChatForm, StackForm, AddtoStackForm, EditStackForm
|
||||||
from app.models import Book, BookSchema, Author, AuthorSchema, Stack, StackSchema, UserIns, Chat, ChatSchema, Instance
|
from app.models import Book, BookSchema, Author, AuthorSchema, Stack, StackSchema, UserIns, Chat, ChatSchema, Instance, Potential
|
||||||
from app.cover import get_cover
|
from app.cover import get_cover
|
||||||
from app.extractText import extract_text
|
from app.extractText import extract_text
|
||||||
from os import environ
|
from os import environ
|
||||||
from flask_socketio import SocketIO, emit
|
from flask_socketio import SocketIO, emit
|
||||||
|
from weasyprint import HTML
|
||||||
import datetime
|
import datetime
|
||||||
import time
|
import time
|
||||||
from csv import DictWriter, DictReader
|
from csv import DictWriter, DictReader
|
||||||
@ -50,6 +52,7 @@ def allowed_file(filename):
|
|||||||
def home():
|
def home():
|
||||||
chat_form = ChatForm()
|
chat_form = ChatForm()
|
||||||
chat_messages = db.session.query(Chat).all()
|
chat_messages = db.session.query(Chat).all()
|
||||||
|
username = 'librarian'
|
||||||
|
|
||||||
# if request.method == 'POST':
|
# if request.method == 'POST':
|
||||||
# if chat_form.validate_on_submit():
|
# if chat_form.validate_on_submit():
|
||||||
@ -64,7 +67,7 @@ def home():
|
|||||||
else:
|
else:
|
||||||
client = request.environ['HTTP_X_FORWARDED_FOR']
|
client = request.environ['HTTP_X_FORWARDED_FOR']
|
||||||
|
|
||||||
return render_template('home.html',domain=DOMAIN,chat=chat_messages, channel = 1, username="librarian", client=client, server=server)
|
return render_template('home.html',domain=DOMAIN,chat=chat_messages, channel = 1, username=username, client=client, server=server)
|
||||||
|
|
||||||
@app.route('/hello/<name>')
|
@app.route('/hello/<name>')
|
||||||
def hello(name):
|
def hello(name):
|
||||||
@ -134,6 +137,15 @@ def show_books_grid():
|
|||||||
def show_book_by_id(id):
|
def show_book_by_id(id):
|
||||||
book = Book.query.get(id)
|
book = Book.query.get(id)
|
||||||
all_instances = db.session.query(Instance).all()
|
all_instances = db.session.query(Instance).all()
|
||||||
|
previousbook = Book.query.filter_by(id=id - 1).first()
|
||||||
|
nextbook = Book.query.filter_by(id=id + 1).first()
|
||||||
|
allbooks = db.session.query(Book).all()
|
||||||
|
edge = len(allbooks)
|
||||||
|
if id == 1:
|
||||||
|
previousbook = None
|
||||||
|
if id == edge:
|
||||||
|
nextbook = None
|
||||||
|
|
||||||
userin = UserIns.query.filter_by(title="lastViewed").first()
|
userin = UserIns.query.filter_by(title="lastViewed").first()
|
||||||
if userin != None:
|
if userin != None:
|
||||||
userin.info = book.title
|
userin.info = book.title
|
||||||
@ -145,7 +157,7 @@ def show_book_by_id(id):
|
|||||||
if not book:
|
if not book:
|
||||||
return render_template('red_link.html', id=id)
|
return render_template('red_link.html', id=id)
|
||||||
else:
|
else:
|
||||||
return render_template('show_book_detail.html', book=book, all_instances=all_instances)
|
return render_template('show_book_detail.html', book=book, previousbook = previousbook, nextbook = nextbook, all_instances=all_instances)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/books/<int:id>/delete', methods=['POST', 'GET'])
|
@app.route('/books/<int:id>/delete', methods=['POST', 'GET'])
|
||||||
@ -161,24 +173,23 @@ def remove_book_by_id(id):
|
|||||||
@app.route('/books/<int:id>/edit', methods=['POST', 'GET'])
|
@app.route('/books/<int:id>/edit', methods=['POST', 'GET'])
|
||||||
def edit_book_by_id(id):
|
def edit_book_by_id(id):
|
||||||
book_to_edit = Book.query.filter_by(id=id).first()
|
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)
|
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)
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
if user_form.validate_on_submit():
|
if user_form.validate_on_submit():
|
||||||
# check if the post request has the file part
|
# on submit, check fields
|
||||||
title = user_form.title.data # You could also have used request.form['name']
|
title = user_form.title.data
|
||||||
input_authors = user_form.author.data # You could also have used request.form['email']
|
input_authors = user_form.author.data
|
||||||
category = user_form.category.data
|
category = user_form.category.data
|
||||||
year_published = user_form.year_published.data
|
year_published = user_form.year_published.data
|
||||||
|
message = user_form.message.data
|
||||||
if year_published=="":
|
if year_published=="":
|
||||||
year_published = None
|
year_published = None
|
||||||
# save user to database
|
|
||||||
#book = Book(title, author, filename, cover, file_extension)
|
|
||||||
|
|
||||||
book = Book.query.filter_by(id=id).first()
|
book = Book.query.filter_by(id=id).first()
|
||||||
book.title = title
|
book.title = title
|
||||||
book.category = category
|
book.category = category
|
||||||
book.year_published = year_published
|
book.year_published = year_published
|
||||||
|
book.message = message
|
||||||
|
|
||||||
#authors update
|
#authors update
|
||||||
book.authors.clear()
|
book.authors.clear()
|
||||||
@ -195,6 +206,26 @@ def edit_book_by_id(id):
|
|||||||
if existing_ip:
|
if existing_ip:
|
||||||
i.name = existing_ip.name
|
i.name = existing_ip.name
|
||||||
book.instances.append(i)
|
book.instances.append(i)
|
||||||
|
|
||||||
|
# editing / uploading new file
|
||||||
|
if user_form.file.data:
|
||||||
|
file = request.files['file']
|
||||||
|
if file.filename == '':
|
||||||
|
flash('No selected file')
|
||||||
|
return redirect(request.url)
|
||||||
|
if file and allowed_file(file.filename):
|
||||||
|
allbooks = db.session.query(Book).all()
|
||||||
|
id = book.id
|
||||||
|
|
||||||
|
filename = str(id) + "_" + secure_filename(file.filename)
|
||||||
|
fullpath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
||||||
|
name, file_extension = os.path.splitext(filename)
|
||||||
|
file.save(fullpath)
|
||||||
|
book.cover = get_cover(fullpath, name)
|
||||||
|
book.file = filename
|
||||||
|
else:
|
||||||
|
flash('allowed file formats: %s' % ALLOWED_EXTENSIONS)
|
||||||
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
flash("%s updated" % (title))
|
flash("%s updated" % (title))
|
||||||
return redirect(url_for('show_book_by_id', id=id))
|
return redirect(url_for('show_book_by_id', id=id))
|
||||||
@ -205,6 +236,17 @@ def edit_book_by_id(id):
|
|||||||
@app.route('/add-book', methods=['POST', 'GET'])
|
@app.route('/add-book', methods=['POST', 'GET'])
|
||||||
def add_book():
|
def add_book():
|
||||||
upload_form = UploadForm()
|
upload_form = UploadForm()
|
||||||
|
allbooks = db.session.query(Book).all()
|
||||||
|
books_all = len(allbooks)
|
||||||
|
allauthors = db.session.query(Author).all()
|
||||||
|
authors_all = len(allauthors)
|
||||||
|
stacks_all = [s.stack_name for s in db.session.query(Stack.stack_name)]
|
||||||
|
categories = [r.category for r in db.session.query(Book.category).distinct()]
|
||||||
|
allpotential = db.session.query(Book).filter(Book.file.contains('potential.pdf')).all()
|
||||||
|
books_potential = len(allpotential)
|
||||||
|
earliest = db.session.query(func.min(Book.year_published)).scalar()
|
||||||
|
latest = db.session.query(func.max(Book.year_published)).scalar()
|
||||||
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
if upload_form.validate_on_submit():
|
if upload_form.validate_on_submit():
|
||||||
@ -212,7 +254,14 @@ def add_book():
|
|||||||
title = upload_form.title.data
|
title = upload_form.title.data
|
||||||
authors = upload_form.author.data
|
authors = upload_form.author.data
|
||||||
category = upload_form.category.data
|
category = upload_form.category.data
|
||||||
|
message = upload_form.message.data
|
||||||
year_published = upload_form.year_published.data
|
year_published = upload_form.year_published.data
|
||||||
|
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=="":
|
if year_published=="":
|
||||||
year_published = None
|
year_published = None
|
||||||
|
|
||||||
@ -229,12 +278,12 @@ def add_book():
|
|||||||
flash('No selected file')
|
flash('No selected file')
|
||||||
return redirect(request.url)
|
return redirect(request.url)
|
||||||
if file and allowed_file(file.filename):
|
if file and allowed_file(file.filename):
|
||||||
filename = secure_filename(file.filename)
|
|
||||||
allbooks = db.session.query(Book).all()
|
allbooks = db.session.query(Book).all()
|
||||||
id = len(allbooks)+1
|
id = len(allbooks)+1
|
||||||
new_filename = str(id) +"_"+ filename
|
filename = str(id) + "_" + secure_filename(file.filename)
|
||||||
fullpath = os.path.join(app.config['UPLOAD_FOLDER'], new_filename)
|
|
||||||
name, file_extension = os.path.splitext(new_filename)
|
fullpath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
||||||
|
name, file_extension = os.path.splitext(filename)
|
||||||
file.save(fullpath)
|
file.save(fullpath)
|
||||||
try:
|
try:
|
||||||
cover = get_cover(fullpath, name)
|
cover = get_cover(fullpath, name)
|
||||||
@ -247,15 +296,22 @@ def add_book():
|
|||||||
flash('allowed file formats: %s' % ALLOWED_EXTENSIONS)
|
flash('allowed file formats: %s' % ALLOWED_EXTENSIONS)
|
||||||
#if upload without file -> wishform, with potential PDF
|
#if upload without file -> wishform, with potential PDF
|
||||||
if upload_form.wish.data:
|
if upload_form.wish.data:
|
||||||
#TO DO: make pdf generator
|
#pdf generator
|
||||||
#file = open('app/uploads/potential.pdf')
|
filename = 'potential.pdf'
|
||||||
#filename = 'potential.pdf'
|
file_extension = '.pdf'
|
||||||
#file_extension = '.pdf'
|
cover= ''
|
||||||
filename = ''
|
ptitle = upload_form.title.data
|
||||||
file_extension = ''
|
pbook = Potential(ptitle)
|
||||||
cover = ''
|
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');
|
||||||
|
print ('potential_pdf')
|
||||||
|
|
||||||
book = Book(title, filename, cover, file_extension, category,year_published)
|
book = Book(title, filename, cover, file_extension, category, year_published, message, sameness, diversity, gender, who, time)
|
||||||
db.session.add(book)
|
db.session.add(book)
|
||||||
for author in authors:
|
for author in authors:
|
||||||
author_name = author.get("author_name")
|
author_name = author.get("author_name")
|
||||||
@ -276,7 +332,7 @@ def add_book():
|
|||||||
return redirect(url_for('show_books'))
|
return redirect(url_for('show_books'))
|
||||||
|
|
||||||
flash_errors(upload_form)
|
flash_errors(upload_form)
|
||||||
return render_template('add_book.html', form=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)
|
||||||
|
|
||||||
|
|
||||||
# Flash errors from the form if validation fails
|
# Flash errors from the form if validation fails
|
||||||
@ -318,9 +374,10 @@ def add_stack():
|
|||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
stack_name = form.stack_name.data
|
stack_name = form.stack_name.data
|
||||||
stack_description = form.stack_description.data
|
stack_description = form.stack_description.data
|
||||||
stack = Stack(stack_name, stack_description)
|
stack_author = form.stack_author.data
|
||||||
|
stack = Stack(stack_name, stack_description, stack_author)
|
||||||
if form.stack_name.data:
|
if form.stack_name.data:
|
||||||
stack = Stack(stack_name, stack_description)
|
stack = Stack(stack_name, stack_description, stack_author)
|
||||||
db.session.add(stack)
|
db.session.add(stack)
|
||||||
stacks = db.session.query(Stack).all()
|
stacks = db.session.query(Stack).all()
|
||||||
return redirect(url_for('show_stacks'))
|
return redirect(url_for('show_stacks'))
|
||||||
@ -396,48 +453,130 @@ def show_instances():
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
return render_template('show_instances.html', instances=instances)
|
return render_template('show_instances.html', instances=instances)
|
||||||
|
|
||||||
|
@app.route('/stacks/<int:stackid>/remove/<int:bookid>', methods=['POST', 'GET'])
|
||||||
|
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)
|
||||||
|
stack.books.remove(book)
|
||||||
|
db.session.commit()
|
||||||
|
return render_template('show_book_detail.html', book=book)
|
||||||
|
|
||||||
## search
|
## search
|
||||||
|
view = ['1']
|
||||||
|
|
||||||
@app.route('/books', methods= ['POST','GET'])
|
@app.route('/books', methods= ['POST','GET'])
|
||||||
def show_books():
|
def show_books():
|
||||||
#autocomplete.load() #Train markov model once, for autocomplete in search
|
books = db.session.query(Book).order_by(Book.title)
|
||||||
|
|
||||||
books = db.session.query(Book).all()
|
|
||||||
search = SearchForm(request.form)
|
search = SearchForm(request.form)
|
||||||
|
view.append('1')
|
||||||
|
viewby = '1'
|
||||||
|
|
||||||
|
if search.grid.data:
|
||||||
|
viewby = '2'
|
||||||
|
view.append('2')
|
||||||
|
return render_template ('show_books_grid.html', books=books, form=search)
|
||||||
|
|
||||||
|
if search.listview.data:
|
||||||
|
viewby = '1'
|
||||||
|
view.append('1')
|
||||||
|
return render_template ('show_books.html', books=books, form=search)
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
return redirect((url_for('search_results', searchtype=search.select.data, query=search.search.data)))
|
newmsg = 'searched for: ' + search.search.data
|
||||||
|
socketio.emit('channel-' + str(1), {
|
||||||
|
'username': 'Search form',
|
||||||
|
'text': search.search.data,
|
||||||
|
'time': str(datetime.datetime.utcnow().strftime("%d.%m.%Y %H:%M"))}, broadcast=True)
|
||||||
|
# Save message
|
||||||
|
my_new_chat = Chat(message=newmsg)
|
||||||
|
db.session.add(my_new_chat)
|
||||||
|
try:
|
||||||
|
db.session.commit()
|
||||||
|
except:
|
||||||
|
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)
|
||||||
|
|
||||||
@app.route('/search/<searchtype>/<query>/', methods=['POST', 'GET'])
|
@app.route('/search/<searchtype>/<viewby>/<query>', methods=['POST', 'GET'])
|
||||||
def search_results(searchtype, query):
|
def search_results(searchtype, query, viewby):
|
||||||
search = SearchForm(request.form)
|
search = SearchForm(request.form, search=query)
|
||||||
random_order=Book.query.order_by(func.random()).limit(10)
|
results=Book.query.filter(Book.title.contains(query)).order_by(Book.title)
|
||||||
results=Book.query.filter(Book.title.contains(query)).all()
|
allbooks = set(Book.query.all())
|
||||||
|
viewby = view[-1]
|
||||||
|
|
||||||
if searchtype == 'Title':
|
if searchtype == 'Title':
|
||||||
results=Book.query.filter(Book.title.contains(query)).all()
|
results=Book.query.filter(Book.title.contains(query)).order_by(Book.title)
|
||||||
|
|
||||||
if searchtype == 'Category':
|
if searchtype == 'Category':
|
||||||
results=Book.query.filter(Book.category.contains(query)).all()
|
results=Book.query.filter(Book.category.contains(query)).order_by(Book.title)
|
||||||
|
|
||||||
|
if searchtype== 'Author':
|
||||||
|
results=db.session.query(Book).join(Book.authors).filter(Author.author_name.contains(query)).order_by(Book.title)
|
||||||
|
|
||||||
|
if searchtype== 'Stack':
|
||||||
|
results=db.session.query(Book).join(Book.stacks).filter(Stack.stack_name.contains(query)).order_by(Book.title)
|
||||||
|
|
||||||
if searchtype== 'All':
|
if searchtype== 'All':
|
||||||
results=Book.query.whoosh_search(query).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)
|
||||||
|
|
||||||
if not results:
|
if results.count() == 0:
|
||||||
|
books = Book.query.filter(Book.file.like('potential.pdf'))
|
||||||
upload_form = UploadForm(title= query, author='')
|
upload_form = UploadForm(title= query, author='')
|
||||||
return render_template('red_link.html', form=upload_form, title=query)
|
return render_template('red_link.html', form=upload_form, title=query, books=books)
|
||||||
|
|
||||||
|
count = results.count()
|
||||||
|
whole = Book.query.count()
|
||||||
|
percentage = float(count / whole * 100)
|
||||||
|
fbooks = set(results)
|
||||||
|
books_all = allbooks - fbooks
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
|
newmsg = 'searched for: ' + search.search.data
|
||||||
|
socketio.emit('channel-' + str(1), {
|
||||||
|
'username': 'Search form',
|
||||||
|
'text': search.search.data,
|
||||||
|
'time': str(datetime.datetime.utcnow().strftime("%d.%m.%Y %H:%M"))}, broadcast=True)
|
||||||
|
# Save message
|
||||||
|
my_new_chat = Chat(message=newmsg)
|
||||||
|
db.session.add(my_new_chat)
|
||||||
|
try:
|
||||||
|
db.session.commit()
|
||||||
|
except:
|
||||||
|
db.session.rollback()
|
||||||
|
|
||||||
query = search.search.data
|
query = search.search.data
|
||||||
results = []
|
results = []
|
||||||
return redirect((url_for('search_results', searchtype=search.select.data, query=search.search.data)))
|
if viewby == '1':
|
||||||
|
print (view[-1])
|
||||||
|
return redirect((url_for('search_results', searchtype=search.select.data, query=search.search.data, viewby=viewby)))
|
||||||
|
else:
|
||||||
|
return redirect((url_for('search_results', searchtype=search.select.data, query=search.search.data, viewby=viewby)))
|
||||||
|
|
||||||
return render_template('results.html', form=search, books=results, books_all=random_order, searchtype=search.select.data, query=query)
|
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)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
## Search - autocomplete
|
|
||||||
autocomplete_suggestions = []
|
autocomplete_suggestions = []
|
||||||
autocomplete.load() #Train markov model once, for autocomplete in search
|
autocomplete.load()
|
||||||
|
|
||||||
@app.route('/autocomplete_suggestions', methods=['GET', 'POST'])
|
@app.route('/autocomplete_suggestions', methods=['GET', 'POST'])
|
||||||
def autocomplete_search():
|
def autocomplete_search():
|
||||||
@ -457,7 +596,6 @@ def autocomplete_search():
|
|||||||
|
|
||||||
return Response(json.dumps(autocomplete_suggestions), mimetype='application/json')
|
return Response(json.dumps(autocomplete_suggestions), mimetype='application/json')
|
||||||
|
|
||||||
|
|
||||||
## STACKS!
|
## STACKS!
|
||||||
|
|
||||||
@app.route('/add_to_stack/<int:id>', methods=['GET', 'POST'])
|
@app.route('/add_to_stack/<int:id>', methods=['GET', 'POST'])
|
||||||
@ -536,7 +674,7 @@ def import_csv():
|
|||||||
year_published = int(row['year_published'])
|
year_published = int(row['year_published'])
|
||||||
else:
|
else:
|
||||||
year_published = None;
|
year_published = None;
|
||||||
book = Book(row['title'], row['file'], cover, row['fileformat'], row['category'],year_published)
|
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.scapeX = float(row['scapeX'])
|
||||||
book.scapeY = float(row['scapeY'])
|
book.scapeY = float(row['scapeY'])
|
||||||
|
|
||||||
@ -555,7 +693,7 @@ def import_csv():
|
|||||||
return render_template('import_csv.html', numberadded=numberadded)
|
return render_template('import_csv.html', numberadded=numberadded)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/empty_catalogue', methods= ['POST','GET'])
|
@app.route('/empty_catalogue487352698237465', methods= ['POST','GET'])
|
||||||
def empty_catalogue():
|
def empty_catalogue():
|
||||||
meta = db.metadata
|
meta = db.metadata
|
||||||
for table in reversed(meta.sorted_tables):
|
for table in reversed(meta.sorted_tables):
|
||||||
@ -565,6 +703,7 @@ def empty_catalogue():
|
|||||||
db.create_all()
|
db.create_all()
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return "ALL CLEARED"
|
return "ALL CLEARED"
|
||||||
|
|
||||||
###
|
###
|
||||||
# The API
|
# The API
|
||||||
###
|
###
|
||||||
@ -648,7 +787,6 @@ def new_message(message):
|
|||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
socketio.run(app)
|
socketio.run(app)
|
||||||
#app.run(debug=True,host="0.0.0.0",port="8080")
|
#app.run(debug=True,host="0.0.0.0",port="8080")
|
||||||
|
@ -20,7 +20,7 @@ with open(args.csv) as f:
|
|||||||
print ('get_cover', fullpath, name)
|
print ('get_cover', fullpath, name)
|
||||||
cover = get_cover(fullpath, name)
|
cover = get_cover(fullpath, name)
|
||||||
|
|
||||||
book = Book(row['Title'], row['Filename'], cover, row['Format'], row['Category'], None)
|
book = Book(row['Title'], row['Filename'], cover, row['Format'], row['Category'], None, None, None, None, None, None, None)
|
||||||
|
|
||||||
db.session.add(book)
|
db.session.add(book)
|
||||||
authors = row['Author'].split(',')
|
authors = row['Author'].split(',')
|
||||||
@ -39,7 +39,7 @@ with open(args.csv) as f:
|
|||||||
if stack:
|
if stack:
|
||||||
b = db.session.query(Stack).filter_by(stack_name=stack).first()
|
b = db.session.query(Stack).filter_by(stack_name=stack).first()
|
||||||
if b == None:
|
if b == None:
|
||||||
b = Stack(stack_name=stack, stack_description=stack_description)
|
b = Stack(stack_name=stack, stack_description=None, stack_author=None)
|
||||||
|
|
||||||
db.session.add(b)
|
db.session.add(b)
|
||||||
book.stacks.append(b)
|
book.stacks.append(b)
|
||||||
|
BIN
whoosh/Book/MAIN_taxstcerlfadcokk.seg
Normal file
BIN
whoosh/Book/MAIN_taxstcerlfadcokk.seg
Normal file
Binary file not shown.
BIN
whoosh/Book/_MAIN_4.toc
Normal file
BIN
whoosh/Book/_MAIN_4.toc
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user