stars filter

This commit is contained in:
Mouse Reeve 2020-01-29 15:10:32 -08:00
parent 668e714c31
commit 093f2d4fdd
8 changed files with 141 additions and 26 deletions

View file

@ -28,6 +28,7 @@ INSTALLED_APPS = [
'django.contrib.sessions', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'django.contrib.humanize',
'fedireads', 'fedireads',
] ]

View file

@ -16,6 +16,7 @@ h2 {
background-color: #B2DBBF; background-color: #B2DBBF;
padding: 0.5rem 0.2rem; padding: 0.5rem 0.2rem;
margin-bottom: 1rem; margin-bottom: 1rem;
height: 1rem;
} }
#top-bar { #top-bar {
@ -51,18 +52,21 @@ h2 {
#feed, #content, #sidebar { #feed, #content, #sidebar {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin: 0 1rem 0 0; margin: 0 1rem 1rem 0;
} }
#sidebar { #sidebar {
min-width: 20rem; min-width: 20rem;
margin-right: 0;
} }
.user-pic { .user-pic {
width: 2rem; width: 2rem;
height: auto; height: auto;
border-radius: 50%; border-radius: 50%;
vertical-align: middle; vertical-align: top;
position: relative;
bottom: 0.5em;
} }
.book-preview { .book-preview {
@ -72,7 +76,6 @@ h2 {
.book-preview img { .book-preview img {
float: left; float: left;
margin-right: 1em; margin-right: 1em;
margin-bottom: 1em;
} }
.book-cover.small { .book-cover.small {
@ -110,3 +113,23 @@ blockquote {
clear: both; clear: both;
margin-top: 1rem; margin-top: 1rem;
} }
table {
border-collapse: collapse;
margin: 1em;
}
tr {
vertical-align: top;
}
tr:nth-child(even) {
background-color: #DDD;
}
th {
font-weight: bold;
}
th, td {
padding: 1em;
text-align: left;
}

View file

@ -1,4 +1,5 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load fr_display %}
{% block content %} {% block content %}
<div id="content"> <div id="content">
<div> <div>
@ -6,13 +7,14 @@
<img class="book-cover" src="{% if book.cover %}/images/{{ book.cover }}{% else %}/static/images/no_cover.jpg{% endif %}"> <img class="book-cover" src="{% if book.cover %}/images/{{ book.cover }}{% else %}/static/images/no_cover.jpg{% endif %}">
<h1>{{ book.data.title }}</h1> <h1>{{ book.data.title }}</h1>
by {{ book.authors.first.data.name }} by {{ book.authors.first.data.name }}
{{ rating }} stars {{ rating | stars }} {{ rating }}
<blockquote>{{ book.data.description }}</blockquote> <blockquote>{{ book.data.description }}</blockquote>
</div> </div>
<h3>Leave a review</h3> <h3>Leave a review</h3>
<form class="review-form" name="review" action="/review/" method="post"> <form class="review-form" name="review" action="/review/" method="post">
{% csrf_token %}
<input type="hidden" name="book" value="{{ book.openlibrary_key }}"></input> <input type="hidden" name="book" value="{{ book.openlibrary_key }}"></input>
{{ review_form.as_p }} {{ review_form.as_p }}
<button type="submit">Post review</button> <button type="submit">Post review</button>
@ -27,7 +29,7 @@
{% for review in reviews %} {% for review in reviews %}
<div class="review"> <div class="review">
<h4>{{ review.name }} <h4>{{ review.name }}
<small>{{ review.rating }} stars, by {{ review.user.username }}</small> <small>{{ review.rating | stars }} stars, by {{ review.user.username }}</small>
</h4> </h4>
<blockquote>{{ review.review_content }}</blockquote> <blockquote>{{ review.review_content }}</blockquote>
</div> </div>

View file

@ -1,4 +1,5 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load fr_display %}
{% block content %} {% block content %}
<div id="sidebar"> <div id="sidebar">
<div> <div>
@ -103,7 +104,7 @@
</p> </p>
<h3>{{ activity.name }}</h3> <h3>{{ activity.name }}</h3>
<p>{{ activity.rating }} stars</p> <p>{{ activity.rating | stars }} stars</p>
<p>{{ activity.review_content }}</p> <p>{{ activity.review_content }}</p>
</div> </div>
<div class="interaction"><button>⭐️ Like</button></div> <div class="interaction"><button>⭐️ Like</button></div>

View file

@ -1,51 +1,122 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load humanize %}
{% load fr_display %}
{% block content %} {% block content %}
<div id="content"> <div id="sidebar">
<div class="user-profile"> <div class="user-profile">
<img class="user-pic" src="{% if user.avatar %}/images/{{ user.avatar }}{% else %}/static/images/default_avi.jpg{% endif %}"> <h2>
<h1>{% if user.name %}{{ user.name }}<br>{% endif %}{% if user.localname %}{{ user.localname }}{% else %}{{ user.username }}{% endif %}</h1> <img class="user-pic" src="{% if user.avatar %}/images/{{ user.avatar }}{% else %}/static/images/default_avi.jpg{% endif %}">
{% if user.name %}{{ user.name }}{% endif %}
<small>{{ user.username }}</small>
</h2>
{% if user.summary %} {% if user.summary %}
<blockquote>{{ user.summary }}</blockquote> <blockquote>{{ user.summary }}</blockquote>
{% endif %} {% endif %}
{% if is_self %}<a href="/user/{{ user.localname }}/edit">Edit profile</a>
<p>Since {{ user.created_date }}</p>
{% endif %}
{% if not is_self %} {% if not is_self %}
{% if not following %} {% if not request.user in user.followers.all %}
<form action="/follow/" method="post"> <form action="/follow/" method="post">
{% csrf_token %}
<input type="hidden" name="user" value="{{ user.id }}"></input> <input type="hidden" name="user" value="{{ user.id }}"></input>
<input type="submit" value="Follow"></input> <input type="submit" value="Follow"></input>
</form> </form>
{% else %} {% else %}
<form action="/unfollow/" method="post"> <form action="/unfollow/" method="post">
{% csrf_token %}
<input type="hidden" name="user" value="{{ user.id }}"></input> <input type="hidden" name="user" value="{{ user.id }}"></input>
<input type="submit" value="Unfollow"></input> <input type="submit" value="Unfollow"></input>
</form> </form>
{% endif %} {% endif %}
{% endif %} {% endif %}
</div>
<div> {% if is_self %}
<h2>Books</h2> <div class="interaction">
{% for book in books.all %} <a href="/user/{{ user.localname }}/edit">Edit profile</a>
<div class="book">
{{ book.data.title }} by {{ book.authors.first.data.name }}
</div> </div>
{% endfor %} {% endif %}
</div> </div>
<div> <div>
<h2>Followers</h2> <h2>Followers</h2>
{% for follower in user.followers.all %} {% for follower in user.followers.all %}
<div> <div>
<a href="{{ follower.actor }}">{{ follower.username }}</a> <a href="{{ follower.actor }}">{{ follower.username }}</a>
{% if not request.user in follower.followers.all %}
<form action="/follow/" method="post"> <form action="/follow/" method="post">
{% csrf_token %}
<input type="hidden" name="user" value="{{ follower.id }}"></input> <input type="hidden" name="user" value="{{ follower.id }}"></input>
<input type="submit" value="Follow"></input> <input type="submit" value="Follow"></input>
</form> </form>
{% else %}
<form action="/unfollow/" method="post">
{% csrf_token %}
<input type="hidden" name="user" value="{{ follower.id }}"></input>
<input type="submit" value="Unfollow"></input>
</form>
{% endif %}
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
<div id="content">
{% for shelf in shelves %}
<div>
<h2>{{ shelf.shelf.name }}</h2>
{% if shelf.books %}
<table>
<tr class="book-preview">
<th>
Cover
</th>
<th>
Title
</th>
<th>
Author
</th>
<th>
Published
</th>
<th>
Shelved
</th>
<th>
External links
</th>
<th>
Rating
</th>
</tr>
{% for book in shelf.books.all %}
<tr class="book-preview">
<td>
<img src="/images/{{ book.cover }}" class="book-cover small">
</td>
<td>
<a href="{{ book.openlibrary_key }}">{{ book.data.title }}</a>
</td>
<td>
{{ book.authors.first.data.name }}
</td>
<td>
{{ book.data.first_publish_date }}
</td>
<td>
{{ book.added_date | naturalday }}
</td>
<td>
<a href="https://openlibrary.org{{ book.data.key }}" target="_blank">OpenLibrary</a>
</td>
<td>
{{ ratings | dict_key:book.id | stars}}
</td>
</tr>
{% endfor %}
</table>
{% else %}
<p>This shelf is empty.</p>
{% endif %}
</div>
{% endfor %}
</div>
{% endblock %} {% endblock %}

View file

View file

@ -0,0 +1,15 @@
''' template filters '''
from django import template
register = template.Library()
@register.filter(name='dict_key')
def dict_key(d, k):
'''Returns the given key from a dictionary.'''
return d.get(k) or 0
@register.filter(name='stars')
def stars(number):
''' turn integers into stars '''
number = int(number)
return ('' * number) + '' * (5 - number)

View file

@ -1,11 +1,10 @@
''' application views/pages ''' ''' application views/pages '''
from django.contrib.auth import authenticate, login, logout from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.db.models import Avg, Q from django.db.models import Avg, FilteredRelation, Q
from django.http import HttpResponseNotFound from django.http import HttpResponseNotFound
from django.shortcuts import redirect from django.shortcuts import redirect
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.views.decorators.csrf import csrf_exempt
import re import re
from fedireads import forms, models, openlibrary, outgoing, incoming from fedireads import forms, models, openlibrary, outgoing, incoming
@ -120,10 +119,13 @@ def user_profile(request, username):
except models.User.DoesNotExist: except models.User.DoesNotExist:
return HttpResponseNotFound() return HttpResponseNotFound()
books = models.Book.objects.filter(shelves__user=user) shelves = models.Shelf.objects.filter(user=user)
ratings = {r.book.id: r.rating for r in models.Review.objects.filter(user=user, book__shelves__user=user)}
data = { data = {
'user': user, 'user': user,
'books': books, 'shelves': shelves,
'ratings': ratings,
'is_self': request.user.id == user.id, 'is_self': request.user.id == user.id,
} }
return TemplateResponse(request, 'user.html', data) return TemplateResponse(request, 'user.html', data)