fix: created dynamic serializer

This commit is contained in:
NarayanBavisetti 2023-08-18 16:04:28 +05:30
parent e1b77d400a
commit 2058334559
25 changed files with 931 additions and 272 deletions

View File

@ -14,7 +14,6 @@ from .project import (
ProjectMemberInviteSerializer,
ProjectIdentifierSerializer,
ProjectFavoriteSerializer,
ProjectLiteSerializer,
ProjectMemberLiteSerializer,
ProjectDeployBoardSerializer,
ProjectMemberAdminSerializer,
@ -30,7 +29,7 @@ from .issue import (
IssuePropertySerializer,
BlockerIssueSerializer,
BlockedIssueSerializer,
IssueAssigneeSerializer,
# IssueAssigneeSerializer,
LabelSerializer,
IssueSerializer,
IssueFlatSerializer,

View File

@ -1,5 +1,22 @@
from rest_framework import serializers
def filterFields(self, fields):
for field_name in fields:
if isinstance(field_name, dict):
for key, value in field_name.items():
if isinstance(value, list):
filterFields(self.fields[key], value)
allowed = []
for item in fields:
if isinstance(item, str):
allowed.append(item)
elif isinstance(item, dict):
allowed.append(list(item.keys())[0])
existing = set(self.fields)
allowed = set(allowed)
for field_name in existing - allowed:
self.fields.pop(field_name)
return self.fields
class BaseSerializer(serializers.ModelSerializer):
id = serializers.PrimaryKeyRelatedField(read_only=True)
@ -7,18 +24,10 @@ class BaseSerializer(serializers.ModelSerializer):
def __init__(self, *args, **kwargs):
# Don't pass the 'fields' arg up to the superclass
fields = kwargs.pop("fields", None)
remove_nested_fields = kwargs.pop("remove_nested_fields", None)
# Instantiate the superclass normally
super().__init__(*args, **kwargs)
if fields is not None:
# Drop any fields that are not specified in the `fields` argument.
allowed = set(fields)
existing = set(self.fields)
for field_name in existing - allowed:
self.fields.pop(field_name)
if remove_nested_fields:
for field_name in remove_nested_fields:
for fields in remove_nested_fields[field_name]:
self.fields[field_name].fields.pop(fields)
self.fields = filterFields(self, fields)

View File

@ -9,7 +9,7 @@ from .base import BaseSerializer
from .user import UserSerializer
from .issue import IssueStateSerializer
from .workspace import WorkSpaceSerializer
from .project import ProjectLiteSerializer
from .project import ProjectSerializer
from plane.db.models import Cycle, CycleIssue, CycleFavorite
class CycleWriteSerializer(BaseSerializer):
@ -20,10 +20,7 @@ class CycleWriteSerializer(BaseSerializer):
class CycleSerializer(BaseSerializer):
owned_by = UserSerializer(
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
read_only=True,
)
owned_by = UserSerializer(read_only=True)
is_favorite = serializers.BooleanField(read_only=True)
total_issues = serializers.IntegerField(read_only=True)
cancelled_issues = serializers.IntegerField(read_only=True)
@ -36,12 +33,8 @@ class CycleSerializer(BaseSerializer):
total_estimates = serializers.IntegerField(read_only=True)
completed_estimates = serializers.IntegerField(read_only=True)
started_estimates = serializers.IntegerField(read_only=True)
workspace_detail = WorkSpaceSerializer(
source="workspace",
fields=("id", "name", "slug"),
read_only=True,
)
project_detail = ProjectLiteSerializer(read_only=True, source="project")
workspace_detail = WorkSpaceSerializer(source="workspace",read_only=True)
project_detail = ProjectSerializer(read_only=True, source="project")
def get_assignees(self, obj):
members = [

View File

@ -2,7 +2,7 @@
from .base import BaseSerializer
from plane.db.models import Estimate, EstimatePoint
from plane.api.serializers import WorkSpaceSerializer, ProjectLiteSerializer
from plane.api.serializers import WorkSpaceSerializer, ProjectSerializer
class EstimateSerializer(BaseSerializer):
@ -11,7 +11,7 @@ class EstimateSerializer(BaseSerializer):
fields=("id", "name", "slug"),
read_only=True,
)
project_detail = ProjectLiteSerializer(read_only=True, source="project")
project_detail = ProjectSerializer(read_only=True, source="project", fields=("id","name","cover_image","icon_prop","emoji","description"))
class Meta:
model = Estimate
@ -40,7 +40,7 @@ class EstimateReadSerializer(BaseSerializer):
fields=("id", "name", "slug"),
read_only=True,
)
project_detail = ProjectLiteSerializer(read_only=True, source="project")
project_detail = ProjectSerializer(source="project", fields=("id","name","cover_image","icon_prop","emoji","description"), read_only=True)
class Meta:
model = Estimate

View File

@ -5,11 +5,7 @@ from .user import UserSerializer
class ExporterHistorySerializer(BaseSerializer):
initiated_by_detail = UserSerializer(
source="initiated_by",
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
read_only=True,
)
initiated_by_detail = UserSerializer(source="initiated_by",read_only=True)
class Meta:
model = ExporterHistory

View File

@ -1,18 +1,14 @@
# Module imports
from .base import BaseSerializer
from .user import UserSerializer
from .project import ProjectLiteSerializer
from .project import ProjectSerializer
from .workspace import WorkSpaceSerializer
from plane.db.models import Importer
class ImporterSerializer(BaseSerializer):
initiated_by_detail = UserSerializer(
source="initiated_by",
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
read_only=True,
)
project_detail = ProjectLiteSerializer(source="project", read_only=True)
initiated_by_detail = UserSerializer(source="initiated_by",read_only=True)
project_detail = ProjectSerializer(source="project", fields=("id","name","cover_image","icon_prop","emoji","description"), read_only=True)
workspace_detail = WorkSpaceSerializer(source="workspace", read_only=True)
class Meta:

View File

@ -4,15 +4,14 @@ from rest_framework import serializers
# Module imports
from .base import BaseSerializer
from .issue import IssueFlatSerializer, LabelLiteSerializer
from .project import ProjectLiteSerializer
from .project import ProjectSerializer
from .state import StateLiteSerializer
from .project import ProjectLiteSerializer
from .user import UserSerializer
from plane.db.models import Inbox, InboxIssue, Issue
class InboxSerializer(BaseSerializer):
project_detail = ProjectLiteSerializer(source="project", read_only=True)
project_detail = ProjectSerializer(source="project", fields=("id","name","cover_image","icon_prop","emoji","description"), read_only=True)
pending_issue_count = serializers.IntegerField(read_only=True)
class Meta:
@ -26,7 +25,7 @@ class InboxSerializer(BaseSerializer):
class InboxIssueSerializer(BaseSerializer):
issue_detail = IssueFlatSerializer(source="issue", read_only=True)
project_detail = ProjectLiteSerializer(source="project", read_only=True)
project_detail = ProjectSerializer(source="project", fields=("id","name","cover_image","icon_prop","emoji","description"), read_only=True)
class Meta:
model = InboxIssue
@ -46,14 +45,9 @@ class InboxIssueLiteSerializer(BaseSerializer):
class IssueStateInboxSerializer(BaseSerializer):
state_detail = StateLiteSerializer(read_only=True, source="state")
project_detail = ProjectLiteSerializer(read_only=True, source="project")
project_detail = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
label_details = LabelLiteSerializer(read_only=True, source="labels", many=True)
assignee_details = UserSerializer(
source="assignees",
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
read_only=True,
many=True,
)
assignee_details = UserSerializer(source="assignees", read_only=True, many=True)
sub_issues_count = serializers.IntegerField(read_only=True)
bridge_id = serializers.UUIDField(read_only=True)
issue_inbox = InboxIssueLiteSerializer(read_only=True, many=True)

View File

@ -8,7 +8,7 @@ from rest_framework import serializers
from .base import BaseSerializer
from .user import UserSerializer
from .state import StateSerializer, StateLiteSerializer
from .project import ProjectSerializer, ProjectLiteSerializer
from .project import ProjectSerializer
from .workspace import WorkSpaceSerializer
from plane.db.models import (
User,
@ -53,7 +53,7 @@ class IssueFlatSerializer(BaseSerializer):
class IssueProjectLiteSerializer(BaseSerializer):
project_detail = ProjectLiteSerializer(source="project", read_only=True)
project_detail = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
class Meta:
model = Issue
@ -70,12 +70,8 @@ class IssueProjectLiteSerializer(BaseSerializer):
## Find a better approach to save manytomany?
class IssueCreateSerializer(BaseSerializer):
state_detail = StateSerializer(read_only=True, source="state")
created_by_detail = UserSerializer(
source="created_by",
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
read_only=True,
)
project_detail = ProjectLiteSerializer(read_only=True, source="project")
created_by_detail = UserSerializer(source="created_by", read_only=True,)
project_detail = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
workspace_detail = WorkSpaceSerializer(
source="workspace",
fields=("id", "name", "slug"),
@ -307,47 +303,15 @@ class IssueCreateSerializer(BaseSerializer):
class IssueActivitySerializer(BaseSerializer):
actor_detail = UserSerializer(
source="actor",
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
read_only=True,
)
actor_detail = UserSerializer(source="actor", read_only=True)
issue_detail = IssueFlatSerializer(read_only=True, source="issue")
project_detail = ProjectLiteSerializer(read_only=True, source="project")
project_detail = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
class Meta:
model = IssueActivity
fields = "__all__"
class IssueCommentSerializer(BaseSerializer):
actor_detail = UserSerializer(
source="actor",
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
read_only=True,
)
issue_detail = IssueFlatSerializer(read_only=True, source="issue")
project_detail = ProjectLiteSerializer(read_only=True, source="project")
workspace_detail = WorkSpaceSerializer(
source="workspace",
fields=("id", "name", "slug"),
read_only=True,
)
class Meta:
model = IssueComment
fields = "__all__"
read_only_fields = [
"workspace",
"project",
"issue",
"created_by",
"updated_by",
"created_at",
"updated_at",
]
class IssuePropertySerializer(BaseSerializer):
class Meta:
model = IssueProperty
@ -363,7 +327,7 @@ class LabelSerializer(BaseSerializer):
workspace_detail = WorkSpaceSerializer(
source="workspace", fields=("id", "name", "slug"), read_only=True
)
project_detail = ProjectLiteSerializer(source="project", read_only=True)
project_detail = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
class Meta:
model = Label
@ -424,16 +388,16 @@ class BlockerIssueSerializer(BaseSerializer):
read_only_fields = fields
class IssueAssigneeSerializer(BaseSerializer):
assignee_details = UserSerializer(
source="assignee",
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
read_only=True,
)
# class IssueAssigneeSerializer(BaseSerializer):
# assignee_details = UserSerializer(
# source="assignee",
# fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
# read_only=True,
# )
class Meta:
model = IssueAssignee
fields = "__all__"
# class Meta:
# model = IssueAssignee
# fields = "__all__"
class CycleBaseSerializer(BaseSerializer):
@ -603,13 +567,9 @@ class IssueVoteSerializer(BaseSerializer):
class IssueCommentSerializer(BaseSerializer):
actor_detail = UserSerializer(
source="actor",
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
read_only=True,
)
actor_detail = UserSerializer(source="actor", read_only=True)
issue_detail = IssueFlatSerializer(read_only=True, source="issue")
project_detail = ProjectLiteSerializer(read_only=True, source="project")
project_detail = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
workspace_details = WorkSpaceSerializer(
source="workspace",
@ -635,7 +595,7 @@ class IssueCommentSerializer(BaseSerializer):
class IssueStateFlatSerializer(BaseSerializer):
state_detail = StateLiteSerializer(read_only=True, source="state")
project_detail = ProjectLiteSerializer(read_only=True, source="project")
project_detail = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
class Meta:
model = Issue
@ -652,7 +612,7 @@ class IssueStateFlatSerializer(BaseSerializer):
class IssueStateSerializer(BaseSerializer):
label_details = LabelLiteSerializer(read_only=True, source="labels", many=True)
state_detail = StateLiteSerializer(read_only=True, source="state")
project_detail = ProjectLiteSerializer(read_only=True, source="project")
project_detail = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
assignee_details = UserSerializer(
source="assignees",
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
@ -670,7 +630,7 @@ class IssueStateSerializer(BaseSerializer):
class IssueSerializer(BaseSerializer):
project_detail = ProjectLiteSerializer(read_only=True, source="project")
project_detail = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
state_detail = StateSerializer(read_only=True, source="state")
parent_detail = IssueStateFlatSerializer(read_only=True, source="parent")
label_details = LabelSerializer(read_only=True, source="labels", many=True)
@ -710,7 +670,7 @@ class IssueLiteSerializer(BaseSerializer):
fields=("id", "name", "slug"),
read_only=True,
)
project_detail = ProjectLiteSerializer(read_only=True, source="project")
project_detail = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
state_detail = StateLiteSerializer(read_only=True, source="state")
label_details = LabelLiteSerializer(read_only=True, source="labels", many=True)
assignee_details = UserSerializer(

View File

@ -4,7 +4,7 @@ from rest_framework import serializers
# Module imports
from .base import BaseSerializer
from .user import UserSerializer
from .project import ProjectSerializer, ProjectLiteSerializer
from .project import ProjectSerializer
from .workspace import WorkSpaceSerializer
from .issue import IssueStateSerializer
@ -25,7 +25,7 @@ class ModuleWriteSerializer(BaseSerializer):
required=False,
)
project_detail = ProjectLiteSerializer(source="project", read_only=True)
project_detail = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
workspace_detail = WorkSpaceSerializer(
source="workspace",
fields=("id", "name", "slug"),
@ -110,7 +110,7 @@ class ModuleFlatSerializer(BaseSerializer):
class ModuleIssueSerializer(BaseSerializer):
module_detail = ModuleFlatSerializer(read_only=True, source="module")
issue_detail = ProjectLiteSerializer(read_only=True, source="issue")
issue_detail = ProjectSerializer(source="issue", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
sub_issues_count = serializers.IntegerField(read_only=True)
class Meta:
@ -159,7 +159,7 @@ class ModuleLinkSerializer(BaseSerializer):
class ModuleSerializer(BaseSerializer):
project_detail = ProjectLiteSerializer(read_only=True, source="project")
project_detail = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
lead_detail = UserSerializer(
source="lead",
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),

View File

@ -5,13 +5,13 @@ from rest_framework import serializers
from .base import BaseSerializer
from .issue import IssueFlatSerializer, LabelLiteSerializer
from .workspace import WorkSpaceSerializer
from .project import ProjectLiteSerializer
from .project import ProjectSerializer
from plane.db.models import Page, PageBlock, PageFavorite, PageLabel, Label
class PageBlockSerializer(BaseSerializer):
issue_detail = IssueFlatSerializer(source="issue", read_only=True)
project_detail = ProjectLiteSerializer(source="project", read_only=True)
project_detail = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
workspace_detail = WorkSpaceSerializer(
source="workspace",
fields=("id", "name", "slug"),
@ -43,7 +43,7 @@ class PageSerializer(BaseSerializer):
required=False,
)
blocks = PageBlockLiteSerializer(read_only=True, many=True)
project_detail = ProjectLiteSerializer(source="project", read_only=True)
project_detail = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
workspace_detail = WorkSpaceSerializer(
source="workspace",
fields=("id", "name", "slug"),

View File

@ -19,9 +19,26 @@ from plane.db.models import (
class ProjectSerializer(BaseSerializer):
# workspace = WorkSpaceSerializer(read_only=True)
default_assignee = UserSerializer(
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
read_only=True,
)
project_lead = UserSerializer(
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
read_only=True,
)
is_favorite = serializers.BooleanField(read_only=True)
total_members = serializers.IntegerField(read_only=True)
total_cycles = serializers.IntegerField(read_only=True)
total_modules = serializers.IntegerField(read_only=True)
is_member = serializers.BooleanField(read_only=True)
sort_order = serializers.FloatField(read_only=True)
member_role = serializers.IntegerField(read_only=True)
is_deployed = serializers.BooleanField(read_only=True)
workspace_detail = WorkSpaceSerializer(
source="workspace",
fields=("id", "name", "slug"),
# fields=("id", "name", "slug"),
read_only=True,
)
@ -82,21 +99,6 @@ class ProjectSerializer(BaseSerializer):
raise serializers.ValidationError(detail="Project Identifier is already taken")
class ProjectLiteSerializer(BaseSerializer):
class Meta:
model = Project
fields = [
"id",
"identifier",
"name",
"cover_image",
"icon_prop",
"emoji",
"description",
]
read_only_fields = fields
class ProjectDetailSerializer(BaseSerializer):
workspace = WorkSpaceSerializer(read_only=True)
default_assignee = UserSerializer(
@ -123,7 +125,7 @@ class ProjectDetailSerializer(BaseSerializer):
class ProjectMemberSerializer(BaseSerializer):
workspace = WorkSpaceSerializer(read_only=True)
project = ProjectLiteSerializer(read_only=True)
project = ProjectSerializer(fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
member = UserSerializer(
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
read_only=True,
@ -140,7 +142,7 @@ class ProjectMemberAdminSerializer(BaseSerializer):
fields=("id", "name", "slug"),
read_only=True,
)
project = ProjectLiteSerializer(read_only=True)
project = ProjectSerializer(fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
member = UserSerializer(
fields=(
"id",
@ -160,7 +162,7 @@ class ProjectMemberAdminSerializer(BaseSerializer):
class ProjectMemberInviteSerializer(BaseSerializer):
project = ProjectLiteSerializer(read_only=True)
project = ProjectSerializer(fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
workspace = WorkSpaceSerializer(
fields=("id", "name", "slug"),
read_only=True,
@ -178,7 +180,7 @@ class ProjectIdentifierSerializer(BaseSerializer):
class ProjectFavoriteSerializer(BaseSerializer):
project_detail = ProjectLiteSerializer(source="project", read_only=True)
project_detail = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
class Meta:
model = ProjectFavorite
@ -203,7 +205,7 @@ class ProjectMemberLiteSerializer(BaseSerializer):
class ProjectDeployBoardSerializer(BaseSerializer):
project_details = ProjectLiteSerializer(read_only=True, source="project")
project_details = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
workspace_detail = WorkSpaceSerializer(
source="workspace",
fields=("id", "name", "slug"),

View File

@ -1,7 +1,7 @@
# Module imports
from .base import BaseSerializer
from .workspace import WorkSpaceSerializer
from .project import ProjectLiteSerializer
from .project import ProjectSerializer
from plane.db.models import State
@ -12,7 +12,7 @@ class StateSerializer(BaseSerializer):
fields=("id", "name", "slug"),
read_only=True,
)
project_detail = ProjectLiteSerializer(read_only=True, source="project")
project_detail = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
class Meta:
model = State

View File

@ -4,14 +4,14 @@ from rest_framework import serializers
# Module imports
from .base import BaseSerializer
from .workspace import WorkSpaceSerializer
from .project import ProjectLiteSerializer
from .project import ProjectSerializer
from plane.db.models import IssueView, IssueViewFavorite
from plane.utils.issue_filters import issue_filters
class IssueViewSerializer(BaseSerializer):
is_favorite = serializers.BooleanField(read_only=True)
project_detail = ProjectLiteSerializer(source="project", read_only=True)
project_detail = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
workspace_detail = WorkSpaceSerializer(
source="workspace",
fields=("id", "name", "slug"),

View File

@ -18,7 +18,7 @@ from plane.db.models import (
class WorkSpaceSerializer(BaseSerializer):
owner = UserSerializer(
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
# fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
read_only=True,
)
total_members = serializers.IntegerField(read_only=True)
@ -37,7 +37,6 @@ class WorkSpaceSerializer(BaseSerializer):
]
class WorkSpaceMemberSerializer(BaseSerializer):
member = UserSerializer(
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name" ,"email"),
@ -53,30 +52,6 @@ class WorkSpaceMemberSerializer(BaseSerializer):
fields = "__all__"
# class WorkspaceMemberAdminSerializer(BaseSerializer):
# member = UserSerializer(
# fields=(
# "id",
# "first_name",
# "last_name",
# "avatar",
# "is_bot",
# "display_name",
# "email",
# ),
# read_only=True,
# )
# workspace = WorkSpaceSerializer(
# fields=("id", "name", "slug"),
# read_only=True,
# )
# class Meta:
# model = WorkspaceMember
# fields = "__all__"
class WorkSpaceMemberInviteSerializer(BaseSerializer):
workspace = WorkSpaceSerializer(read_only=True)
total_members = serializers.IntegerField(read_only=True)

View File

@ -56,6 +56,10 @@ class CycleViewSet(BaseViewSet):
permission_classes = [
ProjectEntityPermission,
]
# def get_serializer_class(self):
# return (
# CycleSerializer(nested_fields={"owned_by":("id", "first_name", "last_name", "avatar", "is_bot", "display_name")})
# )
def perform_create(self, serializer):
serializer.save(
@ -148,13 +152,15 @@ class CycleViewSet(BaseViewSet):
.prefetch_related(
Prefetch(
"issue_cycle__issue__assignees",
queryset=User.objects.only("avatar", "first_name", "id").distinct(),
queryset=User.objects.only(
"avatar", "first_name", "id").distinct(),
)
)
.prefetch_related(
Prefetch(
"issue_cycle__issue__labels",
queryset=Label.objects.only("name", "color", "id").distinct(),
queryset=Label.objects.only(
"name", "color", "id").distinct(),
)
)
.order_by("-is_favorite", "name")
@ -172,7 +178,8 @@ class CycleViewSet(BaseViewSet):
# All Cycles
if cycle_view == "all":
return Response(
CycleSerializer(queryset, many=True).data, status=status.HTTP_200_OK
CycleSerializer(queryset, fields=["id", "created_by", "created_at", "updated_at", "updated_by", "project", "workspace", "name", "description", "start_date", "end_date", "owned_by", "view_props", "sort_order", "is_favorite", "total_issues", "cancelled_issues", "completed_issues", "started_issues", "unstarted_issues"
, "backlog_issues", "assignees", "labels", "total_estimates", "completed_estimates", "started_estimates",{"workspace_detail": ["id", "name","slug"]},{ "project_detail": ["id", "name", "cover_image", "icon_prop", "emoji", "description"]}, {"owned_by": ["id", "first_name", "last_name", "avatar", "is_bot", "display_name"]}], many=True).data, status=status.HTTP_200_OK
)
# Current Cycle
@ -182,7 +189,8 @@ class CycleViewSet(BaseViewSet):
end_date__gte=timezone.now(),
)
data = CycleSerializer(queryset, many=True).data
data = CycleSerializer(queryset, fields=["id", "created_by", "created_at", "updated_at", "updated_by", "project", "workspace", "name", "description", "start_date", "end_date", "owned_by", "view_props", "sort_order", "is_favorite", "total_issues", "cancelled_issues", "completed_issues", "started_issues", "unstarted_issues"
, "backlog_issues", "assignees", "labels", "total_estimates", "completed_estimates", "started_estimates",{"workspace_detail": ["id", "name","slug"]},{ "project_detail": ["id", "name", "cover_image", "icon_prop", "emoji", "description"]}, {"owned_by": ["id", "first_name", "last_name", "avatar", "is_bot", "display_name"]}], many=True).data
if len(data):
assignee_distribution = (
@ -256,14 +264,16 @@ class CycleViewSet(BaseViewSet):
if cycle_view == "upcoming":
queryset = queryset.filter(start_date__gt=timezone.now())
return Response(
CycleSerializer(queryset, many=True).data, status=status.HTTP_200_OK
CycleSerializer(queryset, fields=["id", "created_by", "created_at", "updated_at", "updated_by", "project", "workspace", "name", "description", "start_date", "end_date", "owned_by", "view_props", "sort_order", "is_favorite", "total_issues", "cancelled_issues", "completed_issues", "started_issues", "unstarted_issues"
, "backlog_issues", "assignees", "labels", "total_estimates", "completed_estimates", "started_estimates",{"workspace_detail": ["id", "name","slug"]},{ "project_detail": ["id", "name", "cover_image", "icon_prop", "emoji", "description"]}, {"owned_by": ["id", "first_name", "last_name", "avatar", "is_bot", "display_name"]}], many=True).data, status=status.HTTP_200_OK
)
# Completed Cycles
if cycle_view == "completed":
queryset = queryset.filter(end_date__lt=timezone.now())
return Response(
CycleSerializer(queryset, many=True).data, status=status.HTTP_200_OK
CycleSerializer(queryset, fields=["id", "created_by", "created_at", "updated_at", "updated_by", "project", "workspace", "name", "description", "start_date", "end_date", "owned_by", "view_props", "sort_order", "is_favorite", "total_issues", "cancelled_issues", "completed_issues", "started_issues", "unstarted_issues"
, "backlog_issues", "assignees", "labels", "total_estimates", "completed_estimates", "started_estimates",{"workspace_detail": ["id", "name","slug"]},{ "project_detail": ["id", "name", "cover_image", "icon_prop", "emoji", "description"]}, {"owned_by": ["id", "first_name", "last_name", "avatar", "is_bot", "display_name"]}], many=True).data, status=status.HTTP_200_OK
)
# Draft Cycles
@ -274,16 +284,19 @@ class CycleViewSet(BaseViewSet):
)
return Response(
CycleSerializer(queryset, many=True).data, status=status.HTTP_200_OK
CycleSerializer(queryset, fields=["id", "created_by", "created_at", "updated_at", "updated_by", "project", "workspace", "name", "description", "start_date", "end_date", "owned_by", "view_props", "sort_order", "is_favorite", "total_issues", "cancelled_issues", "completed_issues", "started_issues", "unstarted_issues"
, "backlog_issues", "assignees", "labels", "total_estimates", "completed_estimates", "started_estimates",{"workspace_detail": ["id", "name","slug"]},{ "project_detail": ["id", "name", "cover_image", "icon_prop", "emoji", "description"]}, {"owned_by": ["id", "first_name", "last_name", "avatar", "is_bot", "display_name"]}], many=True).data, status=status.HTTP_200_OK
)
# Incomplete Cycles
if cycle_view == "incomplete":
queryset = queryset.filter(
Q(end_date__gte=timezone.now().date()) | Q(end_date__isnull=True),
Q(end_date__gte=timezone.now().date()) | Q(
end_date__isnull=True),
)
return Response(
CycleSerializer(queryset, many=True).data, status=status.HTTP_200_OK
CycleSerializer(queryset, fields=["id", "created_by", "created_at", "updated_at", "updated_by", "project", "workspace", "name", "description", "start_date", "end_date", "owned_by", "view_props", "sort_order", "is_favorite", "total_issues", "cancelled_issues", "completed_issues", "started_issues", "unstarted_issues"
, "backlog_issues", "assignees", "labels", "total_estimates", "completed_estimates", "started_estimates",{"workspace_detail": ["id", "name","slug"]},{ "project_detail": ["id", "name", "cover_image", "icon_prop", "emoji", "description"]}, {"owned_by": ["id", "first_name", "last_name", "avatar", "is_bot", "display_name"]}], many=True).data, status=status.HTTP_200_OK
)
return Response(
@ -306,7 +319,8 @@ class CycleViewSet(BaseViewSet):
request.data.get("start_date", None) is not None
and request.data.get("end_date", None) is not None
):
serializer = CycleSerializer(data=request.data)
serializer = CycleSerializer(data=request.data, fields=["id", "created_by", "created_at", "updated_at", "updated_by", "project", "workspace", "name", "description", "start_date", "end_date", "owned_by", "view_props", "sort_order", "is_favorite", "total_issues", "cancelled_issues", "completed_issues", "started_issues", "unstarted_issues"
, "backlog_issues", "assignees", "labels", "total_estimates", "completed_estimates", "started_estimates",{"workspace_detail": ["id", "name","slug"]},{ "project_detail": ["id", "name", "cover_image", "icon_prop", "emoji", "description"]}, {"owned_by": ["id", "first_name", "last_name", "avatar", "is_bot", "display_name"]}])
if serializer.is_valid():
serializer.save(
project_id=project_id,
@ -342,7 +356,8 @@ class CycleViewSet(BaseViewSet):
status=status.HTTP_400_BAD_REQUEST,
)
serializer = CycleWriteSerializer(cycle, data=request.data, partial=True)
serializer = CycleWriteSerializer(
cycle, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
@ -418,7 +433,8 @@ class CycleViewSet(BaseViewSet):
.order_by("label_name")
)
data = CycleSerializer(queryset).data
data = CycleSerializer(queryset, fields=["id", "created_by", "created_at", "updated_at", "updated_by", "project", "workspace", "name", "description", "start_date", "end_date", "owned_by", "view_props", "sort_order", "is_favorite", "total_issues", "cancelled_issues", "completed_issues", "started_issues", "unstarted_issues"
, "backlog_issues", "assignees", "labels", "total_estimates", "completed_estimates", "started_estimates",{"workspace_detail": ["id", "name","slug"]},{ "project_detail": ["id", "name", "cover_image", "icon_prop", "emoji", "description"]}, {"owned_by": ["id", "first_name", "last_name", "avatar", "is_bot", "display_name"]}]).data
data["distribution"] = {
"assignees": assignee_distribution,
"labels": label_distribution,
@ -486,7 +502,8 @@ class CycleIssueViewSet(BaseViewSet):
super()
.get_queryset()
.annotate(
sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("issue_id"))
sub_issues_count=Issue.issue_objects.filter(
parent=OuterRef("issue_id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@ -512,7 +529,8 @@ class CycleIssueViewSet(BaseViewSet):
issues = (
Issue.issue_objects.filter(issue_cycle__cycle_id=cycle_id)
.annotate(
sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
sub_issues_count=Issue.issue_objects.filter(
parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")

View File

@ -23,11 +23,11 @@ class ExportIssuesEndpoint(BaseAPIView):
try:
# Get the workspace
workspace = Workspace.objects.get(slug=slug)
provider = request.data.get("provider", False)
multiple = request.data.get("multiple", False)
project_ids = request.data.get("project", [])
if provider in ["csv", "xlsx", "json"]:
if not project_ids:
project_ids = Project.objects.filter(
@ -77,14 +77,38 @@ class ExportIssuesEndpoint(BaseAPIView):
try:
exporter_history = ExporterHistory.objects.filter(
workspace__slug=slug
).select_related("workspace","initiated_by")
).select_related("workspace", "initiated_by")
if request.GET.get("per_page", False) and request.GET.get("cursor", False):
return self.paginate(
request=request,
queryset=exporter_history,
on_results=lambda exporter_history: ExporterHistorySerializer(
exporter_history, many=True
exporter_history,
fields=[
"id",
"created_by",
"created_at",
"updated_at",
"updated_by",
"initiated_by",
"status",
"url",
"token",
"project",
"provider",
{
"initiated_by_detail": [
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
]
},
],
many=True,
).data,
)
else:

View File

@ -14,7 +14,7 @@ from django.conf import settings
from .base import BaseAPIView
from plane.api.permissions import ProjectEntityPermission
from plane.db.models import Workspace, Project
from plane.api.serializers import ProjectLiteSerializer, WorkSpaceSerializer
from plane.api.serializers import ProjectSerializer, WorkSpaceSerializer
class GPTIntegrationEndpoint(BaseAPIView):
@ -57,10 +57,25 @@ class GPTIntegrationEndpoint(BaseAPIView):
{
"response": text,
"response_html": text_html,
"project_detail": ProjectLiteSerializer(project).data,
"project_detail": ProjectSerializer(
project,
fields=[
"id",
"name",
"cover_image",
"icon_prop",
"emoji",
"description",
"created_by",
"updated_by",
"created_at",
"updated_at",
],
read_only=True,
).data,
"workspace_detail": WorkSpaceSerializer(
workspace,
fields=("id", "name", "slug"),
fields=["id", "name", "slug"],
).data,
},
status=status.HTTP_200_OK,

View File

@ -177,7 +177,36 @@ class ImportServiceEndpoint(BaseAPIView):
)
service_importer.delay(service, importer.id)
serializer = ImporterSerializer(importer)
serializer = ImporterSerializer(
importer,
fields={
"id": [],
"created_by": [],
"created_at": [],
"updated_at": [],
"updated_by": [],
"workspace": [],
"project": [],
"initiated_by": [],
"project_detail": [],
"workspace_detail": [],
"service": [],
"status": [],
"metadata": [],
"config": [],
"data": [],
"token": [],
"imported_data": [],
"initiated_by_detail": [
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
],
},
)
return Response(serializer.data, status=status.HTTP_201_CREATED)
if service == "jira":
@ -213,7 +242,36 @@ class ImportServiceEndpoint(BaseAPIView):
)
service_importer.delay(service, importer.id)
serializer = ImporterSerializer(importer)
serializer = ImporterSerializer(
importer,
fields={
"id": [],
"created_by": [],
"created_at": [],
"updated_at": [],
"updated_by": [],
"workspace": [],
"project": [],
"initiated_by": [],
"project_detail": [],
"workspace_detail": [],
"service": [],
"status": [],
"metadata": [],
"config": [],
"data": [],
"token": [],
"imported_data": [],
"initiated_by_detail": [
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
],
},
)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(
@ -243,7 +301,39 @@ class ImportServiceEndpoint(BaseAPIView):
.order_by("-created_at")
.select_related("initiated_by", "project", "workspace")
)
serializer = ImporterSerializer(imports, many=True)
serializer = ImporterSerializer(
imports,
fields=[
"id",
"created_by",
"created_at",
"updated_at",
"updated_by",
"workspace",
"project",
"initiated_by",
"project_detail",
"workspace_detail",
"service",
"status",
"metadata",
"config",
"data",
"token",
"imported_data",
{
"initiated_by_detail": [
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
]
},
],
many=True,
)
return Response(serializer.data)
except Exception as e:
capture_exception(e)
@ -284,7 +374,40 @@ class ImportServiceEndpoint(BaseAPIView):
importer = Importer.objects.get(
pk=pk, service=service, workspace__slug=slug
)
serializer = ImporterSerializer(importer, data=request.data, partial=True)
serializer = ImporterSerializer(
importer,
fields=[
"id",
"created_by",
"created_at",
"updated_at",
"updated_by",
"workspace",
"project",
"initiated_by",
"project_detail",
"workspace_detail",
"service",
"status",
"metadata",
"config",
"data",
"token",
"imported_data",
{
"initiated_by_detail": [
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
]
},
],
data=request.data,
partial=True,
)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)

View File

@ -152,7 +152,22 @@ class InboxIssueViewSet(BaseViewSet):
)
)
)
issues_data = IssueStateInboxSerializer(issues, many=True).data
issues_data = IssueStateInboxSerializer(
issues,
fields=[
{
"assignee_details": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
}
],
many=True,
).data
return Response(
issues_data,
status=status.HTTP_200_OK,
@ -222,7 +237,19 @@ class InboxIssueViewSet(BaseViewSet):
source=request.data.get("source", "in-app"),
)
serializer = IssueStateInboxSerializer(issue)
serializer = IssueStateInboxSerializer(
issue,
nested_fields={
"assignee_details": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
},
)
return Response(serializer.data, status=status.HTTP_200_OK)
except Exception as e:
capture_exception(e)
@ -237,10 +264,17 @@ class InboxIssueViewSet(BaseViewSet):
pk=pk, workspace__slug=slug, project_id=project_id, inbox_id=inbox_id
)
# Get the project member
project_member = ProjectMember.objects.get(workspace__slug=slug, project_id=project_id, member=request.user)
project_member = ProjectMember.objects.get(
workspace__slug=slug, project_id=project_id, member=request.user
)
# Only project members admins and created_by users can access this endpoint
if project_member.role <= 10 and str(inbox_issue.created_by_id) != str(request.user.id):
return Response({"error": "You cannot edit inbox issues"}, status=status.HTTP_400_BAD_REQUEST)
if project_member.role <= 10 and str(inbox_issue.created_by_id) != str(
request.user.id
):
return Response(
{"error": "You cannot edit inbox issues"},
status=status.HTTP_400_BAD_REQUEST,
)
# Get issue data
issue_data = request.data.pop("issue", False)
@ -251,15 +285,29 @@ class InboxIssueViewSet(BaseViewSet):
)
# Only allow guests and viewers to edit name and description
if project_member.role <= 10:
# viewers and guests since only viewers and guests
# viewers and guests since only viewers and guests
issue_data = {
"name": issue_data.get("name", issue.name),
"description_html": issue_data.get("description_html", issue.description_html),
"description": issue_data.get("description", issue.description)
"description_html": issue_data.get(
"description_html", issue.description_html
),
"description": issue_data.get("description", issue.description),
}
issue_serializer = IssueCreateSerializer(
issue, data=issue_data, partial=True
issue,
data=issue_data,
nested_fields={
"created_by_detail": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
},
partial=True,
)
if issue_serializer.is_valid():
@ -300,7 +348,9 @@ class InboxIssueViewSet(BaseViewSet):
project_id=project_id,
)
state = State.objects.filter(
group="cancelled", workspace__slug=slug, project_id=project_id
group="cancelled",
workspace__slug=slug,
project_id=project_id,
).first()
if state is not None:
issue.state = state
@ -318,7 +368,9 @@ class InboxIssueViewSet(BaseViewSet):
if issue.state.name == "Triage":
# Move to default state
state = State.objects.filter(
workspace__slug=slug, project_id=project_id, default=True
workspace__slug=slug,
project_id=project_id,
default=True,
).first()
if state is not None:
issue.state = state
@ -327,7 +379,9 @@ class InboxIssueViewSet(BaseViewSet):
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(InboxIssueSerializer(inbox_issue).data, status=status.HTTP_200_OK)
return Response(
InboxIssueSerializer(inbox_issue).data, status=status.HTTP_200_OK
)
except InboxIssue.DoesNotExist:
return Response(
{"error": "Inbox Issue does not exist"},
@ -348,7 +402,19 @@ class InboxIssueViewSet(BaseViewSet):
issue = Issue.objects.get(
pk=inbox_issue.issue_id, workspace__slug=slug, project_id=project_id
)
serializer = IssueStateInboxSerializer(issue)
serializer = IssueStateInboxSerializer(
issue,
nested_fields={
"assignee_details": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
},
)
return Response(serializer.data, status=status.HTTP_200_OK)
except Exception as e:
capture_exception(e)
@ -363,15 +429,25 @@ class InboxIssueViewSet(BaseViewSet):
pk=pk, workspace__slug=slug, project_id=project_id, inbox_id=inbox_id
)
# Get the project member
project_member = ProjectMember.objects.get(workspace__slug=slug, project_id=project_id, member=request.user)
project_member = ProjectMember.objects.get(
workspace__slug=slug, project_id=project_id, member=request.user
)
if project_member.role <= 10 and str(inbox_issue.created_by_id) != str(request.user.id):
return Response({"error": "You cannot delete inbox issue"}, status=status.HTTP_400_BAD_REQUEST)
if project_member.role <= 10 and str(inbox_issue.created_by_id) != str(
request.user.id
):
return Response(
{"error": "You cannot delete inbox issue"},
status=status.HTTP_400_BAD_REQUEST,
)
inbox_issue.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
except InboxIssue.DoesNotExist:
return Response({"error": "Inbox Issue does not exists"}, status=status.HTTP_400_BAD_REQUEST)
return Response(
{"error": "Inbox Issue does not exists"},
status=status.HTTP_400_BAD_REQUEST,
)
except Exception as e:
capture_exception(e)
return Response(
@ -389,7 +465,10 @@ class InboxIssuePublicViewSet(BaseViewSet):
]
def get_queryset(self):
project_deploy_board = ProjectDeployBoard.objects.get(workspace__slug=self.kwargs.get("slug"), project_id=self.kwargs.get("project_id"))
project_deploy_board = ProjectDeployBoard.objects.get(
workspace__slug=self.kwargs.get("slug"),
project_id=self.kwargs.get("project_id"),
)
if project_deploy_board is not None:
return self.filter_queryset(
super()
@ -407,9 +486,14 @@ class InboxIssuePublicViewSet(BaseViewSet):
def list(self, request, slug, project_id, inbox_id):
try:
project_deploy_board = ProjectDeployBoard.objects.get(workspace__slug=slug, project_id=project_id)
project_deploy_board = ProjectDeployBoard.objects.get(
workspace__slug=slug, project_id=project_id
)
if project_deploy_board.inbox is None:
return Response({"error": "Inbox is not enabled for this Project Board"}, status=status.HTTP_400_BAD_REQUEST)
return Response(
{"error": "Inbox is not enabled for this Project Board"},
status=status.HTTP_400_BAD_REQUEST,
)
filters = issue_filters(request.query_params, "GET")
issues = (
@ -452,13 +536,29 @@ class InboxIssuePublicViewSet(BaseViewSet):
)
)
)
issues_data = IssueStateInboxSerializer(issues, many=True).data
issues_data = IssueStateInboxSerializer(
issues,
nested_fields={
"assignee_details": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
},
many=True,
).data
return Response(
issues_data,
status=status.HTTP_200_OK,
)
except ProjectDeployBoard.DoesNotExist:
return Response({"error": "Project Deploy Board does not exist"}, status=status.HTTP_400_BAD_REQUEST)
return Response(
{"error": "Project Deploy Board does not exist"},
status=status.HTTP_400_BAD_REQUEST,
)
except Exception as e:
capture_exception(e)
return Response(
@ -468,9 +568,14 @@ class InboxIssuePublicViewSet(BaseViewSet):
def create(self, request, slug, project_id, inbox_id):
try:
project_deploy_board = ProjectDeployBoard.objects.get(workspace__slug=slug, project_id=project_id)
project_deploy_board = ProjectDeployBoard.objects.get(
workspace__slug=slug, project_id=project_id
)
if project_deploy_board.inbox is None:
return Response({"error": "Inbox is not enabled for this Project Board"}, status=status.HTTP_400_BAD_REQUEST)
return Response(
{"error": "Inbox is not enabled for this Project Board"},
status=status.HTTP_400_BAD_REQUEST,
)
if not request.data.get("issue", {}).get("name", False):
return Response(
@ -527,7 +632,19 @@ class InboxIssuePublicViewSet(BaseViewSet):
source=request.data.get("source", "in-app"),
)
serializer = IssueStateInboxSerializer(issue)
serializer = IssueStateInboxSerializer(
issue,
nested_fields={
"assignee_details": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
},
)
return Response(serializer.data, status=status.HTTP_200_OK)
except Exception as e:
capture_exception(e)
@ -538,33 +655,54 @@ class InboxIssuePublicViewSet(BaseViewSet):
def partial_update(self, request, slug, project_id, inbox_id, pk):
try:
project_deploy_board = ProjectDeployBoard.objects.get(workspace__slug=slug, project_id=project_id)
project_deploy_board = ProjectDeployBoard.objects.get(
workspace__slug=slug, project_id=project_id
)
if project_deploy_board.inbox is None:
return Response({"error": "Inbox is not enabled for this Project Board"}, status=status.HTTP_400_BAD_REQUEST)
return Response(
{"error": "Inbox is not enabled for this Project Board"},
status=status.HTTP_400_BAD_REQUEST,
)
inbox_issue = InboxIssue.objects.get(
pk=pk, workspace__slug=slug, project_id=project_id, inbox_id=inbox_id
)
# Get the project member
if str(inbox_issue.created_by_id) != str(request.user.id):
return Response({"error": "You cannot edit inbox issues"}, status=status.HTTP_400_BAD_REQUEST)
return Response(
{"error": "You cannot edit inbox issues"},
status=status.HTTP_400_BAD_REQUEST,
)
# Get issue data
issue_data = request.data.pop("issue", False)
issue = Issue.objects.get(
pk=inbox_issue.issue_id, workspace__slug=slug, project_id=project_id
)
# viewers and guests since only viewers and guests
# viewers and guests since only viewers and guests
issue_data = {
"name": issue_data.get("name", issue.name),
"description_html": issue_data.get("description_html", issue.description_html),
"description": issue_data.get("description", issue.description)
"description_html": issue_data.get(
"description_html", issue.description_html
),
"description": issue_data.get("description", issue.description),
}
issue_serializer = IssueCreateSerializer(
issue, data=issue_data, partial=True
issue,
data=issue_data,
nested_fields={
"created_by_detail": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
},
partial=True,
)
if issue_serializer.is_valid():
@ -600,17 +738,34 @@ class InboxIssuePublicViewSet(BaseViewSet):
def retrieve(self, request, slug, project_id, inbox_id, pk):
try:
project_deploy_board = ProjectDeployBoard.objects.get(workspace__slug=slug, project_id=project_id)
project_deploy_board = ProjectDeployBoard.objects.get(
workspace__slug=slug, project_id=project_id
)
if project_deploy_board.inbox is None:
return Response({"error": "Inbox is not enabled for this Project Board"}, status=status.HTTP_400_BAD_REQUEST)
return Response(
{"error": "Inbox is not enabled for this Project Board"},
status=status.HTTP_400_BAD_REQUEST,
)
inbox_issue = InboxIssue.objects.get(
pk=pk, workspace__slug=slug, project_id=project_id, inbox_id=inbox_id
)
issue = Issue.objects.get(
pk=inbox_issue.issue_id, workspace__slug=slug, project_id=project_id
)
serializer = IssueStateInboxSerializer(issue)
serializer = IssueStateInboxSerializer(
issue,
nested_fields={
"assignee_details": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
},
)
return Response(serializer.data, status=status.HTTP_200_OK)
except Exception as e:
capture_exception(e)
@ -621,25 +776,35 @@ class InboxIssuePublicViewSet(BaseViewSet):
def destroy(self, request, slug, project_id, inbox_id, pk):
try:
project_deploy_board = ProjectDeployBoard.objects.get(workspace__slug=slug, project_id=project_id)
project_deploy_board = ProjectDeployBoard.objects.get(
workspace__slug=slug, project_id=project_id
)
if project_deploy_board.inbox is None:
return Response({"error": "Inbox is not enabled for this Project Board"}, status=status.HTTP_400_BAD_REQUEST)
return Response(
{"error": "Inbox is not enabled for this Project Board"},
status=status.HTTP_400_BAD_REQUEST,
)
inbox_issue = InboxIssue.objects.get(
pk=pk, workspace__slug=slug, project_id=project_id, inbox_id=inbox_id
)
if str(inbox_issue.created_by_id) != str(request.user.id):
return Response({"error": "You cannot delete inbox issue"}, status=status.HTTP_400_BAD_REQUEST)
return Response(
{"error": "You cannot delete inbox issue"},
status=status.HTTP_400_BAD_REQUEST,
)
inbox_issue.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
except InboxIssue.DoesNotExist:
return Response({"error": "Inbox Issue does not exists"}, status=status.HTTP_400_BAD_REQUEST)
return Response(
{"error": "Inbox Issue 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_400_BAD_REQUEST,
)

View File

@ -281,6 +281,16 @@ class IssueViewSet(BaseViewSet):
serializer = IssueCreateSerializer(
data=request.data,
nested_fields={
"created_by_detail": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
},
context={
"project_id": project_id,
"workspace_id": project.workspace_id,
@ -493,8 +503,34 @@ class IssueActivityEndpoint(BaseAPIView):
.order_by("created_at")
.select_related("actor", "issue", "project", "workspace")
)
issue_activities = IssueActivitySerializer(issue_activities, many=True).data
issue_comments = IssueCommentSerializer(issue_comments, many=True).data
issue_activities = IssueActivitySerializer(
issue_activities,
nested_fields={
"actor_detail": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
},
many=True,
).data
issue_comments = IssueCommentSerializer(
issue_comments,
nested_fields={
"actor_detail": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
},
many=True,
).data
result_list = sorted(
chain(issue_activities, issue_comments),
@ -522,6 +558,9 @@ class IssueCommentViewSet(BaseViewSet):
"workspace__id",
]
# def get_serializer_class(self):
# return IssueCommentSerializer(nested_fields={"actor_detail":("id", "first_name", "last_name", "avatar", "is_bot", "display_name")})
def perform_create(self, serializer):
serializer.save(
project_id=self.kwargs.get("project_id"),
@ -550,7 +589,19 @@ class IssueCommentViewSet(BaseViewSet):
issue_id=str(self.kwargs.get("issue_id", None)),
project_id=str(self.kwargs.get("project_id", None)),
current_instance=json.dumps(
IssueCommentSerializer(current_instance).data,
IssueCommentSerializer(
current_instance,
nested_fields={
"actor_detail": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
},
).data,
cls=DjangoJSONEncoder,
),
)
@ -571,7 +622,19 @@ class IssueCommentViewSet(BaseViewSet):
issue_id=str(self.kwargs.get("issue_id", None)),
project_id=str(self.kwargs.get("project_id", None)),
current_instance=json.dumps(
IssueCommentSerializer(current_instance).data,
IssueCommentSerializer(
current_instance,
nested_fields={
"actor_detail": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
},
).data,
cls=DjangoJSONEncoder,
),
)
@ -769,7 +832,9 @@ class SubIssuesEndpoint(BaseAPIView):
.order_by("state_group")
)
result = {item["state_group"]: item["state_count"] for item in state_distribution}
result = {
item["state_group"]: item["state_count"] for item in state_distribution
}
serializer = IssueLiteSerializer(
sub_issues,
@ -1507,7 +1572,19 @@ class IssueCommentPublicViewSet(BaseViewSet):
else "EXTERNAL"
)
serializer = IssueCommentSerializer(data=request.data)
serializer = IssueCommentSerializer(
data=request.data,
nested_fields={
"actor_detail": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
},
)
if serializer.is_valid():
serializer.save(
project_id=project_id,
@ -1547,7 +1624,19 @@ class IssueCommentPublicViewSet(BaseViewSet):
workspace__slug=slug, pk=pk, actor=request.user
)
serializer = IssueCommentSerializer(
comment, data=request.data, partial=True
comment,
data=request.data,
nested_fields={
"actor_detail": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
},
partial=True,
)
if serializer.is_valid():
serializer.save()
@ -1558,7 +1647,19 @@ class IssueCommentPublicViewSet(BaseViewSet):
issue_id=str(issue_id),
project_id=str(project_id),
current_instance=json.dumps(
IssueCommentSerializer(comment).data,
IssueCommentSerializer(
comment,
nested_fields={
"actor_detail": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
},
).data,
cls=DjangoJSONEncoder,
),
)
@ -1567,7 +1668,8 @@ class IssueCommentPublicViewSet(BaseViewSet):
except (IssueComment.DoesNotExist, ProjectDeployBoard.DoesNotExist):
return Response(
{"error": "IssueComent Does not exists"},
status=status.HTTP_400_BAD_REQUEST,)
status=status.HTTP_400_BAD_REQUEST,
)
def destroy(self, request, slug, project_id, issue_id, pk):
try:
@ -1590,7 +1692,19 @@ class IssueCommentPublicViewSet(BaseViewSet):
issue_id=str(issue_id),
project_id=str(project_id),
current_instance=json.dumps(
IssueCommentSerializer(comment).data,
IssueCommentSerializer(
comment,
nested_fields={
"actor_detail": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
},
).data,
cls=DjangoJSONEncoder,
),
)
@ -1835,9 +1949,11 @@ class ExportIssuesEndpoint(BaseAPIView):
def post(self, request, slug):
try:
issue_export_task.delay(
email=request.user.email, data=request.data, slug=slug ,exporter_name=request.user.first_name
email=request.user.email,
data=request.data,
slug=slug,
exporter_name=request.user.first_name,
)
return Response(
@ -1851,4 +1967,4 @@ class ExportIssuesEndpoint(BaseAPIView):
return Response(
{"error": "Something went wrong please try again later"},
status=status.HTTP_400_BAD_REQUEST,
)
)

View File

@ -91,10 +91,10 @@ class ProjectViewSet(BaseViewSet):
ProjectBasePermission,
]
def get_serializer_class(self, *args, **kwargs):
if self.action == "update" or self.action == "partial_update":
return ProjectSerializer
return ProjectDetailSerializer
# def get_serializer_class(self, *args, **kwargs):
# if self.action == "update" or self.action == "partial_update":
# return ProjectSerializer(fields=['id', {'workspace_detail': ["id", "name", "slug"]}, 'created_at', 'updated_at', 'name', 'description', 'description_text', 'description_html', 'network', 'identifier', 'emoji', 'icon_prop', 'module_view', 'cycle_view', 'issue_views_view', 'page_view', 'inbox_view', 'cover_image', 'archive_in', 'close_in', 'created_by', 'updated_by', 'workspace', 'default_assignee', 'project_lead', 'estimate', 'default_state', 'sort_order'],)
# return ProjectDetailSerializer
def get_queryset(self):
subquery = ProjectFavorite.objects.filter(
@ -216,7 +216,38 @@ class ProjectViewSet(BaseViewSet):
workspace = Workspace.objects.get(slug=slug)
serializer = ProjectSerializer(
data={**request.data}, context={"workspace_id": workspace.id}
data={**request.data},
fields=[
"id",
{"workspace_detail": ["id", "name", "slug"]},
"created_at",
"updated_at",
"name",
"description",
"description_text",
"description_html",
"network",
"identifier",
"emoji",
"icon_prop",
"module_view",
"cycle_view",
"issue_views_view",
"page_view",
"inbox_view",
"cover_image",
"archive_in",
"close_in",
"created_by",
"updated_by",
"workspace",
"default_assignee",
"project_lead",
"estimate",
"default_state",
"sort_order",
],
context={"workspace_id": workspace.id},
)
if serializer.is_valid():
serializer.save()
@ -330,6 +361,36 @@ class ProjectViewSet(BaseViewSet):
serializer = ProjectSerializer(
project,
data={**request.data},
fields=[
"id",
{"workspace_detail": ["id", "name", "slug"]},
"created_at",
"updated_at",
"name",
"description",
"description_text",
"description_html",
"network",
"identifier",
"emoji",
"icon_prop",
"module_view",
"cycle_view",
"issue_views_view",
"page_view",
"inbox_view",
"cover_image",
"archive_in",
"close_in",
"created_by",
"updated_by",
"workspace",
"default_assignee",
"project_lead",
"estimate",
"default_state",
"sort_order",
],
context={"workspace_id": workspace.id},
partial=True,
)
@ -1263,7 +1324,7 @@ class ProjectDeployBoardIssuesPublicEndpoint(BaseAPIView):
workspace__slug=slug, project_id=project_id
).values("id", "name", "color", "parent")
## Grouping the results
# Grouping the results
group_by = request.GET.get("group_by", False)
if group_by:
issues = group_results(issues, group_by)

View File

@ -147,7 +147,18 @@ class UserActivityEndpoint(BaseAPIView, BasePaginator):
request=request,
queryset=queryset,
on_results=lambda issue_activities: IssueActivitySerializer(
issue_activities, many=True
issue_activities,
nested_fields={
"actor_detail": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
},
many=True,
).data,
)
except Exception as e:

View File

@ -163,8 +163,8 @@ class WorkSpaceViewSet(BaseViewSet):
status=status.HTTP_400_BAD_REQUEST,
)
## Handling unique integrity error for now
## TODO: Extend this to handle other common errors which are not automatically handled by APIException
# Handling unique integrity error for now
# TODO: Extend this to handle other common errors which are not automatically handled by APIException
except IntegrityError as e:
if "already exists" in str(e):
return Response(
@ -299,7 +299,31 @@ class InviteWorkspaceEndpoint(BaseAPIView):
{
"error": "Some users are already member of workspace",
"workspace_users": WorkSpaceMemberSerializer(
workspace_members, many=True
workspace_members,
fields=[
"id",
"created_by",
"created_at",
"updated_at",
"updated_by",
"name",
"logo",
"owner",
"slug",
"organization_size",
{"workspace": ["id", "name", "slug"]},
{
"member": [
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
]
},
],
many=True,
).data,
},
status=status.HTTP_400_BAD_REQUEST,
@ -541,7 +565,7 @@ class UserWorkspaceInvitationsEndpoint(BaseViewSet):
class WorkSpaceMemberViewSet(BaseViewSet):
# serializer_class = WorkSpaceMemberSerializer
serializer_class = WorkSpaceMemberSerializer
model = WorkspaceMember
permission_classes = [
@ -590,7 +614,32 @@ class WorkSpaceMemberViewSet(BaseViewSet):
)
serializer = WorkSpaceMemberSerializer(
workspace_member, data=request.data, partial=True
workspace_member,
data=request.data,
partial=True,
fields=[
"id",
"created_by",
"created_at",
"updated_at",
"updated_by",
"name",
"logo",
"owner",
"slug",
"organization_size",
{"workspace": ["id", "name", "slug"]},
{
"member": [
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
]
},
],
)
if serializer.is_valid():
@ -724,7 +773,18 @@ class TeamMemberViewSet(BaseViewSet):
users = list(set(request.data.get("members", [])).difference(members))
users = User.objects.filter(pk__in=users)
serializer = UserSerializer(users, fields=('id', 'first_name',"last_name","avatar","is_bot","display_name"),many=True)
serializer = UserSerializer(
users,
fields=[
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
],
many=True,
)
return Response(
{
"error": f"{len(users)} of the member(s) are not a part of the workspace",
@ -790,15 +850,95 @@ class UserLastProjectWithWorkspaceEndpoint(BaseAPIView):
)
workspace = Workspace.objects.get(pk=last_workspace_id)
workspace_serializer = WorkSpaceSerializer(workspace)
# workspace_serializer = WorkSpaceSerializer(workspace, fields=("member": (fields: "displayname")))
workspace_serializer = WorkSpaceSerializer(
workspace,
fields=[
"id",
{
"owner": [
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
]
},
"created_at",
"updated_at",
"name",
"logo",
"slug",
"organization_size",
"created_by",
"updated_by",
],
)
project_member = ProjectMember.objects.filter(
workspace_id=last_workspace_id, member=request.user
).select_related("workspace", "project", "member", "workspace__owner")
project_member_serializer = ProjectMemberSerializer(
project_member, many=True
project_member,
fields=[
"id",
{
"workspace": [
"id",
{
"owner": [
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
]
},
"created_at",
"updated_at",
"name",
"logo",
"slug",
"organization_size",
"created_by",
"updated_by",
]
},
{
"project": [
"id",
"identifier",
"name",
"cover_image",
"icon_prop",
"emoji",
"description",
]
},
{
"member": [
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
]
},
"created_at",
"updated_at",
"comment",
"role",
"view_props",
"default_props",
"preferences",
"sort_order",
"created_by",
"updated_by",
],
many=True,
)
return Response(
@ -825,7 +965,32 @@ class WorkspaceMemberUserEndpoint(BaseAPIView):
workspace_member = WorkspaceMember.objects.get(
member=request.user, workspace__slug=slug
)
serializer = WorkSpaceMemberSerializer(workspace_member, fields=("member","workspace"), remove_nested_fields={"member": ("email",)})
serializer = WorkSpaceMemberSerializer(
workspace_member,
fields=[
"id",
"created_by",
"created_at",
"updated_at",
"updated_by",
"name",
"logo",
"owner",
"slug",
"organization_size",
{"workspace": ["id", "name", "slug"]},
{
"member": [
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
]
},
],
)
return Response(serializer.data, status=status.HTTP_200_OK)
except (Workspace.DoesNotExist, WorkspaceMember.DoesNotExist):
return Response({"error": "Forbidden"}, status=status.HTTP_403_FORBIDDEN)
@ -998,7 +1163,7 @@ class UserWorkspaceDashboardEndpoint(BaseAPIView):
workspace__slug=slug,
assignees__in=[request.user],
completed_at__isnull=True,
).values("id", "name", "workspace__slug", "project_id", "target_date")
).values("id", "name", "workspace__slug", "project_id", "start_date")
return Response(
{
@ -1209,7 +1374,18 @@ class WorkspaceUserActivityEndpoint(BaseAPIView):
request=request,
queryset=queryset,
on_results=lambda issue_activities: IssueActivitySerializer(
issue_activities, many=True
issue_activities,
nested_fields={
"actor_detail": (
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
)
},
many=True,
).data,
)
except Exception as e:
@ -1417,7 +1593,7 @@ class WorkspaceUserProfileIssuesEndpoint(BaseAPIView):
issues = IssueLiteSerializer(issue_queryset, many=True).data
## Grouping the results
# Grouping the results
group_by = request.GET.get("group_by", False)
if group_by:
return Response(
@ -1464,8 +1640,34 @@ class WorkspaceMembersEndpoint(BaseAPIView):
workspace__slug=slug,
member__is_bot=False,
).select_related("workspace", "member")
serialzier = WorkSpaceMemberSerializer(workspace_members, many=True)
return Response(serialzier.data, status=status.HTTP_200_OK)
serializer = WorkSpaceMemberSerializer(
workspace_members,
fields=[
"id",
"created_by",
"created_at",
"updated_at",
"updated_by",
"name",
"logo",
"owner",
"slug",
"organization_size",
{"workspace": ["id", "name", "slug"]},
{
"member": [
"id",
"first_name",
"last_name",
"avatar",
"is_bot",
"display_name",
]
},
],
many=True,
)
return Response(serializer.data, status=status.HTTP_200_OK)
except Exception as e:
capture_exception(e)
return Response(

View File

@ -161,7 +161,7 @@ def service_importer(service, importer_id):
if settings.PROXY_BASE_URL:
headers = {"Content-Type": "application/json"}
import_data_json = json.dumps(
ImporterSerializer(importer).data,
ImporterSerializer(importer,fields=["id","created_by","created_at","updated_at","updated_by","workspace","project","initiated_by","project_detail","workspace_detail","service","status","metadata","config","data","token","imported_data",{"initiated_by_detail":["id", "first_name", "last_name", "avatar", "is_bot", "display_name"]}]).data,
cls=DjangoJSONEncoder,
)
res = requests.post(

View File

@ -1103,7 +1103,7 @@ def issue_activity(
for issue_activity in issue_activities_created:
headers = {"Content-Type": "application/json"}
issue_activity_json = json.dumps(
IssueActivitySerializer(issue_activity).data,
IssueActivitySerializer(issue_activity,fields=[{"actor_detail":["id", "first_name", "last_name", "avatar", "is_bot", "display_name"]}]).data,
cls=DjangoJSONEncoder,
)
_ = requests.post(