From 879fda8117b497e9a58a85e83554bd565eb0c1c0 Mon Sep 17 00:00:00 2001 From: NarayanBavisetti Date: Thu, 14 Sep 2023 17:15:26 +0530 Subject: [PATCH] chore: added epoch in issue activity --- apiserver/plane/api/views/cycle.py | 3 + apiserver/plane/api/views/inbox.py | 4 + apiserver/plane/api/views/issue.py | 32 +++++ apiserver/plane/api/views/module.py | 4 + .../plane/bgtasks/issue_activites_task.py | 120 +++++++++++++----- .../plane/bgtasks/issue_automation_task.py | 2 + ..._alter_analyticview_created_by_and_more.py | 27 ++++ apiserver/plane/db/models/issue.py | 1 + 8 files changed, 163 insertions(+), 30 deletions(-) create mode 100644 apiserver/plane/db/migrations/0045_issueactivity_epoch_alter_analyticview_created_by_and_more.py diff --git a/apiserver/plane/api/views/cycle.py b/apiserver/plane/api/views/cycle.py index 4f9e1db32..4f895aeba 100644 --- a/apiserver/plane/api/views/cycle.py +++ b/apiserver/plane/api/views/cycle.py @@ -80,6 +80,7 @@ class CycleViewSet(BaseViewSet): issue_id=str(self.kwargs.get("pk", None)), project_id=str(self.kwargs.get("project_id", None)), current_instance=None, + epoch = int(timezone.now().timestamp()) ) return super().perform_destroy(instance) @@ -487,6 +488,7 @@ class CycleIssueViewSet(BaseViewSet): issue_id=str(self.kwargs.get("pk", None)), project_id=str(self.kwargs.get("project_id", None)), current_instance=None, + epoch = int(timezone.now().timestamp()) ) return super().perform_destroy(instance) @@ -662,6 +664,7 @@ class CycleIssueViewSet(BaseViewSet): ), } ), + epoch = int(timezone.now().timestamp()) ) # Return all Cycle Issues diff --git a/apiserver/plane/api/views/inbox.py b/apiserver/plane/api/views/inbox.py index 4fbea5f87..1a0284ea4 100644 --- a/apiserver/plane/api/views/inbox.py +++ b/apiserver/plane/api/views/inbox.py @@ -213,6 +213,7 @@ class InboxIssueViewSet(BaseViewSet): issue_id=str(issue.id), project_id=str(project_id), current_instance=None, + epoch = int(timezone.now().timestamp()) ) # create an inbox issue InboxIssue.objects.create( @@ -277,6 +278,7 @@ class InboxIssueViewSet(BaseViewSet): IssueSerializer(current_instance).data, cls=DjangoJSONEncoder, ), + epoch = int(timezone.now().timestamp()) ) issue_serializer.save() else: @@ -518,6 +520,7 @@ class InboxIssuePublicViewSet(BaseViewSet): issue_id=str(issue.id), project_id=str(project_id), current_instance=None, + epoch = int(timezone.now().timestamp()) ) # create an inbox issue InboxIssue.objects.create( @@ -582,6 +585,7 @@ class InboxIssuePublicViewSet(BaseViewSet): IssueSerializer(current_instance).data, cls=DjangoJSONEncoder, ), + epoch = int(timezone.now().timestamp()) ) issue_serializer.save() return Response(issue_serializer.data, status=status.HTTP_200_OK) diff --git a/apiserver/plane/api/views/issue.py b/apiserver/plane/api/views/issue.py index 16dce6f47..4ba30fcdd 100644 --- a/apiserver/plane/api/views/issue.py +++ b/apiserver/plane/api/views/issue.py @@ -4,6 +4,7 @@ import random from itertools import chain # Django imports +from django.utils import timezone from django.db.models import ( Prefetch, OuterRef, @@ -128,6 +129,7 @@ class IssueViewSet(BaseViewSet): current_instance=json.dumps( IssueSerializer(current_instance).data, cls=DjangoJSONEncoder ), + epoch = int(timezone.now().time()) ) return super().perform_update(serializer) @@ -148,6 +150,7 @@ class IssueViewSet(BaseViewSet): current_instance=json.dumps( IssueSerializer(current_instance).data, cls=DjangoJSONEncoder ), + epoch = int(timezone.now().timestamp()) ) return super().perform_destroy(instance) @@ -314,6 +317,7 @@ class IssueViewSet(BaseViewSet): issue_id=str(serializer.data.get("id", None)), project_id=str(project_id), current_instance=None, + epoch = int(timezone.now().timestamp()) ) return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @@ -567,6 +571,7 @@ class IssueCommentViewSet(BaseViewSet): issue_id=str(self.kwargs.get("issue_id")), project_id=str(self.kwargs.get("project_id")), current_instance=None, + epoch = int(timezone.now().timestamp()) ) def perform_update(self, serializer): @@ -585,6 +590,7 @@ class IssueCommentViewSet(BaseViewSet): IssueCommentSerializer(current_instance).data, cls=DjangoJSONEncoder, ), + epoch = int(timezone.now().timestamp()) ) return super().perform_update(serializer) @@ -606,6 +612,7 @@ class IssueCommentViewSet(BaseViewSet): IssueCommentSerializer(current_instance).data, cls=DjangoJSONEncoder, ), + epoch = int(timezone.now().timestamp()) ) return super().perform_destroy(instance) @@ -889,6 +896,7 @@ class IssueLinkViewSet(BaseViewSet): issue_id=str(self.kwargs.get("issue_id")), project_id=str(self.kwargs.get("project_id")), current_instance=None, + epoch = int(timezone.now().timestamp()) ) def perform_update(self, serializer): @@ -907,6 +915,7 @@ class IssueLinkViewSet(BaseViewSet): IssueLinkSerializer(current_instance).data, cls=DjangoJSONEncoder, ), + epoch = int(timezone.now().timestamp()) ) return super().perform_update(serializer) @@ -928,6 +937,7 @@ class IssueLinkViewSet(BaseViewSet): IssueLinkSerializer(current_instance).data, cls=DjangoJSONEncoder, ), + epoch = int(timezone.now().timestamp()) ) return super().perform_destroy(instance) @@ -1006,6 +1016,7 @@ class IssueAttachmentEndpoint(BaseAPIView): serializer.data, cls=DjangoJSONEncoder, ), + epoch = int(timezone.now().timestamp()) ) return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @@ -1028,6 +1039,7 @@ class IssueAttachmentEndpoint(BaseAPIView): issue_id=str(self.kwargs.get("issue_id", None)), project_id=str(self.kwargs.get("project_id", None)), current_instance=None, + epoch = int(timezone.now().timestamp()) ) return Response(status=status.HTTP_204_NO_CONTENT) @@ -1230,6 +1242,7 @@ class IssueArchiveViewSet(BaseViewSet): issue_id=str(issue.id), project_id=str(project_id), current_instance=None, + epoch = int(timezone.now().timestamp()) ) return Response(IssueSerializer(issue).data, status=status.HTTP_200_OK) @@ -1434,6 +1447,7 @@ class IssueReactionViewSet(BaseViewSet): issue_id=str(self.kwargs.get("issue_id", None)), project_id=str(self.kwargs.get("project_id", None)), current_instance=None, + epoch = int(timezone.now().timestamp()) ) def destroy(self, request, slug, project_id, issue_id, reaction_code): @@ -1457,6 +1471,7 @@ class IssueReactionViewSet(BaseViewSet): "identifier": str(issue_reaction.id), } ), + epoch = int(timezone.now().timestamp()) ) issue_reaction.delete() return Response(status=status.HTTP_204_NO_CONTENT) @@ -1505,6 +1520,7 @@ class CommentReactionViewSet(BaseViewSet): issue_id=None, project_id=str(self.kwargs.get("project_id", None)), current_instance=None, + epoch = int(timezone.now().timestamp()) ) def destroy(self, request, slug, project_id, comment_id, reaction_code): @@ -1529,6 +1545,7 @@ class CommentReactionViewSet(BaseViewSet): "comment_id": str(comment_id), } ), + epoch = int(timezone.now().timestamp()) ) comment_reaction.delete() return Response(status=status.HTTP_204_NO_CONTENT) @@ -1625,6 +1642,7 @@ class IssueCommentPublicViewSet(BaseViewSet): issue_id=str(issue_id), project_id=str(project_id), current_instance=None, + epoch = int(timezone.now().timestamp()) ) if not ProjectMember.objects.filter( project_id=project_id, @@ -1674,6 +1692,7 @@ class IssueCommentPublicViewSet(BaseViewSet): IssueCommentSerializer(comment).data, cls=DjangoJSONEncoder, ), + epoch = int(timezone.now().timestamp()) ) return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @@ -1707,6 +1726,7 @@ class IssueCommentPublicViewSet(BaseViewSet): IssueCommentSerializer(comment).data, cls=DjangoJSONEncoder, ), + epoch = int(timezone.now().timestamp()) ) comment.delete() return Response(status=status.HTTP_204_NO_CONTENT) @@ -1781,6 +1801,7 @@ class IssueReactionPublicViewSet(BaseViewSet): issue_id=str(self.kwargs.get("issue_id", None)), project_id=str(self.kwargs.get("project_id", None)), current_instance=None, + epoch = int(timezone.now().timestamp()) ) return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @@ -1825,6 +1846,7 @@ class IssueReactionPublicViewSet(BaseViewSet): "identifier": str(issue_reaction.id), } ), + epoch = int(timezone.now().timestamp()) ) issue_reaction.delete() return Response(status=status.HTTP_204_NO_CONTENT) @@ -1898,6 +1920,7 @@ class CommentReactionPublicViewSet(BaseViewSet): issue_id=None, project_id=str(self.kwargs.get("project_id", None)), current_instance=None, + epoch = int(timezone.now().timestamp()) ) return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @@ -1949,6 +1972,7 @@ class CommentReactionPublicViewSet(BaseViewSet): "comment_id": str(comment_id), } ), + epoch = int(timezone.now().timestamp()) ) comment_reaction.delete() return Response(status=status.HTTP_204_NO_CONTENT) @@ -2012,6 +2036,7 @@ class IssueVotePublicViewSet(BaseViewSet): issue_id=str(self.kwargs.get("issue_id", None)), project_id=str(self.kwargs.get("project_id", None)), current_instance=None, + epoch = int(timezone.now().timestamp()) ) serializer = IssueVoteSerializer(issue_vote) return Response(serializer.data, status=status.HTTP_201_CREATED) @@ -2046,6 +2071,7 @@ class IssueVotePublicViewSet(BaseViewSet): "identifier": str(issue_vote.id), } ), + epoch = int(timezone.now().timestamp()) ) issue_vote.delete() return Response(status=status.HTTP_204_NO_CONTENT) @@ -2079,6 +2105,7 @@ class IssueRelationViewSet(BaseViewSet): IssueRelationSerializer(current_instance).data, cls=DjangoJSONEncoder, ), + epoch = int(timezone.now().timestamp()) ) return super().perform_destroy(instance) @@ -2111,6 +2138,7 @@ class IssueRelationViewSet(BaseViewSet): issue_id=str(issue_id), project_id=str(project_id), current_instance=None, + epoch = int(timezone.now().timestamp()) ) return Response( @@ -2149,6 +2177,8 @@ class IssueRelationViewSet(BaseViewSet): .select_related("issue") .distinct() ) + + class IssueRetrievePublicEndpoint(BaseAPIView): permission_classes = [ AllowAny, @@ -2374,6 +2404,7 @@ class IssueDraftViewSet(BaseViewSet): current_instance=json.dumps( IssueSerializer(current_instance).data, cls=DjangoJSONEncoder ), + epoch = int(timezone.now().time()) ) return super().perform_update(serializer) @@ -2558,6 +2589,7 @@ class IssueDraftViewSet(BaseViewSet): issue_id=str(serializer.data.get("id", None)), project_id=str(project_id), current_instance=None, + epoch = int(timezone.now().timestamp()) ) return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) diff --git a/apiserver/plane/api/views/module.py b/apiserver/plane/api/views/module.py index 5a472945a..c2a15da1c 100644 --- a/apiserver/plane/api/views/module.py +++ b/apiserver/plane/api/views/module.py @@ -2,6 +2,7 @@ import json # Django Imports +from django.utils import timezone from django.db import IntegrityError from django.db.models import Prefetch, F, OuterRef, Func, Exists, Count, Q from django.core import serializers @@ -129,6 +130,7 @@ class ModuleViewSet(BaseViewSet): issue_id=str(self.kwargs.get("pk", None)), project_id=str(self.kwargs.get("project_id", None)), current_instance=None, + epoch = int(timezone.now().timestamp()) ) return super().perform_destroy(instance) @@ -277,6 +279,7 @@ class ModuleIssueViewSet(BaseViewSet): issue_id=str(self.kwargs.get("pk", None)), project_id=str(self.kwargs.get("project_id", None)), current_instance=None, + epoch = int(timezone.now().timestamp()) ) return super().perform_destroy(instance) @@ -444,6 +447,7 @@ class ModuleIssueViewSet(BaseViewSet): ), } ), + epoch = int(timezone.now().timestamp()) ) return Response( diff --git a/apiserver/plane/bgtasks/issue_activites_task.py b/apiserver/plane/bgtasks/issue_activites_task.py index 73fd54a7e..d01bd32ef 100644 --- a/apiserver/plane/bgtasks/issue_activites_task.py +++ b/apiserver/plane/bgtasks/issue_activites_task.py @@ -39,6 +39,7 @@ def track_name( project, actor, issue_activities, + epoch ): if current_instance.get("name") != requested_data.get("name"): issue_activities.append( @@ -52,6 +53,7 @@ def track_name( project=project, workspace=project.workspace, comment=f"updated the name to {requested_data.get('name')}", + epoch=epoch, ) ) @@ -64,6 +66,7 @@ def track_parent( project, actor, issue_activities, + epoch ): if current_instance.get("parent") != requested_data.get("parent"): if requested_data.get("parent") == None: @@ -81,6 +84,7 @@ def track_parent( comment=f"updated the parent issue to None", old_identifier=old_parent.id, new_identifier=None, + epoch=epoch, ) ) else: @@ -101,6 +105,7 @@ def track_parent( comment=f"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, + epoch=epoch, ) ) @@ -113,6 +118,7 @@ def track_priority( project, actor, issue_activities, + epoch ): if current_instance.get("priority") != requested_data.get("priority"): if requested_data.get("priority") == None: @@ -127,6 +133,7 @@ def track_priority( project=project, workspace=project.workspace, comment=f"updated the priority to None", + epoch=epoch, ) ) else: @@ -141,6 +148,7 @@ def track_priority( project=project, workspace=project.workspace, comment=f"updated the priority to {requested_data.get('priority')}", + epoch=epoch, ) ) @@ -153,6 +161,7 @@ def track_state( project, actor, issue_activities, + epoch ): if current_instance.get("state") != requested_data.get("state"): new_state = State.objects.get(pk=requested_data.get("state", None)) @@ -171,6 +180,7 @@ def track_state( comment=f"updated the state to {new_state.name}", old_identifier=old_state.id, new_identifier=new_state.id, + epoch=epoch, ) ) @@ -183,6 +193,7 @@ def track_description( project, actor, issue_activities, + epoch ): if current_instance.get("description_html") != requested_data.get( "description_html" @@ -203,6 +214,7 @@ def track_description( project=project, workspace=project.workspace, comment=f"updated the description to {requested_data.get('description_html')}", + epoch=epoch, ) ) @@ -215,6 +227,7 @@ def track_target_date( project, actor, issue_activities, + epoch ): if current_instance.get("target_date") != requested_data.get("target_date"): if requested_data.get("target_date") == None: @@ -229,6 +242,7 @@ def track_target_date( project=project, workspace=project.workspace, comment=f"updated the target date to None", + epoch=epoch, ) ) else: @@ -243,6 +257,7 @@ def track_target_date( project=project, workspace=project.workspace, comment=f"updated the target date to {requested_data.get('target_date')}", + epoch=epoch, ) ) @@ -255,6 +270,7 @@ def track_start_date( project, actor, issue_activities, + epoch ): if current_instance.get("start_date") != requested_data.get("start_date"): if requested_data.get("start_date") == None: @@ -269,6 +285,7 @@ def track_start_date( project=project, workspace=project.workspace, comment=f"updated the start date to None", + epoch=epoch, ) ) else: @@ -283,6 +300,7 @@ def track_start_date( project=project, workspace=project.workspace, comment=f"updated the start date to {requested_data.get('start_date')}", + epoch=epoch, ) ) @@ -295,6 +313,7 @@ def track_labels( project, actor, issue_activities, + epoch ): # Label Addition if len(requested_data.get("labels_list")) > len(current_instance.get("labels")): @@ -314,6 +333,7 @@ def track_labels( comment=f"added label {label.name}", new_identifier=label.id, old_identifier=None, + epoch=epoch, ) ) @@ -335,6 +355,7 @@ def track_labels( comment=f"removed label {label.name}", old_identifier=label.id, new_identifier=None, + epoch=epoch, ) ) @@ -347,6 +368,7 @@ def track_assignees( project, actor, issue_activities, + epoch ): # Assignee Addition if len(requested_data.get("assignees_list")) > len( @@ -367,6 +389,7 @@ def track_assignees( workspace=project.workspace, comment=f"added assignee {assignee.display_name}", new_identifier=assignee.id, + epoch=epoch, ) ) @@ -389,12 +412,13 @@ def track_assignees( workspace=project.workspace, comment=f"removed assignee {assignee.display_name}", old_identifier=assignee.id, + epoch=epoch, ) ) def create_issue_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): issue_activities.append( IssueActivity( @@ -404,12 +428,13 @@ def create_issue_activity( comment=f"created the issue", verb="created", actor=actor, + epoch=epoch, ) ) def track_estimate_points( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): if current_instance.get("estimate_point") != requested_data.get("estimate_point"): if requested_data.get("estimate_point") == None: @@ -424,6 +449,7 @@ def track_estimate_points( project=project, workspace=project.workspace, comment=f"updated the estimate point to None", + epoch=epoch, ) ) else: @@ -438,12 +464,13 @@ def track_estimate_points( project=project, workspace=project.workspace, comment=f"updated the estimate point to {requested_data.get('estimate_point')}", + epoch=epoch, ) ) def track_archive_at( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): if requested_data.get("archived_at") is None: issue_activities.append( @@ -457,6 +484,7 @@ def track_archive_at( field="archived_at", old_value="archive", new_value="restore", + epoch=epoch, ) ) else: @@ -471,12 +499,13 @@ def track_archive_at( field="archived_at", old_value=None, new_value="archive", + epoch=epoch, ) ) def track_closed_to( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): if requested_data.get("closed_to") is not None: updated_state = State.objects.get( @@ -496,12 +525,13 @@ def track_closed_to( comment=f"Plane updated the state to {updated_state.name}", old_identifier=None, new_identifier=updated_state.id, + epoch=epoch, ) ) def update_issue_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): ISSUE_ACTIVITY_MAPPER = { "name": track_name, @@ -528,11 +558,12 @@ def update_issue_activity( project, actor, issue_activities, + epoch ) def delete_issue_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): issue_activities.append( IssueActivity( @@ -542,12 +573,13 @@ def delete_issue_activity( verb="deleted", actor=actor, field="issue", + epoch=epoch, ) ) def create_comment_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): requested_data = json.loads(requested_data) if requested_data is not None else None current_instance = ( @@ -566,12 +598,13 @@ def create_comment_activity( new_value=requested_data.get("comment_html", ""), new_identifier=requested_data.get("id", None), issue_comment_id=requested_data.get("id", None), + epoch=epoch, ) ) def update_comment_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): requested_data = json.loads(requested_data) if requested_data is not None else None current_instance = ( @@ -593,12 +626,13 @@ def update_comment_activity( new_value=requested_data.get("comment_html", ""), new_identifier=current_instance.get("id", None), issue_comment_id=current_instance.get("id", None), + epoch=epoch, ) ) def delete_comment_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): issue_activities.append( IssueActivity( @@ -609,12 +643,13 @@ def delete_comment_activity( verb="deleted", actor=actor, field="comment", + epoch=epoch, ) ) def create_cycle_issue_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): requested_data = json.loads(requested_data) if requested_data is not None else None current_instance = ( @@ -646,6 +681,7 @@ def create_cycle_issue_activity( comment=f"updated cycle from {old_cycle.name} to {new_cycle.name}", old_identifier=old_cycle.id, new_identifier=new_cycle.id, + epoch=epoch, ) ) @@ -666,12 +702,13 @@ def create_cycle_issue_activity( workspace=project.workspace, comment=f"added cycle {cycle.name}", new_identifier=cycle.id, + epoch=epoch, ) ) def delete_cycle_issue_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): requested_data = json.loads(requested_data) if requested_data is not None else None current_instance = ( @@ -695,12 +732,13 @@ def delete_cycle_issue_activity( workspace=project.workspace, comment=f"removed this issue from {cycle.name if cycle is not None else None}", old_identifier=cycle.id if cycle is not None else None, + epoch=epoch, ) ) def create_module_issue_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): requested_data = json.loads(requested_data) if requested_data is not None else None current_instance = ( @@ -732,6 +770,7 @@ def create_module_issue_activity( comment=f"updated module from {old_module.name} to {new_module.name}", old_identifier=old_module.id, new_identifier=new_module.id, + epoch=epoch, ) ) @@ -751,12 +790,13 @@ def create_module_issue_activity( workspace=project.workspace, comment=f"added module {module.name}", new_identifier=module.id, + epoch=epoch, ) ) def delete_module_issue_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): requested_data = json.loads(requested_data) if requested_data is not None else None current_instance = ( @@ -780,12 +820,13 @@ def delete_module_issue_activity( workspace=project.workspace, comment=f"removed this issue from {module.name if module is not None else None}", old_identifier=module.id if module is not None else None, + epoch=epoch, ) ) def create_link_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): requested_data = json.loads(requested_data) if requested_data is not None else None current_instance = ( @@ -803,12 +844,13 @@ def create_link_activity( field="link", new_value=requested_data.get("url", ""), new_identifier=requested_data.get("id", None), + epoch=epoch, ) ) def update_link_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): requested_data = json.loads(requested_data) if requested_data is not None else None current_instance = ( @@ -829,12 +871,13 @@ def update_link_activity( old_identifier=current_instance.get("id"), new_value=requested_data.get("url", ""), new_identifier=current_instance.get("id", None), + epoch=epoch, ) ) def delete_link_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): current_instance = ( @@ -851,13 +894,14 @@ def delete_link_activity( actor=actor, field="link", old_value=current_instance.get("url", ""), - new_value="" + new_value="", + epoch=epoch, ) ) def create_attachment_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): requested_data = json.loads(requested_data) if requested_data is not None else None current_instance = ( @@ -875,12 +919,13 @@ def create_attachment_activity( field="attachment", new_value=current_instance.get("asset", ""), new_identifier=current_instance.get("id", None), + epoch=epoch, ) ) def delete_attachment_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): issue_activities.append( IssueActivity( @@ -891,11 +936,12 @@ def delete_attachment_activity( verb="deleted", actor=actor, field="attachment", + epoch=epoch, ) ) def create_issue_reaction_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): requested_data = json.loads(requested_data) if requested_data is not None else None if requested_data and requested_data.get("reaction") is not None: @@ -914,12 +960,13 @@ def create_issue_reaction_activity( comment="added the reaction", old_identifier=None, new_identifier=issue_reaction, + epoch=epoch, ) ) def delete_issue_reaction_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): current_instance = ( json.loads(current_instance) if current_instance is not None else None @@ -938,12 +985,13 @@ def delete_issue_reaction_activity( comment="removed the reaction", old_identifier=current_instance.get("identifier"), new_identifier=None, + epoch=epoch, ) ) def create_comment_reaction_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): requested_data = json.loads(requested_data) if requested_data is not None else None if requested_data and requested_data.get("reaction") is not None: @@ -963,12 +1011,13 @@ def create_comment_reaction_activity( comment="added the reaction", old_identifier=None, new_identifier=comment_reaction_id, + epoch=epoch, ) ) def delete_comment_reaction_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): current_instance = ( json.loads(current_instance) if current_instance is not None else None @@ -989,12 +1038,13 @@ def delete_comment_reaction_activity( comment="removed the reaction", old_identifier=current_instance.get("identifier"), new_identifier=None, + epoch=epoch, ) ) def create_issue_vote_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): requested_data = json.loads(requested_data) if requested_data is not None else None if requested_data and requested_data.get("vote") is not None: @@ -1011,12 +1061,13 @@ def create_issue_vote_activity( comment="added the vote", old_identifier=None, new_identifier=None, + epoch=epoch, ) ) def delete_issue_vote_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): current_instance = ( json.loads(current_instance) if current_instance is not None else None @@ -1035,12 +1086,13 @@ def delete_issue_vote_activity( comment="removed the vote", old_identifier=current_instance.get("identifier"), new_identifier=None, + epoch=epoch, ) ) def create_issue_relation_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): requested_data = json.loads(requested_data) if requested_data is not None else None current_instance = ( @@ -1061,12 +1113,13 @@ def create_issue_relation_activity( workspace=project.workspace, comment=f'added {issue_relation.get("relation_type")} relation', old_identifier=issue_relation.get("issue"), + epoch=epoch, ) ) def delete_issue_relation_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): requested_data = json.loads(requested_data) if requested_data is not None else None current_instance = ( @@ -1086,12 +1139,13 @@ def delete_issue_relation_activity( workspace=project.workspace, comment=f'deleted the {current_instance.get("relation_type")} relation', old_identifier=current_instance.get("issue"), + epoch=epoch, ) ) def create_draft_issue_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): issue_activities.append( IssueActivity( @@ -1102,12 +1156,13 @@ def create_draft_issue_activity( field="draft", verb="created", actor=actor, + epoch=epoch, ) ) def update_draft_issue_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): requested_data = json.loads(requested_data) if requested_data is not None else None current_instance = ( @@ -1122,6 +1177,7 @@ def update_draft_issue_activity( comment=f"created the issue", verb="updated", actor=actor, + epoch=epoch, ) ) else: @@ -1134,13 +1190,14 @@ def update_draft_issue_activity( field="draft", verb="updated", actor=actor, + epoch=epoch, ) ) def delete_draft_issue_activity( - requested_data, current_instance, issue_id, project, actor, issue_activities + requested_data, current_instance, issue_id, project, actor, issue_activities, epoch ): issue_activities.append( IssueActivity( @@ -1150,6 +1207,7 @@ def delete_draft_issue_activity( field="draft", verb="deleted", actor=actor, + epoch=epoch, ) ) @@ -1162,6 +1220,7 @@ def issue_activity( issue_id, actor_id, project_id, + epoch, subscriber=True, ): try: @@ -1238,6 +1297,7 @@ def issue_activity( project, actor, issue_activities, + epoch, ) # Save all the values to database diff --git a/apiserver/plane/bgtasks/issue_automation_task.py b/apiserver/plane/bgtasks/issue_automation_task.py index 645772c94..f7b06c625 100644 --- a/apiserver/plane/bgtasks/issue_automation_task.py +++ b/apiserver/plane/bgtasks/issue_automation_task.py @@ -77,6 +77,7 @@ def archive_old_issues(): project_id=project_id, current_instance=None, subscriber=False, + epoch = int(timezone.now().timestamp()) ) for issue in updated_issues ] @@ -148,6 +149,7 @@ def close_old_issues(): project_id=project_id, current_instance=None, subscriber=False, + epoch = int(timezone.now().timestamp()) ) for issue in updated_issues ] diff --git a/apiserver/plane/db/migrations/0045_issueactivity_epoch_alter_analyticview_created_by_and_more.py b/apiserver/plane/db/migrations/0045_issueactivity_epoch_alter_analyticview_created_by_and_more.py new file mode 100644 index 000000000..0d2cca641 --- /dev/null +++ b/apiserver/plane/db/migrations/0045_issueactivity_epoch_alter_analyticview_created_by_and_more.py @@ -0,0 +1,27 @@ +# Generated by Django 4.2.3 on 2023-09-14 06:49 + +from django.db import migrations, models + +def update_epoch(apps, schema_editor): + IssueActivity = apps.get_model('db', 'IssueActivity') + updated_issue_activity = [] + for obj in IssueActivity.objects.all(): + obj.epoch = int(obj.created_at.timestamp()) + updated_issue_activity.append(obj) + IssueActivity.objects.bulk_update(updated_issue_activity, ["epoch"], batch_size=100) + + +class Migration(migrations.Migration): + + dependencies = [ + ('db', '0044_auto_20230913_0709'), + ] + + operations = [ + migrations.AddField( + model_name='issueactivity', + name='epoch', + field=models.FloatField(null=True), + ), + migrations.RunPython(update_epoch), + ] diff --git a/apiserver/plane/db/models/issue.py b/apiserver/plane/db/models/issue.py index 65f1bc965..3ba054d49 100644 --- a/apiserver/plane/db/models/issue.py +++ b/apiserver/plane/db/models/issue.py @@ -309,6 +309,7 @@ class IssueActivity(ProjectBaseModel): ) old_identifier = models.UUIDField(null=True) new_identifier = models.UUIDField(null=True) + epoch = models.FloatField(null=True) class Meta: verbose_name = "Issue Activity"