From a247ff61e95a4d03d5bbeca630822a7cb8d15b7c Mon Sep 17 00:00:00 2001 From: Aleksei Pirogov Date: Fri, 4 Jun 2021 22:09:29 +0300 Subject: [PATCH] add the "book notes" feature --- Makefile | 4 + djaif/book/migrations/0016_note.py | 24 +++ djaif/book/migrations/0017_note_progress.py | 20 +++ djaif/book/migrations/0018_note_pinned.py | 18 +++ djaif/book/models.py | 19 ++- djaif/book/templates/note.html | 45 ++++++ djaif/book/templates/page.html | 154 ++++++++++++-------- djaif/book/urls.py | 20 +++ djaif/book/views.py | 74 ++++++++++ 9 files changed, 319 insertions(+), 59 deletions(-) create mode 100644 Makefile create mode 100644 djaif/book/migrations/0016_note.py create mode 100644 djaif/book/migrations/0017_note_progress.py create mode 100644 djaif/book/migrations/0018_note_pinned.py create mode 100644 djaif/book/templates/note.html diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bd6db2c --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +MANAGE := poetry run python manage.py + +run: + $(MANAGE) runserver diff --git a/djaif/book/migrations/0016_note.py b/djaif/book/migrations/0016_note.py new file mode 100644 index 0000000..70a8eb4 --- /dev/null +++ b/djaif/book/migrations/0016_note.py @@ -0,0 +1,24 @@ +# Generated by Django 3.0.5 on 2021-06-04 16:31 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('book', '0015_droppeditemsave'), + ] + + operations = [ + migrations.CreateModel( + name='Note', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('text', models.TextField()), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('page', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='book.BookPage')), + ], + ), + ] diff --git a/djaif/book/migrations/0017_note_progress.py b/djaif/book/migrations/0017_note_progress.py new file mode 100644 index 0000000..ee6b85c --- /dev/null +++ b/djaif/book/migrations/0017_note_progress.py @@ -0,0 +1,20 @@ +# Generated by Django 3.0.5 on 2021-06-04 16:39 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('book', '0016_note'), + ] + + operations = [ + migrations.AddField( + model_name='note', + name='progress', + field=models.ForeignKey(default=42, on_delete=django.db.models.deletion.CASCADE, to='book.BookProgress'), + preserve_default=False, + ), + ] diff --git a/djaif/book/migrations/0018_note_pinned.py b/djaif/book/migrations/0018_note_pinned.py new file mode 100644 index 0000000..2d34978 --- /dev/null +++ b/djaif/book/migrations/0018_note_pinned.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.5 on 2021-06-04 17:24 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('book', '0017_note_progress'), + ] + + operations = [ + migrations.AddField( + model_name='note', + name='pinned', + field=models.BooleanField(default=False), + ), + ] diff --git a/djaif/book/models.py b/djaif/book/models.py index a6eb567..15d505b 100644 --- a/djaif/book/models.py +++ b/djaif/book/models.py @@ -2,7 +2,6 @@ from django.db import models, transaction -# Create your models here. class Book(models.Model): title = models.CharField(name='title', max_length=100, unique=True) first_page = models.ForeignKey( @@ -63,7 +62,9 @@ class Meta: @classmethod def start_reading(cls, user, book): - progress = BookProgress(user=user, book=book, book_page=book.first_page) + progress = BookProgress( + user=user, book=book, book_page=book.first_page, + ) progress.save() return progress @@ -133,3 +134,17 @@ class DroppedItemSave(models.Model): item = models.ForeignKey(Item, on_delete=models.CASCADE) book_page = models.ForeignKey(BookPage, on_delete=models.CASCADE) progress_save = models.ForeignKey(ProgressSave, on_delete=models.CASCADE) + + +class Note(models.Model): + text = models.TextField() + progress = models.ForeignKey(BookProgress, on_delete=models.CASCADE) + page = models.ForeignKey( + BookPage, + on_delete=models.CASCADE, + null=True, + blank=True, + ) + pinned = models.BooleanField(default=False) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) diff --git a/djaif/book/templates/note.html b/djaif/book/templates/note.html new file mode 100644 index 0000000..eef7051 --- /dev/null +++ b/djaif/book/templates/note.html @@ -0,0 +1,45 @@ + + + + + {{ page.book.title }}: {{ page.title }} + + +

+ {{ page.title }}: Заметка +

+
+ {% csrf_token %} + + + + + + + + +
+ + diff --git a/djaif/book/templates/page.html b/djaif/book/templates/page.html index 51410b6..65bc705 100644 --- a/djaif/book/templates/page.html +++ b/djaif/book/templates/page.html @@ -5,63 +5,103 @@ {{ page.book.title }}: {{ page.title }} -

- {{ page.title }} -

- {{ page.body }} - {% if page_items %} -

Вы видите

- - {% endif %} - {% if dropped_items %} -

Брошено вами ранее

- - {% endif %} -

Куда податься?

- - {% if progress.items.all %} -

Инвентарь

- - {% endif %} -
- Сохранения + {% if dropped_items %} +

Брошено вами ранее

+ + {% endif %} +

Куда податься?

+ + {% if progress.items.all %} +

Инвентарь

+ + {% endif %} +
+ Сохранения + + + diff --git a/djaif/book/urls.py b/djaif/book/urls.py index 5b1db06..90dc10a 100644 --- a/djaif/book/urls.py +++ b/djaif/book/urls.py @@ -34,5 +34,25 @@ views.delete_save, name='delete_save', ), + path( + 'book//notes/add', + views.add_note, + name='add_note', + ), + path( + 'book//notes/delete/', + views.delete_note, + name='delete_note', + ), + path( + 'book//notes/toggle/', + views.toggle_note, + name='toggle_note', + ), + path( + 'book//notes/update/', + views.update_note, + name='update_note', + ), path('book//map.svg', views.view_book_map), ] diff --git a/djaif/book/views.py b/djaif/book/views.py index dacf067..e6831b2 100644 --- a/djaif/book/views.py +++ b/djaif/book/views.py @@ -1,6 +1,7 @@ from functools import wraps from django.db import transaction +from django.db.models import F, Func # noqa: WPS347 from django.http import FileResponse from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse @@ -73,6 +74,28 @@ def view_book(request, book_id): 'dropped_items': progress.droppeditem_set.filter( book_page=page, ).all(), + 'notesets': [ + ( + 'pinned', + progress.note_set.filter( + pinned=True, + ).order_by('-updated_at').all(), + ), + ( + 'page', + progress.note_set.filter( + page=page, pinned=False, + ).order_by('-updated_at').all(), + ), + ( + 'other', + progress.note_set.exclude( + page=page, + ).filter( + pinned=False, + ).order_by('-updated_at').all(), + ), + ], }, ) @@ -168,3 +191,54 @@ def delete_save(request, book_id, save_id): def view_book_map(request, book_id): book = get_object_or_404(models.Book, id=book_id) return FileResponse(book_map.book_map(book), filename='map.svg') + + +@on_progress +def add_note(request, progress, book_id): + if 'pin' in request.POST: + page = progress.book_page + else: + page = None + models.Note.objects.create( + progress=progress, + text=request.POST['text'], + page=page, + ) + return _return_to(book_id) + + +def delete_note(request, book_id, note_id): + models.Note.objects.get(id=note_id).delete() + return _return_to(book_id) + + +def toggle_note(request, book_id, note_id): + models.Note.objects.filter( + id=note_id, + ).update( + pinned=Func(F('pinned'), function='NOT'), + ) + return _return_to(book_id) + + +@on_progress +def update_note(request, progress, book_id, note_id): + note = get_object_or_404(models.Note, id=note_id) + if request.method == 'GET': + return render( + request, + 'note.html', + context={ + 'page': progress.book_page, + 'note': note, + }, + ) + note.text = request.POST['text'] + note.pinned = 'pinned' in request.POST + note.page = { + 'keep': note.page, + 'change': progress.book_page, + 'remove': None, + }[request.POST['page']] + note.save() + return _return_to(book_id)