Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WEB-468] fix: issue detail endpoints #3722

Merged
merged 14 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apiserver/plane/app/serializers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@
RelatedIssueSerializer,
IssuePublicSerializer,
IssueDetailSerializer,
IssueReactionLiteSerializer,
IssueAttachmentLiteSerializer,
IssueLinkLiteSerializer,
)

from .module import (
Expand Down
51 changes: 42 additions & 9 deletions apiserver/plane/app/serializers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,12 @@ def _filter_fields(self, fields):
IssueSerializer,
LabelSerializer,
CycleIssueSerializer,
IssueFlatSerializer,
IssueLiteSerializer,
IssueRelationSerializer,
InboxIssueLiteSerializer
InboxIssueLiteSerializer,
IssueReactionLiteSerializer,
IssueAttachmentLiteSerializer,
IssueLinkLiteSerializer,
)

# Expansion mapper
Expand All @@ -79,12 +82,34 @@ def _filter_fields(self, fields):
"assignees": UserLiteSerializer,
"labels": LabelSerializer,
"issue_cycle": CycleIssueSerializer,
"parent": IssueSerializer,
"parent": IssueLiteSerializer,
"issue_relation": IssueRelationSerializer,
"issue_inbox" : InboxIssueLiteSerializer,
"issue_inbox": InboxIssueLiteSerializer,
"issue_reactions": IssueReactionLiteSerializer,
"issue_attachment": IssueAttachmentLiteSerializer,
"issue_link": IssueLinkLiteSerializer,
"sub_issues": IssueLiteSerializer,
}

self.fields[field] = expansion[field](many=True if field in ["members", "assignees", "labels", "issue_cycle", "issue_relation", "issue_inbox"] else False)

self.fields[field] = expansion[field](
many=(
True
if field
in [
"members",
"assignees",
"labels",
"issue_cycle",
"issue_relation",
"issue_inbox",
"issue_reactions",
"issue_attachment",
"issue_link",
"sub_issues",
]
else False
)
)

return self.fields

Expand All @@ -105,7 +130,11 @@ def to_representation(self, instance):
LabelSerializer,
CycleIssueSerializer,
IssueRelationSerializer,
InboxIssueLiteSerializer
InboxIssueLiteSerializer,
IssueLiteSerializer,
IssueReactionLiteSerializer,
IssueAttachmentLiteSerializer,
IssueLinkLiteSerializer,
)

# Expansion mapper
Expand All @@ -124,9 +153,13 @@ def to_representation(self, instance):
"assignees": UserLiteSerializer,
"labels": LabelSerializer,
"issue_cycle": CycleIssueSerializer,
"parent": IssueSerializer,
"parent": IssueLiteSerializer,
"issue_relation": IssueRelationSerializer,
"issue_inbox" : InboxIssueLiteSerializer,
"issue_inbox": InboxIssueLiteSerializer,
"issue_reactions": IssueReactionLiteSerializer,
"issue_attachment": IssueAttachmentLiteSerializer,
"issue_link": IssueLinkLiteSerializer,
"sub_issues": IssueLiteSerializer,
}
# Check if field in expansion then expand the field
if expand in expansion:
Expand Down
94 changes: 64 additions & 30 deletions apiserver/plane/app/serializers/issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,22 @@ def create(self, validated_data):
return IssueLink.objects.create(**validated_data)


class IssueLinkLiteSerializer(BaseSerializer):

class Meta:
model = IssueLink
fields = [
"id",
"issue_id",
"title",
"url",
"metadata",
"created_by_id",
"created_at",
]
read_only_fields = fields


class IssueAttachmentSerializer(BaseSerializer):
class Meta:
model = IssueAttachment
Expand All @@ -459,6 +475,21 @@ class Meta:
]


class IssueAttachmentLiteSerializer(DynamicBaseSerializer):

class Meta:
model = IssueAttachment
fields = [
"id",
"asset",
"attributes",
"issue_id",
"updated_at",
"updated_by_id",
]
read_only_fields = fields


class IssueReactionSerializer(BaseSerializer):
actor_detail = UserLiteSerializer(read_only=True, source="actor")

Expand All @@ -473,6 +504,18 @@ class Meta:
]


class IssueReactionLiteSerializer(DynamicBaseSerializer):

class Meta:
model = IssueReaction
fields = [
"id",
"actor_id",
"issue_id",
"reaction",
]


class CommentReactionSerializer(BaseSerializer):
class Meta:
model = CommentReaction
Expand Down Expand Up @@ -606,48 +649,39 @@ class Meta:
read_only_fields = fields



class IssueDetailSerializer(IssueSerializer):
description_html = serializers.CharField()
is_subscribed = serializers.BooleanField(read_only=True)

class Meta(IssueSerializer.Meta):
fields = IssueSerializer.Meta.fields + ["description_html", "is_subscribed"]
fields = IssueSerializer.Meta.fields + [
"description_html",
"is_subscribed",
]


class IssueLiteSerializer(DynamicBaseSerializer):
workspace_detail = WorkspaceLiteSerializer(
read_only=True, source="workspace"
)
project_detail = ProjectLiteSerializer(read_only=True, source="project")
state_detail = StateLiteSerializer(read_only=True, source="state")
label_details = LabelLiteSerializer(
read_only=True, source="labels", many=True
)
assignee_details = UserLiteSerializer(
read_only=True, source="assignees", many=True
)
sub_issues_count = serializers.IntegerField(read_only=True)
cycle_id = serializers.UUIDField(read_only=True)
module_id = serializers.UUIDField(read_only=True)
attachment_count = serializers.IntegerField(read_only=True)
link_count = serializers.IntegerField(read_only=True)
issue_reactions = IssueReactionSerializer(read_only=True, many=True)

class Meta:
model = Issue
fields = "__all__"
read_only_fields = [
"start_date",
"target_date",
"completed_at",
"workspace",
"project",
"created_by",
"updated_by",
"created_at",
"updated_at",
fields = [
"id",
"sequence_id",
"project_id",
]
read_only_fields = fields


class IssueDetailSerializer(IssueSerializer):
description_html = serializers.CharField()
is_subscribed = serializers.BooleanField()

class Meta(IssueSerializer.Meta):
fields = IssueSerializer.Meta.fields + [
"description_html",
"is_subscribed",
]
read_only_fields = fields


class IssuePublicSerializer(BaseSerializer):
Expand Down
55 changes: 44 additions & 11 deletions apiserver/plane/app/views/inbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

# Django import
from django.utils import timezone
from django.db.models import Q, Count, OuterRef, Func, F, Prefetch
from django.db.models import Q, Count, OuterRef, Func, F, Prefetch, Exists
from django.core.serializers.json import DjangoJSONEncoder
from django.contrib.postgres.aggregates import ArrayAgg
from django.contrib.postgres.fields import ArrayField
Expand All @@ -25,13 +25,14 @@
IssueLink,
IssueAttachment,
ProjectMember,
IssueReaction,
IssueSubscriber,
)
from plane.app.serializers import (
IssueCreateSerializer,
IssueSerializer,
InboxSerializer,
InboxIssueSerializer,
IssueCreateSerializer,
IssueDetailSerializer,
)
from plane.utils.issue_filters import issue_filters
from plane.bgtasks.issue_activites_task import issue_activity
Expand Down Expand Up @@ -385,9 +386,7 @@ def partial_update(self, request, slug, project_id, inbox_id, issue_id):
if state is not None:
issue.state = state
issue.save()
issue = self.get_queryset().filter(pk=issue_id).first()
serializer = IssueSerializer(issue, expand=self.expand)
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(status=status.HTTP_204_NO_CONTENT)
return Response(
serializer.errors, status=status.HTTP_400_BAD_REQUEST
)
Expand All @@ -397,11 +396,45 @@ def partial_update(self, request, slug, project_id, inbox_id, issue_id):
return Response(serializer.data, status=status.HTTP_200_OK)

def retrieve(self, request, slug, project_id, inbox_id, issue_id):
issue = self.get_queryset().filter(pk=issue_id).first()
serializer = IssueDetailSerializer(
issue,
expand=self.expand,
)
issue = (
self.get_queryset()
.filter(pk=issue_id)
.prefetch_related(
Prefetch(
"issue_reactions",
queryset=IssueReaction.objects.select_related(
"issue", "actor"
),
)
)
.prefetch_related(
Prefetch(
"issue_attachment",
queryset=IssueAttachment.objects.select_related("issue"),
)
)
.prefetch_related(
Prefetch(
"issue_link",
queryset=IssueLink.objects.select_related("created_by"),
)
)
.annotate(
is_subscribed=Exists(
IssueSubscriber.objects.filter(
workspace__slug=slug,
project_id=project_id,
issue_id=OuterRef("pk"),
subscriber=request.user,
)
)
)
).first()

if issue is None:
return Response({"error": "Requested object was not found"}, status=status.HTTP_404_NOT_FOUND)

serializer = IssueSerializer(issue)
return Response(serializer.data, status=status.HTTP_200_OK)

def destroy(self, request, slug, project_id, inbox_id, issue_id):
Expand Down
Loading
Loading