forked from mirrors/bookwyrm
Differentiate friends/local/federated reviews
This commit is contained in:
parent
20522cbd11
commit
a46193a37b
12 changed files with 118 additions and 30 deletions
|
@ -7,6 +7,8 @@ import re
|
||||||
|
|
||||||
from fedireads.utils.models import FedireadsModel
|
from fedireads.utils.models import FedireadsModel
|
||||||
|
|
||||||
|
# TODO: quote, comment, poll, recommendation, content warning, image
|
||||||
|
|
||||||
|
|
||||||
class Status(FedireadsModel):
|
class Status(FedireadsModel):
|
||||||
''' any post, like a reply to a review, etc '''
|
''' any post, like a reply to a review, etc '''
|
||||||
|
|
|
@ -87,11 +87,11 @@ h2 {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#feed-tabs {
|
.tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
.active {
|
.tab.active {
|
||||||
background-color: #FF1654;
|
background-color: #FF1654;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% load fr_display %}
|
{% load fr_display %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div id="content">
|
<div id="sidebar">
|
||||||
<div>
|
<div>
|
||||||
<div class="book-preview">
|
<h2><q>{{ book.data.title }}</q> and You</h2>
|
||||||
{% include 'snippets/book.html' with book=book size=large rating=rating description=True shelf_pulldown=True %}
|
<p>{% if shelf %}On shelf <q>{{ shelf.name }}</q>{% endif %}</p>
|
||||||
</div>
|
{% include 'snippets/shelve-button.html' with book=book pulldown=True %}
|
||||||
|
|
||||||
<div id="tag-cloud">
|
<div id="tag-cloud">
|
||||||
{% for tag in tags %}
|
{% for tag in user_tags %}
|
||||||
{% include 'snippets/tag.html' with tag=tag user=request.user %}
|
{% include 'snippets/tag.html' with tag=tag user=request.user user_tags=user_tag_names %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<form class="tag-form" name="tag" action="/tag/" method="post">
|
<form class="tag-form" name="tag" action="/tag/" method="post">
|
||||||
|
@ -18,6 +19,33 @@
|
||||||
<button type="submit">Add tag</button>
|
<button type="submit">Add tag</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="content">
|
||||||
|
<div>
|
||||||
|
<h2><q>{{ book.data.title }}</q> by
|
||||||
|
{% include 'snippets/authors.html' with book=book %}</h2>
|
||||||
|
<div class="book-preview">
|
||||||
|
{% include 'snippets/book_cover.html' with book=book size=large %}
|
||||||
|
<p>{{ active_tab }} rating: {{ rating | stars }}</p>
|
||||||
|
{% if description %}
|
||||||
|
<blockquote>{{ book.data.description | description }}</blockquote>
|
||||||
|
{% endif %}
|
||||||
|
{% for review in user_reviews %}
|
||||||
|
{% include 'snippets/review.html' with review=review %}
|
||||||
|
{% endfor %}
|
||||||
|
<div>
|
||||||
|
<div id="tag-cloud">
|
||||||
|
{% for tag in tags %}
|
||||||
|
{% include 'snippets/tag.html' with tag=tag user=request.user user_tags=user_tag_names %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% include 'snippets/tabs.html' with tabs=feed_tabs active_tab=active_tab path=path %}
|
||||||
<div class="reviews">
|
<div class="reviews">
|
||||||
<h2>Reviews</h2>
|
<h2>Reviews</h2>
|
||||||
{% if not reviews %}
|
{% if not reviews %}
|
||||||
|
@ -29,13 +57,9 @@
|
||||||
{{ review_form.as_p }}
|
{{ review_form.as_p }}
|
||||||
<button type="submit">Post review</button>
|
<button type="submit">Post review</button>
|
||||||
</form>
|
</form>
|
||||||
|
<p>Average rating: {{ rating | stars }}</p>
|
||||||
{% for review in reviews %}
|
{% for review in reviews %}
|
||||||
<div class="review">
|
{% include 'snippets/review.html' with review=review %}
|
||||||
<h4>{{ review.name }}
|
|
||||||
<small>{{ review.rating | stars }} stars, by {% include 'snippets/username.html' with user=review.user %}</small>
|
|
||||||
</h4>
|
|
||||||
<blockquote>{{ review.content }}</blockquote>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% load fr_display %}
|
{% load fr_display %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div id="sidebar">
|
|
||||||
|
|
||||||
|
<div id="sidebar">
|
||||||
<div>
|
<div>
|
||||||
{% if shelves %}
|
{% if shelves %}
|
||||||
{% for shelf in shelves %}
|
{% for shelf in shelves %}
|
||||||
|
@ -33,17 +33,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div id="feed">
|
<div id="feed">
|
||||||
<div id="feed-tabs">
|
{% include 'snippets/tabs.html' with tabs=feed_tabs active_tab=active_tab %}
|
||||||
{% for tab in feed_tabs %}
|
|
||||||
<div class="{% if tab == active_tab %}active{% endif %}">
|
|
||||||
<a href="/{{ tab }}">{{ tab }}</a>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% for activity in activities %}
|
{% for activity in activities %}
|
||||||
{% include 'snippets/status.html' with activity=activity %}
|
{% include 'snippets/status.html' with activity=activity %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
1
fedireads/templates/snippets/authors.html
Normal file
1
fedireads/templates/snippets/authors.html
Normal file
|
@ -0,0 +1 @@
|
||||||
|
by <a href="/author/{{ book.authors.first.openlibrary_key }}" class="author">{{ book.authors.first.data.name }}</a>
|
|
@ -3,7 +3,9 @@
|
||||||
<p class="title">
|
<p class="title">
|
||||||
<a href="/book/{{ book.openlibrary_key }}">{{ book.data.title }}</a>
|
<a href="/book/{{ book.openlibrary_key }}">{{ book.data.title }}</a>
|
||||||
</p>
|
</p>
|
||||||
<p>by <a href="/author/{{ book.authors.first.openlibrary_key }}" class="author">{{ book.authors.first.data.name }}</a></p>
|
<p>
|
||||||
|
{% include 'snippets/authors.html' with book=book %}
|
||||||
|
</p>
|
||||||
|
|
||||||
{% if rating %}
|
{% if rating %}
|
||||||
{{ rating | stars }} {{ rating }}
|
{{ rating | stars }} {{ rating }}
|
||||||
|
@ -13,4 +15,4 @@
|
||||||
<blockquote>{{ book.data.description | description }}</blockquote>
|
<blockquote>{{ book.data.description | description }}</blockquote>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% include 'snippets/shelve-button.html' with book=book pulldown=shelf_pulldown%}
|
{% include 'snippets/shelve-button.html' with book=book pulldown=shelf_pulldown %}
|
||||||
|
|
8
fedireads/templates/snippets/review.html
Normal file
8
fedireads/templates/snippets/review.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{% load fr_display %}
|
||||||
|
<div class="review">
|
||||||
|
<h4>{{ review.name }}
|
||||||
|
<small>{{ review.rating | stars }} stars, by {% include 'snippets/username.html' with user=review.user %}</small>
|
||||||
|
</h4>
|
||||||
|
<blockquote>{{ review.content }}</blockquote>
|
||||||
|
</div>
|
||||||
|
|
8
fedireads/templates/snippets/tabs.html
Normal file
8
fedireads/templates/snippets/tabs.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<div class="tabs">
|
||||||
|
{% for tab in tabs %}
|
||||||
|
<div class="tab {% if tab == active_tab %}active{% endif %}">
|
||||||
|
<a href="{{ path }}/{{ tab }}">{{ tab }}</a>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="tag">
|
<div class="tag">
|
||||||
<a href="/tag/{{ tag.identifier }}">{{ tag.name }}</a>
|
<a href="/tag/{{ tag.identifier }}">{{ tag.name }}</a>
|
||||||
{% if tag.name in user_tags %}
|
{% if tag.identifier in user_tags %}
|
||||||
<form class="tag-form" name="tag" action="/untag/" method="post">
|
<form class="tag-form" name="tag" action="/untag/" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="book" value="{{ book.openlibrary_key }}"></input>
|
<input type="hidden" name="book" value="{{ book.openlibrary_key }}"></input>
|
||||||
|
|
|
@ -80,3 +80,16 @@ def shelve_button_text(context, book):
|
||||||
return 'I\'m done!'
|
return 'I\'m done!'
|
||||||
return 'Want to read'
|
return 'Want to read'
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag(takes_context=True)
|
||||||
|
def current_shelf(context, book):
|
||||||
|
''' check what shelf a user has a book on, if any '''
|
||||||
|
try:
|
||||||
|
shelf = models.ShelfBook.objects.get(
|
||||||
|
shelf__user=context['user'],
|
||||||
|
book=book
|
||||||
|
)
|
||||||
|
except models.ShelfBook.DoesNotExist:
|
||||||
|
return None
|
||||||
|
return shelf.name
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ urlpatterns = [
|
||||||
re_path(r'%s/edit/?$' % user_path, views.edit_profile_page),
|
re_path(r'%s/edit/?$' % user_path, views.edit_profile_page),
|
||||||
re_path(r'^user/edit/?$', views.edit_profile_page),
|
re_path(r'^user/edit/?$', views.edit_profile_page),
|
||||||
re_path(r'^book/(?P<book_identifier>\w+)/?$', views.book_page),
|
re_path(r'^book/(?P<book_identifier>\w+)/?$', views.book_page),
|
||||||
|
re_path(r'^book/(?P<book_identifier>\w+)/(?P<tab>friends|local|federated)?$', views.book_page),
|
||||||
re_path(r'^author/(?P<author_identifier>\w+)/?$', views.author_page),
|
re_path(r'^author/(?P<author_identifier>\w+)/?$', views.author_page),
|
||||||
re_path(r'^tag/(?P<tag_id>[\w-]+)/?$', views.tag_page),
|
re_path(r'^tag/(?P<tag_id>[\w-]+)/?$', views.tag_page),
|
||||||
re_path(r'^shelf/%s/(?P<shelf_identifier>[\w-]+)/?$' % username_regex, views.shelf_page),
|
re_path(r'^shelf/%s/(?P<shelf_identifier>[\w-]+)/?$' % username_regex, views.shelf_page),
|
||||||
|
|
|
@ -185,12 +185,38 @@ def edit_profile_page(request, username):
|
||||||
return TemplateResponse(request, 'edit_user.html', data)
|
return TemplateResponse(request, 'edit_user.html', data)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
def book_page(request, book_identifier):
|
def book_page(request, book_identifier, tab='friends'):
|
||||||
''' info about a book '''
|
''' info about a book '''
|
||||||
book = openlibrary.get_or_create_book(book_identifier)
|
book = openlibrary.get_or_create_book(book_identifier)
|
||||||
# TODO: again, post privacy?
|
|
||||||
reviews = models.Review.objects.filter(book=book)
|
user_reviews = models.Review.objects.filter(user=request.user, book=book).all()
|
||||||
|
|
||||||
|
if tab == 'friends':
|
||||||
|
reviews = models.Review.objects.filter(
|
||||||
|
Q(user__followers=request.user, privacy='public') | \
|
||||||
|
Q(mention_users=request.user),
|
||||||
|
book=book,
|
||||||
|
)
|
||||||
|
elif tab == 'local':
|
||||||
|
reviews = models.Review.objects.filter(
|
||||||
|
Q(privacy='public') | \
|
||||||
|
Q(mention_users=request.user),
|
||||||
|
user__local=True,
|
||||||
|
book=book,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
reviews = models.Review.objects.filter(
|
||||||
|
Q(privacy='public') | \
|
||||||
|
Q(mention_users=request.user),
|
||||||
|
book=book,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
shelf = models.Shelf.objects.get(user=request.user, book=book)
|
||||||
|
except models.Shelf.DoesNotExist:
|
||||||
|
shelf = None
|
||||||
|
|
||||||
rating = reviews.aggregate(Avg('rating'))
|
rating = reviews.aggregate(Avg('rating'))
|
||||||
tags = models.Tag.objects.filter(
|
tags = models.Tag.objects.filter(
|
||||||
book=book
|
book=book
|
||||||
|
@ -199,18 +225,25 @@ def book_page(request, book_identifier):
|
||||||
).distinct().all()
|
).distinct().all()
|
||||||
user_tags = models.Tag.objects.filter(
|
user_tags = models.Tag.objects.filter(
|
||||||
book=book, user=request.user
|
book=book, user=request.user
|
||||||
).values_list('name', flat=True)
|
).all()
|
||||||
|
|
||||||
review_form = forms.ReviewForm()
|
review_form = forms.ReviewForm()
|
||||||
tag_form = forms.TagForm()
|
tag_form = forms.TagForm()
|
||||||
data = {
|
data = {
|
||||||
'book': book,
|
'book': book,
|
||||||
|
'shelf': shelf,
|
||||||
|
'user_reviews': user_reviews,
|
||||||
|
'user_rating': user_reviews.aggregate(Avg('rating')),
|
||||||
'reviews': reviews,
|
'reviews': reviews,
|
||||||
'rating': rating['rating__avg'],
|
'rating': rating['rating__avg'],
|
||||||
'tags': tags,
|
'tags': tags,
|
||||||
'user_tags': user_tags,
|
'user_tags': user_tags,
|
||||||
|
'user_tag_names': user_tags.values_list('identifier', flat=True),
|
||||||
'review_form': review_form,
|
'review_form': review_form,
|
||||||
'tag_form': tag_form,
|
'tag_form': tag_form,
|
||||||
|
'feed_tabs': ['friends', 'local', 'federated'],
|
||||||
|
'active_tab': tab,
|
||||||
|
'path': '/book/%s' % book_identifier,
|
||||||
}
|
}
|
||||||
return TemplateResponse(request, 'book.html', data)
|
return TemplateResponse(request, 'book.html', data)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue