Pagination for the notifications page

main
Thomas Sileo 2022-08-25 08:45:07 +02:00
parent d43bf54609
commit 30cfd6260b
2 changed files with 50 additions and 1 deletions

View File

@ -211,6 +211,7 @@ async def admin_bookmarks(
request: Request, request: Request,
db_session: AsyncSession = Depends(get_db_session), db_session: AsyncSession = Depends(get_db_session),
) -> templates.TemplateResponse: ) -> templates.TemplateResponse:
# TODO: support pagination
stream = ( stream = (
( (
await db_session.scalars( await db_session.scalars(
@ -667,12 +668,25 @@ async def admin_outbox(
@router.get("/notifications") @router.get("/notifications")
async def 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: ) -> 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 = ( notifications = (
( (
await db_session.scalars( await db_session.scalars(
select(models.Notification) select(models.Notification)
.where(*where)
.options( .options(
joinedload(models.Notification.actor), joinedload(models.Notification.actor),
joinedload(models.Notification.inbox_object), joinedload(models.Notification.inbox_object),
@ -684,6 +698,7 @@ async def get_notifications(
joinedload(models.Notification.webmention), joinedload(models.Notification.webmention),
) )
.order_by(models.Notification.created_at.desc()) .order_by(models.Notification.created_at.desc())
.limit(page_size)
) )
) )
.unique() .unique()
@ -697,6 +712,27 @@ async def get_notifications(
notif.is_new = False notif.is_new = False
await db_session.commit() 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( return await templates.render_template(
db_session, db_session,
request, request,
@ -704,6 +740,8 @@ async def get_notifications(
{ {
"notifications": notifications, "notifications": notifications,
"actors_metadata": actors_metadata, "actors_metadata": actors_metadata,
"next_cursor": next_cursor,
"more_unread_count": more_unread_count,
}, },
) )

View File

@ -88,4 +88,15 @@
</div> </div>
{%- endfor %} {%- endfor %}
</div> </div>
{% if next_cursor %}
<div class="box">
<p>
<a href="{{ request.url._path }}?cursor={{ next_cursor }}">
See more{% if more_unread_count %}({{ more_unread_count }} unread left){% endif %}
</a>
</p>
</div>
{% endif %}
{% endblock %} {% endblock %}