diff --git a/apps/api/plane/app/views/page/base.py b/apps/api/plane/app/views/page/base.py index d3ad49b5fda..820f982f6bd 100644 --- a/apps/api/plane/app/views/page/base.py +++ b/apps/api/plane/app/views/page/base.py @@ -46,7 +46,7 @@ # Local imports from ..base import BaseAPIView, BaseViewSet from plane.bgtasks.page_transaction_task import page_transaction -from plane.bgtasks.page_version_task import page_version +from plane.bgtasks.page_version_task import track_page_version from plane.bgtasks.recent_visited_task import recent_visited_task from plane.bgtasks.copy_s3_object import copy_s3_objects_of_description_and_assets from plane.app.permissions import ProjectPagePermission @@ -541,26 +541,28 @@ def partial_update(self, request, slug, project_id, page_id): status=status.HTTP_400_BAD_REQUEST, ) + # Store the old description_html before saving (needed for both tasks) + old_description_html = page.description_html + # Serialize the existing instance - existing_instance = json.dumps({"description_html": page.description_html}, cls=DjangoJSONEncoder) + existing_instance = json.dumps({"description_html": old_description_html}, cls=DjangoJSONEncoder) # Use serializer for validation and update serializer = PageBinaryUpdateSerializer(page, data=request.data, partial=True) if serializer.is_valid(): + serializer.save() + # Capture the page transaction if request.data.get("description_html"): page_transaction.delay( new_description_html=request.data.get("description_html", "
"), - old_description_html=page.description_html, + old_description_html=old_description_html, page_id=page_id, ) - # Update the page using serializer - updated_page = serializer.save() - # Run background tasks - page_version.delay( - page_id=updated_page.id, + track_page_version.delay( + page_id=page_id, existing_instance=existing_instance, user_id=request.user.id, ) diff --git a/apps/api/plane/bgtasks/page_version_task.py b/apps/api/plane/bgtasks/page_version_task.py index 4de2387becf..dd825987484 100644 --- a/apps/api/plane/bgtasks/page_version_task.py +++ b/apps/api/plane/bgtasks/page_version_task.py @@ -1,37 +1,70 @@ # Python imports import json + # Third party imports from celery import shared_task +# Django imports +from django.utils import timezone + # Module imports from plane.db.models import Page, PageVersion from plane.utils.exception_logger import log_exception +PAGE_VERSION_TASK_TIMEOUT = 600 @shared_task -def page_version(page_id, existing_instance, user_id): +def track_page_version(page_id, existing_instance, user_id): try: # Get the page page = Page.objects.get(id=page_id) # Get the current instance current_instance = json.loads(existing_instance) if existing_instance is not None else {} + sub_pages = {} + # Create a version if description_html is updated if current_instance.get("description_html") != page.description_html: - # Create a new page version - PageVersion.objects.create( - page_id=page_id, - workspace_id=page.workspace_id, - description_html=page.description_html, - description_binary=page.description_binary, - owned_by_id=user_id, - last_saved_at=page.updated_at, - description_json=page.description, - description_stripped=page.description_stripped, - ) + # Fetch the latest page version + page_version = PageVersion.objects.filter(page_id=page_id).order_by("-last_saved_at").first() + + # Get the latest page version if it exists and is owned by the user + if ( + page_version + and str(page_version.owned_by_id) == str(user_id) + and (timezone.now() - page_version.last_saved_at).total_seconds() <= PAGE_VERSION_TASK_TIMEOUT + ): + page_version.description_html = page.description_html + page_version.description_binary = page.description_binary + page_version.description_json = page.description + page_version.description_stripped = page.description_stripped + page_version.sub_pages_data = sub_pages + page_version.save( + update_fields=[ + "description_html", + "description_binary", + "description_json", + "description_stripped", + "sub_pages_data", + "updated_at" + ] + ) + else: + # Create a new page version + PageVersion.objects.create( + page_id=page_id, + workspace_id=page.workspace_id, + description_json=page.description, + description_html=page.description_html, + description_binary=page.description_binary, + description_stripped=page.description_stripped, + owned_by_id=user_id, + last_saved_at=timezone.now(), + sub_pages_data=sub_pages, + ) # If page versions are greater than 20 delete the oldest one if PageVersion.objects.filter(page_id=page_id).count() > 20: # Delete the old page version