Improves templates

This commit is contained in:
Mouse Reeve 2020-01-28 17:23:38 -08:00
parent b554280481
commit e0c174d990
11 changed files with 166 additions and 132 deletions

View file

@ -1,4 +1,4 @@
# Generated by Django 3.0.2 on 2020-01-28 23:19 # Generated by Django 3.0.2 on 2020-01-29 01:16
from django.conf import settings from django.conf import settings
import django.contrib.auth.models import django.contrib.auth.models
@ -86,7 +86,7 @@ class Migration(migrations.Migration):
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('activitypub_id', models.CharField(max_length=255)), ('activitypub_id', models.CharField(max_length=255)),
('openlibrary_key', models.CharField(max_length=255)), ('openlibrary_key', models.CharField(max_length=255, unique=True)),
('data', django.contrib.postgres.fields.jsonb.JSONField()), ('data', django.contrib.postgres.fields.jsonb.JSONField()),
('added_date', models.DateTimeField(auto_now_add=True)), ('added_date', models.DateTimeField(auto_now_add=True)),
('updated_date', models.DateTimeField(auto_now=True)), ('updated_date', models.DateTimeField(auto_now=True)),

View file

@ -199,7 +199,7 @@ class ShelfBook(models.Model):
class Book(models.Model): class Book(models.Model):
''' a non-canonical copy from open library ''' ''' a non-canonical copy from open library '''
activitypub_id = models.CharField(max_length=255) activitypub_id = models.CharField(max_length=255)
openlibrary_key = models.CharField(max_length=255) openlibrary_key = models.CharField(max_length=255, unique=True)
data = JSONField() data = JSONField()
works = models.ManyToManyField('Work') works = models.ManyToManyField('Work')
authors = models.ManyToManyField('Author') authors = models.ManyToManyField('Author')

View file

@ -1,23 +1,41 @@
/* some colors that are okay: #247BA0 #70C1B2 #B2DBBF #F3FFBD #FF1654 */
* { * {
margin: 0; margin: 0;
padding: 0; padding: 0;
line-height: 1.3em; line-height: 1.3em;
overflow: auto; overflow: auto;
font-family: sans-serif;
font-weight: normal;
} }
body > * > * { h1 {
font-size: 1.2rem;
}
h2 {
font-size: 1rem;
background-color: #F3FFBD;
padding: 0.5rem 0.2rem;
margin-bottom: 1rem;
}
#main {
margin: 0 auto; margin: 0 auto;
padding: 1rem; display: flex;
flex-flow: row wrap;
max-width: 75rem; max-width: 75rem;
min-width: 30rem;
} }
#top-bar { #top-bar {
height: 4rem; height: 4rem;
border-bottom: 1px solid #aaa; background-color: #B2DBBF;
box-shadow: 0 0.5em 0.5em -0.6em #666; overflow: hidden;
margin-bottom: 1em; padding: 0.5rem;
overflow: auto; }
#top-bar a {
color: black;
text-decoration: none;
} }
#branding { #branding {
@ -33,17 +51,9 @@ header > div:last-child {
} }
#sidebar { #sidebar {
width: 30%; display: flex;
float: left; flex-direction: column;
} flex-grow: 1;
.carosel {
margin-bottom: 1rem;
}
.carosel > div {
display: inline-block;
margin: 0 1rem;
vertical-align: top;
} }
.user-pic { .user-pic {
@ -63,16 +73,24 @@ header > div:last-child {
margin-right: 0.5em; margin-right: 0.5em;
} }
.update { #feed, #content {
border: 1px solid #333; display: flex;
border-radius: 0.2rem; flex-direction: column;
margin-bottom: 1em; flex-grow: 3;
} }
.update > * { #content > div, #feed > div, #sidebar > div {
padding: 1em; background-color: #EFEFEF;
margin: 1rem auto;
padding: 1rem;
width: 90%;
} }
.interact { form label {
background-color: #eee; display: block;
}
.review-form textarea {
width: 30rem;
height: 10rem;
} }

View file

@ -1,19 +1,30 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% block content %} {% block content %}
<div id="main"> <div id="content">
<div class="book-profile"> <div>
<img class="book-cover" src="/static/images/med.jpg"> <div class="book-preview">
<h1>{{ book.data.title }}</h1> <img class="book-cover" src="/static/images/med.jpg">
by {{ book.authors.first.data.name }} <h1>{{ book.data.title }}</h1>
{{ rating }} stars by {{ book.authors.first.data.name }}
{{ rating }} stars
</div>
<h3>Leave a review</h3>
<form class="review-form" name="review" action="/review/" method="post">
<input type="hidden" name="book" value="{{ book.openlibrary_key }}"></input>
<label for="name">Title:
<input type="text" name="name"></input>
</label>
<label for="content">
<textarea name="content"></textarea>
</label>
<label for="rating">Your rating (1-5)
<input type="number" name="rating"></input>
</label>
<button type="submit">Post review</button>
</form>
</div> </div>
<form name="review" action="/review/" method="post">
<input type="hidden" name="book" value="{{ book.openlibrary_key }}"></input>
<input type="text" name="name"></input>
<textarea name="content">Your review</textarea>
<input type="number" name="rating"></input>
<input type="submit" value="Post review"></input>
</form>
<div class="reviews"> <div class="reviews">
<h2>Reviews</h2> <h2>Reviews</h2>

View file

@ -1,6 +1,6 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% block content %} {% block content %}
<div id="main"> <div id="content">
<div class="user-profile"> <div class="user-profile">
<img class="user-pic" src="/static/images/profile.jpg"> <img class="user-pic" src="/static/images/profile.jpg">
<form name="avatar" action="/upload-avatar/" method="post" enctype="multipart/form-data"> <form name="avatar" action="/upload-avatar/" method="post" enctype="multipart/form-data">

View file

@ -1,30 +1,27 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% block content %} {% block content %}
<div id="sidebar"> <div id="sidebar">
{# listing books currently on user's shelves #} <div>
{# TODO: this should only show currently reading probably #} <h2>Currently Reading</h2>
{% for shelf in shelves %} {# listing books currently on user's shelves #}
{% if shelf.books.all %} {% if not shelves.first.books.all %}
<h2>{{ shelf.name }}</h2> <p>Start a book!</p>
{% for book in shelf.books.all %}
<div class="book-preview">
<img class="cover" src="static/images/small.jpg">
<p class="title"><a href="{{ book.openlibrary_key }}">{{ book.data.title }}</a></p>
<p>by <a href="" class="author">{{ book.authors.first.data.name }}</a></p>
{% if shelf.type == 'reading' %}
{# TODO: re-shelve a book #}
<button>done reading</button>
{% endif %} {% endif %}
{% for book in shelves.first.books.all %}
<div class="book-preview">
<img class="cover" src="static/images/small.jpg">
<p class="title"><a href="{{ book.openlibrary_key }}">{{ book.data.title }}</a></p>
<p>by <a href="" class="author">{{ book.authors.first.data.name }}</a></p>
{% if shelf.type == 'reading' %}
{# TODO: re-shelve a book #}
<button>done reading</button>
{% endif %}
</div>
{% endfor %}
</div> </div>
{% endfor %}
{% endif %}
{% endfor %}
</div>
<div id="main"> <div>
<h2>Recently Added Books</h2>
<div class="carosel">
{# a display of books in your local db, so you have somewhere to start #}
{% for book in recent_books %} {% for book in recent_books %}
<div class="book-preview"> <div class="book-preview">
<img class="cover" src="static/images/small.jpg"> <img class="cover" src="static/images/small.jpg">
@ -34,7 +31,7 @@
{# TODO: there should be a helper function for listing authors #} {# TODO: there should be a helper function for listing authors #}
<a href="" class="author">{{ book.authors.first.data.name }}</a> <a href="" class="author">{{ book.authors.first.data.name }}</a>
</p> </p>
{% if not book.user_shelves %} {% if not book in user_books.all %}
<form name="shelve" action="/shelve/{{ request.user.localname }}_to-read/{{ book.id }}" method="post"> <form name="shelve" action="/shelve/{{ request.user.localname }}_to-read/{{ book.id }}" method="post">
<input type="hidden" name="book" value="book.id"></input> <input type="hidden" name="book" value="book.id"></input>
<button type="submit">Want to read</button> <button type="submit">Want to read</button>
@ -43,55 +40,62 @@
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
</div>
<div id="feed">
{% for activity in activities %} {% for activity in activities %}
<div class="update"> <div class="update">
<div class="user-preview"> <h2>
<img class="user-pic" src="static/images/profile.jpg"> <img class="user-pic" src="static/images/profile.jpg">
{# TODO: a helper function for displaying a username #} {# TODO: a helper function for displaying a username #}
<span><a href="/user/{% if activity.user.localname %}{{ activity.user.localname }}{% else %}{{ activity.user.username }}{% endif %}" class="user"> <a href="/user/{% if activity.user.localname %}{{ activity.user.localname }}{% else %}{{ activity.user.username }}{% endif %}" class="user">
{% if activity.user.localname %}{{ activity.user.localname }}{% else %}{{ activity.user.username }}{% endif %}</a> {% if activity.user.localname %}{{ activity.user.localname }}{% else %}{{ activity.user.username }}{% endif %}</a>
{% if activity.fedireads_type == 'Shelve' %} {% if activity.fedireads_type == 'Shelve' %}
{# display a reading/shelving activity #} {# display a reading/shelving activity #}
{% if activity.shelf.shelf_type == 'to-read' %} {% if activity.shelf.shelf_type == 'to-read' %}
wants to read wants to read
{% elif activity.shelf.shelf_type == 'read' %} {% elif activity.shelf.shelf_type == 'read' %}
finished reading finished reading
{% elif activity.shelf.shelf_type == 'reading' %} {% elif activity.shelf.shelf_type == 'reading' %}
started reading started reading
{% else %}
shelved in "{{ activity.shelf.name }}"
{% endif %}
{# TODO: wouldn't it rule if this was a reusable piece of markup? #}
<div class="book-preview">
<img class="cover" src="static/images/med.jpg">
<p class="title">
<a href="{{ activity.book.openlibrary_key }}">{{ activity.book.data.title }}</a>
by
<a href="" class="author">{{ activity.book.authors.first.data.name }}</a>
</p>
</div>
{% elif activity.fedireads_type == 'Review' %}
{# display a review #}
reviewed {{ activity.book.data.title }}
<div class="book-preview review">
<img class="cover" src="static/images/med.jpg">
<p class="title">
<a href="{{ activity.book.openlibrary_key }}">{{ activity.book.data.title }}</a>
by
<a href="" class="author">{{ activity.book.authors.first.data.name }}</a>
</p>
<h3>{{ activity.name }}</h3>
<p>{{ activity.rating }} stars</p>
<p>{{ activity.review_content }}</p>
</div>
{% elif activity.activity_type == 'Follow' %}
started following someone
{% else %} {% else %}
{# generic handling for a misc activity, which perhaps should not be displayed at all #} shelved in "{{ activity.shelf.name }}"
did {{ activity.activity_type }}</span>
{% endif %} {% endif %}
</div> </h2>
{# TODO: wouldn't it rule if this was a reusable piece of markup? #}
<div class="book-preview">
<img class="cover" src="static/images/med.jpg">
<p class="title">
<a href="{{ activity.book.openlibrary_key }}">{{ activity.book.data.title }}</a>
by
<a href="" class="author">{{ activity.book.authors.first.data.name }}</a>
</p>
</div>
{% elif activity.fedireads_type == 'Review' %}
{# display a review #}
reviewed {{ activity.book.data.title }}
</h2>
<div class="book-preview review">
<img class="cover" src="static/images/med.jpg">
<p class="title">
<a href="{{ activity.book.openlibrary_key }}">{{ activity.book.data.title }}</a>
by
<a href="" class="author">{{ activity.book.authors.first.data.name }}</a>
</p>
<h3>{{ activity.name }}</h3>
<p>{{ activity.rating }} stars</p>
<p>{{ activity.review_content }}</p>
</div>
{% elif activity.activity_type == 'Follow' %}
started following someone
</h2>
{% else %}
{# generic handling for a misc activity, which perhaps should not be displayed at all #}
did {{ activity.activity_type }}
</h2>
{% endif %}
</div> </div>
{% endfor %} {% endfor %}
</div> </div>

View file

@ -47,12 +47,9 @@
</header> </header>
</div> </div>
<div id="content"> <div id="main">
<div> {% block content %}
{% block content %} {% endblock %}
{% endblock %}
</div>
</div> </div>
</body> </body>

View file

@ -1,8 +1,17 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% block content %} {% block content %}
<form name="login" method="post"> <div id="content">
<input type="text" name="username"></input> <div>
<input type="password" name="password"></input> <form name="login" method="post">
<input type="submit"></input> <label for="username">Username:
</form> <input type="text" name="username"></input>
</label>
<label for="password">Password:
<input type="password" name="password"></input>
</label>
<button type="submit">Log in</button>
</form>
</div>
</div>
{% endblock %} {% endblock %}

View file

@ -1,6 +1,6 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% block content %} {% block content %}
<div id="main"> <div id="content">
{% for result in results %} {% for result in results %}
{{ result.username }} {{ result.username }}
<form action="/follow/" method="post"> <form action="/follow/" method="post">

View file

@ -1,6 +1,6 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% block content %} {% block content %}
<div id="main"> <div id="content">
<div class="user-profile"> <div class="user-profile">
<img class="user-pic" src="/static/images/profile.jpg"> <img class="user-pic" src="/static/images/profile.jpg">
<h1>{% if user.localname %}{{ user.localname }}{% else %}{{ user.username }}{% endif %}</h1> <h1>{% if user.localname %}{{ user.localname }}{% else %}{{ user.username }}{% endif %}</h1>

View file

@ -1,7 +1,7 @@
''' 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, FilteredRelation, Q from django.db.models import Avg, 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
@ -15,16 +15,10 @@ from fedireads import models, openlibrary, outgoing as api
def home(request): def home(request):
''' user's homepage with activity feed ''' ''' user's homepage with activity feed '''
shelves = models.Shelf.objects.filter(user=request.user.id) shelves = models.Shelf.objects.filter(user=request.user.id)
user_books = models.Book.objects.filter(shelves__user=request.user).all()
recent_books = models.Book.objects.order_by( recent_books = models.Book.objects.order_by(
'added_date' 'added_date'
).annotate( )[:10]
user_shelves=FilteredRelation(
'shelves',
condition=Q(shelves__user_id=request.user.id)
)
).values(
'id', 'authors', 'data', 'user_shelves', 'openlibrary_key'
).distinct()
following = models.User.objects.filter( following = models.User.objects.filter(
Q(followers=request.user) | Q(id=request.user.id) Q(followers=request.user) | Q(id=request.user.id)
@ -41,6 +35,7 @@ def home(request):
'user': request.user, 'user': request.user,
'shelves': shelves, 'shelves': shelves,
'recent_books': recent_books, 'recent_books': recent_books,
'user_books': user_books,
'activities': activities, 'activities': activities,
} }
return TemplateResponse(request, 'feed.html', data) return TemplateResponse(request, 'feed.html', data)