From 30cfd6260b37b9af793128456f5be02b51e052cf Mon Sep 17 00:00:00 2001 From: Thomas Sileo Date: Thu, 25 Aug 2022 08:45:07 +0200 Subject: [PATCH] Pagination for the notifications page --- app/admin.py | 40 +++++++++++++++++++++++++++++++- app/templates/notifications.html | 11 +++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/app/admin.py b/app/admin.py index c847f62..4300613 100644 --- a/app/admin.py +++ b/app/admin.py @@ -211,6 +211,7 @@ async def admin_bookmarks( request: Request, db_session: AsyncSession = Depends(get_db_session), ) -> templates.TemplateResponse: + # TODO: support pagination stream = ( ( await db_session.scalars( @@ -667,12 +668,25 @@ async def admin_outbox( @router.get("/notifications") async def get_notifications( - request: Request, db_session: AsyncSession = Depends(get_db_session) + request: Request, + db_session: AsyncSession = Depends(get_db_session), + cursor: str | None = None, ) -> templates.TemplateResponse: + where = [] + if cursor: + decoded_cursor = pagination.decode_cursor(cursor) + where.append(models.Notification.created_at < decoded_cursor) + + page_size = 20 + remaining_count = await db_session.scalar( + select(func.count(models.Notification.id)).where(*where) + ) + notifications = ( ( await db_session.scalars( select(models.Notification) + .where(*where) .options( joinedload(models.Notification.actor), joinedload(models.Notification.inbox_object), @@ -684,6 +698,7 @@ async def get_notifications( joinedload(models.Notification.webmention), ) .order_by(models.Notification.created_at.desc()) + .limit(page_size) ) ) .unique() @@ -697,6 +712,27 @@ async def get_notifications( notif.is_new = False await db_session.commit() + next_cursor = ( + pagination.encode_cursor(notifications[-1].created_at) + if notifications and remaining_count > page_size + else None + ) + + more_unread_count = 0 + next_cursor = None + if notifications and remaining_count > page_size: + decoded_next_cursor = notifications[-1].created_at + next_cursor = pagination.encode_cursor(decoded_next_cursor) + + # If on the "see more" page there's more unread notification, we want + # to display it next to the link + more_unread_count = await db_session.scalar( + select(func.count(models.Notification.id)).where( + models.Notification.is_new.is_(True), + models.Notification.created_at < decoded_next_cursor, + ) + ) + return await templates.render_template( db_session, request, @@ -704,6 +740,8 @@ async def get_notifications( { "notifications": notifications, "actors_metadata": actors_metadata, + "next_cursor": next_cursor, + "more_unread_count": more_unread_count, }, ) diff --git a/app/templates/notifications.html b/app/templates/notifications.html index 3f35fe8..6a4c085 100644 --- a/app/templates/notifications.html +++ b/app/templates/notifications.html @@ -88,4 +88,15 @@ {%- endfor %} + +{% if next_cursor %} +
+

+ + See more{% if more_unread_count %}({{ more_unread_count }} unread left){% endif %} + +

+
+{% endif %} + {% endblock %}