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
import django.contrib.auth.models
@ -86,7 +86,7 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('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()),
('added_date', models.DateTimeField(auto_now_add=True)),
('updated_date', models.DateTimeField(auto_now=True)),

View file

@ -199,7 +199,7 @@ class ShelfBook(models.Model):
class Book(models.Model):
''' a non-canonical copy from open library '''
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()
works = models.ManyToManyField('Work')
authors = models.ManyToManyField('Author')

View file

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

View file

@ -1,19 +1,30 @@
{% extends 'layout.html' %}
{% block content %}
<div id="main">
<div class="book-profile">
<img class="book-cover" src="/static/images/med.jpg">
<h1>{{ book.data.title }}</h1>
by {{ book.authors.first.data.name }}
{{ rating }} stars
<div id="content">
<div>
<div class="book-preview">
<img class="book-cover" src="/static/images/med.jpg">
<h1>{{ book.data.title }}</h1>
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>
<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">
<h2>Reviews</h2>

View file

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

View file

@ -1,30 +1,27 @@
{% extends 'layout.html' %}
{% block content %}
<div id="sidebar">
{# listing books currently on user's shelves #}
{# TODO: this should only show currently reading probably #}
{% for shelf in shelves %}
{% if shelf.books.all %}
<h2>{{ shelf.name }}</h2>
{% 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>
<div>
<h2>Currently Reading</h2>
{# listing books currently on user's shelves #}
{% if not shelves.first.books.all %}
<p>Start a book!</p>
{% 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>
{% endfor %}
{% endif %}
{% endfor %}
</div>
<div id="main">
<div class="carosel">
{# a display of books in your local db, so you have somewhere to start #}
<div>
<h2>Recently Added Books</h2>
{% for book in recent_books %}
<div class="book-preview">
<img class="cover" src="static/images/small.jpg">
@ -34,7 +31,7 @@
{# TODO: there should be a helper function for listing authors #}
<a href="" class="author">{{ book.authors.first.data.name }}</a>
</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">
<input type="hidden" name="book" value="book.id"></input>
<button type="submit">Want to read</button>
@ -43,55 +40,62 @@
</div>
{% endfor %}
</div>
</div>
<div id="feed">
{% for activity in activities %}
<div class="update">
<div class="user-preview">
<img class="user-pic" src="static/images/profile.jpg">
{# 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">
{% if activity.user.localname %}{{ activity.user.localname }}{% else %}{{ activity.user.username }}{% endif %}</a>
{% if activity.fedireads_type == 'Shelve' %}
{# display a reading/shelving activity #}
{% if activity.shelf.shelf_type == 'to-read' %}
wants to read
{% elif activity.shelf.shelf_type == 'read' %}
finished reading
{% elif activity.shelf.shelf_type == '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
<h2>
<img class="user-pic" src="static/images/profile.jpg">
{# TODO: a helper function for displaying a username #}
<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.fedireads_type == 'Shelve' %}
{# display a reading/shelving activity #}
{% if activity.shelf.shelf_type == 'to-read' %}
wants to read
{% elif activity.shelf.shelf_type == 'read' %}
finished reading
{% elif activity.shelf.shelf_type == 'reading' %}
started reading
{% else %}
{# generic handling for a misc activity, which perhaps should not be displayed at all #}
did {{ activity.activity_type }}</span>
shelved in "{{ activity.shelf.name }}"
{% 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>
{% endfor %}
</div>

View file

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

View file

@ -1,8 +1,17 @@
{% extends 'layout.html' %}
{% block content %}
<form name="login" method="post">
<input type="text" name="username"></input>
<input type="password" name="password"></input>
<input type="submit"></input>
</form>
<div id="content">
<div>
<form name="login" method="post">
<label for="username">Username:
<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 %}

View file

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

View file

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

View file

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