from rest_framework import status from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated from rest_framework.generics import CreateAPIView, DestroyAPIView from rest_framework.exceptions import ValidationError from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi from apps.bookmark.models import Bookmark from apps.bookmark.serializers import BookmarkSerializer class AddBookmarkView(CreateAPIView): """ Add a bookmark for a specific content in a service. If the bookmark already exists but is inactive, it will be reactivated. """ permission_classes = [IsAuthenticated] serializer_class = BookmarkSerializer @swagger_auto_schema( operation_description="Add a bookmark for a specific content in a service. If the bookmark already exists but is inactive, it will be reactivated.", request_body=BookmarkSerializer, responses={ 201: "Bookmark created successfully.", 200: "Bookmark reactivated or already active.", 400: "Invalid input." } ) def create(self, request, *args, **kwargs): service = request.data.get('service') content_id = request.data.get('content_id') if not service or not content_id: return Response( {'error': 'Both service and content_id are required'}, status=status.HTTP_400_BAD_REQUEST ) # Check if the bookmark already exists bookmark = Bookmark.objects.filter( user=request.user, service=service, content_id=content_id ).first() if bookmark: # If bookmark exists but is inactive, reactivate it if not bookmark.status: bookmark.status = True bookmark.save() serializer = self.get_serializer(bookmark) return Response(serializer.data, status=status.HTTP_200_OK) # If bookmark exists and is active, return it serializer = self.get_serializer(bookmark) return Response(serializer.data, status=status.HTTP_200_OK) # Create a new bookmark serializer = self.get_serializer(data={ 'user': request.user.id, 'service': service, 'content_id': content_id, 'status': True }) serializer.is_valid(raise_exception=True) self.perform_create(serializer) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) class RemoveBookmarkView(DestroyAPIView): """ Deactivate a bookmark by setting its status to False using content_id and user. The request should specify the content_id of the bookmark to be deactivated. """ permission_classes = [IsAuthenticated] serializer_class = BookmarkSerializer @swagger_auto_schema( operation_description="Deactivate a bookmark by setting its status to False using content_id and user.", request_body=openapi.Schema( type=openapi.TYPE_OBJECT, properties={ 'service': openapi.Schema(type=openapi.TYPE_STRING, description='The service associated with the bookmark.'), 'content_id': openapi.Schema(type=openapi.TYPE_STRING, description='The ID of the content to deactivate the bookmark for.') }, required=['service', 'content_id'] ), responses={ 204: "Bookmark deactivated successfully.", 400: "Invalid input.", 404: "Bookmark not found or already inactive." } ) def get_object(self): service = self.request.data.get('service') content_id = self.request.data.get('content_id') if not service or not content_id: raise ValidationError('Both service and content_id are required') bookmark = Bookmark.objects.filter( user=self.request.user, service=service, content_id=content_id, status=True ).first() if not bookmark: raise ValidationError('Bookmark not found or already inactive') return bookmark def destroy(self, request, *args, **kwargs): bookmark = self.get_object() bookmark.status = False bookmark.save() return Response(status=status.HTTP_204_NO_CONTENT) class BookmarkStatusView(APIView): """ Return the count of bookmarks for each service for the current user. """ permission_classes = [IsAuthenticated] @swagger_auto_schema( operation_description="Return the count of bookmarks for each service for the current user.", responses={ 200: "A list of bookmark counts for each service.", } ) def get(self, request): # Get all active bookmarks for the current user user_bookmarks = Bookmark.objects.filter( user=request.user, status=True ) # Get the count of bookmarks for each service service_counts = {} for service_choice in Bookmark.ServiceChoices.choices: service_code = service_choice[0] # Get the service code (e.g., 'library') service_name = service_choice[1] # Get the service display name (e.g., 'Library') # Count bookmarks for this service count = user_bookmarks.filter(service=service_code).count() # Add to results service_counts[service_code] = { 'service': service_code, 'service_display': service_name, 'count': count } # Convert to list for response result = list(service_counts.values()) return Response(result, status=status.HTTP_200_OK)