forked from mirrors/bookwyrm
128 lines
4.3 KiB
Python
128 lines
4.3 KiB
Python
''' non-interactive pages '''
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.core.paginator import Paginator
|
|
from django.db.models import Avg, Max
|
|
from django.template.response import TemplateResponse
|
|
from django.utils import timezone
|
|
from django.utils.decorators import method_decorator
|
|
from django.views import View
|
|
|
|
from bookwyrm import forms, models
|
|
from bookwyrm.settings import PAGE_LENGTH
|
|
from .helpers import get_activity_feed
|
|
|
|
|
|
# pylint: disable= no-self-use
|
|
class About(View):
|
|
''' create invites '''
|
|
def get(self, request):
|
|
''' more information about the instance '''
|
|
data = {
|
|
'title': 'About',
|
|
}
|
|
return TemplateResponse(request, 'about.html', data)
|
|
|
|
class Home(View):
|
|
''' discover page or home feed depending on auth '''
|
|
def get(self, request):
|
|
''' this is the same as the feed on the home tab '''
|
|
if request.user.is_authenticated:
|
|
feed_view = Feed.as_view()
|
|
return feed_view(request, 'home')
|
|
discover_view = Discover.as_view()
|
|
return discover_view(request)
|
|
|
|
class Discover(View):
|
|
''' preview of recently reviewed books '''
|
|
def get(self, request):
|
|
''' tiled book activity page '''
|
|
books = models.Edition.objects.filter(
|
|
review__published_date__isnull=False,
|
|
review__user__local=True,
|
|
review__privacy__in=['public', 'unlisted'],
|
|
).exclude(
|
|
cover__exact=''
|
|
).annotate(
|
|
Max('review__published_date')
|
|
).order_by('-review__published_date__max')[:6]
|
|
|
|
ratings = {}
|
|
for book in books:
|
|
reviews = models.Review.objects.filter(
|
|
book__in=book.parent_work.editions.all()
|
|
)
|
|
reviews = get_activity_feed(
|
|
request.user, ['public', 'unlisted'], queryset=reviews)
|
|
ratings[book.id] = reviews.aggregate(Avg('rating'))['rating__avg']
|
|
data = {
|
|
'title': 'Discover',
|
|
'register_form': forms.RegisterForm(),
|
|
'books': list(set(books)),
|
|
'ratings': ratings
|
|
}
|
|
return TemplateResponse(request, 'discover.html', data)
|
|
|
|
|
|
@method_decorator(login_required, name='dispatch')
|
|
class Feed(View):
|
|
''' activity stream '''
|
|
def get(self, request, tab):
|
|
''' user's homepage with activity feed '''
|
|
try:
|
|
page = int(request.GET.get('page', 1))
|
|
except ValueError:
|
|
page = 1
|
|
|
|
suggested_books = get_suggested_books(request.user)
|
|
|
|
if tab == 'home':
|
|
activities = get_activity_feed(
|
|
request.user, ['public', 'unlisted', 'followers'],
|
|
following_only=True)
|
|
elif tab == 'local':
|
|
activities = get_activity_feed(
|
|
request.user, ['public', 'followers'], local_only=True)
|
|
else:
|
|
activities = get_activity_feed(
|
|
request.user, ['public', 'followers'])
|
|
paginated = Paginator(activities, PAGE_LENGTH)
|
|
|
|
goal = models.AnnualGoal.objects.filter(
|
|
user=request.user, year=timezone.now().year
|
|
).first()
|
|
data = {
|
|
'title': 'Updates Feed',
|
|
'user': request.user,
|
|
'suggested_books': suggested_books,
|
|
'activities': paginated.page(page),
|
|
'tab': tab,
|
|
'goal': goal,
|
|
'goal_form': forms.GoalForm(),
|
|
}
|
|
return TemplateResponse(request, 'feed.html', data)
|
|
|
|
|
|
def get_suggested_books(user, max_books=5):
|
|
''' helper to get a user's recent books '''
|
|
book_count = 0
|
|
preset_shelves = [
|
|
('reading', max_books), ('read', 2), ('to-read', max_books)
|
|
]
|
|
suggested_books = []
|
|
for (preset, shelf_max) in preset_shelves:
|
|
limit = shelf_max if shelf_max < (max_books - book_count) \
|
|
else max_books - book_count
|
|
shelf = user.shelf_set.get(identifier=preset)
|
|
|
|
shelf_books = shelf.shelfbook_set.order_by(
|
|
'-updated_date'
|
|
).all()[:limit]
|
|
if not shelf_books:
|
|
continue
|
|
shelf_preview = {
|
|
'name': shelf.name,
|
|
'books': [s.book for s in shelf_books]
|
|
}
|
|
suggested_books.append(shelf_preview)
|
|
book_count += len(shelf_preview['books'])
|
|
return suggested_books
|