mirror of
https://github.com/th3r00t/pyShelf.git
synced 2026-04-28 01:59:35 -04:00
Massive UI changes, and updates to the collection system
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -129,3 +129,6 @@ create_db.sql
|
|||||||
uwsgi.ini
|
uwsgi.ini
|
||||||
installer.log
|
installer.log
|
||||||
pyshelf_nginx.conf
|
pyshelf_nginx.conf
|
||||||
|
tags
|
||||||
|
TAGS
|
||||||
|
config.json
|
||||||
|
|||||||
2
config.json
vendored
2
config.json
vendored
@@ -1 +1 @@
|
|||||||
{"TITLE": "pyShelf E-Book Server", "VERSION": "0.4.1", "BOOKPATH": "/home/raelon/Books", "DB_HOST": "localhost", "DB_PORT": "5432", "DATABASE": "pyshelf", "USER": "pyshelf", "PASSWORD": "pyshelf", "BOOKSHELF": "data/shelf.json", "ALLOWED_HOSTS": "*", "hostname": "localhost", "webport": "8000", "wsgiport": "8001"}
|
{"TITLE": "pyShelf E-Book Server", "VERSION": "0.5.0", "BOOKPATH": "/home/raelon/Books", "DB_HOST": "localhost", "DB_PORT": "5432", "DATABASE": "pyshelf", "USER": "pyshelf", "PASSWORD": "pyshelf", "BOOKSHELF": "data/shelf.json", "ALLOWED_HOSTS": "*", "hostname": "localhost", "webport": "8000", "wsgiport": "8001"}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
import re
|
||||||
|
|
||||||
import psycopg2
|
import psycopg2
|
||||||
|
|
||||||
|
|
||||||
@@ -96,6 +98,7 @@ class Storage:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def make_collections(self):
|
def make_collections(self):
|
||||||
|
_title_regx = re.compile(r"^[0-9][0-9]*|-|\ \B")
|
||||||
_q = "SELECT id,file_name FROM books"
|
_q = "SELECT id,file_name FROM books"
|
||||||
self.cursor.execute(_q)
|
self.cursor.execute(_q)
|
||||||
_set = self.cursor.fetchall()
|
_set = self.cursor.fetchall()
|
||||||
@@ -107,6 +110,9 @@ class Storage:
|
|||||||
_pathing.pop(-1)
|
_pathing.pop(-1)
|
||||||
for _p in _pathing:
|
for _p in _pathing:
|
||||||
_s = _p.replace("'", "")
|
_s = _p.replace("'", "")
|
||||||
|
_x = re.sub(_title_regx, "", _s)
|
||||||
|
_s = _x.strip()
|
||||||
|
breakpoint()
|
||||||
_q_x = """
|
_q_x = """
|
||||||
SELECT id FROM collections where collection='%s' AND book_id_id=%s
|
SELECT id FROM collections where collection='%s' AND book_id_id=%s
|
||||||
""" % (
|
""" % (
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ SECRET_KEY = "@(9b9jslgg41u1u=mr)-2*-n2x0vef0zsy39*z@sz18&tvow18"
|
|||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = TEMPLATE_DEBUG = True
|
DEBUG = TEMPLATE_DEBUG = True
|
||||||
|
if DEBUG is True:
|
||||||
|
from pudb.remote import set_trace
|
||||||
ALLOWED_HOSTS = CONFIG.allowed_hosts
|
ALLOWED_HOSTS = CONFIG.allowed_hosts
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,15 @@ class Books(models.Model):
|
|||||||
progress = models.IntegerField(null=True)
|
progress = models.IntegerField(null=True)
|
||||||
file_name = models.CharField(max_length=255, null=False)
|
file_name = models.CharField(max_length=255, null=False)
|
||||||
|
|
||||||
|
def generic_search(self, query):
|
||||||
|
try:
|
||||||
|
results = Books.objects.annotate(
|
||||||
|
search=SearchVector("title", "file_name", "author"),
|
||||||
|
).filter(search=query)
|
||||||
|
except Exception as e:
|
||||||
|
raise
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
class Collections(models.Model):
|
class Collections(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
64
src/interface/static/css/main.css
vendored
64
src/interface/static/css/main.css
vendored
@@ -12,7 +12,7 @@ body {
|
|||||||
"app_body"
|
"app_body"
|
||||||
"app_footer";
|
"app_footer";
|
||||||
grid-template-rows: auto auto auto;
|
grid-template-rows: auto auto auto;
|
||||||
max-height: 100%;
|
/*max-height: 100%;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.clear {
|
.clear {
|
||||||
@@ -84,23 +84,61 @@ body {
|
|||||||
grid-area: app_body;
|
grid-area: app_body;
|
||||||
grid-template-rows: auto;
|
grid-template-rows: auto;
|
||||||
grid-template-areas: "nav_l shelf";
|
grid-template-areas: "nav_l shelf";
|
||||||
grid-template-columns: 13vw auto;
|
grid-template-columns: 15vw 85vw;
|
||||||
justify-items: center;
|
|
||||||
background-color: dimgray;
|
background-color: dimgray;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav_l {
|
.nav_l {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-area: nav_l;
|
grid-area: nav_l;
|
||||||
|
font-family: 'Gruppo', cursive;
|
||||||
|
font-size: 20px;
|
||||||
|
max-height: 500px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
padding: 0px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav_l_hdr {}
|
.popover{
|
||||||
|
display: none;
|
||||||
|
z-index: 100;
|
||||||
|
background-color: #000;
|
||||||
|
/*min-width: 200px;*/
|
||||||
|
min-height: 30px;
|
||||||
|
position: fixed;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
align-items: center;
|
||||||
|
justify-content:center;
|
||||||
|
justify-items: center;
|
||||||
|
padding: 0px 10px;
|
||||||
|
}
|
||||||
|
.nav_l_hdr {
|
||||||
|
text-align: center;
|
||||||
|
padding: 5px;
|
||||||
|
background-color: #292f35;
|
||||||
|
border-bottom: 2px solid #000;
|
||||||
|
}
|
||||||
|
|
||||||
.nav_l_0 {background-color: #2b2b2b; font-size: 15px; padding: 5px;}
|
.nav_l_0 {
|
||||||
|
background-color: #2b2b2b;
|
||||||
|
padding: 5px;
|
||||||
|
text-align: center;
|
||||||
|
border-bottom: 1px solid #000;
|
||||||
|
}
|
||||||
|
|
||||||
.nav_l_1 {font-size: 15px; padding: 5px;}
|
.nav_l_1 {
|
||||||
|
padding: 5px;
|
||||||
|
text-align: center;
|
||||||
|
border-bottom: 1px solid #000;
|
||||||
|
}
|
||||||
.nav_link {}
|
.nav_link {}
|
||||||
#vert-nav {list-style: None; padding: 0px;}
|
#vert-nav {
|
||||||
|
list-style: None;
|
||||||
|
padding: 0px;
|
||||||
|
margin: 10px 0px;
|
||||||
|
border-left: 5px solid #292f35;
|
||||||
|
border-right: 5px solid #292f35;
|
||||||
|
}
|
||||||
|
|
||||||
.vert-nav-item {}
|
.vert-nav-item {}
|
||||||
|
|
||||||
@@ -208,6 +246,8 @@ body {
|
|||||||
margin: 0px 0px;
|
margin: 0px 0px;
|
||||||
padding: 10px 0px 10px;
|
padding: 10px 0px 10px;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.shelf_contents {}
|
.shelf_contents {}
|
||||||
@@ -234,7 +274,7 @@ p {
|
|||||||
|
|
||||||
#book_shelf {
|
#book_shelf {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 25% 25% 25% 25%;
|
grid-template-columns: 21% 21% 21% 21%;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
font-family: 'Audiowide', cursive;
|
font-family: 'Audiowide', cursive;
|
||||||
font-size: 25px;
|
font-size: 25px;
|
||||||
@@ -247,14 +287,14 @@ p {
|
|||||||
display: grid;
|
display: grid;
|
||||||
background-color: burlywood;
|
background-color: burlywood;
|
||||||
margin: 0 10px 10px 10px;
|
margin: 0 10px 10px 10px;
|
||||||
max-width: 23vw;
|
max-width: 20vw;
|
||||||
max-height: 75vh;
|
max-height: 70vh;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.book_thumb {
|
.book_thumb {
|
||||||
width: 23vw;
|
width: 20vw;
|
||||||
height: 50vh;
|
height: 70vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.book_link {
|
a.book_link {
|
||||||
|
|||||||
65
src/interface/static/js/pyshelf_ux.js
vendored
65
src/interface/static/js/pyshelf_ux.js
vendored
@@ -1,15 +1,54 @@
|
|||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
$(".search_submit").click(function(){
|
function customlog(outstream) {
|
||||||
var query = $('.nav_search').val();
|
/* Gather my variables and output them */
|
||||||
console.log(query);
|
for (var i = 0; i < outstream.length; i++){
|
||||||
window.location.href = '/search/'+query;
|
console.log(">> "+outstream[i]);
|
||||||
});
|
};
|
||||||
$('.nav_search').on('keypress', function (e) {
|
};
|
||||||
if(e.which === 13){
|
/* Initialize ui variables */
|
||||||
$(this).attr("disabled", "disabled");
|
var outstream = []; // put customlog messages here
|
||||||
var query = $('.nav_search').val();
|
var win_height = window.innerHeight; // Get the displays height
|
||||||
window.location.href = '/search/'+query;
|
var win_width = window.innwerWidth; // Get the displays width
|
||||||
$(this).removeAttr("disabled");
|
var scr_height = window.outerHeight;
|
||||||
}
|
var scr_width = window.outerWidth;
|
||||||
});
|
var hdr_height = $('.app_hdr').height(); // Get our header height
|
||||||
|
var ftr_height = $('.app_footer').height(); // Get our footer height
|
||||||
|
var nav_width = $('.nav_l').width(); // Get the width of our nav items
|
||||||
|
var cmp_height = window.screen.availHeight;
|
||||||
|
var max_height = win_height - (hdr_height + ftr_height) - (scr_height - win_height); // Set our available height
|
||||||
|
customlog([cmp_height]);
|
||||||
|
$(".search_submit").click(function(){
|
||||||
|
var query = $('.nav_search').val();
|
||||||
|
console.log(query);
|
||||||
|
window.location.href = '/search/'+query;
|
||||||
|
});
|
||||||
|
$('.nav_search').on('keypress', function (e) {
|
||||||
|
if(e.which === 13){
|
||||||
|
$(this).attr("disabled", "disabled");
|
||||||
|
var query = $('.nav_search').val();
|
||||||
|
window.location.href = '/search/'+query;
|
||||||
|
$(this).removeAttr("disabled");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('#app').css("height", max_height);
|
||||||
|
$('.nav_l').css("max-height", max_height);
|
||||||
|
$('div.shelf').css("max-height", max_height);
|
||||||
|
$('.nav_link').on('mouseover', function (e){
|
||||||
|
var popover_str = $(this).attr('alt');
|
||||||
|
x = $(this).offset().left
|
||||||
|
y = $(this).offset().top
|
||||||
|
$('.popover').html(popover_str);
|
||||||
|
$('.popover').css('left', x+nav_width);
|
||||||
|
$('.popover').css('top', y);
|
||||||
|
$('.popover').css('display','flex');
|
||||||
|
});
|
||||||
|
$('.nav_link').on('mouseout', function (e){
|
||||||
|
var popover_str = $(this).attr('alt');
|
||||||
|
x = $(this).offset().left
|
||||||
|
y = $(this).offset().top
|
||||||
|
$('.popover').html(popover_str);
|
||||||
|
$('.popover').css('left', x);
|
||||||
|
$('.popover').css('top', y);
|
||||||
|
$('.popover').css('display','none');
|
||||||
|
});
|
||||||
})
|
})
|
||||||
|
|||||||
3
src/interface/templates/index.html
vendored
3
src/interface/templates/index.html
vendored
@@ -51,10 +51,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="app_body">
|
<div class="app_body">
|
||||||
<div class="nav_l">
|
<div class="nav_l">
|
||||||
|
<p class="popover"></p>
|
||||||
<ul id="vert-nav">
|
<ul id="vert-nav">
|
||||||
<li class="vert-nav-item nav_l_hdr">Collections</li>
|
<li class="vert-nav-item nav_l_hdr">Collections</li>
|
||||||
{% for row in LeftNav %}
|
{% for row in LeftNav %}
|
||||||
<a href="{% url 'show_collection' _collection=row.link _colset=Set%}" class="nav_link">
|
<a href="{% url 'show_collection' _collection=row.link _colset=Set%}" class="nav_link" alt="{{row.link}}">
|
||||||
<li class="nav_l_{{row.class}}">
|
<li class="nav_l_{{row.class}}">
|
||||||
{{ row.string }}
|
{{ row.string }}
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
12
src/interface/templates/search.html
vendored
12
src/interface/templates/search.html
vendored
@@ -48,6 +48,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="app_body" >
|
<div class="app_body" >
|
||||||
|
<div class="nav_l">
|
||||||
|
<ul id="vert-nav">
|
||||||
|
<li class="vert-nav-item nav_l_hdr">Collections</li>
|
||||||
|
{% for row in LeftNav %}
|
||||||
|
<a href="{% url 'show_collection' _collection=row.link _colset=Set%}" class="nav_link" alt="{{row.link}}">
|
||||||
|
<li class="nav_l_{{row.class}}">
|
||||||
|
{{ row.string }}
|
||||||
|
</li>
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
<div class="shelf">
|
<div class="shelf">
|
||||||
<div class="search_details">
|
<div class="search_details">
|
||||||
Your search for {{ Query }} returned {{ len_results }} results
|
Your search for {{ Query }} returned {{ len_results }} results
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ def show_collection(request, _collection, _colset):
|
|||||||
_set = 1
|
_set = 1
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
"search.html",
|
"index.html",
|
||||||
{
|
{
|
||||||
"Books": collection(_collection, _set),
|
"Books": collection(_collection, _set),
|
||||||
"Set": str(_set),
|
"Set": str(_set),
|
||||||
@@ -48,26 +48,6 @@ def show_collection(request, _collection, _colset):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def menu(which):
|
|
||||||
if which == "collections":
|
|
||||||
collection_list = Collections.objects.all()
|
|
||||||
collections = []
|
|
||||||
collection_key = []
|
|
||||||
x = 0
|
|
||||||
for i in collection_list:
|
|
||||||
if x % 2 == 0:
|
|
||||||
c = 0
|
|
||||||
else:
|
|
||||||
c = 1
|
|
||||||
if i.collection not in collection_key:
|
|
||||||
collections.append(
|
|
||||||
{"string": i.collection, "link": i.collection, "class": c}
|
|
||||||
)
|
|
||||||
collection_key.append(i.collection)
|
|
||||||
x = x + 1
|
|
||||||
return collections
|
|
||||||
|
|
||||||
|
|
||||||
def next_page(request, bookset):
|
def next_page(request, bookset):
|
||||||
"""
|
"""
|
||||||
Goto next page in bookset
|
Goto next page in bookset
|
||||||
@@ -79,7 +59,12 @@ def next_page(request, bookset):
|
|||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
"index.html",
|
"index.html",
|
||||||
{"Books": book_set(None, _set), "Set": str(_set), "Version": config.VERSION},
|
{
|
||||||
|
"Books": book_set(None, _set),
|
||||||
|
"Set": str(_set),
|
||||||
|
"Version": config.VERSION,
|
||||||
|
"LeftNav": menu("collections"),
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -98,7 +83,12 @@ def prev_page(request, bookset):
|
|||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
"index.html",
|
"index.html",
|
||||||
{"Books": book_set(None, _set), "Set": str(_set), "Version": config.VERSION},
|
{
|
||||||
|
"Books": book_set(None, _set),
|
||||||
|
"Set": str(_set),
|
||||||
|
"Version": config.VERSION,
|
||||||
|
"LeftNav": menu("collections"),
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -127,6 +117,7 @@ def search(request, query=None, _set=1, _limit=None):
|
|||||||
"Set": _set,
|
"Set": _set,
|
||||||
"len_results": search_len,
|
"len_results": search_len,
|
||||||
"Version": config.VERSION,
|
"Version": config.VERSION,
|
||||||
|
"LeftNav": menu("collections"),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -197,3 +188,33 @@ def hr_name(book):
|
|||||||
Nicer file names
|
Nicer file names
|
||||||
"""
|
"""
|
||||||
return "{0}{1}".format(slugify(book.title), os.path.splitext(book.file_name)[1])
|
return "{0}{1}".format(slugify(book.title), os.path.splitext(book.file_name)[1])
|
||||||
|
|
||||||
|
|
||||||
|
def menu(which, _set=1):
|
||||||
|
if which == "collections":
|
||||||
|
collection_list = Collections.objects.all()
|
||||||
|
collections, collection_key, x = [], [], 0
|
||||||
|
for i in collection_list:
|
||||||
|
if i.collection not in collection_key:
|
||||||
|
# Using c as the alternating row identifier
|
||||||
|
# set c here
|
||||||
|
if x % 2 == 0:
|
||||||
|
c = 0
|
||||||
|
else:
|
||||||
|
c = 1
|
||||||
|
if x <= 10:
|
||||||
|
x = x + 1
|
||||||
|
else:
|
||||||
|
x = 0
|
||||||
|
breakpoint()
|
||||||
|
# TODO trim #'s and symbols from front of collection name
|
||||||
|
if len(i.collection) > 16:
|
||||||
|
collection_string = i.collection[0:16] + " ..."
|
||||||
|
else:
|
||||||
|
collection_string = i.collection
|
||||||
|
|
||||||
|
collections.append(
|
||||||
|
{"string": collection_string, "link": i.collection, "class": c}
|
||||||
|
)
|
||||||
|
collection_key.append(i.collection)
|
||||||
|
return collections
|
||||||
|
|||||||
Reference in New Issue
Block a user