mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: removed bulk operations
This commit is contained in:
parent
ddf7ac856a
commit
e17396b8d4
@ -20,8 +20,6 @@ from plane.app.views import (
|
|||||||
IssueViewSet,
|
IssueViewSet,
|
||||||
LabelViewSet,
|
LabelViewSet,
|
||||||
IssueDescriptionViewSet,
|
IssueDescriptionViewSet,
|
||||||
BulkIssueOperationsEndpoint,
|
|
||||||
BulkArchiveIssuesEndpoint,
|
|
||||||
ArchivedIssueDescriptionViewSet,
|
ArchivedIssueDescriptionViewSet,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -95,11 +93,6 @@ urlpatterns = [
|
|||||||
BulkDeleteIssuesEndpoint.as_view(),
|
BulkDeleteIssuesEndpoint.as_view(),
|
||||||
name="project-issues-bulk",
|
name="project-issues-bulk",
|
||||||
),
|
),
|
||||||
path(
|
|
||||||
"workspaces/<str:slug>/projects/<uuid:project_id>/bulk-archive-issues/",
|
|
||||||
BulkArchiveIssuesEndpoint.as_view(),
|
|
||||||
name="bulk-archive-issues",
|
|
||||||
),
|
|
||||||
##
|
##
|
||||||
path(
|
path(
|
||||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:issue_id>/sub-issues/",
|
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:issue_id>/sub-issues/",
|
||||||
@ -327,11 +320,6 @@ urlpatterns = [
|
|||||||
),
|
),
|
||||||
name="project-issue-draft",
|
name="project-issue-draft",
|
||||||
),
|
),
|
||||||
path(
|
|
||||||
"workspaces/<str:slug>/projects/<uuid:project_id>/bulk-operation-issues/",
|
|
||||||
BulkIssueOperationsEndpoint.as_view(),
|
|
||||||
name="bulk-operations-issues",
|
|
||||||
),
|
|
||||||
path(
|
path(
|
||||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issue-drafts/<uuid:pk>/description/",
|
"workspaces/<str:slug>/projects/<uuid:project_id>/issue-drafts/<uuid:pk>/description/",
|
||||||
IssueDraftViewSet.as_view(
|
IssueDraftViewSet.as_view(
|
||||||
|
@ -114,7 +114,7 @@ from .issue.activity import (
|
|||||||
IssueActivityEndpoint,
|
IssueActivityEndpoint,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .issue.archive import IssueArchiveViewSet, BulkArchiveIssuesEndpoint
|
from .issue.archive import IssueArchiveViewSet
|
||||||
from .issue.archive import IssueArchiveViewSet, ArchivedIssueDescriptionViewSet
|
from .issue.archive import IssueArchiveViewSet, ArchivedIssueDescriptionViewSet
|
||||||
|
|
||||||
from .issue.attachment import (
|
from .issue.attachment import (
|
||||||
@ -153,9 +153,6 @@ from .issue.subscriber import (
|
|||||||
IssueSubscriberViewSet,
|
IssueSubscriberViewSet,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
from .issue.bulk_operations import BulkIssueOperationsEndpoint
|
|
||||||
|
|
||||||
from .module.base import (
|
from .module.base import (
|
||||||
ModuleViewSet,
|
ModuleViewSet,
|
||||||
ModuleLinkViewSet,
|
ModuleLinkViewSet,
|
||||||
|
@ -5,6 +5,7 @@ import base64
|
|||||||
# Django imports
|
# Django imports
|
||||||
from django.contrib.postgres.aggregates import ArrayAgg
|
from django.contrib.postgres.aggregates import ArrayAgg
|
||||||
from django.contrib.postgres.fields import ArrayField
|
from django.contrib.postgres.fields import ArrayField
|
||||||
|
from django.http import StreamingHttpResponse
|
||||||
from django.core.serializers.json import DjangoJSONEncoder
|
from django.core.serializers.json import DjangoJSONEncoder
|
||||||
from django.db.models import (
|
from django.db.models import (
|
||||||
Exists,
|
Exists,
|
||||||
|
@ -1,288 +0,0 @@
|
|||||||
# Python imports
|
|
||||||
import json
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
# Django imports
|
|
||||||
from django.utils import timezone
|
|
||||||
|
|
||||||
# Third Party imports
|
|
||||||
from rest_framework.response import Response
|
|
||||||
from rest_framework import status
|
|
||||||
|
|
||||||
# Module imports
|
|
||||||
from .. import BaseAPIView
|
|
||||||
from plane.app.permissions import (
|
|
||||||
ProjectEntityPermission,
|
|
||||||
)
|
|
||||||
from plane.db.models import (
|
|
||||||
Project,
|
|
||||||
Issue,
|
|
||||||
IssueLabel,
|
|
||||||
IssueAssignee,
|
|
||||||
)
|
|
||||||
from plane.bgtasks.issue_activites_task import issue_activity
|
|
||||||
|
|
||||||
|
|
||||||
class BulkIssueOperationsEndpoint(BaseAPIView):
|
|
||||||
permission_classes = [
|
|
||||||
ProjectEntityPermission,
|
|
||||||
]
|
|
||||||
|
|
||||||
def post(self, request, slug, project_id):
|
|
||||||
issue_ids = request.data.get("issue_ids", [])
|
|
||||||
if not len(issue_ids):
|
|
||||||
return Response(
|
|
||||||
{"error": "Issue IDs are required"},
|
|
||||||
status=status.HTTP_400_BAD_REQUEST,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Get all the issues
|
|
||||||
issues = (
|
|
||||||
Issue.objects.filter(
|
|
||||||
workspace__slug=slug, project_id=project_id, pk__in=issue_ids
|
|
||||||
)
|
|
||||||
.select_related("state")
|
|
||||||
.prefetch_related("labels", "assignees")
|
|
||||||
)
|
|
||||||
# Current epoch
|
|
||||||
epoch = int(timezone.now().timestamp())
|
|
||||||
|
|
||||||
# Project details
|
|
||||||
project = Project.objects.get(workspace__slug=slug, pk=project_id)
|
|
||||||
workspace_id = project.workspace_id
|
|
||||||
|
|
||||||
# Initialize arrays
|
|
||||||
bulk_update_issues = []
|
|
||||||
bulk_issue_activities = []
|
|
||||||
bulk_update_issue_labels = []
|
|
||||||
bulk_update_issue_assignees = []
|
|
||||||
|
|
||||||
properties = request.data.get("properties", {})
|
|
||||||
|
|
||||||
if properties.get("start_date", False) and properties.get("target_date", False):
|
|
||||||
if (
|
|
||||||
datetime.strptime(properties.get("start_date"), "%Y-%m-%d").date()
|
|
||||||
> datetime.strptime(properties.get("target_date"), "%Y-%m-%d").date()
|
|
||||||
):
|
|
||||||
return Response(
|
|
||||||
{
|
|
||||||
"error_code": 4100,
|
|
||||||
"error_message": "INVALID_ISSUE_DATES",
|
|
||||||
},
|
|
||||||
status=status.HTTP_400_BAD_REQUEST,
|
|
||||||
)
|
|
||||||
|
|
||||||
for issue in issues:
|
|
||||||
|
|
||||||
# Priority
|
|
||||||
if properties.get("priority", False):
|
|
||||||
bulk_issue_activities.append(
|
|
||||||
{
|
|
||||||
"type": "issue.activity.updated",
|
|
||||||
"requested_data": json.dumps(
|
|
||||||
{"priority": properties.get("priority")}
|
|
||||||
),
|
|
||||||
"current_instance": json.dumps(
|
|
||||||
{"priority": (issue.priority)}
|
|
||||||
),
|
|
||||||
"issue_id": str(issue.id),
|
|
||||||
"actor_id": str(request.user.id),
|
|
||||||
"project_id": str(project_id),
|
|
||||||
"epoch": epoch,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
issue.priority = properties.get("priority")
|
|
||||||
|
|
||||||
# State
|
|
||||||
if properties.get("state_id", False):
|
|
||||||
bulk_issue_activities.append(
|
|
||||||
{
|
|
||||||
"type": "issue.activity.updated",
|
|
||||||
"requested_data": json.dumps(
|
|
||||||
{"state": properties.get("state")}
|
|
||||||
),
|
|
||||||
"current_instance": json.dumps(
|
|
||||||
{"state": str(issue.state_id)}
|
|
||||||
),
|
|
||||||
"issue_id": str(issue.id),
|
|
||||||
"actor_id": str(request.user.id),
|
|
||||||
"project_id": str(project_id),
|
|
||||||
"epoch": epoch,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
issue.state_id = properties.get("state_id")
|
|
||||||
|
|
||||||
# Start date
|
|
||||||
if properties.get("start_date", False):
|
|
||||||
if (
|
|
||||||
issue.target_date
|
|
||||||
and not properties.get("target_date", False)
|
|
||||||
and issue.target_date
|
|
||||||
<= datetime.strptime(
|
|
||||||
properties.get("start_date"), "%Y-%m-%d"
|
|
||||||
).date()
|
|
||||||
):
|
|
||||||
return Response(
|
|
||||||
{
|
|
||||||
"error_code": 4101,
|
|
||||||
"error_message": "INVALID_ISSUE_START_DATE",
|
|
||||||
},
|
|
||||||
status=status.HTTP_400_BAD_REQUEST,
|
|
||||||
)
|
|
||||||
bulk_issue_activities.append(
|
|
||||||
{
|
|
||||||
"type": "issue.activity.updated",
|
|
||||||
"requested_data": json.dumps(
|
|
||||||
{"start_date": properties.get("start_date")}
|
|
||||||
),
|
|
||||||
"current_instance": json.dumps(
|
|
||||||
{"start_date": str(issue.start_date)}
|
|
||||||
),
|
|
||||||
"issue_id": str(issue.id),
|
|
||||||
"actor_id": str(request.user.id),
|
|
||||||
"project_id": str(project_id),
|
|
||||||
"epoch": epoch,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
issue.start_date = properties.get("start_date")
|
|
||||||
|
|
||||||
# Target date
|
|
||||||
if properties.get("target_date", False):
|
|
||||||
if (
|
|
||||||
issue.start_date
|
|
||||||
and not properties.get("start_date", False)
|
|
||||||
and issue.start_date
|
|
||||||
>= datetime.strptime(
|
|
||||||
properties.get("target_date"), "%Y-%m-%d"
|
|
||||||
).date()
|
|
||||||
):
|
|
||||||
return Response(
|
|
||||||
{
|
|
||||||
"error_code": 4102,
|
|
||||||
"error_message": "INVALID_ISSUE_TARGET_DATE",
|
|
||||||
},
|
|
||||||
status=status.HTTP_400_BAD_REQUEST,
|
|
||||||
)
|
|
||||||
bulk_issue_activities.append(
|
|
||||||
{
|
|
||||||
"type": "issue.activity.updated",
|
|
||||||
"requested_data": json.dumps(
|
|
||||||
{"target_date": properties.get("target_date")}
|
|
||||||
),
|
|
||||||
"current_instance": json.dumps(
|
|
||||||
{"target_date": str(issue.target_date)}
|
|
||||||
),
|
|
||||||
"issue_id": str(issue.id),
|
|
||||||
"actor_id": str(request.user.id),
|
|
||||||
"project_id": str(project_id),
|
|
||||||
"epoch": epoch,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
issue.target_date = properties.get("target_date")
|
|
||||||
|
|
||||||
bulk_update_issues.append(issue)
|
|
||||||
|
|
||||||
# Labels
|
|
||||||
if properties.get("label_ids", []):
|
|
||||||
for label_id in properties.get("label_ids", []):
|
|
||||||
bulk_update_issue_labels.append(
|
|
||||||
IssueLabel(
|
|
||||||
issue=issue,
|
|
||||||
label_id=label_id,
|
|
||||||
created_by=request.user,
|
|
||||||
project_id=project_id,
|
|
||||||
workspace_id=workspace_id,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
bulk_issue_activities.append(
|
|
||||||
{
|
|
||||||
"type": "issue.activity.updated",
|
|
||||||
"requested_data": json.dumps(
|
|
||||||
{"label_ids": properties.get("label_ids", [])}
|
|
||||||
),
|
|
||||||
"current_instance": json.dumps(
|
|
||||||
{
|
|
||||||
"label_ids": [
|
|
||||||
str(label.id)
|
|
||||||
for label in issue.labels.all()
|
|
||||||
]
|
|
||||||
}
|
|
||||||
),
|
|
||||||
"issue_id": str(issue.id),
|
|
||||||
"actor_id": str(request.user.id),
|
|
||||||
"project_id": str(project_id),
|
|
||||||
"epoch": epoch,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Assignees
|
|
||||||
if properties.get("assignee_ids", []):
|
|
||||||
for assignee_id in properties.get(
|
|
||||||
"assignee_ids", issue.assignees
|
|
||||||
):
|
|
||||||
bulk_update_issue_assignees.append(
|
|
||||||
IssueAssignee(
|
|
||||||
issue=issue,
|
|
||||||
assignee_id=assignee_id,
|
|
||||||
created_by=request.user,
|
|
||||||
project_id=project_id,
|
|
||||||
workspace_id=workspace_id,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
bulk_issue_activities.append(
|
|
||||||
{
|
|
||||||
"type": "issue.activity.updated",
|
|
||||||
"requested_data": json.dumps(
|
|
||||||
{
|
|
||||||
"assignee_ids": properties.get(
|
|
||||||
"assignee_ids", []
|
|
||||||
)
|
|
||||||
}
|
|
||||||
),
|
|
||||||
"current_instance": json.dumps(
|
|
||||||
{
|
|
||||||
"assignee_ids": [
|
|
||||||
str(assignee.id)
|
|
||||||
for assignee in issue.assignees.all()
|
|
||||||
]
|
|
||||||
}
|
|
||||||
),
|
|
||||||
"issue_id": str(issue.id),
|
|
||||||
"actor_id": str(request.user.id),
|
|
||||||
"project_id": str(project_id),
|
|
||||||
"epoch": epoch,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Bulk update all the objects
|
|
||||||
Issue.objects.bulk_update(
|
|
||||||
bulk_update_issues,
|
|
||||||
[
|
|
||||||
"priority",
|
|
||||||
"start_date",
|
|
||||||
"target_date",
|
|
||||||
"state",
|
|
||||||
],
|
|
||||||
batch_size=100,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Create new labels
|
|
||||||
IssueLabel.objects.bulk_create(
|
|
||||||
bulk_update_issue_labels,
|
|
||||||
ignore_conflicts=True,
|
|
||||||
batch_size=100,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Create new assignees
|
|
||||||
IssueAssignee.objects.bulk_create(
|
|
||||||
bulk_update_issue_assignees,
|
|
||||||
ignore_conflicts=True,
|
|
||||||
batch_size=100,
|
|
||||||
)
|
|
||||||
# update the issue activity
|
|
||||||
[
|
|
||||||
issue_activity.delay(**activity)
|
|
||||||
for activity in bulk_issue_activities
|
|
||||||
]
|
|
||||||
|
|
||||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
|
Loading…
Reference in New Issue
Block a user