This commit is contained in:
Mouse Reeve 2020-01-29 00:05:58 -08:00
parent 789b9a1dc0
commit f3330ab6e7
9 changed files with 58 additions and 24 deletions

View file

@ -1,4 +1,4 @@
# Generated by Django 3.0.2 on 2020-01-29 06:31 # Generated by Django 3.0.2 on 2020-01-29 07:36
from django.conf import settings from django.conf import settings
import django.contrib.auth.models import django.contrib.auth.models
@ -43,7 +43,7 @@ class Migration(migrations.Migration):
('local', models.BooleanField(default=True)), ('local', models.BooleanField(default=True)),
('localname', models.CharField(blank=True, max_length=255, null=True, unique=True)), ('localname', models.CharField(blank=True, max_length=255, null=True, unique=True)),
('name', models.CharField(blank=True, max_length=100, null=True)), ('name', models.CharField(blank=True, max_length=100, null=True)),
('avatar', models.ImageField(blank=True, null=True, upload_to='uploads/')), ('avatar', models.ImageField(blank=True, null=True, upload_to='avatars/')),
('created_date', models.DateTimeField(auto_now_add=True)), ('created_date', models.DateTimeField(auto_now_add=True)),
('updated_date', models.DateTimeField(auto_now=True)), ('updated_date', models.DateTimeField(auto_now=True)),
('followers', models.ManyToManyField(to=settings.AUTH_USER_MODEL)), ('followers', models.ManyToManyField(to=settings.AUTH_USER_MODEL)),
@ -89,6 +89,7 @@ class Migration(migrations.Migration):
('activitypub_id', models.CharField(max_length=255)), ('activitypub_id', models.CharField(max_length=255)),
('openlibrary_key', models.CharField(max_length=255, unique=True)), ('openlibrary_key', models.CharField(max_length=255, unique=True)),
('data', django.contrib.postgres.fields.jsonb.JSONField()), ('data', django.contrib.postgres.fields.jsonb.JSONField()),
('cover', models.ImageField(blank=True, null=True, upload_to='covers/')),
('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)),
('added_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), ('added_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),

View file

@ -30,7 +30,7 @@ class User(AbstractUser):
) )
# name is your display name, which you can change at will # name is your display name, which you can change at will
name = models.CharField(max_length=100, blank=True, null=True) name = models.CharField(max_length=100, blank=True, null=True)
avatar = models.ImageField(upload_to='uploads/', blank=True, null=True) avatar = models.ImageField(upload_to='avatars/', blank=True, null=True)
# TODO: a field for if non-local users are readers or others # TODO: a field for if non-local users are readers or others
followers = models.ManyToManyField('self', symmetrical=False) followers = models.ManyToManyField('self', symmetrical=False)
created_date = models.DateTimeField(auto_now_add=True) created_date = models.DateTimeField(auto_now_add=True)
@ -205,6 +205,7 @@ class Book(models.Model):
data = JSONField() data = JSONField()
works = models.ManyToManyField('Work') works = models.ManyToManyField('Work')
authors = models.ManyToManyField('Author') authors = models.ManyToManyField('Author')
cover = models.ImageField(upload_to='covers/', blank=True, null=True)
shelves = models.ManyToManyField( shelves = models.ManyToManyField(
'Shelf', 'Shelf',
symmetrical=False, symmetrical=False,

View file

@ -1,12 +1,13 @@
''' activitystream api and books ''' ''' activitystream api and books '''
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.core.files.base import ContentFile
import requests import requests
from fedireads.models import Author, Book, Work from fedireads.models import Author, Book, Work
from fedireads.settings import OL_URL from fedireads.settings import OL_URL
def get_or_create_book(olkey, user=None, update=True): def get_or_create_book(olkey, user=None, update=False):
''' add a book ''' ''' add a book '''
# TODO: check if this is a valid open library key, and a book # TODO: check if this is a valid open library key, and a book
olkey = olkey olkey = olkey
@ -44,9 +45,23 @@ def get_or_create_book(olkey, user=None, update=True):
author_id = author_id['key'] author_id = author_id['key']
book.authors.add(get_or_create_author(author_id)) book.authors.add(get_or_create_author(author_id))
if len(data['covers']):
book.cover.save(*get_cover(data['covers'][0]), save=True)
return book return book
def get_cover(cover_id):
''' ask openlibrary for the cover '''
image_name = '%s-M.jpg' % cover_id
url = 'https://covers.openlibrary.org/b/id/%s' % image_name
response = requests.get(url)
if not response.ok:
response.raise_for_status()
image_content = ContentFile(requests.get(url).content)
return [image_name, image_content]
def get_or_create_work(olkey): def get_or_create_work(olkey):
''' load em up ''' ''' load em up '''
# TODO: validate that this is a work key # TODO: validate that this is a work key

View file

@ -33,6 +33,10 @@ h2 {
#branding { #branding {
flex-grow: 1; flex-grow: 1;
} }
#branding a {
text-decoration: none;
color: black;
}
#actions { #actions {
flex-grow: 0; flex-grow: 0;
text-align: right; text-align: right;
@ -44,11 +48,6 @@ h2 {
padding: 0.5rem; padding: 0.5rem;
} }
#top-bar a {
color: black;
text-decoration: none;
}
#branding { #branding {
font-size: 2em; font-size: 2em;
} }
@ -76,6 +75,11 @@ h2 {
margin-right: 0.5em; margin-right: 0.5em;
} }
.book-cover.small {
width: 50px;
height: auto;
}
#feed, #content { #feed, #content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View file

@ -3,7 +3,7 @@
<div id="content"> <div id="content">
<div> <div>
<div class="book-preview"> <div class="book-preview">
<img class="book-cover" src="/static/images/med.jpg"> <img class="book-cover" src="{% if book.cover %}/images/{{ book.cover }}{% else %}/static/images/no_cover.jpg{% endif %}">
<h1>{{ book.data.title }}</h1> <h1>{{ book.data.title }}</h1>
by {{ book.authors.first.data.name }} by {{ book.authors.first.data.name }}
{{ rating }} stars {{ rating }} stars

View file

@ -3,7 +3,6 @@
<div id="content"> <div id="content">
<div class="user-profile"> <div class="user-profile">
<h1>{% if user.localname %}{{ user.localname }}{% else %}{{ user.username }}{% endif %}</h1> <h1>{% if user.localname %}{{ user.localname }}{% else %}{{ user.username }}{% endif %}</h1>
<img class="user-pic" src="/static/images/profile.jpg">
<form name="avatar" action="/edit_profile/" method="post" enctype="multipart/form-data"> <form name="avatar" action="/edit_profile/" method="post" enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
{{ form.as_p }} {{ form.as_p }}

View file

@ -4,18 +4,24 @@
<div> <div>
<h2>Currently Reading</h2> <h2>Currently Reading</h2>
{# listing books currently on user's shelves #} {# listing books currently on user's shelves #}
{% if not shelves.first.books.all %} {% if not reading.books.all %}
<p>Start a book!</p> <p>Start a book!</p>
{% endif %} {% for book in to_read.books.all %}
{% for book in shelves.first.books.all %}
<div class="book-preview"> <div class="book-preview">
<img class="cover" src="static/images/small.jpg"> <img class="book-cover small" src="{% if book.cover %}/images/{{ book.cover }}{% else %}/static/images/no_cover.jpg{% endif %}">
<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>
<button>start reading</button>
</div>
{% endfor %}
{% endif %}
{% for book in reading.books.all %}
<div class="book-preview">
<img class="book-cover small" src="{% if book.cover %}/images/{{ book.cover }}{% else %}/static/images/no_cover.jpg{% endif %}">
<p class="title"><a href="{{ book.openlibrary_key }}">{{ book.data.title }}</a></p> <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> <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> <button>done reading</button>
{% endif %}
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
@ -24,7 +30,7 @@
<h2>Recently Added Books</h2> <h2>Recently Added Books</h2>
{% 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="book-cover small" src="{% if book.cover %}/images/{{ book.cover }}{% else %}/static/images/no_cover.jpg{% endif %}">
<p class="title"> <p class="title">
<a href="{{ book.openlibrary_key }}">{{ book.data.title }}</a> <a href="{{ book.openlibrary_key }}">{{ book.data.title }}</a>
by by
@ -65,7 +71,7 @@
</h2> </h2>
{# TODO: wouldn't it rule if this was a reusable piece of markup? #} {# TODO: wouldn't it rule if this was a reusable piece of markup? #}
<div class="book-preview"> <div class="book-preview">
<img class="cover" src="static/images/med.jpg"> <img class="book-cover" src="{% if activity.book.cover %}/images/{{ activity.book.cover }}{% else %}/static/images/no_cover.jpg{% endif %}">
<p class="title"> <p class="title">
<a href="{{ activity.book.openlibrary_key }}">{{ activity.book.data.title }}</a> <a href="{{ activity.book.openlibrary_key }}">{{ activity.book.data.title }}</a>
by by
@ -77,7 +83,7 @@
reviewed {{ activity.book.data.title }} reviewed {{ activity.book.data.title }}
</h2> </h2>
<div class="book-preview review"> <div class="book-preview review">
<img class="cover" src="static/images/med.jpg"> <img class="book-cover" src="{% if activity.book.cover %}/images/{{ activity.book.cover }}{% else %}/static/images/no_cover.jpg{% endif %}">
<p class="title"> <p class="title">
<a href="{{ activity.book.openlibrary_key }}">{{ activity.book.data.title }}</a> <a href="{{ activity.book.openlibrary_key }}">{{ activity.book.data.title }}</a>
by by

View file

@ -27,7 +27,7 @@
<div id="account"> <div id="account">
{% if user.is_authenticated %} {% if user.is_authenticated %}
<form name="logout" action="/logout/" method="post"> <form name="logout" action="/logout/" method="post">
Welcome, <a href="{{ request.user.actor }}">{% if request.user.localname %}{{ request.user.localname }}{% else %}{{ request.user.username }}{% endif %}</a> Welcome, <a href="/user/{{ request.user.localname }}">{{ request.user.localname }}</a>
<input type="submit" value="Log out"></input> <input type="submit" value="Log out"></input>
</form> </form>
{% else %} {% else %}

View file

@ -15,7 +15,14 @@ from fedireads.settings import DOMAIN
@login_required @login_required
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) reading = models.Shelf.objects.get(
user=request.user,
shelf_type='reading'
)
to_read = models.Shelf.objects.get(
user=request.user,
shelf_type='to-read'
)
user_books = models.Book.objects.filter(shelves__user=request.user).all() 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'
@ -35,7 +42,8 @@ def home(request):
login_form = forms.LoginForm() login_form = forms.LoginForm()
data = { data = {
'user': request.user, 'user': request.user,
'shelves': shelves, 'reading': reading,
'to_read': to_read,
'recent_books': recent_books, 'recent_books': recent_books,
'user_books': user_books, 'user_books': user_books,
'activities': activities, 'activities': activities,