forked from mirrors/bookwyrm
Improves templates
This commit is contained in:
parent
b554280481
commit
e0c174d990
11 changed files with 166 additions and 132 deletions
|
@ -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)),
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -47,12 +47,9 @@
|
|||
</header>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<div>
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
<div id="main">
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue