forked from github/plane
chore: replaced v3 issues endpoints (#2945)
* chore: removed v3 endpoints * chore: replace v3 issues to normal issues endpoints * build-error: Bulid error is new issue structure --------- Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>
This commit is contained in:
parent
86de3188b1
commit
86408fcd46
@ -7,7 +7,6 @@ from plane.app.views import (
|
||||
CycleDateCheckEndpoint,
|
||||
CycleFavoriteViewSet,
|
||||
TransferCycleIssueEndpoint,
|
||||
CycleIssueGroupedEndpoint,
|
||||
)
|
||||
|
||||
|
||||
@ -44,11 +43,6 @@ urlpatterns = [
|
||||
),
|
||||
name="project-issue-cycle",
|
||||
),
|
||||
path(
|
||||
"v3/workspaces/<str:slug>/projects/<uuid:project_id>/cycles/<uuid:cycle_id>/cycle-issues/",
|
||||
CycleIssueGroupedEndpoint.as_view(),
|
||||
name="project-issue-cycle",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/cycles/<uuid:cycle_id>/cycle-issues/<uuid:pk>/",
|
||||
CycleIssueViewSet.as_view(
|
||||
|
@ -3,8 +3,6 @@ from django.urls import path
|
||||
|
||||
from plane.app.views import (
|
||||
IssueViewSet,
|
||||
IssueListEndpoint,
|
||||
IssueListGroupedEndpoint,
|
||||
LabelViewSet,
|
||||
BulkCreateIssueLabelsEndpoint,
|
||||
BulkDeleteIssuesEndpoint,
|
||||
@ -37,16 +35,6 @@ urlpatterns = [
|
||||
),
|
||||
name="project-issue",
|
||||
),
|
||||
path(
|
||||
"v2/workspaces/<str:slug>/projects/<uuid:project_id>/issues/",
|
||||
IssueListEndpoint.as_view(),
|
||||
name="project-issue",
|
||||
),
|
||||
path(
|
||||
"v3/workspaces/<str:slug>/projects/<uuid:project_id>/issues/",
|
||||
IssueListGroupedEndpoint.as_view(),
|
||||
name="project-issue",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:pk>/",
|
||||
IssueViewSet.as_view(
|
||||
|
@ -7,7 +7,6 @@ from plane.app.views import (
|
||||
ModuleLinkViewSet,
|
||||
ModuleFavoriteViewSet,
|
||||
BulkImportModulesEndpoint,
|
||||
ModuleIssueGroupedEndpoint,
|
||||
)
|
||||
|
||||
|
||||
@ -44,11 +43,6 @@ urlpatterns = [
|
||||
),
|
||||
name="project-module-issues",
|
||||
),
|
||||
path(
|
||||
"v3/workspaces/<str:slug>/projects/<uuid:project_id>/modules/<uuid:module_id>/module-issues/",
|
||||
ModuleIssueGroupedEndpoint.as_view(),
|
||||
name="project-issue-cycle",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/modules/<uuid:module_id>/module-issues/<uuid:pk>/",
|
||||
ModuleIssueViewSet.as_view(
|
||||
|
@ -6,7 +6,6 @@ from plane.app.views import (
|
||||
GlobalViewViewSet,
|
||||
GlobalViewIssuesViewSet,
|
||||
IssueViewFavoriteViewSet,
|
||||
GlobalViewIssuesGroupedEndpoint
|
||||
)
|
||||
|
||||
|
||||
@ -64,11 +63,6 @@ urlpatterns = [
|
||||
),
|
||||
name="global-view-issues",
|
||||
),
|
||||
path(
|
||||
"v3/workspaces/<str:slug>/issues/",
|
||||
GlobalViewIssuesGroupedEndpoint.as_view(),
|
||||
name="global-view-issues",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/user-favorite-views/",
|
||||
IssueViewFavoriteViewSet.as_view(
|
||||
|
@ -18,7 +18,6 @@ from plane.app.views import (
|
||||
WorkspaceUserProfileEndpoint,
|
||||
WorkspaceUserProfileIssuesEndpoint,
|
||||
WorkspaceLabelsEndpoint,
|
||||
WorkspaceUserProfileIssuesGroupedEndpoint
|
||||
)
|
||||
|
||||
|
||||
@ -190,11 +189,6 @@ urlpatterns = [
|
||||
WorkspaceUserProfileIssuesEndpoint.as_view(),
|
||||
name="workspace-user-profile-issues",
|
||||
),
|
||||
path(
|
||||
"v3/workspaces/<str:slug>/user-issues/<uuid:user_id>/",
|
||||
WorkspaceUserProfileIssuesGroupedEndpoint.as_view(),
|
||||
name="workspace-user-profile-issues",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/labels/",
|
||||
WorkspaceLabelsEndpoint.as_view(),
|
||||
|
@ -44,7 +44,6 @@ from .workspace import (
|
||||
WorkspaceUserProfileEndpoint,
|
||||
WorkspaceUserProfileIssuesEndpoint,
|
||||
WorkspaceLabelsEndpoint,
|
||||
WorkspaceUserProfileIssuesGroupedEndpoint
|
||||
)
|
||||
from .state import StateViewSet
|
||||
from .view import (
|
||||
@ -52,7 +51,6 @@ from .view import (
|
||||
GlobalViewIssuesViewSet,
|
||||
IssueViewViewSet,
|
||||
IssueViewFavoriteViewSet,
|
||||
GlobalViewIssuesGroupedEndpoint
|
||||
)
|
||||
from .cycle import (
|
||||
CycleViewSet,
|
||||
@ -60,13 +58,10 @@ from .cycle import (
|
||||
CycleDateCheckEndpoint,
|
||||
CycleFavoriteViewSet,
|
||||
TransferCycleIssueEndpoint,
|
||||
CycleIssueGroupedEndpoint,
|
||||
)
|
||||
from .asset import FileAssetEndpoint, UserAssetsEndpoint, FileAssetViewSet
|
||||
from .issue import (
|
||||
IssueViewSet,
|
||||
IssueListEndpoint,
|
||||
IssueListGroupedEndpoint,
|
||||
WorkSpaceIssuesEndpoint,
|
||||
IssueActivityEndpoint,
|
||||
IssueCommentViewSet,
|
||||
@ -108,7 +103,6 @@ from .module import (
|
||||
ModuleIssueViewSet,
|
||||
ModuleLinkViewSet,
|
||||
ModuleFavoriteViewSet,
|
||||
ModuleIssueGroupedEndpoint,
|
||||
)
|
||||
|
||||
from .api import ApiTokenEndpoint
|
||||
|
@ -539,9 +539,8 @@ class CycleIssueViewSet(WebhookMixin, BaseViewSet):
|
||||
|
||||
@method_decorator(gzip_page)
|
||||
def list(self, request, slug, project_id, cycle_id):
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
order_by = request.GET.get("order_by", "created_at")
|
||||
group_by = request.GET.get("group_by", False)
|
||||
sub_group_by = request.GET.get("sub_group_by", False)
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
issues = (
|
||||
Issue.issue_objects.filter(issue_cycle__cycle_id=cycle_id)
|
||||
@ -576,24 +575,9 @@ class CycleIssueViewSet(WebhookMixin, BaseViewSet):
|
||||
)
|
||||
)
|
||||
|
||||
issues_data = IssueStateSerializer(issues, many=True).data
|
||||
|
||||
if sub_group_by and sub_group_by == group_by:
|
||||
return Response(
|
||||
{"error": "Group by and sub group by cannot be same"},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
if group_by:
|
||||
grouped_results = group_results(issues_data, group_by, sub_group_by)
|
||||
return Response(
|
||||
grouped_results,
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
return Response(
|
||||
issues_data, status=status.HTTP_200_OK
|
||||
)
|
||||
issues = IssueStateSerializer(issues, many=True, fields=fields if fields else None).data
|
||||
issue_dict = {str(issue["id"]): issue for issue in issues}
|
||||
return Response(issue_dict, status=status.HTTP_200_OK)
|
||||
|
||||
def create(self, request, slug, project_id, cycle_id):
|
||||
issues = request.data.get("issues", [])
|
||||
@ -709,56 +693,6 @@ class CycleIssueViewSet(WebhookMixin, BaseViewSet):
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
class CycleIssueGroupedEndpoint(BaseAPIView):
|
||||
|
||||
permission_classes = [
|
||||
ProjectEntityPermission,
|
||||
]
|
||||
|
||||
def get(self, request, slug, project_id, cycle_id):
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
|
||||
issues = (
|
||||
Issue.issue_objects.filter(issue_cycle__cycle_id=cycle_id)
|
||||
.annotate(
|
||||
sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
.annotate(bridge_id=F("issue_cycle__id"))
|
||||
.filter(project_id=project_id)
|
||||
.filter(workspace__slug=slug)
|
||||
.select_related("project")
|
||||
.select_related("workspace")
|
||||
.select_related("state")
|
||||
.select_related("parent")
|
||||
.prefetch_related("assignees")
|
||||
.prefetch_related("labels")
|
||||
.filter(**filters)
|
||||
.annotate(
|
||||
link_count=IssueLink.objects.filter(issue=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
.annotate(
|
||||
attachment_count=IssueAttachment.objects.filter(issue=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
)
|
||||
|
||||
issues = IssueStateSerializer(issues, many=True, fields=fields if fields else None).data
|
||||
issue_dict = {str(issue["id"]): issue for issue in issues}
|
||||
return Response(
|
||||
issue_dict,
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
|
||||
class CycleDateCheckEndpoint(BaseAPIView):
|
||||
permission_classes = [
|
||||
ProjectEntityPermission,
|
||||
|
@ -133,6 +133,7 @@ class IssueViewSet(WebhookMixin, BaseViewSet):
|
||||
|
||||
@method_decorator(gzip_page)
|
||||
def list(self, request, slug, project_id):
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
|
||||
# Custom ordering for priority and state
|
||||
@ -216,25 +217,9 @@ class IssueViewSet(WebhookMixin, BaseViewSet):
|
||||
else:
|
||||
issue_queryset = issue_queryset.order_by(order_by_param)
|
||||
|
||||
issues = IssueLiteSerializer(issue_queryset, many=True).data
|
||||
|
||||
## Grouping the results
|
||||
group_by = request.GET.get("group_by", False)
|
||||
sub_group_by = request.GET.get("sub_group_by", False)
|
||||
if sub_group_by and sub_group_by == group_by:
|
||||
return Response(
|
||||
{"error": "Group by and sub group by cannot be same"},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
if group_by:
|
||||
grouped_results = group_results(issues, group_by, sub_group_by)
|
||||
return Response(
|
||||
grouped_results,
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
return Response(issues, status=status.HTTP_200_OK)
|
||||
issues = IssueLiteSerializer(issue_queryset, many=True, fields=fields if fields else None).data
|
||||
issue_dict = {str(issue["id"]): issue for issue in issues}
|
||||
return Response(issue_dict, status=status.HTTP_200_OK)
|
||||
|
||||
def create(self, request, slug, project_id):
|
||||
project = Project.objects.get(pk=project_id)
|
||||
@ -312,114 +297,6 @@ class IssueViewSet(WebhookMixin, BaseViewSet):
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
class IssueListEndpoint(BaseAPIView):
|
||||
permission_classes = [
|
||||
ProjectEntityPermission,
|
||||
]
|
||||
|
||||
def get(self, request, slug, project_id):
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
|
||||
issue_queryset = (
|
||||
Issue.objects.filter(workspace__slug=slug, project_id=project_id)
|
||||
.select_related("project")
|
||||
.select_related("workspace")
|
||||
.select_related("state")
|
||||
.select_related("parent")
|
||||
.prefetch_related("assignees")
|
||||
.prefetch_related("labels")
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"issue_reactions",
|
||||
queryset=IssueReaction.objects.select_related("actor"),
|
||||
)
|
||||
)
|
||||
.filter(**filters)
|
||||
.annotate(cycle_id=F("issue_cycle__cycle_id"))
|
||||
.annotate(module_id=F("issue_module__module_id"))
|
||||
.annotate(
|
||||
link_count=IssueLink.objects.filter(issue=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
.annotate(
|
||||
attachment_count=IssueAttachment.objects.filter(issue=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
.distinct()
|
||||
)
|
||||
|
||||
serializer = IssueLiteSerializer(
|
||||
issue_queryset, many=True, fields=fields if fields else None
|
||||
)
|
||||
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class IssueListGroupedEndpoint(BaseAPIView):
|
||||
|
||||
permission_classes = [
|
||||
ProjectEntityPermission,
|
||||
]
|
||||
|
||||
def get(self, request, slug, project_id):
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
archive = request.GET.get("archived", False)
|
||||
draft = request.GET.get("draft", False)
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
|
||||
issue_queryset = (
|
||||
Issue.objects.filter(workspace__slug=slug, project_id=project_id)
|
||||
.select_related("project")
|
||||
.select_related("workspace")
|
||||
.select_related("state")
|
||||
.select_related("parent")
|
||||
.prefetch_related("assignees")
|
||||
.prefetch_related("labels")
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"issue_reactions",
|
||||
queryset=IssueReaction.objects.select_related("actor"),
|
||||
)
|
||||
)
|
||||
.filter(**filters)
|
||||
.filter(is_draft=bool(draft))
|
||||
.filter(~Q(archived_at__isnull=bool(archive)))
|
||||
.filter(
|
||||
models.Q(issue_inbox__status=1)
|
||||
| models.Q(issue_inbox__status=-1)
|
||||
| models.Q(issue_inbox__status=2)
|
||||
| models.Q(issue_inbox__isnull=True)
|
||||
)
|
||||
.annotate(cycle_id=F("issue_cycle__cycle_id"))
|
||||
.annotate(module_id=F("issue_module__module_id"))
|
||||
.annotate(
|
||||
link_count=IssueLink.objects.filter(issue=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
.annotate(
|
||||
attachment_count=IssueAttachment.objects.filter(issue=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
.distinct()
|
||||
)
|
||||
|
||||
issues = IssueLiteSerializer(issue_queryset, many=True, fields=fields if fields else None).data
|
||||
issue_dict = {str(issue["id"]): issue for issue in issues}
|
||||
return Response(
|
||||
issue_dict,
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
|
||||
class UserWorkSpaceIssues(BaseAPIView):
|
||||
@method_decorator(gzip_page)
|
||||
def get(self, request, slug):
|
||||
@ -1094,6 +971,7 @@ class IssueArchiveViewSet(BaseViewSet):
|
||||
|
||||
@method_decorator(gzip_page)
|
||||
def list(self, request, slug, project_id):
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
show_sub_issues = request.GET.get("show_sub_issues", "true")
|
||||
|
||||
@ -1184,14 +1062,9 @@ class IssueArchiveViewSet(BaseViewSet):
|
||||
else issue_queryset.filter(parent__isnull=True)
|
||||
)
|
||||
|
||||
issues = IssueLiteSerializer(issue_queryset, many=True).data
|
||||
|
||||
## Grouping the results
|
||||
group_by = request.GET.get("group_by", False)
|
||||
if group_by:
|
||||
return Response(group_results(issues, group_by), status=status.HTTP_200_OK)
|
||||
|
||||
return Response(issues, status=status.HTTP_200_OK)
|
||||
issues = IssueLiteSerializer(issue_queryset, many=True, fields=fields if fields else None).data
|
||||
issue_dict = {str(issue["id"]): issue for issue in issues}
|
||||
return Response(issue_dict, status=status.HTTP_200_OK)
|
||||
|
||||
def retrieve(self, request, slug, project_id, pk=None):
|
||||
issue = Issue.objects.get(
|
||||
@ -1591,6 +1464,7 @@ class IssueDraftViewSet(BaseViewSet):
|
||||
@method_decorator(gzip_page)
|
||||
def list(self, request, slug, project_id):
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
|
||||
# Custom ordering for priority and state
|
||||
priority_order = ["urgent", "high", "medium", "low", "none"]
|
||||
@ -1673,18 +1547,9 @@ class IssueDraftViewSet(BaseViewSet):
|
||||
else:
|
||||
issue_queryset = issue_queryset.order_by(order_by_param)
|
||||
|
||||
issues = IssueLiteSerializer(issue_queryset, many=True).data
|
||||
|
||||
## Grouping the results
|
||||
group_by = request.GET.get("group_by", False)
|
||||
if group_by:
|
||||
grouped_results = group_results(issues, group_by)
|
||||
return Response(
|
||||
grouped_results,
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
return Response(issues, status=status.HTTP_200_OK)
|
||||
issues = IssueLiteSerializer(issue_queryset, many=True, fields=fields if fields else None).data
|
||||
issue_dict = {str(issue["id"]): issue for issue in issues}
|
||||
return Response(issue_dict, status=status.HTTP_200_OK)
|
||||
|
||||
def create(self, request, slug, project_id):
|
||||
project = Project.objects.get(pk=project_id)
|
||||
|
@ -324,9 +324,8 @@ class ModuleIssueViewSet(WebhookMixin, BaseViewSet):
|
||||
|
||||
@method_decorator(gzip_page)
|
||||
def list(self, request, slug, project_id, module_id):
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
order_by = request.GET.get("order_by", "created_at")
|
||||
group_by = request.GET.get("group_by", False)
|
||||
sub_group_by = request.GET.get("sub_group_by", False)
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
issues = (
|
||||
Issue.issue_objects.filter(issue_module__module_id=module_id)
|
||||
@ -360,24 +359,9 @@ class ModuleIssueViewSet(WebhookMixin, BaseViewSet):
|
||||
.values("count")
|
||||
)
|
||||
)
|
||||
issues_data = IssueStateSerializer(issues, many=True).data
|
||||
|
||||
if sub_group_by and sub_group_by == group_by:
|
||||
return Response(
|
||||
{"error": "Group by and sub group by cannot be same"},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
if group_by:
|
||||
grouped_results = group_results(issues_data, group_by, sub_group_by)
|
||||
return Response(
|
||||
grouped_results,
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
return Response(
|
||||
issues_data, status=status.HTTP_200_OK
|
||||
)
|
||||
issues = IssueStateSerializer(issues, many=True, fields=fields if fields else None).data
|
||||
issue_dict = {str(issue["id"]): issue for issue in issues}
|
||||
return Response(issue_dict, status=status.HTTP_200_OK)
|
||||
|
||||
def create(self, request, slug, project_id, module_id):
|
||||
issues = request.data.get("issues", [])
|
||||
@ -482,55 +466,6 @@ class ModuleIssueViewSet(WebhookMixin, BaseViewSet):
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
class ModuleIssueGroupedEndpoint(BaseAPIView):
|
||||
|
||||
permission_classes = [
|
||||
ProjectEntityPermission,
|
||||
]
|
||||
|
||||
def get(self, request, slug, project_id, module_id):
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
|
||||
issues = (
|
||||
Issue.issue_objects.filter(issue_module__module_id=module_id)
|
||||
.annotate(
|
||||
sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
.annotate(bridge_id=F("issue_module__id"))
|
||||
.filter(project_id=project_id)
|
||||
.filter(workspace__slug=slug)
|
||||
.select_related("project")
|
||||
.select_related("workspace")
|
||||
.select_related("state")
|
||||
.select_related("parent")
|
||||
.prefetch_related("assignees")
|
||||
.prefetch_related("labels")
|
||||
.filter(**filters)
|
||||
.annotate(
|
||||
link_count=IssueLink.objects.filter(issue=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
.annotate(
|
||||
attachment_count=IssueAttachment.objects.filter(issue=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
)
|
||||
|
||||
issues = IssueStateSerializer(issues, many=True, fields=fields if fields else None).data
|
||||
issue_dict = {str(issue["id"]): issue for issue in issues}
|
||||
return Response(
|
||||
issue_dict,
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
class ModuleLinkViewSet(BaseViewSet):
|
||||
permission_classes = [
|
||||
ProjectEntityPermission,
|
||||
|
@ -95,6 +95,7 @@ class GlobalViewIssuesViewSet(BaseViewSet):
|
||||
@method_decorator(gzip_page)
|
||||
def list(self, request, slug):
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
|
||||
# Custom ordering for priority and state
|
||||
priority_order = ["urgent", "high", "medium", "low", "none"]
|
||||
@ -177,73 +178,6 @@ class GlobalViewIssuesViewSet(BaseViewSet):
|
||||
)
|
||||
else:
|
||||
issue_queryset = issue_queryset.order_by(order_by_param)
|
||||
issues = IssueLiteSerializer(issue_queryset, many=True).data
|
||||
|
||||
## Grouping the results
|
||||
group_by = request.GET.get("group_by", False)
|
||||
sub_group_by = request.GET.get("sub_group_by", False)
|
||||
if sub_group_by and sub_group_by == group_by:
|
||||
return Response(
|
||||
{"error": "Group by and sub group by cannot be same"},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
if group_by:
|
||||
grouped_results = group_results(issues, group_by, sub_group_by)
|
||||
return Response(
|
||||
grouped_results,
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
return Response(issues, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class GlobalViewIssuesGroupedEndpoint(BaseAPIView):
|
||||
permission_classes = [
|
||||
WorkspaceEntityPermission,
|
||||
]
|
||||
|
||||
def get(self, request, slug):
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
|
||||
issue_queryset = (
|
||||
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")
|
||||
)
|
||||
.filter(workspace__slug=self.kwargs.get("slug"))
|
||||
.filter(project__project_projectmember__member=self.request.user)
|
||||
.filter(**filters)
|
||||
.select_related("project")
|
||||
.select_related("workspace")
|
||||
.select_related("state")
|
||||
.select_related("parent")
|
||||
.prefetch_related("assignees")
|
||||
.prefetch_related("labels")
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"issue_reactions",
|
||||
queryset=IssueReaction.objects.select_related("actor"),
|
||||
)
|
||||
)
|
||||
.annotate(cycle_id=F("issue_cycle__cycle_id"))
|
||||
.annotate(module_id=F("issue_module__module_id"))
|
||||
.annotate(
|
||||
link_count=IssueLink.objects.filter(issue=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
.annotate(
|
||||
attachment_count=IssueAttachment.objects.filter(issue=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
)
|
||||
|
||||
issues = IssueLiteSerializer(issue_queryset, many=True, fields=fields if fields else None).data
|
||||
issue_dict = {str(issue["id"]): issue for issue in issues}
|
||||
@ -252,6 +186,7 @@ class GlobalViewIssuesGroupedEndpoint(BaseAPIView):
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
|
||||
class IssueViewViewSet(BaseViewSet):
|
||||
serializer_class = IssueViewSerializer
|
||||
model = IssueView
|
||||
|
@ -1207,6 +1207,7 @@ class WorkspaceUserProfileIssuesEndpoint(BaseAPIView):
|
||||
]
|
||||
|
||||
def get(self, request, slug, user_id):
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
|
||||
# Custom ordering for priority and state
|
||||
@ -1308,75 +1309,11 @@ class WorkspaceUserProfileIssuesEndpoint(BaseAPIView):
|
||||
else:
|
||||
issue_queryset = issue_queryset.order_by(order_by_param)
|
||||
|
||||
issues = IssueLiteSerializer(issue_queryset, many=True).data
|
||||
|
||||
## Grouping the results
|
||||
group_by = request.GET.get("group_by", False)
|
||||
if group_by:
|
||||
grouped_results = group_results(issues, group_by)
|
||||
return Response(
|
||||
grouped_results,
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
return Response(issues, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class WorkspaceUserProfileIssuesGroupedEndpoint(BaseAPIView):
|
||||
permission_classes = [
|
||||
WorkspaceViewerPermission,
|
||||
]
|
||||
|
||||
def get(self, request, slug, user_id):
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
|
||||
issue_queryset = (
|
||||
Issue.issue_objects.filter(
|
||||
Q(assignees__in=[user_id])
|
||||
| Q(created_by_id=user_id)
|
||||
| Q(issue_subscribers__subscriber_id=user_id),
|
||||
workspace__slug=slug,
|
||||
project__project_projectmember__member=request.user,
|
||||
)
|
||||
.filter(**filters)
|
||||
.annotate(
|
||||
sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
.select_related("project", "workspace", "state", "parent")
|
||||
.prefetch_related("assignees", "labels")
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"issue_reactions",
|
||||
queryset=IssueReaction.objects.select_related("actor"),
|
||||
)
|
||||
)
|
||||
.order_by("-created_at")
|
||||
.annotate(
|
||||
link_count=IssueLink.objects.filter(issue=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
.annotate(
|
||||
attachment_count=IssueAttachment.objects.filter(issue=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
).distinct()
|
||||
|
||||
issues = IssueLiteSerializer(
|
||||
issue_queryset, many=True, fields=fields if fields else None
|
||||
).data
|
||||
issue_dict = {str(issue["id"]): issue for issue in issues}
|
||||
return Response(
|
||||
issue_dict,
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
return Response(issue_dict, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class WorkspaceLabelsEndpoint(BaseAPIView):
|
||||
|
@ -101,8 +101,8 @@ export const BulkDeleteIssuesModal: React.FC<Props> = (props) => {
|
||||
|
||||
const filteredIssues: IIssue[] =
|
||||
query === ""
|
||||
? issues ?? []
|
||||
: issues?.filter(
|
||||
? Object.values(issues ?? {})
|
||||
: Object.values(issues ?? {})?.filter(
|
||||
(issue) =>
|
||||
issue.name.toLowerCase().includes(query.toLowerCase()) ||
|
||||
`${issue.project_detail.identifier}-${issue.sequence_id}`.toLowerCase().includes(query.toLowerCase())
|
||||
|
@ -40,7 +40,7 @@ export const SelectDuplicateInboxIssueModal: React.FC<Props> = (props) => {
|
||||
? () =>
|
||||
issueService
|
||||
.getIssues(workspaceSlug as string, projectId as string)
|
||||
.then((res) => res.filter((issue) => issue.id !== issueId))
|
||||
.then((res) => Object.values(res ?? {}).filter((issue) => issue.id !== issueId))
|
||||
: null
|
||||
);
|
||||
|
||||
|
@ -51,27 +51,12 @@ export class CycleService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async getV3CycleIssues(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
cycleId: string,
|
||||
queries?: any
|
||||
): Promise<IIssueResponse> {
|
||||
return this.get(`/api/v3/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/cycle-issues/`, {
|
||||
params: queries,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getCycleIssuesWithParams(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
cycleId: string,
|
||||
queries?: any
|
||||
): Promise<IIssue[] | { [key: string]: IIssue[] }> {
|
||||
): Promise<IIssueResponse> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/cycle-issues/`, {
|
||||
params: queries,
|
||||
})
|
||||
|
@ -19,16 +19,8 @@ export class IssueService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async getIssues(workspaceSlug: string, projectId: string): Promise<IIssue[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getV3Issues(workspaceSlug: string, projectId: string, queries?: any): Promise<IIssueResponse> {
|
||||
return this.get(`/api/v3/workspaces/${workspaceSlug}/projects/${projectId}/issues/`, {
|
||||
async getIssues(workspaceSlug: string, projectId: string, queries?: any): Promise<IIssueResponse> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/`, {
|
||||
params: queries,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
|
@ -9,17 +9,7 @@ export class IssueArchiveService extends APIService {
|
||||
|
||||
async getArchivedIssues(workspaceSlug: string, projectId: string, queries?: any): Promise<any> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/archived-issues/`, {
|
||||
params: queries,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getV3ArchivedIssues(workspaceSlug: string, projectId: string, queries?: any): Promise<any> {
|
||||
return this.get(`/api/v3/workspaces/${workspaceSlug}/projects/${projectId}/issues/`, {
|
||||
params: { ...queries, archived: true },
|
||||
params: { ...queries },
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
|
@ -1,24 +1,15 @@
|
||||
import { APIService } from "services/api.service";
|
||||
// helpers
|
||||
import { API_BASE_URL } from "helpers/common.helper";
|
||||
import { IIssueResponse } from "store/issues/types";
|
||||
|
||||
export class IssueDraftService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async getDraftIssues(workspaceSlug: string, projectId: string, params?: any): Promise<any> {
|
||||
async getDraftIssues(workspaceSlug: string, projectId: string, query?: any): Promise<IIssueResponse> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-drafts/`, {
|
||||
params,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async getV3DraftIssues(workspaceSlug: string, projectId: string, query?: any): Promise<any> {
|
||||
return this.get(`/api/v3/workspaces/${workspaceSlug}/projects/${projectId}/issues/?draft=true`, {
|
||||
params: { ...query },
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
|
@ -63,21 +63,13 @@ export class ModuleService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async getModuleIssues(workspaceSlug: string, projectId: string, moduleId: string): Promise<IIssue[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-issues/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getV3ModuleIssues(
|
||||
async getModuleIssues(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
moduleId: string,
|
||||
queries?: any
|
||||
): Promise<IIssueResponse> {
|
||||
return this.get(`/api/v3/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-issues/`, {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-issues/`, {
|
||||
params: queries,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
|
@ -152,16 +152,7 @@ export class UserService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async getUserProfileIssues(
|
||||
workspaceSlug: string,
|
||||
userId: string,
|
||||
params: any
|
||||
): Promise<
|
||||
| {
|
||||
[key: string]: IIssue[];
|
||||
}
|
||||
| IIssue[]
|
||||
> {
|
||||
async getUserProfileIssues(workspaceSlug: string, userId: string, params: any): Promise<IIssueResponse> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/user-issues/${userId}/`, {
|
||||
params,
|
||||
})
|
||||
@ -171,16 +162,6 @@ export class UserService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async getV3UserProfileIssues(workspaceSlug: string, userId: string, params: any): Promise<IIssueResponse> {
|
||||
return this.get(`/api/v3/workspaces/${workspaceSlug}/user-issues/${userId}/`, {
|
||||
params,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deactivateAccount() {
|
||||
return this.delete(`/api/users/me/`)
|
||||
.then((response) => response?.data)
|
||||
|
@ -233,7 +233,7 @@ export class CycleStore implements ICycleStore {
|
||||
|
||||
const _activeCycleIssues = {
|
||||
...this.active_cycle_issues,
|
||||
[cycleId]: _cycleIssues as IIssue[],
|
||||
[cycleId]: Object.values(_cycleIssues) as IIssue[],
|
||||
};
|
||||
|
||||
runInAction(() => {
|
||||
|
@ -39,7 +39,7 @@ export class DraftIssuesStore {
|
||||
const issues = Array.isArray(issuesResponse) ? { allIssues: issuesResponse } : issuesResponse;
|
||||
|
||||
runInAction(() => {
|
||||
this.issues = issues;
|
||||
this.issues = Object.values(issues) as any;
|
||||
this.isIssuesLoading = false;
|
||||
});
|
||||
} catch (error) {
|
||||
|
@ -159,7 +159,7 @@ export class GlobalIssuesStore extends IssueBaseStore implements IGlobalIssuesSt
|
||||
else if (this.currentUserIssueTab === "subscribed")
|
||||
params = params ? { ...params, subscriber: userId } : { subscriber: userId };
|
||||
|
||||
const response = await this.userService.getV3UserProfileIssues(workspaceSlug, userId, params);
|
||||
const response = await this.userService.getUserProfileIssues(workspaceSlug, userId, params);
|
||||
|
||||
if (!this.currentUserIssueTab) return;
|
||||
|
||||
|
@ -173,7 +173,7 @@ export class ProfileIssuesStore extends IssueBaseStore implements IProfileIssues
|
||||
else if (this.currentUserIssueTab === "subscribed")
|
||||
params = params ? { ...params, subscriber: userId } : { subscriber: userId };
|
||||
|
||||
const response = await this.userService.getV3UserProfileIssues(workspaceSlug, userId, params);
|
||||
const response = await this.userService.getUserProfileIssues(workspaceSlug, userId, params);
|
||||
|
||||
if (!this.currentUserIssueTab) return;
|
||||
|
||||
|
@ -100,7 +100,7 @@ export class ProjectArchivedIssuesStore extends IssueBaseStore implements IProje
|
||||
this.loader = loadType;
|
||||
|
||||
const params = this.rootStore?.projectArchivedIssuesFilter?.appliedFilters;
|
||||
const response = await this.archivedIssueService.getV3ArchivedIssues(workspaceSlug, projectId, params);
|
||||
const response = await this.archivedIssueService.getArchivedIssues(workspaceSlug, projectId, params);
|
||||
|
||||
const _issues = { ...this.issues, [projectId]: { ...response } };
|
||||
|
||||
|
@ -168,7 +168,7 @@ export class CycleIssuesStore extends IssueBaseStore implements ICycleIssuesStor
|
||||
this.currentProjectId = projectId;
|
||||
|
||||
const params = this.rootStore?.cycleIssuesFilter?.appliedFilters;
|
||||
const response = await this.cycleService.getV3CycleIssues(workspaceSlug, projectId, cycleId, params);
|
||||
const response = await this.cycleService.getCycleIssuesWithParams(workspaceSlug, projectId, cycleId, params);
|
||||
|
||||
const _issues = { ...this.issues, [cycleId]: { ...response } };
|
||||
|
||||
|
@ -107,7 +107,7 @@ export class ProjectDraftIssuesStore extends IssueBaseStore implements IProjectD
|
||||
this.loader = loadType;
|
||||
|
||||
const params = this.rootStore?.projectDraftIssuesFilter?.appliedFilters;
|
||||
const response = await this.issueDraftService.getV3DraftIssues(workspaceSlug, projectId, params);
|
||||
const response = await this.issueDraftService.getDraftIssues(workspaceSlug, projectId, params);
|
||||
|
||||
const _issues = { ...this.issues, [projectId]: { ...response } };
|
||||
|
||||
|
@ -166,7 +166,7 @@ export class ModuleIssuesStore extends IssueBaseStore implements IModuleIssuesSt
|
||||
this.loader = loadType;
|
||||
|
||||
const params = this.rootStore?.moduleIssuesFilter?.appliedFilters;
|
||||
const response = await this.moduleService.getV3ModuleIssues(workspaceSlug, projectId, moduleId, params);
|
||||
const response = await this.moduleService.getModuleIssues(workspaceSlug, projectId, moduleId, params);
|
||||
|
||||
const _issues = { ...this.issues, [moduleId]: { ...response } };
|
||||
|
||||
|
@ -112,7 +112,7 @@ export class ViewIssuesStore extends IssueBaseStore implements IViewIssuesStore
|
||||
this.loader = loadType;
|
||||
|
||||
const params = this.rootStore?.viewIssuesFilter?.appliedFilters;
|
||||
const response = await this.issueService.getV3Issues(workspaceSlug, projectId, params);
|
||||
const response = await this.issueService.getIssues(workspaceSlug, projectId, params);
|
||||
|
||||
const _issues = { ...this.issues, [projectId]: { ...response } };
|
||||
|
||||
|
@ -112,7 +112,7 @@ export class ProjectIssuesStore extends IssueBaseStore implements IProjectIssues
|
||||
this.loader = loadType;
|
||||
|
||||
const params = this.rootStore?.projectIssuesFilter?.appliedFilters;
|
||||
const response = await this.issueService.getV3Issues(workspaceSlug, projectId, params);
|
||||
const response = await this.issueService.getIssues(workspaceSlug, projectId, params);
|
||||
|
||||
const _issues = { ...this.issues, [projectId]: { ...response } };
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user