From 8123ee8d3a9eaa7a6a0eeb6f1e7c753ec465366e Mon Sep 17 00:00:00 2001 From: pablohashescobar Date: Fri, 14 Jun 2024 15:45:48 +0530 Subject: [PATCH] dev: fix pages responses --- apiserver/plane/app/serializers/page.py | 21 ++++++++----- apiserver/plane/app/views/page/base.py | 39 ++++++++++++++++++++----- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/apiserver/plane/app/serializers/page.py b/apiserver/plane/app/serializers/page.py index 853d854b3..6e38537f0 100644 --- a/apiserver/plane/app/serializers/page.py +++ b/apiserver/plane/app/serializers/page.py @@ -20,7 +20,15 @@ class PageSerializer(BaseSerializer): write_only=True, required=False, ) - project = serializers.UUIDField(read_only=True) + # Many to many + label_ids = serializers.ListField( + child=serializers.UUIDField(), + required=False, + ) + project_ids = serializers.ListField( + child=serializers.UUIDField(), + required=False, + ) class Meta: model = Page @@ -42,18 +50,14 @@ class PageSerializer(BaseSerializer): "updated_by", "view_props", "logo_props", - "project", + "label_ids", + "project_ids", ] read_only_fields = [ "workspace", "owned_by", ] - def to_representation(self, instance): - data = super().to_representation(instance) - data["labels"] = [str(label.id) for label in instance.labels.all()] - return data - def create(self, validated_data): labels = validated_data.pop("labels", None) project_id = self.context["project_id"] @@ -63,6 +67,7 @@ class PageSerializer(BaseSerializer): # Get the workspace id from the project project = Project.objects.get(pk=project_id) + # Create the page page = Page.objects.create( **validated_data, description_html=description_html, @@ -70,6 +75,7 @@ class PageSerializer(BaseSerializer): workspace_id=project.workspace_id, ) + # Create the project page ProjectPage.objects.create( workspace_id=page.workspace_id, project_id=project_id, @@ -78,6 +84,7 @@ class PageSerializer(BaseSerializer): updated_by_id=page.updated_by_id, ) + # Create page labels if labels is not None: PageLabel.objects.bulk_create( [ diff --git a/apiserver/plane/app/views/page/base.py b/apiserver/plane/app/views/page/base.py index dbe85f2bc..3682d486c 100644 --- a/apiserver/plane/app/views/page/base.py +++ b/apiserver/plane/app/views/page/base.py @@ -6,10 +6,13 @@ from django.core.serializers.json import DjangoJSONEncoder # Django imports from django.db import connection -from django.db.models import Exists, OuterRef, Q, Subquery +from django.db.models import Exists, OuterRef, Q, Value, UUIDField from django.utils.decorators import method_decorator from django.views.decorators.gzip import gzip_page from django.http import StreamingHttpResponse +from django.contrib.postgres.aggregates import ArrayAgg +from django.contrib.postgres.fields import ArrayField +from django.db.models.functions import Coalesce # Third party imports from rest_framework import status @@ -70,9 +73,6 @@ class PageViewSet(BaseViewSet): entity_identifier=OuterRef("pk"), workspace__slug=self.kwargs.get("slug"), ) - project_subquery = ProjectPage.objects.filter( - page_id=OuterRef("id"), project_id=self.kwargs.get("project_id") - ).values_list("project_id", flat=True)[:1] return self.filter_queryset( super() .get_queryset() @@ -91,8 +91,33 @@ class PageViewSet(BaseViewSet): .order_by(self.request.GET.get("order_by", "-created_at")) .prefetch_related("labels") .order_by("-is_favorite", "-created_at") - .annotate(project=Subquery(project_subquery)) - .filter(project=self.kwargs.get("project_id")) + .annotate( + project=Exists( + ProjectPage.objects.filter( + page_id=OuterRef("id"), + project_id=self.kwargs.get("project_id"), + ) + ) + ) + .annotate( + label_ids=Coalesce( + ArrayAgg( + "page_labels__label_id", + distinct=True, + filter=~Q(page_labels__label_id__isnull=True), + ), + Value([], output_field=ArrayField(UUIDField())), + ), + project_ids=Coalesce( + ArrayAgg( + "projects__id", + distinct=True, + filter=~Q(projects__id=True), + ), + Value([], output_field=ArrayField(UUIDField())), + ), + ) + .filter(project=True) .distinct() ) @@ -112,7 +137,7 @@ class PageViewSet(BaseViewSet): serializer.save() # capture the page transaction page_transaction.delay(request.data, None, serializer.data["id"]) - page = Page.objects.get(pk=serializer.data["id"]) + page = self.get_queryset().get(pk=serializer.data["id"]) serializer = PageDetailSerializer(page) return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)