mirror of
https://github.com/jointakahe/takahe.git
synced 2024-11-22 07:10:59 +00:00
Add support to dismiss notifications (#605)
This commit is contained in:
parent
1cc9c16b8c
commit
5f49f9b2bb
6 changed files with 102 additions and 9 deletions
18
activities/migrations/0018_timelineevent_dismissed.py
Normal file
18
activities/migrations/0018_timelineevent_dismissed.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 4.2.2 on 2023-07-09 17:25
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("activities", "0017_stator_next_change"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="timelineevent",
|
||||||
|
name="dismissed",
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
|
@ -55,6 +55,7 @@ class TimelineEvent(models.Model):
|
||||||
|
|
||||||
published = models.DateTimeField(default=timezone.now)
|
published = models.DateTimeField(default=timezone.now)
|
||||||
seen = models.BooleanField(default=False)
|
seen = models.BooleanField(default=False)
|
||||||
|
dismissed = models.BooleanField(default=False)
|
||||||
|
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ class TimelineService:
|
||||||
def notifications(self, types: list[str]) -> models.QuerySet[TimelineEvent]:
|
def notifications(self, types: list[str]) -> models.QuerySet[TimelineEvent]:
|
||||||
return (
|
return (
|
||||||
self.event_queryset()
|
self.event_queryset()
|
||||||
.filter(identity=self.identity, type__in=types)
|
.filter(identity=self.identity, type__in=types, dismissed=False)
|
||||||
.order_by("-created")
|
.order_by("-created")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,9 @@ urlpatterns = [
|
||||||
path("v1/statuses/<id>/source", statuses.status_source),
|
path("v1/statuses/<id>/source", statuses.status_source),
|
||||||
# Notifications
|
# Notifications
|
||||||
path("v1/notifications", notifications.notifications),
|
path("v1/notifications", notifications.notifications),
|
||||||
|
path("v1/notifications/clear", notifications.dismiss_notifications),
|
||||||
path("v1/notifications/<id>", notifications.get_notification),
|
path("v1/notifications/<id>", notifications.get_notification),
|
||||||
|
path("v1/notifications/<id>/dismiss", notifications.dismiss_notification),
|
||||||
# Polls
|
# Polls
|
||||||
path("v1/polls/<id>", polls.get_poll),
|
path("v1/polls/<id>", polls.get_poll),
|
||||||
path("v1/polls/<id>/votes", polls.vote_poll),
|
path("v1/polls/<id>/votes", polls.vote_poll),
|
||||||
|
|
|
@ -72,3 +72,29 @@ def get_notification(
|
||||||
id=id,
|
id=id,
|
||||||
)
|
)
|
||||||
return schemas.Notification.from_timeline_event(notification)
|
return schemas.Notification.from_timeline_event(notification)
|
||||||
|
|
||||||
|
|
||||||
|
@scope_required("write:notifications")
|
||||||
|
@api_view.post
|
||||||
|
def dismiss_notifications(request: HttpRequest) -> dict:
|
||||||
|
TimelineService(request.identity).notifications(
|
||||||
|
list(NOTIFICATION_TYPES.values())
|
||||||
|
).update(dismissed=True)
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
@scope_required("write:notifications")
|
||||||
|
@api_view.post
|
||||||
|
def dismiss_notification(request: HttpRequest, id: str) -> dict:
|
||||||
|
notification = get_object_or_404(
|
||||||
|
TimelineService(request.identity).notifications(
|
||||||
|
list(NOTIFICATION_TYPES.values())
|
||||||
|
),
|
||||||
|
id=id,
|
||||||
|
)
|
||||||
|
|
||||||
|
notification.dismissed = True
|
||||||
|
notification.save()
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
|
@ -11,11 +11,10 @@ def test_notifications(api_client, identity, remote_identity):
|
||||||
subject_identity=remote_identity,
|
subject_identity=remote_identity,
|
||||||
)
|
)
|
||||||
|
|
||||||
response = api_client.get("/api/v1/notifications").json()
|
data = api_client.get("/api/v1/notifications").json()
|
||||||
|
assert len(data) == 1
|
||||||
assert len(response) == 1
|
assert data[0]["type"] == "follow"
|
||||||
assert response[0]["type"] == "follow"
|
assert data[0]["account"]["id"] == str(remote_identity.id)
|
||||||
assert response[0]["account"]["id"] == str(remote_identity.id)
|
|
||||||
|
|
||||||
event.delete()
|
event.delete()
|
||||||
|
|
||||||
|
@ -28,8 +27,55 @@ def test_get_notification(api_client, identity, remote_identity):
|
||||||
subject_identity=remote_identity,
|
subject_identity=remote_identity,
|
||||||
)
|
)
|
||||||
|
|
||||||
response = api_client.get(f"/api/v1/notifications/{event.id}").json()
|
data = api_client.get(f"/api/v1/notifications/{event.id}").json()
|
||||||
assert response["type"] == "follow"
|
assert data["type"] == "follow"
|
||||||
assert response["account"]["id"] == str(remote_identity.id)
|
assert data["account"]["id"] == str(remote_identity.id)
|
||||||
|
|
||||||
event.delete()
|
event.delete()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_dismiss_notifications(api_client, identity, identity2, remote_identity):
|
||||||
|
TimelineEvent.objects.create(
|
||||||
|
identity=identity,
|
||||||
|
type=TimelineEvent.Types.followed,
|
||||||
|
subject_identity=identity2,
|
||||||
|
)
|
||||||
|
TimelineEvent.objects.create(
|
||||||
|
identity=identity,
|
||||||
|
type=TimelineEvent.Types.followed,
|
||||||
|
subject_identity=remote_identity,
|
||||||
|
)
|
||||||
|
|
||||||
|
data = api_client.get("/api/v1/notifications").json()
|
||||||
|
assert len(data) == 2
|
||||||
|
|
||||||
|
response = api_client.post("/api/v1/notifications/clear", {})
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json() == {}
|
||||||
|
|
||||||
|
data = api_client.get("/api/v1/notifications").json()
|
||||||
|
assert len(data) == 0
|
||||||
|
|
||||||
|
TimelineEvent.objects.filter(identity=identity).delete()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_dismiss_notification(api_client, identity, remote_identity):
|
||||||
|
event = TimelineEvent.objects.create(
|
||||||
|
identity=identity,
|
||||||
|
type=TimelineEvent.Types.followed,
|
||||||
|
subject_identity=remote_identity,
|
||||||
|
)
|
||||||
|
|
||||||
|
data = api_client.get("/api/v1/notifications").json()
|
||||||
|
assert len(data) == 1
|
||||||
|
|
||||||
|
response = api_client.post(f"/api/v1/notifications/{event.id}/dismiss", {})
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json() == {}
|
||||||
|
|
||||||
|
data = api_client.get("/api/v1/notifications").json()
|
||||||
|
assert len(data) == 0
|
||||||
|
|
||||||
|
TimelineEvent.objects.filter(identity=identity).delete()
|
||||||
|
|
Loading…
Reference in a new issue