From 9461163a9bdb886fdf8f52c5c7e62fbe949740bd Mon Sep 17 00:00:00 2001 From: NarayanBavisetti Date: Sat, 30 Nov 2024 15:30:58 +0530 Subject: [PATCH 1/2] chore: issue description history --- apiserver/plane/app/views/issue/base.py | 5 +- apiserver/plane/bgtasks/issue_version_task.py | 83 +++++++++++++++++++ apiserver/plane/db/models/__init__.py | 3 +- 3 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 apiserver/plane/bgtasks/issue_version_task.py diff --git a/apiserver/plane/app/views/issue/base.py b/apiserver/plane/app/views/issue/base.py index 3d548aeacce..18402cfa912 100644 --- a/apiserver/plane/app/views/issue/base.py +++ b/apiserver/plane/app/views/issue/base.py @@ -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]) @@ -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) diff --git a/apiserver/plane/bgtasks/issue_version_task.py b/apiserver/plane/bgtasks/issue_version_task.py new file mode 100644 index 00000000000..a36e308c753 --- /dev/null +++ b/apiserver/plane/bgtasks/issue_version_task.py @@ -0,0 +1,83 @@ +# 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 {} + ) + + # 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.objects.create( + issue_id=issue_id, + workspace_id=issue.workspace_id, + description=issue.description, + description_html=issue.description_html, + description_binary=issue.description_binary, + description_stripped=issue.description_stripped, + owned_by=user_id, + last_saved_at=issue.updated_at, + project_id=issue.project_id, + created_by_id=issue.created_by_id, + updated_by_id=issue.updated_by_id, + priority=issue.priority, + + ) + return + except Issue.DoesNotExist: + return + except Exception as e: + log_exception(e) + return diff --git a/apiserver/plane/db/models/__init__.py b/apiserver/plane/db/models/__init__.py index 36810956c27..9be2e99724f 100644 --- a/apiserver/plane/db/models/__init__.py +++ b/apiserver/plane/db/models/__init__.py @@ -41,6 +41,7 @@ IssueSequence, IssueSubscriber, IssueVote, + IssueVersion, ) from .module import Module, ModuleIssue, ModuleLink, ModuleMember, ModuleUserProperties from .notification import EmailNotificationLog, Notification, UserNotificationPreference @@ -53,7 +54,6 @@ ProjectMemberInvite, ProjectPublicMember, ) -from .deploy_board import DeployBoard from .session import Session from .social_connection import SocialLoginConnection from .state import State @@ -68,7 +68,6 @@ WorkspaceTheme, WorkspaceUserProperties, ) - from .importer import Importer from .page import Page, PageLog, PageLabel From 28ece2946f5fb34f3f350251a73c11c263de9cb6 Mon Sep 17 00:00:00 2001 From: NarayanBavisetti Date: Sun, 1 Dec 2024 21:00:54 +0530 Subject: [PATCH 2/2] chore: updated issue version with model method --- apiserver/plane/bgtasks/issue_version_task.py | 16 +------------ apiserver/plane/db/models/issue.py | 24 +++++++++---------- 2 files changed, 13 insertions(+), 27 deletions(-) diff --git a/apiserver/plane/bgtasks/issue_version_task.py b/apiserver/plane/bgtasks/issue_version_task.py index a36e308c753..f039e5efe1f 100644 --- a/apiserver/plane/bgtasks/issue_version_task.py +++ b/apiserver/plane/bgtasks/issue_version_task.py @@ -60,21 +60,7 @@ def issue_version_task( ) else: # Create a new issue version - IssueVersion.objects.create( - issue_id=issue_id, - workspace_id=issue.workspace_id, - description=issue.description, - description_html=issue.description_html, - description_binary=issue.description_binary, - description_stripped=issue.description_stripped, - owned_by=user_id, - last_saved_at=issue.updated_at, - project_id=issue.project_id, - created_by_id=issue.created_by_id, - updated_by_id=issue.updated_by_id, - priority=issue.priority, - - ) + IssueVersion.log_issue_version(issue, user_id) return except Issue.DoesNotExist: return diff --git a/apiserver/plane/db/models/issue.py b/apiserver/plane/db/models/issue.py index e50dbe7ce82..779f9705a90 100644 --- a/apiserver/plane/db/models/issue.py +++ b/apiserver/plane/db/models/issue.py @@ -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 @@ -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( @@ -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, @@ -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, )