Skip to content

[WEB-2383] feat: Inbox Settings v2 #6644

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 12 commits into
base: preview
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion apiserver/plane/app/serializers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,11 @@

from .analytic import AnalyticViewSerializer

from .notification import NotificationSerializer, UserNotificationPreferenceSerializer
from .notification import (
NotificationSerializer,
UserNotificationPreferenceSerializer,
WorkspaceUserNotificationPreferenceSerializer
)

from .exporter import ExporterHistorySerializer

Expand Down
7 changes: 6 additions & 1 deletion apiserver/plane/app/serializers/notification.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Module imports
from .base import BaseSerializer
from .user import UserLiteSerializer
from plane.db.models import Notification, UserNotificationPreference
from plane.db.models import Notification, UserNotificationPreference, WorkspaceUserNotificationPreference

# Third Party imports
from rest_framework import serializers
Expand All @@ -22,3 +22,8 @@ class UserNotificationPreferenceSerializer(BaseSerializer):
class Meta:
model = UserNotificationPreference
fields = "__all__"

class WorkspaceUserNotificationPreferenceSerializer(BaseSerializer):
class Meta:
model = WorkspaceUserNotificationPreference
fields = "__all__"
11 changes: 11 additions & 0 deletions apiserver/plane/app/urls/notification.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
UnreadNotificationEndpoint,
MarkAllReadNotificationViewSet,
UserNotificationPreferenceEndpoint,
WorkspaceUserNotificationPreferenceEndpoint,
)


Expand Down Expand Up @@ -47,4 +48,14 @@
UserNotificationPreferenceEndpoint.as_view(),
name="user-notification-preferences",
),
path(
"workspaces/<str:slug>/user-notification-preferences/<str:transport>/",
WorkspaceUserNotificationPreferenceEndpoint.as_view(),
name="workspace-user-notification-preference",
),
path(
"workspaces/<str:slug>/user-notification-preferences/",
WorkspaceUserNotificationPreferenceEndpoint.as_view(),
name="workspace-user-notification-preference",
),
]
1 change: 1 addition & 0 deletions apiserver/plane/app/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@
NotificationViewSet,
UnreadNotificationEndpoint,
UserNotificationPreferenceEndpoint,
WorkspaceUserNotificationPreferenceEndpoint,
)

from .exporter.base import ExportIssuesEndpoint
Expand Down
82 changes: 82 additions & 0 deletions apiserver/plane/app/views/notification/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from plane.app.serializers import (
NotificationSerializer,
UserNotificationPreferenceSerializer,
WorkspaceUserNotificationPreferenceSerializer
)
from plane.db.models import (
Issue,
Expand All @@ -17,6 +18,9 @@
Notification,
UserNotificationPreference,
WorkspaceMember,
Workspace,
WorkspaceUserNotificationPreference,
NotificationTransportChoices
)
from plane.utils.paginator import BasePaginator
from plane.app.permissions import allow_permission, ROLE
Expand Down Expand Up @@ -360,3 +364,81 @@ def patch(self, request):
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)



class WorkspaceUserNotificationPreferenceEndpoint(BaseAPIView):
model = WorkspaceUserNotificationPreference
serializer_class = WorkspaceUserNotificationPreferenceSerializer

@allow_permission(
allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE"
)
def get(self, request, slug):
workspace = Workspace.objects.get(slug=slug)
get_notification_preferences = (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 377 to 395 can be clubbed into the following.

existing_transports = UserNotificationPreference.objects.filter(
    workspace=workspace, user=request.user
).values_list('transport', flat=True)
create_transports = [
    transport
    for transport, _ in NotificationTransportChoices.choices
    if transport not in existing_transports
]

This will be concise and improve readability of the code.

WorkspaceUserNotificationPreference.objects.filter(
workspace=workspace, user=request.user
)
)

create_transports = []

transports = [
transport
for transport, _ in NotificationTransportChoices.choices
]

for transport in transports:
if transport not in get_notification_preferences.values_list(
"transport", flat=True
):
create_transports.append(transport)


notification_preferences = (
WorkspaceUserNotificationPreference.objects.bulk_create(
[
WorkspaceUserNotificationPreference(
workspace=workspace,
user=request.user,
transport=transport,
)
for transport in create_transports
]
)
)

notification_preferences = WorkspaceUserNotificationPreference.objects.filter(
workspace=workspace, user=request.user
)

return Response(
WorkspaceUserNotificationPreferenceSerializer(
notification_preferences, many=True
).data,
status=status.HTTP_200_OK,
)

@allow_permission(
allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE"
)
def patch(self, request, slug, transport):
notification_preference = WorkspaceUserNotificationPreference.objects.filter(
transport=transport, workspace__slug=slug, user=request.user
).first()

if notification_preference:
serializer = WorkspaceUserNotificationPreferenceSerializer(
notification_preference, data=request.data, partial=True
)

if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

return Response(
{"detail": "Workspace notification preference not found"},
status=status.HTTP_404_NOT_FOUND,
)
33 changes: 32 additions & 1 deletion apiserver/plane/app/views/workspace/home.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from ..base import BaseAPIView
from plane.db.models.workspace import WorkspaceHomePreference
from plane.app.permissions import allow_permission, ROLE
from plane.db.models import Workspace
from plane.db.models import Workspace, WorkspaceUserNotificationPreference, NotificationTransportChoices
from plane.app.serializers.workspace import WorkspaceHomePreferenceSerializer

# Third party imports
Expand Down Expand Up @@ -59,6 +59,37 @@ def get(self, request, slug):
user=request.user, workspace_id=workspace.id
)

# Notification preference get or create
workspace = Workspace.objects.get(slug=slug)
get_notification_preferences = (
Comment on lines +62 to +64
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove redundant workspace fetch.

The workspace object is already fetched on line 21, so there's no need to fetch it again here. This redundant fetch can be removed to improve performance.

  # Notification preference get or create
- workspace = Workspace.objects.get(slug=slug)
  get_notification_preferences = (
      WorkspaceUserNotificationPreference.objects.filter(
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Notification preference get or create
workspace = Workspace.objects.get(slug=slug)
get_notification_preferences = (
# Notification preference get or create
get_notification_preferences = (
WorkspaceUserNotificationPreference.objects.filter(

WorkspaceUserNotificationPreference.objects.filter(
workspace=workspace, user=request.user
)
)

create_transports = []

transports = [
transport
for transport, _ in NotificationTransportChoices.choices
]


for transport in transports:
if transport not in get_notification_preferences.values_list(
"transport", flat=True
):
create_transports.append(transport)

_ = WorkspaceUserNotificationPreference.objects.bulk_create(
[
WorkspaceUserNotificationPreference(
workspace=workspace, user=request.user, transport=transport
)
for transport in create_transports
]
)

return Response(
preference.values("key", "is_enabled", "config", "sort_order"),
status=status.HTTP_200_OK,
Expand Down
Loading