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.messages',
'django.contrib.staticfiles',
'django.contrib.humanize',
'fedireads',
]

View file

@ -16,6 +16,7 @@ h2 {
background-color: #B2DBBF;
padding: 0.5rem 0.2rem;
margin-bottom: 1rem;
height: 1rem;
}
#top-bar {
@ -51,18 +52,21 @@ h2 {
#feed, #content, #sidebar {
display: flex;
flex-direction: column;
margin: 0 1rem 0 0;
margin: 0 1rem 1rem 0;
}
#sidebar {
min-width: 20rem;
margin-right: 0;
}
.user-pic {
width: 2rem;
height: auto;
border-radius: 50%;
vertical-align: middle;
vertical-align: top;
position: relative;
bottom: 0.5em;
}
.book-preview {
@ -72,7 +76,6 @@ h2 {
.book-preview img {
float: left;
margin-right: 1em;
margin-bottom: 1em;
}
.book-cover.small {
@ -110,3 +113,23 @@ blockquote {
clear: both;
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' %}
{% load fr_display %}
{% block content %}
<div id="content">
<div>
@ -6,13 +7,14 @@
<img class="book-cover" src="{% if book.cover %}/images/{{ book.cover }}{% else %}/static/images/no_cover.jpg{% endif %}">
<h1>{{ book.data.title }}</h1>
by {{ book.authors.first.data.name }}
{{ rating }} stars
{{ rating | stars }} {{ rating }}
<blockquote>{{ book.data.description }}</blockquote>
</div>
<h3>Leave a review</h3>
<form class="review-form" name="review" action="/review/" method="post">
{% csrf_token %}
<input type="hidden" name="book" value="{{ book.openlibrary_key }}"></input>
{{ review_form.as_p }}
<button type="submit">Post review</button>
@ -27,7 +29,7 @@
{% for review in reviews %}
<div class="review">
<h4>{{ review.name }}
<small>{{ review.rating }} stars, by {{ review.user.username }}</small>
<small>{{ review.rating | stars }} stars, by {{ review.user.username }}</small>
</h4>
<blockquote>{{ review.review_content }}</blockquote>
</div>

View file

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

View file

@ -1,51 +1,122 @@
{% extends 'layout.html' %}
{% load humanize %}
{% load fr_display %}
{% block content %}
<div id="content">
<div id="sidebar">
<div class="user-profile">
<h2>
<img class="user-pic" src="{% if user.avatar %}/images/{{ user.avatar }}{% else %}/static/images/default_avi.jpg{% endif %}">
<h1>{% if user.name %}{{ user.name }}<br>{% endif %}{% if user.localname %}{{ user.localname }}{% else %}{{ user.username }}{% endif %}</h1>
{% if user.name %}{{ user.name }}{% endif %}
<small>{{ user.username }}</small>
</h2>
{% if user.summary %}
<blockquote>{{ user.summary }}</blockquote>
{% 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 following %}
{% if not request.user in user.followers.all %}
<form action="/follow/" method="post">
{% csrf_token %}
<input type="hidden" name="user" value="{{ user.id }}"></input>
<input type="submit" value="Follow"></input>
</form>
{% else %}
<form action="/unfollow/" method="post">
{% csrf_token %}
<input type="hidden" name="user" value="{{ user.id }}"></input>
<input type="submit" value="Unfollow"></input>
</form>
{% endif %}
{% endif %}
</div>
<div>
<h2>Books</h2>
{% for book in books.all %}
<div class="book">
{{ book.data.title }} by {{ book.authors.first.data.name }}
{% if is_self %}
<div class="interaction">
<a href="/user/{{ user.localname }}/edit">Edit profile</a>
</div>
{% endfor %}
{% endif %}
</div>
<div>
<h2>Followers</h2>
{% for follower in user.followers.all %}
<div>
<a href="{{ follower.actor }}">{{ follower.username }}</a>
{% if not request.user in follower.followers.all %}
<form action="/follow/" method="post">
{% csrf_token %}
<input type="hidden" name="user" value="{{ follower.id }}"></input>
<input type="submit" value="Follow"></input>
</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>
{% endfor %}
</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>
</div>
{% 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 '''
from django.contrib.auth import authenticate, login, logout
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.shortcuts import redirect
from django.template.response import TemplateResponse
from django.views.decorators.csrf import csrf_exempt
import re
from fedireads import forms, models, openlibrary, outgoing, incoming
@ -120,10 +119,13 @@ def user_profile(request, username):
except models.User.DoesNotExist:
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 = {
'user': user,
'books': books,
'shelves': shelves,
'ratings': ratings,
'is_self': request.user.id == user.id,
}
return TemplateResponse(request, 'user.html', data)