mirror of
https://github.com/makeplane/plane.git
synced 2026-07-13 14:01:45 +02:00
fix: work item external api endpoint fix (#3785)
This commit is contained in:
committed by
GitHub
parent
a60e88768d
commit
98a6ff254e
@@ -153,74 +153,6 @@ from plane.ee.bgtasks.entity_issue_state_progress_task import (
|
||||
entity_issue_state_activity_task,
|
||||
)
|
||||
|
||||
from plane.utils.openapi import (
|
||||
work_item_docs,
|
||||
label_docs,
|
||||
issue_link_docs,
|
||||
issue_comment_docs,
|
||||
issue_activity_docs,
|
||||
issue_attachment_docs,
|
||||
WORKSPACE_SLUG_PARAMETER,
|
||||
PROJECT_IDENTIFIER_PARAMETER,
|
||||
ISSUE_IDENTIFIER_PARAMETER,
|
||||
PROJECT_ID_PARAMETER,
|
||||
ISSUE_ID_PARAMETER,
|
||||
LABEL_ID_PARAMETER,
|
||||
COMMENT_ID_PARAMETER,
|
||||
LINK_ID_PARAMETER,
|
||||
ATTACHMENT_ID_PARAMETER,
|
||||
ACTIVITY_ID_PARAMETER,
|
||||
PROJECT_ID_QUERY_PARAMETER,
|
||||
CURSOR_PARAMETER,
|
||||
PER_PAGE_PARAMETER,
|
||||
EXTERNAL_ID_PARAMETER,
|
||||
EXTERNAL_SOURCE_PARAMETER,
|
||||
ORDER_BY_PARAMETER,
|
||||
SEARCH_PARAMETER,
|
||||
SEARCH_PARAMETER_REQUIRED,
|
||||
LIMIT_PARAMETER,
|
||||
WORKSPACE_SEARCH_PARAMETER,
|
||||
FIELDS_PARAMETER,
|
||||
EXPAND_PARAMETER,
|
||||
create_paginated_response,
|
||||
# Request Examples
|
||||
ISSUE_CREATE_EXAMPLE,
|
||||
ISSUE_UPDATE_EXAMPLE,
|
||||
ISSUE_UPSERT_EXAMPLE,
|
||||
LABEL_CREATE_EXAMPLE,
|
||||
LABEL_UPDATE_EXAMPLE,
|
||||
ISSUE_LINK_CREATE_EXAMPLE,
|
||||
ISSUE_LINK_UPDATE_EXAMPLE,
|
||||
ISSUE_COMMENT_CREATE_EXAMPLE,
|
||||
ISSUE_COMMENT_UPDATE_EXAMPLE,
|
||||
ISSUE_ATTACHMENT_UPLOAD_EXAMPLE,
|
||||
ATTACHMENT_UPLOAD_CONFIRM_EXAMPLE,
|
||||
# Response Examples
|
||||
ISSUE_EXAMPLE,
|
||||
LABEL_EXAMPLE,
|
||||
ISSUE_LINK_EXAMPLE,
|
||||
ISSUE_COMMENT_EXAMPLE,
|
||||
ISSUE_ATTACHMENT_EXAMPLE,
|
||||
ISSUE_ATTACHMENT_NOT_UPLOADED_EXAMPLE,
|
||||
ISSUE_SEARCH_EXAMPLE,
|
||||
WORK_ITEM_NOT_FOUND_RESPONSE,
|
||||
ISSUE_NOT_FOUND_RESPONSE,
|
||||
PROJECT_NOT_FOUND_RESPONSE,
|
||||
EXTERNAL_ID_EXISTS_RESPONSE,
|
||||
DELETED_RESPONSE,
|
||||
ADMIN_ONLY_RESPONSE,
|
||||
LABEL_NOT_FOUND_RESPONSE,
|
||||
LABEL_NAME_EXISTS_RESPONSE,
|
||||
INVALID_REQUEST_RESPONSE,
|
||||
LINK_NOT_FOUND_RESPONSE,
|
||||
COMMENT_NOT_FOUND_RESPONSE,
|
||||
ATTACHMENT_NOT_FOUND_RESPONSE,
|
||||
BAD_SEARCH_REQUEST_RESPONSE,
|
||||
UNAUTHORIZED_RESPONSE,
|
||||
FORBIDDEN_RESPONSE,
|
||||
WORKSPACE_NOT_FOUND_RESPONSE,
|
||||
)
|
||||
|
||||
|
||||
class WorkspaceIssueAPIEndpoint(BaseAPIView):
|
||||
"""
|
||||
@@ -634,115 +566,16 @@ class IssueDetailAPIEndpoint(BaseAPIView):
|
||||
Supports filtering, ordering, and field selection through query parameters.
|
||||
"""
|
||||
|
||||
external_id = request.GET.get("external_id")
|
||||
external_source = request.GET.get("external_source")
|
||||
issue = Issue.issue_objects.annotate(
|
||||
sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
).get(workspace__slug=slug, project_id=project_id, pk=pk)
|
||||
|
||||
if external_id and external_source:
|
||||
issue = Issue.objects.get(
|
||||
external_id=external_id,
|
||||
external_source=external_source,
|
||||
workspace__slug=slug,
|
||||
project_id=project_id,
|
||||
)
|
||||
return Response(
|
||||
IssueSerializer(issue, fields=self.fields, expand=self.expand).data,
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
# Custom ordering for priority and state
|
||||
priority_order = ["urgent", "high", "medium", "low", "none"]
|
||||
state_order = ["backlog", "unstarted", "started", "completed", "cancelled"]
|
||||
|
||||
order_by_param = request.GET.get("order_by", "-created_at")
|
||||
|
||||
issue_queryset = (
|
||||
self.get_queryset()
|
||||
.annotate(
|
||||
cycle_id=Subquery(
|
||||
CycleIssue.objects.filter(
|
||||
issue=OuterRef("id"), deleted_at__isnull=True
|
||||
).values("cycle_id")[:1]
|
||||
)
|
||||
)
|
||||
.annotate(
|
||||
link_count=IssueLink.objects.filter(issue=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
.annotate(
|
||||
attachment_count=FileAsset.objects.filter(
|
||||
issue_id=OuterRef("id"),
|
||||
entity_type=FileAsset.EntityTypeContext.ISSUE_ATTACHMENT,
|
||||
)
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
)
|
||||
|
||||
# Priority Ordering
|
||||
if order_by_param == "priority" or order_by_param == "-priority":
|
||||
priority_order = (
|
||||
priority_order if order_by_param == "priority" else priority_order[::-1]
|
||||
)
|
||||
issue_queryset = issue_queryset.annotate(
|
||||
priority_order=Case(
|
||||
*[
|
||||
When(priority=p, then=Value(i))
|
||||
for i, p in enumerate(priority_order)
|
||||
],
|
||||
output_field=CharField(),
|
||||
)
|
||||
).order_by("priority_order")
|
||||
|
||||
# State Ordering
|
||||
elif order_by_param in [
|
||||
"state__name",
|
||||
"state__group",
|
||||
"-state__name",
|
||||
"-state__group",
|
||||
]:
|
||||
state_order = (
|
||||
state_order
|
||||
if order_by_param in ["state__name", "state__group"]
|
||||
else state_order[::-1]
|
||||
)
|
||||
issue_queryset = issue_queryset.annotate(
|
||||
state_order=Case(
|
||||
*[
|
||||
When(state__group=state_group, then=Value(i))
|
||||
for i, state_group in enumerate(state_order)
|
||||
],
|
||||
default=Value(len(state_order)),
|
||||
output_field=CharField(),
|
||||
)
|
||||
).order_by("state_order")
|
||||
# assignee and label ordering
|
||||
elif order_by_param in [
|
||||
"labels__name",
|
||||
"-labels__name",
|
||||
"assignees__first_name",
|
||||
"-assignees__first_name",
|
||||
]:
|
||||
issue_queryset = issue_queryset.annotate(
|
||||
max_values=Max(
|
||||
order_by_param[1::]
|
||||
if order_by_param.startswith("-")
|
||||
else order_by_param
|
||||
)
|
||||
).order_by(
|
||||
"-max_values" if order_by_param.startswith("-") else "max_values"
|
||||
)
|
||||
else:
|
||||
issue_queryset = issue_queryset.order_by(order_by_param)
|
||||
|
||||
return self.paginate(
|
||||
request=request,
|
||||
queryset=(issue_queryset),
|
||||
on_results=lambda issues: IssueSerializer(
|
||||
issues, many=True, fields=self.fields, expand=self.expand
|
||||
).data,
|
||||
return Response(
|
||||
IssueSerializer(issue, fields=self.fields, expand=self.expand).data,
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
@work_item_docs(
|
||||
@@ -2470,6 +2303,7 @@ class IssueAttachmentServerEndpoint(BaseAPIView):
|
||||
serializer_class = IssueAttachmentSerializer
|
||||
permission_classes = [ProjectEntityPermission]
|
||||
model = FileAsset
|
||||
use_read_replica = True
|
||||
|
||||
def post(self, request, slug, project_id, issue_id):
|
||||
name = request.data.get("name")
|
||||
|
||||
Reference in New Issue
Block a user