forked from github/plane
chore: notifications (#1515)
* chore: add triggered by details for notifications * dev: update issue activity json to include extra fields * dev: triggered_by details * dev: add bot filtering * dev: unread notification count endpoint * dev: update endpoint to send count for all notification types
This commit is contained in:
parent
e0181342c0
commit
b69c4b6b30
@ -1,9 +1,12 @@
|
|||||||
# Module imports
|
# Module imports
|
||||||
from .base import BaseSerializer
|
from .base import BaseSerializer
|
||||||
|
from .user import UserLiteSerializer
|
||||||
from plane.db.models import Notification
|
from plane.db.models import Notification
|
||||||
|
|
||||||
class NotificationSerializer(BaseSerializer):
|
class NotificationSerializer(BaseSerializer):
|
||||||
|
|
||||||
|
triggered_by_details = UserLiteSerializer(read_only=True, source="triggered_by")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Notification
|
model = Notification
|
||||||
fields = "__all__"
|
fields = "__all__"
|
||||||
|
@ -153,6 +153,7 @@ from plane.api.views import (
|
|||||||
## End Analytics
|
## End Analytics
|
||||||
# Notification
|
# Notification
|
||||||
NotificationViewSet,
|
NotificationViewSet,
|
||||||
|
UnreadNotificationEndpoint,
|
||||||
## End Notification
|
## End Notification
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1382,5 +1383,10 @@ urlpatterns = [
|
|||||||
),
|
),
|
||||||
name="notifications",
|
name="notifications",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"workspaces/<str:slug>/users/notifications/unread/",
|
||||||
|
UnreadNotificationEndpoint.as_view(),
|
||||||
|
name="unread-notifications",
|
||||||
|
),
|
||||||
## End Notification
|
## End Notification
|
||||||
]
|
]
|
||||||
|
@ -145,4 +145,4 @@ from .analytic import (
|
|||||||
DefaultAnalyticsEndpoint,
|
DefaultAnalyticsEndpoint,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .notification import NotificationViewSet
|
from .notification import NotificationViewSet, UnreadNotificationEndpoint
|
@ -8,7 +8,7 @@ from rest_framework.response import Response
|
|||||||
from sentry_sdk import capture_exception
|
from sentry_sdk import capture_exception
|
||||||
|
|
||||||
# Module imports
|
# Module imports
|
||||||
from .base import BaseViewSet
|
from .base import BaseViewSet, BaseAPIView
|
||||||
from plane.db.models import Notification, IssueAssignee, IssueSubscriber, Issue
|
from plane.db.models import Notification, IssueAssignee, IssueSubscriber, Issue
|
||||||
from plane.api.serializers import NotificationSerializer
|
from plane.api.serializers import NotificationSerializer
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ class NotificationViewSet(BaseViewSet):
|
|||||||
workspace__slug=self.kwargs.get("slug"),
|
workspace__slug=self.kwargs.get("slug"),
|
||||||
receiver_id=self.request.user.id,
|
receiver_id=self.request.user.id,
|
||||||
)
|
)
|
||||||
.select_related("workspace")
|
.select_related("workspace", "project," "triggered_by", "receiver")
|
||||||
)
|
)
|
||||||
|
|
||||||
def list(self, request, slug):
|
def list(self, request, slug):
|
||||||
@ -123,7 +123,7 @@ class NotificationViewSet(BaseViewSet):
|
|||||||
{"error": "Something went wrong please try again later"},
|
{"error": "Something went wrong please try again later"},
|
||||||
status=status.HTTP_400_BAD_REQUEST,
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
)
|
)
|
||||||
|
|
||||||
def mark_read(self, request, slug, pk):
|
def mark_read(self, request, slug, pk):
|
||||||
try:
|
try:
|
||||||
notification = Notification.objects.get(
|
notification = Notification.objects.get(
|
||||||
@ -166,7 +166,6 @@ class NotificationViewSet(BaseViewSet):
|
|||||||
status=status.HTTP_400_BAD_REQUEST,
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def archive(self, request, slug, pk):
|
def archive(self, request, slug, pk):
|
||||||
try:
|
try:
|
||||||
notification = Notification.objects.get(
|
notification = Notification.objects.get(
|
||||||
@ -209,3 +208,48 @@ class NotificationViewSet(BaseViewSet):
|
|||||||
status=status.HTTP_400_BAD_REQUEST,
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class UnreadNotificationEndpoint(BaseAPIView):
|
||||||
|
def get(self, request, slug):
|
||||||
|
try:
|
||||||
|
# Watching Issues Count
|
||||||
|
watching_notification_count = Notification.objects.filter(
|
||||||
|
workspace__slug=slug,
|
||||||
|
receiver_id=request.user.id,
|
||||||
|
entity_identifier__in=IssueSubscriber.objects.filter(
|
||||||
|
workspace__slug=slug, subscriber_id=request.user.id
|
||||||
|
).values_list("issue_id", flat=True),
|
||||||
|
).count()
|
||||||
|
|
||||||
|
# My Issues Count
|
||||||
|
my_issues_count = Notification.objects.filter(
|
||||||
|
workspace__slug=slug,
|
||||||
|
receiver_id=request.user.id,
|
||||||
|
entity_identifier__in=IssueAssignee.objects.filter(
|
||||||
|
workspace__slug=slug, assignee_id=request.user.id
|
||||||
|
).values_list("issue_id", flat=True),
|
||||||
|
).count()
|
||||||
|
|
||||||
|
# Created Issues Count
|
||||||
|
created_issues_count = Notification.objects.filter(
|
||||||
|
workspace__slug=slug,
|
||||||
|
receiver_id=request.user.id,
|
||||||
|
entity_identifier__in=Issue.objects.filter(
|
||||||
|
workspace__slug=slug, created_by=request.user
|
||||||
|
).values_list("pk", flat=True),
|
||||||
|
).count()
|
||||||
|
|
||||||
|
return Response(
|
||||||
|
{
|
||||||
|
"watching_notifications": watching_notification_count,
|
||||||
|
"my_issues": my_issues_count,
|
||||||
|
"created_issues": created_issues_count,
|
||||||
|
},
|
||||||
|
status=status.HTTP_200_OK,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
capture_exception(e)
|
||||||
|
return Response(
|
||||||
|
{"error": "Something went wrong please try again later"},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
|
)
|
||||||
|
@ -1109,7 +1109,8 @@ def issue_activity(
|
|||||||
|
|
||||||
issue_subscribers = issue_subscribers + issue_assignees
|
issue_subscribers = issue_subscribers + issue_assignees
|
||||||
|
|
||||||
if issue.created_by_id:
|
# Add bot filtering
|
||||||
|
if issue.created_by_id is not None and not issue.created_by.is_bot:
|
||||||
issue_subscribers = issue_subscribers + [issue.created_by_id]
|
issue_subscribers = issue_subscribers + [issue.created_by_id]
|
||||||
|
|
||||||
issue = Issue.objects.get(project=project, pk=issue_id)
|
issue = Issue.objects.get(project=project, pk=issue_id)
|
||||||
@ -1134,7 +1135,17 @@ def issue_activity(
|
|||||||
"state_name": issue.state.name,
|
"state_name": issue.state.name,
|
||||||
"state_group": issue.state.group,
|
"state_group": issue.state.group,
|
||||||
},
|
},
|
||||||
"issue_activity": str(issue_activity.id),
|
"issue_activity": {
|
||||||
|
"id": str(issue_activity.id),
|
||||||
|
"verb": str(issue_activity.verb),
|
||||||
|
"field": str(issue_activity.field),
|
||||||
|
"actor": str(issue_activity.actor_id),
|
||||||
|
"new_value": str(issue_activity.new_value),
|
||||||
|
"old_value": str(issue_activity.old_value),
|
||||||
|
"issue_comment": str(
|
||||||
|
issue_activity.issue_comment.comment_stripped if issue_activity.issue_comment is not None else ""
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user