From 6873d0a174d9dbb73ff40900550c95a643699d7c Mon Sep 17 00:00:00 2001 From: sosokker Date: Tue, 21 Nov 2023 02:38:57 +0700 Subject: [PATCH] Add kanban position manage api --- backend/tasks/tasks/serializers.py | 41 ++++++++++++- backend/tasks/tasks/views.py | 93 +++++++++++++++++++++++++++++- 2 files changed, 131 insertions(+), 3 deletions(-) diff --git a/backend/tasks/tasks/serializers.py b/backend/tasks/tasks/serializers.py index 3098493..fd55d9f 100644 --- a/backend/tasks/tasks/serializers.py +++ b/backend/tasks/tasks/serializers.py @@ -1,5 +1,6 @@ from rest_framework import serializers -from ..models import Todo, RecurrenceTask, Habit +from boards.models import ListBoard +from tasks.models import Todo, RecurrenceTask, Habit class TaskSerializer(serializers.ModelSerializer): class Meta: @@ -14,7 +15,43 @@ class TaskCreateSerializer(serializers.ModelSerializer): class Meta: model = Todo exclude = ('tags',) - + +class ChangeTaskOrderSerializer(serializers.Serializer): + list_board_id = serializers.IntegerField( + help_text='ID of the ListBoard for which the task order should be updated.' + ) + todo_order = serializers.ListField( + child=serializers.IntegerField(), + required=False, + help_text='New order of Todo IDs in the ListBoard.' + ) + + def validate(self, data): + list_board_id = data.get('list_board_id') + todo_order = data.get('todo_order', []) + + if not ListBoard.objects.filter(id=list_board_id).exists(): + raise serializers.ValidationError('ListBoard does not exist.') + + return data + +class ChangeTaskListBoardSerializer(serializers.Serializer): + todo_id = serializers.IntegerField() + new_list_board_id = serializers.IntegerField() + new_index = serializers.IntegerField(required=False) + + def validate(self, data): + todo_id = data.get('todo_id') + new_list_board_id = data.get('new_list_board_id') + new_index = data.get('new_index') + + if not Todo.objects.filter(id=todo_id, user=self.context['request'].user).exists(): + raise serializers.ValidationError('Todo does not exist for the authenticated user.') + + if not ListBoard.objects.filter(id=new_list_board_id).exists(): + raise serializers.ValidationError('ListBoard does not exist.') + + return data class RecurrenceTaskSerializer(serializers.ModelSerializer): class Meta: diff --git a/backend/tasks/tasks/views.py b/backend/tasks/tasks/views.py index 87bbaca..4fc407d 100644 --- a/backend/tasks/tasks/views.py +++ b/backend/tasks/tasks/views.py @@ -1,5 +1,12 @@ -from rest_framework import viewsets +from django.shortcuts import get_object_or_404 +from django.db import IntegrityError +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 .serializers import ChangeTaskListBoardSerializer, ChangeTaskOrderSerializer +from boards.models import ListBoard, KanbanTaskOrder from tasks.models import Todo, RecurrenceTask, Habit from tasks.tasks.serializers import (TaskCreateSerializer, TaskSerializer, @@ -23,6 +30,90 @@ class TodoViewSet(viewsets.ModelViewSet): if self.action == 'create': return TaskCreateSerializer return TaskSerializer + + def create(self, request, *args, **kwargs): + try: + new_task_data = request.data + new_task_data['user'] = self.request.user + serializer = self.get_serializer(data=new_task_data) + 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) + + except IntegrityError as e: + return Response({'error': 'IntegrityError - Duplicate Entry'}, status=status.HTTP_400_BAD_REQUEST) + + except Exception as e: + return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + @action(detail=False, methods=['put']) + def change_task_order(self, request): + try: + serializer = ChangeTaskOrderSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + + list_board_id = serializer.validated_data['list_board_id'] + new_order = serializer.validated_data.get('todo_order', []) + + list_board = get_object_or_404(ListBoard, id=list_board_id) + kanban_order, created = KanbanTaskOrder.objects.get_or_create(list_board=list_board) + kanban_order.todo_order = new_order + kanban_order.save() + + return Response({'message': 'Task order updated successfully'}) + + except serializers.ValidationError as e: + return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) + + except Exception as e: + return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + @action(detail=False, methods=['put']) + def change_task_list_board(self, request): + try: + serializer = ChangeTaskListBoardSerializer(data=request.data, context={'request': request}) + serializer.is_valid(raise_exception=True) + + todo_id = serializer.validated_data['todo_id'] + new_list_board_id = serializer.validated_data['new_list_board_id'] + new_index = serializer.validated_data.get('new_index') + + todo_id = request.data.get('todo_id') + new_list_board_id = request.data.get('new_list_board_id') + + todo = get_object_or_404(Todo, id=todo_id, user=self.request.user) + old_list_board = todo.list_board + + # Remove todoId from todo_order of the old list board + old_kanban_order, _ = KanbanTaskOrder.objects.get_or_create(list_board=old_list_board) + old_kanban_order.todo_order = [t_id for t_id in old_kanban_order.todo_order if t_id != todo.id] + old_kanban_order.save() + + # Get the index to insert the todo in the new list board's todo_order + new_list_board = get_object_or_404(ListBoard, id=new_list_board_id) + new_kanban_order, _ = KanbanTaskOrder.objects.get_or_create(list_board=new_list_board) + + # Index where todo need to insert (start from 0) + new_index = request.data.get('new_index', None) + + if new_index is not None and 0 <= new_index <= len(new_kanban_order.todo_order): + new_kanban_order.todo_order.insert(new_index, todo.id) + else: + new_kanban_order.todo_order.append(todo.id) + + new_kanban_order.save() + + todo.list_board = new_list_board + todo.save() + + return Response({'message': 'ListBoard updated successfully'}) + + except serializers.ValidationError as e: + return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) + + except Exception as e: + return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) class RecurrenceTaskViewSet(viewsets.ModelViewSet):