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, ProjectMemberInviteSerializer,
ProjectIdentifierSerializer, ProjectIdentifierSerializer,
ProjectFavoriteSerializer, ProjectFavoriteSerializer,
ProjectLiteSerializer,
ProjectMemberLiteSerializer, ProjectMemberLiteSerializer,
ProjectDeployBoardSerializer, ProjectDeployBoardSerializer,
ProjectMemberAdminSerializer, ProjectMemberAdminSerializer,
@ -30,7 +29,7 @@ from .issue import (
IssuePropertySerializer, IssuePropertySerializer,
BlockerIssueSerializer, BlockerIssueSerializer,
BlockedIssueSerializer, BlockedIssueSerializer,
IssueAssigneeSerializer, # IssueAssigneeSerializer,
LabelSerializer, LabelSerializer,
IssueSerializer, IssueSerializer,
IssueFlatSerializer, IssueFlatSerializer,

View File

@ -1,5 +1,22 @@
from rest_framework import serializers 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): class BaseSerializer(serializers.ModelSerializer):
id = serializers.PrimaryKeyRelatedField(read_only=True) id = serializers.PrimaryKeyRelatedField(read_only=True)
@ -7,18 +24,10 @@ class BaseSerializer(serializers.ModelSerializer):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
# Don't pass the 'fields' arg up to the superclass # Don't pass the 'fields' arg up to the superclass
fields = kwargs.pop("fields", None) fields = kwargs.pop("fields", None)
remove_nested_fields = kwargs.pop("remove_nested_fields", None)
# Instantiate the superclass normally # Instantiate the superclass normally
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
if fields is not None: if fields is not None:
# Drop any fields that are not specified in the `fields` argument. # Drop any fields that are not specified in the `fields` argument.
allowed = set(fields) self.fields = filterFields(self, 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)

View File

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

View File

@ -2,7 +2,7 @@
from .base import BaseSerializer from .base import BaseSerializer
from plane.db.models import Estimate, EstimatePoint from plane.db.models import Estimate, EstimatePoint
from plane.api.serializers import WorkSpaceSerializer, ProjectLiteSerializer from plane.api.serializers import WorkSpaceSerializer, ProjectSerializer
class EstimateSerializer(BaseSerializer): class EstimateSerializer(BaseSerializer):
@ -11,7 +11,7 @@ class EstimateSerializer(BaseSerializer):
fields=("id", "name", "slug"), fields=("id", "name", "slug"),
read_only=True, 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: class Meta:
model = Estimate model = Estimate
@ -40,7 +40,7 @@ class EstimateReadSerializer(BaseSerializer):
fields=("id", "name", "slug"), fields=("id", "name", "slug"),
read_only=True, 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: class Meta:
model = Estimate model = Estimate

View File

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

View File

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

View File

@ -4,15 +4,14 @@ from rest_framework import serializers
# Module imports # Module imports
from .base import BaseSerializer from .base import BaseSerializer
from .issue import IssueFlatSerializer, LabelLiteSerializer from .issue import IssueFlatSerializer, LabelLiteSerializer
from .project import ProjectLiteSerializer from .project import ProjectSerializer
from .state import StateLiteSerializer from .state import StateLiteSerializer
from .project import ProjectLiteSerializer
from .user import UserSerializer from .user import UserSerializer
from plane.db.models import Inbox, InboxIssue, Issue from plane.db.models import Inbox, InboxIssue, Issue
class InboxSerializer(BaseSerializer): 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) pending_issue_count = serializers.IntegerField(read_only=True)
class Meta: class Meta:
@ -26,7 +25,7 @@ class InboxSerializer(BaseSerializer):
class InboxIssueSerializer(BaseSerializer): class InboxIssueSerializer(BaseSerializer):
issue_detail = IssueFlatSerializer(source="issue", read_only=True) 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: class Meta:
model = InboxIssue model = InboxIssue
@ -46,14 +45,9 @@ class InboxIssueLiteSerializer(BaseSerializer):
class IssueStateInboxSerializer(BaseSerializer): class IssueStateInboxSerializer(BaseSerializer):
state_detail = StateLiteSerializer(read_only=True, source="state") 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) label_details = LabelLiteSerializer(read_only=True, source="labels", many=True)
assignee_details = UserSerializer( assignee_details = UserSerializer(source="assignees", read_only=True, many=True)
source="assignees",
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
read_only=True,
many=True,
)
sub_issues_count = serializers.IntegerField(read_only=True) sub_issues_count = serializers.IntegerField(read_only=True)
bridge_id = serializers.UUIDField(read_only=True) bridge_id = serializers.UUIDField(read_only=True)
issue_inbox = InboxIssueLiteSerializer(read_only=True, many=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 .base import BaseSerializer
from .user import UserSerializer from .user import UserSerializer
from .state import StateSerializer, StateLiteSerializer from .state import StateSerializer, StateLiteSerializer
from .project import ProjectSerializer, ProjectLiteSerializer from .project import ProjectSerializer
from .workspace import WorkSpaceSerializer from .workspace import WorkSpaceSerializer
from plane.db.models import ( from plane.db.models import (
User, User,
@ -53,7 +53,7 @@ class IssueFlatSerializer(BaseSerializer):
class IssueProjectLiteSerializer(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: class Meta:
model = Issue model = Issue
@ -70,12 +70,8 @@ class IssueProjectLiteSerializer(BaseSerializer):
## Find a better approach to save manytomany? ## Find a better approach to save manytomany?
class IssueCreateSerializer(BaseSerializer): class IssueCreateSerializer(BaseSerializer):
state_detail = StateSerializer(read_only=True, source="state") state_detail = StateSerializer(read_only=True, source="state")
created_by_detail = UserSerializer( created_by_detail = UserSerializer(source="created_by", read_only=True,)
source="created_by", project_detail = ProjectSerializer(source="project", fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
read_only=True,
)
project_detail = ProjectLiteSerializer(read_only=True, source="project")
workspace_detail = WorkSpaceSerializer( workspace_detail = WorkSpaceSerializer(
source="workspace", source="workspace",
fields=("id", "name", "slug"), fields=("id", "name", "slug"),
@ -307,47 +303,15 @@ class IssueCreateSerializer(BaseSerializer):
class IssueActivitySerializer(BaseSerializer): class IssueActivitySerializer(BaseSerializer):
actor_detail = UserSerializer( actor_detail = UserSerializer(source="actor", read_only=True)
source="actor",
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
read_only=True,
)
issue_detail = IssueFlatSerializer(read_only=True, source="issue") 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: class Meta:
model = IssueActivity model = IssueActivity
fields = "__all__" 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 IssuePropertySerializer(BaseSerializer):
class Meta: class Meta:
model = IssueProperty model = IssueProperty
@ -363,7 +327,7 @@ class LabelSerializer(BaseSerializer):
workspace_detail = WorkSpaceSerializer( workspace_detail = WorkSpaceSerializer(
source="workspace", fields=("id", "name", "slug"), read_only=True 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: class Meta:
model = Label model = Label
@ -424,16 +388,16 @@ class BlockerIssueSerializer(BaseSerializer):
read_only_fields = fields read_only_fields = fields
class IssueAssigneeSerializer(BaseSerializer): # class IssueAssigneeSerializer(BaseSerializer):
assignee_details = UserSerializer( # assignee_details = UserSerializer(
source="assignee", # source="assignee",
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, # read_only=True,
) # )
class Meta: # class Meta:
model = IssueAssignee # model = IssueAssignee
fields = "__all__" # fields = "__all__"
class CycleBaseSerializer(BaseSerializer): class CycleBaseSerializer(BaseSerializer):
@ -603,13 +567,9 @@ class IssueVoteSerializer(BaseSerializer):
class IssueCommentSerializer(BaseSerializer): class IssueCommentSerializer(BaseSerializer):
actor_detail = UserSerializer( actor_detail = UserSerializer(source="actor", read_only=True)
source="actor",
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
read_only=True,
)
issue_detail = IssueFlatSerializer(read_only=True, source="issue") 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( workspace_details = WorkSpaceSerializer(
source="workspace", source="workspace",
@ -635,7 +595,7 @@ class IssueCommentSerializer(BaseSerializer):
class IssueStateFlatSerializer(BaseSerializer): class IssueStateFlatSerializer(BaseSerializer):
state_detail = StateLiteSerializer(read_only=True, source="state") 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: class Meta:
model = Issue model = Issue
@ -652,7 +612,7 @@ class IssueStateFlatSerializer(BaseSerializer):
class IssueStateSerializer(BaseSerializer): class IssueStateSerializer(BaseSerializer):
label_details = LabelLiteSerializer(read_only=True, source="labels", many=True) label_details = LabelLiteSerializer(read_only=True, source="labels", many=True)
state_detail = StateLiteSerializer(read_only=True, source="state") 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( assignee_details = UserSerializer(
source="assignees", source="assignees",
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"), fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"),
@ -670,7 +630,7 @@ class IssueStateSerializer(BaseSerializer):
class IssueSerializer(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") state_detail = StateSerializer(read_only=True, source="state")
parent_detail = IssueStateFlatSerializer(read_only=True, source="parent") parent_detail = IssueStateFlatSerializer(read_only=True, source="parent")
label_details = LabelSerializer(read_only=True, source="labels", many=True) label_details = LabelSerializer(read_only=True, source="labels", many=True)
@ -710,7 +670,7 @@ class IssueLiteSerializer(BaseSerializer):
fields=("id", "name", "slug"), fields=("id", "name", "slug"),
read_only=True, 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") state_detail = StateLiteSerializer(read_only=True, source="state")
label_details = LabelLiteSerializer(read_only=True, source="labels", many=True) label_details = LabelLiteSerializer(read_only=True, source="labels", many=True)
assignee_details = UserSerializer( assignee_details = UserSerializer(

View File

@ -4,7 +4,7 @@ from rest_framework import serializers
# Module imports # Module imports
from .base import BaseSerializer from .base import BaseSerializer
from .user import UserSerializer from .user import UserSerializer
from .project import ProjectSerializer, ProjectLiteSerializer from .project import ProjectSerializer
from .workspace import WorkSpaceSerializer from .workspace import WorkSpaceSerializer
from .issue import IssueStateSerializer from .issue import IssueStateSerializer
@ -25,7 +25,7 @@ class ModuleWriteSerializer(BaseSerializer):
required=False, 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( workspace_detail = WorkSpaceSerializer(
source="workspace", source="workspace",
fields=("id", "name", "slug"), fields=("id", "name", "slug"),
@ -110,7 +110,7 @@ class ModuleFlatSerializer(BaseSerializer):
class ModuleIssueSerializer(BaseSerializer): class ModuleIssueSerializer(BaseSerializer):
module_detail = ModuleFlatSerializer(read_only=True, source="module") 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) sub_issues_count = serializers.IntegerField(read_only=True)
class Meta: class Meta:
@ -159,7 +159,7 @@ class ModuleLinkSerializer(BaseSerializer):
class ModuleSerializer(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( lead_detail = UserSerializer(
source="lead", source="lead",
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name"), 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 .base import BaseSerializer
from .issue import IssueFlatSerializer, LabelLiteSerializer from .issue import IssueFlatSerializer, LabelLiteSerializer
from .workspace import WorkSpaceSerializer from .workspace import WorkSpaceSerializer
from .project import ProjectLiteSerializer from .project import ProjectSerializer
from plane.db.models import Page, PageBlock, PageFavorite, PageLabel, Label from plane.db.models import Page, PageBlock, PageFavorite, PageLabel, Label
class PageBlockSerializer(BaseSerializer): class PageBlockSerializer(BaseSerializer):
issue_detail = IssueFlatSerializer(source="issue", read_only=True) 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( workspace_detail = WorkSpaceSerializer(
source="workspace", source="workspace",
fields=("id", "name", "slug"), fields=("id", "name", "slug"),
@ -43,7 +43,7 @@ class PageSerializer(BaseSerializer):
required=False, required=False,
) )
blocks = PageBlockLiteSerializer(read_only=True, many=True) 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( workspace_detail = WorkSpaceSerializer(
source="workspace", source="workspace",
fields=("id", "name", "slug"), fields=("id", "name", "slug"),

View File

@ -19,9 +19,26 @@ from plane.db.models import (
class ProjectSerializer(BaseSerializer): 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( workspace_detail = WorkSpaceSerializer(
source="workspace", source="workspace",
fields=("id", "name", "slug"), # fields=("id", "name", "slug"),
read_only=True, read_only=True,
) )
@ -82,21 +99,6 @@ class ProjectSerializer(BaseSerializer):
raise serializers.ValidationError(detail="Project Identifier is already taken") 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): class ProjectDetailSerializer(BaseSerializer):
workspace = WorkSpaceSerializer(read_only=True) workspace = WorkSpaceSerializer(read_only=True)
default_assignee = UserSerializer( default_assignee = UserSerializer(
@ -123,7 +125,7 @@ class ProjectDetailSerializer(BaseSerializer):
class ProjectMemberSerializer(BaseSerializer): class ProjectMemberSerializer(BaseSerializer):
workspace = WorkSpaceSerializer(read_only=True) 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( member = 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, read_only=True,
@ -140,7 +142,7 @@ class ProjectMemberAdminSerializer(BaseSerializer):
fields=("id", "name", "slug"), fields=("id", "name", "slug"),
read_only=True, read_only=True,
) )
project = ProjectLiteSerializer(read_only=True) project = ProjectSerializer(fields=("id", "name", "cover_image", "icon_prop", "emoji", "description"), read_only=True)
member = UserSerializer( member = UserSerializer(
fields=( fields=(
"id", "id",
@ -160,7 +162,7 @@ class ProjectMemberAdminSerializer(BaseSerializer):
class ProjectMemberInviteSerializer(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( workspace = WorkSpaceSerializer(
fields=("id", "name", "slug"), fields=("id", "name", "slug"),
read_only=True, read_only=True,
@ -178,7 +180,7 @@ class ProjectIdentifierSerializer(BaseSerializer):
class ProjectFavoriteSerializer(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: class Meta:
model = ProjectFavorite model = ProjectFavorite
@ -203,7 +205,7 @@ class ProjectMemberLiteSerializer(BaseSerializer):
class ProjectDeployBoardSerializer(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( workspace_detail = WorkSpaceSerializer(
source="workspace", source="workspace",
fields=("id", "name", "slug"), fields=("id", "name", "slug"),

View File

@ -1,7 +1,7 @@
# Module imports # Module imports
from .base import BaseSerializer from .base import BaseSerializer
from .workspace import WorkSpaceSerializer from .workspace import WorkSpaceSerializer
from .project import ProjectLiteSerializer from .project import ProjectSerializer
from plane.db.models import State from plane.db.models import State
@ -12,7 +12,7 @@ class StateSerializer(BaseSerializer):
fields=("id", "name", "slug"), fields=("id", "name", "slug"),
read_only=True, 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: class Meta:
model = State model = State

View File

@ -4,14 +4,14 @@ from rest_framework import serializers
# Module imports # Module imports
from .base import BaseSerializer from .base import BaseSerializer
from .workspace import WorkSpaceSerializer from .workspace import WorkSpaceSerializer
from .project import ProjectLiteSerializer from .project import ProjectSerializer
from plane.db.models import IssueView, IssueViewFavorite from plane.db.models import IssueView, IssueViewFavorite
from plane.utils.issue_filters import issue_filters from plane.utils.issue_filters import issue_filters
class IssueViewSerializer(BaseSerializer): class IssueViewSerializer(BaseSerializer):
is_favorite = serializers.BooleanField(read_only=True) 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( workspace_detail = WorkSpaceSerializer(
source="workspace", source="workspace",
fields=("id", "name", "slug"), fields=("id", "name", "slug"),

View File

@ -18,7 +18,7 @@ from plane.db.models import (
class WorkSpaceSerializer(BaseSerializer): class WorkSpaceSerializer(BaseSerializer):
owner = UserSerializer( 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, read_only=True,
) )
total_members = serializers.IntegerField(read_only=True) total_members = serializers.IntegerField(read_only=True)
@ -37,7 +37,6 @@ class WorkSpaceSerializer(BaseSerializer):
] ]
class WorkSpaceMemberSerializer(BaseSerializer): class WorkSpaceMemberSerializer(BaseSerializer):
member = UserSerializer( member = UserSerializer(
fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name" ,"email"), fields=("id", "first_name", "last_name", "avatar", "is_bot", "display_name" ,"email"),
@ -53,30 +52,6 @@ class WorkSpaceMemberSerializer(BaseSerializer):
fields = "__all__" 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): class WorkSpaceMemberInviteSerializer(BaseSerializer):
workspace = WorkSpaceSerializer(read_only=True) workspace = WorkSpaceSerializer(read_only=True)
total_members = serializers.IntegerField(read_only=True) total_members = serializers.IntegerField(read_only=True)

View File

@ -56,6 +56,10 @@ class CycleViewSet(BaseViewSet):
permission_classes = [ permission_classes = [
ProjectEntityPermission, 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): def perform_create(self, serializer):
serializer.save( serializer.save(
@ -148,13 +152,15 @@ class CycleViewSet(BaseViewSet):
.prefetch_related( .prefetch_related(
Prefetch( Prefetch(
"issue_cycle__issue__assignees", "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_related(
Prefetch( Prefetch(
"issue_cycle__issue__labels", "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") .order_by("-is_favorite", "name")
@ -172,7 +178,8 @@ class CycleViewSet(BaseViewSet):
# All Cycles # All Cycles
if cycle_view == "all": if cycle_view == "all":
return Response( 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 # Current Cycle
@ -182,7 +189,8 @@ class CycleViewSet(BaseViewSet):
end_date__gte=timezone.now(), 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): if len(data):
assignee_distribution = ( assignee_distribution = (
@ -256,14 +264,16 @@ class CycleViewSet(BaseViewSet):
if cycle_view == "upcoming": if cycle_view == "upcoming":
queryset = queryset.filter(start_date__gt=timezone.now()) queryset = queryset.filter(start_date__gt=timezone.now())
return Response( 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 # Completed Cycles
if cycle_view == "completed": if cycle_view == "completed":
queryset = queryset.filter(end_date__lt=timezone.now()) queryset = queryset.filter(end_date__lt=timezone.now())
return Response( 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 # Draft Cycles
@ -274,16 +284,19 @@ class CycleViewSet(BaseViewSet):
) )
return Response( 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 # Incomplete Cycles
if cycle_view == "incomplete": if cycle_view == "incomplete":
queryset = queryset.filter( 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( 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( return Response(
@ -306,7 +319,8 @@ class CycleViewSet(BaseViewSet):
request.data.get("start_date", None) is not None request.data.get("start_date", None) is not None
and request.data.get("end_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(): if serializer.is_valid():
serializer.save( serializer.save(
project_id=project_id, project_id=project_id,
@ -342,7 +356,8 @@ class CycleViewSet(BaseViewSet):
status=status.HTTP_400_BAD_REQUEST, 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(): if serializer.is_valid():
serializer.save() serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.data, status=status.HTTP_200_OK)
@ -418,7 +433,8 @@ class CycleViewSet(BaseViewSet):
.order_by("label_name") .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"] = { data["distribution"] = {
"assignees": assignee_distribution, "assignees": assignee_distribution,
"labels": label_distribution, "labels": label_distribution,
@ -486,7 +502,8 @@ class CycleIssueViewSet(BaseViewSet):
super() super()
.get_queryset() .get_queryset()
.annotate( .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() .order_by()
.annotate(count=Func(F("id"), function="Count")) .annotate(count=Func(F("id"), function="Count"))
.values("count") .values("count")
@ -512,7 +529,8 @@ class CycleIssueViewSet(BaseViewSet):
issues = ( issues = (
Issue.issue_objects.filter(issue_cycle__cycle_id=cycle_id) Issue.issue_objects.filter(issue_cycle__cycle_id=cycle_id)
.annotate( .annotate(
sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id")) sub_issues_count=Issue.issue_objects.filter(
parent=OuterRef("id"))
.order_by() .order_by()
.annotate(count=Func(F("id"), function="Count")) .annotate(count=Func(F("id"), function="Count"))
.values("count") .values("count")

View File

@ -23,11 +23,11 @@ class ExportIssuesEndpoint(BaseAPIView):
try: try:
# Get the workspace # Get the workspace
workspace = Workspace.objects.get(slug=slug) workspace = Workspace.objects.get(slug=slug)
provider = request.data.get("provider", False) provider = request.data.get("provider", False)
multiple = request.data.get("multiple", False) multiple = request.data.get("multiple", False)
project_ids = request.data.get("project", []) project_ids = request.data.get("project", [])
if provider in ["csv", "xlsx", "json"]: if provider in ["csv", "xlsx", "json"]:
if not project_ids: if not project_ids:
project_ids = Project.objects.filter( project_ids = Project.objects.filter(
@ -77,14 +77,38 @@ class ExportIssuesEndpoint(BaseAPIView):
try: try:
exporter_history = ExporterHistory.objects.filter( exporter_history = ExporterHistory.objects.filter(
workspace__slug=slug 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): if request.GET.get("per_page", False) and request.GET.get("cursor", False):
return self.paginate( return self.paginate(
request=request, request=request,
queryset=exporter_history, queryset=exporter_history,
on_results=lambda exporter_history: ExporterHistorySerializer( 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, ).data,
) )
else: else:

View File

@ -14,7 +14,7 @@ from django.conf import settings
from .base import BaseAPIView from .base import BaseAPIView
from plane.api.permissions import ProjectEntityPermission from plane.api.permissions import ProjectEntityPermission
from plane.db.models import Workspace, Project from plane.db.models import Workspace, Project
from plane.api.serializers import ProjectLiteSerializer, WorkSpaceSerializer from plane.api.serializers import ProjectSerializer, WorkSpaceSerializer
class GPTIntegrationEndpoint(BaseAPIView): class GPTIntegrationEndpoint(BaseAPIView):
@ -57,10 +57,25 @@ class GPTIntegrationEndpoint(BaseAPIView):
{ {
"response": text, "response": text,
"response_html": text_html, "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_detail": WorkSpaceSerializer(
workspace, workspace,
fields=("id", "name", "slug"), fields=["id", "name", "slug"],
).data, ).data,
}, },
status=status.HTTP_200_OK, status=status.HTTP_200_OK,

View File

@ -177,7 +177,36 @@ class ImportServiceEndpoint(BaseAPIView):
) )
service_importer.delay(service, importer.id) 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(serializer.data, status=status.HTTP_201_CREATED)
if service == "jira": if service == "jira":
@ -213,7 +242,36 @@ class ImportServiceEndpoint(BaseAPIView):
) )
service_importer.delay(service, importer.id) 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(serializer.data, status=status.HTTP_201_CREATED)
return Response( return Response(
@ -243,7 +301,39 @@ class ImportServiceEndpoint(BaseAPIView):
.order_by("-created_at") .order_by("-created_at")
.select_related("initiated_by", "project", "workspace") .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) return Response(serializer.data)
except Exception as e: except Exception as e:
capture_exception(e) capture_exception(e)
@ -284,7 +374,40 @@ class ImportServiceEndpoint(BaseAPIView):
importer = Importer.objects.get( importer = Importer.objects.get(
pk=pk, service=service, workspace__slug=slug 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(): if serializer.is_valid():
serializer.save() serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK) 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( return Response(
issues_data, issues_data,
status=status.HTTP_200_OK, status=status.HTTP_200_OK,
@ -222,7 +237,19 @@ class InboxIssueViewSet(BaseViewSet):
source=request.data.get("source", "in-app"), 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) return Response(serializer.data, status=status.HTTP_200_OK)
except Exception as e: except Exception as e:
capture_exception(e) capture_exception(e)
@ -237,10 +264,17 @@ class InboxIssueViewSet(BaseViewSet):
pk=pk, workspace__slug=slug, project_id=project_id, inbox_id=inbox_id pk=pk, workspace__slug=slug, project_id=project_id, inbox_id=inbox_id
) )
# Get the project member # 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 # 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): if project_member.role <= 10 and str(inbox_issue.created_by_id) != str(
return Response({"error": "You cannot edit inbox issues"}, status=status.HTTP_400_BAD_REQUEST) request.user.id
):
return Response(
{"error": "You cannot edit inbox issues"},
status=status.HTTP_400_BAD_REQUEST,
)
# Get issue data # Get issue data
issue_data = request.data.pop("issue", False) issue_data = request.data.pop("issue", False)
@ -251,15 +285,29 @@ class InboxIssueViewSet(BaseViewSet):
) )
# Only allow guests and viewers to edit name and description # Only allow guests and viewers to edit name and description
if project_member.role <= 10: if project_member.role <= 10:
# viewers and guests since only viewers and guests # viewers and guests since only viewers and guests
issue_data = { issue_data = {
"name": issue_data.get("name", issue.name), "name": issue_data.get("name", issue.name),
"description_html": issue_data.get("description_html", issue.description_html), "description_html": issue_data.get(
"description": issue_data.get("description", issue.description) "description_html", issue.description_html
),
"description": issue_data.get("description", issue.description),
} }
issue_serializer = IssueCreateSerializer( 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(): if issue_serializer.is_valid():
@ -300,7 +348,9 @@ class InboxIssueViewSet(BaseViewSet):
project_id=project_id, project_id=project_id,
) )
state = State.objects.filter( state = State.objects.filter(
group="cancelled", workspace__slug=slug, project_id=project_id group="cancelled",
workspace__slug=slug,
project_id=project_id,
).first() ).first()
if state is not None: if state is not None:
issue.state = state issue.state = state
@ -318,7 +368,9 @@ class InboxIssueViewSet(BaseViewSet):
if issue.state.name == "Triage": if issue.state.name == "Triage":
# Move to default state # Move to default state
state = State.objects.filter( state = State.objects.filter(
workspace__slug=slug, project_id=project_id, default=True workspace__slug=slug,
project_id=project_id,
default=True,
).first() ).first()
if state is not None: if state is not None:
issue.state = state issue.state = state
@ -327,7 +379,9 @@ class InboxIssueViewSet(BaseViewSet):
return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else: 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: except InboxIssue.DoesNotExist:
return Response( return Response(
{"error": "Inbox Issue does not exist"}, {"error": "Inbox Issue does not exist"},
@ -348,7 +402,19 @@ class InboxIssueViewSet(BaseViewSet):
issue = Issue.objects.get( issue = Issue.objects.get(
pk=inbox_issue.issue_id, workspace__slug=slug, project_id=project_id 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) return Response(serializer.data, status=status.HTTP_200_OK)
except Exception as e: except Exception as e:
capture_exception(e) capture_exception(e)
@ -363,15 +429,25 @@ class InboxIssueViewSet(BaseViewSet):
pk=pk, workspace__slug=slug, project_id=project_id, inbox_id=inbox_id pk=pk, workspace__slug=slug, project_id=project_id, inbox_id=inbox_id
) )
# Get the project member # 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): if project_member.role <= 10 and str(inbox_issue.created_by_id) != str(
return Response({"error": "You cannot delete inbox issue"}, status=status.HTTP_400_BAD_REQUEST) request.user.id
):
return Response(
{"error": "You cannot delete inbox issue"},
status=status.HTTP_400_BAD_REQUEST,
)
inbox_issue.delete() inbox_issue.delete()
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)
except InboxIssue.DoesNotExist: 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: except Exception as e:
capture_exception(e) capture_exception(e)
return Response( return Response(
@ -389,7 +465,10 @@ class InboxIssuePublicViewSet(BaseViewSet):
] ]
def get_queryset(self): 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: if project_deploy_board is not None:
return self.filter_queryset( return self.filter_queryset(
super() super()
@ -407,9 +486,14 @@ class InboxIssuePublicViewSet(BaseViewSet):
def list(self, request, slug, project_id, inbox_id): def list(self, request, slug, project_id, inbox_id):
try: 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: 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") filters = issue_filters(request.query_params, "GET")
issues = ( 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( return Response(
issues_data, issues_data,
status=status.HTTP_200_OK, status=status.HTTP_200_OK,
) )
except ProjectDeployBoard.DoesNotExist: 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: except Exception as e:
capture_exception(e) capture_exception(e)
return Response( return Response(
@ -468,9 +568,14 @@ class InboxIssuePublicViewSet(BaseViewSet):
def create(self, request, slug, project_id, inbox_id): def create(self, request, slug, project_id, inbox_id):
try: 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: 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): if not request.data.get("issue", {}).get("name", False):
return Response( return Response(
@ -527,7 +632,19 @@ class InboxIssuePublicViewSet(BaseViewSet):
source=request.data.get("source", "in-app"), 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) return Response(serializer.data, status=status.HTTP_200_OK)
except Exception as e: except Exception as e:
capture_exception(e) capture_exception(e)
@ -538,33 +655,54 @@ class InboxIssuePublicViewSet(BaseViewSet):
def partial_update(self, request, slug, project_id, inbox_id, pk): def partial_update(self, request, slug, project_id, inbox_id, pk):
try: 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: 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( inbox_issue = InboxIssue.objects.get(
pk=pk, workspace__slug=slug, project_id=project_id, inbox_id=inbox_id pk=pk, workspace__slug=slug, project_id=project_id, inbox_id=inbox_id
) )
# Get the project member # Get the project member
if str(inbox_issue.created_by_id) != str(request.user.id): 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 # Get issue data
issue_data = request.data.pop("issue", False) issue_data = request.data.pop("issue", False)
issue = Issue.objects.get( issue = Issue.objects.get(
pk=inbox_issue.issue_id, workspace__slug=slug, project_id=project_id 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 = { issue_data = {
"name": issue_data.get("name", issue.name), "name": issue_data.get("name", issue.name),
"description_html": issue_data.get("description_html", issue.description_html), "description_html": issue_data.get(
"description": issue_data.get("description", issue.description) "description_html", issue.description_html
),
"description": issue_data.get("description", issue.description),
} }
issue_serializer = IssueCreateSerializer( 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(): if issue_serializer.is_valid():
@ -600,17 +738,34 @@ class InboxIssuePublicViewSet(BaseViewSet):
def retrieve(self, request, slug, project_id, inbox_id, pk): def retrieve(self, request, slug, project_id, inbox_id, pk):
try: 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: 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( inbox_issue = InboxIssue.objects.get(
pk=pk, workspace__slug=slug, project_id=project_id, inbox_id=inbox_id pk=pk, workspace__slug=slug, project_id=project_id, inbox_id=inbox_id
) )
issue = Issue.objects.get( issue = Issue.objects.get(
pk=inbox_issue.issue_id, workspace__slug=slug, project_id=project_id 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) return Response(serializer.data, status=status.HTTP_200_OK)
except Exception as e: except Exception as e:
capture_exception(e) capture_exception(e)
@ -621,25 +776,35 @@ class InboxIssuePublicViewSet(BaseViewSet):
def destroy(self, request, slug, project_id, inbox_id, pk): def destroy(self, request, slug, project_id, inbox_id, pk):
try: 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: 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( inbox_issue = InboxIssue.objects.get(
pk=pk, workspace__slug=slug, project_id=project_id, inbox_id=inbox_id pk=pk, workspace__slug=slug, project_id=project_id, inbox_id=inbox_id
) )
if str(inbox_issue.created_by_id) != str(request.user.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() inbox_issue.delete()
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)
except InboxIssue.DoesNotExist: 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: except Exception as e:
capture_exception(e) capture_exception(e)
return Response( return Response(
{"error": "Something went wrong please try again later"}, {"error": "Something went wrong please try again later"},
status=status.HTTP_400_BAD_REQUEST, status=status.HTTP_400_BAD_REQUEST,
) )

View File

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

View File

@ -91,10 +91,10 @@ class ProjectViewSet(BaseViewSet):
ProjectBasePermission, ProjectBasePermission,
] ]
def get_serializer_class(self, *args, **kwargs): # def get_serializer_class(self, *args, **kwargs):
if self.action == "update" or self.action == "partial_update": # if self.action == "update" or self.action == "partial_update":
return ProjectSerializer # 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 # return ProjectDetailSerializer
def get_queryset(self): def get_queryset(self):
subquery = ProjectFavorite.objects.filter( subquery = ProjectFavorite.objects.filter(
@ -216,7 +216,38 @@ class ProjectViewSet(BaseViewSet):
workspace = Workspace.objects.get(slug=slug) workspace = Workspace.objects.get(slug=slug)
serializer = ProjectSerializer( 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(): if serializer.is_valid():
serializer.save() serializer.save()
@ -330,6 +361,36 @@ class ProjectViewSet(BaseViewSet):
serializer = ProjectSerializer( serializer = ProjectSerializer(
project, project,
data={**request.data}, 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}, context={"workspace_id": workspace.id},
partial=True, partial=True,
) )
@ -1263,7 +1324,7 @@ class ProjectDeployBoardIssuesPublicEndpoint(BaseAPIView):
workspace__slug=slug, project_id=project_id workspace__slug=slug, project_id=project_id
).values("id", "name", "color", "parent") ).values("id", "name", "color", "parent")
## Grouping the results # Grouping the results
group_by = request.GET.get("group_by", False) group_by = request.GET.get("group_by", False)
if group_by: if group_by:
issues = group_results(issues, group_by) issues = group_results(issues, group_by)

View File

@ -147,7 +147,18 @@ class UserActivityEndpoint(BaseAPIView, BasePaginator):
request=request, request=request,
queryset=queryset, queryset=queryset,
on_results=lambda issue_activities: IssueActivitySerializer( 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, ).data,
) )
except Exception as e: except Exception as e:

View File

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

View File

@ -161,7 +161,7 @@ def service_importer(service, importer_id):
if settings.PROXY_BASE_URL: if settings.PROXY_BASE_URL:
headers = {"Content-Type": "application/json"} headers = {"Content-Type": "application/json"}
import_data_json = json.dumps( 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, cls=DjangoJSONEncoder,
) )
res = requests.post( res = requests.post(

View File

@ -1103,7 +1103,7 @@ def issue_activity(
for issue_activity in issue_activities_created: for issue_activity in issue_activities_created:
headers = {"Content-Type": "application/json"} headers = {"Content-Type": "application/json"}
issue_activity_json = json.dumps( 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, cls=DjangoJSONEncoder,
) )
_ = requests.post( _ = requests.post(