toggle ascending/descending mode

This commit is contained in:
Raelon Masters
2020-07-06 02:37:35 -04:00
parent 6af7bb459a
commit 4079e04d9b
17 changed files with 147 additions and 211 deletions

2
config.json vendored
View File

@@ -1 +1 @@
{"TITLE": "pyShelf E-Book Server", "VERSION": "0.6.0", "BOOKPATH": "", "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.6.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"}

View File

@@ -28,6 +28,7 @@ class Catalogue:
self.html_regx = re.compile(r"\.html")
self.title_sanitization_regx = re.compile(r"^(Book )+[0-9]*")
self.title_sanitization_lvl2_regx = re.compile(r"^(Book )+[0-9]*\W+(-)")
self.title_sanitization_dirs_regx = re.compile(r"/")
self.root_dir = config.root
self.book_folder = config.book_path
self.books = None

View File

@@ -1,6 +1,6 @@
#!/usr/bin/python
import re
import datetime
import psycopg2
@@ -53,7 +53,7 @@ class Storage:
Insert book in database
:returns: True if succeeds False if not
"""
q = "INSERT INTO books (title, author, cover, progress, file_name, pages, description, identifier, publisher, rights, tags) values (%s, %s, %s, 0, %s, 0, %s, %s, %s, %s, %s);"
q = "INSERT INTO books (title, author, cover, progress, file_name, pages, description, identifier, publisher, date, rights, tags) values (%s, %s, %s, 0, %s, 0, %s, %s, %s, %s, %s, %s);"
try:
try:
cover_image = book[2].data
@@ -71,7 +71,7 @@ class Storage:
book[4], # descr
book[5], # ident
book[6], # publisher
# book[7], # date # TODO: set import time
datetime.datetime.now(),
book[8], # rights
book[9], # tags
),
@@ -114,6 +114,7 @@ class Storage:
return True
def make_collections(self):
breakpoint()
_title_regx = re.compile(r"^[0-9][0-9]*|-|\ \B")
_q = "SELECT id,file_name FROM books"
self.cursor.execute(_q)

View File

@@ -23,6 +23,7 @@ urlpatterns = [
path("", views.index, name="index"),
path("home", views.home, name="index"),
path("sort/<_order>", views.index, name="index"),
path("flip_sort/<_order>", views.flip_sort, name="index"),
path("download/<pk>", views.download, name="download"),
path("favorite/<pk>", views.favorite, name="favorite"),
path("share/<pk>", views.share, name="share"),

95
src/interface/migrations/0001_initial.py Executable file → Normal file
View File

@@ -1,35 +1,90 @@
# Generated by Django 2.2.7 on 2019-11-28 19:24
# Generated by Django 3.0.7 on 2020-07-05 23:21
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = []
dependencies = [
]
operations = [
migrations.CreateModel(
name="Books",
name='Books',
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("title", models.CharField(max_length=255)),
("author", models.CharField(max_length=255, null=True)),
("categories", models.CharField(max_length=255, null=True)),
("cover", models.BinaryField(editable=True, null=True)),
("pages", models.IntegerField(null=True)),
("progress", models.IntegerField(null=True)),
("file_name", models.CharField(max_length=255)),
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.TextField()),
('author', models.CharField(max_length=255, null=True)),
('categories', models.TextField(null=True)),
('cover', models.BinaryField(editable=True, null=True)),
('pages', models.IntegerField(null=True)),
('progress', models.IntegerField(null=True)),
('file_name', models.TextField()),
('description', models.TextField(null=True)),
('identifier', models.CharField(max_length=255, null=True)),
('publisher', models.TextField(null=True)),
('date', models.DateField(null=True)),
('rights', models.CharField(max_length=255, null=True)),
('tags', models.TextField(null=True)),
],
options={"db_table": "books",},
options={
'db_table': 'books',
},
),
migrations.CreateModel(
name='Navigation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=255)),
('link', models.CharField(max_length=255, null=True)),
('category', models.CharField(max_length=255, null=True)),
('parent_id', models.IntegerField(null=True)),
('alt', models.CharField(max_length=255, null=True)),
('type', models.IntegerField(null=True)),
('socket', models.CharField(max_length=255)),
],
options={
'db_table': 'navigation',
},
),
migrations.CreateModel(
name='Users',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uname', models.CharField(max_length=255)),
('fname', models.CharField(max_length=255, null=True)),
('lname', models.CharField(max_length=255, null=True)),
('email', models.CharField(max_length=255, null=True)),
('password', models.CharField(max_length=255, null=True)),
('ulvl', models.IntegerField(null=True)),
],
options={
'db_table': 'users',
},
),
migrations.CreateModel(
name='Favorites',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('favorite', models.ManyToManyField(to='interface.Books')),
('uname', models.ManyToManyField(to='interface.Users')),
],
options={
'db_table': 'favorites',
},
),
migrations.CreateModel(
name='Collections',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('collection', models.CharField(max_length=255)),
('book_id', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='interface.Books')),
],
options={
'db_table': 'collections',
},
),
]

View File

@@ -1,14 +0,0 @@
# Generated by Django 2.2.7 on 2020-01-01 04:45
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("interface", "0001_initial"),
]
operations = [
migrations.AlterModelOptions(name="books", options={"managed": False},),
]

View File

@@ -1,14 +0,0 @@
# Generated by Django 2.2.7 on 2020-01-01 04:47
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("interface", "0002_auto_20200101_0445"),
]
operations = [
migrations.AlterModelOptions(name="books", options={},),
]

View File

@@ -1,37 +0,0 @@
# Generated by Django 3.0.2 on 2020-02-04 20:22
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("interface", "0003_auto_20200101_0447"),
]
operations = [
migrations.CreateModel(
name="Collections",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("collection", models.CharField(max_length=255)),
(
"book_id",
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
to="interface.Books",
),
),
],
options={"db_table": "collections",},
),
]

View File

@@ -1,35 +0,0 @@
# Generated by Django 3.0.4 on 2020-06-10 05:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("interface", "0004_collections"),
]
operations = [
migrations.CreateModel(
name="Navigation",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("title", models.CharField(max_length=255)),
("link", models.CharField(max_length=255, null=True)),
("category", models.CharField(max_length=255, null=True)),
("parent_id", models.IntegerField(null=True)),
("alt", models.CharField(max_length=255, null=True)),
("type", models.IntegerField(null=True)),
("socket", models.CharField(max_length=255)),
],
options={"db_table": "navigation",},
),
]

View File

@@ -1,69 +0,0 @@
# Generated by Django 3.0.7 on 2020-06-17 23:33
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('interface', '0005_navigation'),
]
operations = [
migrations.CreateModel(
name='Users',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uname', models.CharField(max_length=255)),
('fname', models.CharField(max_length=255, null=True)),
('lname', models.CharField(max_length=255, null=True)),
('email', models.CharField(max_length=255, null=True)),
('password', models.CharField(max_length=255, null=True)),
('ulvl', models.IntegerField(null=True)),
],
options={
'db_table': 'users',
},
),
migrations.AddField(
model_name='books',
name='date',
field=models.DateField(null=True),
),
migrations.AddField(
model_name='books',
name='description',
field=models.TextField(null=True),
),
migrations.AddField(
model_name='books',
name='identifier',
field=models.CharField(max_length=255, null=True),
),
migrations.AddField(
model_name='books',
name='publisher',
field=models.CharField(max_length=266, null=True),
),
migrations.AddField(
model_name='books',
name='rights',
field=models.CharField(max_length=255, null=True),
),
migrations.AddField(
model_name='books',
name='tags',
field=models.CharField(max_length=255, null=True),
),
migrations.CreateModel(
name='Favorites',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('favorite', models.ManyToManyField(to='interface.Books')),
('uname', models.ManyToManyField(to='interface.Users')),
],
options={
'db_table': 'favorites',
},
),
]

0
src/interface/migrations/__init__.py Executable file → Normal file
View File

View File

@@ -22,19 +22,20 @@ class Books(models.Model):
def __str__(self):
return self.title
title = models.CharField(max_length=255)
title = models.TextField(max_length=None)
author = models.CharField(max_length=255, null=True)
categories = models.CharField(max_length=255, null=True)
categories = models.TextField(max_length=None, null=True)
cover = models.BinaryField(null=True, editable=True)
pages = models.IntegerField(null=True)
progress = models.IntegerField(null=True)
file_name = models.CharField(max_length=255, null=False)
file_name = models.TextField(max_length=None, null=False)
date = models.DateTimeField(auto_now_add=True)
description = models.TextField(null=True)
identifier = models.CharField(max_length=255, null=True)
publisher = models.CharField(max_length=266, null=True)
publisher = models.TextField(max_length=None, null=True)
date = models.DateField(null=True)
rights = models.CharField(max_length=255, null=True)
tags = models.CharField(max_length=255, null=True)
tags = models.TextField(max_length=None, null=True)
def generic_search(self, query):
try:
@@ -68,7 +69,6 @@ class Collections(models.Model):
raise
return results
class Navigation(models.Model):
"""
pyShelfs Navigation Database class
@@ -105,7 +105,6 @@ class Navigation(models.Model):
raise
return results
class Users(models.Model):
"""
pyShelfs User Database class
@@ -139,7 +138,6 @@ class Users(models.Model):
raise
return results
class Favorites(models.Model):
"""
pyShelfs User Database class

View File

@@ -349,6 +349,11 @@ body {
/* min-width: 55px; */
}
#flip_sort {
margin: 0px;
display: inline-flex;
}
.ui_icon_notxt {
margin: 0px 5px 0px 0px;
}

View File

@@ -364,6 +364,10 @@ body {
justify-content: center;
align-items: center;/* min-width: 55px; */
}
#flip_sort{
margin: 0px;
display: inline-flex;
}
.ui_icon_notxt{
margin: 0px 5px 0px 0px;
}

View File

@@ -84,6 +84,9 @@ $(document).ready(function(){
_location = $(this).attr('data-location');
window.location.href=_location;
});
$('#flip_sort').on("click", function(){
window.location.href="/flip_sort/"+$("#_order").val()
});
$('#search_string').html("<i> "+$('#_search').val().substr(0,15)+"</i>")
resize_search();
$(window).resize(resize_search(win_width));

View File

@@ -59,8 +59,10 @@
</select>
</div>
<div id="horiz_nav_center">
<div id="flip_sort" class="btn">
<i class="fas fa-sort-alpha-down nav_icon"></i>
<i class="fas fa-sort-alpha-up nav_icon"></i>
</div>
<input class="nav_search input_box search_string" type="text" size="40" value="search by Title, Author, Tags, or Collections">
<i class="fas fa-search search_submit search_button" id="search_string" onclick="window.location.href = '/prev_page/{{ Set }}'"></i>
</div>

View File

@@ -60,6 +60,19 @@ def show_collection(request, _collection, _colset):
},
)
def flip_sort(request, bookset=1, query=None, _limit=None, _order='title'):
"""
Goto next page in bookset
"""
try: _set = int(bookset)
except Exception: _set = 1
_payload = payload(request, query, _set, _limit, _order, flip_sort=True)
return render(
request,
"index.html",
_payload,
)
def next_page(request, bookset, query=None, _limit=None, _order='title'):
"""
Goto next page in bookset
@@ -94,7 +107,7 @@ def prev_page(request, bookset, query=None, _limit=None, _order='title'):
_payload,
)
def book_set(_order, _limit=None, _set=1):
def book_set(_order, _limit=None, _set=1, _flip=False):
"""
Get books results by set #
"""
@@ -102,6 +115,9 @@ def book_set(_order, _limit=None, _set=1):
_limit = 20 # TODO default from user choice
_set_max = int(_set) * _limit
_set_min = _set_max - _limit
if _flip:
books = Books.objects.all().order_by(_order).reverse()[_set_min:_set_max]
else:
books = Books.objects.all().order_by(_order)[_set_min:_set_max]
return books
@@ -247,7 +263,15 @@ def collections_list():
def payload(request, query, _set, _limit, _order, **kwargs):
"""
Return formatted data to template
: notes : This is the least pythonic function I have ever written, but its
still beautiful
"""
try: request.session['ascending']
except KeyError: request.session['ascending'] = bool
try:
if kwargs['flip_sort']:
request.session['ascending'] = not request.session['ascending']
except KeyError: pass
try:
if kwargs['reset']:
request.session['cached_query'] = query
@@ -256,7 +280,10 @@ def payload(request, query, _set, _limit, _order, **kwargs):
_set_max = int(_set) * _limit
_set_min = _set_max - _limit
_now_showing = "%s-%s"%(_set_min, _set_max)
_r, _r_len, _search = book_set(_order, _limit, _set), None, None
if request.session['ascending']:
_r = book_set(_order, _limit, _set)
else: _r = book_set(_order, _limit, _set, True)
_r_len, _search = None, None
except KeyError:
_set = int(_set)
if _set < 1: _set = 1
@@ -267,26 +294,34 @@ def payload(request, query, _set, _limit, _order, **kwargs):
if query:
if query != request.session.get('cached_query'):
request.session['cached_query'] = query
if request.session['ascending']:
_results = Books().generic_search(query)
else: _results = Books().generic_search(query).reverse()
_r, _r_len = \
_results[_set_min:_set_max],\
_results.count()
elif query == request.session.get('cached_query'):
if request.session['ascending']:
_results = Books().generic_search(query)
else: _results = Books().generic_search(query).reverse()
_r, _r_len = \
_results.order_by(_order)[_set_min:_set_max],\
_results.count()
else:
try:
query = request.session['cached_query']
if query == None: raise KeyError
if request.session['ascending']:
_results = Books().generic_search(query)
else: _results = Books().generic_search(query).reverse()
_r, _r_len = \
_results.order_by(_order)[_set_min:_set_max],\
_results.count()
except KeyError:
_r, _r_len, _search = book_set(_order, _limit, _set), None, None
if request.session['ascending']:
_r = book_set(_order, _limit, _set)
else: _r = book_set(_order, _limit, _set, True)
_r_len, _search = None, None
_bookstats, _collectionstats, _collectionobject = \
Books.objects.all().count, Collections.objects.all().count, \