From 97ffdc81242108c444fa04a9db5aa83ffb31bcf6 Mon Sep 17 00:00:00 2001 From: pablohashescobar <118773738+pablohashescobar@users.noreply.github.com> Date: Tue, 14 Feb 2023 01:12:32 +0530 Subject: [PATCH] feat: default state for project (#264) --- apiserver/plane/api/views/project.py | 21 +++------------------ apiserver/plane/api/views/state.py | 21 ++++++++++++++++++++- apiserver/plane/db/models/issue.py | 11 ++++++++--- apiserver/plane/db/models/state.py | 1 + 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/apiserver/plane/api/views/project.py b/apiserver/plane/api/views/project.py index 2ec6faf1e..e24477ecd 100644 --- a/apiserver/plane/api/views/project.py +++ b/apiserver/plane/api/views/project.py @@ -75,7 +75,6 @@ class ProjectViewSet(BaseViewSet): def create(self, request, slug): try: - workspace = Workspace.objects.get(slug=slug) serializer = ProjectSerializer( @@ -96,6 +95,7 @@ class ProjectViewSet(BaseViewSet): "color": "#5e6ad2", "sequence": 15000, "group": "backlog", + "default": True, }, { "name": "Todo", @@ -132,6 +132,7 @@ class ProjectViewSet(BaseViewSet): sequence=state["sequence"], workspace=serializer.instance.workspace, group=state["group"], + default=state.get("default", False), ) for state in states ] @@ -188,7 +189,7 @@ class ProjectViewSet(BaseViewSet): {"name": "The project name is already taken"}, status=status.HTTP_410_GONE, ) - except (Project.DoesNotExist or Workspace.DoesNotExist) as e: + except Project.DoesNotExist or Workspace.DoesNotExist as e: return Response( {"error": "Project does not exist"}, status=status.HTTP_404_NOT_FOUND ) @@ -206,14 +207,12 @@ class ProjectViewSet(BaseViewSet): class InviteProjectEndpoint(BaseAPIView): - permission_classes = [ ProjectBasePermission, ] def post(self, request, slug, project_id): try: - email = request.data.get("email", False) role = request.data.get("role", False) @@ -287,7 +286,6 @@ class InviteProjectEndpoint(BaseAPIView): class UserProjectInvitationsViewset(BaseViewSet): - serializer_class = ProjectMemberInviteSerializer model = ProjectMemberInvite @@ -301,7 +299,6 @@ class UserProjectInvitationsViewset(BaseViewSet): def create(self, request): try: - invitations = request.data.get("invitations") project_invitations = ProjectMemberInvite.objects.filter( pk__in=invitations, accepted=True @@ -331,7 +328,6 @@ class UserProjectInvitationsViewset(BaseViewSet): class ProjectMemberViewSet(BaseViewSet): - serializer_class = ProjectMemberSerializer model = ProjectMember permission_classes = [ @@ -356,14 +352,12 @@ class ProjectMemberViewSet(BaseViewSet): class AddMemberToProjectEndpoint(BaseAPIView): - permission_classes = [ ProjectBasePermission, ] def post(self, request, slug, project_id): try: - member_id = request.data.get("member_id", False) role = request.data.get("role", False) @@ -412,13 +406,11 @@ class AddMemberToProjectEndpoint(BaseAPIView): class AddTeamToProjectEndpoint(BaseAPIView): - permission_classes = [ ProjectBasePermission, ] def post(self, request, slug, project_id): - try: team_members = TeamMember.objects.filter( workspace__slug=slug, team__in=request.data.get("teams", []) @@ -467,7 +459,6 @@ class AddTeamToProjectEndpoint(BaseAPIView): class ProjectMemberInvitationsViewset(BaseViewSet): - serializer_class = ProjectMemberInviteSerializer model = ProjectMemberInvite @@ -489,7 +480,6 @@ class ProjectMemberInvitationsViewset(BaseViewSet): class ProjectMemberInviteDetailViewSet(BaseViewSet): - serializer_class = ProjectMemberInviteSerializer model = ProjectMemberInvite @@ -509,14 +499,12 @@ class ProjectMemberInviteDetailViewSet(BaseViewSet): class ProjectIdentifierEndpoint(BaseAPIView): - permission_classes = [ ProjectBasePermission, ] def get(self, request, slug): try: - name = request.GET.get("name", "").strip().upper() if name == "": @@ -541,7 +529,6 @@ class ProjectIdentifierEndpoint(BaseAPIView): def delete(self, request, slug): try: - name = request.data.get("name", "").strip().upper() if name == "": @@ -616,7 +603,6 @@ class ProjectJoinEndpoint(BaseAPIView): class ProjectUserViewsEndpoint(BaseAPIView): def post(self, request, slug, project_id): try: - project = Project.objects.get(pk=project_id, workspace__slug=slug) project_member = ProjectMember.objects.filter( @@ -655,7 +641,6 @@ class ProjectUserViewsEndpoint(BaseAPIView): class ProjectMemberUserEndpoint(BaseAPIView): def get(self, request, slug, project_id): try: - project_member = ProjectMember.objects.get( project_id=project_id, workspace__slug=slug, member=request.user ) diff --git a/apiserver/plane/api/views/state.py b/apiserver/plane/api/views/state.py index 8054b15dd..21ca6c714 100644 --- a/apiserver/plane/api/views/state.py +++ b/apiserver/plane/api/views/state.py @@ -1,3 +1,7 @@ +# Third party imports +from rest_framework import status +from rest_framework.response import Response + # Module imports from . import BaseViewSet from plane.api.serializers import StateSerializer @@ -6,7 +10,6 @@ from plane.db.models import State class StateViewSet(BaseViewSet): - serializer_class = StateSerializer model = State permission_classes = [ @@ -27,3 +30,19 @@ class StateViewSet(BaseViewSet): .select_related("workspace") .distinct() ) + + def destroy(self, request, slug, project_id, pk): + try: + state = State.objects.get( + pk=pk, project_id=project_id, workspace__slug=slug + ) + + if state.default: + return Response( + {"error": "Default state cannot be deleted"}, status=False + ) + + state.delete() + return Response(status=status.HTTP_204_NO_CONTENT) + except State.DoesNotExist: + return Response({"error": "State does not exists"}, status=status.HTTP_404) diff --git a/apiserver/plane/db/models/issue.py b/apiserver/plane/db/models/issue.py index a870eb93f..82e8343bb 100644 --- a/apiserver/plane/db/models/issue.py +++ b/apiserver/plane/db/models/issue.py @@ -83,9 +83,14 @@ class Issue(ProjectBaseModel): try: from plane.db.models import State - self.state, created = State.objects.get_or_create( - project=self.project, name="Backlog" - ) + default_state = State.objects.filter( + project=self.project, default=True + ).first() + # if there is no default state assign any random state + if default_state is None: + self.state = State.objects.filter(project=self.project).first() + else: + self.state = default_state except ImportError: pass else: diff --git a/apiserver/plane/db/models/state.py b/apiserver/plane/db/models/state.py index 2c6287918..d66ecfa72 100644 --- a/apiserver/plane/db/models/state.py +++ b/apiserver/plane/db/models/state.py @@ -23,6 +23,7 @@ class State(ProjectBaseModel): default="backlog", max_length=20, ) + default = models.BooleanField(default=False) def __str__(self): """Return name of the state"""