forked from github/plane
refactor: move issue activity tracking from django-channels to rqworker (#207)
* refactor: move issue activity tracking from django channels to rqworker * refactor: update old value and new value from character type to text type
This commit is contained in:
parent
0ff5f363ee
commit
45a52116a7
@ -49,7 +49,7 @@ USER root
|
|||||||
RUN apk --update --no-cache add "bash~=5.1"
|
RUN apk --update --no-cache add "bash~=5.1"
|
||||||
COPY ./bin ./bin/
|
COPY ./bin ./bin/
|
||||||
|
|
||||||
RUN chmod +x ./bin/channel-worker ./bin/takeoff ./bin/worker
|
RUN chmod +x ./bin/takeoff ./bin/worker
|
||||||
|
|
||||||
USER captain
|
USER captain
|
||||||
|
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
web: gunicorn -w 4 -k uvicorn.workers.UvicornWorker plane.asgi:application --bind 0.0.0.0:$PORT --config gunicorn.config.py --max-requests 10000 --max-requests-jitter 1000 --access-logfile -
|
web: gunicorn -w 4 -k uvicorn.workers.UvicornWorker plane.asgi:application --bind 0.0.0.0:$PORT --config gunicorn.config.py --max-requests 10000 --max-requests-jitter 1000 --access-logfile -
|
||||||
worker: python manage.py rqworker
|
worker: python manage.py rqworker
|
||||||
channel-worker: python manage.py runworker issue-activites
|
|
@ -1,6 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
python manage.py wait_for_db
|
|
||||||
python manage.py migrate
|
|
||||||
python manage.py runworker issue-activites
|
|
@ -1 +0,0 @@
|
|||||||
from .issue_consumer import IssueConsumer
|
|
@ -1,547 +0,0 @@
|
|||||||
from channels.generic.websocket import SyncConsumer
|
|
||||||
import json
|
|
||||||
from plane.db.models import IssueActivity, Project, User, Issue, State, Label
|
|
||||||
|
|
||||||
|
|
||||||
class IssueConsumer(SyncConsumer):
|
|
||||||
|
|
||||||
# Track Chnages in name
|
|
||||||
def track_name(
|
|
||||||
self,
|
|
||||||
requested_data,
|
|
||||||
current_instance,
|
|
||||||
issue_id,
|
|
||||||
project,
|
|
||||||
actor,
|
|
||||||
issue_activities,
|
|
||||||
):
|
|
||||||
if current_instance.get("name") != requested_data.get("name"):
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value=current_instance.get("name"),
|
|
||||||
new_value=requested_data.get("name"),
|
|
||||||
field="name",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} updated the start date to {requested_data.get('name')}",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Track changes in parent issue
|
|
||||||
def track_parent(
|
|
||||||
self,
|
|
||||||
requested_data,
|
|
||||||
current_instance,
|
|
||||||
issue_id,
|
|
||||||
project,
|
|
||||||
actor,
|
|
||||||
issue_activities,
|
|
||||||
):
|
|
||||||
if current_instance.get("parent") != requested_data.get("parent"):
|
|
||||||
|
|
||||||
if requested_data.get("parent") == None:
|
|
||||||
old_parent = Issue.objects.get(pk=current_instance.get("parent"))
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value=f"{project.identifier}-{old_parent.sequence_id}",
|
|
||||||
new_value=None,
|
|
||||||
field="parent",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} updated the parent issue to None",
|
|
||||||
old_identifier=old_parent.id,
|
|
||||||
new_identifier=None,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
new_parent = Issue.objects.get(pk=requested_data.get("parent"))
|
|
||||||
old_parent = Issue.objects.filter(
|
|
||||||
pk=current_instance.get("parent")
|
|
||||||
).first()
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value=f"{project.identifier}-{old_parent.sequence_id}"
|
|
||||||
if old_parent is not None
|
|
||||||
else None,
|
|
||||||
new_value=f"{project.identifier}-{new_parent.sequence_id}",
|
|
||||||
field="parent",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} updated the parent issue to {new_parent.name}",
|
|
||||||
old_identifier=old_parent.id
|
|
||||||
if old_parent is not None
|
|
||||||
else None,
|
|
||||||
new_identifier=new_parent.id,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Track changes in priority
|
|
||||||
def track_priority(
|
|
||||||
self,
|
|
||||||
requested_data,
|
|
||||||
current_instance,
|
|
||||||
issue_id,
|
|
||||||
project,
|
|
||||||
actor,
|
|
||||||
issue_activities,
|
|
||||||
):
|
|
||||||
if current_instance.get("priority") != requested_data.get("priority"):
|
|
||||||
if requested_data.get("priority") == None:
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value=current_instance.get("parent"),
|
|
||||||
new_value=requested_data.get("parent"),
|
|
||||||
field="priority",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} updated the priority to None",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value=current_instance.get("priority"),
|
|
||||||
new_value=requested_data.get("priority"),
|
|
||||||
field="priority",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} updated the priority to {requested_data.get('priority')}",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Track chnages in state of the issue
|
|
||||||
def track_state(
|
|
||||||
self,
|
|
||||||
requested_data,
|
|
||||||
current_instance,
|
|
||||||
issue_id,
|
|
||||||
project,
|
|
||||||
actor,
|
|
||||||
issue_activities,
|
|
||||||
):
|
|
||||||
if current_instance.get("state") != requested_data.get("state"):
|
|
||||||
|
|
||||||
new_state = State.objects.get(pk=requested_data.get("state", None))
|
|
||||||
old_state = State.objects.get(pk=current_instance.get("state", None))
|
|
||||||
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value=old_state.name,
|
|
||||||
new_value=new_state.name,
|
|
||||||
field="state",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} updated the state to {new_state.name}",
|
|
||||||
old_identifier=old_state.id,
|
|
||||||
new_identifier=new_state.id,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Track issue description
|
|
||||||
def track_description(
|
|
||||||
self,
|
|
||||||
requested_data,
|
|
||||||
current_instance,
|
|
||||||
issue_id,
|
|
||||||
project,
|
|
||||||
actor,
|
|
||||||
issue_activities,
|
|
||||||
):
|
|
||||||
if current_instance.get("description_html") != requested_data.get("description_html"):
|
|
||||||
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value=current_instance.get("description_html"),
|
|
||||||
new_value=requested_data.get("description_html"),
|
|
||||||
field="description",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} updated the description to {requested_data.get('description_html')}",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Track changes in issue target date
|
|
||||||
def track_target_date(
|
|
||||||
self,
|
|
||||||
requested_data,
|
|
||||||
current_instance,
|
|
||||||
issue_id,
|
|
||||||
project,
|
|
||||||
actor,
|
|
||||||
issue_activities,
|
|
||||||
):
|
|
||||||
if current_instance.get("target_date") != requested_data.get("target_date"):
|
|
||||||
if requested_data.get("target_date") == None:
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value=current_instance.get("target_date"),
|
|
||||||
new_value=requested_data.get("target_date"),
|
|
||||||
field="target_date",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} updated the target date to None",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value=current_instance.get("target_date"),
|
|
||||||
new_value=requested_data.get("target_date"),
|
|
||||||
field="target_date",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} updated the target date to {requested_data.get('target_date')}",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Track changes in issue start date
|
|
||||||
def track_start_date(
|
|
||||||
self,
|
|
||||||
requested_data,
|
|
||||||
current_instance,
|
|
||||||
issue_id,
|
|
||||||
project,
|
|
||||||
actor,
|
|
||||||
issue_activities,
|
|
||||||
):
|
|
||||||
if current_instance.get("start_date") != requested_data.get("start_date"):
|
|
||||||
if requested_data.get("start_date") == None:
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value=current_instance.get("start_date"),
|
|
||||||
new_value=requested_data.get("start_date"),
|
|
||||||
field="start_date",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} updated the start date to None",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value=current_instance.get("start_date"),
|
|
||||||
new_value=requested_data.get("start_date"),
|
|
||||||
field="start_date",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} updated the start date to {requested_data.get('start_date')}",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Track changes in issue labels
|
|
||||||
def track_labels(
|
|
||||||
self,
|
|
||||||
requested_data,
|
|
||||||
current_instance,
|
|
||||||
issue_id,
|
|
||||||
project,
|
|
||||||
actor,
|
|
||||||
issue_activities,
|
|
||||||
):
|
|
||||||
# Label Addition
|
|
||||||
if len(requested_data.get("labels_list")) > len(current_instance.get("labels")):
|
|
||||||
|
|
||||||
for label in requested_data.get("labels_list"):
|
|
||||||
if label not in current_instance.get("labels"):
|
|
||||||
label = Label.objects.get(pk=label)
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value="",
|
|
||||||
new_value=label.name,
|
|
||||||
field="labels",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} added label {label.name}",
|
|
||||||
new_identifier=label.id,
|
|
||||||
old_identifier=None,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Label Removal
|
|
||||||
if len(requested_data.get("labels_list")) < len(current_instance.get("labels")):
|
|
||||||
|
|
||||||
for label in current_instance.get("labels"):
|
|
||||||
if label not in requested_data.get("labels_list"):
|
|
||||||
label = Label.objects.get(pk=label)
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value=label.name,
|
|
||||||
new_value="",
|
|
||||||
field="labels",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} removed label {label.name}",
|
|
||||||
old_identifier=label.id,
|
|
||||||
new_identifier=None,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Track changes in issue assignees
|
|
||||||
def track_assignees(
|
|
||||||
self,
|
|
||||||
requested_data,
|
|
||||||
current_instance,
|
|
||||||
issue_id,
|
|
||||||
project,
|
|
||||||
actor,
|
|
||||||
issue_activities,
|
|
||||||
):
|
|
||||||
|
|
||||||
# Assignee Addition
|
|
||||||
if len(requested_data.get("assignees_list")) > len(
|
|
||||||
current_instance.get("assignees")
|
|
||||||
):
|
|
||||||
|
|
||||||
for assignee in requested_data.get("assignees_list"):
|
|
||||||
if assignee not in current_instance.get("assignees"):
|
|
||||||
assignee = User.objects.get(pk=assignee)
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value="",
|
|
||||||
new_value=assignee.email,
|
|
||||||
field="assignees",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} added assignee {assignee.email}",
|
|
||||||
new_identifier=actor.id,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Assignee Removal
|
|
||||||
if len(requested_data.get("assignees_list")) < len(
|
|
||||||
current_instance.get("assignees")
|
|
||||||
):
|
|
||||||
|
|
||||||
for assignee in current_instance.get("assignees"):
|
|
||||||
if assignee not in requested_data.get("assignees_list"):
|
|
||||||
assignee = User.objects.get(pk=assignee)
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value=assignee.email,
|
|
||||||
new_value="",
|
|
||||||
field="assignee",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} removed assignee {assignee.email}",
|
|
||||||
old_identifier=actor.id,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Track changes in blocking issues
|
|
||||||
def track_blocks(
|
|
||||||
self,
|
|
||||||
requested_data,
|
|
||||||
current_instance,
|
|
||||||
issue_id,
|
|
||||||
project,
|
|
||||||
actor,
|
|
||||||
issue_activities,
|
|
||||||
):
|
|
||||||
if len(requested_data.get("blocks_list")) > len(
|
|
||||||
current_instance.get("blocked_issues")
|
|
||||||
):
|
|
||||||
|
|
||||||
for block in requested_data.get("blocks_list"):
|
|
||||||
if (
|
|
||||||
len(
|
|
||||||
[
|
|
||||||
blocked
|
|
||||||
for blocked in current_instance.get("blocked_issues")
|
|
||||||
if blocked.get("block") == block
|
|
||||||
]
|
|
||||||
)
|
|
||||||
== 0
|
|
||||||
):
|
|
||||||
issue = Issue.objects.get(pk=block)
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value="",
|
|
||||||
new_value=f"{project.identifier}-{issue.sequence_id}",
|
|
||||||
field="blocks",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} added blocking issue {project.identifier}-{issue.sequence_id}",
|
|
||||||
new_identifier=issue.id,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Blocked Issue Removal
|
|
||||||
if len(requested_data.get("blocks_list")) < len(
|
|
||||||
current_instance.get("blocked_issues")
|
|
||||||
):
|
|
||||||
|
|
||||||
for blocked in current_instance.get("blocked_issues"):
|
|
||||||
if blocked.get("block") not in requested_data.get("blocks_list"):
|
|
||||||
issue = Issue.objects.get(pk=blocked.get("block"))
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value=f"{project.identifier}-{issue.sequence_id}",
|
|
||||||
new_value="",
|
|
||||||
field="blocks",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} removed blocking issue {project.identifier}-{issue.sequence_id}",
|
|
||||||
old_identifier=issue.id,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Track changes in blocked_by issues
|
|
||||||
def track_blockings(
|
|
||||||
self,
|
|
||||||
requested_data,
|
|
||||||
current_instance,
|
|
||||||
issue_id,
|
|
||||||
project,
|
|
||||||
actor,
|
|
||||||
issue_activities,
|
|
||||||
):
|
|
||||||
if len(requested_data.get("blockers_list")) > len(
|
|
||||||
current_instance.get("blocker_issues")
|
|
||||||
):
|
|
||||||
|
|
||||||
for block in requested_data.get("blockers_list"):
|
|
||||||
if (
|
|
||||||
len(
|
|
||||||
[
|
|
||||||
blocked
|
|
||||||
for blocked in current_instance.get("blocker_issues")
|
|
||||||
if blocked.get("blocked_by") == block
|
|
||||||
]
|
|
||||||
)
|
|
||||||
== 0
|
|
||||||
):
|
|
||||||
issue = Issue.objects.get(pk=block)
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value="",
|
|
||||||
new_value=f"{project.identifier}-{issue.sequence_id}",
|
|
||||||
field="blocking",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} added blocked by issue {project.identifier}-{issue.sequence_id}",
|
|
||||||
new_identifier=issue.id,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Blocked Issue Removal
|
|
||||||
if len(requested_data.get("blockers_list")) < len(
|
|
||||||
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"):
|
|
||||||
issue = Issue.objects.get(pk=blocked.get("blocked_by"))
|
|
||||||
issue_activities.append(
|
|
||||||
IssueActivity(
|
|
||||||
issue_id=issue_id,
|
|
||||||
actor=actor,
|
|
||||||
verb="updated",
|
|
||||||
old_value=f"{project.identifier}-{issue.sequence_id}",
|
|
||||||
new_value="",
|
|
||||||
field="blocking",
|
|
||||||
project=project,
|
|
||||||
workspace=project.workspace,
|
|
||||||
comment=f"{actor.email} removed blocked by issue {project.identifier}-{issue.sequence_id}",
|
|
||||||
old_identifier=issue.id,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Receive message from room group
|
|
||||||
def issue_activity(self, event):
|
|
||||||
|
|
||||||
issue_activities = []
|
|
||||||
# Remove event type:
|
|
||||||
event.pop("type")
|
|
||||||
|
|
||||||
requested_data = json.loads(event.get("requested_data"))
|
|
||||||
current_instance = json.loads(event.get("current_instance"))
|
|
||||||
issue_id = event.get("issue_id")
|
|
||||||
actor_id = event.get("actor_id")
|
|
||||||
project_id = event.get("project_id")
|
|
||||||
|
|
||||||
actor = User.objects.get(pk=actor_id)
|
|
||||||
|
|
||||||
project = Project.objects.get(pk=project_id)
|
|
||||||
|
|
||||||
ISSUE_ACTIVITY_MAPPER = {
|
|
||||||
"name": self.track_name,
|
|
||||||
"parent": self.track_parent,
|
|
||||||
"priority": self.track_priority,
|
|
||||||
"state": self.track_state,
|
|
||||||
"description": self.track_description,
|
|
||||||
"target_date": self.track_target_date,
|
|
||||||
"start_date": self.track_start_date,
|
|
||||||
"labels_list": self.track_labels,
|
|
||||||
"assignees_list": self.track_assignees,
|
|
||||||
"blocks_list": self.track_blocks,
|
|
||||||
"blockers_list": self.track_blockings,
|
|
||||||
}
|
|
||||||
|
|
||||||
for key in requested_data:
|
|
||||||
func = ISSUE_ACTIVITY_MAPPER.get(key, None)
|
|
||||||
if func is not None:
|
|
||||||
func(
|
|
||||||
requested_data,
|
|
||||||
current_instance,
|
|
||||||
issue_id,
|
|
||||||
project,
|
|
||||||
actor,
|
|
||||||
issue_activities,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Save all the values to database
|
|
||||||
IssueActivity.objects.bulk_create(issue_activities)
|
|
@ -10,8 +10,6 @@ from django.core.serializers.json import DjangoJSONEncoder
|
|||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from sentry_sdk import capture_exception
|
from sentry_sdk import capture_exception
|
||||||
from channels.layers import get_channel_layer
|
|
||||||
from asgiref.sync import async_to_sync
|
|
||||||
|
|
||||||
# Module imports
|
# Module imports
|
||||||
from . import BaseViewSet, BaseAPIView
|
from . import BaseViewSet, BaseAPIView
|
||||||
@ -42,6 +40,7 @@ from plane.db.models import (
|
|||||||
CycleIssue,
|
CycleIssue,
|
||||||
ModuleIssue,
|
ModuleIssue,
|
||||||
)
|
)
|
||||||
|
from plane.bgtasks.issue_activites_task import issue_activity
|
||||||
|
|
||||||
|
|
||||||
class IssueViewSet(BaseViewSet):
|
class IssueViewSet(BaseViewSet):
|
||||||
@ -72,12 +71,12 @@ class IssueViewSet(BaseViewSet):
|
|||||||
|
|
||||||
def perform_update(self, serializer):
|
def perform_update(self, serializer):
|
||||||
requested_data = json.dumps(self.request.data, cls=DjangoJSONEncoder)
|
requested_data = json.dumps(self.request.data, cls=DjangoJSONEncoder)
|
||||||
current_instance = Issue.objects.filter(pk=self.kwargs.get("pk", None)).first()
|
current_instance = (
|
||||||
|
self.get_queryset().filter(pk=self.kwargs.get("pk", None)).first()
|
||||||
|
)
|
||||||
if current_instance is not None:
|
if current_instance is not None:
|
||||||
|
|
||||||
channel_layer = get_channel_layer()
|
issue_activity.delay(
|
||||||
async_to_sync(channel_layer.send)(
|
|
||||||
"issue-activites",
|
|
||||||
{
|
{
|
||||||
"type": "issue.activity",
|
"type": "issue.activity",
|
||||||
"requested_data": requested_data,
|
"requested_data": requested_data,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from channels.routing import ProtocolTypeRouter, ChannelNameRouter
|
from channels.routing import ProtocolTypeRouter
|
||||||
from django.core.asgi import get_asgi_application
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
django_asgi_app = get_asgi_application()
|
django_asgi_app = get_asgi_application()
|
||||||
@ -10,15 +10,9 @@ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "plane.settings.production")
|
|||||||
# Initialize Django ASGI application early to ensure the AppRegistry
|
# Initialize Django ASGI application early to ensure the AppRegistry
|
||||||
# is populated before importing code that may import ORM models.
|
# is populated before importing code that may import ORM models.
|
||||||
|
|
||||||
from plane.api.consumers import IssueConsumer
|
|
||||||
|
|
||||||
application = ProtocolTypeRouter(
|
application = ProtocolTypeRouter(
|
||||||
{
|
{
|
||||||
"http": get_asgi_application(),
|
"http": get_asgi_application(),
|
||||||
"channel": ChannelNameRouter(
|
|
||||||
{
|
|
||||||
"issue-activites": IssueConsumer.as_asgi(),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
553
apiserver/plane/bgtasks/issue_activites_task.py
Normal file
553
apiserver/plane/bgtasks/issue_activites_task.py
Normal file
@ -0,0 +1,553 @@
|
|||||||
|
# Python imports
|
||||||
|
import json
|
||||||
|
|
||||||
|
# Third Party imports
|
||||||
|
from django_rq import job
|
||||||
|
from sentry_sdk import capture_exception
|
||||||
|
|
||||||
|
# Module imports
|
||||||
|
from plane.db.models import User, Issue, Project, Label, IssueActivity, State
|
||||||
|
|
||||||
|
|
||||||
|
# Track Chnages in name
|
||||||
|
def track_name(
|
||||||
|
requested_data,
|
||||||
|
current_instance,
|
||||||
|
issue_id,
|
||||||
|
project,
|
||||||
|
actor,
|
||||||
|
issue_activities,
|
||||||
|
):
|
||||||
|
if current_instance.get("name") != requested_data.get("name"):
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value=current_instance.get("name"),
|
||||||
|
new_value=requested_data.get("name"),
|
||||||
|
field="name",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} updated the start date to {requested_data.get('name')}",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Track changes in parent issue
|
||||||
|
def track_parent(
|
||||||
|
requested_data,
|
||||||
|
current_instance,
|
||||||
|
issue_id,
|
||||||
|
project,
|
||||||
|
actor,
|
||||||
|
issue_activities,
|
||||||
|
):
|
||||||
|
if current_instance.get("parent") != requested_data.get("parent"):
|
||||||
|
|
||||||
|
if requested_data.get("parent") == None:
|
||||||
|
old_parent = Issue.objects.get(pk=current_instance.get("parent"))
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value=f"{project.identifier}-{old_parent.sequence_id}",
|
||||||
|
new_value=None,
|
||||||
|
field="parent",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} updated the parent issue to None",
|
||||||
|
old_identifier=old_parent.id,
|
||||||
|
new_identifier=None,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
new_parent = Issue.objects.get(pk=requested_data.get("parent"))
|
||||||
|
old_parent = Issue.objects.filter(pk=current_instance.get("parent")).first()
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value=f"{project.identifier}-{old_parent.sequence_id}"
|
||||||
|
if old_parent is not None
|
||||||
|
else None,
|
||||||
|
new_value=f"{project.identifier}-{new_parent.sequence_id}",
|
||||||
|
field="parent",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} updated the parent issue to {new_parent.name}",
|
||||||
|
old_identifier=old_parent.id if old_parent is not None else None,
|
||||||
|
new_identifier=new_parent.id,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Track changes in priority
|
||||||
|
def track_priority(
|
||||||
|
requested_data,
|
||||||
|
current_instance,
|
||||||
|
issue_id,
|
||||||
|
project,
|
||||||
|
actor,
|
||||||
|
issue_activities,
|
||||||
|
):
|
||||||
|
if current_instance.get("priority") != requested_data.get("priority"):
|
||||||
|
if requested_data.get("priority") == None:
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value=current_instance.get("priority"),
|
||||||
|
new_value=None,
|
||||||
|
field="priority",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} updated the priority to None",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value=current_instance.get("priority"),
|
||||||
|
new_value=requested_data.get("priority"),
|
||||||
|
field="priority",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} updated the priority to {requested_data.get('priority')}",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Track chnages in state of the issue
|
||||||
|
def track_state(
|
||||||
|
requested_data,
|
||||||
|
current_instance,
|
||||||
|
issue_id,
|
||||||
|
project,
|
||||||
|
actor,
|
||||||
|
issue_activities,
|
||||||
|
):
|
||||||
|
if current_instance.get("state") != requested_data.get("state"):
|
||||||
|
|
||||||
|
new_state = State.objects.get(pk=requested_data.get("state", None))
|
||||||
|
old_state = State.objects.get(pk=current_instance.get("state", None))
|
||||||
|
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value=old_state.name,
|
||||||
|
new_value=new_state.name,
|
||||||
|
field="state",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} updated the state to {new_state.name}",
|
||||||
|
old_identifier=old_state.id,
|
||||||
|
new_identifier=new_state.id,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Track issue description
|
||||||
|
def track_description(
|
||||||
|
requested_data,
|
||||||
|
current_instance,
|
||||||
|
issue_id,
|
||||||
|
project,
|
||||||
|
actor,
|
||||||
|
issue_activities,
|
||||||
|
):
|
||||||
|
if current_instance.get("description_html") != requested_data.get(
|
||||||
|
"description_html"
|
||||||
|
):
|
||||||
|
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value=current_instance.get("description_html"),
|
||||||
|
new_value=requested_data.get("description_html"),
|
||||||
|
field="description",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} updated the description to {requested_data.get('description_html')}",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Track changes in issue target date
|
||||||
|
def track_target_date(
|
||||||
|
requested_data,
|
||||||
|
current_instance,
|
||||||
|
issue_id,
|
||||||
|
project,
|
||||||
|
actor,
|
||||||
|
issue_activities,
|
||||||
|
):
|
||||||
|
if current_instance.get("target_date") != requested_data.get("target_date"):
|
||||||
|
if requested_data.get("target_date") == None:
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value=current_instance.get("target_date"),
|
||||||
|
new_value=requested_data.get("target_date"),
|
||||||
|
field="target_date",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} updated the target date to None",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value=current_instance.get("target_date"),
|
||||||
|
new_value=requested_data.get("target_date"),
|
||||||
|
field="target_date",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} updated the target date to {requested_data.get('target_date')}",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Track changes in issue start date
|
||||||
|
def track_start_date(
|
||||||
|
requested_data,
|
||||||
|
current_instance,
|
||||||
|
issue_id,
|
||||||
|
project,
|
||||||
|
actor,
|
||||||
|
issue_activities,
|
||||||
|
):
|
||||||
|
if current_instance.get("start_date") != requested_data.get("start_date"):
|
||||||
|
if requested_data.get("start_date") == None:
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value=current_instance.get("start_date"),
|
||||||
|
new_value=requested_data.get("start_date"),
|
||||||
|
field="start_date",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} updated the start date to None",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value=current_instance.get("start_date"),
|
||||||
|
new_value=requested_data.get("start_date"),
|
||||||
|
field="start_date",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} updated the start date to {requested_data.get('start_date')}",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Track changes in issue labels
|
||||||
|
def track_labels(
|
||||||
|
requested_data,
|
||||||
|
current_instance,
|
||||||
|
issue_id,
|
||||||
|
project,
|
||||||
|
actor,
|
||||||
|
issue_activities,
|
||||||
|
):
|
||||||
|
# Label Addition
|
||||||
|
if len(requested_data.get("labels_list")) > len(current_instance.get("labels")):
|
||||||
|
|
||||||
|
for label in requested_data.get("labels_list"):
|
||||||
|
if label not in current_instance.get("labels"):
|
||||||
|
label = Label.objects.get(pk=label)
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value="",
|
||||||
|
new_value=label.name,
|
||||||
|
field="labels",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} added label {label.name}",
|
||||||
|
new_identifier=label.id,
|
||||||
|
old_identifier=None,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Label Removal
|
||||||
|
if len(requested_data.get("labels_list")) < len(current_instance.get("labels")):
|
||||||
|
|
||||||
|
for label in current_instance.get("labels"):
|
||||||
|
if label not in requested_data.get("labels_list"):
|
||||||
|
label = Label.objects.get(pk=label)
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value=label.name,
|
||||||
|
new_value="",
|
||||||
|
field="labels",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} removed label {label.name}",
|
||||||
|
old_identifier=label.id,
|
||||||
|
new_identifier=None,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Track changes in issue assignees
|
||||||
|
def track_assignees(
|
||||||
|
requested_data,
|
||||||
|
current_instance,
|
||||||
|
issue_id,
|
||||||
|
project,
|
||||||
|
actor,
|
||||||
|
issue_activities,
|
||||||
|
):
|
||||||
|
|
||||||
|
# Assignee Addition
|
||||||
|
if len(requested_data.get("assignees_list")) > len(
|
||||||
|
current_instance.get("assignees")
|
||||||
|
):
|
||||||
|
|
||||||
|
for assignee in requested_data.get("assignees_list"):
|
||||||
|
if assignee not in current_instance.get("assignees"):
|
||||||
|
assignee = User.objects.get(pk=assignee)
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value="",
|
||||||
|
new_value=assignee.email,
|
||||||
|
field="assignees",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} added assignee {assignee.email}",
|
||||||
|
new_identifier=actor.id,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Assignee Removal
|
||||||
|
if len(requested_data.get("assignees_list")) < len(
|
||||||
|
current_instance.get("assignees")
|
||||||
|
):
|
||||||
|
|
||||||
|
for assignee in current_instance.get("assignees"):
|
||||||
|
if assignee not in requested_data.get("assignees_list"):
|
||||||
|
assignee = User.objects.get(pk=assignee)
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value=assignee.email,
|
||||||
|
new_value="",
|
||||||
|
field="assignee",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} removed assignee {assignee.email}",
|
||||||
|
old_identifier=actor.id,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Track changes in blocking issues
|
||||||
|
def track_blocks(
|
||||||
|
requested_data,
|
||||||
|
current_instance,
|
||||||
|
issue_id,
|
||||||
|
project,
|
||||||
|
actor,
|
||||||
|
issue_activities,
|
||||||
|
):
|
||||||
|
if len(requested_data.get("blocks_list")) > len(
|
||||||
|
current_instance.get("blocked_issues")
|
||||||
|
):
|
||||||
|
|
||||||
|
for block in requested_data.get("blocks_list"):
|
||||||
|
if (
|
||||||
|
len(
|
||||||
|
[
|
||||||
|
blocked
|
||||||
|
for blocked in current_instance.get("blocked_issues")
|
||||||
|
if blocked.get("block") == block
|
||||||
|
]
|
||||||
|
)
|
||||||
|
== 0
|
||||||
|
):
|
||||||
|
issue = Issue.objects.get(pk=block)
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value="",
|
||||||
|
new_value=f"{project.identifier}-{issue.sequence_id}",
|
||||||
|
field="blocks",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} added blocking issue {project.identifier}-{issue.sequence_id}",
|
||||||
|
new_identifier=issue.id,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Blocked Issue Removal
|
||||||
|
if len(requested_data.get("blocks_list")) < len(
|
||||||
|
current_instance.get("blocked_issues")
|
||||||
|
):
|
||||||
|
|
||||||
|
for blocked in current_instance.get("blocked_issues"):
|
||||||
|
if blocked.get("block") not in requested_data.get("blocks_list"):
|
||||||
|
issue = Issue.objects.get(pk=blocked.get("block"))
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value=f"{project.identifier}-{issue.sequence_id}",
|
||||||
|
new_value="",
|
||||||
|
field="blocks",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} removed blocking issue {project.identifier}-{issue.sequence_id}",
|
||||||
|
old_identifier=issue.id,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Track changes in blocked_by issues
|
||||||
|
def track_blockings(
|
||||||
|
requested_data,
|
||||||
|
current_instance,
|
||||||
|
issue_id,
|
||||||
|
project,
|
||||||
|
actor,
|
||||||
|
issue_activities,
|
||||||
|
):
|
||||||
|
if len(requested_data.get("blockers_list")) > len(
|
||||||
|
current_instance.get("blocker_issues")
|
||||||
|
):
|
||||||
|
|
||||||
|
for block in requested_data.get("blockers_list"):
|
||||||
|
if (
|
||||||
|
len(
|
||||||
|
[
|
||||||
|
blocked
|
||||||
|
for blocked in current_instance.get("blocker_issues")
|
||||||
|
if blocked.get("blocked_by") == block
|
||||||
|
]
|
||||||
|
)
|
||||||
|
== 0
|
||||||
|
):
|
||||||
|
issue = Issue.objects.get(pk=block)
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value="",
|
||||||
|
new_value=f"{project.identifier}-{issue.sequence_id}",
|
||||||
|
field="blocking",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} added blocked by issue {project.identifier}-{issue.sequence_id}",
|
||||||
|
new_identifier=issue.id,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Blocked Issue Removal
|
||||||
|
if len(requested_data.get("blockers_list")) < len(
|
||||||
|
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"):
|
||||||
|
issue = Issue.objects.get(pk=blocked.get("blocked_by"))
|
||||||
|
issue_activities.append(
|
||||||
|
IssueActivity(
|
||||||
|
issue_id=issue_id,
|
||||||
|
actor=actor,
|
||||||
|
verb="updated",
|
||||||
|
old_value=f"{project.identifier}-{issue.sequence_id}",
|
||||||
|
new_value="",
|
||||||
|
field="blocking",
|
||||||
|
project=project,
|
||||||
|
workspace=project.workspace,
|
||||||
|
comment=f"{actor.email} removed blocked by issue {project.identifier}-{issue.sequence_id}",
|
||||||
|
old_identifier=issue.id,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Receive message from room group
|
||||||
|
@job("default")
|
||||||
|
def issue_activity(event):
|
||||||
|
try:
|
||||||
|
issue_activities = []
|
||||||
|
|
||||||
|
requested_data = json.loads(event.get("requested_data"))
|
||||||
|
current_instance = json.loads(event.get("current_instance"))
|
||||||
|
issue_id = event.get("issue_id")
|
||||||
|
actor_id = event.get("actor_id")
|
||||||
|
project_id = event.get("project_id")
|
||||||
|
|
||||||
|
actor = User.objects.get(pk=actor_id)
|
||||||
|
|
||||||
|
project = Project.objects.get(pk=project_id)
|
||||||
|
|
||||||
|
ISSUE_ACTIVITY_MAPPER = {
|
||||||
|
"name": track_name,
|
||||||
|
"parent": track_parent,
|
||||||
|
"priority": track_priority,
|
||||||
|
"state": track_state,
|
||||||
|
"description": track_description,
|
||||||
|
"target_date": track_target_date,
|
||||||
|
"start_date": track_start_date,
|
||||||
|
"labels_list": track_labels,
|
||||||
|
"assignees_list": track_assignees,
|
||||||
|
"blocks_list": track_blocks,
|
||||||
|
"blockers_list": track_blockings,
|
||||||
|
}
|
||||||
|
|
||||||
|
for key in requested_data:
|
||||||
|
func = ISSUE_ACTIVITY_MAPPER.get(key, None)
|
||||||
|
if func is not None:
|
||||||
|
func(
|
||||||
|
requested_data,
|
||||||
|
current_instance,
|
||||||
|
issue_id,
|
||||||
|
project,
|
||||||
|
actor,
|
||||||
|
issue_activities,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Save all the values to database
|
||||||
|
_ = IssueActivity.objects.bulk_create(issue_activities)
|
||||||
|
|
||||||
|
return
|
||||||
|
except Exception as e:
|
||||||
|
capture_exception(e)
|
||||||
|
return
|
@ -1,52 +1,5 @@
|
|||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
from fieldsignals import post_save_changed
|
|
||||||
|
|
||||||
|
|
||||||
class DbConfig(AppConfig):
|
class DbConfig(AppConfig):
|
||||||
name = "plane.db"
|
name = "plane.db"
|
||||||
|
|
||||||
# def ready(self):
|
|
||||||
|
|
||||||
# post_save_changed.connect(
|
|
||||||
# self.model_activity,
|
|
||||||
# sender=self.get_model("Issue"),
|
|
||||||
# )
|
|
||||||
|
|
||||||
# def model_activity(self, sender, instance, changed_fields, **kwargs):
|
|
||||||
|
|
||||||
# verb = "created" if instance._state.adding else "changed"
|
|
||||||
|
|
||||||
# import inspect
|
|
||||||
|
|
||||||
# for frame_record in inspect.stack():
|
|
||||||
# if frame_record[3] == "get_response":
|
|
||||||
# request = frame_record[0].f_locals["request"]
|
|
||||||
# REQUEST_METHOD = request.method
|
|
||||||
|
|
||||||
# if REQUEST_METHOD == "POST":
|
|
||||||
|
|
||||||
# self.get_model("IssueActivity").objects.create(
|
|
||||||
# issue=instance, project=instance.project, actor=instance.created_by
|
|
||||||
# )
|
|
||||||
|
|
||||||
# elif REQUEST_METHOD == "PATCH":
|
|
||||||
|
|
||||||
# try:
|
|
||||||
# del changed_fields["updated_at"]
|
|
||||||
# del changed_fields["updated_by"]
|
|
||||||
# except KeyError as e:
|
|
||||||
# pass
|
|
||||||
|
|
||||||
# for field_name, (old, new) in changed_fields.items():
|
|
||||||
# field = field_name
|
|
||||||
# old_value = old
|
|
||||||
# new_value = new
|
|
||||||
# self.get_model("IssueActivity").objects.create(
|
|
||||||
# issue=instance,
|
|
||||||
# verb=verb,
|
|
||||||
# field=field,
|
|
||||||
# old_value=old_value,
|
|
||||||
# new_value=new_value,
|
|
||||||
# project=instance.project,
|
|
||||||
# actor=instance.updated_by,
|
|
||||||
# )
|
|
||||||
|
@ -145,12 +145,8 @@ class IssueActivity(ProjectBaseModel):
|
|||||||
field = models.CharField(
|
field = models.CharField(
|
||||||
max_length=255, verbose_name="Field Name", blank=True, null=True
|
max_length=255, verbose_name="Field Name", blank=True, null=True
|
||||||
)
|
)
|
||||||
old_value = models.CharField(
|
old_value = models.TextField(verbose_name="Old Value", blank=True, null=True)
|
||||||
max_length=255, verbose_name="Old Value", blank=True, null=True
|
new_value = models.TextField(verbose_name="New Value", blank=True, null=True)
|
||||||
)
|
|
||||||
new_value = models.CharField(
|
|
||||||
max_length=255, verbose_name="New Value", blank=True, null=True
|
|
||||||
)
|
|
||||||
|
|
||||||
comment = models.TextField(verbose_name="Comment", blank=True)
|
comment = models.TextField(verbose_name="Comment", blank=True)
|
||||||
attachments = ArrayField(models.URLField(), size=10, blank=True, default=list)
|
attachments = ArrayField(models.URLField(), size=10, blank=True, default=list)
|
||||||
|
@ -34,9 +34,7 @@ INSTALLED_APPS = [
|
|||||||
"rest_framework_simplejwt.token_blacklist",
|
"rest_framework_simplejwt.token_blacklist",
|
||||||
"corsheaders",
|
"corsheaders",
|
||||||
"taggit",
|
"taggit",
|
||||||
"fieldsignals",
|
|
||||||
"django_rq",
|
"django_rq",
|
||||||
"channels",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
@ -66,11 +66,3 @@ RQ_QUEUES = {
|
|||||||
|
|
||||||
WEB_URL = "http://localhost:3000"
|
WEB_URL = "http://localhost:3000"
|
||||||
|
|
||||||
CHANNEL_LAYERS = {
|
|
||||||
"default": {
|
|
||||||
"BACKEND": "channels_redis.core.RedisChannelLayer",
|
|
||||||
"CONFIG": {
|
|
||||||
"hosts": [(REDIS_HOST, REDIS_PORT)],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
"""Production settings and globals."""
|
"""Production settings and globals."""
|
||||||
import ssl
|
|
||||||
from typing import Optional
|
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
import dj_database_url
|
import dj_database_url
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
from redis.asyncio.connection import Connection, RedisSSLContext
|
|
||||||
|
|
||||||
import sentry_sdk
|
import sentry_sdk
|
||||||
from sentry_sdk.integrations.django import DjangoIntegration
|
from sentry_sdk.integrations.django import DjangoIntegration
|
||||||
@ -186,64 +183,10 @@ RQ_QUEUES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class CustomSSLConnection(Connection):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
ssl_context: Optional[str] = None,
|
|
||||||
**kwargs,
|
|
||||||
):
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
self.ssl_context = RedisSSLContext(ssl_context)
|
|
||||||
|
|
||||||
|
|
||||||
class RedisSSLContext:
|
|
||||||
__slots__ = ("context",)
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
ssl_context,
|
|
||||||
):
|
|
||||||
self.context = ssl_context
|
|
||||||
|
|
||||||
def get(self):
|
|
||||||
return self.context
|
|
||||||
|
|
||||||
|
|
||||||
url = urlparse(os.environ.get("REDIS_URL"))
|
url = urlparse(os.environ.get("REDIS_URL"))
|
||||||
|
|
||||||
DOCKERIZED = os.environ.get("DOCKERIZED", False) # Set the variable true if running in docker-compose environment
|
DOCKERIZED = os.environ.get(
|
||||||
|
"DOCKERIZED", False
|
||||||
if not DOCKERIZED:
|
) # Set the variable true if running in docker-compose environment
|
||||||
|
|
||||||
ssl_context = ssl.SSLContext()
|
|
||||||
ssl_context.check_hostname = False
|
|
||||||
|
|
||||||
CHANNEL_LAYERS = {
|
|
||||||
"default": {
|
|
||||||
"BACKEND": "channels_redis.core.RedisChannelLayer",
|
|
||||||
"CONFIG": {
|
|
||||||
"hosts": [
|
|
||||||
{
|
|
||||||
"host": url.hostname,
|
|
||||||
"port": url.port,
|
|
||||||
"username": url.username,
|
|
||||||
"password": url.password,
|
|
||||||
"connection_class": CustomSSLConnection,
|
|
||||||
"ssl_context": ssl_context,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
CHANNEL_LAYERS = {
|
|
||||||
"default": {
|
|
||||||
"BACKEND": "channels_redis.core.RedisChannelLayer",
|
|
||||||
"CONFIG": {
|
|
||||||
"hosts": [(os.environ.get("REDIS_URL"))],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
WEB_URL = os.environ.get("WEB_URL")
|
WEB_URL = os.environ.get("WEB_URL")
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
"""Production settings and globals."""
|
"""Production settings and globals."""
|
||||||
import ssl
|
|
||||||
from typing import Optional
|
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
import dj_database_url
|
import dj_database_url
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
from redis.asyncio.connection import Connection, RedisSSLContext
|
|
||||||
|
|
||||||
import sentry_sdk
|
import sentry_sdk
|
||||||
from sentry_sdk.integrations.django import DjangoIntegration
|
from sentry_sdk.integrations.django import DjangoIntegration
|
||||||
@ -186,52 +183,5 @@ RQ_QUEUES = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CustomSSLConnection(Connection):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
ssl_context: Optional[str] = None,
|
|
||||||
**kwargs,
|
|
||||||
):
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
self.ssl_context = RedisSSLContext(ssl_context)
|
|
||||||
|
|
||||||
class RedisSSLContext:
|
|
||||||
__slots__ = (
|
|
||||||
"context",
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
ssl_context,
|
|
||||||
):
|
|
||||||
self.context = ssl_context
|
|
||||||
|
|
||||||
def get(self):
|
|
||||||
return self.context
|
|
||||||
|
|
||||||
|
|
||||||
url = urlparse(os.environ.get("REDIS_URL"))
|
|
||||||
|
|
||||||
ssl_context = ssl.SSLContext()
|
|
||||||
ssl_context.check_hostname = False
|
|
||||||
|
|
||||||
CHANNEL_LAYERS = {
|
|
||||||
'default': {
|
|
||||||
'BACKEND': 'channels_redis.core.RedisChannelLayer',
|
|
||||||
'CONFIG': {
|
|
||||||
'hosts': [
|
|
||||||
{
|
|
||||||
'host': url.hostname,
|
|
||||||
'port': url.port,
|
|
||||||
'username': url.username,
|
|
||||||
'password': url.password,
|
|
||||||
'connection_class': CustomSSLConnection,
|
|
||||||
'ssl_context': ssl_context,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
WEB_URL = os.environ.get("WEB_URL")
|
WEB_URL = os.environ.get("WEB_URL")
|
||||||
|
@ -20,12 +20,9 @@ sentry-sdk==1.13.0
|
|||||||
django-s3-storage==0.13.6
|
django-s3-storage==0.13.6
|
||||||
django-crum==0.7.9
|
django-crum==0.7.9
|
||||||
django-guardian==2.4.0
|
django-guardian==2.4.0
|
||||||
django-fieldsignals==0.7.0
|
|
||||||
dj_rest_auth==2.2.5
|
dj_rest_auth==2.2.5
|
||||||
google-auth==2.9.1
|
google-auth==2.9.1
|
||||||
google-api-python-client==2.55.0
|
google-api-python-client==2.55.0
|
||||||
django-rq==2.5.1
|
django-rq==2.5.1
|
||||||
django-redis==5.2.0
|
django-redis==5.2.0
|
||||||
channels==4.0.0
|
|
||||||
channels-redis==4.0.0
|
|
||||||
uvicorn==0.20.0
|
uvicorn==0.20.0
|
@ -68,21 +68,6 @@ services:
|
|||||||
env_file:
|
env_file:
|
||||||
- ./apiserver/.env
|
- ./apiserver/.env
|
||||||
|
|
||||||
plane-channel-worker:
|
|
||||||
image: plane-api
|
|
||||||
container_name: plane-channel-worker
|
|
||||||
restart: always
|
|
||||||
depends_on:
|
|
||||||
- redis
|
|
||||||
- db
|
|
||||||
- plane-api
|
|
||||||
command: ./bin/channel-worker
|
|
||||||
links:
|
|
||||||
- redis:redis
|
|
||||||
- db:db
|
|
||||||
env_file:
|
|
||||||
- ./apiserver/.env
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
pgdata:
|
pgdata:
|
||||||
redisdata:
|
redisdata:
|
||||||
|
Loading…
Reference in New Issue
Block a user