Merge branch 'revamp-estimates' of gurusainath:makeplane/plane into revamp-estimates

This commit is contained in:
guru_sainath 2024-05-24 15:07:59 +05:30
commit 07e905f879
5 changed files with 110 additions and 35 deletions

View File

@ -4,6 +4,7 @@ from django.urls import path
from plane.app.views import (
ProjectEstimatePointEndpoint,
BulkEstimatePointEndpoint,
DeleteEstimatePoint,
)
@ -34,4 +35,9 @@ urlpatterns = [
),
name="bulk-create-estimate-points",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/estimates/<uuid:estimate_id>/estimate-point/<estimate_point_id>/",
DeleteEstimatePoint.as_view({"patch": "partial_update"}),
name="delete-estimate-points",
),
]

View File

@ -189,6 +189,7 @@ from .external.base import (
from .estimate.base import (
ProjectEstimatePointEndpoint,
BulkEstimatePointEndpoint,
DeleteEstimatePoint,
)
from .inbox.base import InboxViewSet, InboxIssueViewSet

View File

@ -1,3 +1,6 @@
import random
import string
# Third party imports
from rest_framework.response import Response
from rest_framework import status
@ -5,7 +8,7 @@ from rest_framework import status
# Module imports
from ..base import BaseViewSet, BaseAPIView
from plane.app.permissions import ProjectEntityPermission
from plane.db.models import Project, Estimate, EstimatePoint
from plane.db.models import Project, Estimate, EstimatePoint, Issue
from plane.app.serializers import (
EstimateSerializer,
EstimatePointSerializer,
@ -13,6 +16,12 @@ from plane.app.serializers import (
)
from plane.utils.cache import invalidate_cache
def generate_random_name(length=10):
letters = string.ascii_lowercase
return "".join(random.choice(letters) for i in range(length))
class ProjectEstimatePointEndpoint(BaseAPIView):
permission_classes = [
ProjectEntityPermission,
@ -49,13 +58,14 @@ class BulkEstimatePointEndpoint(BaseViewSet):
serializer = EstimateReadSerializer(estimates, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
@invalidate_cache(path="/api/workspaces/:slug/estimates/", url_params=True, user=False)
@invalidate_cache(
path="/api/workspaces/:slug/estimates/", url_params=True, user=False
)
def create(self, request, slug, project_id):
if not request.data.get("estimate", False):
return Response(
{"error": "Estimate is required"},
status=status.HTTP_400_BAD_REQUEST,
)
estimate_name = generate_random_name()
estimate = Estimate.objects.create(
name=estimate_name, project_id=project_id
)
estimate_points = request.data.get("estimate_points", [])
@ -67,14 +77,6 @@ class BulkEstimatePointEndpoint(BaseViewSet):
serializer.errors, status=status.HTTP_400_BAD_REQUEST
)
estimate_serializer = EstimateSerializer(
data=request.data.get("estimate")
)
if not estimate_serializer.is_valid():
return Response(
estimate_serializer.errors, status=status.HTTP_400_BAD_REQUEST
)
estimate = estimate_serializer.save(project_id=project_id)
estimate_points = EstimatePoint.objects.bulk_create(
[
EstimatePoint(
@ -99,7 +101,6 @@ class BulkEstimatePointEndpoint(BaseViewSet):
return Response(
{
"estimate": estimate_serializer.data,
"estimate_points": estimate_point_serializer.data,
},
status=status.HTTP_200_OK,
@ -115,13 +116,10 @@ class BulkEstimatePointEndpoint(BaseViewSet):
status=status.HTTP_200_OK,
)
@invalidate_cache(path="/api/workspaces/:slug/estimates/", url_params=True, user=False)
@invalidate_cache(
path="/api/workspaces/:slug/estimates/", url_params=True, user=False
)
def partial_update(self, request, slug, project_id, estimate_id):
if not request.data.get("estimate", False):
return Response(
{"error": "Estimate is required"},
status=status.HTTP_400_BAD_REQUEST,
)
if not len(request.data.get("estimate_points", [])):
return Response(
@ -129,17 +127,7 @@ class BulkEstimatePointEndpoint(BaseViewSet):
status=status.HTTP_400_BAD_REQUEST,
)
estimate = Estimate.objects.get(pk=estimate_id)
estimate_serializer = EstimateSerializer(
estimate, data=request.data.get("estimate"), partial=True
)
if not estimate_serializer.is_valid():
return Response(
estimate_serializer.errors, status=status.HTTP_400_BAD_REQUEST
)
estimate = estimate_serializer.save()
_ = Estimate.objects.get(pk=estimate_id)
estimate_points_data = request.data.get("estimate_points", [])
@ -178,16 +166,65 @@ class BulkEstimatePointEndpoint(BaseViewSet):
)
return Response(
{
"estimate": estimate_serializer.data,
"estimate_points": estimate_point_serializer.data,
},
status=status.HTTP_200_OK,
)
@invalidate_cache(path="/api/workspaces/:slug/estimates/", url_params=True, user=False)
@invalidate_cache(
path="/api/workspaces/:slug/estimates/", url_params=True, user=False
)
def destroy(self, request, slug, project_id, estimate_id):
estimate = Estimate.objects.get(
pk=estimate_id, workspace__slug=slug, project_id=project_id
)
estimate.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
class DeleteEstimatePoint(BaseViewSet):
permission_classes = [
ProjectEntityPermission,
]
def partial_update(
self, request, slug, project_id, estimate_id, estimate_point_id
):
new_estimate_id = request.data.get("new_estimate_id", None)
estimate_points = EstimatePoint.objects.filter(
estimate_id=estimate_id,
project_id=project_id,
workspace__slug=slug,
)
# update all the issues with the new estimate
if new_estimate_id:
_ = Issue.objects.filter(
project_id=project_id,
workspace__slug=slug,
estimate_id=estimate_point_id,
).update(estimate_id=new_estimate_id)
# delete the estimate point
old_estimate_point = EstimatePoint.objects.filter(
pk=estimate_point_id
).first()
# rearrange the estimate points
updated_estimate_points = []
for estimate_point in estimate_points:
if estimate_point.key > old_estimate_point.key:
estimate_point.key -= 1
updated_estimate_points.append(estimate_point)
EstimatePoint.objects.bulk_update(
updated_estimate_points,
["key"],
batch_size=10,
)
old_estimate_point.delete()
return Response(
EstimatePointSerializer(updated_estimate_points, many=True).data,
status=status.HTTP_200_OK,
)

View File

@ -0,0 +1,24 @@
# Generated by Django 4.2.7 on 2024-05-22 09:57
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("db", "0065_auto_20240415_0937"),
]
operations = [
migrations.AddField(
model_name="issue",
name="estimate",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="issue_estimate",
to="db.estimatepoint",
),
),
]

View File

@ -124,6 +124,13 @@ class Issue(ProjectBaseModel):
null=True,
blank=True,
)
estimate = models.ForeignKey(
"db.Estimate",
on_delete=models.SET_NULL,
related_name="issue_estimate",
null=True,
blank=True,
)
name = models.CharField(max_length=255, verbose_name="Issue Name")
description = models.JSONField(blank=True, default=dict)
description_html = models.TextField(blank=True, default="<p></p>")