diff --git a/apiserver/plane/app/views/cycle.py b/apiserver/plane/app/views/cycle.py index de4752806..f5701fc7e 100644 --- a/apiserver/plane/app/views/cycle.py +++ b/apiserver/plane/app/views/cycle.py @@ -39,6 +39,7 @@ from plane.app.serializers import ( from plane.app.permissions import ( ProjectEntityPermission, ProjectLitePermission, + WorkspaceUserPermission ) from plane.db.models import ( User, @@ -912,6 +913,9 @@ class CycleUserPropertiesEndpoint(BaseAPIView): class ActiveCycleEndpoint(BaseAPIView): + permission_classes = [ + WorkspaceUserPermission, + ] def get(self, request, slug): subquery = CycleFavorite.objects.filter( user=self.request.user, @@ -1043,4 +1047,110 @@ class ActiveCycleEndpoint(BaseAPIView): ) cycles = CycleSerializer(active_cycles, many=True).data + + for cycle in cycles: + assignee_distribution = ( + Issue.objects.filter( + issue_cycle__cycle_id=cycle["id"], + project_id=cycle["project"], + workspace__slug=slug, + ) + .annotate(display_name=F("assignees__display_name")) + .annotate(assignee_id=F("assignees__id")) + .annotate(avatar=F("assignees__avatar")) + .values("display_name", "assignee_id", "avatar") + .annotate( + total_issues=Count( + "assignee_id", + filter=Q(archived_at__isnull=True, is_draft=False), + ), + ) + .annotate( + completed_issues=Count( + "assignee_id", + filter=Q( + completed_at__isnull=False, + archived_at__isnull=True, + is_draft=False, + ), + ) + ) + .annotate( + pending_issues=Count( + "assignee_id", + filter=Q( + completed_at__isnull=True, + archived_at__isnull=True, + is_draft=False, + ), + ) + ) + .order_by("display_name") + ) + + label_distribution = ( + Issue.objects.filter( + issue_cycle__cycle_id=cycle["id"], + project_id=cycle["project"], + workspace__slug=slug, + ) + .annotate(label_name=F("labels__name")) + .annotate(color=F("labels__color")) + .annotate(label_id=F("labels__id")) + .values("label_name", "color", "label_id") + .annotate( + total_issues=Count( + "label_id", + filter=Q(archived_at__isnull=True, is_draft=False), + ) + ) + .annotate( + completed_issues=Count( + "label_id", + filter=Q( + completed_at__isnull=False, + archived_at__isnull=True, + is_draft=False, + ), + ) + ) + .annotate( + pending_issues=Count( + "label_id", + filter=Q( + completed_at__isnull=True, + archived_at__isnull=True, + is_draft=False, + ), + ) + ) + .order_by("label_name") + ) + cycle["distribution"] = { + "assignees": assignee_distribution, + "labels": label_distribution, + "completion_chart": {}, + } + if cycle["start_date"] and cycle["end_date"]: + cycle["distribution"][ + "completion_chart" + ] = burndown_plot( + queryset=active_cycles.get(pk=cycle["id"]), + slug=slug, + project_id=cycle["project"], + cycle_id=cycle["id"], + ) + + priority_issues = Issue.objects.filter(issue_cycle__cycle_id=cycle["id"], priority__in=["urgent", "high"]) + # Priority Ordering + priority_order = ["urgent", "high"] + priority_issues = priority_issues.annotate( + priority_order=Case( + *[When(priority=p, then=Value(i)) for i, p in enumerate(priority_order)], + output_field=CharField(), + ) + ).order_by("priority_order")[:5] + + cycle["issues"] = IssueSerializer(priority_issues, many=True).data + return Response(cycles, status=status.HTTP_200_OK)