mirror of
https://github.com/makeplane/plane.git
synced 2026-02-25 04:35:21 +01:00
fix: active cycles be fixes
This commit is contained in:
@@ -42,6 +42,7 @@ from .view import (
|
||||
)
|
||||
from .cycle import (
|
||||
CycleSerializer,
|
||||
ActiveCycleSerializer,
|
||||
CycleIssueSerializer,
|
||||
CycleFavoriteSerializer,
|
||||
CycleWriteSerializer,
|
||||
@@ -118,7 +119,10 @@ from .inbox import (
|
||||
|
||||
from .analytic import AnalyticViewSerializer
|
||||
|
||||
from .notification import NotificationSerializer, UserNotificationPreferenceSerializer
|
||||
from .notification import (
|
||||
NotificationSerializer,
|
||||
UserNotificationPreferenceSerializer,
|
||||
)
|
||||
|
||||
from .exporter import ExporterHistorySerializer
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ from rest_framework import serializers
|
||||
|
||||
# Module imports
|
||||
from .base import BaseSerializer
|
||||
from .project import ProjectLiteSerializer
|
||||
from .issue import IssueStateSerializer
|
||||
from plane.db.models import (
|
||||
Cycle,
|
||||
@@ -11,6 +12,7 @@ from plane.db.models import (
|
||||
CycleUserProperties,
|
||||
)
|
||||
|
||||
|
||||
class CycleWriteSerializer(BaseSerializer):
|
||||
def validate(self, data):
|
||||
if (
|
||||
@@ -47,6 +49,53 @@ class CycleSerializer(BaseSerializer):
|
||||
# active | draft | upcoming | completed
|
||||
status = serializers.CharField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Cycle
|
||||
fields = [
|
||||
# necessary fields
|
||||
"id",
|
||||
"workspace_id",
|
||||
"project_id",
|
||||
# model fields
|
||||
"name",
|
||||
"description",
|
||||
"start_date",
|
||||
"end_date",
|
||||
"owned_by_id",
|
||||
"view_props",
|
||||
"sort_order",
|
||||
"external_source",
|
||||
"external_id",
|
||||
"progress_snapshot",
|
||||
# meta fields
|
||||
"is_favorite",
|
||||
"total_issues",
|
||||
"cancelled_issues",
|
||||
"completed_issues",
|
||||
"started_issues",
|
||||
"unstarted_issues",
|
||||
"backlog_issues",
|
||||
"status",
|
||||
]
|
||||
read_only_fields = fields
|
||||
|
||||
|
||||
class ActiveCycleSerializer(BaseSerializer):
|
||||
# favorite
|
||||
is_favorite = serializers.BooleanField(read_only=True)
|
||||
total_issues = serializers.IntegerField(read_only=True)
|
||||
# state group wise distribution
|
||||
cancelled_issues = serializers.IntegerField(read_only=True)
|
||||
completed_issues = serializers.IntegerField(read_only=True)
|
||||
started_issues = serializers.IntegerField(read_only=True)
|
||||
unstarted_issues = serializers.IntegerField(read_only=True)
|
||||
backlog_issues = serializers.IntegerField(read_only=True)
|
||||
|
||||
# active | draft | upcoming | completed
|
||||
status = serializers.CharField(read_only=True)
|
||||
|
||||
# project details
|
||||
project_detail = ProjectLiteSerializer(read_only=True, source="project")
|
||||
|
||||
class Meta:
|
||||
model = Cycle
|
||||
@@ -75,6 +124,7 @@ class CycleSerializer(BaseSerializer):
|
||||
"unstarted_issues",
|
||||
"backlog_issues",
|
||||
"status",
|
||||
"project_detail",
|
||||
]
|
||||
read_only_fields = fields
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ from plane.app.serializers import (
|
||||
IssueSerializer,
|
||||
CycleWriteSerializer,
|
||||
CycleUserPropertiesSerializer,
|
||||
ActiveCycleSerializer,
|
||||
)
|
||||
from plane.app.permissions import (
|
||||
WorkspaceUserPermission,
|
||||
@@ -425,9 +426,8 @@ class CycleViewSet(WebhookMixin, BaseViewSet):
|
||||
)
|
||||
|
||||
def partial_update(self, request, slug, project_id, pk):
|
||||
queryset = (
|
||||
self.get_queryset()
|
||||
.filter(workspace__slug=slug, project_id=project_id, pk=pk)
|
||||
queryset = self.get_queryset().filter(
|
||||
workspace__slug=slug, project_id=project_id, pk=pk
|
||||
)
|
||||
cycle = queryset.first()
|
||||
request_data = request.data
|
||||
@@ -878,7 +878,9 @@ class CycleIssueViewSet(WebhookMixin, BaseViewSet):
|
||||
)
|
||||
|
||||
# Update the cycle issues
|
||||
CycleIssue.objects.bulk_update(updated_records, ["cycle_id"], batch_size=100)
|
||||
CycleIssue.objects.bulk_update(
|
||||
updated_records, ["cycle_id"], batch_size=100
|
||||
)
|
||||
# Capture Issue Activity
|
||||
issue_activity.delay(
|
||||
type="cycle.activity.created",
|
||||
@@ -1306,16 +1308,14 @@ class ActiveCycleEndpoint(BaseAPIView):
|
||||
"completion_chart": {},
|
||||
}
|
||||
if cycle["start_date"] and cycle["end_date"]:
|
||||
cycle["distribution"][
|
||||
"completion_chart"
|
||||
] = burndown_plot(
|
||||
cycle["distribution"]["completion_chart"] = burndown_plot(
|
||||
queryset=active_cycles.get(pk=cycle["id"]),
|
||||
slug=self.kwargs.get("slug"),
|
||||
project_id=cycle["project"],
|
||||
project_id=cycle["project_id"],
|
||||
cycle_id=cycle["id"],
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
def get(self, request, slug):
|
||||
subquery = CycleFavorite.objects.filter(
|
||||
user=self.request.user,
|
||||
@@ -1393,27 +1393,6 @@ class ActiveCycleEndpoint(BaseAPIView):
|
||||
),
|
||||
)
|
||||
)
|
||||
.annotate(total_estimates=Sum("issue_cycle__issue__estimate_point"))
|
||||
.annotate(
|
||||
completed_estimates=Sum(
|
||||
"issue_cycle__issue__estimate_point",
|
||||
filter=Q(
|
||||
issue_cycle__issue__state__group="completed",
|
||||
issue_cycle__issue__archived_at__isnull=True,
|
||||
issue_cycle__issue__is_draft=False,
|
||||
),
|
||||
)
|
||||
)
|
||||
.annotate(
|
||||
started_estimates=Sum(
|
||||
"issue_cycle__issue__estimate_point",
|
||||
filter=Q(
|
||||
issue_cycle__issue__state__group="started",
|
||||
issue_cycle__issue__archived_at__isnull=True,
|
||||
issue_cycle__issue__is_draft=False,
|
||||
),
|
||||
)
|
||||
)
|
||||
.annotate(
|
||||
status=Case(
|
||||
When(
|
||||
@@ -1421,7 +1400,9 @@ class ActiveCycleEndpoint(BaseAPIView):
|
||||
& Q(end_date__gte=timezone.now()),
|
||||
then=Value("CURRENT"),
|
||||
),
|
||||
When(start_date__gt=timezone.now(), then=Value("UPCOMING")),
|
||||
When(
|
||||
start_date__gt=timezone.now(), then=Value("UPCOMING")
|
||||
),
|
||||
When(end_date__lt=timezone.now(), then=Value("COMPLETED")),
|
||||
When(
|
||||
Q(start_date__isnull=True) & Q(end_date__isnull=True),
|
||||
@@ -1434,22 +1415,30 @@ class ActiveCycleEndpoint(BaseAPIView):
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"issue_cycle__issue__assignees",
|
||||
queryset=User.objects.only("avatar", "first_name", "id").distinct(),
|
||||
queryset=User.objects.only(
|
||||
"avatar", "first_name", "id"
|
||||
).distinct(),
|
||||
)
|
||||
)
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"issue_cycle__issue__labels",
|
||||
queryset=Label.objects.only("name", "color", "id").distinct(),
|
||||
queryset=Label.objects.only(
|
||||
"name", "color", "id"
|
||||
).distinct(),
|
||||
)
|
||||
)
|
||||
.order_by("-created_at")
|
||||
)
|
||||
|
||||
|
||||
return self.paginate(
|
||||
request=request,
|
||||
queryset=active_cycles,
|
||||
on_results=lambda active_cycles: CycleSerializer(active_cycles, many=True).data,
|
||||
controller=lambda results: self.get_results_controller(results, active_cycles),
|
||||
default_per_page=int(request.GET.get("per_page", 3))
|
||||
on_results=lambda active_cycles: ActiveCycleSerializer(
|
||||
active_cycles, many=True
|
||||
).data,
|
||||
controller=lambda results: self.get_results_controller(
|
||||
results, active_cycles
|
||||
),
|
||||
default_per_page=int(request.GET.get("per_page", 3)),
|
||||
)
|
||||
|
||||
5
packages/types/src/active-cycle.d.ts
vendored
Normal file
5
packages/types/src/active-cycle.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import type { IProjectLite, ICycle } from "@plane/types";
|
||||
|
||||
export interface IActiveCycle extends ICycle {
|
||||
project_detail: IProjectLite;
|
||||
}
|
||||
3
packages/types/src/index.d.ts
vendored
3
packages/types/src/index.d.ts
vendored
@@ -32,6 +32,9 @@ export * from "./api_token";
|
||||
export * from "./instance";
|
||||
export * from "./app";
|
||||
|
||||
// enterprise
|
||||
export * from "./active-cycle";
|
||||
|
||||
export type NestedKeyOf<ObjectType extends object> = {
|
||||
[Key in keyof ObjectType & (string | number)]: ObjectType[Key] extends object
|
||||
? ObjectType[Key] extends { pop: any; push: any }
|
||||
|
||||
Reference in New Issue
Block a user