potential pdfs

This commit is contained in:
nberting 2018-06-09 15:41:21 +02:00
parent 72004d6c51
commit 34f736ef06
6 changed files with 95 additions and 553 deletions

View File

@ -97,6 +97,18 @@ class Stack(db.Model):
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()

View File

@ -19,8 +19,7 @@
<div class="form-group">Title: {{ form.title (size=34, 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">
Author(s): <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>
@ -34,14 +33,15 @@
{% endfor %} {% endfor %}
</table> </table>
</div> </div>
</div> </div>
<br> <br>
<div style="padding-left:10px;"> <div style="padding-left:10px;">
Category: {{ form.category(size=27, class="form-control") }} Category: {{ form.category(size=27, class="form-control") }}
<br> <br>
<br> <br>
Year published: {{ form.year_published(size=8, class="form-control") }}
<br>
<br>
{{ form.file }} {{ form.file }}
{{ form.upload }} {{ form.upload }}
{{ form.wish }} {{ form.wish }}

View File

@ -0,0 +1,50 @@
<!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>
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container" style="padding:20px;">
<h1 style='font-family: Archivo Narrow; text-align: center;'>A Potential Collection</h1>
<h3 style='font-family: Archivo Narrow; text-align: center;'>Every book ever requested by XPPL librarians: </h3>
<div style='font-family: Courier New; text-align: center;'>
<p> {% for pbook in pbooks %}{{ pbook.ptitle }} requested on: {{ pbook.time }}
</p>{% endfor %}
</div>
</body>
<br>
<div class="footer" style="padding-left: 40%">
<pre>
, ,
/////|
///// |
|~~~| |
|===| |
|x | |
| p | |
|p l| /
|===|/
'---'
</pre>
</div>
</html>

View File

@ -59,10 +59,12 @@
{% endfor %} {% endfor %}
</table> </table>
</div> </div>
</form>
</div> </div>
<div style="padding-left:10px;">
Category: {{ form.category(size=27, class="form-control") }}
<br> <br>
<div class="form-group">Category: {{ form.category(size=27, class="form-control") }}</div> <br>
Year published: {{ form.year_published(size=8, class="form-control") }}
<br> <br>
{{ form.file }} {{ form.file }}
{{ form.upload }} {{ form.upload }}

View File

@ -10,10 +10,11 @@ from flask import Flask, Response, render_template, request, redirect, url_for,
import json import json
from sqlalchemy.sql.expression import func, select from sqlalchemy.sql.expression import func, select
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 from app.models import Book, BookSchema, Author, AuthorSchema, Stack, StackSchema, UserIns, Chat, ChatSchema, Potential
from app.cover import get_cover from app.cover import get_cover
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
import autocomplete import autocomplete
@ -128,6 +129,15 @@ def remove_book_by_id(id):
flash("%s deleted from library" % (title)) flash("%s deleted from library" % (title))
return redirect(url_for('show_books')) return redirect(url_for('show_books'))
@app.route('/potential')
def htmlpdf():
paragraphs= ['test title']
template = 'app/templates/potential_pdf.html'
html_string = render_template('potential_pdf.html', paragraphs=paragraphs)
html = HTML(string=html_string)
html.write_pdf(target='app/uploads/potential2.pdf');
return render_template('potential_pdf.html', paragraphs=paragraphs)
@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()
@ -223,13 +233,20 @@ 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)
db.session.add(book) db.session.add(book)

View File

@ -1,539 +0,0 @@
"""
Flask Documentation: http://flask.pocoo.org/docs/
Jinja2 Documentation: http://jinja.pocoo.org/2/documentation/
Werkzeug Documentation: http://werkzeug.pocoo.org/documentation/
This file creates your application.
"""
from app import app, db, socketio, DOMAIN
from flask import Flask, Response, render_template, request, redirect, url_for, flash, send_from_directory, jsonify, abort
import json
from sqlalchemy.sql.expression import func, select
from app.forms import UploadForm, EditForm, SearchForm, ChatForm, StackForm, AddtoStackForm, EditStackForm
from app.models import Book, BookSchema, Author, AuthorSchema, Stack, StackSchema, UserIns, Chat, ChatSchema
from app.cover import get_cover
from os import environ
from flask_socketio import SocketIO, emit
import datetime
import time
import autocomplete
import sys
from csv import DictWriter
import io
import os
from werkzeug.utils import secure_filename
# import sqlite3
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'epub', 'chm', 'mobi'])
author_schema = AuthorSchema()
authors_schema = AuthorSchema(many=True)
book_schema = BookSchema()
books_schema = BookSchema(many=True)
stack_schema = StackSchema()
stacks_schema = StackSchema(many=True)
chat_schema = ChatSchema()
chats_schema = ChatSchema(many=True)
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
###
# Routing for your application.
###
@app.route('/', methods= ['POST','GET'])
def home():
chat_form = ChatForm()
chat_messages = db.session.query(Chat).all()
# if request.method == 'POST':
# if chat_form.validate_on_submit():
# message = chat_form.message.data
# msg = Chat(message)
# db.session.add(msg)
# db.session.commit()
return render_template('home.html',domain=DOMAIN,chat=chat_messages, channel = 1, username="librarian")
@app.route('/hello/<name>')
def hello(name):
return "Hello " + name
@app.route('/about/')
def about():
"""Render the website's about page."""
return render_template('about.html', name="Mary Jane")
@app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'],
filename)
@app.route('/uploads/cover/<filename>')
def uploaded_file_cover(filename):
return send_from_directory(app.config['UPLOAD_FOLDER_COVER'],
filename)
@app.route('/updates', methods=['POST', 'GET'])
def get_updates():
userin = UserIns.query.filter_by(title="lastViewed").first()
allbooks = db.session.query(Book).all()
id = len(allbooks)
latest_upload = allbooks[-1]
return "This is the XPPL ~ Library XPUB ~ Updates / / / / / / / Last viewed: " + userin.info + " / / / / / / / " + str(len(allbooks)) + " Books online "+ " / / / / / / / " + "Latest upload: " + latest_upload.title
@app.route('/scape', methods=['POST', 'GET'])
def scape():
if request.method == 'POST':
data = request.form
book = Book.query.get(data['id'])
print(book.scapeX)
book.scapeX = data['x']
book.scapeY = data['y']
db.session.commit()
books = db.session.query(Book).all() # or you could have used User.query.all()
return render_template('scape.html', books=books)
@app.route('/books_grid')
def show_books_grid():
books = db.session.query(Book).all() # or you could have used User.query.all()
return render_template('show_books_grid.html', books=books)
@app.route('/books/<int:id>')
def show_book_by_id(id):
book = Book.query.get(id)
userin = UserIns.query.filter_by(title="lastViewed").first()
if userin != None:
userin.info = book.title
db.session.commit()
else:
user_info = UserIns("lastViewed", book.title)
db.session.add(user_info)
db.session.commit()
if not book:
return render_template('red_link.html', id=id)
else:
return render_template('show_book_detail.html', book=book)
@app.route('/books/<int:id>/delete', methods=['POST', 'GET'])
def remove_book_by_id(id):
book_to_edit = Book.query.filter_by(id=id).first()
title = book_to_edit.title
Book.query.filter_by(id=id).delete()
#author_table = Author.query.filter_by(book_id=book_to_edit.id).delete()
db.session.commit()
flash("%s deleted from library" % (title))
return redirect(url_for('show_books'))
@app.route('/books/<int:id>/edit', methods=['POST', 'GET'])
def edit_book_by_id(id):
book_to_edit = Book.query.filter_by(id=id).first()
user_form = EditForm(title = book_to_edit.title, author =book_to_edit.authors, category = book_to_edit.category, year_published= book_to_edit.year_published)
if request.method == 'POST':
if user_form.validate_on_submit():
# on submit, check fields
title = user_form.title.data
input_authors = user_form.author.data
category = user_form.category.data
year_published = user_form.year_published.data
if year_published=="":
year_published = None
book = Book.query.filter_by(id=id).first()
book.title = title
book.category = category
book.year_published = year_published
#authors update
book.authors.clear()
for i, author in enumerate(input_authors):
author_name = author.get("author_name")
if author_name:
a = db.session.query(Author).filter_by(author_name=author_name).first()
if a == None:
a = Author(author_name=author_name)
db.session.add(a)
book.authors.append(a)
# 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):
filename = secure_filename(file.filename)
allbooks = db.session.query(Book).all()
id = book.id
new_filename = str(id) +"_"+ filename
fullpath = os.path.join(app.config['UPLOAD_FOLDER'], new_filename)
name, file_extension = os.path.splitext(new_filename)
file.save(fullpath)
book.cover = get_cover(fullpath, name)
book.file = new_filename
else:
flash('allowed file formats: %s' % ALLOWED_EXTENSIONS)
db.session.commit()
flash("%s updated" % (title))
return redirect(url_for('show_book_by_id', id=id))
return render_template('edit_book_detail.html', book=book_to_edit, form=user_form)
@app.route('/add-book', methods=['POST', 'GET'])
def add_book():
upload_form = UploadForm()
if request.method == 'POST':
if upload_form.validate_on_submit():
#get data from form
title = upload_form.title.data
authors = upload_form.author.data
category = upload_form.category.data
year_published = upload_form.year_published.data
if year_published=="":
year_published = None
#if upload with file
if upload_form.upload.data:
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
# submit a empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
allbooks = db.session.query(Book).all()
id = len(allbooks)+1
new_filename = str(id) +"_"+ filename
fullpath = os.path.join(app.config['UPLOAD_FOLDER'], new_filename)
name, file_extension = os.path.splitext(new_filename)
file.save(fullpath)
cover = get_cover(fullpath, name)
else:
flash('allowed file formats: %s' % ALLOWED_EXTENSIONS)
#if upload without file -> wishform, with potential PDF
if upload_form.wish.data:
#TO DO: make pdf generator
#file = open('app/uploads/potential.pdf')
#filename = 'potential.pdf'
#file_extension = '.pdf'
filename = ''
file_extension = ''
cover = ''
book = Book(title, filename, cover, file_extension, category,year_published)
db.session.add(book)
for author in authors:
author_name = author.get("author_name")
if author_name:
a = db.session.query(Author).filter_by(author_name=author_name).first()
if a == None:
a = Author(author_name=author_name)
db.session.add(a)
book.authors.append(a)
db.session.commit()
flash("%s added to the library" % (title))
return redirect(url_for('show_books'))
flash_errors(upload_form)
return render_template('add_book.html', form=upload_form)
# Flash errors from the form if validation fails
def flash_errors(form):
for field, errors in form.errors.items():
for error in errors:
flash(u"Error in the %s field - %s" % (
getattr(form, field).label.text,
error
))
#Authors
@app.route('/authors/<int:id>')
def show_author_by_id(id):
author = Author.query.get(id)
if not author:
abort (404)
else:
return render_template('show_author_detail.html', author=author)
@app.route('/authors/<int:id>/edit', methods=['POST', 'GET'])
def edit_author_by_id(id):
return "Ask the programmer."
##stacks
@app.route('/stacks')
def show_stacks():
stacks = db.session.query(Stack).all()
return render_template('show_stacks.html', stacks=stacks)
@app.route('/stacks/add_stack', methods=['POST', 'GET'])
def add_stack():
form = StackForm()
stacks = db.session.query(Stack).all()
if form.validate_on_submit():
stack_name = form.stack_name.data
stack_description = form.stack_description.data
stack = Stack(stack_name, stack_description)
if form.stack_name.data:
stack = Stack(stack_name, stack_description)
db.session.add(stack)
stacks = db.session.query(Stack).all()
return redirect(url_for('show_stacks'))
flash("%s stack created" % (stack_name))
return render_template('add_stack.html', stacks=stacks, form=form)
@app.route('/stacks/tab/<int:id>', methods=['POST', 'GET'])
def show_stack_in_tab(id):
return show_stack_by_id(id, is_tab=True)
@app.route('/stacks/<int:id>', methods=['POST', 'GET'])
def show_stack_by_id(id, is_tab=False):
stack = Stack.query.get(id)
if not stack:
abort (404)
else:
if is_tab == False:
return render_template('show_stack_detail.html', stack=stack)
else:
return render_template('show_stack_detail_tab.html', stack=stack)
@app.route('/stacks/<int:id>/delete', methods=['POST', 'GET'])
def remove_stack_by_id(id):
Stack.query.filter_by(id=id).delete()
db.session.commit()
return redirect(url_for('show_stacks'))
@app.route('/stacks/<int:id>/edit', methods=['POST', 'GET'])
def edit_stack_by_id(id):
stack = Stack.query.filter_by(id=id).first()
form = EditStackForm(edit_stack_name = stack.stack_name, edit_stack_description = stack.stack_description)
if request.method == 'POST':
if form.validate_on_submit():
stack_name = form.edit_stack_name.data
stack_description = form.edit_stack_description.data
stack.stack_name = stack_name
stack.stack_description = stack_description
db.session.commit()
return redirect(url_for('show_stack_by_id', id=id))
return render_template('edit_stack_detail.html', stack=stack, form=form)
#@app.route('/stacks/<int:stackid>/remove/<int:bookid>', methods=['POST', 'GET'])
#def remove_from_stack(bookid, stackid):
# import ipdb; ipdb.set_trace()
# book = Book.query.get(id)
# stack = Stack.query.get(id)
# stack = db.session.query(Stack).join(stack.books).filter_by(stackid=stackid)
# stack.books.delete(book)
# db.session.commit()
# return render_template('show_book_by_id.html', stackid=stack.id, bookid=book.id)
@app.route('/add_to_stack/<int:id>', methods=['GET', 'POST'])
def add_to_stack(id):
stacks = db.session.query(Stack).all()
add_form = AddtoStackForm(request.form)
add_form.select_stack.choices = [(stack.id, stack.stack_name) for stack in stacks]
if request.method == 'GET':
book = Book.query.get(id)
return render_template('add_to_stacks.html', id=id, stacks=stacks, book=book, add_form=add_form)
else:
stack = Stack.query.get(int(add_form.select_stack.data))
book = Book.query.get(id)
stack.books.append(book)
db.session.commit()
return render_template('show_stack_detail.html', stack=stack)
## search
@app.route('/books', methods= ['POST','GET'])
def show_books():
books = db.session.query(Book).all()
search = SearchForm(request.form)
if request.method == 'POST':
return redirect((url_for('search_results', searchtype=search.select.data, query=search.search.data)))
return render_template('show_books.html', books=books, form=search)
@app.route('/search/<searchtype>/<query>/', methods=['POST', 'GET'])
def search_results(searchtype, query):
search = SearchForm(request.form)
random_order=Book.query.order_by(func.random()).limit(10)
results=Book.query.filter(Book.title.contains(query))
if searchtype == 'Title':
results=Book.query.filter(Book.title.contains(query))
if searchtype == 'Category':
results=Book.query.filter(Book.category.contains(query))
if searchtype== 'Author':
results=db.session.query(Book).join(Book.authors).filter(Author.author_name.contains(query))
if searchtype== 'Stack':
results=db.session.query(Book).join(Book.stacks).filter(Stack.stack_name.contains(query))
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)))
if results.count() == 0:
upload_form = UploadForm(title= query, author='')
return render_template('red_link.html', form=upload_form, title=query)
if request.method == 'POST':
query = search.search.data
results = []
return redirect((url_for('search_results', searchtype=search.select.data, query=search.search.data)))
count = results.count()
whole = Book.query.count()
percentage = float(count / whole * 100)
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 = []
@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('/export/csv', methods=['GET'])
def export_csv ():
output = io.StringIO()
fieldnames = ['title', 'authors']
csv = DictWriter(output,fieldnames)
csv.writeheader()
# for i in range(10):
# csv.writerow({'ID': i, 'fruit': "Tomato"})
for book in Book.query.order_by("title"):
authors = ", ".join([x.author_name for x in book.authors])
csv.writerow({"title": book.title, "authors": authors})
resp = Response(output.getvalue(), mimetype="text/plain")
# resp.headers["Content-Disposition"] = "attachment;filename=export.csv"
return resp
###
# The API
###
@app.route('/api/books', methods=['GET'])
def get_books():
books = Book.query.all()
data = books_schema.dump(books)
#print(errors)
return jsonify({'books': data})
@app.route('/api/books/<int:id>', methods=['GET'])
def get_book_by_id(id):
book = Book.query.get(id)
data = book_schema.dump(book)
if not data:
return jsonify({"message": "Book could not be found."}), 400
else:
return jsonify({'book': data })
@app.route('/api/chats', methods=['GET'])
def get_chat():
chats = Chat.query.all()
data = chats_schema.dump(chats)
#print(errors)
return jsonify({'chat': data})
###
# The functions below should be applicable to all Flask apps.
###
@app.route('/<file_name>.txt')
def send_text_file(file_name):
"""Send your static text file."""
file_dot_text = file_name + '.txt'
return app.send_static_file(file_dot_text)
@app.after_request
def add_header(response):
"""
Add headers to both force latest IE rendering engine or Chrome Frame,
and also to cache the rendered page for 10 minutes.
"""
response.headers['X-UA-Compatible'] = 'IE=Edge,chrome=1'
response.headers['Cache-Control'] = 'public, max-age=600'
return response
@app.errorhandler(404)
def page_not_found(error):
"""Custom 404 page."""
return render_template('404.html'), 404
@socketio.on('new_message')
def new_message(message):
# Send message to alls users
print("new message")
emit('channel-' + str(message['channel']), {
'username': message['username'],
'text': message['text'],
'time': str(datetime.datetime.utcnow().strftime("%d.%m.%Y %H:%M"))
},
broadcast=True
)
# Save message
my_new_chat = Chat(
message=message['text']
)
db.session.add(my_new_chat)
try:
db.session.commit()
except:
db.session.rollback()
if __name__ == '__main__':
socketio.run(app)
#app.run(debug=True,host="0.0.0.0",port="8080")