diff --git a/apiserver/plane/api/urls.py b/apiserver/plane/api/urls.py index 93af9d762..73d3382a2 100644 --- a/apiserver/plane/api/urls.py +++ b/apiserver/plane/api/urls.py @@ -96,12 +96,8 @@ from plane.api.views import ( CycleViewSet, CycleIssueViewSet, CycleDateCheckEndpoint, - CurrentUpcomingCyclesEndpoint, - CompletedCyclesEndpoint, CycleFavoriteViewSet, - DraftCyclesEndpoint, TransferCycleIssueEndpoint, - InCompleteCyclesEndpoint, ## End Cycles # Modules ModuleViewSet, @@ -664,21 +660,6 @@ urlpatterns = [ CycleDateCheckEndpoint.as_view(), name="project-cycle", ), - path( - "workspaces//projects//cycles/current-upcoming-cycles/", - CurrentUpcomingCyclesEndpoint.as_view(), - name="project-cycle-upcoming", - ), - path( - "workspaces//projects//cycles/completed-cycles/", - CompletedCyclesEndpoint.as_view(), - name="project-cycle-completed", - ), - path( - "workspaces//projects//cycles/draft-cycles/", - DraftCyclesEndpoint.as_view(), - name="project-cycle-draft", - ), path( "workspaces//projects//user-favorite-cycles/", CycleFavoriteViewSet.as_view( @@ -703,11 +684,6 @@ urlpatterns = [ TransferCycleIssueEndpoint.as_view(), name="transfer-issues", ), - path( - "workspaces//projects//incomplete-cycles/", - InCompleteCyclesEndpoint.as_view(), - name="transfer-issues", - ), ## End Cycles # Issue path( diff --git a/apiserver/plane/api/views/__init__.py b/apiserver/plane/api/views/__init__.py index 65554f529..6b4cb52a7 100644 --- a/apiserver/plane/api/views/__init__.py +++ b/apiserver/plane/api/views/__init__.py @@ -49,12 +49,8 @@ from .cycle import ( CycleViewSet, CycleIssueViewSet, CycleDateCheckEndpoint, - CurrentUpcomingCyclesEndpoint, - CompletedCyclesEndpoint, CycleFavoriteViewSet, - DraftCyclesEndpoint, TransferCycleIssueEndpoint, - InCompleteCyclesEndpoint, ) from .asset import FileAssetEndpoint, UserAssetsEndpoint from .issue import ( diff --git a/apiserver/plane/api/views/cycle.py b/apiserver/plane/api/views/cycle.py index b12b49b2f..63c832e71 100644 --- a/apiserver/plane/api/views/cycle.py +++ b/apiserver/plane/api/views/cycle.py @@ -152,6 +152,75 @@ class CycleViewSet(BaseViewSet): .distinct() ) + def list(self, request, slug, project_id): + try: + queryset = self.get_queryset() + cycle_view = request.GET.get("cycle_view", False) + if not cycle_view: + return Response( + {"error": "Cycle View parameter is required"}, + status=status.HTTP_400_BAD_REQUEST, + ) + + # All Cycles + if cycle_view == "all": + return Response( + CycleSerializer(queryset, many=True).data, status=status.HTTP_200_OK + ) + + # Current Cycle + if cycle_view == "current": + queryset = queryset.filter( + start_date__lte=timezone.now(), + end_date__gte=timezone.now(), + ) + return Response( + CycleSerializer(queryset, many=True).data, status=status.HTTP_200_OK + ) + + # Upcoming Cycles + if cycle_view == "upcoming": + queryset = queryset.filter(start_date__gt=timezone.now()) + return Response( + CycleSerializer(queryset, many=True).data, status=status.HTTP_200_OK + ) + + # Completed Cycles + if cycle_view == "completed": + queryset = queryset.filter(end_date__lt=timezone.now()) + return Response( + CycleSerializer(queryset, many=True).data, status=status.HTTP_200_OK + ) + + # Draft Cycles + if cycle_view == "draft": + queryset = queryset.filter( + end_date=None, + start_date=None, + ) + return Response( + CycleSerializer(queryset, many=True).data, status=status.HTTP_200_OK + ) + + # Incomplete Cycles + if cycle_view == "incomplete": + queryset = queryset.filter( + Q(end_date__gte=timezone.now().date()) | Q(end_date__isnull=True), + ) + return Response( + CycleSerializer(queryset, many=True).data, status=status.HTTP_200_OK + ) + + return Response( + {"error": "No matching view found"}, status=status.HTTP_400_BAD_REQUEST + ) + except Exception as e: + capture_exception(e) + return Response( + {"error": "Something went wrong please try again later"}, + status=status.HTTP_400_BAD_REQUEST, + ) + def create(self, request, slug, project_id): try: if ( @@ -478,352 +547,6 @@ class CycleDateCheckEndpoint(BaseAPIView): ) -class CurrentUpcomingCyclesEndpoint(BaseAPIView): - permission_classes = [ - ProjectEntityPermission, - ] - - def get(self, request, slug, project_id): - try: - subquery = CycleFavorite.objects.filter( - user=self.request.user, - cycle_id=OuterRef("pk"), - project_id=project_id, - workspace__slug=slug, - ) - current_cycle = ( - Cycle.objects.filter( - workspace__slug=slug, - project_id=project_id, - start_date__lte=timezone.now(), - end_date__gte=timezone.now(), - ) - .select_related("project") - .select_related("workspace") - .select_related("owned_by") - .annotate(is_favorite=Exists(subquery)) - .annotate(total_issues=Count("issue_cycle")) - .annotate( - completed_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="completed"), - ) - ) - .annotate( - cancelled_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="cancelled"), - ) - ) - .annotate( - started_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="started"), - ) - ) - .annotate( - unstarted_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="unstarted"), - ) - ) - .annotate( - backlog_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="backlog"), - ) - ) - .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"), - ) - ) - .annotate( - started_estimates=Sum( - "issue_cycle__issue__estimate_point", - filter=Q(issue_cycle__issue__state__group="started"), - ) - ) - .prefetch_related( - Prefetch( - "issue_cycle__issue__assignees", - queryset=User.objects.only( - "avatar", "first_name", "id" - ).distinct(), - ) - ) - .order_by("name", "-is_favorite") - ) - - upcoming_cycle = ( - Cycle.objects.filter( - workspace__slug=slug, - project_id=project_id, - start_date__gt=timezone.now(), - ) - .select_related("project") - .select_related("workspace") - .select_related("owned_by") - .annotate(is_favorite=Exists(subquery)) - .annotate(total_issues=Count("issue_cycle")) - .annotate( - completed_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="completed"), - ) - ) - .annotate( - cancelled_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="cancelled"), - ) - ) - .annotate( - started_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="started"), - ) - ) - .annotate( - unstarted_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="unstarted"), - ) - ) - .annotate( - backlog_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="backlog"), - ) - ) - .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"), - ) - ) - .annotate( - started_estimates=Sum( - "issue_cycle__issue__estimate_point", - filter=Q(issue_cycle__issue__state__group="started"), - ) - ) - .prefetch_related( - Prefetch( - "issue_cycle__issue__assignees", - queryset=User.objects.only( - "avatar", "first_name", "id" - ).distinct(), - ) - ) - .order_by("name", "-is_favorite") - ) - - return Response( - { - "current_cycle": CycleSerializer(current_cycle, many=True).data, - "upcoming_cycle": CycleSerializer(upcoming_cycle, many=True).data, - }, - status=status.HTTP_200_OK, - ) - - except Exception as e: - capture_exception(e) - return Response( - {"error": "Something went wrong please try again later"}, - status=status.HTTP_400_BAD_REQUEST, - ) - - -class CompletedCyclesEndpoint(BaseAPIView): - permission_classes = [ - ProjectEntityPermission, - ] - - def get(self, request, slug, project_id): - try: - subquery = CycleFavorite.objects.filter( - user=self.request.user, - cycle_id=OuterRef("pk"), - project_id=project_id, - workspace__slug=slug, - ) - completed_cycles = ( - Cycle.objects.filter( - workspace__slug=slug, - project_id=project_id, - end_date__lt=timezone.now(), - ) - .select_related("project") - .select_related("workspace") - .select_related("owned_by") - .annotate(is_favorite=Exists(subquery)) - .annotate(total_issues=Count("issue_cycle")) - .annotate( - completed_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="completed"), - ) - ) - .annotate( - cancelled_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="cancelled"), - ) - ) - .annotate( - started_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="started"), - ) - ) - .annotate( - unstarted_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="unstarted"), - ) - ) - .annotate( - backlog_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="backlog"), - ) - ) - .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"), - ) - ) - .annotate( - started_estimates=Sum( - "issue_cycle__issue__estimate_point", - filter=Q(issue_cycle__issue__state__group="started"), - ) - ) - .prefetch_related( - Prefetch( - "issue_cycle__issue__assignees", - queryset=User.objects.only( - "avatar", "first_name", "id" - ).distinct(), - ) - ) - .order_by("name", "-is_favorite") - ) - - return Response( - { - "completed_cycles": CycleSerializer( - completed_cycles, many=True - ).data, - }, - status=status.HTTP_200_OK, - ) - - except Exception as e: - capture_exception(e) - return Response( - {"error": "Something went wrong please try again later"}, - status=status.HTTP_400_BAD_REQUEST, - ) - - -class DraftCyclesEndpoint(BaseAPIView): - permission_classes = [ - ProjectEntityPermission, - ] - - def get(self, request, slug, project_id): - try: - subquery = CycleFavorite.objects.filter( - user=self.request.user, - cycle_id=OuterRef("pk"), - project_id=project_id, - workspace__slug=slug, - ) - draft_cycles = ( - Cycle.objects.filter( - workspace__slug=slug, - project_id=project_id, - end_date=None, - start_date=None, - ) - .select_related("project") - .select_related("workspace") - .select_related("owned_by") - .annotate(is_favorite=Exists(subquery)) - .annotate(total_issues=Count("issue_cycle")) - .annotate( - completed_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="completed"), - ) - ) - .annotate( - cancelled_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="cancelled"), - ) - ) - .annotate( - started_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="started"), - ) - ) - .annotate( - unstarted_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="unstarted"), - ) - ) - .annotate( - backlog_issues=Count( - "issue_cycle__issue__state__group", - filter=Q(issue_cycle__issue__state__group="backlog"), - ) - ) - .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"), - ) - ) - .annotate( - started_estimates=Sum( - "issue_cycle__issue__estimate_point", - filter=Q(issue_cycle__issue__state__group="started"), - ) - ) - .prefetch_related( - Prefetch( - "issue_cycle__issue__assignees", - queryset=User.objects.only( - "avatar", "first_name", "id" - ).distinct(), - ) - ) - .order_by("name", "-is_favorite") - ) - - return Response( - {"draft_cycles": CycleSerializer(draft_cycles, many=True).data}, - status=status.HTTP_200_OK, - ) - except Exception as e: - capture_exception(e) - return Response( - {"error": "Something went wrong please try again later"}, - status=status.HTTP_400_BAD_REQUEST, - ) - - class CycleFavoriteViewSet(BaseViewSet): permission_classes = [ ProjectEntityPermission, @@ -948,22 +671,3 @@ class TransferCycleIssueEndpoint(BaseAPIView): {"error": "Something went wrong please try again later"}, status=status.HTTP_400_BAD_REQUEST, ) - - -class InCompleteCyclesEndpoint(BaseAPIView): - def get(self, request, slug, project_id): - try: - cycles = Cycle.objects.filter( - Q(end_date__gte=timezone.now().date()) | Q(end_date__isnull=True), - workspace__slug=slug, - project_id=project_id, - ).select_related("owned_by") - - serializer = CycleSerializer(cycles, many=True) - return Response(serializer.data, status=status.HTTP_200_OK) - except Exception as e: - capture_exception(e) - return Response( - {"error": "Something went wrong please try again later"}, - status=status.HTTP_400_BAD_REQUEST, - )