diff --git a/backend/tasks/tasks/serializers.py b/backend/tasks/tasks/serializers.py index 12bea72..65ea0c2 100644 --- a/backend/tasks/tasks/serializers.py +++ b/backend/tasks/tasks/serializers.py @@ -1,7 +1,7 @@ from rest_framework import serializers from users.models import CustomUser from boards.models import ListBoard -from tasks.models import Todo, RecurrenceTask, Habit +from tasks.models import Todo, RecurrenceTask, Habit, Subtask class TaskSerializer(serializers.ModelSerializer): class Meta: @@ -97,4 +97,14 @@ class HabitTaskSerializer(serializers.ModelSerializer): class HabitTaskCreateSerializer(serializers.ModelSerializer): class Meta: model = Habit - exclude = ('tags',) \ No newline at end of file + exclude = ('tags',) + + +class SubTaskSerializer(serializers.ModelSerializer): + class Meta: + model = Subtask + fields = '__all__' + + def create(self, validated_data): + # Create a new task with validated data + return Todo.objects.create(**validated_data) \ No newline at end of file diff --git a/backend/tasks/tasks/views.py b/backend/tasks/tasks/views.py index fe1c82d..18a3410 100644 --- a/backend/tasks/tasks/views.py +++ b/backend/tasks/tasks/views.py @@ -4,10 +4,13 @@ from rest_framework import viewsets, status, serializers from rest_framework.decorators import action from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response +from rest_framework import mixins -from .serializers import ChangeTaskListBoardSerializer, ChangeTaskOrderSerializer +from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiParameter + +from tasks.tasks.serializers import ChangeTaskListBoardSerializer, ChangeTaskOrderSerializer, SubTaskSerializer from boards.models import ListBoard, KanbanTaskOrder -from tasks.models import Todo, RecurrenceTask, Habit +from tasks.models import Todo, RecurrenceTask, Habit, Subtask from tasks.tasks.serializers import (TaskCreateSerializer, TaskSerializer, RecurrenceTaskSerializer, @@ -117,6 +120,59 @@ class TodoViewSet(viewsets.ModelViewSet): return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) +@extend_schema_view( +list=extend_schema( + parameters=[ + OpenApiParameter(name='parent_task', description='Parent Task ID', type=int), + ] + ) +) +class SubTaskViewset(viewsets.GenericViewSet, + mixins.CreateModelMixin, + mixins.DestroyModelMixin, + mixins.ListModelMixin): + queryset = Subtask.objects.all() + permission_classes = (IsAuthenticated,) + + def get_serializer_class(self): + return SubTaskSerializer + + def list(self, request, *args, **kwargs): + """List only subtask of parent task.""" + try: + parent_task = request.query_params.get('parent_task') + if not parent_task: + raise serializers.ValidationError('parent_task is required.') + queryset = self.get_queryset().filter(parent_task_id=parent_task) + serializer = self.get_serializer(queryset, many=True) + return Response(serializer.data) + + except Exception as e: + return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + def create(self, request, *args, **kwargs): + """Create a new subtask, point to some parent tasks.""" + try: + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + self.perform_create(serializer) + return Response(serializer.data) + + except Exception as e: + return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + + def destroy(self, request, *args, **kwargs): + """Delete a subtask.""" + try: + instance = self.get_object() + self.perform_destroy(instance) + return Response(status=status.HTTP_204_NO_CONTENT) + + except Exception as e: + return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + class RecurrenceTaskViewSet(viewsets.ModelViewSet): queryset = RecurrenceTask.objects.all() serializer_class = RecurrenceTaskSerializer diff --git a/backend/tasks/urls.py b/backend/tasks/urls.py index d830a65..cf37e23 100644 --- a/backend/tasks/urls.py +++ b/backend/tasks/urls.py @@ -3,7 +3,7 @@ from django.urls import path, include from rest_framework.routers import DefaultRouter from tasks.api import GoogleCalendarEventViewset -from tasks.tasks.views import TodoViewSet, RecurrenceTaskViewSet, HabitTaskViewSet +from tasks.tasks.views import TodoViewSet, RecurrenceTaskViewSet, HabitTaskViewSet, SubTaskViewset from tasks.misc.views import TagViewSet @@ -13,6 +13,7 @@ router.register(r'daily', RecurrenceTaskViewSet) router.register(r'habit', HabitTaskViewSet) router.register(r'tags', TagViewSet) router.register(r'calendar-events', GoogleCalendarEventViewset, basename='calendar-events') +router.register(r'subtasks', SubTaskViewset, basename='subtasks') urlpatterns = [ path('', include(router.urls)),