mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-12-14 04:06:36 +00:00
Merge branch 'main' into production
This commit is contained in:
commit
2719332e82
10 changed files with 215 additions and 40 deletions
|
@ -108,7 +108,7 @@ class Connector(AbstractConnector):
|
|||
def get_cover_url(self, cover_blob):
|
||||
''' ask openlibrary for the cover '''
|
||||
cover_id = cover_blob[0]
|
||||
image_name = '%s-M.jpg' % cover_id
|
||||
image_name = '%s-L.jpg' % cover_id
|
||||
return '%s/b/id/%s' % (self.covers_url, image_name)
|
||||
|
||||
|
||||
|
|
|
@ -67,6 +67,13 @@ input.toggle-control:checked ~ .modal.toggle-content {
|
|||
width: max-content;
|
||||
max-width: 250px;
|
||||
}
|
||||
.cover-container.is-large {
|
||||
height: max-content;
|
||||
max-width: 500px;
|
||||
}
|
||||
.cover-container.is-large img {
|
||||
max-height: 500px;
|
||||
}
|
||||
.cover-container.is-medium {
|
||||
height: 150px;
|
||||
}
|
||||
|
|
80
bookwyrm/templates/discover.html
Normal file
80
bookwyrm/templates/discover.html
Normal file
|
@ -0,0 +1,80 @@
|
|||
{% extends 'layout.html' %}
|
||||
{% block content %}
|
||||
|
||||
{% if not request.user.is_authenticated %}
|
||||
<div class="block">
|
||||
<h1 class="title has-text-centered">{{ site.name }}: Social Reading and Reviewing</h1>
|
||||
</div>
|
||||
|
||||
<section class="tile is-ancestor">
|
||||
<div class="tile is-7 is-parent">
|
||||
<div class="tile is-child block">
|
||||
{% include 'snippets/about.html' %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-5 is-parent">
|
||||
<div class="tile is-child box has-background-primary-light">
|
||||
{% if site.allow_registration %}
|
||||
<h2 class="title">Join {{ site.name }}</h2>
|
||||
<form name="register" method="post" action="/user-register">
|
||||
{% include 'snippets/register_form.html' %}
|
||||
</form>
|
||||
{% else %}
|
||||
<h2 class="title">This instance is closed</h2>
|
||||
<p>Contact an administrator to get an invite</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% else %}
|
||||
<div class="block">
|
||||
<h1 class="title has-text-centered">Discover</h1>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="block is-hidden-tablet">
|
||||
<h2 class="title has-text-centered">Recent Books</h2>
|
||||
</div>
|
||||
|
||||
<section class="tile is-ancestor">
|
||||
<div class="tile is-vertical">
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child box has-background-white-ter">
|
||||
{% include 'snippets/discover/large-book.html' with book=books.0 %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile">
|
||||
<div class="tile is-parent is-6">
|
||||
<div class="tile is-child box has-background-white-ter">
|
||||
{% include 'snippets/discover/small-book.html' with book=books.1 %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent is-6">
|
||||
<div class="tile is-child box has-background-white-ter">
|
||||
{% include 'snippets/discover/small-book.html' with book=books.2 %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-vertical">
|
||||
<div class="tile">
|
||||
<div class="tile is-parent is-6">
|
||||
<div class="tile is-child box has-background-white-ter">
|
||||
{% include 'snippets/discover/small-book.html' with book=books.3 %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent is-6">
|
||||
<div class="tile is-child box has-background-white-ter">
|
||||
{% include 'snippets/discover/small-book.html' with book=books.4 %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child box has-background-white-ter">
|
||||
{% include 'snippets/discover/large-book.html' with book=books.5 %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% endblock %}
|
|
@ -18,7 +18,7 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<nav class="navbar" role="navigation" aria-label="main navigation">
|
||||
<nav class="navbar container" role="navigation" aria-label="main navigation">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="/">
|
||||
<img class="image logo" src="/static/images/logo-small.png" alt="Home page">
|
||||
|
@ -63,7 +63,7 @@
|
|||
<div class="navbar-end">
|
||||
{% if request.user.is_authenticated %}
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<div class="navbar-link" role="button" aria-expanded=false" onmouseover="toggleMenu(this)" tabindex="0" aria-haspopup="true" aria-controls="navbar-dropdown"><p>
|
||||
<div class="navbar-link" role="button" aria-expanded=false" onclick="toggleMenu(this)" tabindex="0" aria-haspopup="true" aria-controls="navbar-dropdown"><p>
|
||||
{% include 'snippets/avatar.html' with user=request.user %}
|
||||
{% include 'snippets/username.html' with user=request.user %}
|
||||
</p></div>
|
||||
|
@ -117,48 +117,74 @@
|
|||
</div>
|
||||
</a>
|
||||
</div>
|
||||
{% else %}
|
||||
{% elif request.path != '/login' and request.path != '/login/' %}
|
||||
<div class="navbar-item">
|
||||
<div class="buttons">
|
||||
<a href="/login" class="button is-primary">
|
||||
Join
|
||||
</a>
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<form name="login" method="post" action="/user-login">
|
||||
{% csrf_token %}
|
||||
<div class="field is-grouped">
|
||||
<div class="control">
|
||||
<label class="is-sr-only" for="id_username">Username:</label>
|
||||
<input type="text" name="username" maxlength="150" class="input" required="" id="id_username" placeholder="username">
|
||||
</div>
|
||||
<div class="control">
|
||||
<label class="is-sr-only" for="id_password">Username:</label>
|
||||
<input type="password" name="password" maxlength="128" class="input" required="" id="id_password" placeholder="password">
|
||||
<p class="help"><a href="/password-reset">Forgot your password?</a></p>
|
||||
</div>
|
||||
<button class="button is-primary" type="submit">Log in</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="column is-narrow">
|
||||
<a href="/login" class="button is-link">
|
||||
Join
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="navbar-item">
|
||||
<a href="/login" class="button is-link">
|
||||
Join
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="section">
|
||||
<div class="section container">
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<p>
|
||||
<a href="/about">About this server</a>
|
||||
</p>
|
||||
{% if site.admin_email %}
|
||||
<p>
|
||||
<a href="mailto:{{ site.admin_email }}">Contact site admin</a>
|
||||
</p>
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<p>
|
||||
<a href="/about">About this server</a>
|
||||
</p>
|
||||
{% if site.admin_email %}
|
||||
<p>
|
||||
<a href="mailto:{{ site.admin_email }}">Contact site admin</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if site.support_link %}
|
||||
<div class="column">
|
||||
<span class="icon icon-heart"></span>
|
||||
Support {{ site.name }} on <a href="{{ site.support_link }}" target="_blank">{{ site.support_title }}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if site.support_link %}
|
||||
<div class="column">
|
||||
<span class="icon icon-heart"></span>
|
||||
Support {{ site.name }} on <a href="{{ site.support_link }}" target="_blank">{{ site.support_title }}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="column">
|
||||
BookWyrm is open source software. You can contribute or report issues on <a href="https://github.com/mouse-reeve/bookwyrm">GitHub</a>.
|
||||
<div class="column">
|
||||
BookWyrm is open source software. You can contribute or report issues on <a href="https://github.com/mouse-reeve/bookwyrm">GitHub</a>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
var csrf_token = '{{ csrf_token }}';
|
||||
|
@ -166,4 +192,3 @@
|
|||
<script src="/static/js/shared.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
<h1 class="title">About {{ site.name }}</h1>
|
||||
<div class="block">
|
||||
<img src="/static/images/logo.png" alt="BookWyrm">
|
||||
<div class="columns">
|
||||
<div class="column is-narrow is-hidden-mobile">
|
||||
<figure class="block">
|
||||
<img src="/static/images/logo.png" alt="BookWyrm">
|
||||
</figure>
|
||||
</div>
|
||||
<div class="content">
|
||||
<p class="block">
|
||||
{{ site.instance_description | safe }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="block">
|
||||
{{ site.instance_description }}
|
||||
</p>
|
||||
|
|
16
bookwyrm/templates/snippets/discover/large-book.html
Normal file
16
bookwyrm/templates/snippets/discover/large-book.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
{% load bookwyrm_tags %}
|
||||
{% if book %}
|
||||
<div class="columns">
|
||||
<div class="column is-narrow">
|
||||
{% include 'snippets/book_cover.html' with book=book size="large" %}
|
||||
{% include 'snippets/stars.html' with rating=ratings|dict_key:book.id %}
|
||||
</div>
|
||||
<div class="column">
|
||||
<h3 class="title is-5"><a href="/book/{{ book.id }}">{{ book.title }}</a></h3>
|
||||
{% if book.authors %}
|
||||
<p class="subtitle is-5">by {% include 'snippets/authors.html' with book=book %}</p>
|
||||
{% endif %}
|
||||
<blockquote class="content">{{ book|book_description|to_markdown|safe|truncatewords_html:50 }}</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
11
bookwyrm/templates/snippets/discover/small-book.html
Normal file
11
bookwyrm/templates/snippets/discover/small-book.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
{% load bookwyrm_tags %}
|
||||
{% if book %}
|
||||
{% include 'snippets/book_cover.html' with book=book %}
|
||||
{% include 'snippets/stars.html' with rating=ratings|dict_key:book.id %}
|
||||
|
||||
<h3 class="title is-6"><a href="/book/{{ book.id }}">{{ book.title }}</a></h3>
|
||||
{% if book.authors %}
|
||||
<p class="subtitle is-6">by {% include 'snippets/authors.html' with book=book %}</p>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
|
@ -104,7 +104,7 @@ class Openlibrary(TestCase):
|
|||
blob = ['image']
|
||||
result = self.connector.get_cover_url(blob)
|
||||
self.assertEqual(
|
||||
result, 'https://covers.openlibrary.org/b/id/image-M.jpg')
|
||||
result, 'https://covers.openlibrary.org/b/id/image-L.jpg')
|
||||
|
||||
def test_parse_search_result(self):
|
||||
''' extract the results from the search json response '''
|
||||
|
|
|
@ -52,6 +52,7 @@ urlpatterns = [
|
|||
|
||||
path('', views.home),
|
||||
re_path(r'^(?P<tab>home|local|federated)/?$', views.home_tab),
|
||||
re_path(r'^discover/?$', views.discover_page),
|
||||
re_path(r'^notifications/?$', views.notifications_page),
|
||||
re_path(r'^direct-messages/?$', views.direct_messages_page),
|
||||
re_path(r'^import/?$', views.import_page),
|
||||
|
|
|
@ -4,7 +4,7 @@ import re
|
|||
from django.contrib.auth.decorators import login_required, permission_required
|
||||
from django.contrib.postgres.search import TrigramSimilarity
|
||||
from django.core.paginator import Paginator
|
||||
from django.db.models import Avg, Q
|
||||
from django.db.models import Avg, F, Q, Max
|
||||
from django.db.models.functions import Greatest
|
||||
from django.http import HttpResponseNotFound, JsonResponse
|
||||
from django.core.exceptions import PermissionDenied
|
||||
|
@ -64,11 +64,12 @@ def not_found_page(request, _):
|
|||
request, 'notfound.html', {'title': 'Not found'}, status=404)
|
||||
|
||||
|
||||
@login_required
|
||||
@require_GET
|
||||
def home(request):
|
||||
''' this is the same as the feed on the home tab '''
|
||||
return home_tab(request, 'home')
|
||||
if request.user.is_authenticated:
|
||||
return home_tab(request, 'home')
|
||||
return discover_page(request)
|
||||
|
||||
|
||||
@login_required
|
||||
|
@ -131,6 +132,35 @@ def get_suggested_books(user, max_books=5):
|
|||
return suggested_books
|
||||
|
||||
|
||||
@require_GET
|
||||
def discover_page(request):
|
||||
''' tiled book activity page '''
|
||||
books = models.Edition.objects.filter(
|
||||
review__published_date__isnull=False,
|
||||
review__user__local=True
|
||||
).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, 'federated', model=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)
|
||||
|
||||
|
||||
@login_required
|
||||
@require_GET
|
||||
def direct_messages_page(request, page=1):
|
||||
|
|
Loading…
Reference in a new issue