Skip to content

Commit

Permalink
[WEB-402] chore: project issues count (#3911)
Browse files Browse the repository at this point in the history
* chore: added project issues count

* chore: project module and cycle issue count

* chore: resolved merge conflicts

* chore: added import statement

* chore: issue count type added

* chore: issue count added in project, cycle and module issues

* fix: lint fixes

* chore: tooltip added in issue count badge

* chore: tooltip added in issue count badge

---------

Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>
Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
  • Loading branch information
3 people authored Mar 11, 2024
1 parent b57c389 commit 01702e9
Show file tree
Hide file tree
Showing 13 changed files with 256 additions and 51 deletions.
3 changes: 2 additions & 1 deletion apiserver/plane/app/serializers/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,10 @@ class Meta:

class ModuleDetailSerializer(ModuleSerializer):
link_module = ModuleLinkSerializer(read_only=True, many=True)
sub_issues = serializers.IntegerField(read_only=True)

class Meta(ModuleSerializer.Meta):
fields = ModuleSerializer.Meta.fields + ["link_module"]
fields = ModuleSerializer.Meta.fields + ["link_module", "sub_issues"]


class ModuleFavoriteSerializer(BaseSerializer):
Expand Down
6 changes: 6 additions & 0 deletions apiserver/plane/app/serializers/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ class Meta:


class ProjectListSerializer(DynamicBaseSerializer):
total_issues = serializers.IntegerField(read_only=True)
archived_issues = serializers.IntegerField(read_only=True)
archived_sub_issues = serializers.IntegerField(read_only=True)
draft_issues = serializers.IntegerField(read_only=True)
draft_sub_issues = serializers.IntegerField(read_only=True)
sub_issues = serializers.IntegerField(read_only=True)
is_favorite = serializers.BooleanField(read_only=True)
total_members = serializers.IntegerField(read_only=True)
total_cycles = serializers.IntegerField(read_only=True)
Expand Down
62 changes: 41 additions & 21 deletions apiserver/plane/app/views/cycle/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,6 @@ def get_queryset(self):
)
)
.annotate(is_favorite=Exists(favorite_subquery))
.annotate(
total_issues=Count(
"issue_cycle",
filter=Q(
issue_cycle__issue__archived_at__isnull=True,
issue_cycle__issue__is_draft=False,
),
)
)
.annotate(
completed_issues=Count(
"issue_cycle__issue__state__group",
Expand Down Expand Up @@ -232,7 +223,6 @@ def list(self, request, slug, project_id):
"progress_snapshot",
# meta fields
"is_favorite",
"total_issues",
"cancelled_issues",
"completed_issues",
"started_issues",
Expand Down Expand Up @@ -327,13 +317,13 @@ def list(self, request, slug, project_id):
}

if data[0]["start_date"] and data[0]["end_date"]:
data[0]["distribution"][
"completion_chart"
] = burndown_plot(
queryset=queryset.first(),
slug=slug,
project_id=project_id,
cycle_id=data[0]["id"],
data[0]["distribution"]["completion_chart"] = (
burndown_plot(
queryset=queryset.first(),
slug=slug,
project_id=project_id,
cycle_id=data[0]["id"],
)
)

return Response(data, status=status.HTTP_200_OK)
Expand All @@ -356,7 +346,6 @@ def list(self, request, slug, project_id):
"progress_snapshot",
# meta fields
"is_favorite",
"total_issues",
"cancelled_issues",
"completed_issues",
"started_issues",
Expand Down Expand Up @@ -402,7 +391,6 @@ def create(self, request, slug, project_id):
"progress_snapshot",
# meta fields
"is_favorite",
"total_issues",
"cancelled_issues",
"completed_issues",
"started_issues",
Expand Down Expand Up @@ -474,7 +462,6 @@ def partial_update(self, request, slug, project_id, pk):
"progress_snapshot",
# meta fields
"is_favorite",
"total_issues",
"cancelled_issues",
"completed_issues",
"started_issues",
Expand All @@ -487,10 +474,42 @@ def partial_update(self, request, slug, project_id, pk):
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

def retrieve(self, request, slug, project_id, pk):
queryset = self.get_queryset().filter(pk=pk)
queryset = (
self.get_queryset()
.filter(pk=pk)
.annotate(
total_issues=Count(
"issue_cycle",
filter=Q(
issue_cycle__issue__archived_at__isnull=True,
issue_cycle__issue__is_draft=False,
),
)
)
)
data = (
self.get_queryset()
.filter(pk=pk)
.annotate(
total_issues=Issue.issue_objects.filter(
project_id=self.kwargs.get("project_id"),
parent__isnull=True,
issue_cycle__cycle_id=pk,
)
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
)
.annotate(
sub_issues=Issue.issue_objects.filter(
project_id=self.kwargs.get("project_id"),
parent__isnull=False,
issue_cycle__cycle_id=pk,
)
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
)
.values(
# necessary fields
"id",
Expand All @@ -507,6 +526,7 @@ def retrieve(self, request, slug, project_id, pk):
"external_source",
"external_id",
"progress_snapshot",
"sub_issues",
# meta fields
"is_favorite",
"total_issues",
Expand Down
39 changes: 25 additions & 14 deletions apiserver/plane/app/views/module/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

# Django Imports
from django.utils import timezone
from django.db.models import Prefetch, F, OuterRef, Exists, Count, Q
from django.db.models import Prefetch, F, OuterRef, Exists, Count, Q, Func
from django.contrib.postgres.aggregates import ArrayAgg
from django.contrib.postgres.fields import ArrayField
from django.db.models import Value, UUIDField
Expand Down Expand Up @@ -79,15 +79,6 @@ def get_queryset(self):
),
)
)
.annotate(
total_issues=Count(
"issue_module",
filter=Q(
issue_module__issue__archived_at__isnull=True,
issue_module__issue__is_draft=False,
),
),
)
.annotate(
completed_issues=Count(
"issue_module__issue__state__group",
Expand Down Expand Up @@ -183,7 +174,6 @@ def create(self, request, slug, project_id):
"external_id",
# computed fields
"is_favorite",
"total_issues",
"cancelled_issues",
"completed_issues",
"started_issues",
Expand Down Expand Up @@ -225,7 +215,6 @@ def list(self, request, slug, project_id):
"external_id",
# computed fields
"is_favorite",
"total_issues",
"cancelled_issues",
"completed_issues",
"started_issues",
Expand All @@ -237,7 +226,30 @@ def list(self, request, slug, project_id):
return Response(modules, status=status.HTTP_200_OK)

def retrieve(self, request, slug, project_id, pk):
queryset = self.get_queryset().filter(pk=pk)
queryset = (
self.get_queryset()
.filter(pk=pk)
.annotate(
total_issues=Issue.issue_objects.filter(
project_id=self.kwargs.get("project_id"),
parent__isnull=True,
issue_module__module_id=pk,
)
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
)
.annotate(
sub_issues=Issue.issue_objects.filter(
project_id=self.kwargs.get("project_id"),
parent__isnull=False,
issue_module__module_id=pk,
)
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
)
)

assignee_distribution = (
Issue.objects.filter(
Expand Down Expand Up @@ -380,7 +392,6 @@ def partial_update(self, request, slug, project_id, pk):
"external_id",
# computed fields
"is_favorite",
"total_issues",
"cancelled_issues",
"completed_issues",
"started_issues",
Expand Down
70 changes: 70 additions & 0 deletions apiserver/plane/app/views/project/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,11 @@
Inbox,
ProjectDeployBoard,
IssueProperty,
Issue,
)
from plane.utils.cache import cache_response


class ProjectViewSet(WebhookMixin, BaseViewSet):
serializer_class = ProjectListSerializer
model = Project
Expand Down Expand Up @@ -171,6 +173,73 @@ def list(self, request, slug):
).data
return Response(projects, status=status.HTTP_200_OK)

def retrieve(self, request, slug, pk):
project = (
self.get_queryset()
.filter(pk=pk)
.annotate(
total_issues=Issue.issue_objects.filter(
project_id=self.kwargs.get("pk"),
parent__isnull=True,
)
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
)
.annotate(
sub_issues=Issue.issue_objects.filter(
project_id=self.kwargs.get("pk"),
parent__isnull=False,
)
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
)
.annotate(
archived_issues=Issue.objects.filter(
project_id=self.kwargs.get("pk"),
archived_at__isnull=False,
parent__isnull=True,
)
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
)
.annotate(
archived_sub_issues=Issue.objects.filter(
project_id=self.kwargs.get("pk"),
archived_at__isnull=False,
parent__isnull=False,
)
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
)
.annotate(
draft_issues=Issue.objects.filter(
project_id=self.kwargs.get("pk"),
is_draft=True,
parent__isnull=True,
)
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
)
.annotate(
draft_sub_issues=Issue.objects.filter(
project_id=self.kwargs.get("pk"),
is_draft=True,
parent__isnull=False,
)
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
)
).first()

serializer = ProjectListSerializer(project)
return Response(serializer.data, status=status.HTTP_200_OK)

def create(self, request, slug):
try:
workspace = Workspace.objects.get(slug=slug)
Expand Down Expand Up @@ -471,6 +540,7 @@ class ProjectPublicCoverImagesEndpoint(BaseAPIView):
permission_classes = [
AllowAny,
]

# Cache the below api for 24 hours
@cache_response(60 * 60 * 24, user=False)
def get(self, request):
Expand Down
1 change: 1 addition & 0 deletions packages/types/src/cycle/cycle.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface ICycle {
sort_order: number;
start_date: string | null;
started_issues: number;
sub_issues: number;
total_issues: number;
unstarted_issues: number;
updated_at: Date;
Expand Down
1 change: 1 addition & 0 deletions packages/types/src/modules.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export interface IModule {
name: string;
project_id: string;
sort_order: number;
sub_issues: number;
start_date: string | null;
started_issues: number;
status: TModuleStatus;
Expand Down
6 changes: 6 additions & 0 deletions packages/types/src/projects.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export type TProjectLogoProps = {

export interface IProject {
archive_in: number;
archived_issues: number;
archived_sub_issues: number;
close_in: number;
created_at: Date;
created_by: string;
Expand All @@ -35,6 +37,8 @@ export interface IProject {
default_assignee: IUser | string | null;
default_state: string | null;
description: string;
draft_issues: number;
draft_sub_issues: number;
estimate: string | null;
id: string;
identifier: string;
Expand All @@ -48,7 +52,9 @@ export interface IProject {
network: number;
project_lead: IUserLite | string | null;
sort_order: number | null;
sub_issues: number;
total_cycles: number;
total_issues: number;
total_members: number;
total_modules: number;
updated_at: Date;
Expand Down
Loading

0 comments on commit 01702e9

Please sign in to comment.