Merge pull request #70 from th3r00t/admin

V 0.7.0 Update.
This commit is contained in:
th3r00t
2021-08-14 21:58:53 +00:00
committed by GitHub
15 changed files with 135 additions and 126 deletions

18
.gitattributes vendored
View File

@@ -1,14 +1,4 @@
docs/* linguist-documentation
src/backend/*
src/interace/static/css/* linguist-vendored
src/interface/admin.py
src/interface/apps.py
src/interface/forms.py
src/interface/models.py
src/interface/tests.py
src/interfaec/views.py
src/interface/templates/*
src/interface/templatetags/*
src/interace/static/js/pyshelf_ux.js
src/frontend/urs.py
src/frontend/settings.py
* linguist-vendored
*.py linguist-vendored=false
*.js linguist-vendored=false
*.html linguist-vendored=false

53
README.md vendored
View File

@@ -1,4 +1,4 @@
# pyShelf 0.6.1
# pyShelf 0.7.0
<p align="center"><b>Terminal based ebook server. Open source & Lightweight.</b></p>
<p align="center">Having used Calibre for hosting my eBook collection in the past, I found myself frustrated having to install X on my server, or manage my library externally, Thus I have decided to spin up my own.</p>
@@ -14,6 +14,12 @@ Follow or influence development @ <p align="center"><b>
<a href="https://discord.gg/H9TbNJS">Discord</a>
</b></p>
## 0.7.0 Patch Notes.
# New Features
* Administration System
* PDF Support
## Current Features
@@ -43,49 +49,6 @@ Follow or influence development @ <p align="center"><b>
* mobi
* pdf
## 0.6.1 Patch Notes.
# New Features
* PDF Format
* Image & Description acquisition needs work.
## 0.6.0 Patch Notes.
# New Features
* Automated Collections
* A work in progress, the collections are based on your folder structure.
* User System
* Per User Favorites
* Expanded book information view
* Websocket server
* currently only responds to ping, and importBooks, more responders are planned.
* Full <b>Docker</b> integration.
* On Demand Importing
* .mobi Support
* Result set ordering
* You can now choose to order your results:
* Title
* Author
* Categories
* & Tags
* Reworked UI/UX
* More intuitive, less intrusive, & stays out of the way. <i>caveat: I need to rework the placement of the next & previous page controls. While they do remain usable, I intend to have them follow the users</i>
position on the page in future releases.
![pyShelf 0.6.0 navbar](https://github.com/th3r00t/pyShelf/raw/master/src/interface/static/img/navbar.png)
* New controls
* Sort
* Ascending / Descending result set
* Display of the result set count, and your current position in the set.
* A pop over layer to hold things like
* [x] User login & Registration
* [x] Control panel
* [x] Book details
## Installation & Support Information
# Installation
@@ -133,7 +96,7 @@ The first step is to login, after logging in the button whill show your username
- [x] Automated Collections
- [ ] Manual Collections
- [ ] Books Removal
- [x] Books Removal
- [ ] Access Restrictions
- [ ] Metadata Manipulation
- [ ] Others?

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": "*", "SECRET": "", "BUILD_MODE": "production"}
{"TITLE": "pyShelf E-Book Server", "VERSION": "0.7.0", "BOOKPATH": "", "DB_HOST": "localhost", "DB_PORT": "5432", "DATABASE": "pyshelf", "USER": "pyshelf", "PASSWORD": "pyshelf", "BOOKSHELF": "data/shelf.json", "ALLOWED_HOSTS": "*", "SECRET": "", "BUILD_MODE": "production"}

2
doxygen.conf vendored
View File

@@ -38,7 +38,7 @@ PROJECT_NAME = "pyShelf Open Source Ebook Server"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 0.6.0
PROJECT_NUMBER = 0.7.0
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

View File

@@ -22,9 +22,10 @@ from django.urls import include, path, re_path
from django.conf.urls.static import static
from asgiref.sync import sync_to_async
from interface import views
from interface.admin import admin_site
urlpatterns = [
path("admin/", admin.site.urls),
path("admin/", admin_site.urls),
path("", views.index, name="index"),
path("home", views.home, name="home"),
re_path("^live$", views.live, name="live"),

View File

@@ -1,4 +1,5 @@
from django.contrib import admin
from django.contrib.admin import AdminSite
from django.contrib.auth.admin import UserAdmin
from .models import Books, Collections, Favorites, Navigation, User
@@ -22,8 +23,27 @@ class CustomUserAdmin(UserAdmin):
)
admin.site.register(Books)
admin.site.register(Collections)
admin.site.register(Favorites)
admin.site.register(Navigation)
admin.site.register(User, CustomUserAdmin)
class pyShelfAdminSite(AdminSite):
site_title = 'pyShelf admin'
site_header = 'pyShelf Administration'
index_title = 'Library'
class BookModelSearch(admin.ModelAdmin):
search_fields=('title','author','tags')
class CollectionModelSearch(admin.ModelAdmin):
search_fields=('collection',)
class FavoritesModelSearch(admin.ModelAdmin):
search_fields=('user_id',)
admin_site = pyShelfAdminSite(name='pyadmin')
admin_site.register(Books, BookModelSearch)
admin_site.register(Collections, CollectionModelSearch)
admin_site.register(Favorites, FavoritesModelSearch)
admin_site.register(Navigation)
admin_site.register(User, CustomUserAdmin)

View File

@@ -21,6 +21,7 @@ class Books(models.Model):
class Meta:
db_table = "books"
verbose_name_plural = 'Books'
def __str__(self):
return self.title
@@ -59,6 +60,7 @@ class Books(models.Model):
class Collections(models.Model):
class Meta:
db_table = "collections"
verbose_name_plural = 'Collections'
def __str__(self):
return self.collection.__str__()
@@ -120,6 +122,7 @@ class Navigation(models.Model):
class Meta:
db_table = "navigation"
verbose_name_plural = "Navigation"
def __str__(self):
return self.title
@@ -162,6 +165,7 @@ class Favorites(models.Model):
class Meta:
db_table = "favorites"
verbose_name_plural = "Favorites"
def __str__(self):
return str(self.book)

View File

@@ -13,19 +13,19 @@ body {
padding: 0;
font-size: 14px;
font-family: "Roboto","Lucida Grande","DejaVu Sans","Bitstream Vera Sans",Verdana,Arial,sans-serif;
color: #333;
background: #fff;
color: #fff;
background: #282828;
}
/* LINKS */
a:link, a:visited {
color: #447e9b;
color: #fff;
text-decoration: none;
}
a:focus, a:hover {
color: #036;
color: #909090;
}
a:focus {
@@ -64,7 +64,7 @@ h1 {
margin: 0 0 20px;
font-weight: 300;
font-size: 20px;
color: #666;
color: #3f3;
}
h2 {
@@ -234,10 +234,10 @@ th {
thead th,
tfoot td {
color: #666;
color: #000;
padding: 5px 10px;
font-size: 11px;
background: #fff;
background: #676767;
border: none;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
@@ -253,18 +253,18 @@ thead th.required {
}
tr.alt {
background: #f6f6f6;
background: #797979;
}
tr:nth-child(odd), .row-form-errors {
background: #fff;
background: #676767;
}
tr:nth-child(even),
tr:nth-child(even) .errorlist,
tr:nth-child(odd) + .row-form-errors,
tr:nth-child(odd) + .row-form-errors .errorlist {
background: #f9f9f9;
background: #797979;
}
/* SORTABLE TABLES */
@@ -273,15 +273,15 @@ thead th {
padding: 5px 10px;
line-height: normal;
text-transform: uppercase;
background: #f6f6f6;
background: #797979;
}
thead th a:link, thead th a:visited {
color: #666;
color: #000;
}
thead th.sorted {
background: #eee;
background: #797979;
}
thead th.sorted .text {
@@ -300,7 +300,7 @@ table thead th .text a {
}
table thead th .text a:focus, table thead th .text a:hover {
background: #eee;
background: #797979;
}
thead th.sorted a.sortremove {
@@ -327,7 +327,7 @@ table thead th.sorted .sortpriority {
margin-right: 2px;
}
table thead th.sorted .sortoptions a {
table thead th.sort79797e.sortoptions a {
position: relative;
width: 14px;
height: 14px;
@@ -424,7 +424,7 @@ select[multiple] {
/* FORM BUTTONS */
.button, input[type=submit], input[type=button], .submit-row input, a.button {
background: #79aec8;
background: #888;
padding: 10px 15px;
border: none;
border-radius: 4px;
@@ -471,7 +471,7 @@ input[type=button][disabled].default {
.module {
border: none;
margin-bottom: 30px;
background: #fff;
background: #363636;
}
.module p, .module ul, .module h3, .module h4, .module dl, .module pre {
@@ -497,7 +497,7 @@ input[type=button][disabled].default {
font-weight: 400;
font-size: 13px;
text-align: left;
background: #79aec8;
background: #888;
color: #fff;
}
@@ -608,7 +608,7 @@ td ul.errorlist + input, td ul.errorlist + select, td ul.errorlist + textarea {
/* BREADCRUMBS */
div.breadcrumbs {
background: #79aec8;
background: #888;
padding: 10px 40px;
border: none;
font-size: 14px;
@@ -812,10 +812,12 @@ table#change-history tbody th {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 40px;
background: #417690;
color: #ffc;
padding: 10px 10px;
background: #363636;
color: #3f3;
overflow: hidden;
border-bottom: #3f3 1px solid;
margin-bottom: 5px;
}
#header a:link, #header a:visited {
@@ -835,11 +837,11 @@ table#change-history tbody th {
margin: 0 20px 0 0;
font-weight: 300;
font-size: 24px;
color: #f5dd5d;
color: #3f3;
}
#branding h1, #branding h1 a:link, #branding h1 a:visited {
color: #f5dd5d;
color: #3f3;
}
#branding h2 {
@@ -871,14 +873,14 @@ table#change-history tbody th {
#user-tools a:focus, #user-tools a:hover {
text-decoration: none;
border-bottom-color: #79aec8;
color: #79aec8;
border-bottom-color: #888;
color: #888;
}
/* SIDEBAR */
#content-related {
background: #f8f8f8;
background: #797979;
}
#content-related .module {
@@ -887,7 +889,7 @@ table#change-history tbody th {
#content-related h3 {
font-size: 14px;
color: #666;
color: #fff;
padding: 0 16px;
margin: 0 0 16px;
}
@@ -918,7 +920,7 @@ table#change-history tbody th {
margin-bottom: 16px;
border-bottom: 1px solid #eaeaea;
font-size: 18px;
color: #333;
color: #f7f7f7;
}
.delete-confirmation form input[type="submit"] {

View File

@@ -34,13 +34,13 @@
}
#changelist .toplinks {
border-bottom: 1px solid #ddd;
border-bottom: 1px solid #363636;
}
#changelist .paginator {
color: #666;
border-bottom: 1px solid #eee;
background: #fff;
border-bottom: 1px solid #363636;
background: #191919;
overflow: hidden;
}
@@ -69,10 +69,10 @@
#changelist #toolbar {
padding: 8px 10px;
margin-bottom: 15px;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
background: #f8f8f8;
margin-bottom: 0px;
border-top: 1px solid #363636;
border-bottom: 1px solid #363636;
background: #000;
color: #666;
}
@@ -127,7 +127,7 @@
right: 0;
z-index: 1000;
width: 240px;
background: #f8f8f8;
background: #000;
border-left: none;
margin: 0;
}
@@ -151,7 +151,7 @@
#changelist-filter ul {
margin: 5px 0;
padding: 0 15px 15px;
border-bottom: 1px solid #eaeaea;
border-bottom: 1px solid #282828;
}
#changelist-filter ul:last-child {
@@ -172,9 +172,10 @@
}
#changelist-filter li.selected {
border-left: 5px solid #eaeaea;
border-left: 5px solid #797979;
padding-left: 10px;
margin-left: -15px;
background-color: #282828;
}
#changelist-filter li.selected a {
@@ -282,11 +283,11 @@
#changelist .actions {
padding: 10px;
background: #fff;
background: #191919;
border-top: none;
border-bottom: none;
line-height: 24px;
color: #999;
color: #fff;
}
#changelist .actions.selected {
@@ -311,8 +312,8 @@
#changelist .actions select {
vertical-align: top;
height: 24px;
background: none;
color: #000;
background: #363636;
color: #fff;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 14px;
@@ -335,14 +336,14 @@
font-size: 13px;
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
background: #363636;
box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset;
cursor: pointer;
height: 24px;
line-height: 1;
padding: 4px 8px;
margin: 0;
color: #333;
color: #fff;
}
#changelist .actions .button:focus, #changelist .actions .button:hover {

View File

@@ -30,13 +30,13 @@ form .form-row p {
label {
font-weight: normal;
color: #666;
color: #fff;
font-size: 13px;
}
.required label, label.required {
font-weight: bold;
color: #333;
color: #999;
}
/* RADIO BUTTONS */
@@ -250,8 +250,8 @@ fieldset.monospace textarea {
.submit-row {
padding: 12px 14px;
margin: 0 0 20px;
background: #f8f8f8;
border: 1px solid #eee;
background: #888888;
border: 1px solid #3f3f3f;
border-radius: 4px;
text-align: right;
overflow: hidden;

View File

@@ -13,21 +13,22 @@
flex: 0 0 23px;
width: 23px;
border-right: 1px solid #eaeaea;
background-color: #ffffff;
background-color: #262626;
cursor: pointer;
font-size: 20px;
color: #447e9b;
padding: 0;
display: none !important;
}
[dir="rtl"] .toggle-nav-sidebar {
border-left: 1px solid #eaeaea;
border-left: 1px solid #262626;
border-right: 0;
}
.toggle-nav-sidebar:hover,
.toggle-nav-sidebar:focus {
background-color: #f6f6f6;
background-color: #000;
}
#nav-sidebar {
@@ -37,7 +38,8 @@
margin-left: -276px;
border-top: 1px solid transparent;
border-right: 1px solid #eaeaea;
background-color: #ffffff;
border: 0px;
background-color: #282828;
overflow: auto;
}
@@ -59,7 +61,7 @@
}
.main.shifted > #nav-sidebar {
left: 24px;
left: 0px;
margin-left: 0;
}
@@ -96,7 +98,7 @@
}
#nav-sidebar .current-model {
background: #ffc;
background: #555555;
}
@media (max-width: 767px) {

View File

@@ -10768,4 +10768,4 @@ a.nav_link {
.progress_container {
min-width: 300px !important;
}
}

View File

@@ -12,6 +12,27 @@
font-size: small;
}
.shelf_item{
width: fit-content;
}
#book_shelf {
justify-content: left;
flex-direction: column;
}
.book_description {
display: none;
}
.book_details_list {
display: grid;
grid-template-areas:
"book_title"
"book_author"
"book_tags"
"book_controls";
grid-area: details;
grid-template-rows: .5fr .5fr .15fr 0.25fr;
}
}
@@ -29,7 +50,8 @@
font-size: small;
}
.shelf_item{
max-width: min-content;
min-width: 100%;
margin: 0px auto 10px auto;
}
.nav_search{
/* display: none !important; */
@@ -47,7 +69,6 @@
padding: 0px;
margin: 0px 0px;
}
.vert-nav-item {}
#vert-nav {

View File

@@ -33,6 +33,7 @@ $(document).ready(function(){
const navlink = $('.nav_link')
const inputbox = $('input_box')
const loginbtn = $('#btn_login')
const adminbtn = $('.admin-btn')
const server = ('ws://127.0.0.1:1337')
customlog([cmp_height]);
$(".search_submit").click(function(){
@@ -170,6 +171,9 @@ $(document).ready(function(){
'<button type="submit" class="btn-sm btn-secondary import-btn"><i class="fas fa-file-import"></i>&nbsp; Import Books</button>' +
'</div>' +
'<div class="col-auto" id="usercp-col2">' +
'<button type="submit" class="btn-sm btn-secondary admin-btn"><i class="fas fa-sign-out-alt"></i>&nbsp; Admin</button>' +
'</div>' +
'<div class="col-auto" id="usercp-col3">' +
'<button type="submit" class="btn-sm btn-secondary logout-btn"><i class="fas fa-sign-out-alt"></i>&nbsp; Logout</button>' +
'</div>'
);
@@ -181,6 +185,7 @@ $(document).ready(function(){
$('#pop_over_0').dialog("open");
});
$(document).on('click', '.logout-btn', function(){window.location.href = '/logout'});
$(document).on('click', '.admin-btn', function(){window.location.href = '/admin'});
//Web Socket Call
$(document).on('click', '.import-btn', async function(){

View File

@@ -41,7 +41,7 @@
<li class="nav_menu_tab active_tab" id="btn-home" data-location="/home"><i class="fas fa-home"></i>&nbsp;Home</li>
<li class="nav_menu_tab" id="coll_button"><i class="fas fa-layer-group"></i>&nbsp;Collections</li>
<li class="nav_menu_tab"><i class="fas fa-star"></i><a href="/favorites" class="nav_link">&nbsp;Favorites,</a></li>
<li class="nav_menu_tab"><i class="fas fa-bug"></i>&nbsp;Bug report</li>
<li class="nav_menu_tab"><i class="fas fa-bug"></i>&nbsp;<a href="https://github.com/th3r00t/pyShelf/issues" class="nav_link">Bug report</a></li>
{% if request.user.is_authenticated %}
<li class="nav_menu_tab" id="btn_logout"><i class="fa fa-user-circle" aria-hidden="true"></i>&nbsp;{{ request.user }}