[WEB-4951] [WEB-4884] feat: work item filters revamp (#7810)
This commit is contained in:
parent
e6a7ca4c72
commit
9aef5d4aa9
160 changed files with 5879 additions and 4881 deletions
|
|
@ -1080,6 +1080,9 @@ class CycleUserPropertiesEndpoint(BaseAPIView):
|
|||
)
|
||||
|
||||
cycle_properties.filters = request.data.get("filters", cycle_properties.filters)
|
||||
cycle_properties.rich_filters = request.data.get(
|
||||
"rich_filters", cycle_properties.rich_filters
|
||||
)
|
||||
cycle_properties.display_filters = request.data.get(
|
||||
"display_filters", cycle_properties.display_filters
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
# Python imports
|
||||
import copy
|
||||
import json
|
||||
|
||||
# Django imports
|
||||
|
|
@ -28,11 +29,15 @@ from plane.utils.order_queryset import order_issue_queryset
|
|||
from plane.utils.paginator import GroupedOffsetPaginator, SubGroupedOffsetPaginator
|
||||
from plane.app.permissions import allow_permission, ROLE
|
||||
from plane.utils.host import base_host
|
||||
from plane.utils.filters import ComplexFilterBackend
|
||||
from plane.utils.filters import IssueFilterSet
|
||||
|
||||
|
||||
class CycleIssueViewSet(BaseViewSet):
|
||||
serializer_class = CycleIssueSerializer
|
||||
model = CycleIssue
|
||||
filter_backends = (ComplexFilterBackend,)
|
||||
filterset_class = IssueFilterSet
|
||||
|
||||
webhook_event = "cycle_issue"
|
||||
bulk = True
|
||||
|
|
@ -65,24 +70,9 @@ class CycleIssueViewSet(BaseViewSet):
|
|||
.distinct()
|
||||
)
|
||||
|
||||
@method_decorator(gzip_page)
|
||||
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
|
||||
def list(self, request, slug, project_id, cycle_id):
|
||||
order_by_param = request.GET.get("order_by", "created_at")
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
issue_queryset = (
|
||||
Issue.issue_objects.filter(
|
||||
issue_cycle__cycle_id=cycle_id, issue_cycle__deleted_at__isnull=True
|
||||
)
|
||||
.filter(project_id=project_id)
|
||||
.filter(workspace__slug=slug)
|
||||
.filter(**filters)
|
||||
.select_related("workspace", "project", "state", "parent")
|
||||
.prefetch_related(
|
||||
"assignees", "labels", "issue_module__module", "issue_cycle__cycle"
|
||||
)
|
||||
.filter(**filters)
|
||||
.annotate(
|
||||
def apply_annotations(self, issues):
|
||||
return (
|
||||
issues.annotate(
|
||||
cycle_id=Subquery(
|
||||
CycleIssue.objects.filter(
|
||||
issue=OuterRef("id"), deleted_at__isnull=True
|
||||
|
|
@ -110,11 +100,36 @@ class CycleIssueViewSet(BaseViewSet):
|
|||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
.prefetch_related(
|
||||
"assignees", "labels", "issue_module__module", "issue_cycle__cycle"
|
||||
)
|
||||
)
|
||||
|
||||
@method_decorator(gzip_page)
|
||||
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
|
||||
def list(self, request, slug, project_id, cycle_id):
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
issue_queryset = (
|
||||
Issue.issue_objects.filter(
|
||||
issue_cycle__cycle_id=cycle_id, issue_cycle__deleted_at__isnull=True
|
||||
)
|
||||
.filter(project_id=project_id)
|
||||
.filter(workspace__slug=slug)
|
||||
)
|
||||
|
||||
# Apply filtering from filterset
|
||||
issue_queryset = self.filter_queryset(issue_queryset)
|
||||
|
||||
# Apply legacy filters
|
||||
issue_queryset = issue_queryset.filter(**filters)
|
||||
|
||||
# Total count queryset
|
||||
total_issue_queryset = copy.deepcopy(issue_queryset)
|
||||
|
||||
# Applying annotations to the issue queryset
|
||||
issue_queryset = self.apply_annotations(issue_queryset)
|
||||
|
||||
order_by_param = request.GET.get("order_by", "-created_at")
|
||||
issue_queryset = issue_queryset.filter(**filters)
|
||||
# Issue queryset
|
||||
issue_queryset, order_by_param = order_issue_queryset(
|
||||
issue_queryset=issue_queryset, order_by_param=order_by_param
|
||||
|
|
@ -145,6 +160,7 @@ class CycleIssueViewSet(BaseViewSet):
|
|||
request=request,
|
||||
order_by=order_by_param,
|
||||
queryset=issue_queryset,
|
||||
total_count_queryset=total_issue_queryset,
|
||||
on_results=lambda issues: issue_on_results(
|
||||
group_by=group_by, issues=issues, sub_group_by=sub_group_by
|
||||
),
|
||||
|
|
@ -179,6 +195,7 @@ class CycleIssueViewSet(BaseViewSet):
|
|||
request=request,
|
||||
order_by=order_by_param,
|
||||
queryset=issue_queryset,
|
||||
total_count_queryset=total_issue_queryset,
|
||||
on_results=lambda issues: issue_on_results(
|
||||
group_by=group_by, issues=issues, sub_group_by=sub_group_by
|
||||
),
|
||||
|
|
@ -205,6 +222,7 @@ class CycleIssueViewSet(BaseViewSet):
|
|||
order_by=order_by_param,
|
||||
request=request,
|
||||
queryset=issue_queryset,
|
||||
total_count_queryset=total_issue_queryset,
|
||||
on_results=lambda issues: issue_on_results(
|
||||
group_by=group_by, issues=issues, sub_group_by=sub_group_by
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
# Python imports
|
||||
import copy
|
||||
import json
|
||||
|
||||
# Django imports
|
||||
|
|
@ -41,27 +42,20 @@ from plane.utils.host import base_host
|
|||
|
||||
# Module imports
|
||||
from .. import BaseViewSet, BaseAPIView
|
||||
from plane.utils.filters import ComplexFilterBackend
|
||||
from plane.utils.filters import IssueFilterSet
|
||||
|
||||
|
||||
class IssueArchiveViewSet(BaseViewSet):
|
||||
serializer_class = IssueFlatSerializer
|
||||
model = Issue
|
||||
|
||||
def get_queryset(self):
|
||||
filter_backends = (ComplexFilterBackend,)
|
||||
filterset_class = IssueFilterSet
|
||||
|
||||
def apply_annotations(self, issues):
|
||||
return (
|
||||
Issue.objects.annotate(
|
||||
sub_issues_count=Issue.objects.filter(parent=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
.filter(deleted_at__isnull=True)
|
||||
.filter(archived_at__isnull=False)
|
||||
.filter(project_id=self.kwargs.get("project_id"))
|
||||
.filter(workspace__slug=self.kwargs.get("slug"))
|
||||
.select_related("workspace", "project", "state", "parent")
|
||||
.prefetch_related("assignees", "labels", "issue_module__module")
|
||||
.annotate(
|
||||
issues.annotate(
|
||||
cycle_id=Subquery(
|
||||
CycleIssue.objects.filter(
|
||||
issue=OuterRef("id"), deleted_at__isnull=True
|
||||
|
|
@ -95,6 +89,15 @@ class IssueArchiveViewSet(BaseViewSet):
|
|||
.values("count")
|
||||
)
|
||||
)
|
||||
.prefetch_related("assignees", "labels", "issue_module__module")
|
||||
)
|
||||
|
||||
def get_queryset(self):
|
||||
return (
|
||||
Issue.objects.filter(Q(type__isnull=True) | Q(type__is_epic=False))
|
||||
.filter(archived_at__isnull=False)
|
||||
.filter(project_id=self.kwargs.get("project_id"))
|
||||
.filter(workspace__slug=self.kwargs.get("slug"))
|
||||
)
|
||||
|
||||
@method_decorator(gzip_page)
|
||||
|
|
@ -105,26 +108,25 @@ class IssueArchiveViewSet(BaseViewSet):
|
|||
|
||||
order_by_param = request.GET.get("order_by", "-created_at")
|
||||
|
||||
issue_queryset = self.get_queryset().filter(**filters)
|
||||
|
||||
total_issue_queryset = Issue.objects.filter(
|
||||
deleted_at__isnull=True,
|
||||
archived_at__isnull=False,
|
||||
project_id=project_id,
|
||||
workspace__slug=slug,
|
||||
).filter(**filters)
|
||||
|
||||
total_issue_queryset = (
|
||||
total_issue_queryset
|
||||
if show_sub_issues == "true"
|
||||
else total_issue_queryset.filter(parent__isnull=True)
|
||||
)
|
||||
issue_queryset = self.get_queryset()
|
||||
|
||||
issue_queryset = (
|
||||
issue_queryset
|
||||
if show_sub_issues == "true"
|
||||
else issue_queryset.filter(parent__isnull=True)
|
||||
)
|
||||
# Apply filtering from filterset
|
||||
issue_queryset = self.filter_queryset(issue_queryset)
|
||||
|
||||
# Apply legacy filters
|
||||
issue_queryset = issue_queryset.filter(**filters)
|
||||
|
||||
# Total count queryset
|
||||
total_issue_queryset = copy.deepcopy(issue_queryset)
|
||||
|
||||
# Applying annotations to the issue queryset
|
||||
issue_queryset = self.apply_annotations(issue_queryset)
|
||||
|
||||
# Issue queryset
|
||||
issue_queryset, order_by_param = order_issue_queryset(
|
||||
issue_queryset=issue_queryset, order_by_param=order_by_param
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
# Python imports
|
||||
import copy
|
||||
import json
|
||||
|
||||
# Django imports
|
||||
|
|
@ -6,16 +7,16 @@ from django.contrib.postgres.aggregates import ArrayAgg
|
|||
from django.contrib.postgres.fields import ArrayField
|
||||
from django.core.serializers.json import DjangoJSONEncoder
|
||||
from django.db.models import (
|
||||
Count,
|
||||
Exists,
|
||||
F,
|
||||
Func,
|
||||
OuterRef,
|
||||
Prefetch,
|
||||
Q,
|
||||
Subquery,
|
||||
UUIDField,
|
||||
Value,
|
||||
Subquery,
|
||||
Count,
|
||||
)
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.utils import timezone
|
||||
|
|
@ -27,50 +28,55 @@ from rest_framework import status
|
|||
from rest_framework.response import Response
|
||||
|
||||
# Module imports
|
||||
from plane.app.permissions import allow_permission, ROLE
|
||||
from plane.app.permissions import ROLE, allow_permission
|
||||
from plane.app.serializers import (
|
||||
IssueCreateSerializer,
|
||||
IssueDetailSerializer,
|
||||
IssueUserPropertySerializer,
|
||||
IssueSerializer,
|
||||
IssueListDetailSerializer,
|
||||
IssueSerializer,
|
||||
IssueUserPropertySerializer,
|
||||
)
|
||||
from plane.bgtasks.issue_activities_task import issue_activity
|
||||
from plane.bgtasks.issue_description_version_task import issue_description_version_task
|
||||
from plane.bgtasks.recent_visited_task import recent_visited_task
|
||||
from plane.bgtasks.webhook_task import model_activity
|
||||
from plane.db.models import (
|
||||
Issue,
|
||||
FileAsset,
|
||||
IssueLink,
|
||||
IssueUserProperty,
|
||||
IssueReaction,
|
||||
IssueSubscriber,
|
||||
Project,
|
||||
ProjectMember,
|
||||
CycleIssue,
|
||||
UserRecentVisit,
|
||||
ModuleIssue,
|
||||
IssueRelation,
|
||||
FileAsset,
|
||||
IntakeIssue,
|
||||
Issue,
|
||||
IssueAssignee,
|
||||
IssueLabel,
|
||||
IntakeIssue,
|
||||
IssueLink,
|
||||
IssueReaction,
|
||||
IssueRelation,
|
||||
IssueSubscriber,
|
||||
IssueUserProperty,
|
||||
ModuleIssue,
|
||||
Project,
|
||||
ProjectMember,
|
||||
UserRecentVisit,
|
||||
)
|
||||
from plane.utils.filters import ComplexFilterBackend, IssueFilterSet
|
||||
from plane.utils.global_paginator import paginate
|
||||
from plane.utils.grouper import (
|
||||
issue_group_values,
|
||||
issue_on_results,
|
||||
issue_queryset_grouper,
|
||||
)
|
||||
from plane.utils.host import base_host
|
||||
from plane.utils.issue_filters import issue_filters
|
||||
from plane.utils.order_queryset import order_issue_queryset
|
||||
from plane.utils.paginator import GroupedOffsetPaginator, SubGroupedOffsetPaginator
|
||||
from .. import BaseAPIView, BaseViewSet
|
||||
from plane.utils.timezone_converter import user_timezone_converter
|
||||
from plane.bgtasks.recent_visited_task import recent_visited_task
|
||||
from plane.utils.global_paginator import paginate
|
||||
from plane.bgtasks.webhook_task import model_activity
|
||||
from plane.bgtasks.issue_description_version_task import issue_description_version_task
|
||||
from plane.utils.host import base_host
|
||||
|
||||
from .. import BaseAPIView, BaseViewSet
|
||||
|
||||
|
||||
class IssueListEndpoint(BaseAPIView):
|
||||
filter_backends = (ComplexFilterBackend,)
|
||||
filterset_class = IssueFilterSet
|
||||
|
||||
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
|
||||
def get(self, request, slug, project_id):
|
||||
issue_ids = request.GET.get("issues", False)
|
||||
|
|
@ -82,14 +88,27 @@ class IssueListEndpoint(BaseAPIView):
|
|||
|
||||
issue_ids = [issue_id for issue_id in issue_ids.split(",") if issue_id != ""]
|
||||
|
||||
queryset = (
|
||||
Issue.issue_objects.filter(
|
||||
workspace__slug=slug, project_id=project_id, pk__in=issue_ids
|
||||
)
|
||||
.filter(workspace__slug=self.kwargs.get("slug"))
|
||||
.select_related("workspace", "project", "state", "parent")
|
||||
.prefetch_related("assignees", "labels", "issue_module__module")
|
||||
.annotate(
|
||||
# Base queryset with basic filters
|
||||
queryset = Issue.issue_objects.filter(
|
||||
workspace__slug=slug, project_id=project_id, pk__in=issue_ids
|
||||
)
|
||||
|
||||
# Apply filtering from filterset
|
||||
queryset = self.filter_queryset(queryset)
|
||||
|
||||
# Apply legacy filters
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
issue_queryset = queryset.filter(**filters)
|
||||
|
||||
# Add select_related, prefetch_related if fields or expand is not None
|
||||
if self.fields or self.expand:
|
||||
issue_queryset = issue_queryset.select_related(
|
||||
"workspace", "project", "state", "parent"
|
||||
).prefetch_related("assignees", "labels", "issue_module__module")
|
||||
|
||||
# Add annotations
|
||||
issue_queryset = (
|
||||
issue_queryset.annotate(
|
||||
cycle_id=Subquery(
|
||||
CycleIssue.objects.filter(
|
||||
issue=OuterRef("id"), deleted_at__isnull=True
|
||||
|
|
@ -117,12 +136,10 @@ class IssueListEndpoint(BaseAPIView):
|
|||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
).distinct()
|
||||
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
.distinct()
|
||||
)
|
||||
|
||||
order_by_param = request.GET.get("order_by", "-created_at")
|
||||
issue_queryset = queryset.filter(**filters)
|
||||
# Issue queryset
|
||||
issue_queryset, _ = order_issue_queryset(
|
||||
issue_queryset=issue_queryset, order_by_param=order_by_param
|
||||
|
|
@ -186,6 +203,12 @@ class IssueListEndpoint(BaseAPIView):
|
|||
|
||||
|
||||
class IssueViewSet(BaseViewSet):
|
||||
model = Issue
|
||||
webhook_event = "issue"
|
||||
search_fields = ["name"]
|
||||
filter_backends = (ComplexFilterBackend,)
|
||||
filterset_class = IssueFilterSet
|
||||
|
||||
def get_serializer_class(self):
|
||||
return (
|
||||
IssueCreateSerializer
|
||||
|
|
@ -193,20 +216,17 @@ class IssueViewSet(BaseViewSet):
|
|||
else IssueSerializer
|
||||
)
|
||||
|
||||
model = Issue
|
||||
webhook_event = "issue"
|
||||
|
||||
search_fields = ["name"]
|
||||
|
||||
filterset_fields = ["state__name", "assignees__id", "workspace__id"]
|
||||
|
||||
def get_queryset(self):
|
||||
return (
|
||||
Issue.issue_objects.filter(project_id=self.kwargs.get("project_id"))
|
||||
.filter(workspace__slug=self.kwargs.get("slug"))
|
||||
.select_related("workspace", "project", "state", "parent")
|
||||
.prefetch_related("assignees", "labels", "issue_module__module")
|
||||
.annotate(
|
||||
issues = Issue.issue_objects.filter(
|
||||
project_id=self.kwargs.get("project_id"),
|
||||
workspace__slug=self.kwargs.get("slug"),
|
||||
).distinct()
|
||||
|
||||
return issues
|
||||
|
||||
def apply_annotations(self, issues):
|
||||
issues = (
|
||||
issues.annotate(
|
||||
cycle_id=Subquery(
|
||||
CycleIssue.objects.filter(
|
||||
issue=OuterRef("id"), deleted_at__isnull=True
|
||||
|
|
@ -242,6 +262,8 @@ class IssueViewSet(BaseViewSet):
|
|||
)
|
||||
)
|
||||
|
||||
return issues
|
||||
|
||||
@method_decorator(gzip_page)
|
||||
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
|
||||
def list(self, request, slug, project_id):
|
||||
|
|
@ -250,15 +272,24 @@ class IssueViewSet(BaseViewSet):
|
|||
extra_filters = {"updated_at__gt": request.GET.get("updated_at__gt")}
|
||||
|
||||
project = Project.objects.get(pk=project_id, workspace__slug=slug)
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
query_params = request.query_params.copy()
|
||||
|
||||
filters = issue_filters(query_params, "GET")
|
||||
order_by_param = request.GET.get("order_by", "-created_at")
|
||||
|
||||
issue_queryset = self.get_queryset().filter(**filters, **extra_filters)
|
||||
# Custom ordering for priority and state
|
||||
issue_queryset = self.get_queryset()
|
||||
|
||||
total_issue_queryset = Issue.issue_objects.filter(
|
||||
project_id=project_id, workspace__slug=slug
|
||||
).filter(**filters, **extra_filters)
|
||||
# Apply rich filters
|
||||
issue_queryset = self.filter_queryset(issue_queryset)
|
||||
|
||||
# Apply legacy filters
|
||||
issue_queryset = issue_queryset.filter(**filters, **extra_filters)
|
||||
|
||||
# Keeping a copy of the queryset before applying annotations
|
||||
filtered_issue_queryset = copy.deepcopy(issue_queryset)
|
||||
|
||||
# Applying annotations to the issue queryset
|
||||
issue_queryset = self.apply_annotations(issue_queryset)
|
||||
|
||||
# Issue queryset
|
||||
issue_queryset, order_by_param = order_issue_queryset(
|
||||
|
|
@ -292,14 +323,16 @@ class IssueViewSet(BaseViewSet):
|
|||
and not project.guest_view_all_features
|
||||
):
|
||||
issue_queryset = issue_queryset.filter(created_by=request.user)
|
||||
total_issue_queryset = total_issue_queryset.filter(created_by=request.user)
|
||||
filtered_issue_queryset = filtered_issue_queryset.filter(
|
||||
created_by=request.user
|
||||
)
|
||||
|
||||
if group_by:
|
||||
if sub_group_by:
|
||||
if group_by == sub_group_by:
|
||||
return Response(
|
||||
{
|
||||
"error": "Group by and sub group by cannot have same parameters"
|
||||
"error": "Group by and sub group by cannot have same parameters" # noqa: E501
|
||||
},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
|
@ -308,7 +341,7 @@ class IssueViewSet(BaseViewSet):
|
|||
request=request,
|
||||
order_by=order_by_param,
|
||||
queryset=issue_queryset,
|
||||
total_count_queryset=total_issue_queryset,
|
||||
total_count_queryset=filtered_issue_queryset,
|
||||
on_results=lambda issues: issue_on_results(
|
||||
group_by=group_by, issues=issues, sub_group_by=sub_group_by
|
||||
),
|
||||
|
|
@ -318,12 +351,14 @@ class IssueViewSet(BaseViewSet):
|
|||
slug=slug,
|
||||
project_id=project_id,
|
||||
filters=filters,
|
||||
queryset=filtered_issue_queryset,
|
||||
),
|
||||
sub_group_by_fields=issue_group_values(
|
||||
field=sub_group_by,
|
||||
slug=slug,
|
||||
project_id=project_id,
|
||||
filters=filters,
|
||||
queryset=filtered_issue_queryset,
|
||||
),
|
||||
group_by_field_name=group_by,
|
||||
sub_group_by_field_name=sub_group_by,
|
||||
|
|
@ -342,7 +377,7 @@ class IssueViewSet(BaseViewSet):
|
|||
request=request,
|
||||
order_by=order_by_param,
|
||||
queryset=issue_queryset,
|
||||
total_count_queryset=total_issue_queryset,
|
||||
total_count_queryset=filtered_issue_queryset,
|
||||
on_results=lambda issues: issue_on_results(
|
||||
group_by=group_by, issues=issues, sub_group_by=sub_group_by
|
||||
),
|
||||
|
|
@ -352,6 +387,7 @@ class IssueViewSet(BaseViewSet):
|
|||
slug=slug,
|
||||
project_id=project_id,
|
||||
filters=filters,
|
||||
queryset=filtered_issue_queryset,
|
||||
),
|
||||
group_by_field_name=group_by,
|
||||
count_filter=Q(
|
||||
|
|
@ -368,7 +404,7 @@ class IssueViewSet(BaseViewSet):
|
|||
order_by=order_by_param,
|
||||
request=request,
|
||||
queryset=issue_queryset,
|
||||
total_count_queryset=total_issue_queryset,
|
||||
total_count_queryset=filtered_issue_queryset,
|
||||
on_results=lambda issues: issue_on_results(
|
||||
group_by=group_by, issues=issues, sub_group_by=sub_group_by
|
||||
),
|
||||
|
|
@ -402,9 +438,11 @@ class IssueViewSet(BaseViewSet):
|
|||
notification=True,
|
||||
origin=base_host(request=request, is_app=True),
|
||||
)
|
||||
queryset = self.get_queryset()
|
||||
queryset = self.apply_annotations(queryset)
|
||||
issue = (
|
||||
issue_queryset_grouper(
|
||||
queryset=self.get_queryset().filter(pk=serializer.data["id"]),
|
||||
queryset=queryset.filter(pk=serializer.data["id"]),
|
||||
group_by=None,
|
||||
sub_group_by=None,
|
||||
)
|
||||
|
|
@ -609,9 +647,10 @@ class IssueViewSet(BaseViewSet):
|
|||
allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], creator=True, model=Issue
|
||||
)
|
||||
def partial_update(self, request, slug, project_id, pk=None):
|
||||
queryset = self.get_queryset()
|
||||
queryset = self.apply_annotations(queryset)
|
||||
issue = (
|
||||
self.get_queryset()
|
||||
.annotate(
|
||||
queryset.annotate(
|
||||
label_ids=Coalesce(
|
||||
ArrayAgg(
|
||||
"labels__id",
|
||||
|
|
@ -730,6 +769,9 @@ class IssueUserDisplayPropertyEndpoint(BaseAPIView):
|
|||
user=request.user, project_id=project_id
|
||||
)
|
||||
|
||||
issue_property.rich_filters = request.data.get(
|
||||
"rich_filters", issue_property.rich_filters
|
||||
)
|
||||
issue_property.filters = request.data.get("filters", issue_property.filters)
|
||||
issue_property.display_filters = request.data.get(
|
||||
"display_filters", issue_property.display_filters
|
||||
|
|
@ -969,6 +1011,59 @@ class IssuePaginatedViewSet(BaseViewSet):
|
|||
|
||||
|
||||
class IssueDetailEndpoint(BaseAPIView):
|
||||
filter_backends = (ComplexFilterBackend,)
|
||||
filterset_class = IssueFilterSet
|
||||
|
||||
def apply_annotations(self, issues):
|
||||
return (
|
||||
issues.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")
|
||||
)
|
||||
.annotate(
|
||||
sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"issue_assignee",
|
||||
queryset=IssueAssignee.objects.all(),
|
||||
)
|
||||
)
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"label_issue",
|
||||
queryset=IssueLabel.objects.all(),
|
||||
)
|
||||
)
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"issue_module",
|
||||
queryset=ModuleIssue.objects.all(),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
|
||||
def get(self, request, slug, project_id):
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
|
|
@ -1002,56 +1097,9 @@ class IssueDetailEndpoint(BaseAPIView):
|
|||
.values("id")
|
||||
)
|
||||
# Main issue query
|
||||
issue = (
|
||||
Issue.issue_objects.filter(workspace__slug=slug, project_id=project_id)
|
||||
.filter(Exists(permission_subquery))
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"issue_assignee",
|
||||
queryset=IssueAssignee.objects.all(),
|
||||
)
|
||||
)
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"label_issue",
|
||||
queryset=IssueLabel.objects.all(),
|
||||
)
|
||||
)
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"issue_module",
|
||||
queryset=ModuleIssue.objects.all(),
|
||||
)
|
||||
)
|
||||
.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")
|
||||
)
|
||||
.annotate(
|
||||
sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
)
|
||||
issue = Issue.issue_objects.filter(
|
||||
workspace__slug=slug, project_id=project_id
|
||||
).filter(Exists(permission_subquery))
|
||||
|
||||
# Add additional prefetch based on expand parameter
|
||||
if self.expand:
|
||||
|
|
@ -1070,8 +1118,20 @@ class IssueDetailEndpoint(BaseAPIView):
|
|||
)
|
||||
)
|
||||
|
||||
# Apply filtering from filterset
|
||||
issue = self.filter_queryset(issue)
|
||||
|
||||
# Apply legacy filters
|
||||
issue = issue.filter(**filters)
|
||||
|
||||
# Total count queryset
|
||||
total_issue_queryset = copy.deepcopy(issue)
|
||||
|
||||
# Applying annotations to the issue queryset
|
||||
issue = self.apply_annotations(issue)
|
||||
|
||||
order_by_param = request.GET.get("order_by", "-created_at")
|
||||
|
||||
# Issue queryset
|
||||
issue, order_by_param = order_issue_queryset(
|
||||
issue_queryset=issue, order_by_param=order_by_param
|
||||
|
|
@ -1079,7 +1139,8 @@ class IssueDetailEndpoint(BaseAPIView):
|
|||
return self.paginate(
|
||||
request=request,
|
||||
order_by=order_by_param,
|
||||
queryset=(issue),
|
||||
queryset=issue,
|
||||
total_count_queryset=total_issue_queryset,
|
||||
on_results=lambda issue: IssueListDetailSerializer(
|
||||
issue, many=True, fields=self.fields, expand=self.expand
|
||||
).data,
|
||||
|
|
|
|||
|
|
@ -904,6 +904,9 @@ class ModuleUserPropertiesEndpoint(BaseAPIView):
|
|||
module_properties.filters = request.data.get(
|
||||
"filters", module_properties.filters
|
||||
)
|
||||
module_properties.rich_filters = request.data.get(
|
||||
"rich_filters", module_properties.rich_filters
|
||||
)
|
||||
module_properties.display_filters = request.data.get(
|
||||
"display_filters", module_properties.display_filters
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
# Python imports
|
||||
import copy
|
||||
import json
|
||||
|
||||
from django.db.models import F, Func, OuterRef, Q, Subquery
|
||||
|
|
@ -31,8 +32,8 @@ from plane.utils.grouper import (
|
|||
from plane.utils.issue_filters import issue_filters
|
||||
from plane.utils.order_queryset import order_issue_queryset
|
||||
from plane.utils.paginator import GroupedOffsetPaginator, SubGroupedOffsetPaginator
|
||||
|
||||
# Module imports
|
||||
from plane.utils.filters import ComplexFilterBackend
|
||||
from plane.utils.filters import IssueFilterSet
|
||||
from .. import BaseViewSet
|
||||
from plane.utils.host import base_host
|
||||
|
||||
|
|
@ -42,20 +43,12 @@ class ModuleIssueViewSet(BaseViewSet):
|
|||
model = ModuleIssue
|
||||
webhook_event = "module_issue"
|
||||
bulk = True
|
||||
filter_backends = (ComplexFilterBackend,)
|
||||
filterset_class = IssueFilterSet
|
||||
|
||||
filterset_fields = ["issue__labels__id", "issue__assignees__id"]
|
||||
|
||||
def get_queryset(self):
|
||||
def apply_annotations(self, issues):
|
||||
return (
|
||||
Issue.issue_objects.filter(
|
||||
project_id=self.kwargs.get("project_id"),
|
||||
workspace__slug=self.kwargs.get("slug"),
|
||||
issue_module__module_id=self.kwargs.get("module_id"),
|
||||
issue_module__deleted_at__isnull=True,
|
||||
)
|
||||
.select_related("workspace", "project", "state", "parent")
|
||||
.prefetch_related("assignees", "labels", "issue_module__module")
|
||||
.annotate(
|
||||
issues.annotate(
|
||||
cycle_id=Subquery(
|
||||
CycleIssue.objects.filter(
|
||||
issue=OuterRef("id"), deleted_at__isnull=True
|
||||
|
|
@ -83,13 +76,37 @@ class ModuleIssueViewSet(BaseViewSet):
|
|||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
.prefetch_related("assignees", "labels", "issue_module__module")
|
||||
)
|
||||
|
||||
def get_queryset(self):
|
||||
return (
|
||||
Issue.issue_objects.filter(
|
||||
project_id=self.kwargs.get("project_id"),
|
||||
workspace__slug=self.kwargs.get("slug"),
|
||||
issue_module__module_id=self.kwargs.get("module_id"),
|
||||
issue_module__deleted_at__isnull=True,
|
||||
)
|
||||
).distinct()
|
||||
|
||||
@method_decorator(gzip_page)
|
||||
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
|
||||
def list(self, request, slug, project_id, module_id):
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
issue_queryset = self.get_queryset().filter(**filters)
|
||||
issue_queryset = self.get_queryset()
|
||||
|
||||
# Apply filtering from filterset
|
||||
issue_queryset = self.filter_queryset(issue_queryset)
|
||||
|
||||
# Apply legacy filters
|
||||
issue_queryset = issue_queryset.filter(**filters)
|
||||
|
||||
# Total count queryset
|
||||
total_issue_queryset = copy.deepcopy(issue_queryset)
|
||||
|
||||
# Apply annotations to the issue queryset
|
||||
issue_queryset = self.apply_annotations(issue_queryset)
|
||||
|
||||
order_by_param = request.GET.get("order_by", "created_at")
|
||||
|
||||
# Issue queryset
|
||||
|
|
@ -122,6 +139,7 @@ class ModuleIssueViewSet(BaseViewSet):
|
|||
request=request,
|
||||
order_by=order_by_param,
|
||||
queryset=issue_queryset,
|
||||
total_count_queryset=total_issue_queryset,
|
||||
on_results=lambda issues: issue_on_results(
|
||||
group_by=group_by, issues=issues, sub_group_by=sub_group_by
|
||||
),
|
||||
|
|
@ -131,12 +149,14 @@ class ModuleIssueViewSet(BaseViewSet):
|
|||
slug=slug,
|
||||
project_id=project_id,
|
||||
filters=filters,
|
||||
queryset=total_issue_queryset,
|
||||
),
|
||||
sub_group_by_fields=issue_group_values(
|
||||
field=sub_group_by,
|
||||
slug=slug,
|
||||
project_id=project_id,
|
||||
filters=filters,
|
||||
queryset=total_issue_queryset,
|
||||
),
|
||||
group_by_field_name=group_by,
|
||||
sub_group_by_field_name=sub_group_by,
|
||||
|
|
@ -156,6 +176,7 @@ class ModuleIssueViewSet(BaseViewSet):
|
|||
request=request,
|
||||
order_by=order_by_param,
|
||||
queryset=issue_queryset,
|
||||
total_count_queryset=total_issue_queryset,
|
||||
on_results=lambda issues: issue_on_results(
|
||||
group_by=group_by, issues=issues, sub_group_by=sub_group_by
|
||||
),
|
||||
|
|
@ -165,6 +186,7 @@ class ModuleIssueViewSet(BaseViewSet):
|
|||
slug=slug,
|
||||
project_id=project_id,
|
||||
filters=filters,
|
||||
queryset=total_issue_queryset,
|
||||
),
|
||||
group_by_field_name=group_by,
|
||||
count_filter=Q(
|
||||
|
|
@ -182,6 +204,7 @@ class ModuleIssueViewSet(BaseViewSet):
|
|||
order_by=order_by_param,
|
||||
request=request,
|
||||
queryset=issue_queryset,
|
||||
total_count_queryset=total_issue_queryset,
|
||||
on_results=lambda issues: issue_on_results(
|
||||
group_by=group_by, issues=issues, sub_group_by=sub_group_by
|
||||
),
|
||||
|
|
@ -282,9 +305,11 @@ class ModuleIssueViewSet(BaseViewSet):
|
|||
project_id=str(project_id),
|
||||
current_instance=json.dumps(
|
||||
{
|
||||
"module_name": module_issue.first().module.name
|
||||
if (module_issue.first() and module_issue.first().module)
|
||||
else None
|
||||
"module_name": (
|
||||
module_issue.first().module.name
|
||||
if (module_issue.first() and module_issue.first().module)
|
||||
else None
|
||||
)
|
||||
}
|
||||
),
|
||||
epoch=int(timezone.now().timestamp()),
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import copy
|
||||
|
||||
# Django imports
|
||||
from django.db.models import (
|
||||
Exists,
|
||||
|
|
@ -39,6 +41,8 @@ from plane.utils.order_queryset import order_issue_queryset
|
|||
from plane.bgtasks.recent_visited_task import recent_visited_task
|
||||
from .. import BaseViewSet
|
||||
from plane.db.models import UserFavorite
|
||||
from plane.utils.filters import ComplexFilterBackend
|
||||
from plane.utils.filters import IssueFilterSet
|
||||
|
||||
|
||||
class WorkspaceViewViewSet(BaseViewSet):
|
||||
|
|
@ -56,7 +60,6 @@ class WorkspaceViewViewSet(BaseViewSet):
|
|||
.filter(workspace__slug=self.kwargs.get("slug"))
|
||||
.filter(project__isnull=True)
|
||||
.filter(Q(owned_by=self.request.user) | Q(access=1))
|
||||
.select_related("workspace")
|
||||
.order_by(self.request.GET.get("order_by", "-created_at"))
|
||||
.distinct()
|
||||
)
|
||||
|
|
@ -145,6 +148,9 @@ class WorkspaceViewViewSet(BaseViewSet):
|
|||
|
||||
|
||||
class WorkspaceViewIssuesViewSet(BaseViewSet):
|
||||
filter_backends = (ComplexFilterBackend,)
|
||||
filterset_class = IssueFilterSet
|
||||
|
||||
def _get_project_permission_filters(self):
|
||||
"""
|
||||
Get common project permission filters for guest users and role-based access control.
|
||||
|
|
@ -167,35 +173,9 @@ class WorkspaceViewIssuesViewSet(BaseViewSet):
|
|||
project__project_projectmember__is_active=True,
|
||||
)
|
||||
|
||||
def get_queryset(self):
|
||||
def apply_annotations(self, issues):
|
||||
return (
|
||||
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"))
|
||||
.select_related("state")
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"issue_assignee",
|
||||
queryset=IssueAssignee.objects.all(),
|
||||
)
|
||||
)
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"label_issue",
|
||||
queryset=IssueLabel.objects.all(),
|
||||
)
|
||||
)
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"issue_module",
|
||||
queryset=ModuleIssue.objects.all(),
|
||||
)
|
||||
)
|
||||
.annotate(
|
||||
issues.annotate(
|
||||
cycle_id=Subquery(
|
||||
CycleIssue.objects.filter(
|
||||
issue=OuterRef("id"), deleted_at__isnull=True
|
||||
|
|
@ -223,32 +203,57 @@ class WorkspaceViewIssuesViewSet(BaseViewSet):
|
|||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"issue_assignee",
|
||||
queryset=IssueAssignee.objects.all(),
|
||||
)
|
||||
)
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"label_issue",
|
||||
queryset=IssueLabel.objects.all(),
|
||||
)
|
||||
)
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"issue_module",
|
||||
queryset=ModuleIssue.objects.all(),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def get_queryset(self):
|
||||
return Issue.issue_objects.filter(workspace__slug=self.kwargs.get("slug"))
|
||||
|
||||
@method_decorator(gzip_page)
|
||||
@allow_permission(
|
||||
allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE"
|
||||
)
|
||||
def list(self, request, slug):
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
issue_queryset = self.get_queryset()
|
||||
|
||||
# Apply filtering from filterset
|
||||
issue_queryset = self.filter_queryset(issue_queryset)
|
||||
|
||||
order_by_param = request.GET.get("order_by", "-created_at")
|
||||
|
||||
issue_queryset = self.get_queryset().filter(**filters)
|
||||
# Apply legacy filters
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
issue_queryset = issue_queryset.filter(**filters)
|
||||
|
||||
# Get common project permission filters
|
||||
permission_filters = self._get_project_permission_filters()
|
||||
|
||||
# Base query for the counts
|
||||
total_issue_count = (
|
||||
Issue.issue_objects.filter(**filters)
|
||||
.filter(workspace__slug=slug)
|
||||
.filter(permission_filters)
|
||||
.only("id")
|
||||
)
|
||||
|
||||
# Apply project permission filters to the issue queryset
|
||||
issue_queryset = issue_queryset.filter(permission_filters)
|
||||
|
||||
# Base query for the counts
|
||||
total_issue_count_queryset = copy.deepcopy(issue_queryset)
|
||||
total_issue_count_queryset = total_issue_count_queryset.only("id")
|
||||
|
||||
# Apply annotations to the issue queryset
|
||||
issue_queryset = self.apply_annotations(issue_queryset)
|
||||
|
||||
# Issue queryset
|
||||
issue_queryset, order_by_param = order_issue_queryset(
|
||||
issue_queryset=issue_queryset, order_by_param=order_by_param
|
||||
|
|
@ -260,7 +265,7 @@ class WorkspaceViewIssuesViewSet(BaseViewSet):
|
|||
request=request,
|
||||
queryset=issue_queryset,
|
||||
on_results=lambda issues: ViewIssueListSerializer(issues, many=True).data,
|
||||
total_count_queryset=total_issue_count,
|
||||
total_count_queryset=total_issue_count_queryset,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
# Python imports
|
||||
import copy
|
||||
from datetime import date
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
|
@ -56,6 +57,8 @@ from plane.utils.grouper import (
|
|||
from plane.utils.issue_filters import issue_filters
|
||||
from plane.utils.order_queryset import order_issue_queryset
|
||||
from plane.utils.paginator import GroupedOffsetPaginator, SubGroupedOffsetPaginator
|
||||
from plane.utils.filters import ComplexFilterBackend
|
||||
from plane.utils.filters import IssueFilterSet
|
||||
|
||||
|
||||
class UserLastProjectWithWorkspaceEndpoint(BaseAPIView):
|
||||
|
|
@ -91,23 +94,12 @@ class UserLastProjectWithWorkspaceEndpoint(BaseAPIView):
|
|||
class WorkspaceUserProfileIssuesEndpoint(BaseAPIView):
|
||||
permission_classes = [WorkspaceViewerPermission]
|
||||
|
||||
def get(self, request, slug, user_id):
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
filter_backends = (ComplexFilterBackend,)
|
||||
filterset_class = IssueFilterSet
|
||||
|
||||
order_by_param = request.GET.get("order_by", "-created_at")
|
||||
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,
|
||||
project__project_projectmember__is_active=True,
|
||||
)
|
||||
.filter(**filters)
|
||||
.select_related("workspace", "project", "state", "parent")
|
||||
.prefetch_related("assignees", "labels", "issue_module__module")
|
||||
.annotate(
|
||||
def apply_annotations(self, issues):
|
||||
return (
|
||||
issues.annotate(
|
||||
cycle_id=Subquery(
|
||||
CycleIssue.objects.filter(
|
||||
issue=OuterRef("id"), deleted_at__isnull=True
|
||||
|
|
@ -135,8 +127,36 @@ class WorkspaceUserProfileIssuesEndpoint(BaseAPIView):
|
|||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
.order_by("created_at")
|
||||
).distinct()
|
||||
.prefetch_related("assignees", "labels", "issue_module__module")
|
||||
)
|
||||
|
||||
def get(self, request, slug, user_id):
|
||||
filters = issue_filters(request.query_params, "GET")
|
||||
|
||||
order_by_param = request.GET.get("order_by", "-created_at")
|
||||
issue_queryset = Issue.issue_objects.filter(
|
||||
id__in=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,
|
||||
).values_list("id", flat=True),
|
||||
workspace__slug=slug,
|
||||
project__project_projectmember__member=request.user,
|
||||
project__project_projectmember__is_active=True,
|
||||
)
|
||||
|
||||
# Apply filtering from filterset
|
||||
issue_queryset = self.filter_queryset(issue_queryset)
|
||||
|
||||
# Apply legacy filters
|
||||
issue_queryset = issue_queryset.filter(**filters)
|
||||
|
||||
# Total count queryset
|
||||
total_issue_queryset = copy.deepcopy(issue_queryset)
|
||||
|
||||
# Apply annotations to the issue queryset
|
||||
issue_queryset = self.apply_annotations(issue_queryset)
|
||||
|
||||
# Issue queryset
|
||||
issue_queryset, order_by_param = order_issue_queryset(
|
||||
|
|
@ -157,7 +177,7 @@ class WorkspaceUserProfileIssuesEndpoint(BaseAPIView):
|
|||
if group_by == sub_group_by:
|
||||
return Response(
|
||||
{
|
||||
"error": "Group by and sub group by cannot have same parameters"
|
||||
"error": "Group by and sub group by cannot have same parameters" # noqa: E501
|
||||
},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
|
@ -166,15 +186,22 @@ class WorkspaceUserProfileIssuesEndpoint(BaseAPIView):
|
|||
request=request,
|
||||
order_by=order_by_param,
|
||||
queryset=issue_queryset,
|
||||
total_count_queryset=total_issue_queryset,
|
||||
on_results=lambda issues: issue_on_results(
|
||||
group_by=group_by, issues=issues, sub_group_by=sub_group_by
|
||||
),
|
||||
paginator_cls=SubGroupedOffsetPaginator,
|
||||
group_by_fields=issue_group_values(
|
||||
field=group_by, slug=slug, filters=filters
|
||||
field=group_by,
|
||||
slug=slug,
|
||||
filters=filters,
|
||||
queryset=total_issue_queryset,
|
||||
),
|
||||
sub_group_by_fields=issue_group_values(
|
||||
field=sub_group_by, slug=slug, filters=filters
|
||||
field=sub_group_by,
|
||||
slug=slug,
|
||||
filters=filters,
|
||||
queryset=total_issue_queryset,
|
||||
),
|
||||
group_by_field_name=group_by,
|
||||
sub_group_by_field_name=sub_group_by,
|
||||
|
|
@ -193,12 +220,16 @@ class WorkspaceUserProfileIssuesEndpoint(BaseAPIView):
|
|||
request=request,
|
||||
order_by=order_by_param,
|
||||
queryset=issue_queryset,
|
||||
total_count_queryset=total_issue_queryset,
|
||||
on_results=lambda issues: issue_on_results(
|
||||
group_by=group_by, issues=issues, sub_group_by=sub_group_by
|
||||
),
|
||||
paginator_cls=GroupedOffsetPaginator,
|
||||
group_by_fields=issue_group_values(
|
||||
field=group_by, slug=slug, filters=filters
|
||||
field=group_by,
|
||||
slug=slug,
|
||||
filters=filters,
|
||||
queryset=total_issue_queryset,
|
||||
),
|
||||
group_by_field_name=group_by,
|
||||
count_filter=Q(
|
||||
|
|
@ -215,6 +246,7 @@ class WorkspaceUserProfileIssuesEndpoint(BaseAPIView):
|
|||
order_by=order_by_param,
|
||||
request=request,
|
||||
queryset=issue_queryset,
|
||||
total_count_queryset=total_issue_queryset,
|
||||
on_results=lambda issues: issue_on_results(
|
||||
group_by=group_by, issues=issues, sub_group_by=sub_group_by
|
||||
),
|
||||
|
|
@ -232,6 +264,9 @@ class WorkspaceUserPropertiesEndpoint(BaseAPIView):
|
|||
workspace_properties.filters = request.data.get(
|
||||
"filters", workspace_properties.filters
|
||||
)
|
||||
workspace_properties.rich_filters = request.data.get(
|
||||
"rich_filters", workspace_properties.rich_filters
|
||||
)
|
||||
workspace_properties.display_filters = request.data.get(
|
||||
"display_filters", workspace_properties.display_filters
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue