From 5807632ee45a807dedc53d5e3afa78ed6805440d Mon Sep 17 00:00:00 2001 From: pablohashescobar Date: Fri, 16 Dec 2022 11:40:24 +0530 Subject: [PATCH 1/6] feat: add field my_issues_prop to store my_issues property --- apiserver/plane/api/views/people.py | 1 - apiserver/plane/db/models/user.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/apiserver/plane/api/views/people.py b/apiserver/plane/api/views/people.py index 1612e0bc7..81118484c 100644 --- a/apiserver/plane/api/views/people.py +++ b/apiserver/plane/api/views/people.py @@ -52,7 +52,6 @@ class PeopleEndpoint(BaseAPIView): class UserEndpoint(BaseViewSet): serializer_class = UserSerializer model = User - serializers = {} def get_object(self): return self.request.user diff --git a/apiserver/plane/db/models/user.py b/apiserver/plane/db/models/user.py index 7efa4be49..1b08c8d69 100644 --- a/apiserver/plane/db/models/user.py +++ b/apiserver/plane/db/models/user.py @@ -66,6 +66,7 @@ class User(AbstractBaseUser, PermissionsMixin): last_login_uagent = models.TextField(blank=True) token_updated_at = models.DateTimeField(null=True) last_workspace_id = models.UUIDField(null=True) + my_issues_prop = models.JSONField(null=True) USERNAME_FIELD = "email" From 35938cc33ac653c8dcd2841fbd550db99b762cd1 Mon Sep 17 00:00:00 2001 From: pablohashescobar Date: Mon, 19 Dec 2022 23:43:05 +0530 Subject: [PATCH 2/6] refactor: bulk assign issues to module --- apiserver/plane/api/views/module.py | 45 +++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/apiserver/plane/api/views/module.py b/apiserver/plane/api/views/module.py index 4ff914890..a8e4136b6 100644 --- a/apiserver/plane/api/views/module.py +++ b/apiserver/plane/api/views/module.py @@ -5,6 +5,7 @@ from django.db.models import Prefetch # Third party imports from rest_framework.response import Response from rest_framework import status +from sentry_sdk import capture_exception # Module imports from . import BaseViewSet @@ -71,6 +72,13 @@ class ModuleViewSet(BaseViewSet): {"name": "The module name is already taken"}, status=status.HTTP_410_GONE, ) + except Exception as e: + capture_exception(e) + return Response( + {"error": "Something went wrong please try again later"}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) + class ModuleIssueViewSet(BaseViewSet): @@ -107,3 +115,40 @@ class ModuleIssueViewSet(BaseViewSet): .select_related("issue") .distinct() ) + + def create(self, request, slug, project_id, module_id): + try: + issues = request.data.get("issues", []) + if not len(issues): + return Response( + {"error": "Issues are required"}, status=status.HTTP_400_BAD_REQUEST + ) + module = Module.objects.get( + workspace__slug=slug, project_id=project_id, pk=module_id + ) + ModuleIssue.objects.bulk_create( + [ + ModuleIssue( + module=module, + issue_id=issue, + project_id=project_id, + workspace=module.workspace, + created_by=request.user, + updated_by=request.user, + ) + for issue in issues + ], + batch_size=10, + ignore_conflicts=True, + ) + return Response({"message": "Success"}, status=status.HTTP_200_OK) + except Module.DoesNotExist: + return Response( + {"error": "Module Does not exists"}, status=status.HTTP_400_BAD_REQUEST + ) + except Exception as e: + capture_exception(e) + return Response( + {"error": "Something went wrong please try again later"}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) From 0b94172ef7f37c963b6eda3a9d9d2b4ab82f88a2 Mon Sep 17 00:00:00 2001 From: pablohashescobar Date: Tue, 20 Dec 2022 00:31:43 +0530 Subject: [PATCH 3/6] refactor: remove bulk assign endpoint, merge it into a single create endpoint and update the create endpoint to maintain db integrity --- apiserver/plane/api/urls.py | 6 ------ apiserver/plane/api/views/__init__.py | 2 +- apiserver/plane/api/views/cycle.py | 30 +++++++++++++++++---------- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/apiserver/plane/api/urls.py b/apiserver/plane/api/urls.py index d4a9faa6f..b04f9dc3a 100644 --- a/apiserver/plane/api/urls.py +++ b/apiserver/plane/api/urls.py @@ -52,7 +52,6 @@ from plane.api.views import ( AddMemberToProjectEndpoint, ProjectJoinEndpoint, BulkDeleteIssuesEndpoint, - BulkAssignIssuesToCycleEndpoint, ProjectUserViewsEndpoint, ModuleViewSet, ModuleIssueViewSet, @@ -444,11 +443,6 @@ urlpatterns = [ ), name="project-cycle", ), - path( - "workspaces//projects//cycles//bulk-assign-issues/", - BulkAssignIssuesToCycleEndpoint.as_view(), - name="bulk-assign-cycle-issues", - ), ## End Cycles # Issue path( diff --git a/apiserver/plane/api/views/__init__.py b/apiserver/plane/api/views/__init__.py index 5706b1994..b641d6e2c 100644 --- a/apiserver/plane/api/views/__init__.py +++ b/apiserver/plane/api/views/__init__.py @@ -38,7 +38,7 @@ from .workspace import ( from .state import StateViewSet from .shortcut import ShortCutViewSet from .view import ViewViewSet -from .cycle import CycleViewSet, CycleIssueViewSet, BulkAssignIssuesToCycleEndpoint +from .cycle import CycleViewSet, CycleIssueViewSet from .asset import FileAssetEndpoint from .issue import ( IssueViewSet, diff --git a/apiserver/plane/api/views/cycle.py b/apiserver/plane/api/views/cycle.py index 8b74f2a10..873f9518c 100644 --- a/apiserver/plane/api/views/cycle.py +++ b/apiserver/plane/api/views/cycle.py @@ -1,9 +1,10 @@ # Third party imports from rest_framework.response import Response from rest_framework import status +from sentry_sdk import capture_exception # Module imports -from . import BaseViewSet, BaseAPIView +from . import BaseViewSet from plane.api.serializers import CycleSerializer, CycleIssueSerializer from plane.api.permissions import ProjectEntityPermission from plane.db.models import Cycle, CycleIssue, Issue @@ -66,26 +67,27 @@ class CycleIssueViewSet(BaseViewSet): .distinct() ) - -class BulkAssignIssuesToCycleEndpoint(BaseAPIView): - - permission_classes = [ - ProjectEntityPermission, - ] - - def post(self, request, slug, project_id, cycle_id): + def create(self, request, slug, project_id, cycle_id): try: - issue_ids = request.data.get("issue_ids") + issues = request.data.get("issue", []) + + if not len(issues): + return Response( + {"error": "Issues are required"}, status=status.HTTP_400_BAD_REQUEST + ) cycle = Cycle.objects.get( workspace__slug=slug, project_id=project_id, pk=cycle_id ) issues = Issue.objects.filter( - pk__in=issue_ids, workspace__slug=slug, project_id=project_id + pk__in=issues, workspace__slug=slug, project_id=project_id ) + # Delete old records in order to maintain the database integrity + CycleIssue.objects.filter(issue_id__in=issues).delete() + CycleIssue.objects.bulk_create( [ CycleIssue( @@ -107,3 +109,9 @@ class BulkAssignIssuesToCycleEndpoint(BaseAPIView): return Response( {"error": "Cycle not found"}, status=status.HTTP_404_NOT_FOUND ) + except Exception as e: + capture_exception(e) + return Response( + {"error": "Something went wrong please try again later"}, + status=status.HTTP_200_OK, + ) From 9e4d5ac2cc8f80e9ae6661637404e18d76eff623 Mon Sep 17 00:00:00 2001 From: pablohashescobar Date: Tue, 20 Dec 2022 00:56:53 +0530 Subject: [PATCH 4/6] fix: return sequence id on issue flat serializer --- apiserver/plane/api/serializers/issue.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apiserver/plane/api/serializers/issue.py b/apiserver/plane/api/serializers/issue.py index b2dca6625..696e27169 100644 --- a/apiserver/plane/api/serializers/issue.py +++ b/apiserver/plane/api/serializers/issue.py @@ -37,6 +37,7 @@ class IssueFlatSerializer(BaseSerializer): "priority", "start_date", "target_date", + "sequence_id", ] From 602aa30f5891bb51c4886a87c8ed4251f59e16fb Mon Sep 17 00:00:00 2001 From: pablohashescobar Date: Tue, 20 Dec 2022 15:19:09 +0530 Subject: [PATCH 5/6] dev: add migration files --- .../db/migrations/0012_user_my_issues_prop.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 apiserver/plane/db/migrations/0012_user_my_issues_prop.py diff --git a/apiserver/plane/db/migrations/0012_user_my_issues_prop.py b/apiserver/plane/db/migrations/0012_user_my_issues_prop.py new file mode 100644 index 000000000..96c8a33c1 --- /dev/null +++ b/apiserver/plane/db/migrations/0012_user_my_issues_prop.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.14 on 2022-12-20 09:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('db', '0011_auto_20221216_0259'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='my_issues_prop', + field=models.JSONField(null=True), + ), + ] From aef6c783a3f395bd94ece72e2fcadf3ca4ebe510 Mon Sep 17 00:00:00 2001 From: pablohashescobar Date: Tue, 20 Dec 2022 15:31:39 +0530 Subject: [PATCH 6/6] fix: my project member viewset --- apiserver/plane/api/views/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apiserver/plane/api/views/project.py b/apiserver/plane/api/views/project.py index 3a18ef85d..8a8b036b6 100644 --- a/apiserver/plane/api/views/project.py +++ b/apiserver/plane/api/views/project.py @@ -632,7 +632,7 @@ class ProjectMemberUserEndpoint(BaseAPIView): try: project_member = ProjectMember.objects.get( - project=project_id, workpsace__slug=slug, member=request.user + project_id=project_id, workspace__slug=slug, member=request.user ) serializer = ProjectMemberSerializer(project_member)