Compare commits

..

No commits in common. 'new_light' and 'master' have entirely different histories.

1
.gitignore vendored

@ -9,4 +9,3 @@ pyrqlite/
whoosh/ whoosh/
sqlalchemy-rqlite/ sqlalchemy-rqlite/
rqlite* rqlite*
venv/

@ -1,49 +1,38 @@
# XPPL version alt # XPUB Library
Library to hold books / knowledge Library running on Flask and SQLight (maybe to be replaced with a python shelve)
## TO DOs ## Installation
- [x] fix adding stacks
- [x] update requirements
- [ ] generate new requirements.txt and installation process?
- [ ] fix stacks layout
- [ ] remove autocomplete? and training at the start of app
- [ ] update layout navigation
Install the required dependencies:
$ pip3 install -r requirements.txt
## Installation
sudo apt install python3-virtualenv Initialise database
sudo virtualenv venv
source venv/bin/activate
sudo chmod -R 777 XPPL/ $ bash init_db.sh
pip3 install flask
pip3 install flask_sqlalchemy
pip3 install marshmallow
pip3 install flask_socketio
pip3 install python-dotenv
pip3 install flask_weasyprint
pip3 install flask_wtf
pip3 install wand
pip3 install PyPDF2
pip3 install requests
pip3 install autocomplete
sudo apt-get install libpangocairo-1.0-0
sudo apt-get install libmagickwand-dev
bash init_db.sh ### Install rqlite
#### Linux
To download and start rqlite on Linux, execute the following in a shell.
Install the required dependencies: curl -L https://github.com/rqlite/rqlite/releases/download/v4.3.0/rqlite-v4.3.0-linux-amd64.tar.gz -o rqlite-v4.3.0-linux-amd64.tar.gz
tar xvfz rqlite-v4.3.0-linux-amd64.tar.gz
cd rqlite-v4.3.0-linux-amd64
./rqlited ~/node.1
$ pip3 install -r requirements.txt
#### OSX
To download and start rqlite on OSX, execute the following in a shell.
curl -L https://github.com/rqlite/rqlite/releases/download/v4.3.0/rqlite-v4.3.0-darwin-amd64.tar.gz -o rqlite-v4.3.0-darwin-amd64.tar.gz
tar xvfz rqlite-v4.3.0-darwin-amd64.tar.gz
cd rqlite-v4.3.0-darwin-amd64
./rqlited ~/node.1
Initialise database / Why is this needed again, could be checked in flask?
$ bash init_db.sh
### Further install notes (bugs) ### Further install notes (bugs)
@ -51,23 +40,36 @@ Initialise database / Why is this needed again, could be checked in flask?
* create the covers folder inside the uploadsfolder * create the covers folder inside the uploadsfolder
* don't forget to chmod the uploads and coverfolder ;-) * don't forget to chmod the uploads and coverfolder ;-)
* For Mac users -> brew install imagemagick@6 in order to install wand (should not be relevant for debian server install) * For Mac users -> brew install imagemagick@6 in order to install wand
For those on mac and using homebrew, it seems like Wand doesn't support imagemagick 7 yet as mentioned in other answers.
There's a new brew formula for Imagemagick 6 which can be used to install the older version in the meanwhile:
`brew install imagemagick@6`
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
## Run the program ## Run the program
Initialize rqlite database on one terminal (from rqlite install directory)
$ ./rqlited ~.node
Run the script in another terminal (from XPPL directory): Run the script in another terminal (from XPPL directory):
python3 run.py python3 run.py
## Deploy on server
(this will be added soon)
## REST API ## API
Has currently 2 entrypoints: Has currently 2 entrypoints:

@ -23,11 +23,11 @@ app = Flask(__name__)
app.config['SECRET_KEY'] = 'super secret key' app.config['SECRET_KEY'] = 'super secret key'
#app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/mydatabase.db' #app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/mydatabase.db'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
#app.config['SQLALCHEMY_DATABASE_URI'] = 'rqlite+pyrqlite://localhost:4001/' 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
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)
light = not os.path.isdir(UPLOAD_FOLDER) light = not os.path.isdir(UPLOAD_FOLDER)
DOMAIN = environ.get('DOMAIN') DOMAIN = environ.get('DOMAIN')

@ -5,7 +5,7 @@ from wtforms import FieldList
from wtforms import Form as NoCsrfForm from wtforms import Form as NoCsrfForm
from wtforms.fields import StringField, FormField, SubmitField, SelectField, RadioField 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 import DecimalRangeField from wtforms.fields.html5 import DecimalRangeField
# - - - Forms - - - # - - - Forms - - -
@ -80,6 +80,6 @@ class SearchForm(FlaskForm):
('Outliers', 'Outliers')] ('Outliers', 'Outliers')]
select = SelectField('', choices=choices, default='All') select = SelectField('', choices=choices, default='All')
search = StringField('', validators=[InputRequired()]) search = StringField('', validators=[InputRequired()])
# grid = SubmitField('Grid') grid = SubmitField('Grid')
# listview = SubmitField('List') listview = SubmitField('List')
randomize = SubmitField('Order differently') randomize = SubmitField('Order differently')

@ -1,7 +1,8 @@
from app import db from app import db
from marshmallow import Schema, fields, ValidationError, pre_load from marshmallow import Schema, fields, ValidationError, pre_load
import datetime import datetime
from sqlalchemy import Column, DateTime from sqlalchemy import Column, Integer, DateTime
import flask_whooshalchemyplus
authors = db.Table('books_authors', authors = db.Table('books_authors',

@ -1,23 +1,22 @@
@import url("../fonts/fonts_style.css"); @import url("../fonts/fonts_style.css");
*{ *{
font-family: "Archivo Narrow", Helvetica, sans-serif; font-family: "Archivo Narrow";
}
body{
background-color: #f1f1f1;
} }
p{ p{
font-size: 20px; font-size: 20px;
} }
a{ a{
text-decoration: underline; text-decoration: underline;
color: black; color: black;
} }
a:hover{ a:hover{
text-decoration: underline; text-decoration: underline;
color: #0000FF; color: #0000FF;
} }
@ -292,8 +291,7 @@ font-size: 12px;
left:0; left:0;
position: fixed; position: fixed;
font-size: 18px; font-size: 18px;
background-color: rgb(0, 3, 170); background-color: yellow;
color: white;
} }
#annotindication{ #annotindication{

@ -50,8 +50,7 @@
<script type="text/javascript" src="{{ url_for("static", filename="js/jquery.tablesorter.js") }}"></script> <script type="text/javascript" src="{{ url_for("static", filename="js/jquery.tablesorter.js") }}"></script>
<script src="{{ url_for("static", filename="js/app.js") }}"></script> <script src="{{ url_for("static", filename="js/app.js") }}"></script>
<!-- <script src="{{ url_for("static", filename="js/vendor/socket.io.slim.js") }}"></script> --> <script src="{{ url_for("static", filename="js/vendor/socket.io.slim.js") }}"></script>
<script src="https://cdn.socket.io/4.4.0/socket.io.min.js" integrity="sha384-1fOn6VtTq3PWwfsOrk45LnYcGosJwzMHv+Xh/Jx5303FVOXzEnw0EpLv30mtjmlj" crossorigin="anonymous"></script>
<script src="{{ url_for("static", filename="js/vendor/vue.min.js") }}"></script> <script src="{{ url_for("static", filename="js/vendor/vue.min.js") }}"></script>
<script> <script>

@ -2,14 +2,13 @@
<ul> <ul>
<li><a href="{{ url_for('home') }}">Home</a></li> <li><a href="{{ url_for('home') }}">Home</a></li>
<li><a href="{{ url_for('show_books') }}">Catalogue</a></li> <li><a href="{{ url_for('show_books') }}">Catalogue</a></li>
<li><a href="{{ url_for('show_stacks') }}">Stacks</a></li>
{%if light%} {%if light%}
{%else%} {%else%}
<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('show_stacks') }}">Stacks</a></li>
<li><a href="{{ url_for ('add_stack') }}">Add Stack</a></li> <li><a href="{{ url_for ('add_stack') }}">Add Stack</a></li>
{%endif%} {%endif%}
<!-- <li><a href="{{ url_for('annotations') }}">Annotations</a></li> --> <li><a href="{{ url_for('annotations') }}">Annotations</a></li>
<li><a href="{{ url_for('about') }}">About</a></li> <li><a href="{{ url_for('about') }}">About</a></li>
{%if light%} {%if light%}
{%else%} {%else%}

@ -40,7 +40,7 @@ fill: yellow;
<body> <body>
<script> <script>
console.log("hello");
// d3.json("/api/books").then(function(data){ // d3.json("/api/books").then(function(data){
// console.log("loaded"); // console.log("loaded");
// console.log(data) // console.log(data)

@ -8,8 +8,10 @@
<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" @click="sendMessage" class="button is-info" >find</button> <button type="submit" @click="sendMessage" class="button is-info" >browse</button>
<p><br> <p><br>
{{ form.grid(style="font-size:20px")}}{{ form.listview(style="font-size:20px")}}</p>
</form> </form>
<h1 class="page-header">All Books</h1> <h1 class="page-header">All Books</h1>

@ -33,7 +33,7 @@ import sys
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
# import sqlite3 # import sqlite3
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'epub', 'chm', 'mobi', "png", "mp3"]) ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'epub', 'chm', 'mobi'])
author_schema = AuthorSchema() author_schema = AuthorSchema()
authors_schema = AuthorSchema(many=True) authors_schema = AuthorSchema(many=True)
@ -123,6 +123,17 @@ def annotations_pdf():
html = render_template(('annotations.html'), annot=annot, light=light) html = render_template(('annotations.html'), annot=annot, light=light)
return render_pdf(HTML(string=html)) return render_pdf(HTML(string=html))
# @app.route('/myannotations.pdf')
# def myannotations_pdf():
# books = db.session.query(Book).all()
# name=str(request.args.get('query'))
# annot = get_annotations()
# res = get_annot_results(annot,name)
# # Make a PDF straight from HTML in a string.
# html = render_template('results_annot.html', name=name, annot=annot, res=res, books=books)
# return render_pdf(HTML(string=html))
@app.route('/viewpdf/<filename>') @app.route('/viewpdf/<filename>')
def viewtestfile1_file(filename): def viewtestfile1_file(filename):
return redirect("/static/viewer/web/viewer.html?file=%2Fuploads%2F"+urlquote(filename)) return redirect("/static/viewer/web/viewer.html?file=%2Fuploads%2F"+urlquote(filename))
@ -435,8 +446,6 @@ def edit_author_by_id(id):
@app.route('/stacks') @app.route('/stacks')
def show_stacks(): def show_stacks():
stacks = db.session.query(Stack).all() stacks = db.session.query(Stack).all()
print("stacks looooooook")
print(stacks)
return render_template('show_stacks.html', stacks=stacks, light=light) return render_template('show_stacks.html', stacks=stacks, light=light)
@app.route('/stacks/add_stack', methods=['POST', 'GET']) @app.route('/stacks/add_stack', methods=['POST', 'GET'])
@ -453,7 +462,6 @@ def add_stack():
if form.stack_name.data: if form.stack_name.data:
stack = Stack(stack_name, stack_description, stack_author) stack = Stack(stack_name, stack_description, stack_author)
db.session.add(stack) db.session.add(stack)
db.session.commit()
stacks = db.session.query(Stack).all() stacks = db.session.query(Stack).all()
return redirect(url_for('show_stacks')) return redirect(url_for('show_stacks'))
flash("%s stack created" % (stack_name)) flash("%s stack created" % (stack_name))
@ -553,15 +561,15 @@ def show_books():
view.append('1') view.append('1')
viewby = '1' viewby = '1'
# if search.grid.data: if search.grid.data:
# viewby = '2' viewby = '2'
# view.append('2') view.append('2')
# return render_template ('show_books_grid.html', books=books, form=search, light=light) return render_template ('show_books_grid.html', books=books, form=search, light=light)
# if search.listview.data: if search.listview.data:
# viewby = '1' viewby = '1'
# view.append('1') view.append('1')
# return render_template ('show_books.html', books=books, form=search, light=light) return render_template ('show_books.html', books=books, form=search, light=light)
if request.method == 'POST': if request.method == 'POST':
newmsg = 'searched for: ' + search.search.data newmsg = 'searched for: ' + search.search.data

@ -1,41 +1,26 @@
autocomplete==0.0.104 appdirs==1.4.0
bidict==0.21.4 click==6.7
bottle==0.12.19 Flask==0.12
Brotli==1.0.9 Flask-SQLAlchemy==2.1
certifi==2021.10.8 Flask-WTF==0.14.2
cffi==1.15.0 gunicorn==19.6.0
charset-normalizer==2.0.8 itsdangerous==0.24
click==8.0.3 Jinja2==2.9.4
cssselect2==0.4.1 MarkupSafe==0.23
Flask==2.0.2 packaging==16.8
Flask-SocketIO==5.1.1 pyparsing==2.1.10
Flask-SQLAlchemy==2.5.1 six==1.10.0
Flask-WeasyPrint==0.6 SQLAlchemy==1.1.5
Flask-WTF==1.0.0 Werkzeug==0.11.15
fonttools==4.28.2 WTForms==2.1
greenlet==1.1.2 flask-marshmallow==0.9.0
html5lib==1.1 Wand==0.4.4
idna==3.3
itsdangerous==2.0.1
Jinja2==3.0.3
MarkupSafe==2.0.1
marshmallow==3.14.1
Pillow==8.4.0
pycparser==2.21
pydyf==0.1.2
PyPDF2==1.26.0 PyPDF2==1.26.0
pyphen==0.11.0 flask-socketio==2.9.2
python-dotenv==0.19.2 flask-whooshalchemyplus==0.7.5
python-engineio==4.3.0 python-dotenv==0.7.1
python-socketio==5.5.0 autocomplete==0.0.104
requests==2.26.0 git+https://github.com/rqlite/pyrqlite.git
six==1.16.0 git+https://github.com/rqlite/sqlalchemy-rqlite.git
SQLAlchemy==1.4.27 git+https://github.com/Kozea/Flask-WeasyPrint.git
tinycss2==1.1.1 requests=2.20.1
urllib3==1.26.7
Wand==0.6.7
weasyprint==53.4
webencodings==0.5.1
Werkzeug==2.0.2
WTForms==3.0.0
zopfli==0.1.9

Loading…
Cancel
Save