diff --git a/apiserver/plane/app/serializers/__init__.py b/apiserver/plane/app/serializers/__init__.py index 796e68b4070..3568e2b3828 100644 --- a/apiserver/plane/app/serializers/__init__.py +++ b/apiserver/plane/app/serializers/__init__.py @@ -22,6 +22,7 @@ WorkspaceUserLinkSerializer, WorkspaceRecentVisitSerializer, WorkspaceHomePreferenceSerializer, + StickySerializer, ) from .project import ( ProjectSerializer, diff --git a/apiserver/plane/app/serializers/workspace.py b/apiserver/plane/app/serializers/workspace.py index c16fa0f8bf3..862637ff59a 100644 --- a/apiserver/plane/app/serializers/workspace.py +++ b/apiserver/plane/app/serializers/workspace.py @@ -21,6 +21,7 @@ Project, ProjectMember, WorkspaceHomePreference, + Sticky, ) from plane.utils.constants import RESTRICTED_WORKSPACE_SLUGS @@ -150,7 +151,17 @@ class IssueRecentVisitSerializer(serializers.ModelSerializer): class Meta: model = Issue - fields = ["id", "name", "state", "priority", "assignees", "type", "sequence_id", "project_id", "project_identifier", ] + fields = [ + "id", + "name", + "state", + "priority", + "assignees", + "type", + "sequence_id", + "project_id", + "project_identifier", + ] def get_project_identifier(self, obj): project = obj.project @@ -166,9 +177,12 @@ class Meta: fields = ["id", "name", "logo_props", "project_members", "identifier"] def get_project_members(self, obj): - members = ProjectMember.objects.filter(project_id=obj.id).values_list("member", flat=True) + members = ProjectMember.objects.filter(project_id=obj.id).values_list( + "member", flat=True + ) return members - + + class PageRecentVisitSerializer(serializers.ModelSerializer): project_id = serializers.SerializerMethodField() project_identifier = serializers.SerializerMethodField() @@ -235,3 +249,11 @@ class Meta: model = WorkspaceHomePreference fields = ["key", "is_enabled", "sort_order"] read_only_fields = ["worspace", "created_by", "update_by"] + + +class StickySerializer(BaseSerializer): + class Meta: + model = Sticky + fields = "__all__" + read_only_fields = ["workspace", "owner"] + extra_kwargs = {"name": {"required": False}} diff --git a/apiserver/plane/app/urls/workspace.py b/apiserver/plane/app/urls/workspace.py index 2bb3d5b1d12..cb0a026d19a 100644 --- a/apiserver/plane/app/urls/workspace.py +++ b/apiserver/plane/app/urls/workspace.py @@ -30,6 +30,7 @@ QuickLinkViewSet, UserRecentVisitViewSet, WorkspacePreferenceViewSet, + WorkspaceStickyViewSet, ) @@ -245,4 +246,16 @@ UserRecentVisitViewSet.as_view({"get": "list"}), name="workspace-recent-visits", ), + path( + "workspaces//stickies/", + WorkspaceStickyViewSet.as_view({"get": "list", "post": "create"}), + name="workspace-sticky", + ), + path( + "workspaces//stickies//", + WorkspaceStickyViewSet.as_view( + {"get": "retrieve", "patch": "partial_update", "delete": "destroy"} + ), + name="workspace-sticky", + ), ] diff --git a/apiserver/plane/app/views/__init__.py b/apiserver/plane/app/views/__init__.py index 53c9c0a7266..01dba11a127 100644 --- a/apiserver/plane/app/views/__init__.py +++ b/apiserver/plane/app/views/__init__.py @@ -75,6 +75,7 @@ from .workspace.module import WorkspaceModulesEndpoint from .workspace.cycle import WorkspaceCyclesEndpoint from .workspace.quick_link import QuickLinkViewSet +from .workspace.sticky import WorkspaceStickyViewSet from .state.base import StateViewSet from .view.base import ( diff --git a/apiserver/plane/app/views/workspace/sticky.py b/apiserver/plane/app/views/workspace/sticky.py new file mode 100644 index 00000000000..c00a2cd594b --- /dev/null +++ b/apiserver/plane/app/views/workspace/sticky.py @@ -0,0 +1,54 @@ +# Third party imports +from rest_framework.response import Response +from rest_framework import status + +# Module imports +from plane.app.views.base import BaseViewSet +from plane.app.permissions import WorkSpaceBasePermission, ROLE, allow_permission +from plane.db.models import Sticky, Workspace +from plane.app.serializers import StickySerializer + + +class WorkspaceStickyViewSet(BaseViewSet): + serializer_class = StickySerializer + model = Sticky + permission_classes = [WorkSpaceBasePermission] + + def get_queryset(self): + return self.filter_queryset( + super() + .get_queryset() + .filter(workspace__slug=self.kwargs.get("slug")) + .filter(owner_id=self.request.user.id) + .select_related("workspace", "owner") + .distinct() + ) + + @allow_permission( + allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE" + ) + def create(self, request, slug): + workspace = Workspace.objects.get(slug=slug) + serializer = StickySerializer(data=request.data) + if serializer.is_valid(): + serializer.save(workspace_id=workspace.id, owner_id=request.user.id) + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + @allow_permission( + allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE" + ) + def list(self, request, slug): + return self.paginate( + request=request, + queryset=(self.get_queryset()), + on_results=lambda stickies: StickySerializer(stickies, many=True).data, + ) + + @allow_permission(allowed_roles=[], creator=True, model=Sticky, level="WORKSPACE") + def partial_update(self, request, *args, **kwargs): + return super().partial_update(request, *args, **kwargs) + + @allow_permission(allowed_roles=[], creator=True, model=Sticky, level="WORKSPACE") + def destroy(self, request, *args, **kwargs): + return super().destroy(request, *args, **kwargs)