forked from mirrors/bookwyrm
Merge pull request #123 from cthulahoops/progress
Add model to store reading progress.
This commit is contained in:
commit
4f568987f5
7 changed files with 111 additions and 2 deletions
|
@ -2,9 +2,10 @@
|
||||||
import re
|
import re
|
||||||
import csv
|
import csv
|
||||||
import itertools
|
import itertools
|
||||||
|
import dateutil.parser
|
||||||
|
|
||||||
from fedireads import books_manager
|
from fedireads import books_manager
|
||||||
from fedireads.models import Edition
|
from fedireads.models import Edition, ReadThrough
|
||||||
|
|
||||||
|
|
||||||
# Mapping goodreads -> fedireads shelf titles.
|
# Mapping goodreads -> fedireads shelf titles.
|
||||||
|
@ -99,6 +100,25 @@ class GoodreadsItem:
|
||||||
def rating(self):
|
def rating(self):
|
||||||
return int(self.line['My Rating'])
|
return int(self.line['My Rating'])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def date_added(self):
|
||||||
|
if self.line['Date Added']:
|
||||||
|
return dateutil.parser.parse(self.line['Date Added'])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def date_read(self):
|
||||||
|
if self.line['Date Read']:
|
||||||
|
return dateutil.parser.parse(self.line['Date Read'])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reads(self):
|
||||||
|
return [ReadThrough(
|
||||||
|
# Date added isn't the start date, but it's (perhaps) better than nothing.
|
||||||
|
start_date=self.date_added,
|
||||||
|
finish_date=self.date_read,
|
||||||
|
pages_read=None,
|
||||||
|
)]
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<GoodreadsItem {!r}>".format(self.line['Title'])
|
return "<GoodreadsItem {!r}>".format(self.line['Title'])
|
||||||
|
|
||||||
|
|
31
fedireads/migrations/0031_readthrough.py
Normal file
31
fedireads/migrations/0031_readthrough.py
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# Generated by Django 3.0.3 on 2020-04-15 12:24
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('fedireads', '0030_quotation'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ReadThrough',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created_date', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('updated_date', models.DateTimeField(auto_now=True)),
|
||||||
|
('pages_read', models.IntegerField(blank=True, null=True)),
|
||||||
|
('start_date', models.DateTimeField(blank=True, null=True)),
|
||||||
|
('finish_date', models.DateTimeField(blank=True, null=True)),
|
||||||
|
('book', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='fedireads.Book')),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
|
@ -2,6 +2,6 @@
|
||||||
from .book import Connector, Book, Work, Edition, Author
|
from .book import Connector, Book, Work, Edition, Author
|
||||||
from .shelf import Shelf, ShelfBook
|
from .shelf import Shelf, ShelfBook
|
||||||
from .status import Status, Review, Comment, Quotation
|
from .status import Status, Review, Comment, Quotation
|
||||||
from .status import Favorite, Boost, Tag, Notification
|
from .status import Favorite, Boost, Tag, Notification, ReadThrough
|
||||||
from .user import User, UserFollows, UserFollowRequest, UserBlocks
|
from .user import User, UserFollows, UserFollowRequest, UserBlocks
|
||||||
from .user import FederatedServer
|
from .user import FederatedServer
|
||||||
|
|
|
@ -134,6 +134,21 @@ class Tag(FedireadsModel):
|
||||||
unique_together = ('user', 'book', 'name')
|
unique_together = ('user', 'book', 'name')
|
||||||
|
|
||||||
|
|
||||||
|
class ReadThrough(FedireadsModel):
|
||||||
|
''' Store progress through a book in the database. '''
|
||||||
|
user = models.ForeignKey('User', on_delete=models.PROTECT)
|
||||||
|
book = models.ForeignKey('Book', on_delete=models.PROTECT)
|
||||||
|
pages_read = models.IntegerField(
|
||||||
|
null=True,
|
||||||
|
blank=True)
|
||||||
|
start_date = models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
null=True)
|
||||||
|
finish_date = models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
null=True)
|
||||||
|
|
||||||
|
|
||||||
NotificationType = models.TextChoices(
|
NotificationType = models.TextChoices(
|
||||||
'NotificationType', 'FAVORITE REPLY TAG FOLLOW FOLLOW_REQUEST BOOST')
|
'NotificationType', 'FAVORITE REPLY TAG FOLLOW FOLLOW_REQUEST BOOST')
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
''' handles all the activity coming out of the server '''
|
''' handles all the activity coming out of the server '''
|
||||||
|
from datetime import datetime
|
||||||
from urllib.parse import urlencode
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
from django.db import IntegrityError, transaction
|
from django.db import IntegrityError, transaction
|
||||||
|
@ -138,6 +139,25 @@ def handle_shelve(user, book, shelf):
|
||||||
status.status_type = 'Update'
|
status.status_type = 'Update'
|
||||||
status.save()
|
status.save()
|
||||||
|
|
||||||
|
if shelf.identifier == 'reading':
|
||||||
|
read = models.ReadThrough(
|
||||||
|
user=user,
|
||||||
|
book=book,
|
||||||
|
start_date=datetime.now())
|
||||||
|
read.save()
|
||||||
|
elif shelf.identifier == 'read':
|
||||||
|
read = models.ReadThrough.objects.filter(
|
||||||
|
user=user,
|
||||||
|
book=book,
|
||||||
|
finish_date=None).order_by('-created_date').first()
|
||||||
|
if not read:
|
||||||
|
read = models.ReadThrough(
|
||||||
|
user=user,
|
||||||
|
book=book,
|
||||||
|
start_date=datetime.now())
|
||||||
|
read.finish_date = datetime.now()
|
||||||
|
read.save()
|
||||||
|
|
||||||
activity = activitypub.get_status(status)
|
activity = activitypub.get_status(status)
|
||||||
create_activity = activitypub.get_create(user, activity)
|
create_activity = activitypub.get_create(user, activity)
|
||||||
|
|
||||||
|
@ -177,6 +197,11 @@ def handle_import_books(user, items):
|
||||||
recipients = get_recipients(user, 'public')
|
recipients = get_recipients(user, 'public')
|
||||||
broadcast(user, activity, recipients)
|
broadcast(user, activity, recipients)
|
||||||
|
|
||||||
|
for read in item.reads:
|
||||||
|
read.book = item.book
|
||||||
|
read.user = user
|
||||||
|
read.save()
|
||||||
|
|
||||||
if new_books:
|
if new_books:
|
||||||
message = 'imported {} books'.format(len(new_books))
|
message = 'imported {} books'.format(len(new_books))
|
||||||
status = create_status(user, message, mention_books=new_books)
|
status = create_status(user, message, mention_books=new_books)
|
||||||
|
|
|
@ -18,6 +18,12 @@
|
||||||
<th>
|
<th>
|
||||||
Shelved
|
Shelved
|
||||||
</th>
|
</th>
|
||||||
|
<th>
|
||||||
|
Started
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Finished
|
||||||
|
</th>
|
||||||
<th>
|
<th>
|
||||||
External links
|
External links
|
||||||
</th>
|
</th>
|
||||||
|
@ -44,6 +50,13 @@
|
||||||
<td>
|
<td>
|
||||||
{{ book.created_date | naturalday }}
|
{{ book.created_date | naturalday }}
|
||||||
</td>
|
</td>
|
||||||
|
{% latest_read_through book user as read_through %}
|
||||||
|
<td>
|
||||||
|
{{ read_through.start_date | naturalday |default_if_none:""}}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ read_through.finish_date | naturalday |default_if_none:""}}
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="https://openlibrary.org/book/{{ book.openlibrary_key }}" target="_blank">OpenLibrary</a>
|
<a href="https://openlibrary.org/book/{{ book.openlibrary_key }}" target="_blank">OpenLibrary</a>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -168,3 +168,8 @@ def current_shelf(context, book):
|
||||||
return None
|
return None
|
||||||
return shelf.name
|
return shelf.name
|
||||||
|
|
||||||
|
@register.simple_tag(takes_context=False)
|
||||||
|
def latest_read_through(book, user):
|
||||||
|
return models.ReadThrough.objects.filter(
|
||||||
|
user=user,
|
||||||
|
book=book).order_by('-created_date').first()
|
||||||
|
|
Loading…
Reference in a new issue