|
27 | 27 | from plane.api.serializers import ( |
28 | 28 | CycleIssueSerializer, |
29 | 29 | CycleSerializer, |
| 30 | + CycleLiteSerializer, |
30 | 31 | CycleIssueRequestSerializer, |
31 | 32 | TransferCycleIssueRequestSerializer, |
32 | 33 | CycleCreateSerializer, |
|
46 | 47 | UserFavorite, |
47 | 48 | ) |
48 | 49 | from plane.utils.cycle_transfer_issues import transfer_cycle_issues |
49 | | -from plane.utils.order_queryset import ISSUE_ORDER_BY_ALLOWLIST, sanitize_order_by |
| 50 | +from plane.utils.order_queryset import CYCLE_ORDER_BY_ALLOWLIST, ISSUE_ORDER_BY_ALLOWLIST, sanitize_order_by |
50 | 51 | from plane.utils.host import base_host |
51 | 52 | from .base import BaseAPIView |
52 | 53 | from plane.bgtasks.webhook_task import model_activity |
@@ -356,6 +357,54 @@ def post(self, request, slug, project_id): |
356 | 357 | ) |
357 | 358 |
|
358 | 359 |
|
| 360 | +class CycleListLiteAPIEndpoint(BaseAPIView): |
| 361 | + """Cycle Lite List Endpoint""" |
| 362 | + |
| 363 | + serializer_class = CycleLiteSerializer |
| 364 | + model = Cycle |
| 365 | + permission_classes = [ProjectEntityPermission] |
| 366 | + use_read_replica = True |
| 367 | + |
| 368 | + @cycle_docs( |
| 369 | + operation_id="list_cycles_lite", |
| 370 | + summary="List cycles (lite)", |
| 371 | + description="Retrieve a paginated, lightweight list of cycles in a project for pickers and references.", |
| 372 | + parameters=[CURSOR_PARAMETER, PER_PAGE_PARAMETER, ORDER_BY_PARAMETER], |
| 373 | + responses={ |
| 374 | + 200: create_paginated_response( |
| 375 | + CycleLiteSerializer, |
| 376 | + "PaginatedCycleLiteResponse", |
| 377 | + "Paginated list of cycles with minimal fields", |
| 378 | + "Paginated Cycles (Lite)", |
| 379 | + ), |
| 380 | + }, |
| 381 | + ) |
| 382 | + def get(self, request, slug, project_id): |
| 383 | + """List cycles (lite) |
| 384 | +
|
| 385 | + Retrieve a paginated, lightweight list of non-archived cycles in a project, |
| 386 | + optimized for pickers and references. |
| 387 | + """ |
| 388 | + cycles = ( |
| 389 | + Cycle.objects.filter(workspace__slug=slug, project_id=project_id) |
| 390 | + .filter(archived_at__isnull=True) |
| 391 | + .select_related("project", "workspace", "owned_by") |
| 392 | + .order_by( |
| 393 | + sanitize_order_by( |
| 394 | + request.GET.get("order_by", "-created_at"), |
| 395 | + CYCLE_ORDER_BY_ALLOWLIST, |
| 396 | + default="-created_at", |
| 397 | + ) |
| 398 | + ) |
| 399 | + .distinct() |
| 400 | + ) |
| 401 | + return self.paginate( |
| 402 | + request=request, |
| 403 | + queryset=cycles, |
| 404 | + on_results=lambda cycles: CycleLiteSerializer(cycles, many=True).data, |
| 405 | + ) |
| 406 | + |
| 407 | + |
359 | 408 | class CycleDetailAPIEndpoint(BaseAPIView): |
360 | 409 | """ |
361 | 410 | This viewset automatically provides `retrieve`, `update` and `destroy` actions related to cycle. |
|
0 commit comments