Merge branch 'stack_stuff' of git.xpub.nl:/var/www/git.xpub.nl/repos/xpub-lib into stack_stuff

master
Alice 7 years ago
commit 3ffb42280f

@ -3,7 +3,7 @@ from wtforms import StringField, FileField, validators
from wtforms.validators import InputRequired, DataRequired
from wtforms import FieldList
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
# - - - Forms - - -
@ -49,9 +49,12 @@ class SearchForm(FlaskForm):
('Author', 'Author'),
('Category', 'Category'),
('Stack', 'Stack')]
select = SelectField('', choices=choices)
select = SelectField('', choices=choices, default='All')
search = StringField('', validators=[InputRequired()])
grid = SubmitField('Grid')
listview = SubmitField('List')
randomize = SubmitField('Order differently')

@ -84,7 +84,6 @@ class Chat(db.Model):
self.message = message
self.time = datetime.datetime.utcnow()
class Stack(db.Model):
__tablename__ = 'stacks'
id = db.Column(db.Integer, primary_key = True)
@ -125,7 +124,6 @@ class BookSchema(Schema):
stacks = fields.Nested(StackSchema, many=True)
def must_not_be_blank(data):
if not data:
raise ValidationError('You forgot to write stuff.')

@ -24,7 +24,7 @@ float: left;
display: block;
color: black;
text-align: center;
padding: 14px 16px;
padding: 14px 18px;
font-size: 18px;
text-decoration: none;
}
@ -41,7 +41,7 @@ font-style: italic;
}
.container{
padding: 0px 8px;
padding: 0px 10px;
}
@ -139,7 +139,7 @@ font-size: 18px;
padding:6px 15px;
left:0px;
border:0px solid #dbdbdb;
background-color: grey;
background-color: #686d72;
color:#fafafa;
}
@ -225,7 +225,7 @@ div.marquee > div.marquee-text {
padding: 10px;
margin: 0px;
height: 100%;
background-color: #551A8B;
background-color: #b4b9be;
overflow-y: scroll;
overflow-x: hidden;
color: white;
@ -262,7 +262,7 @@ z-index: 100000;
margin:0px!important;
padding:0px!important;
height: 40px;
font-size: 20px;
font-size: 16px;
word-wrap: break-word;
word-break: break-all;
float: left;
@ -287,7 +287,7 @@ box-sizing: border-box;
margin-top: 20px;
}
.messages .msg{
font-size: 30px;
font-size: 24px;
margin: 0px;
margin-top: -15px;
margin-bottom: 10px;

@ -16,10 +16,10 @@
{% endwith %}
<form method="POST" action="{{ url_for('add_book') }}" enctype=multipart/form-data>
{{ 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>
<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>
<table>
<tr>
@ -28,20 +28,24 @@
</tr>
{% for author in form.author %}
<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>
</tr>
{% endfor %}
</table>
</div>
</form>
</div>
<br>
<div class="form-group">{{ form.category.label }} {{ form.category(size=20, class="form-control") }}</div>
<div sclass="form-group" style="padding-left:10px;">Category: {{ form.category(size=27, class="form-control") }}
<br>
<div class="form-group">{{ form.year_published.label }} {{ form.year_published(size=4, class="form-control") }}</div>
<br>
{{ form.file }}
{{ form.upload }}
{{ form.wish }}
</div>
</form>
</div>

@ -1,18 +1,14 @@
{% extends "base.html" %}
{% block title %}Red link page{% endblock %}
{% block css %}
<style type="text/css">
body{
padding-top: 40px;
}
h1, p{
text-align:center;
text-align:left;
}
h1{
font-size:44px;
margin:75px 0 50px;
margin:40px 0 30px;
}
p{
font-size:14px;
@ -21,16 +17,10 @@
</style>
{% endblock %}
{% block header %}{% endblock %}
{% block main %}
<h1>We don't have any results for: {{ title }}</h1>
<p><a href="{{ url_for('add_book') }}">upload</a>?</p>
<p><a href="{{ url_for('home') }}">go back home</a>?</p>
<h1>Nothing in the library yet with: {{ title }}</h1>
<br>
<div class="container">
<h1 class="page-header">Add Book</h1>
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="alert alert-danger">
@ -42,12 +32,19 @@
</div>
{% endif %}
{% 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 potential book:</h2>
<form method="POST" action="{{ url_for('add_book') }}" enctype=multipart/form-data>
{{ 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>
<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>
<table>
<tr>
@ -56,17 +53,21 @@
</tr>
{% for author in form.author %}
<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>
</tr>
{% endfor %}
</table>
</div>
</form>
</div>
<br>
<div class="form-group">Category: {{ form.category(size=27, class="form-control") }}</div>
<br>
<div class="form-group">{{ form.category.label }} {{ form.category(size=20, class="form-control") }}</div>
{{ form.file }}
{{ form.upload }}
{{ form.wish }}
</form>
<p><a href="{{ url_for('home') }}">go back home</a>?</p>
</div>
{% endblock %}

@ -33,7 +33,7 @@
<table class="library_table" id="table" style="width:100%">
<tr id="header">
<th>Cover</th>
<th width="70px;">Cover</th>
<th>Title</th>
<th width="400px;">Author</th>
<th width="100px;">Filetype</th>
@ -45,7 +45,7 @@
{% for book in books %}
<tr>
<td style= "padding: 5px;">
<img class="no_cover" id="{{ book.title }}" src="/uploads/cover/{{ book.cover }}" width="80" onerror="if (this.src != '//uploads/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';"></td>
<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> {% for author in book.authors %}
@ -75,7 +75,7 @@
<table class="library_table" id="table" style="width:100%">
<tr id="header">
<th>Cover</th>
<th width="70px;">Cover</th>
<th>Title</th>
<th width="400px;">Author</th>
<th width="100px;">Filetype</th>

@ -36,7 +36,7 @@
<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="100%" onerror="if (this.src != '//uploads/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';"></a>
<p>
<tbody>

@ -2,10 +2,10 @@
{% block main %}
<div class="container">
<h1 class="header">{{ book.title }}</h1>
<img class="no_cover" id="{{ book.title }}" src="../uploads/cover/{{ book.cover }}" width="150" onerror="if (this.src != '../uploads/cover/{{ book.cover }}') this.src = '../static/img/default_cover.gif';">
<img class="no_cover" id="{{ book.title }}" src="../uploads/cover/{{ book.cover }}" width="180" onerror="if (this.src != '../uploads/cover/{{ book.cover }}') this.src = '../static/img/default_cover.gif';">
<p>Year published: {{ book.year_published }}</p>
<p>Author(s): <ul>{% for author in book.authors %}
<li><a href="{{url_for('show_author_by_id', id=author.id)}}">{{ author.author_name }}</a> </li>
@ -13,9 +13,8 @@
{% endfor %}</ul></p>
<p>Category: {{ book.category }}</p>
<p>Year published: {{ book.year_published }}</p>
<p>Stack(s): <ul>{% for stack in book.stacks %}
<p>Included in stack(s): <ul>{% for stack in book.stacks %}
<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></p>

@ -7,7 +7,8 @@
<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>
<button type="submit" @click="sendMessage" class="button is-info" >browse</button>
<p><br>
{{ form.grid(style="font-size:20px")}}{{ form.listview(style="font-size:20px")}}</p>
</form>
@ -28,7 +29,7 @@
<table class="library_table" id="table" style="width:100%">
<thead>
<tr id="header">
<th>Cover</th>
<th width="70px;">Cover</th>
<th>Title</th>
<th width="400px;">Author</th>
<th width="100px;">Filetype</th>
@ -38,11 +39,11 @@
</tr>
</thead>
<tbody>
{% for book in books|sort(attribute='title', reverse = False) %}
{% for book in books %}
<tr>
<td style= "padding: 5px;">
<img class="no_cover" id="{{ book.title }}" src="/uploads/cover/{{ book.cover }}" width="80" onerror="if (this.src != '//uploads/cover/{{ book.cover }}') this.src = '/static/img/default_cover.gif';">
<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>

@ -13,9 +13,23 @@
</form>
</div>
<h1 class="page-header">All Books</h1>
{% 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">
{% for book in books|sort(attribute='title', reverse = False) %}
{% for book in books %}
<div class="gridbox">

@ -45,6 +45,7 @@ def allowed_file(filename):
def home():
chat_form = ChatForm()
chat_messages = db.session.query(Chat).all()
username = 'librarian'
# if request.method == 'POST':
# if chat_form.validate_on_submit():
@ -53,7 +54,7 @@ def home():
# db.session.add(msg)
# db.session.commit()
return render_template('home.html',domain=DOMAIN,chat=chat_messages, channel = 1, username="librarian")
return render_template('home.html',domain=DOMAIN,chat=chat_messages, channel = 1, username=username)
@app.route('/hello/<name>')
def hello(name):
@ -348,45 +349,72 @@ def remove_from_stack(bookid, stackid):
## search
view = ['1']
@app.route('/books', methods= ['POST','GET'])
def show_books():
books = db.session.query(Book).all()
books = db.session.query(Book).order_by(Book.title)
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':
return redirect((url_for('search_results', searchtype=search.select.data, query=search.search.data)))
newmsg = 'searched for: ' + search.search.data
# message = search.search.data
# newmessage = Chat(message)
# db.session.add(newmessage)
# db.session.commit()
# Send search to socket chat
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)
@app.route('/search/<searchtype>/<query>/', methods=['POST', 'GET'])
def search_results(searchtype, query):
@app.route('/search/<searchtype>/<viewby>/<query>', methods=['POST', 'GET'])
def search_results(searchtype, query, viewby):
search = SearchForm(request.form, search=query)
random_order=Book.query.order_by(func.random()).limit(14)
results=Book.query.filter(Book.title.contains(query))
results=Book.query.filter(Book.title.contains(query)).order_by(Book.title)
viewby = view[-1]
if searchtype == 'Title':
results=Book.query.filter(Book.title.contains(query))
results=Book.query.filter(Book.title.contains(query)).order_by(Book.title)
if searchtype == 'Category':
results=Book.query.filter(Book.category.contains(query))
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))
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))
results=db.session.query(Book).join(Book.stacks).filter(Stack.stack_name.contains(query)).order_by(Book.title)
if searchtype== 'All':
# results=Book.query.whoosh_search(query)
results=Book.query.filter(Book.title.contains(query))
results=results.union(Book.query.filter(Book.category.contains(query)))
results=results.union(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_name.contains(query))).order_by(Book.title)
if results.count() == 0:
upload_form = UploadForm(title= query, author='')
@ -397,40 +425,63 @@ def search_results(searchtype, query):
percentage = float(count / whole * 100)
if search.listview.data:
view.append('1')
return render_template('results.html', books=results, form=search, query=query, books_all=random_order, 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=random_order, searchtype=search.select.data, count = count, whole = whole, percentage = percentage)
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
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)))
if viewby == '2':
return render_template('results_grid.html', form=search, books=results, books_all=random_order, searchtype=search.select.data, query=query, count = count, whole = whole, percentage = percentage)
else:
return render_template('results.html', form=search, books=results, books_all=random_order, searchtype=search.select.data, query=query, count = count, whole = whole, percentage = percentage)
## Search - autocomplete
autocomplete_suggestions = []
# ## Search - autocomplete
# autocomplete_suggestions = []
@app.route('/autocomplete_suggestions', methods=['GET', 'POST'])
def test1():
if request.method == 'POST':
autocomplete.load()
query = request.form['search']
query_tokenized = query.lower().split()
print(query_tokenized)
word_1 = query_tokenized[-2]
word_2 = query_tokenized[-1]
#print(word_1)
autocomplete_output = autocomplete.predict(word_1 , word_2)
autocomplete_suggestions.clear()
for suggestion, score in autocomplete_output:
autocomplete_suggestions.append(suggestion)
print(autocomplete_suggestions)
return Response(json.dumps(autocomplete_suggestions), mimetype='application/json')
# @app.route('/autocomplete_suggestions', methods=['GET', 'POST'])
# def test1():
# if request.method == 'POST':
# autocomplete.load()
# query = request.form['search']
# query_tokenized = query.lower().split()
# print(query_tokenized)
# word_1 = query_tokenized[-2]
# word_2 = query_tokenized[-1]
# #print(word_1)
# autocomplete_output = autocomplete.predict(word_1 , word_2)
# autocomplete_suggestions.clear()
# for suggestion, score in autocomplete_output:
# autocomplete_suggestions.append(suggestion)
# print(autocomplete_suggestions)
# return Response(json.dumps(autocomplete_suggestions), mimetype='application/json')
@app.route('/add_to_stack/<int:id>', methods=['GET', 'POST'])
def add_to_stack(id):
@ -542,7 +593,6 @@ def new_message(message):
db.session.rollback()
if __name__ == '__main__':
socketio.run(app)
#app.run(debug=True,host="0.0.0.0",port="8080")

@ -1,4 +1,4 @@
#! /usr/bin/env python
from app import app, socketio
socketio.run(app)
socketio.run(app, port=8080)
#app.run(debug=True,host="0.0.0.0",port=8080)

Loading…
Cancel
Save