diff --git a/apiserver/plane/app/serializers/__init__.py b/apiserver/plane/app/serializers/__init__.py
index 83981ab53c6..618a9ec20f1 100644
--- a/apiserver/plane/app/serializers/__init__.py
+++ b/apiserver/plane/app/serializers/__init__.py
@@ -92,6 +92,7 @@
SubPageSerializer,
PageDetailSerializer,
PageVersionSerializer,
+ PageVersionDetailSerializer,
)
from .estimate import (
diff --git a/apiserver/plane/app/serializers/page.py b/apiserver/plane/app/serializers/page.py
index c754bd431cc..e7f273d408a 100644
--- a/apiserver/plane/app/serializers/page.py
+++ b/apiserver/plane/app/serializers/page.py
@@ -167,7 +167,40 @@ class Meta:
class PageVersionSerializer(BaseSerializer):
class Meta:
model = PageVersion
- fields = "__all__"
+ fields = [
+ "id",
+ "workspace",
+ "page",
+ "last_saved_at",
+ "owned_by",
+ "created_at",
+ "updated_at",
+ "created_by",
+ "updated_by",
+ ]
+ read_only_fields = [
+ "workspace",
+ "page",
+ ]
+
+
+class PageVersionDetailSerializer(BaseSerializer):
+ class Meta:
+ model = PageVersion
+ fields = [
+ "id",
+ "workspace",
+ "page",
+ "last_saved_at",
+ "description_binary",
+ "description_html",
+ "description_json",
+ "owned_by",
+ "created_at",
+ "updated_at",
+ "created_by",
+ "updated_by",
+ ]
read_only_fields = [
"workspace",
"page",
diff --git a/apiserver/plane/app/views/page/version.py b/apiserver/plane/app/views/page/version.py
index 70f6bd978f4..995a0626362 100644
--- a/apiserver/plane/app/views/page/version.py
+++ b/apiserver/plane/app/views/page/version.py
@@ -5,16 +5,18 @@
# Module imports
from plane.db.models import PageVersion
from ..base import BaseAPIView
-from plane.app.permissions import ProjectEntityPermission
-from plane.app.serializers import PageVersionSerializer
+from plane.app.serializers import (
+ PageVersionSerializer,
+ PageVersionDetailSerializer,
+)
+from plane.app.permissions import allow_permission, ROLE
class PageVersionEndpoint(BaseAPIView):
- permission_classes = [
- ProjectEntityPermission,
- ]
-
+ @allow_permission(
+ allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.VIEWER, ROLE.GUEST]
+ )
def get(self, request, slug, project_id, page_id, pk=None):
# Check if pk is provided
if pk:
@@ -25,7 +27,7 @@ def get(self, request, slug, project_id, page_id, pk=None):
pk=pk,
)
# Serialize the page version
- serializer = PageVersionSerializer(page_version)
+ serializer = PageVersionDetailSerializer(page_version)
return Response(serializer.data, status=status.HTTP_200_OK)
# Return all page versions
page_versions = PageVersion.objects.filter(
diff --git a/packages/editor/src/core/hooks/use-editor.ts b/packages/editor/src/core/hooks/use-editor.ts
index f9e8fdd609f..523c4be0fa1 100644
--- a/packages/editor/src/core/hooks/use-editor.ts
+++ b/packages/editor/src/core/hooks/use-editor.ts
@@ -126,8 +126,8 @@ export const useEditor = (props: CustomEditorProps) => {
useImperativeHandle(
forwardedRef,
() => ({
- clearEditor: () => {
- editorRef.current?.commands.clearContent();
+ clearEditor: (emitUpdate = false) => {
+ editorRef.current?.commands.clearContent(emitUpdate);
},
setEditorValue: (content: string) => {
editorRef.current?.commands.setContent(content);
diff --git a/packages/editor/src/core/types/editor.ts b/packages/editor/src/core/types/editor.ts
index ac804b9b14f..b26fac38445 100644
--- a/packages/editor/src/core/types/editor.ts
+++ b/packages/editor/src/core/types/editor.ts
@@ -6,7 +6,7 @@ import { IMentionHighlight, IMentionSuggestion, TDisplayConfig, TEditorCommands,
export type EditorReadOnlyRefApi = {
getMarkDown: () => string;
getHTML: () => string;
- clearEditor: () => void;
+ clearEditor: (emitUpdate?: boolean) => void;
setEditorValue: (content: string) => void;
scrollSummary: (marking: IMarking) => void;
};
diff --git a/packages/types/src/pages.d.ts b/packages/types/src/pages.d.ts
index ea9b8b8ea5b..a78ff30568b 100644
--- a/packages/types/src/pages.d.ts
+++ b/packages/types/src/pages.d.ts
@@ -48,3 +48,19 @@ export type TPageFilters = {
};
export type TPageEmbedType = "mention" | "issue";
+
+export type TPageVersion = {
+ created_at: string;
+ created_by: string;
+ deleted_at: string | null;
+ description_binary?: string | null;
+ description_html?: string | null;
+ description_json?: object;
+ id: string;
+ last_saved_at: string;
+ owned_by: string;
+ page: string;
+ updated_at: string;
+ updated_by: string;
+ workspace: string;
+}
\ No newline at end of file
diff --git a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx
index 8c96f2bcf80..e9debb2bcf4 100644
--- a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx
+++ b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx
@@ -64,7 +64,7 @@ const PageDetailsPage = observer(() => {
<>
-
+
diff --git a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/header.tsx b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/header.tsx
index c04c6d94484..4cfe11d353d 100644
--- a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/header.tsx
+++ b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/header.tsx
@@ -2,7 +2,7 @@
import { useState } from "react";
import { observer } from "mobx-react";
-import { useParams } from "next/navigation";
+import { useParams, useSearchParams } from "next/navigation";
import { FileText } from "lucide-react";
// types
import { TLogoProps } from "@plane/types";
@@ -25,6 +25,7 @@ export interface IPagesHeaderProps {
export const PageDetailsHeader = observer(() => {
// router
const { workspaceSlug, pageId } = useParams();
+ const searchParams = useSearchParams();
// state
const [isOpen, setIsOpen] = useState(false);
// store hooks
@@ -55,6 +56,8 @@ export const PageDetailsHeader = observer(() => {
}
};
+ const isVersionHistoryOverlayActive = !!searchParams.get("version");
+
return (
@@ -157,7 +160,7 @@ export const PageDetailsHeader = observer(() => {
- {isContentEditable && (
+ {isContentEditable && !isVersionHistoryOverlayActive && (