diff --git a/djaif/book/models.py b/djaif/book/models.py index 15d505b..39521e3 100644 --- a/djaif/book/models.py +++ b/djaif/book/models.py @@ -103,6 +103,32 @@ def load_from(self, save_id): book_progress=self, ).save() + def notes(self): + """Return a prepared set of notes. + + These notes will be annotated with relation to the + current page and will appear in order: + + 1. pinned notes (key=0, pinned=True) + 2. current page notes (key=1) + 3. other notes (key=0, pinned=False) + + Within each group the notes will be ordered + by decreasing of 'updated_at'. + """ + return Note.objects.filter( + progress=self, + ).annotate( + key=models.Count( + 'page', + filter=models.Q(page=self.book_page), + ), + ).order_by( + '-pinned', + '-key', + '-updated_at', + ) + class ProgressSave(models.Model): progress = models.ForeignKey(BookProgress, on_delete=models.CASCADE) diff --git a/djaif/book/templates/page.html b/djaif/book/templates/page.html index 65bc705..4ab35c6 100644 --- a/djaif/book/templates/page.html +++ b/djaif/book/templates/page.html @@ -3,6 +3,8 @@ {{ page.book.title }}: {{ page.title }} + +
@@ -78,28 +80,19 @@

Заметки

{% for name, noteset in notesets %} -
diff --git a/djaif/book/views.py b/djaif/book/views.py index e6831b2..0090e7a 100644 --- a/djaif/book/views.py +++ b/djaif/book/views.py @@ -1,4 +1,5 @@ from functools import wraps +from itertools import groupby from django.db import transaction from django.db.models import F, Func # noqa: WPS347 @@ -39,6 +40,7 @@ def view_books(request): def view_book(request, book_id): book = get_object_or_404(models.Book, id=book_id) + if not book.first_page: raise ValueError("Book {0.id} hasn't a first page!") try: @@ -50,21 +52,41 @@ def view_book(request, book_id): book=book, user=request.user, ) - page = progress.book_page - links = [ (link, link.has_all_needed(list(progress.items.all()))) - for link in page.pagelink_set.all() + for link in progress.book_page.pagelink_set.all() + ] + + notesets = [ + (name, [ + ( + note.id, + note.text, + note.page.title if note.page else '', + ) + for note in group + ]) + for name, group in groupby( + progress.notes().select_related( + 'page', + ).all(), + key=lambda note: ( + 'page' if note.key else + 'pinned' if note.pinned else + 'other' + ), + ) ] return render( request, 'page.html', context={ - 'page': page, + 'page': progress.book_page, 'progress': progress, 'links': links, - 'page_items': page.items.exclude( + 'notesets': notesets, + 'page_items': progress.book_page.items.exclude( id__in=progress.items.only('id'), ).exclude( id__in=progress.droppeditem_set.values_list( @@ -72,30 +94,8 @@ def view_book(request, book_id): ), ).all(), 'dropped_items': progress.droppeditem_set.filter( - book_page=page, + book_page=progress.book_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(), - ), - ], }, ) diff --git a/djaif/settings.py b/djaif/settings.py index 56445a1..3e6621a 100644 --- a/djaif/settings.py +++ b/djaif/settings.py @@ -116,9 +116,12 @@ USE_TZ = True +DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' + +SHELL_PLUS_PRINT_SQL = True # Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/3.0/howto/static-files/ +# https://docs.djangoproject.com/en/3.2/howto/static-files/ STATIC_URL = '/static/' @@ -130,7 +133,3 @@ MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media') - -DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' - -SHELL_PLUS_PRINT_SQL = True diff --git a/setup.cfg b/setup.cfg index 5f09f09..bf06b40 100644 --- a/setup.cfg +++ b/setup.cfg @@ -29,13 +29,16 @@ exclude = ignore = # documentation isn't so important for now D100, D101, D102, D103, D104, D105, D106, + DAR201, # yes, we have bad names here and there WPS110, WPS111, # annoying stuff WPS326, WPS306, WPS317, WPS202, WPS226, WPS411, WPS323, + WPS509, # I like multiline conditions! WPS337, W503, W504, per-file-ignores = settings.py: WPS407, E501, C812, WPS221, WPS226, S105 models.py: WPS226 + views.py: WPS210 diff --git a/static/favicon.png b/static/favicon.png new file mode 100644 index 0000000..adce88a Binary files /dev/null and b/static/favicon.png differ diff --git a/static/page.css b/static/page.css new file mode 100644 index 0000000..23c9075 --- /dev/null +++ b/static/page.css @@ -0,0 +1,9 @@ +.noteset {} + +.noteset-page { + background-color: greenyellow; +} + +.noteset-pinned { + background-color: yellow; +}