mirror of
https://github.com/th3r00t/pyShelf.git
synced 2026-04-28 01:59:35 -04:00
Merge pull request #48 from th3r00t/newui
Roll Favorites system into Development
This commit is contained in:
@@ -52,7 +52,7 @@ INSTALLED_APPS = [
|
|||||||
"interface.templatetags",
|
"interface.templatetags",
|
||||||
"debug_toolbar",
|
"debug_toolbar",
|
||||||
]
|
]
|
||||||
AUTH_USER_MODEL = "interface.CustomUser"
|
AUTH_USER_MODEL = "interface.User"
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
"django.middleware.security.SecurityMiddleware",
|
"django.middleware.security.SecurityMiddleware",
|
||||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ from django.conf import settings
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import include, path, re_path
|
from django.urls import include, path, re_path
|
||||||
from django.contrib.auth import views as auth_views
|
from django.contrib.auth import views as auth_views
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from django.shortcuts import HttpResponse
|
||||||
from interface import views
|
from interface import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
@@ -26,7 +28,6 @@ urlpatterns = [
|
|||||||
path("sort/<_order>", views.index, name="index"),
|
path("sort/<_order>", views.index, name="index"),
|
||||||
path("flip_sort/<_order>", views.flip_sort, name="index"),
|
path("flip_sort/<_order>", views.flip_sort, name="index"),
|
||||||
path("download/<pk>", views.download, name="download"),
|
path("download/<pk>", views.download, name="download"),
|
||||||
path("favorite/<pk>", views.favorite, name="favorite"),
|
|
||||||
path("share/<pk>", views.share, name="share"),
|
path("share/<pk>", views.share, name="share"),
|
||||||
path("share/<pk>", views.info, name="info"),
|
path("share/<pk>", views.info, name="info"),
|
||||||
path("prev_page/<bookset>", views.prev_page, name="prev_page"),
|
path("prev_page/<bookset>", views.prev_page, name="prev_page"),
|
||||||
@@ -40,6 +41,7 @@ urlpatterns = [
|
|||||||
path("signup", views.signup, name="signup"),
|
path("signup", views.signup, name="signup"),
|
||||||
path("login", views.userlogin, name="login"),
|
path("login", views.userlogin, name="login"),
|
||||||
path('logout', views.userlogout, name='logout'),
|
path('logout', views.userlogout, name='logout'),
|
||||||
|
path('favorite/<pk>', views.favorite, name='favorite'),
|
||||||
path(
|
path(
|
||||||
'admin/password_reset/',
|
'admin/password_reset/',
|
||||||
auth_views.PasswordResetView.as_view(),
|
auth_views.PasswordResetView.as_view(),
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.auth.admin import UserAdmin
|
from django.contrib.auth.admin import UserAdmin
|
||||||
|
|
||||||
from .models import Books, Collections, Favorites, Navigation, CustomUser
|
from .models import Books, Collections, Favorites, Navigation, User
|
||||||
from .forms import CustomUserCreationForm, CustomUserChangeForm
|
from .forms import CustomUserCreationForm, CustomUserChangeForm
|
||||||
|
|
||||||
|
|
||||||
class CustomUserAdmin(UserAdmin):
|
class CustomUserAdmin(UserAdmin):
|
||||||
model = CustomUser
|
model = User
|
||||||
add_form = CustomUserCreationForm
|
add_form = CustomUserCreationForm
|
||||||
form = CustomUserChangeForm
|
form = CustomUserChangeForm
|
||||||
list_display = ["email", "username", "facebook", "twitter", "sponsorid", "matrixid"]
|
list_display = ["email", "username", "facebook", "twitter", "sponsorid", "matrixid"]
|
||||||
@@ -27,4 +27,4 @@ admin.site.register(Books)
|
|||||||
admin.site.register(Collections)
|
admin.site.register(Collections)
|
||||||
admin.site.register(Favorites)
|
admin.site.register(Favorites)
|
||||||
admin.site.register(Navigation)
|
admin.site.register(Navigation)
|
||||||
admin.site.register(CustomUser, CustomUserAdmin)
|
admin.site.register(User, CustomUserAdmin)
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.auth.forms import UserCreationForm, UserChangeForm, AuthenticationForm
|
from django.contrib.auth.forms import UserCreationForm, UserChangeForm, AuthenticationForm
|
||||||
from .models import CustomUser
|
from .models import User
|
||||||
|
|
||||||
|
|
||||||
class CustomUserCreationForm(UserCreationForm):
|
class CustomUserCreationForm(UserCreationForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CustomUser
|
model = User
|
||||||
fields = ("username", "email", "facebook", "twitter", "sponsorid", "matrixid")
|
fields = ("username", "email", "facebook", "twitter", "sponsorid", "matrixid")
|
||||||
|
|
||||||
|
|
||||||
class CustomUserChangeForm(UserChangeForm):
|
class CustomUserChangeForm(UserChangeForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CustomUser
|
model = User
|
||||||
fields = ("username", "email", "facebook", "twitter", "sponsorid", "matrixid")
|
fields = ("username", "email", "facebook", "twitter", "sponsorid", "matrixid")
|
||||||
|
|
||||||
|
|
||||||
class CustomUserLoginForm(AuthenticationForm):
|
class CustomUserLoginForm(AuthenticationForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
Model = CustomUser
|
Model = User
|
||||||
fields = ("username", "password")
|
fields = ("username", "password")
|
||||||
|
|
||||||
|
|
||||||
@@ -27,11 +27,11 @@ class SignUpForm(CustomUserCreationForm):
|
|||||||
matrixid = forms.CharField(max_length=30, required=False, help_text='Optional.')
|
matrixid = forms.CharField(max_length=30, required=False, help_text='Optional.')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CustomUser
|
model = User
|
||||||
fields = ("username", "email", "matrixid")
|
fields = ("username", "email", "matrixid")
|
||||||
|
|
||||||
|
|
||||||
class UserLoginForm(CustomUserLoginForm):
|
class UserLoginForm(CustomUserLoginForm):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CustomUser
|
model = User
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
from django.contrib.postgres.search import SearchVector
|
from django.contrib.postgres.search import SearchVector
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import AbstractUser
|
from django.contrib.auth.models import AbstractUser, User
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
|
|
||||||
@@ -110,25 +111,38 @@ class Navigation(models.Model):
|
|||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
class User(AbstractUser):
|
||||||
|
facebook = models.CharField(max_length=255, null=True)
|
||||||
|
twitter = models.CharField(max_length=255, null=True)
|
||||||
|
ulvl = models.IntegerField(default=1)
|
||||||
|
sponsorid = models.IntegerField(null=True)
|
||||||
|
matrixid = models.CharField(max_length=255, null=True)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.username
|
||||||
|
|
||||||
|
|
||||||
class Favorites(models.Model):
|
class Favorites(models.Model):
|
||||||
"""
|
"""
|
||||||
pyShelfs User Database class
|
Favorites Database class
|
||||||
:param uname: User Name
|
:param book: book foreign key
|
||||||
:param fname: First Name
|
:param user: user foreign key
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = "favorites"
|
db_table = "favorites"
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.title
|
return self.book
|
||||||
|
|
||||||
favorite = models.ManyToManyField(Books)
|
book = models.ForeignKey(Books, on_delete=models.CASCADE)
|
||||||
uname = models.ManyToManyField(settings.AUTH_USER_MODEL)
|
user = models.ForeignKey(
|
||||||
|
User,
|
||||||
|
on_delete=models.CASCADE
|
||||||
|
)
|
||||||
def generic_search(self, query):
|
def generic_search(self, query):
|
||||||
try:
|
try:
|
||||||
results = Favorites.objects.annotate(search=SearchVector("uname"),).filter(
|
results = Favorites.objects.annotate(search=SearchVector("user"),).filter(
|
||||||
search=query
|
search=query
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -136,9 +150,3 @@ class Favorites(models.Model):
|
|||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
class CustomUser(AbstractUser):
|
|
||||||
facebook = models.CharField(max_length=255, null=True)
|
|
||||||
twitter = models.CharField(max_length=255, null=True)
|
|
||||||
ulvl = models.IntegerField(default=1)
|
|
||||||
sponsorid = models.IntegerField(null=True)
|
|
||||||
matrixid = models.CharField(max_length=255, null=True)
|
|
||||||
|
|||||||
4
src/interface/static/css/main.css
vendored
4
src/interface/static/css/main.css
vendored
@@ -541,6 +541,10 @@ a.book_link {
|
|||||||
padding: 5px 10px 5px 10px;
|
padding: 5px 10px 5px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.favorite {
|
||||||
|
color: #a7ff00 !important;
|
||||||
|
}
|
||||||
|
|
||||||
.controls {
|
.controls {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|||||||
3
src/interface/static/css/main.scss
vendored
3
src/interface/static/css/main.scss
vendored
@@ -552,6 +552,9 @@ a.book_link {
|
|||||||
font-size: x-large;
|
font-size: x-large;
|
||||||
padding: 5px 10px 5px 10px;
|
padding: 5px 10px 5px 10px;
|
||||||
}
|
}
|
||||||
|
.favorite{
|
||||||
|
color: #a7ff00 !important;
|
||||||
|
}
|
||||||
.controls{
|
.controls{
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|||||||
4
src/interface/static/js/pyshelf_ux.js
vendored
4
src/interface/static/js/pyshelf_ux.js
vendored
@@ -74,6 +74,9 @@ $(document).ready(function(){
|
|||||||
$('#btn_login').on('click', function(){
|
$('#btn_login').on('click', function(){
|
||||||
$('#hdr_nav_login').toggle();
|
$('#hdr_nav_login').toggle();
|
||||||
});
|
});
|
||||||
|
$('.favorite_action').on('click', function(){
|
||||||
|
$(this).toggleClass('favorite');
|
||||||
|
});
|
||||||
$('#sortlist').change(function () {
|
$('#sortlist').change(function () {
|
||||||
var optionSelected = $(this).find("option:selected");
|
var optionSelected = $(this).find("option:selected");
|
||||||
var valueSelected = optionSelected.val();
|
var valueSelected = optionSelected.val();
|
||||||
@@ -101,3 +104,4 @@ function resize_search(win_width){
|
|||||||
$('.search_string').val("Search");
|
$('.search_string').val("Search");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
12
src/interface/templates/index.html
vendored
12
src/interface/templates/index.html
vendored
@@ -39,9 +39,9 @@
|
|||||||
<li class="nav_menu_tab"><i class="fas fa-bug"></i> Bug report</li>
|
<li class="nav_menu_tab"><i class="fas fa-bug"></i> Bug report</li>
|
||||||
<li class="nav_menu_tab" id="btn_login"> <i class="fa fa-user-circle" aria-hidden="true"></i>
|
<li class="nav_menu_tab" id="btn_login"> <i class="fa fa-user-circle" aria-hidden="true"></i>
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
<a href='logout' class='nav_link'> {{ request.user }}</a>
|
<a href='/logout' class='nav_link'> {{ request.user }}</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="login" class='nav_link'> Login</a>
|
<a href="/login" class='nav_link'> Login</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
@@ -97,8 +97,12 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<li class="book_tags">Tags: {{ book.tags }}</li>
|
<li class="book_tags">Tags: {{ book.tags }}</li>
|
||||||
<li class="book_controls">
|
<li class="book_controls">
|
||||||
<span class="favorite-button controls">
|
<span class="favorite-button controls favorite_action">
|
||||||
<a href="{% url 'favorite' pk=book.pk %}" class="book_link"><i class="fas fa-thumbs-up icon"></i></a>
|
{% if book.is_favorite %}
|
||||||
|
<a href="{% url 'favorite' pk=book.pk %}" class="book_link favorite"><i class="fas fa-thumbs-up icon"></i></a>
|
||||||
|
{% else %}
|
||||||
|
<a href="{% url 'favorite' pk=book.pk %}" class="book_link not_favorite"><i class="fas fa-thumbs-up icon"></i></a>
|
||||||
|
{% endif %}
|
||||||
</span>
|
</span>
|
||||||
<span class="download-button controls">
|
<span class="download-button controls">
|
||||||
<a href="{% url 'download' pk=book.pk %}" class="book_link"><i class="fas fa-book icon"></i></a>
|
<a href="{% url 'download' pk=book.pk %}" class="book_link"><i class="fas fa-book icon"></i></a>
|
||||||
|
|||||||
@@ -8,10 +8,13 @@ from django.http import JsonResponse
|
|||||||
from django.shortcuts import HttpResponse, render, redirect # render_to_response
|
from django.shortcuts import HttpResponse, render, redirect # render_to_response
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
from django.contrib.auth import login, authenticate, logout
|
from django.contrib.auth import login, authenticate, logout
|
||||||
|
from django.contrib import auth
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
from django.conf import settings
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
import json
|
import json
|
||||||
from .forms import SignUpForm, UserLoginForm
|
from .forms import SignUpForm, UserLoginForm
|
||||||
from .models import Books, Collections, Navigation, Favorites
|
from .models import Books, Collections, Navigation, Favorites, User
|
||||||
|
|
||||||
config = Config(Path("../"))
|
config = Config(Path("../"))
|
||||||
|
|
||||||
@@ -53,6 +56,7 @@ def userlogin(request):
|
|||||||
user = authenticate(request, username=username, password=password)
|
user = authenticate(request, username=username, password=password)
|
||||||
if user is not None:
|
if user is not None:
|
||||||
login(request, user)
|
login(request, user)
|
||||||
|
user.save()
|
||||||
return redirect('home')
|
return redirect('home')
|
||||||
form = UserLoginForm()
|
form = UserLoginForm()
|
||||||
return render(request, 'login.html', {'form': form})
|
return render(request, 'login.html', {'form': form})
|
||||||
@@ -63,8 +67,8 @@ def userlogout(request):
|
|||||||
return redirect('home')
|
return redirect('home')
|
||||||
|
|
||||||
|
|
||||||
def home(request, query=None, _set=1, _limit=None, _order='title'):
|
def home(request, query=None, _set=1, _limit=None, _order='title'):
|
||||||
"""
|
"""
|
||||||
Reset Search Queries & Return Home
|
Reset Search Queries & Return Home
|
||||||
"""
|
"""
|
||||||
_payload = payload(request, query, _set, _limit, _order, reset='1')
|
_payload = payload(request, query, _set, _limit, _order, reset='1')
|
||||||
@@ -148,7 +152,7 @@ def prev_page(request, bookset, query=None, _limit=None, _order='title'):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def book_set(_order, _limit=None, _set=1, _flip=False):
|
def book_set(request, _order, _limit=None, _set=1, _flip=False):
|
||||||
"""
|
"""
|
||||||
Get books results by set #
|
Get books results by set #
|
||||||
"""
|
"""
|
||||||
@@ -160,7 +164,16 @@ def book_set(_order, _limit=None, _set=1, _flip=False):
|
|||||||
books = Books.objects.all().order_by(_order).reverse()[_set_min:_set_max]
|
books = Books.objects.all().order_by(_order).reverse()[_set_min:_set_max]
|
||||||
else:
|
else:
|
||||||
books = Books.objects.all().order_by(_order)[_set_min:_set_max]
|
books = Books.objects.all().order_by(_order)[_set_min:_set_max]
|
||||||
return books
|
try:
|
||||||
|
favorites = Favorites.objects.filter(user=request.user)
|
||||||
|
for book in books:
|
||||||
|
for favorite in favorites:
|
||||||
|
if book == favorite.book:
|
||||||
|
book.is_favorite = True
|
||||||
|
break
|
||||||
|
return books
|
||||||
|
except Exception as e:
|
||||||
|
return books
|
||||||
|
|
||||||
|
|
||||||
def collection(_collection, _set, _limit=None):
|
def collection(_collection, _set, _limit=None):
|
||||||
@@ -203,7 +216,7 @@ def download(request, pk):
|
|||||||
"""
|
"""
|
||||||
Download book by primary key
|
Download book by primary key
|
||||||
"""
|
"""
|
||||||
_book = Books.objects.all().filter(pk=pk)[0]
|
_book = Books.objects.get(pk=pk)
|
||||||
_fn = hr_name(_book)
|
_fn = hr_name(_book)
|
||||||
response = HttpResponse(
|
response = HttpResponse(
|
||||||
open(os.path.abspath(_book.file_name), "rb"), content_type="application/zip"
|
open(os.path.abspath(_book.file_name), "rb"), content_type="application/zip"
|
||||||
@@ -216,8 +229,14 @@ def favorite(request, pk):
|
|||||||
"""
|
"""
|
||||||
Add book to favorites bu primary key
|
Add book to favorites bu primary key
|
||||||
"""
|
"""
|
||||||
_book = Books.objects.all().filter(pk=pk)[0]
|
_d = Favorites.objects.filter(user=request.user, book=Books.objects.get(pk=pk))
|
||||||
print(Favorite(book=_book, uname=User))
|
if len(_d) == 1:
|
||||||
|
_d.delete()
|
||||||
|
return HttpResponse(status=204)
|
||||||
|
_f = Favorites(book=Books.objects.get(pk=pk))
|
||||||
|
_f.user = request.user
|
||||||
|
_f.save()
|
||||||
|
return HttpResponse(status=204)
|
||||||
|
|
||||||
|
|
||||||
def share(request, pk):
|
def share(request, pk):
|
||||||
@@ -328,8 +347,8 @@ def payload(request, query, _set, _limit, _order, **kwargs):
|
|||||||
_set_min = _set_max - _limit
|
_set_min = _set_max - _limit
|
||||||
_now_showing = "%s-%s"%(_set_min, _set_max)
|
_now_showing = "%s-%s"%(_set_min, _set_max)
|
||||||
if request.session['ascending']:
|
if request.session['ascending']:
|
||||||
_r = book_set(_order, _limit, _set)
|
_r = book_set(request, _order, _limit, _set)
|
||||||
else: _r = book_set(_order, _limit, _set, True)
|
else: _r = book_set(request, _order, _limit, _set, True)
|
||||||
_r_len, _search = None, None
|
_r_len, _search = None, None
|
||||||
except KeyError:
|
except KeyError:
|
||||||
_set = int(_set)
|
_set = int(_set)
|
||||||
@@ -366,8 +385,8 @@ def payload(request, query, _set, _limit, _order, **kwargs):
|
|||||||
_results.count()
|
_results.count()
|
||||||
except KeyError:
|
except KeyError:
|
||||||
if request.session['ascending']:
|
if request.session['ascending']:
|
||||||
_r = book_set(_order, _limit, _set)
|
_r = book_set(request, _order, _limit, _set)
|
||||||
else: _r = book_set(_order, _limit, _set, True)
|
else: _r = book_set(request, _order, _limit, _set, True)
|
||||||
_r_len, _search = None, None
|
_r_len, _search = None, None
|
||||||
|
|
||||||
_bookstats, _collectionstats, _collectionobject = \
|
_bookstats, _collectionstats, _collectionobject = \
|
||||||
|
|||||||
Reference in New Issue
Block a user