diff --git a/apiserver/plane/app/serializers/workspace.py b/apiserver/plane/app/serializers/workspace.py index 5d8e5a4d5e3..68e12608517 100644 --- a/apiserver/plane/app/serializers/workspace.py +++ b/apiserver/plane/app/serializers/workspace.py @@ -22,6 +22,7 @@ ProjectMember, WorkspaceHomePreference, Sticky, + WorkspaceUserPreference, ) from plane.utils.constants import RESTRICTED_WORKSPACE_SLUGS @@ -258,3 +259,10 @@ class Meta: fields = "__all__" read_only_fields = ["workspace", "owner"] extra_kwargs = {"name": {"required": False}} + + +class WorkspaceUserPreferenceSerializer(BaseSerializer): + class Meta: + model = WorkspaceUserPreference + fields = ["key", "is_pinned", "sort_order"] + read_only_fields = ["workspace", "created_by", "updated_by"] diff --git a/apiserver/plane/app/urls/workspace.py b/apiserver/plane/app/urls/workspace.py index 90fdf64c272..ea81d1ef730 100644 --- a/apiserver/plane/app/urls/workspace.py +++ b/apiserver/plane/app/urls/workspace.py @@ -31,6 +31,7 @@ UserRecentVisitViewSet, WorkspaceHomePreferenceViewSet, WorkspaceStickyViewSet, + WorkspaceUserPreferenceViewSet, ) @@ -258,4 +259,15 @@ ), name="workspace-sticky", ), + # User Preference + path( + "workspaces//user-preferences/", + WorkspaceUserPreferenceViewSet.as_view(), + name="workspace-user-preference", + ), + path( + "workspaces//user-preferences//", + WorkspaceUserPreferenceViewSet.as_view(), + name="workspace-user-preference", + ), ] diff --git a/apiserver/plane/app/views/__init__.py b/apiserver/plane/app/views/__init__.py index 6c49ca9a848..cb10c879f4e 100644 --- a/apiserver/plane/app/views/__init__.py +++ b/apiserver/plane/app/views/__init__.py @@ -48,6 +48,7 @@ WorkspaceFavoriteGroupEndpoint, ) from .workspace.recent_visit import UserRecentVisitViewSet +from .workspace.user_preference import WorkspaceUserPreferenceViewSet from .workspace.member import ( WorkSpaceMemberViewSet, diff --git a/apiserver/plane/app/views/workspace/user_preference.py b/apiserver/plane/app/views/workspace/user_preference.py new file mode 100644 index 00000000000..4c245b8f8d4 --- /dev/null +++ b/apiserver/plane/app/views/workspace/user_preference.py @@ -0,0 +1,74 @@ +# Module imports +from ..base import BaseAPIView +from plane.db.models.workspace import WorkspaceUserPreference +from plane.app.serializers.workspace import WorkspaceUserPreferenceSerializer +from plane.app.permissions import allow_permission, ROLE +from plane.db.models import Workspace + + +# Third party imports +from rest_framework.response import Response +from rest_framework import status + + +class WorkspaceUserPreferenceViewSet(BaseAPIView): + model = WorkspaceUserPreference + + def get_serializer_class(self): + return WorkspaceUserPreferenceSerializer + + @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE") + def get(self, request, slug): + workspace = Workspace.objects.get(slug=slug) + + get_preference = WorkspaceUserPreference.objects.filter( + user=request.user, workspace_id=workspace.id + ) + + create_preference_keys = [] + + keys = [key for key, _ in WorkspaceUserPreference.UserPreferenceKeys.choices] + + for preference in keys: + if preference not in get_preference.values_list("key", flat=True): + create_preference_keys.append(preference) + + preference = WorkspaceUserPreference.objects.bulk_create( + [ + WorkspaceUserPreference( + key=key, user=request.user, workspace=workspace + ) + for key in create_preference_keys + ], + batch_size=10, + ignore_conflicts=True, + ) + + preference = WorkspaceUserPreference.objects.filter( + user=request.user, workspace_id=workspace.id + ) + + return Response( + preference.values("key", "is_pinned", "sort_order"), + status=status.HTTP_200_OK, + ) + + @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE") + def patch(self, request, slug, key): + preference = WorkspaceUserPreference.objects.filter( + key=key, workspace__slug=slug, user=request.user + ).first() + + if preference: + serializer = WorkspaceUserPreferenceSerializer( + 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": "Preference not found"}, status=status.HTTP_404_NOT_FOUND + ) diff --git a/apiserver/plane/db/models/__init__.py b/apiserver/plane/db/models/__init__.py index 436ed5148b3..8e20a8d6714 100644 --- a/apiserver/plane/db/models/__init__.py +++ b/apiserver/plane/db/models/__init__.py @@ -69,7 +69,8 @@ WorkspaceTheme, WorkspaceUserProperties, WorkspaceUserLink, - WorkspaceHomePreference + WorkspaceHomePreference, + WorkspaceUserPreference, ) from .favorite import UserFavorite diff --git a/apiserver/plane/db/models/workspace.py b/apiserver/plane/db/models/workspace.py index ddeb50fcf51..cb80fa056bb 100644 --- a/apiserver/plane/db/models/workspace.py +++ b/apiserver/plane/db/models/workspace.py @@ -388,7 +388,6 @@ def __str__(self): return f"{self.workspace.name} {self.user.email} {self.key}" - class WorkspaceUserPreference(BaseModel): """Preference for the workspace for a user""" @@ -396,6 +395,8 @@ class UserPreferenceKeys(models.TextChoices): CYCLES = "cycles", "Cycles" VIEWS = "views", "Views" ANALYTICS = "analytics", "Analytics" + TEAMS = "teams", "Teams" + INITIATIVES = "initiatives", "Initiatives" PROJECTS = "projects", "Projects" workspace = models.ForeignKey(