fix conflicts xpplanot again
This commit is contained in:
commit
6205fc7272
@ -36,4 +36,3 @@ socketio = SocketIO(app)
|
|||||||
app.config.from_object(__name__)
|
app.config.from_object(__name__)
|
||||||
from app import views
|
from app import views
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ def get_cover(file_path, filename):
|
|||||||
big_filename = "app/uploads/cover/"+page["filename"] + "_cover.png"
|
big_filename = "app/uploads/cover/"+page["filename"] + "_cover.png"
|
||||||
small_filename = "app/uploads/cover/"+page["filename"] + "cover_small" + ".png"
|
small_filename = "app/uploads/cover/"+page["filename"] + "cover_small" + ".png"
|
||||||
|
|
||||||
img = pdf_page_to_png(src_pdf, pagenum = page["pagenum"], resolution = 300)
|
img = pdf_page_to_png(src_pdf, pagenum = page["pagenum"], resolution = 200)
|
||||||
img.save(filename = big_filename)
|
img.save(filename = big_filename)
|
||||||
|
|
||||||
# Ensmallen
|
# Ensmallen
|
||||||
|
23
app/extractText.py
Normal file
23
app/extractText.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import PyPDF2
|
||||||
|
|
||||||
|
|
||||||
|
def get_text(file_path, filename):
|
||||||
|
read_pdf =file_path
|
||||||
|
|
||||||
|
with open(read_pdf,'rb') as pdf_file, open("app/uploads/"+filename+'.txt', 'w') as text_file:
|
||||||
|
read_pdf = PyPDF2.PdfFileReader(pdf_file)
|
||||||
|
number_of_pages = read_pdf.getNumPages()
|
||||||
|
for page_number in range(number_of_pages): # use xrange in Py2
|
||||||
|
page = read_pdf.getPage(page_number)
|
||||||
|
page_content = page.extractText()
|
||||||
|
text_file.write(page_content)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def extract_text(file_path, filename):
|
||||||
|
try:
|
||||||
|
get_text(file_path, filename)
|
||||||
|
except:
|
||||||
|
with open(filename+'.txt', 'w') as text_file:
|
||||||
|
page_content = ""
|
||||||
|
text_file.write(page_content)
|
@ -15,6 +15,11 @@ stacks = db.Table('books_stacks',
|
|||||||
db.Column('stack_id', db.Integer, db.ForeignKey('stacks.id'), primary_key=True)
|
db.Column('stack_id', db.Integer, db.ForeignKey('stacks.id'), primary_key=True)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
instances = db.Table('books_instances',
|
||||||
|
db.Column('book_id', db.Integer, db.ForeignKey('books.id'), primary_key=True),
|
||||||
|
db.Column('instance_id', db.Integer, db.ForeignKey('instances.id'), primary_key=True)
|
||||||
|
)
|
||||||
|
|
||||||
class Book(db.Model):
|
class Book(db.Model):
|
||||||
__tablename__ = 'books'
|
__tablename__ = 'books'
|
||||||
|
|
||||||
@ -26,10 +31,14 @@ class Book(db.Model):
|
|||||||
category = db.Column(db.String(255))
|
category = db.Column(db.String(255))
|
||||||
year_published = db.Column(db.Numeric(4,0))
|
year_published = db.Column(db.Numeric(4,0))
|
||||||
description = db.Column(db.String(2500))
|
description = db.Column(db.String(2500))
|
||||||
|
html = db.Column(db.String(255))
|
||||||
|
downloads = db.Column(db.Numeric(100,0))
|
||||||
authors = db.relationship('Author', secondary=authors,cascade="delete", lazy='subquery',
|
authors = db.relationship('Author', secondary=authors,cascade="delete", lazy='subquery',
|
||||||
backref=db.backref('books', lazy=True),passive_deletes=True)
|
backref=db.backref('books', lazy=True),passive_deletes=True)
|
||||||
stacks = db.relationship('Stack', secondary=stacks, lazy='subquery',
|
stacks = db.relationship('Stack', secondary=stacks, lazy='subquery',
|
||||||
backref=db.backref('books', lazy=True))
|
backref=db.backref('books', lazy=True))
|
||||||
|
instances = db.relationship('Instance', secondary=instances, lazy='subquery',
|
||||||
|
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))
|
message = db.Column(db.String(1000))
|
||||||
@ -47,6 +56,7 @@ class Book(db.Model):
|
|||||||
self.fileformat = fileformat
|
self.fileformat = fileformat
|
||||||
self.category = category
|
self.category = category
|
||||||
self.year_published = year_published
|
self.year_published = year_published
|
||||||
|
self.download = None
|
||||||
self.scapeX = 0
|
self.scapeX = 0
|
||||||
self.scapeY = 0
|
self.scapeY = 0
|
||||||
self.message = message
|
self.message = message
|
||||||
@ -73,6 +83,19 @@ class Author(db.Model):
|
|||||||
def __init__(self, author_name):
|
def __init__(self, author_name):
|
||||||
self.author_name = author_name
|
self.author_name = author_name
|
||||||
|
|
||||||
|
class Instance(db.Model):
|
||||||
|
__tablename__ = 'instances'
|
||||||
|
|
||||||
|
id = db.Column(db.Integer(), primary_key=True)
|
||||||
|
name = db.Column(db.String(50))
|
||||||
|
ip = db.Column(db.String(50))
|
||||||
|
action = db.Column(db.String(50))
|
||||||
|
|
||||||
|
def __init__(self, ip, action):
|
||||||
|
self.name = ip
|
||||||
|
self.ip = ip
|
||||||
|
self.action = action
|
||||||
|
|
||||||
|
|
||||||
class UserIns(db.Model):
|
class UserIns(db.Model):
|
||||||
__tablename__ = 'userins'
|
__tablename__ = 'userins'
|
||||||
|
@ -199,6 +199,7 @@ font-size: 12px;
|
|||||||
|
|
||||||
.ui-tabs-vertical { width: 100em; border-top: 0;}
|
.ui-tabs-vertical { width: 100em; border-top: 0;}
|
||||||
<<<<<<< HEAD
|
<<<<<<< HEAD
|
||||||
|
<<<<<<< HEAD
|
||||||
.ui-tabs-vertical .ui-tabs-nav { padding: .2em .2em .2em .2em; float: left; width: 15em; }
|
.ui-tabs-vertical .ui-tabs-nav { padding: .2em .2em .2em .2em; float: left; width: 15em; }
|
||||||
.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 li { clear: left; width: 100%; border-bottom-width: 0 !important; border-right-width: 0 !important; margin: 0 -1px .2em 0; }
|
||||||
=======
|
=======
|
||||||
@ -206,6 +207,11 @@ font-size: 12px;
|
|||||||
.ui-tabs-vertical .ui-tabs-nav { padding: .2em .2em .2em .2em; float: left; width: 15em; -webkit-appearance: none;}
|
.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 { clear: left; width: 100%; border-bottom-width: 0 !important; border-right-width: 0 !important; margin: 0 -1px .2em 0; list-style-type: none; }
|
||||||
>>>>>>> stack_stuff
|
>>>>>>> stack_stuff
|
||||||
|
=======
|
||||||
|
.ui-tabs-vertical a { text-decoration: none; color: black;}
|
||||||
|
.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; }
|
||||||
|
>>>>>>> master
|
||||||
.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: yellow !important; list-style-type: none;}
|
.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; list-style-type: none;}
|
.ui-tabs-vertical .ui-tabs-panel { padding: 1em; float: left; width: 50em; font-size: 12px; list-style-type: none;}
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
<link rel="stylesheet" href="/static/css/style.css">
|
<link rel="stylesheet" href="/static/css/style.css">
|
||||||
<link rel="stylesheet" href="/static/js/jquery-ui-1.12.1.custom/jquery-ui.css">
|
|
||||||
<link rel="stylesheet" href="/static/js/jquery-ui-1.12.1.custom/jquery-ui.js">
|
<link rel="stylesheet" href="/static/js/jquery-ui-1.12.1.custom/jquery-ui.js">
|
||||||
{% block css %} {% endblock%}
|
{% block css %} {% endblock%}
|
||||||
</head>
|
</head>
|
||||||
@ -62,7 +61,7 @@ console.log(time)
|
|||||||
return ('0'+time.getDate()).slice(-2) + '.' + ('0'+(time.getMonth()+1)).slice(-2) + '.' + time.getFullYear() +" " + ('0'+time.getHours()).slice(-2)+":"+ ('0'+time.getMinutes()).slice(-2);
|
return ('0'+time.getDate()).slice(-2) + '.' + ('0'+(time.getMonth()+1)).slice(-2) + '.' + time.getFullYear() +" " + ('0'+time.getHours()).slice(-2)+":"+ ('0'+time.getMinutes()).slice(-2);
|
||||||
}
|
}
|
||||||
//change addr when ONLINE::::::->
|
//change addr when ONLINE::::::->
|
||||||
var socket = io.connect('http://localhost:5000');
|
var socket = io.connect('{{server}}');
|
||||||
var app = new Vue({
|
var app = new Vue({
|
||||||
el: "#app",
|
el: "#app",
|
||||||
delimiters: ['[[', ']]'],
|
delimiters: ['[[', ']]'],
|
||||||
@ -112,6 +111,11 @@ socket.on('channel-' + app.channel, function(msg) {
|
|||||||
scrollTop: $('.messages')[0].scrollHeight
|
scrollTop: $('.messages')[0].scrollHeight
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
document.getElementById("file_import_csv").onchange = function() {
|
||||||
|
document.getElementById("form_import_csv").submit();
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
<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 ('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>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
</nav>
|
</nav>
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
<div id="home_content">
|
<div id="home_content">
|
||||||
<h1 class="header" id="title_xppl">XPPL</h1>
|
<h1 class="header" id="title_xppl">XPPL</h1>
|
||||||
<p class="lead">This is the awesome library of Experimental Publishing. <br>
|
<p class="lead">This is the awesome library of Experimental Publishing. <br>
|
||||||
|
On instance: {{server}} / From: {{client}}
|
||||||
|
<br>
|
||||||
This might only be one interface to this library:
|
This might only be one interface to this library:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@ -12,6 +14,14 @@ This might only be one interface to this library:
|
|||||||
<a href="{{url_for('show_books')}}">List</a>
|
<a href="{{url_for('show_books')}}">List</a>
|
||||||
|
|
||||||
<br><br><br>
|
<br><br><br>
|
||||||
|
|
||||||
|
<form method="GET" action="/export/csv">
|
||||||
|
<button type="submit">Export Catalogue (.CSV)</button>
|
||||||
|
</form>
|
||||||
|
<form method="POST" action="/import/csv" id="form_import_csv" enctype=multipart/form-data>
|
||||||
|
<input type="file" id="file_import_csv" name=file style="display:none;" />
|
||||||
|
<button type = "button" onclick="document.getElementById('file_import_csv').click()">Import Catalogue (.CSV)</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="app" class="container">
|
<div id="app" class="container">
|
||||||
|
7
app/templates/import_csv.html
Normal file
7
app/templates/import_csv.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
<h1 class="page-header">Imported CSV</h1>
|
||||||
|
<p>{{numberadded}} books added!</p>
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -3,27 +3,100 @@
|
|||||||
<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 {
|
||||||
|
zoom: 1;
|
||||||
|
}
|
||||||
body .ui-selecting { border:2px solid yellow; }
|
body .ui-selecting { border:2px solid yellow; }
|
||||||
body .ui-selected {border:2px solid black;}
|
body .ui-selected {border:2px solid black;}
|
||||||
|
|
||||||
body {overflow: scroll;}
|
body {overflow: scroll;}
|
||||||
#scape_container{overflow: scroll;width: 100%; height:100vh;}
|
#scape_container{overflow: scroll;width: 100%; height:100vh;}
|
||||||
|
|
||||||
|
#zoombuttons{
|
||||||
|
position: fixed;
|
||||||
|
right:20px;
|
||||||
|
bottom: 20px;
|
||||||
|
z-index: +999999999999999999999999999999999999999999999;
|
||||||
|
user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-o-user-select: none;
|
||||||
|
}
|
||||||
|
#zoom-in{
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
background-color: rgb(240,240,240);
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid black;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
#zoom-out{
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
background-color: rgb(240,240,240);
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid black;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 10px;
|
||||||
|
|
||||||
|
}
|
||||||
|
#zoom-in:hover{
|
||||||
|
background-color: rgb(230,230,230);
|
||||||
|
}
|
||||||
|
#zoom-out:hover{
|
||||||
|
background-color: rgb(230,230,230);
|
||||||
|
}
|
||||||
|
.booktitle a{
|
||||||
|
text-decoration: none;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
<div id="zoombuttons">
|
||||||
|
<select name="selector" id="selector">
|
||||||
|
{% for instance in instances %}
|
||||||
|
<option value="{{instance.name}}">{{instance.name}}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
<div id="zoom-in">+</div>
|
||||||
|
<div id="zoom-out">-</div>
|
||||||
|
</div>
|
||||||
<div id ="scape_container">
|
<div id ="scape_container">
|
||||||
|
|
||||||
|
|
||||||
{% for book in books|sort(attribute='title', reverse = False) %}
|
{% for book in books|sort(attribute='title', reverse = False) %}
|
||||||
<div class = "drag" id = "{{ book.id }}" style="position: absolute;width:40px;height:auto; top:{{ book.scapeY }}px; left:{{ book.scapeX }}px;">
|
<div class = "drag" id = "{{ book.id }}" style="position: absolute;width:70px;height:auto; top:{{ book.scapeY }}px; left:{{ book.scapeX }}px;">
|
||||||
|
|
||||||
|
|
||||||
<img class="no_cover" id="{{ book.title }}" src="../uploads/cover/{{ book.cover }}" style="width:100%;height:auto;" onerror="if (this.src != '../static/img/default_cover.png') this.src = '../static/img/default_cover.png';">
|
<img class="no_cover" id="{{ book.title }}" src="../uploads/cover/{{ book.cover }}" style="width:100%;height:auto;" onerror="if (this.src != '../static/img/default_cover.png') this.src = '../static/img/default_cover.png';">
|
||||||
<p style="font-size:7px;"><a href="books/{{ book.id }}">{{ book.title }}</a></p>
|
<p class="booktitle" style="font-size:7px;"><a href="books/{{ book.id }}">{{ book.title }}</a></p>
|
||||||
|
|
||||||
|
{% set got = {} %}
|
||||||
|
{% set all = 1 %}
|
||||||
|
{% for instance in book.instances %}
|
||||||
|
|
||||||
|
{% if instance.name in got %}
|
||||||
|
{% set x=got.__setitem__(instance.name, got[instance.name]+1) %}
|
||||||
|
{% else %}
|
||||||
|
{% set x=got.__setitem__(instance.name, 1) %}
|
||||||
|
{% endif %}
|
||||||
|
{% set all = loop.index %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% for instance, value in got.items() %}
|
||||||
|
{% set result = value/(book.instances|length) %}
|
||||||
|
<p hidden="True" >{{ instance }}</p>
|
||||||
|
<p hidden="True" class = "{{ instance }}" >{{result}}</p>
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<div id="random" style="padding:2px; margin: 0;position: absolute;width:120px;height:20px;background-color:yellow;z-index:999999999999999999900000000000000;cursor:pointer;">
|
<div id="random" style="padding:2px; margin: 0;position: absolute;width:120px;height:20px;background-color:yellow;z-index:999999999999999999900000000000000;cursor:pointer;">
|
||||||
@ -81,7 +154,29 @@
|
|||||||
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
|
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$( function() {
|
$( function() {
|
||||||
|
var currentZoom = $('#scape_container').css('zoom');
|
||||||
|
var zoom = parseFloat(currentZoom);
|
||||||
|
var pointerX;
|
||||||
|
var pointerY;
|
||||||
$( ".drag" ).draggable({ stack: ".drag",
|
$( ".drag" ).draggable({ stack: ".drag",
|
||||||
|
start : function(evt, ui) {
|
||||||
|
pointerY = (evt.pageY - $('#scape_container').offset().top) / zoom - parseInt($(evt.target).css('top'));
|
||||||
|
pointerX = (evt.pageX - $('#scape_container').offset().left) / zoom - parseInt($(evt.target).css('left'));
|
||||||
|
},
|
||||||
|
drag : function(evt, ui) {
|
||||||
|
var canvasTop = $('#scape_container').offset().top;
|
||||||
|
var canvasLeft = $('#scape_container').offset().left;
|
||||||
|
var canvasHeight = $('#scape_container').height();
|
||||||
|
var canvasWidth = $('#scape_container').width();
|
||||||
|
|
||||||
|
// Fix for zoom
|
||||||
|
ui.position.top = Math.round((evt.pageY - canvasTop) / zoom - pointerY);
|
||||||
|
ui.position.left = Math.round((evt.pageX - canvasLeft) / zoom - pointerX);
|
||||||
|
|
||||||
|
// Finally, make sure offset aligns with position
|
||||||
|
ui.offset.top = Math.round(ui.position.top + canvasTop);
|
||||||
|
ui.offset.left = Math.round(ui.position.left + canvasLeft);
|
||||||
|
},
|
||||||
stop: function(){
|
stop: function(){
|
||||||
var offset = $(this).offset();
|
var offset = $(this).offset();
|
||||||
var id = $(this).attr('id');
|
var id = $(this).attr('id');
|
||||||
@ -108,12 +203,7 @@
|
|||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
$( function() {
|
|
||||||
$( ".drag" ).resizable({aspectRatio: true});
|
|
||||||
} );
|
|
||||||
/* $( function() {
|
|
||||||
$( "body" ).selectable();
|
|
||||||
} );*/
|
|
||||||
|
|
||||||
$( "#random" ).click(function() {
|
$( "#random" ).click(function() {
|
||||||
console.log("hallo");
|
console.log("hallo");
|
||||||
@ -121,8 +211,8 @@ $( ".drag" ).each(function() {
|
|||||||
var id = $(this).attr('id');
|
var id = $(this).attr('id');
|
||||||
var postForm = { //Fetch form data
|
var postForm = { //Fetch form data
|
||||||
'id' : id,
|
'id' : id,
|
||||||
'x' : Math.floor(Math.random() * window.innerWidth) , //Store name fields value,
|
'x' : Math.floor(Math.random() * 2000) , //Store name fields value,
|
||||||
'y' : Math.floor(Math.random() * window.innerHeight)
|
'y' : Math.floor(Math.random() * 2000)
|
||||||
};
|
};
|
||||||
$( this ).css("top", postForm['y']);
|
$( this ).css("top", postForm['y']);
|
||||||
$( this ).css("left", postForm['x']);
|
$( this ).css("left", postForm['x']);
|
||||||
@ -137,6 +227,42 @@ $( ".drag" ).each(function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#zoom-in").click(function(){
|
||||||
|
var currentZoom = $('#scape_container').css('zoom');
|
||||||
|
|
||||||
|
var newnumber = parseFloat(currentZoom) + 0.1;
|
||||||
|
console.log(newnumber)
|
||||||
|
//$('#scape_container').css('zoom','90%'); /* Webkit browsers */
|
||||||
|
$('#scape_container').css('zoom',newnumber.toString()); /* Other non-webkit browsers */
|
||||||
|
// $('#scape_container').css('-moz-transform',scale(0.9, 0.9)); /* Moz-browsers */
|
||||||
|
});
|
||||||
|
$("#zoom-out").click(function(){
|
||||||
|
var currentZoom = $('#scape_container').css('zoom');
|
||||||
|
var newnumber = parseFloat(currentZoom) - 0.1;
|
||||||
|
console.log(currentZoom+", "+newnumber.toString())
|
||||||
|
|
||||||
|
//$('#scape_container').css('zoom','90%'); /* Webkit browsers */
|
||||||
|
$('#scape_container').css('zoom',newnumber.toString()); /* Other non-webkit browsers */
|
||||||
|
// $('#scape_container').css('-moz-transform',scale(0.9, 0.9)); /* Moz-browsers */
|
||||||
|
});
|
||||||
|
|
||||||
|
$("select[name=selector]").on('change', function() {
|
||||||
|
var selectedInstance = $('select[name=selector]').val()
|
||||||
|
|
||||||
|
$( ".drag" ).each(function() {
|
||||||
|
if($(this).find('.'+selectedInstance).length==0)
|
||||||
|
{
|
||||||
|
$(this).css("opacity", "0.02")
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
var found = $(this).find('.'+selectedInstance).html()
|
||||||
|
$(this).css("opacity", found)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
@ -35,11 +35,11 @@
|
|||||||
<p style="font-size: 10px;"><a href="{{url_for('remove_from_stack', stackid=stack.id, bookid=book.id)}}"> – Remove from stack</a>{% endfor %}</td>
|
<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>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-style: italic;">Notes from uploader</td>
|
<td style="font-style: italic;">Notes from uploader</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -66,6 +66,7 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
<<<<<<< HEAD
|
<<<<<<< HEAD
|
||||||
<a href="/viewpdf/{{ book.file }}">download {{ book.fileformat }}</a>
|
<a href="/viewpdf/{{ book.file }}">download {{ book.fileformat }}</a>
|
||||||
<link rel="stylesheet" href="/static/css/style.css">
|
<link rel="stylesheet" href="/static/css/style.css">
|
||||||
@ -92,18 +93,52 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
>>>>>>> stack_stuff
|
>>>>>>> stack_stuff
|
||||||
|
=======
|
||||||
|
<a href="../uploads/{{ book.file }}">download {{ book.fileformat }}</a>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<p>Instances:</p>
|
||||||
|
{% set got = {} %}
|
||||||
|
{% set all = 1 %}
|
||||||
|
{% for instance in book.instances %}
|
||||||
|
|
||||||
|
{% if instance.name in got %}
|
||||||
|
{% set x=got.__setitem__(instance.name, got[instance.name]+1) %}
|
||||||
|
{% else %}
|
||||||
|
{% set x=got.__setitem__(instance.name, 1) %}
|
||||||
|
{% endif %}
|
||||||
|
{% set all = loop.index %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% for instance, value in got.items() %}
|
||||||
|
{% set result = value/(book.instances|length) %}
|
||||||
|
{{ instance }}: {{ (result*100)|round|int }}%<br>
|
||||||
|
{% endfor %}
|
||||||
|
<br>
|
||||||
|
|
||||||
|
|
||||||
|
{% if book.file %}
|
||||||
|
<button id="myBtn" style= "width: 180px; font-size: 10pt;"><a> Download this {{ book.fileformat }}</a></button>
|
||||||
|
<div id="myModal" class="modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<span class="close">×</span>
|
||||||
|
<h3>A message from the uploading librarian:</h3>
|
||||||
|
<span style="font-style: italic;">"{{book.message or 'Happy reading.'}}" </span><br>
|
||||||
|
<h4><a href="../uploads/{{ book.file }}"> >>>> Link to file <<<<</h4></a></div>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{% endif %}
|
||||||
|
>>>>>>> master
|
||||||
|
|
||||||
<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('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>
|
<button style= "font-size: 10pt;"> <a href="{{ url_for('remove_book_by_id', id=book.id)}}">delete</a></button>
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
{% if previousbook %}
|
{% if previousbook %}
|
||||||
<a href="{{ url_for('show_book_by_id', id=previousbook.id )}}" style="font-size: 9pt;"> < see the previous book added to XPPL: <i>{{ previousbook.title |truncate(40,True,'...') }} </i></a> {% endif %}
|
<a href="{{ url_for('show_book_by_id', id=previousbook.id )}}" style="font-size: 9pt;"> < see the previous book added to XPPL: <i>{{ previousbook.title |truncate(40,True,'...') }} </i></a> {% endif %}
|
||||||
{% if nextbook %}
|
{% if nextbook %}
|
||||||
<a href="{{ url_for('show_book_by_id', id=nextbook.id )}}" style="float:right; font-size: 9pt;"> see the next book added to XPPL: <i>{{ nextbook.title|truncate(40,True,'...')}} </i>> </a>{% endif %}
|
<a href="{{ url_for('show_book_by_id', id=nextbook.id )}}" style="float:right; font-size: 9pt;"> see the next book added to XPPL: <i>{{ nextbook.title|truncate(40,True,'...')}} </i>> </a>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
37
app/templates/show_instances.html
Normal file
37
app/templates/show_instances.html
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="page-header">Instances</h1>
|
||||||
|
<p>All instances, that are using this library</p>
|
||||||
|
|
||||||
|
<table style="width:100%">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<td> {% for stack in stacks %}
|
||||||
|
|
||||||
|
<li><a href="{{url_for('show_stack_by_id', id=stack.id)}}">{{ stack.stack_name }}</a> </li>
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
</table>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
{% for instance in instances %}
|
||||||
|
|
||||||
|
<li>{{ instance.name }} / {{ instance.ip }}</li>
|
||||||
|
<form method="post">
|
||||||
|
<input id="{{ instance.name }}" type="text" name="{{ instance.name }}"><br>
|
||||||
|
<input type="submit" value="rename">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
216
app/views.py
216
app/views.py
@ -13,16 +13,23 @@ import os
|
|||||||
from sqlalchemy.sql.expression import func, select
|
from sqlalchemy.sql.expression import func, select
|
||||||
from sqlalchemy.sql import except_
|
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, Potential
|
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
|
||||||
|
<<<<<<< HEAD
|
||||||
from app.getannot import get_annotations
|
from app.getannot import get_annotations
|
||||||
from urllib.parse import quote as urlquote
|
from urllib.parse import quote as urlquote
|
||||||
|
=======
|
||||||
|
from app.extractText import extract_text
|
||||||
|
>>>>>>> master
|
||||||
from os import environ
|
from os import environ
|
||||||
from flask_socketio import SocketIO, emit
|
from flask_socketio import SocketIO, emit
|
||||||
from weasyprint import HTML
|
from weasyprint import HTML
|
||||||
import datetime
|
import datetime
|
||||||
import time
|
import time
|
||||||
import autocomplete
|
from csv import DictWriter, DictReader
|
||||||
|
import io
|
||||||
|
from sqlalchemy.inspection import inspect
|
||||||
|
#import autocomplete
|
||||||
import sys
|
import sys
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
|
|
||||||
@ -57,8 +64,14 @@ def home():
|
|||||||
# msg = Chat(message)
|
# msg = Chat(message)
|
||||||
# db.session.add(msg)
|
# db.session.add(msg)
|
||||||
# db.session.commit()
|
# db.session.commit()
|
||||||
|
#client = request.remote_addr
|
||||||
|
server = request.host
|
||||||
|
if request.environ.get('HTTP_X_FORWARDED_FOR') is None:
|
||||||
|
client =request.environ['REMOTE_ADDR']
|
||||||
|
else:
|
||||||
|
client = request.environ['HTTP_X_FORWARDED_FOR']
|
||||||
|
|
||||||
return render_template('home.html',domain=DOMAIN,chat=chat_messages, channel = 1, username=username)
|
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):
|
||||||
@ -71,6 +84,13 @@ def about():
|
|||||||
|
|
||||||
@app.route('/uploads/<filename>')
|
@app.route('/uploads/<filename>')
|
||||||
def uploaded_file(filename):
|
def uploaded_file(filename):
|
||||||
|
book = Book.query.filter_by(file=filename).first()
|
||||||
|
i = Instance(request.host, "download")
|
||||||
|
existing_ip = db.session.query(Instance).filter_by(ip=request.host).first()
|
||||||
|
if existing_ip:
|
||||||
|
i.name = existing_ip.name
|
||||||
|
book.instances.append(i)
|
||||||
|
db.session.commit()
|
||||||
return send_from_directory(app.config['UPLOAD_FOLDER'],
|
return send_from_directory(app.config['UPLOAD_FOLDER'],
|
||||||
filename)
|
filename)
|
||||||
|
|
||||||
@ -101,7 +121,19 @@ def scape():
|
|||||||
book.scapeY = data['y']
|
book.scapeY = data['y']
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
books = db.session.query(Book).all() # or you could have used User.query.all()
|
books = db.session.query(Book).all() # or you could have used User.query.all()
|
||||||
return render_template('scape.html', books=books)
|
all_instances = db.session.query(Instance).all()
|
||||||
|
instances = []
|
||||||
|
for instance in all_instances:
|
||||||
|
exists = False
|
||||||
|
for existing_inst in instances:
|
||||||
|
if existing_inst.name == instance.name:
|
||||||
|
exists = True
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
exists = False
|
||||||
|
if not exists:
|
||||||
|
instances.append(instance)
|
||||||
|
return render_template('scape.html', books=books, instances=instances)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/books_grid')
|
@app.route('/books_grid')
|
||||||
@ -112,6 +144,7 @@ def show_books_grid():
|
|||||||
@app.route('/books/<int:id>')
|
@app.route('/books/<int:id>')
|
||||||
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()
|
||||||
previousbook = Book.query.filter_by(id=id - 1).first()
|
previousbook = Book.query.filter_by(id=id - 1).first()
|
||||||
nextbook = Book.query.filter_by(id=id + 1).first()
|
nextbook = Book.query.filter_by(id=id + 1).first()
|
||||||
allbooks = db.session.query(Book).all()
|
allbooks = db.session.query(Book).all()
|
||||||
@ -132,7 +165,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, previousbook = previousbook, nextbook = nextbook)
|
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'])
|
||||||
@ -176,6 +209,11 @@ def edit_book_by_id(id):
|
|||||||
a = Author(author_name=author_name)
|
a = Author(author_name=author_name)
|
||||||
db.session.add(a)
|
db.session.add(a)
|
||||||
book.authors.append(a)
|
book.authors.append(a)
|
||||||
|
i = Instance(request.host, "edit")
|
||||||
|
existing_ip = db.session.query(Instance).filter_by(ip=request.host).first()
|
||||||
|
if existing_ip:
|
||||||
|
i.name = existing_ip.name
|
||||||
|
book.instances.append(i)
|
||||||
|
|
||||||
# editing / uploading new file
|
# editing / uploading new file
|
||||||
if user_form.file.data:
|
if user_form.file.data:
|
||||||
@ -255,7 +293,13 @@ def add_book():
|
|||||||
fullpath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
fullpath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
||||||
name, file_extension = os.path.splitext(filename)
|
name, file_extension = os.path.splitext(filename)
|
||||||
file.save(fullpath)
|
file.save(fullpath)
|
||||||
cover = get_cover(fullpath, name)
|
try:
|
||||||
|
cover = get_cover(fullpath, name)
|
||||||
|
except:
|
||||||
|
cover = ''
|
||||||
|
|
||||||
|
extract_text(fullpath, name)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
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
|
||||||
@ -285,6 +329,11 @@ def add_book():
|
|||||||
a = Author(author_name=author_name)
|
a = Author(author_name=author_name)
|
||||||
db.session.add(a)
|
db.session.add(a)
|
||||||
book.authors.append(a)
|
book.authors.append(a)
|
||||||
|
i = Instance(request.host, "add")
|
||||||
|
existing_ip = db.session.query(Instance).filter_by(ip=request.host).first()
|
||||||
|
if existing_ip:
|
||||||
|
i.name = existing_ip.name
|
||||||
|
book.instances.append(i)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
flash("%s added to the library" % (title))
|
flash("%s added to the library" % (title))
|
||||||
@ -378,10 +427,40 @@ def edit_stack_by_id(id):
|
|||||||
stack.stack_name = stack_name
|
stack.stack_name = stack_name
|
||||||
stack.stack_description = stack_description
|
stack.stack_description = stack_description
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
return redirect(url_for('show_stack_by_id', id=id))
|
return redirect(url_for('show_stack_by_id', id=id))
|
||||||
return render_template('edit_stack_detail.html', stack=stack, form=form)
|
return render_template('edit_stack_detail.html', stack=stack, form=form)
|
||||||
|
|
||||||
|
@app.route('/instances', methods=['POST', 'GET'])
|
||||||
|
def show_instances():
|
||||||
|
all_instances = db.session.query(Instance).all()
|
||||||
|
instances = []
|
||||||
|
for instance in all_instances:
|
||||||
|
exists = False
|
||||||
|
for existing_inst in instances:
|
||||||
|
if existing_inst.name == instance.name:
|
||||||
|
exists = True
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
exists = False
|
||||||
|
if not exists:
|
||||||
|
instances.append(instance)
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
for item in request.form.items():
|
||||||
|
for i, itm in enumerate(item):
|
||||||
|
if i == 0:
|
||||||
|
oldname = itm
|
||||||
|
if i == 1:
|
||||||
|
name = itm
|
||||||
|
|
||||||
|
all_instances = db.session.query(Instance).filter_by(name=oldname).all()
|
||||||
|
for instance in all_instances:
|
||||||
|
instance.name = name
|
||||||
|
print(oldname)
|
||||||
|
print(name)
|
||||||
|
db.session.commit()
|
||||||
|
return render_template('show_instances.html', instances=instances)
|
||||||
|
|
||||||
@app.route('/stacks/<int:stackid>/remove/<int:bookid>', methods=['POST', 'GET'])
|
@app.route('/stacks/<int:stackid>/remove/<int:bookid>', methods=['POST', 'GET'])
|
||||||
def remove_from_stack(bookid, stackid):
|
def remove_from_stack(bookid, stackid):
|
||||||
book = Book.query.get(bookid)
|
book = Book.query.get(bookid)
|
||||||
@ -392,18 +471,21 @@ def remove_from_stack(bookid, stackid):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
return render_template('show_book_detail.html', book=book)
|
return render_template('show_book_detail.html', book=book)
|
||||||
|
|
||||||
|
|
||||||
## search
|
## search
|
||||||
view = ['1']
|
view = ['1']
|
||||||
|
|
||||||
@app.route('/books', methods= ['POST','GET'])
|
@app.route('/books', methods= ['POST','GET'])
|
||||||
def show_books():
|
def show_books():
|
||||||
|
<<<<<<< HEAD
|
||||||
<<<<<<< HEAD
|
<<<<<<< HEAD
|
||||||
autocomplete.load() #Train markov model once, for autocomplete in search
|
autocomplete.load() #Train markov model once, for autocomplete in search
|
||||||
books = db.session.query(Book).all()
|
books = db.session.query(Book).all()
|
||||||
=======
|
=======
|
||||||
books = db.session.query(Book).order_by(Book.title)
|
books = db.session.query(Book).order_by(Book.title)
|
||||||
>>>>>>> stack_stuff
|
>>>>>>> stack_stuff
|
||||||
|
=======
|
||||||
|
books = db.session.query(Book).order_by(Book.title)
|
||||||
|
>>>>>>> master
|
||||||
search = SearchForm(request.form)
|
search = SearchForm(request.form)
|
||||||
view.append('1')
|
view.append('1')
|
||||||
viewby = '1'
|
viewby = '1'
|
||||||
@ -514,6 +596,7 @@ def search_results(searchtype, query, viewby):
|
|||||||
if viewby == '2':
|
if viewby == '2':
|
||||||
return render_template('results_grid.html', form=search, books=results, books_all=books_all, searchtype=search.select.data, query=query, count = count, whole = whole, percentage = percentage)
|
return render_template('results_grid.html', form=search, books=results, books_all=books_all, searchtype=search.select.data, query=query, count = count, whole = whole, percentage = percentage)
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
<<<<<<< HEAD
|
<<<<<<< HEAD
|
||||||
## Search - autocomplete
|
## Search - autocomplete
|
||||||
autocomplete_suggestions = []
|
autocomplete_suggestions = []
|
||||||
@ -541,6 +624,8 @@ def test1():
|
|||||||
|
|
||||||
## STACKS!
|
## STACKS!
|
||||||
=======
|
=======
|
||||||
|
=======
|
||||||
|
>>>>>>> master
|
||||||
else:
|
else:
|
||||||
return render_template('results.html', form=search, books=results, books_all=books_all, searchtype=search.select.data, query=query, count = count, whole = whole, percentage = percentage)
|
return render_template('results.html', form=search, books=results, books_all=books_all, searchtype=search.select.data, query=query, count = count, whole = whole, percentage = percentage)
|
||||||
|
|
||||||
@ -562,11 +647,21 @@ def test1():
|
|||||||
# autocomplete_suggestions.clear()
|
# autocomplete_suggestions.clear()
|
||||||
# for suggestion, score in autocomplete_output:
|
# for suggestion, score in autocomplete_output:
|
||||||
# autocomplete_suggestions.append(suggestion)
|
# autocomplete_suggestions.append(suggestion)
|
||||||
|
#
|
||||||
|
# session['autocomplete_suggestions'] = str(autocomplete_suggestions)
|
||||||
|
#
|
||||||
|
# print(session['autocomplete_suggestions'])
|
||||||
|
#
|
||||||
|
# return Response(json.dumps(session['autocomplete_suggestions']), mimetype='application/json')
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
# print(autocomplete_suggestions)
|
# print(autocomplete_suggestions)
|
||||||
|
|
||||||
# return Response(json.dumps(autocomplete_suggestions), mimetype='application/json')
|
# return Response(json.dumps(autocomplete_suggestions), mimetype='application/json')
|
||||||
>>>>>>> stack_stuff
|
>>>>>>> stack_stuff
|
||||||
|
=======
|
||||||
|
## STACKS!
|
||||||
|
>>>>>>> master
|
||||||
|
|
||||||
@app.route('/add_to_stack/<int:id>', methods=['GET', 'POST'])
|
@app.route('/add_to_stack/<int:id>', methods=['GET', 'POST'])
|
||||||
def add_to_stack(id):
|
def add_to_stack(id):
|
||||||
@ -583,23 +678,97 @@ def add_to_stack(id):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
return render_template('show_stack_detail.html', stack=stack)
|
return render_template('show_stack_detail.html', stack=stack)
|
||||||
|
|
||||||
from csv import DictWriter
|
|
||||||
import io
|
|
||||||
|
|
||||||
@app.route('/export/csv', methods=['GET'])
|
@app.route('/export/csv', methods=['GET'])
|
||||||
def export_csv ():
|
def export_csv():
|
||||||
output = io.StringIO()
|
output = io.StringIO()
|
||||||
fieldnames = ['title', 'authors']
|
#fieldnames = ['title', 'authors', 'file', 'fileformat', 'category', 'year_published', 'description' ]
|
||||||
csv = DictWriter(output,fieldnames)
|
fields = Book.__mapper__.columns
|
||||||
|
fieldnames = []
|
||||||
|
for columns in fields:
|
||||||
|
fieldnames.append(columns.name)
|
||||||
|
i = inspect(Book)
|
||||||
|
referred_classes = [r.mapper.class_ for r in i.relationships]
|
||||||
|
referred_classes_tablenames = [r.mapper.class_.__tablename__ for r in i.relationships]
|
||||||
|
print(fieldnames+referred_classes_tablenames)
|
||||||
|
csv = DictWriter(output,fieldnames+referred_classes_tablenames)
|
||||||
csv.writeheader()
|
csv.writeheader()
|
||||||
# for i in range(10):
|
|
||||||
# csv.writerow({'ID': i, 'fruit': "Tomato"})
|
|
||||||
for book in Book.query.order_by("title"):
|
for book in Book.query.order_by("title"):
|
||||||
authors = ", ".join([x.author_name for x in book.authors])
|
row = {}
|
||||||
csv.writerow({"title": book.title, "authors": authors})
|
for col in fieldnames:
|
||||||
resp = Response(output.getvalue(), mimetype="text/plain")
|
print(getattr(book, col))
|
||||||
# resp.headers["Content-Disposition"] = "attachment;filename=export.csv"
|
row[col] = getattr(book, col)
|
||||||
|
for col in referred_classes:
|
||||||
|
subattr = []
|
||||||
|
for subcol in getattr(book, col.__tablename__):
|
||||||
|
for metacol in subcol.__mapper__.columns:
|
||||||
|
query = metacol.name
|
||||||
|
if query != "id":
|
||||||
|
this = getattr(subcol, query)
|
||||||
|
subattr.append(this)
|
||||||
|
row[col.__tablename__] = " | ".join(subattr)
|
||||||
|
csv.writerow(row)
|
||||||
|
#print(row)
|
||||||
|
resp = Response(output.getvalue(), mimetype="text/csv")
|
||||||
|
resp.headers["Content-Disposition"] = "attachment;filename=export.csv"
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
import codecs
|
||||||
|
@app.route('/import/csv', methods= ['POST','GET'])
|
||||||
|
def import_csv():
|
||||||
|
if request.method == 'POST':
|
||||||
|
if 'file' not in request.files:
|
||||||
|
flash('No file part')
|
||||||
|
return redirect(request.url)
|
||||||
|
else:
|
||||||
|
file = request.files['file']
|
||||||
|
for row in DictReader(codecs.iterdecode(file, 'utf-8')):
|
||||||
|
numberadded = 0;
|
||||||
|
book = Book.query.filter_by(title=row['title']).first()
|
||||||
|
if book:
|
||||||
|
print("allreadyexists")
|
||||||
|
else:
|
||||||
|
cover = ''
|
||||||
|
if row['file']:
|
||||||
|
fullpath = os.path.join(app.config['UPLOAD_FOLDER'], row['file'])
|
||||||
|
name, file_extension = os.path.splitext(row['file'])
|
||||||
|
print ('get_cover', fullpath, name)
|
||||||
|
cover = get_cover(fullpath, name)
|
||||||
|
|
||||||
|
if row['year_published']:
|
||||||
|
year_published = int(row['year_published'])
|
||||||
|
else:
|
||||||
|
year_published = None;
|
||||||
|
book = Book(row['title'], row['file'], cover, row['fileformat'], row['category'],year_published, None, None, None, None, None, None)
|
||||||
|
book.scapeX = float(row['scapeX'])
|
||||||
|
book.scapeY = float(row['scapeY'])
|
||||||
|
|
||||||
|
db.session.add(book)
|
||||||
|
numberadded = numberadded+1
|
||||||
|
authors = row['authors'].split('|')
|
||||||
|
authors = [x.strip() for x in authors]
|
||||||
|
for author in authors:
|
||||||
|
if author:
|
||||||
|
a = db.session.query(Author).filter_by(author_name=author).first()
|
||||||
|
if a == None:
|
||||||
|
a = Author(author_name=author)
|
||||||
|
db.session.add(a)
|
||||||
|
book.authors.append(a)
|
||||||
|
db.session.commit()
|
||||||
|
return render_template('import_csv.html', numberadded=numberadded)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/empty_catalogue487352698237465', methods= ['POST','GET'])
|
||||||
|
def empty_catalogue():
|
||||||
|
meta = db.metadata
|
||||||
|
for table in reversed(meta.sorted_tables):
|
||||||
|
if str(table) == "books" or str(table) == "authors" or str(table) == "books_authors":
|
||||||
|
print('Clear table %s' % table)
|
||||||
|
db.session.execute(table.delete())
|
||||||
|
db.create_all()
|
||||||
|
db.session.commit()
|
||||||
|
return "ALL CLEARED"
|
||||||
|
|
||||||
###
|
###
|
||||||
# The API
|
# The API
|
||||||
###
|
###
|
||||||
@ -673,10 +842,14 @@ def page_not_found(error):
|
|||||||
"""Custom 404 page."""
|
"""Custom 404 page."""
|
||||||
return render_template('404.html'), 404
|
return render_template('404.html'), 404
|
||||||
|
|
||||||
|
|
||||||
|
### SOCKET for the chat
|
||||||
|
|
||||||
@socketio.on('new_message')
|
@socketio.on('new_message')
|
||||||
def new_message(message):
|
def new_message(message):
|
||||||
# Send message to alls users
|
# Send message to all users
|
||||||
print("new message")
|
# print("new message")
|
||||||
|
# channel is always 1 now, but might be interesting for further development
|
||||||
emit('channel-' + str(message['channel']), {
|
emit('channel-' + str(message['channel']), {
|
||||||
'username': message['username'],
|
'username': message['username'],
|
||||||
'text': message['text'],
|
'text': message['text'],
|
||||||
@ -688,6 +861,7 @@ def new_message(message):
|
|||||||
my_new_chat = Chat(
|
my_new_chat = Chat(
|
||||||
message=message['text']
|
message=message['text']
|
||||||
)
|
)
|
||||||
|
|
||||||
db.session.add(my_new_chat)
|
db.session.add(my_new_chat)
|
||||||
try:
|
try:
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
@ -4,4 +4,4 @@ mkdir -p app/uploads/cover
|
|||||||
chmod 777 app/uploads/
|
chmod 777 app/uploads/
|
||||||
chmod 777 app/uploads/cover
|
chmod 777 app/uploads/cover
|
||||||
python3 init.py
|
python3 init.py
|
||||||
python3 import_csv.py xpublibrary.csv
|
#python3 import_csv.py xpublibrary.csv
|
||||||
|
@ -16,6 +16,12 @@ WTForms==2.1
|
|||||||
flask-marshmallow==0.9.0
|
flask-marshmallow==0.9.0
|
||||||
Wand==0.4.4
|
Wand==0.4.4
|
||||||
PyPDF2==1.26.0
|
PyPDF2==1.26.0
|
||||||
|
<<<<<<< HEAD
|
||||||
|
flask-socketio==2.9.2
|
||||||
|
flask-whooshalchemyplus==0.7.5
|
||||||
|
python-dotenv==0.7.1
|
||||||
|
=======
|
||||||
autocomplete==0.0.104
|
autocomplete==0.0.104
|
||||||
|
|
||||||
|
|
||||||
|
>>>>>>> 30d8bade54d8646ad4a5e314022d62e2dbf81755
|
||||||
|
4
run.py
4
run.py
@ -1,9 +1,13 @@
|
|||||||
#! /usr/bin/env python
|
#! /usr/bin/env python
|
||||||
from app import app, socketio
|
from app import app, socketio
|
||||||
<<<<<<< HEAD
|
<<<<<<< HEAD
|
||||||
|
<<<<<<< HEAD
|
||||||
# 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)
|
||||||
=======
|
=======
|
||||||
socketio.run(app, port=8080)
|
socketio.run(app, port=8080)
|
||||||
|
=======
|
||||||
|
socketio.run(app,host="0.0.0.0", port=8080)
|
||||||
|
>>>>>>> master
|
||||||
#app.run(debug=True,host="0.0.0.0",port=8080)
|
#app.run(debug=True,host="0.0.0.0",port=8080)
|
||||||
>>>>>>> stack_stuff
|
>>>>>>> stack_stuff
|
||||||
|
BIN
whoosh/Book/MAIN_071mbyqoitijmyv4.seg
Normal file
BIN
whoosh/Book/MAIN_071mbyqoitijmyv4.seg
Normal file
Binary file not shown.
BIN
whoosh/Book/MAIN_2a7vygakwdvdefoe.seg
Normal file
BIN
whoosh/Book/MAIN_2a7vygakwdvdefoe.seg
Normal file
Binary file not shown.
BIN
whoosh/Book/MAIN_5id3ip2mvmsu2mbl.seg
Normal file
BIN
whoosh/Book/MAIN_5id3ip2mvmsu2mbl.seg
Normal file
Binary file not shown.
BIN
whoosh/Book/MAIN_6bsjkp9xdes7zrrx.seg
Normal file
BIN
whoosh/Book/MAIN_6bsjkp9xdes7zrrx.seg
Normal file
Binary file not shown.
BIN
whoosh/Book/MAIN_es8t5xyup7nfqm7j.seg
Normal file
BIN
whoosh/Book/MAIN_es8t5xyup7nfqm7j.seg
Normal file
Binary file not shown.
BIN
whoosh/Book/MAIN_hljrpqpa46dk3vgc.seg
Normal file
BIN
whoosh/Book/MAIN_hljrpqpa46dk3vgc.seg
Normal file
Binary file not shown.
BIN
whoosh/Book/MAIN_q0ohjvxyt5ufv1vl.seg
Normal file
BIN
whoosh/Book/MAIN_q0ohjvxyt5ufv1vl.seg
Normal file
Binary file not shown.
BIN
whoosh/Book/_MAIN_293.toc
Normal file
BIN
whoosh/Book/_MAIN_293.toc
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user