Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion apiserver/plane/app/views/issue/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
from plane.bgtasks.recent_visited_task import recent_visited_task
from plane.utils.global_paginator import paginate
from plane.bgtasks.webhook_task import model_activity

from plane.bgtasks.issue_version_task import issue_version_task

class IssueListEndpoint(BaseAPIView):
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
Expand Down Expand Up @@ -653,6 +653,9 @@ def partial_update(self, request, slug, project_id, pk=None):
slug=slug,
origin=request.META.get("HTTP_ORIGIN"),
)
issue_version_task.delay(
issue_id=pk, existing_instance=current_instance, user_id=request.user.id
)
return Response(status=status.HTTP_204_NO_CONTENT)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Expand Down
69 changes: 69 additions & 0 deletions apiserver/plane/bgtasks/issue_version_task.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Python imports
import json

# Django imports
from django.utils import timezone

# Third party imports
from celery import shared_task

# Module imports
from plane.db.models import Issue, IssueVersion
from plane.utils.exception_logger import log_exception


@shared_task
def issue_version_task(
issue_id,
existing_instance,
user_id,
):
try:

# Get the current instance
current_instance = (
json.loads(existing_instance) if existing_instance is not None else {}
)
Comment on lines +25 to +26
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add error handling for JSON parsing of existing_instance.

Parsing existing_instance without handling potential JSONDecodeError exceptions may lead to crashes if invalid JSON is provided. Consider adding a try-except block to handle this scenario gracefully.

Apply this diff to fix the issue:

 try:
     current_instance = (
-        json.loads(existing_instance) if existing_instance is not None else {}
+        json.loads(existing_instance) if existing_instance else {}
     )
+except json.JSONDecodeError:
+    current_instance = {}
+    # Optionally, log the error or handle it appropriately

Committable suggestion skipped: line range outside the PR's diff.


# Get the issue
issue = Issue.objects.get(id=issue_id)

# Create a version if description_html is updated
if current_instance.get("description_html") != issue.description_html:
# Fetch the latest issue version
issue_version = (
IssueVersion.objects.filter(issue_id=issue_id)
.order_by("-last_saved_at")
.first()
)

# Get the latest issue version if it exists and is owned by the user
if (
issue_version
and str(issue_version.owned_by) == str(user_id)
and (timezone.now() - issue_version.last_saved_at).total_seconds()
<= 600
):
issue_version.description = issue.description
issue_version.description_html = issue.description_html
issue_version.description_binary = issue.description_binary
issue_version.description_stripped = issue.description_stripped
issue_version.last_saved_at = timezone.now()
issue_version.save(
update_fields=[
"description",
"description_html",
"description_binary",
"description_stripped",
"last_saved_at",
]
)
else:
# Create a new issue version
IssueVersion.log_issue_version(issue, user_id)
return
except Issue.DoesNotExist:
return
except Exception as e:
log_exception(e)
return
3 changes: 1 addition & 2 deletions apiserver/plane/db/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
IssueSequence,
IssueSubscriber,
IssueVote,
IssueVersion,
)
from .module import Module, ModuleIssue, ModuleLink, ModuleMember, ModuleUserProperties
from .notification import EmailNotificationLog, Notification, UserNotificationPreference
Expand All @@ -53,7 +54,6 @@
ProjectMemberInvite,
ProjectPublicMember,
)
from .deploy_board import DeployBoard
from .session import Session
from .social_connection import SocialLoginConnection
from .state import State
Expand All @@ -68,7 +68,6 @@
WorkspaceTheme,
WorkspaceUserProperties,
)

from .importer import Importer

from .page import Page, PageLog, PageLabel
Expand Down
24 changes: 12 additions & 12 deletions apiserver/plane/db/models/issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from django.db import models, transaction
from django.utils import timezone
from django.db.models import Q
from django import apps
from django.apps import apps

# Module imports
from plane.utils.html_processor import strip_tags
Expand Down Expand Up @@ -738,7 +738,7 @@ def log_issue_version(cls, issue, user):
Log the issue version
"""

Module = apps.get_model("db.Module")
ModuleIssue = apps.get_model("db.ModuleIssue")
CycleIssue = apps.get_model("db.CycleIssue")

cycle_issue = CycleIssue.objects.filter(
Expand All @@ -747,10 +747,10 @@ def log_issue_version(cls, issue, user):

cls.objects.create(
issue=issue,
parent=issue.parent,
state=issue.state,
point=issue.point,
estimate_point=issue.estimate_point,
project_id=issue.project_id,
parent=issue.parent_id,
state=issue.state_id,
estimate_point=issue.estimate_point_id,
name=issue.name,
description=issue.description,
description_html=issue.description_html,
Expand All @@ -767,12 +767,12 @@ def log_issue_version(cls, issue, user):
external_source=issue.external_source,
external_id=issue.external_id,
type=issue.type,
last_saved_at=issue.last_saved_at,
assignees=issue.assignees,
labels=issue.labels,
cycle=cycle_issue.cycle if cycle_issue else None,
modules=Module.objects.filter(issue=issue).values_list(
"id", flat=True
last_saved_at=timezone.now(),
assignees=list(issue.assignees.values_list("id", flat=True)),
labels=list(issue.labels.values_list("id", flat=True)),
cycle=cycle_issue.cycle_id if cycle_issue else None,
modules=list(ModuleIssue.objects.filter(issue=issue).values_list(
"id", flat=True)
),
owned_by=user,
)
Expand Down
Loading