mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 07:31:07 -05:00
feat: Add PrimeProgress, PrimeSelect, and PrimeSkeleton components with customizable styles and props
- Implemented PrimeProgress component with support for labels, helper text, and various styles (size, variant, color). - Created PrimeSelect component with dropdown functionality, custom templates, and validation states. - Developed PrimeSkeleton component for loading placeholders with different shapes and animations. - Updated index.ts to export new components for easy import. - Enhanced PrimeVueTest.vue to include tests for new components and their functionalities. - Introduced a custom ThrillWiki theme for PrimeVue with tailored color schemes and component styles. - Added ambient type declarations for various components to improve TypeScript support.
This commit is contained in:
@@ -2,7 +2,9 @@
|
||||
API viewsets for the ride ranking system.
|
||||
"""
|
||||
|
||||
from django.db.models import Q
|
||||
from typing import TYPE_CHECKING, Any, Type, cast
|
||||
|
||||
from django.db.models import Q, QuerySet
|
||||
from django.utils import timezone
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiParameter
|
||||
@@ -11,10 +13,15 @@ from rest_framework import status
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.filters import OrderingFilter
|
||||
from rest_framework.permissions import IsAuthenticatedOrReadOnly, AllowAny
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.serializers import BaseSerializer
|
||||
from rest_framework.viewsets import ReadOnlyModelViewSet
|
||||
from rest_framework.views import APIView
|
||||
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
|
||||
# Import models inside methods to avoid Django initialization issues
|
||||
from .serializers_rankings import (
|
||||
RideRankingSerializer,
|
||||
@@ -101,7 +108,7 @@ class RideRankingViewSet(ReadOnlyModelViewSet):
|
||||
]
|
||||
ordering = ["rank"]
|
||||
|
||||
def get_queryset(self):
|
||||
def get_queryset(self) -> QuerySet[Any]: # type: ignore
|
||||
"""Get rankings with optimized queries."""
|
||||
from apps.rides.models import RideRanking
|
||||
|
||||
@@ -109,13 +116,16 @@ class RideRankingViewSet(ReadOnlyModelViewSet):
|
||||
"ride", "ride__park", "ride__park__location", "ride__manufacturer"
|
||||
)
|
||||
|
||||
# Cast self.request to DRF Request so type checker recognizes query_params
|
||||
request = cast(Request, self.request)
|
||||
|
||||
# Filter by category
|
||||
category = self.request.query_params.get("category")
|
||||
category = request.query_params.get("category")
|
||||
if category:
|
||||
queryset = queryset.filter(ride__category=category)
|
||||
|
||||
# Filter by minimum mutual riders
|
||||
min_riders = self.request.query_params.get("min_riders")
|
||||
min_riders = request.query_params.get("min_riders")
|
||||
if min_riders:
|
||||
try:
|
||||
queryset = queryset.filter(mutual_riders_count__gte=int(min_riders))
|
||||
@@ -123,21 +133,21 @@ class RideRankingViewSet(ReadOnlyModelViewSet):
|
||||
pass
|
||||
|
||||
# Filter by park
|
||||
park_slug = self.request.query_params.get("park")
|
||||
park_slug = request.query_params.get("park")
|
||||
if park_slug:
|
||||
queryset = queryset.filter(ride__park__slug=park_slug)
|
||||
|
||||
return queryset
|
||||
|
||||
def get_serializer_class(self):
|
||||
def get_serializer_class(self) -> Any: # type: ignore[override]
|
||||
"""Use different serializers for list vs detail."""
|
||||
if self.action == "retrieve":
|
||||
return RideRankingDetailSerializer
|
||||
return cast(Type[BaseSerializer], RideRankingDetailSerializer)
|
||||
elif self.action == "history":
|
||||
return RankingSnapshotSerializer
|
||||
return cast(Type[BaseSerializer], RankingSnapshotSerializer)
|
||||
elif self.action == "statistics":
|
||||
return RankingStatsSerializer
|
||||
return RideRankingSerializer
|
||||
return cast(Type[BaseSerializer], RankingStatsSerializer)
|
||||
return cast(Type[BaseSerializer], RideRankingSerializer)
|
||||
|
||||
@action(detail=True, methods=["get"])
|
||||
def history(self, request, ride_slug=None):
|
||||
@@ -246,6 +256,12 @@ class RideRankingViewSet(ReadOnlyModelViewSet):
|
||||
serializer = RankingStatsSerializer(stats)
|
||||
return Response(serializer.data)
|
||||
|
||||
@extend_schema(
|
||||
summary="Get ride comparisons",
|
||||
description="Get head-to-head comparisons for a specific ride",
|
||||
responses={200: OpenApiTypes.OBJECT},
|
||||
tags=["Rankings"],
|
||||
)
|
||||
@action(detail=True, methods=["get"])
|
||||
def comparisons(self, request, ride_slug=None):
|
||||
"""Get head-to-head comparisons for a specific ride."""
|
||||
@@ -331,7 +347,27 @@ class TriggerRankingCalculationView(APIView):
|
||||
{"error": "Admin access required"}, status=status.HTTP_403_FORBIDDEN
|
||||
)
|
||||
|
||||
from apps.rides.services import RideRankingService
|
||||
# Replace direct import with a guarded runtime import to avoid static-analysis/initialization errors
|
||||
try:
|
||||
from apps.rides.services import RideRankingService # type: ignore
|
||||
except Exception:
|
||||
RideRankingService = None # type: ignore
|
||||
|
||||
# Attempt a dynamic import as a fallback if the direct import failed
|
||||
if RideRankingService is None:
|
||||
try:
|
||||
import importlib
|
||||
|
||||
_services_mod = importlib.import_module("apps.rides.services")
|
||||
RideRankingService = getattr(_services_mod, "RideRankingService", None)
|
||||
except Exception:
|
||||
RideRankingService = None
|
||||
|
||||
if not RideRankingService:
|
||||
return Response(
|
||||
{"error": "Ranking service unavailable"},
|
||||
status=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
)
|
||||
|
||||
category = request.data.get("category")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user