User page

This commit is contained in:
Mouse Reeve 2020-03-16 16:10:59 -07:00
parent d28efe54dd
commit c41b53bdbe
7 changed files with 180 additions and 108 deletions

View file

@ -39,6 +39,7 @@ h2 {
font-size: 1rem;
padding: 0.5rem 0.2rem;
margin-bottom: 1rem;
border-bottom: 3px solid #B2DBBF;
}
#top-bar {
@ -69,6 +70,9 @@ h2 {
#actions > * {
display: inline-block;
}
#actions > *:last-child {
margin-left: 0.5em;
}
#notifications .icon {
font-size: 1.1rem;
@ -165,6 +169,21 @@ ul.menu a {
.row > * {
flex-grow: 1;
width: min-content;
margin-right: 1em;
}
.row > *:last-child {
margin-right: 0;
}
.row.shrink > * {
flex-grow: 0;
width: max-content;
}
.follow-requests .row {
margin-bottom: 0.5em;
}
.follow-requests .row > *:first-child {
width: 15em;
}
.login form {
@ -196,9 +215,8 @@ button.secondary {
border: 2px solid #247BA0;
color: #247BA0;
}
.login h2 {
border-bottom: 3px solid #B2DBBF;
button.warning {
background-color: #FF1654;
}
.tabs {
@ -235,6 +253,25 @@ button.secondary {
position: relative;
bottom: 0.35em;
}
.user-pic.large {
width: 5em;
height: 5em;
}
.user-profile h2 a {
text-decoration: none;
font-size: 0.9em;
float: right;
}
.user-profile h2 .icon {
font-size: 1.2em;
}
.user-profile .row > * {
flex-grow: 0;
}
.user-profile .row > *:last-child {
flex-grow: 1;
}
.review-form label {
display: block;
@ -285,8 +322,19 @@ button.secondary {
.all-shelves > div:first-child > * {
padding-left: 1em;
}
.all-shelves h2 {
border-bottom: 3px solid #B2DBBF;
.user-shelves .covers-shelf {
flex-wrap: wrap;
}
.user-shelves > div {
margin: 1em 0;
padding: 0;
}
.user-shelves > div > * {
padding-left: 1em;
}
.user-shelves .covers-shelf .book-cover {
height: 9em;
}
.covers-shelf {
@ -378,7 +426,14 @@ button.secondary {
}
blockquote {
white-space: pre-wrap;
white-space: pre-line;
margin-left: 2em;
}
blockquote .icon-quote-open {
float: left;
font-size: 2rem;
margin-right: 0.5rem;
color: #888;
}
.interaction {
@ -456,6 +511,7 @@ th, td {
.post h2, .compose-suggestion h2 {
position: relative;
right: 2em;
border: none;
}
.post .time-ago {
position: relative;
@ -487,6 +543,11 @@ th, td {
background-color: #DDD;
}
a .icon {
color: black;
text-decoration: none;
}
.hidden-text {
height: 0;
width: 0;

View file

@ -3,25 +3,7 @@
{% block content %}
<div class="all-shelves content-container">
{% for shelf in shelves %}
{% if shelf.books %}
<div>
<h2>{{ shelf.name }}
{% if shelf.size > shelf.books|length %}
<small>(<a href="/shelf/{{ user | username }}/{{ shelf.identifier }}">See all {{ shelf.size }}</a>)</small>
{% endif %}
</h2>
<div class="covers-shelf {{ shelf.identifier }}">
{% for book in shelf.books %}
<div class="book-preview" onclick="show_compose(this)" id="book-{{ book.id }}">
{% include 'snippets/book_cover.html' with book=book %}
{% include 'snippets/shelve_button.html' with book=book %}
</div>
{% endfor %}
</div>
</div>
{% endif %}
{% endfor %}
{% include 'snippets/covers_shelf.html' with shelves=shelves user=request.user %}
</div>
{% for shelf in shelves %}

View file

@ -1,2 +1,2 @@
<img class="user-pic" src="{% if user.avatar %}/images/{{ user.avatar }}{% else %}/static/images/default_avi.jpg{% endif %}">
<img class="user-pic{% if large %} large{% endif %}" src="{% if user.avatar %}/images/{{ user.avatar }}{% else %}/static/images/default_avi.jpg{% endif %}">

View file

@ -1,6 +1,20 @@
{% load fr_display %}
{% for book in books %}
<div class="book-preview">
{% include 'snippets/book.html' with rating=rating %}
{% for shelf in shelves %}
{% if shelf.books %}
<div>
<h2>{{ shelf.name }}
{% if shelf.size > shelf.books|length %}
<small>(<a href="/shelf/{{ user | username }}/{{ shelf.identifier }}">See all {{ shelf.size }}</a>)</small>
{% endif %}
</h2>
<div class="covers-shelf {{ shelf.identifier }}">
{% for book in shelf.books %}
<div class="book-preview" onclick="show_compose(this)" id="book-{{ book.id }}">
{% include 'snippets/book_cover.html' with book=book %}
{% include 'snippets/shelve_button.html' with book=book %}
</div>
{% endfor %}
</div>
</div>
{% endif %}
{% endfor %}

View file

@ -1,10 +1,10 @@
<form action="/accept_follow_request/" method="POST">
{% csrf_token %}
<input type=hidden name="user" value="{{ user.username }}">
<input type=submit value="Accept">
<input type="hidden" name="user" value="{{ user.username }}">
<button type="submit">Accept</button>
</form>
<form action="/delete_follow_request/" method="POST">
{% csrf_token %}
<input type=hidden name="user" value="{{ user.username }}">
<input type=submit value="Delete">
<input type="hidden" name="user" value="{{ user.username }}">
<button type="submit" class="warning">Delete</button>
</form>

View file

@ -1,64 +1,61 @@
{% extends 'layout.html' %}
{% load humanize %}
{% block content %}
<div id="sidebar">
<div class="user-profile">
<h2>
{% include 'snippets/avatar.html' with user=user %}
{% if user.name %}{{ user.name }}{% endif %}
<small>{{ user.username }}</small>
</h2>
{% if user.summary %}
<blockquote>{{ user.summary | safe }}</blockquote>
{% endif %}
{% if not is_self %}
{% include 'snippets/follow_button.html' with user=user %}
{% endif %}
<div class="content-container user-profile">
<h2>User Profile
{% if is_self %}
<div class="interaction">
<a href="/user-edit/">Edit profile</a>
<a href="/user-edit/">edit
<span class="icon icon-pencil">
<span class="hidden-text">Edit profile</span>
</span>
</a>
{% endif %}
</h2>
<div class="row">
<div class="pic-container">
{% include 'snippets/avatar.html' with user=user large=True %}
</div>
<div>
<p>{% if user.name %}{{ user.name }}{% else %}{{ user.localname }}{% endif %}</p>
<p>{{ user.username }}</p>
<p>Joined {{ user.created_date | naturaltime }}</p>
</div>
{% if user.summary %}
<blockquote><span class="icon icon-quote-open"></span>{{ user.summary | safe }}</blockquote>
{% endif %}
</div>
{% if not is_self %}
{% include 'snippets/follow_button.html' with user=user %}
{% endif %}
{% if is_self and user.follower_requests.all %}
<div>
<div class="follow-requests">
<h2>Follow Requests</h2>
{% for requester in user.follower_requests.all %}
<div>
{% include 'snippets/username.html' with user=requester show_full=True %}
<div class="row shrink">
<p>
{% include 'snippets/username.html' with user=requester show_full=True %}
</p>
{% include 'snippets/follow_request_buttons.html' with user=requester %}
</div>
{% endfor %}
</div>
{% endif %}
<div>
<h2>Followers</h2>
{% for follower in user.followers.all %}
<div>
{% include 'snippets/username.html' with user=follower show_full=True %}
{% include 'snippets/follow_button.html' with user=follower %}
</div>
{% endfor %}
</div>
<div>
<h2>Following</h2>
{% for following in user.following.all %}
<div>
{% include 'snippets/username.html' with user=following show_full=True %}
{% include 'snippets/follow_button.html' with user=following %}
</div>
{% endfor %}
</div>
</div>
<div id="content">
{% for shelf in shelves %}
<div>
<h2>{{ shelf.name }}</h2>
{% include 'snippets/shelf.html' with shelf=shelf ratings=ratings %}
<div class="all-shelves content-container">
{% include 'snippets/covers_shelf.html' with shelves=shelves user=user %}
</div>
<div>
<div class="content-container"><h2>User Activity</h2></div>
{% for activity in activities %}
<div class="content-container">
{% include 'snippets/status.html' with status=activity %}
</div>
{% endfor %}
</div>

View file

@ -37,39 +37,20 @@ def home(request):
def home_tab(request, tab):
''' user's homepage with activity feed '''
shelves = []
book_count = 6
for (identifier, count) in [('reading', 3), ('read', 1), ('to-read', 3)]:
if book_count <= 0:
break
shelf = models.Shelf.objects.get(
user=request.user,
identifier=identifier,
)
if not shelf.books.count():
continue
books = models.ShelfBook.objects.filter(
shelf=shelf,
).order_by(
'-updated_date'
)[:count]
book_count -= len(books)
shelves.append({
'name': shelf.name,
'identifier': shelf.identifier,
'books': [b.book for b in books],
'size': shelf.books.count(),
})
shelves = get_user_shelf_preview(
request.user,
[('reading', 3), ('read', 1), ('to-read', 3)]
)
size = sum(len(s['books']) for s in shelves)
# books new to the instance, for discovery
if book_count > 0:
if size < 6:
shelves.append({
'name': 'Recently added',
'identifier': None,
'books': models.Book.objects.order_by(
'-created_date'
)[:book_count],
'count': book_count,
)[:6 - size],
'count': 6 - size,
})
# allows us to check if a user has shelved a book
@ -138,7 +119,6 @@ def notifications_page(request):
notifications.update(read=True)
return TemplateResponse(request, 'notifications.html', data)
@csrf_exempt
def user_page(request, username):
''' profile page for a user '''
@ -153,15 +133,19 @@ def user_page(request, username):
# otherwise we're at a UI view
# TODO: change display with privacy and authentication considerations
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)}
shelves = get_user_shelf_preview(user)
activities = models.Status.objects.filter(
user=user,
).order_by(
'-created_date',
).select_subclasses()[:10]
data = {
'user': user,
'shelves': shelves,
'ratings': ratings,
'is_self': request.user.id == user.id,
'activities': activities,
}
return TemplateResponse(request, 'user.html', data)
@ -390,3 +374,37 @@ def shelf_page(request, username, shelf_identifier):
}
return TemplateResponse(request, 'shelf.html', data)
def get_user_shelf_preview(user, shelf_proportions=None):
''' data for the covers shelf (user page and feed page) '''
shelves = []
shelf_max = 6
if not shelf_proportions:
shelf_proportions = [('reading', 3), ('read', 2), ('to-read', -1)]
for (identifier, count) in shelf_proportions:
if shelf_max <= 0:
break
if count > shelf_max or count < 0:
count = shelf_max
shelf = models.Shelf.objects.get(
user=user,
identifier=identifier,
)
if not shelf.books.count():
continue
books = models.ShelfBook.objects.filter(
shelf=shelf,
).order_by(
'-updated_date'
)[:count]
shelf_max -= len(books)
shelves.append({
'name': shelf.name,
'identifier': shelf.identifier,
'books': [b.book for b in books],
'size': shelf.books.count(),
})
return shelves