refactor: track cycles and modules for issue

This commit is contained in:
pablohashescobar 2023-02-06 15:31:05 +05:30
parent 7207d92d62
commit 67a1052b7b
3 changed files with 197 additions and 21 deletions

View File

@ -1,5 +1,9 @@
# Python imports
import json
# Django imports # Django imports
from django.db.models import OuterRef, Func, F from django.db.models import OuterRef, Func, F
from django.core import serializers
# Third party imports # Third party imports
from rest_framework.response import Response from rest_framework.response import Response
@ -11,6 +15,7 @@ from . import BaseViewSet
from plane.api.serializers import CycleSerializer, CycleIssueSerializer from plane.api.serializers import CycleSerializer, CycleIssueSerializer
from plane.api.permissions import ProjectEntityPermission from plane.api.permissions import ProjectEntityPermission
from plane.db.models import Cycle, CycleIssue, Issue from plane.db.models import Cycle, CycleIssue, Issue
from plane.bgtasks.issue_activites_task import issue_activity
class CycleViewSet(BaseViewSet): class CycleViewSet(BaseViewSet):
@ -90,19 +95,28 @@ class CycleIssueViewSet(BaseViewSet):
# Get all CycleIssues already created # Get all CycleIssues already created
cycle_issues = list(CycleIssue.objects.filter(issue_id__in=issues)) cycle_issues = list(CycleIssue.objects.filter(issue_id__in=issues))
records_to_update = [] records_to_update = []
update_cycle_issue_activity = []
record_to_create = [] record_to_create = []
for issue in issues: for issue in issues:
cycle_issue = [ cycle_issue = [
cycle_issue cycle_issue
for cycle_issue in cycle_issues for cycle_issue in cycle_issues
if cycle_issue.issue_id in issues if str(cycle_issue.issue_id) in issues
] ]
# Update only when cycle changes
if len(cycle_issue): if len(cycle_issue):
cycle_issue[0].cycle_id = cycle_id if cycle_issue[0].cycle_id != cycle_id:
records_to_update.append(cycle_issue[0]) update_cycle_issue_activity.append(
{
"old_cycle_id": str(cycle_issue[0].cycle_id),
"new_cycle_id": str(cycle_id),
"issue_id": str(cycle_issue[0].issue_id),
}
)
cycle_issue[0].cycle_id = cycle_id
records_to_update.append(cycle_issue[0])
else: else:
record_to_create.append( record_to_create.append(
CycleIssue( CycleIssue(
@ -126,9 +140,29 @@ class CycleIssueViewSet(BaseViewSet):
batch_size=10, batch_size=10,
) )
# Capture Issue Activity
issue_activity.delay(
{
"type": "issue.activity",
"requested_data": json.dumps({"cycles_list": issues}),
"actor_id": str(self.request.user.id),
"issue_id": str(self.kwargs.get("pk", None)),
"project_id": str(self.kwargs.get("project_id", None)),
"current_instance": json.dumps(
{
"updated_cycle_issues": update_cycle_issue_activity,
"created_cycle_issues": serializers.serialize(
"json", record_to_create
),
}
),
},
)
# Return all Cycle Issues # Return all Cycle Issues
return Response( return Response(
CycleIssueSerializer(self.get_queryset(), many=True).data, status=status.HTTP_200_OK CycleIssueSerializer(self.get_queryset(), many=True).data,
status=status.HTTP_200_OK,
) )
except Cycle.DoesNotExist: except Cycle.DoesNotExist:

View File

@ -1,6 +1,10 @@
# Python imports
import json
# Django Imports # Django Imports
from django.db import IntegrityError from django.db import IntegrityError
from django.db.models import Prefetch, F, OuterRef, Func from django.db.models import Prefetch, F, OuterRef, Func
from django.core import serializers
# Third party imports # Third party imports
from rest_framework.response import Response from rest_framework.response import Response
@ -22,6 +26,7 @@ from plane.db.models import (
Issue, Issue,
ModuleLink, ModuleLink,
) )
from plane.bgtasks.issue_activites_task import issue_activity
class ModuleViewSet(BaseViewSet): class ModuleViewSet(BaseViewSet):
@ -148,6 +153,7 @@ class ModuleIssueViewSet(BaseViewSet):
module_issues = list(ModuleIssue.objects.filter(issue_id__in=issues)) module_issues = list(ModuleIssue.objects.filter(issue_id__in=issues))
update_module_issue_activity = []
records_to_update = [] records_to_update = []
record_to_create = [] record_to_create = []
@ -159,8 +165,16 @@ class ModuleIssueViewSet(BaseViewSet):
] ]
if len(module_issue): if len(module_issue):
module_issue[0].module_id = module_id if module_issue[0].cycle_id != module_id:
records_to_update.append(module_issue[0]) update_module_issue_activity.append(
{
"old_module_id": str(module_issue[0].cycle_id),
"new_module_id": str(module_id),
"issue_id": str(module_issue[0].issue_id),
}
)
module_issue[0].module_id = module_id
records_to_update.append(module_issue[0])
else: else:
record_to_create.append( record_to_create.append(
ModuleIssue( ModuleIssue(
@ -185,6 +199,25 @@ class ModuleIssueViewSet(BaseViewSet):
batch_size=10, batch_size=10,
) )
# Capture Issue Activity
issue_activity.delay(
{
"type": "issue.activity",
"requested_data": json.dumps({"cycles_list": issues}),
"actor_id": str(self.request.user.id),
"issue_id": str(self.kwargs.get("pk", None)),
"project_id": str(self.kwargs.get("project_id", None)),
"current_instance": json.dumps(
{
"updated_cycle_issues": update_module_issue_activity,
"created_cycle_issues": serializers.serialize(
"json", record_to_create
),
}
),
},
)
return Response( return Response(
ModuleIssueSerializer(self.get_queryset(), many=True).data, ModuleIssueSerializer(self.get_queryset(), many=True).data,
status=status.HTTP_200_OK, status=status.HTTP_200_OK,

View File

@ -6,7 +6,16 @@ from django_rq import job
from sentry_sdk import capture_exception from sentry_sdk import capture_exception
# Module imports # Module imports
from plane.db.models import User, Issue, Project, Label, IssueActivity, State from plane.db.models import (
User,
Issue,
Project,
Label,
IssueActivity,
State,
Cycle,
Module,
)
# Track Chnages in name # Track Chnages in name
@ -44,7 +53,6 @@ def track_parent(
issue_activities, issue_activities,
): ):
if current_instance.get("parent") != requested_data.get("parent"): if current_instance.get("parent") != requested_data.get("parent"):
if requested_data.get("parent") == None: if requested_data.get("parent") == None:
old_parent = Issue.objects.get(pk=current_instance.get("parent")) old_parent = Issue.objects.get(pk=current_instance.get("parent"))
issue_activities.append( issue_activities.append(
@ -134,7 +142,6 @@ def track_state(
issue_activities, issue_activities,
): ):
if current_instance.get("state") != requested_data.get("state"): if current_instance.get("state") != requested_data.get("state"):
new_state = State.objects.get(pk=requested_data.get("state", None)) new_state = State.objects.get(pk=requested_data.get("state", None))
old_state = State.objects.get(pk=current_instance.get("state", None)) old_state = State.objects.get(pk=current_instance.get("state", None))
@ -167,7 +174,6 @@ def track_description(
if current_instance.get("description_html") != requested_data.get( if current_instance.get("description_html") != requested_data.get(
"description_html" "description_html"
): ):
issue_activities.append( issue_activities.append(
IssueActivity( IssueActivity(
issue_id=issue_id, issue_id=issue_id,
@ -274,7 +280,6 @@ def track_labels(
): ):
# Label Addition # Label Addition
if len(requested_data.get("labels_list")) > len(current_instance.get("labels")): if len(requested_data.get("labels_list")) > len(current_instance.get("labels")):
for label in requested_data.get("labels_list"): for label in requested_data.get("labels_list"):
if label not in current_instance.get("labels"): if label not in current_instance.get("labels"):
label = Label.objects.get(pk=label) label = Label.objects.get(pk=label)
@ -296,7 +301,6 @@ def track_labels(
# Label Removal # Label Removal
if len(requested_data.get("labels_list")) < len(current_instance.get("labels")): if len(requested_data.get("labels_list")) < len(current_instance.get("labels")):
for label in current_instance.get("labels"): for label in current_instance.get("labels"):
if label not in requested_data.get("labels_list"): if label not in requested_data.get("labels_list"):
label = Label.objects.get(pk=label) label = Label.objects.get(pk=label)
@ -326,12 +330,10 @@ def track_assignees(
actor, actor,
issue_activities, issue_activities,
): ):
# Assignee Addition # Assignee Addition
if len(requested_data.get("assignees_list")) > len( if len(requested_data.get("assignees_list")) > len(
current_instance.get("assignees") current_instance.get("assignees")
): ):
for assignee in requested_data.get("assignees_list"): for assignee in requested_data.get("assignees_list"):
if assignee not in current_instance.get("assignees"): if assignee not in current_instance.get("assignees"):
assignee = User.objects.get(pk=assignee) assignee = User.objects.get(pk=assignee)
@ -354,7 +356,6 @@ def track_assignees(
if len(requested_data.get("assignees_list")) < len( if len(requested_data.get("assignees_list")) < len(
current_instance.get("assignees") current_instance.get("assignees")
): ):
for assignee in current_instance.get("assignees"): for assignee in current_instance.get("assignees"):
if assignee not in requested_data.get("assignees_list"): if assignee not in requested_data.get("assignees_list"):
assignee = User.objects.get(pk=assignee) assignee = User.objects.get(pk=assignee)
@ -386,7 +387,6 @@ def track_blocks(
if len(requested_data.get("blocks_list")) > len( if len(requested_data.get("blocks_list")) > len(
current_instance.get("blocked_issues") current_instance.get("blocked_issues")
): ):
for block in requested_data.get("blocks_list"): for block in requested_data.get("blocks_list"):
if ( if (
len( len(
@ -418,7 +418,6 @@ def track_blocks(
if len(requested_data.get("blocks_list")) < len( if len(requested_data.get("blocks_list")) < len(
current_instance.get("blocked_issues") current_instance.get("blocked_issues")
): ):
for blocked in current_instance.get("blocked_issues"): for blocked in current_instance.get("blocked_issues"):
if blocked.get("block") not in requested_data.get("blocks_list"): if blocked.get("block") not in requested_data.get("blocks_list"):
issue = Issue.objects.get(pk=blocked.get("block")) issue = Issue.objects.get(pk=blocked.get("block"))
@ -450,7 +449,6 @@ def track_blockings(
if len(requested_data.get("blockers_list")) > len( if len(requested_data.get("blockers_list")) > len(
current_instance.get("blocker_issues") current_instance.get("blocker_issues")
): ):
for block in requested_data.get("blockers_list"): for block in requested_data.get("blockers_list"):
if ( if (
len( len(
@ -482,7 +480,6 @@ def track_blockings(
if len(requested_data.get("blockers_list")) < len( if len(requested_data.get("blockers_list")) < len(
current_instance.get("blocker_issues") current_instance.get("blocker_issues")
): ):
for blocked in current_instance.get("blocker_issues"): for blocked in current_instance.get("blocker_issues"):
if blocked.get("blocked_by") not in requested_data.get("blockers_list"): if blocked.get("blocked_by") not in requested_data.get("blockers_list"):
issue = Issue.objects.get(pk=blocked.get("blocked_by")) issue = Issue.objects.get(pk=blocked.get("blocked_by"))
@ -502,6 +499,116 @@ def track_blockings(
) )
def track_cycles(
requested_data,
current_instance,
issue_id,
project,
actor,
issue_activities,
):
# Updated Records:
updated_records = current_instance.get("updated_cycle_issues", [])
created_records = json.loads(current_instance.get("created_cycle_issues", []))
for updated_record in updated_records:
old_cycle = Cycle.objects.filter(
pk=updated_record.get("old_cycle_id", None)
).first()
new_cycle = Cycle.objects.filter(
pk=updated_record.get("new_cycle_id", None)
).first()
issue_activities.append(
IssueActivity(
issue_id=updated_record.get("issue_id"),
actor=actor,
verb="updated",
old_value=old_cycle.name,
new_value=new_cycle.name,
field="cycles",
project=project,
workspace=project.workspace,
comment=f"{actor.email} updated cycle from {old_cycle.name} to {new_cycle.name}",
old_identifier=old_cycle.id,
new_identifier=new_cycle.id,
)
)
for created_record in created_records:
cycle = Cycle.objects.filter(pk=created_record.cycle_id).first()
issue_activities.append(
IssueActivity(
issue_id=created_record.issue_id,
actor=actor,
verb="created",
old_value="",
new_value=cycle.name,
field="cycles",
project=project,
workspace=project.workspace,
comment=f"{actor.email} added cycle {cycle.name}",
old_identifier="",
new_identifier=cycle.id,
)
)
def track_modules(
requested_data,
current_instance,
issue_id,
project,
actor,
issue_activities,
):
# Updated Records:
updated_records = current_instance.get("updated_module_issues", [])
created_records = json.loads(current_instance.get("created_module_issues", []))
for updated_record in updated_records:
old_module = Module.objects.filter(
pk=updated_record.get("old_module_id", None)
).first()
new_module = Module.objects.filter(
pk=updated_record.get("new_module_id", None)
).first()
issue_activities.append(
IssueActivity(
issue_id=updated_record.get("issue_id"),
actor=actor,
verb="updated",
old_value=old_module.name,
new_value=new_module.name,
field="modules",
project=project,
workspace=project.workspace,
comment=f"{actor.email} updated module from {old_module.name} to {new_module.name}",
old_identifier=old_module.id,
new_identifier=new_module.id,
)
)
for created_record in created_records:
module = Module.objects.filter(pk=created_record.module_id).first()
issue_activities.append(
IssueActivity(
issue_id=created_record.issue_id,
actor=actor,
verb="created",
old_value="",
new_value=module.name,
field="modules",
project=project,
workspace=project.workspace,
comment=f"{actor.email} added module {module.name}",
old_identifier="",
new_identifier=module.id,
)
)
# Receive message from room group # Receive message from room group
@job("default") @job("default")
def issue_activity(event): def issue_activity(event):
@ -510,7 +617,7 @@ def issue_activity(event):
requested_data = json.loads(event.get("requested_data")) requested_data = json.loads(event.get("requested_data"))
current_instance = json.loads(event.get("current_instance")) current_instance = json.loads(event.get("current_instance"))
issue_id = event.get("issue_id") issue_id = event.get("issue_id", None)
actor_id = event.get("actor_id") actor_id = event.get("actor_id")
project_id = event.get("project_id") project_id = event.get("project_id")
@ -530,6 +637,8 @@ def issue_activity(event):
"assignees_list": track_assignees, "assignees_list": track_assignees,
"blocks_list": track_blocks, "blocks_list": track_blocks,
"blockers_list": track_blockings, "blockers_list": track_blockings,
"cycles_list": track_cycles,
"modules_list": track_modules,
} }
for key in requested_data: for key in requested_data: