Browse Source

Add Mark all read button to unread notifications

This will only mark notifications upto the timestamp of the last one on the unread notifications page where it was clicked.
merge-requests/20/head
James Southern 7 years ago
parent
commit
13309ca093
  1. 5
      tildes/tildes/routes.py
  2. 14
      tildes/tildes/templates/notifications_unread.jinja2
  3. 73
      tildes/tildes/views/api/web/notifications.py

5
tildes/tildes/routes.py

@ -183,6 +183,11 @@ def add_intercooler_routes(config: Configurator) -> None:
'/user/{username}/default_listing_options',
factory=user_by_username,
)
add_ic_route(
'mark_notifications_read_before',
'/notifications/{last_notification_seen}/mark_read_before',
factory=LoggedInFactory,
)
class LoggedInFactory:

14
tildes/tildes/templates/notifications_unread.jinja2

@ -5,7 +5,19 @@
{% block title %}Unread notifications{% endblock %}
{% block main_heading %}Unread notifications{% endblock %}
{% block main_heading %}Unread notifications
{% if notifications and not request.user.auto_mark_notifications_read %}
<button
class="btn btn-link-minimal ml-2"
data-ic-put-to="{{ request.route_url(
'ic_mark_notifications_read_before',
last_notification_seen=notifications[0].created_time,
)}}",
data-ic-target="closest main"
>Mark all read</button>
{% endif %}
{% endblock %}
{% block content %}
{% if notifications %}

73
tildes/tildes/views/api/web/notifications.py

@ -0,0 +1,73 @@
"""Web API endpoints related to comment notifications."""
from datetime import datetime
from marshmallow.fields import DateTime
from pyramid.request import Request
from pyramid.response import Response
from sqlalchemy.dialects.postgresql import insert
from webargs.pyramidparser import use_kwargs
from zope.sqlalchemy import mark_changed
from tildes.lib.datetime import utc_now
from tildes.models.comment import CommentNotification
from tildes.models.topic import TopicVisit
from tildes.views.decorators import ic_view_config
@ic_view_config(
route_name='mark_notifications_read_before', request_method='PUT',
)
@use_kwargs(
{'last_notification_seen': DateTime(required=True)},
locations=('matchdict',),
)
def put_notifications_read_before(
request: Request,
last_notification_seen: datetime,
) -> Response:
"""Clear all user comment notifications before the latest displayed."""
notifications = (
request.query(CommentNotification)
.join_all_relationships()
.filter(
CommentNotification.user == request.user,
CommentNotification.is_unread == True, # noqa
CommentNotification.created_time <= last_notification_seen,
)
.all()
)
# If the user has the "track comment visits" feature enabled, we want to
# increment the number of comments they've seen in the thread that the
# comment came from, so that they don't *both* get a notification as well
# as have the thread highlight with "(1 new)". This should only happen if
# their last visit was before the comment was posted, however.
# Below, this is implemented as a INSERT ... ON CONFLICT DO UPDATE so that
# it will insert a new topic visit with 1 comment if they didn't previously
# have one at all.
if request.user.track_comment_visits:
for notification in notifications:
statement = (
insert(TopicVisit.__table__)
.values(
user_id=request.user.user_id,
topic_id=notification.comment.topic_id,
visit_time=utc_now(),
num_comments=1,
)
.on_conflict_do_update(
constraint=TopicVisit.__table__.primary_key,
set_={'num_comments': TopicVisit.num_comments + 1},
where=TopicVisit.visit_time <
notification.comment.created_time,
)
)
request.db_session.execute(statement)
mark_changed(request.db_session)
for notification in notifications:
notification.is_unread = False
return Response('Your comment notifications have been cleared.')
Loading…
Cancel
Save