mirror of
https://github.com/makeplane/plane
synced 2025-08-07 19:59:33 +00:00
Compare commits
3 Commits
chore-remo
...
feat/issue
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
afdb3214c5 | ||
|
|
3b7fbde6b9 | ||
|
|
eb9d84a65a |
3
packages/types/src/pages.d.ts
vendored
3
packages/types/src/pages.d.ts
vendored
@@ -49,7 +49,7 @@ export type TPageFilters = {
|
||||
|
||||
export type TPageEmbedType = "mention" | "issue";
|
||||
|
||||
export type TPageVersion = {
|
||||
export type TEditorVersion = {
|
||||
created_at: string;
|
||||
created_by: string;
|
||||
deleted_at: string | null;
|
||||
@@ -59,7 +59,6 @@ export type TPageVersion = {
|
||||
id: string;
|
||||
last_saved_at: string;
|
||||
owned_by: string;
|
||||
page: string;
|
||||
updated_at: string;
|
||||
updated_by: string;
|
||||
workspace: string;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from "./lite-text-editor";
|
||||
export * from "./pdf";
|
||||
export * from "./rich-text-editor";
|
||||
export * from "./version-history";
|
||||
|
||||
11
web/core/components/editor/version-history/editors/index.ts
Normal file
11
web/core/components/editor/version-history/editors/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { TEditorVersion } from "@plane/types";
|
||||
|
||||
export type TVersionEditorProps = {
|
||||
activeVersion: string | null;
|
||||
currentVersionDescription: string | null;
|
||||
isCurrentVersionActive: boolean;
|
||||
versionDetails: TEditorVersion | undefined;
|
||||
};
|
||||
|
||||
export * from "./issue-version-editor";
|
||||
export * from "./page-version-editor";
|
||||
@@ -0,0 +1,70 @@
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
// plane ui
|
||||
import { Loader } from "@plane/ui";
|
||||
// components
|
||||
import { RichTextReadOnlyEditor } from "@/components/editor";
|
||||
// local types
|
||||
import { TVersionEditorProps } from ".";
|
||||
|
||||
export const IssueVersionEditor: React.FC<TVersionEditorProps> = observer((props) => {
|
||||
const { activeVersion, currentVersionDescription, isCurrentVersionActive, versionDetails } = props;
|
||||
// params
|
||||
const { workspaceSlug, projectId } = useParams();
|
||||
|
||||
if (!isCurrentVersionActive && !versionDetails)
|
||||
return (
|
||||
<div className="size-full px-5">
|
||||
<Loader className="relative space-y-4">
|
||||
<Loader.Item width="50%" height="36px" />
|
||||
<div className="space-y-2">
|
||||
<div className="py-2">
|
||||
<Loader.Item width="100%" height="36px" />
|
||||
</div>
|
||||
<Loader.Item width="80%" height="22px" />
|
||||
<div className="relative flex items-center gap-2">
|
||||
<Loader.Item width="30px" height="30px" />
|
||||
<Loader.Item width="30%" height="22px" />
|
||||
</div>
|
||||
<div className="py-2">
|
||||
<Loader.Item width="60%" height="36px" />
|
||||
</div>
|
||||
<Loader.Item width="70%" height="22px" />
|
||||
<Loader.Item width="30%" height="22px" />
|
||||
<div className="relative flex items-center gap-2">
|
||||
<Loader.Item width="30px" height="30px" />
|
||||
<Loader.Item width="30%" height="22px" />
|
||||
</div>
|
||||
<div className="py-2">
|
||||
<Loader.Item width="50%" height="30px" />
|
||||
</div>
|
||||
<Loader.Item width="100%" height="22px" />
|
||||
<div className="py-2">
|
||||
<Loader.Item width="30%" height="30px" />
|
||||
</div>
|
||||
<Loader.Item width="30%" height="22px" />
|
||||
<div className="relative flex items-center gap-2">
|
||||
<div className="py-2">
|
||||
<Loader.Item width="30px" height="30px" />
|
||||
</div>
|
||||
<Loader.Item width="30%" height="22px" />
|
||||
</div>
|
||||
</div>
|
||||
</Loader>
|
||||
</div>
|
||||
);
|
||||
|
||||
const description = isCurrentVersionActive ? currentVersionDescription : versionDetails?.description_html;
|
||||
if (description === undefined || description?.trim() === "") return null;
|
||||
|
||||
return (
|
||||
<RichTextReadOnlyEditor
|
||||
id={activeVersion ?? ""}
|
||||
initialValue={description ?? "<p></p>"}
|
||||
containerClassName="p-0 pb-64 border-none"
|
||||
editorClassName="pl-10"
|
||||
workspaceSlug={workspaceSlug?.toString() ?? ""}
|
||||
projectId={projectId?.toString() ?? ""}
|
||||
/>
|
||||
);
|
||||
});
|
||||
@@ -1,27 +1,21 @@
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
// plane editor
|
||||
import { DocumentReadOnlyEditorWithRef, TDisplayConfig } from "@plane/editor";
|
||||
import { DocumentReadOnlyEditorWithRef } from "@plane/editor";
|
||||
// plane types
|
||||
import { IUserLite, TPageVersion } from "@plane/types";
|
||||
import { IUserLite } from "@plane/types";
|
||||
// plane ui
|
||||
import { Loader } from "@plane/ui";
|
||||
// helpers
|
||||
import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper";
|
||||
// hooks
|
||||
import { useMember, useMention, useUser } from "@/hooks/store";
|
||||
import { usePageFilters } from "@/hooks/use-page-filters";
|
||||
// plane web hooks
|
||||
import { useIssueEmbed } from "@/plane-web/hooks/use-issue-embed";
|
||||
// local types
|
||||
import { TVersionEditorProps } from ".";
|
||||
|
||||
export type TVersionEditorProps = {
|
||||
activeVersion: string | null;
|
||||
currentVersionDescription: string | null;
|
||||
isCurrentVersionActive: boolean;
|
||||
versionDetails: TPageVersion | undefined;
|
||||
};
|
||||
|
||||
export const PagesVersionEditor: React.FC<TVersionEditorProps> = observer((props) => {
|
||||
export const PageVersionEditor: React.FC<TVersionEditorProps> = observer((props) => {
|
||||
const { activeVersion, currentVersionDescription, isCurrentVersionActive, versionDetails } = props;
|
||||
// params
|
||||
const { workspaceSlug, projectId } = useParams();
|
||||
@@ -43,13 +37,6 @@ export const PagesVersionEditor: React.FC<TVersionEditorProps> = observer((props
|
||||
members: projectMemberDetails,
|
||||
user: currentUser ?? undefined,
|
||||
});
|
||||
// page filters
|
||||
const { fontSize, fontStyle } = usePageFilters();
|
||||
|
||||
const displayConfig: TDisplayConfig = {
|
||||
fontSize,
|
||||
fontStyle,
|
||||
};
|
||||
|
||||
if (!isCurrentVersionActive && !versionDetails)
|
||||
return (
|
||||
@@ -101,7 +88,6 @@ export const PagesVersionEditor: React.FC<TVersionEditorProps> = observer((props
|
||||
id={activeVersion ?? ""}
|
||||
initialValue={description ?? "<p></p>"}
|
||||
containerClassName="p-0 pb-64 border-none"
|
||||
displayConfig={displayConfig}
|
||||
editorClassName="pl-10"
|
||||
fileHandler={getReadOnlyEditorFileHandlers({
|
||||
projectId: projectId?.toString() ?? "",
|
||||
@@ -1,4 +1,4 @@
|
||||
export * from "./editor";
|
||||
export * from "./editors";
|
||||
export * from "./main-content";
|
||||
export * from "./root";
|
||||
export * from "./sidebar-list-item";
|
||||
@@ -3,34 +3,34 @@ import { observer } from "mobx-react";
|
||||
import useSWR from "swr";
|
||||
import { TriangleAlert } from "lucide-react";
|
||||
// plane types
|
||||
import { TPageVersion } from "@plane/types";
|
||||
import { TEditorVersion } from "@plane/types";
|
||||
// plane ui
|
||||
import { Button, setToast, TOAST_TYPE } from "@plane/ui";
|
||||
// components
|
||||
import { TVersionEditorProps } from "@/components/pages";
|
||||
// helpers
|
||||
import { renderFormattedDate, renderFormattedTime } from "@/helpers/date-time.helper";
|
||||
// local types
|
||||
import { TVersionEditorProps } from ".";
|
||||
|
||||
type Props = {
|
||||
activeVersion: string | null;
|
||||
currentVersionDescription: string | null;
|
||||
editorComponent: React.FC<TVersionEditorProps>;
|
||||
fetchVersionDetails: (pageId: string, versionId: string) => Promise<TPageVersion | undefined>;
|
||||
entityId: string;
|
||||
fetchVersionDetails: (entityId: string, versionId: string) => Promise<TEditorVersion | undefined>;
|
||||
handleClose: () => void;
|
||||
handleRestore: (descriptionHTML: string) => Promise<void>;
|
||||
pageId: string;
|
||||
restoreEnabled: boolean;
|
||||
};
|
||||
|
||||
export const PageVersionsMainContent: React.FC<Props> = observer((props) => {
|
||||
export const EditorVersionHistoryMainContent: React.FC<Props> = observer((props) => {
|
||||
const {
|
||||
activeVersion,
|
||||
currentVersionDescription,
|
||||
editorComponent,
|
||||
entityId,
|
||||
fetchVersionDetails,
|
||||
handleClose,
|
||||
handleRestore,
|
||||
pageId,
|
||||
restoreEnabled,
|
||||
} = props;
|
||||
// states
|
||||
@@ -42,8 +42,8 @@ export const PageVersionsMainContent: React.FC<Props> = observer((props) => {
|
||||
error: versionDetailsError,
|
||||
mutate: mutateVersionDetails,
|
||||
} = useSWR(
|
||||
pageId && activeVersion && activeVersion !== "current" ? `PAGE_VERSION_${activeVersion}` : null,
|
||||
pageId && activeVersion && activeVersion !== "current" ? () => fetchVersionDetails(pageId, activeVersion) : null
|
||||
entityId && activeVersion && activeVersion !== "current" ? `EDITOR_VERSION_${activeVersion}` : null,
|
||||
entityId && activeVersion && activeVersion !== "current" ? () => fetchVersionDetails(entityId, activeVersion) : null
|
||||
);
|
||||
|
||||
const isCurrentVersionActive = activeVersion === "current";
|
||||
@@ -55,14 +55,14 @@ export const PageVersionsMainContent: React.FC<Props> = observer((props) => {
|
||||
.then(() => {
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Page version restored.",
|
||||
title: "Version restored.",
|
||||
});
|
||||
handleClose();
|
||||
})
|
||||
.catch(() =>
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Failed to restore page version.",
|
||||
title: "Failed to restore version.",
|
||||
})
|
||||
)
|
||||
.finally(() => setIsRestoring(false));
|
||||
@@ -1,35 +1,35 @@
|
||||
import { observer } from "mobx-react";
|
||||
// plane types
|
||||
import { TPageVersion } from "@plane/types";
|
||||
// components
|
||||
import { PageVersionsMainContent, PageVersionsSidebarRoot, TVersionEditorProps } from "@/components/pages";
|
||||
import { TEditorVersion } from "@plane/types";
|
||||
// helpers
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
// local components
|
||||
import { EditorVersionHistoryMainContent, EditorVersionHistorySidebarRoot, TVersionEditorProps } from ".";
|
||||
|
||||
type Props = {
|
||||
activeVersion: string | null;
|
||||
currentVersionDescription: string | null;
|
||||
editorComponent: React.FC<TVersionEditorProps>;
|
||||
fetchAllVersions: (pageId: string) => Promise<TPageVersion[] | undefined>;
|
||||
fetchVersionDetails: (pageId: string, versionId: string) => Promise<TPageVersion | undefined>;
|
||||
entityId: string;
|
||||
fetchAllVersions: (entityId: string) => Promise<TEditorVersion[] | undefined>;
|
||||
fetchVersionDetails: (entityId: string, versionId: string) => Promise<TEditorVersion | undefined>;
|
||||
handleRestore: (descriptionHTML: string) => Promise<void>;
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
pageId: string;
|
||||
restoreEnabled: boolean;
|
||||
};
|
||||
|
||||
export const PageVersionsOverlay: React.FC<Props> = observer((props) => {
|
||||
export const EditorVersionHistoryOverlay: React.FC<Props> = observer((props) => {
|
||||
const {
|
||||
activeVersion,
|
||||
currentVersionDescription,
|
||||
editorComponent,
|
||||
entityId,
|
||||
fetchAllVersions,
|
||||
fetchVersionDetails,
|
||||
handleRestore,
|
||||
isOpen,
|
||||
onClose,
|
||||
pageId,
|
||||
restoreEnabled,
|
||||
} = props;
|
||||
|
||||
@@ -46,22 +46,22 @@ export const PageVersionsOverlay: React.FC<Props> = observer((props) => {
|
||||
}
|
||||
)}
|
||||
>
|
||||
<PageVersionsMainContent
|
||||
<EditorVersionHistoryMainContent
|
||||
activeVersion={activeVersion}
|
||||
currentVersionDescription={currentVersionDescription}
|
||||
editorComponent={editorComponent}
|
||||
entityId={entityId}
|
||||
fetchVersionDetails={fetchVersionDetails}
|
||||
handleClose={handleClose}
|
||||
handleRestore={handleRestore}
|
||||
pageId={pageId}
|
||||
restoreEnabled={restoreEnabled}
|
||||
/>
|
||||
<PageVersionsSidebarRoot
|
||||
<EditorVersionHistorySidebarRoot
|
||||
activeVersion={activeVersion}
|
||||
entityId={entityId}
|
||||
fetchAllVersions={fetchAllVersions}
|
||||
handleClose={handleClose}
|
||||
isOpen={isOpen}
|
||||
pageId={pageId}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@@ -1,7 +1,7 @@
|
||||
import { observer } from "mobx-react";
|
||||
import Link from "next/link";
|
||||
// plane types
|
||||
import { TPageVersion } from "@plane/types";
|
||||
import { TEditorVersion } from "@plane/types";
|
||||
// plane ui
|
||||
import { Avatar } from "@plane/ui";
|
||||
// helpers
|
||||
@@ -14,10 +14,10 @@ import { useMember } from "@/hooks/store";
|
||||
type Props = {
|
||||
href: string;
|
||||
isActive: boolean;
|
||||
version: TPageVersion;
|
||||
version: TEditorVersion;
|
||||
};
|
||||
|
||||
export const PlaneVersionsSidebarListItem: React.FC<Props> = observer((props) => {
|
||||
export const EditorVersionHistorySidebarListItem: React.FC<Props> = observer((props) => {
|
||||
const { href, isActive, version } = props;
|
||||
// store hooks
|
||||
const { getUserDetails } = useMember();
|
||||
@@ -3,25 +3,25 @@ import Link from "next/link";
|
||||
import useSWR from "swr";
|
||||
import { TriangleAlert } from "lucide-react";
|
||||
// plane types
|
||||
import { TPageVersion } from "@plane/types";
|
||||
import { TEditorVersion } from "@plane/types";
|
||||
// plane ui
|
||||
import { Button, Loader } from "@plane/ui";
|
||||
// components
|
||||
import { PlaneVersionsSidebarListItem } from "@/components/pages";
|
||||
// helpers
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
// hooks
|
||||
import { useQueryParams } from "@/hooks/use-query-params";
|
||||
// local components
|
||||
import { EditorVersionHistorySidebarListItem } from ".";
|
||||
|
||||
type Props = {
|
||||
activeVersion: string | null;
|
||||
fetchAllVersions: (pageId: string) => Promise<TPageVersion[] | undefined>;
|
||||
entityId: string;
|
||||
fetchAllVersions: (entityId: string) => Promise<TEditorVersion[] | undefined>;
|
||||
isOpen: boolean;
|
||||
pageId: string;
|
||||
};
|
||||
|
||||
export const PageVersionsSidebarList: React.FC<Props> = (props) => {
|
||||
const { activeVersion, fetchAllVersions, isOpen, pageId } = props;
|
||||
export const EditorVersionHistorySidebarList: React.FC<Props> = (props) => {
|
||||
const { activeVersion, entityId, fetchAllVersions, isOpen } = props;
|
||||
// states
|
||||
const [isRetrying, setIsRetrying] = useState(false);
|
||||
// update query params
|
||||
@@ -32,8 +32,8 @@ export const PageVersionsSidebarList: React.FC<Props> = (props) => {
|
||||
error: versionsListError,
|
||||
mutate: mutateVersionsList,
|
||||
} = useSWR(
|
||||
pageId && isOpen ? `PAGE_VERSIONS_LIST_${pageId}` : null,
|
||||
pageId && isOpen ? () => fetchAllVersions(pageId) : null
|
||||
entityId && isOpen ? `EDITOR_VERSIONS_LIST_${entityId}` : null,
|
||||
entityId && isOpen ? () => fetchAllVersions(entityId) : null
|
||||
);
|
||||
|
||||
const handleRetry = async () => {
|
||||
@@ -78,7 +78,7 @@ export const PageVersionsSidebarList: React.FC<Props> = (props) => {
|
||||
</div>
|
||||
) : versionsList ? (
|
||||
versionsList.map((version) => (
|
||||
<PlaneVersionsSidebarListItem
|
||||
<EditorVersionHistorySidebarListItem
|
||||
key={version.id}
|
||||
href={getVersionLink(version.id)}
|
||||
isActive={activeVersion === version.id}
|
||||
@@ -1,19 +1,19 @@
|
||||
import { X } from "lucide-react";
|
||||
// plane types
|
||||
import { TPageVersion } from "@plane/types";
|
||||
// components
|
||||
import { PageVersionsSidebarList } from "@/components/pages";
|
||||
import { TEditorVersion } from "@plane/types";
|
||||
// local components
|
||||
import { EditorVersionHistorySidebarList } from ".";
|
||||
|
||||
type Props = {
|
||||
activeVersion: string | null;
|
||||
fetchAllVersions: (pageId: string) => Promise<TPageVersion[] | undefined>;
|
||||
entityId: string;
|
||||
fetchAllVersions: (entityId: string) => Promise<TEditorVersion[] | undefined>;
|
||||
handleClose: () => void;
|
||||
isOpen: boolean;
|
||||
pageId: string;
|
||||
};
|
||||
|
||||
export const PageVersionsSidebarRoot: React.FC<Props> = (props) => {
|
||||
const { activeVersion, fetchAllVersions, handleClose, isOpen, pageId } = props;
|
||||
export const EditorVersionHistorySidebarRoot: React.FC<Props> = (props) => {
|
||||
const { activeVersion, entityId, fetchAllVersions, handleClose, isOpen } = props;
|
||||
|
||||
return (
|
||||
<div className="flex-shrink-0 py-4 border-l border-custom-border-200 flex flex-col">
|
||||
@@ -27,11 +27,11 @@ export const PageVersionsSidebarRoot: React.FC<Props> = (props) => {
|
||||
<X className="size-4" />
|
||||
</button>
|
||||
</div>
|
||||
<PageVersionsSidebarList
|
||||
<EditorVersionHistorySidebarList
|
||||
activeVersion={activeVersion}
|
||||
entityId={entityId}
|
||||
fetchAllVersions={fetchAllVersions}
|
||||
isOpen={isOpen}
|
||||
pageId={pageId}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@@ -4,6 +4,7 @@ export * from "./links";
|
||||
export * from "./parent";
|
||||
export * from "./reactions";
|
||||
export * from "./cycle-select";
|
||||
export * from "./issue-detail-quick-actions";
|
||||
export * from "./main-content";
|
||||
export * from "./module-select";
|
||||
export * from "./parent-select";
|
||||
@@ -11,4 +12,4 @@ export * from "./relation-select";
|
||||
export * from "./root";
|
||||
export * from "./sidebar";
|
||||
export * from "./subscription";
|
||||
export * from "./issue-detail-quick-actions";
|
||||
export * from "./version-history";
|
||||
|
||||
@@ -175,7 +175,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
},
|
||||
path: pathname,
|
||||
});
|
||||
} catch (error) {
|
||||
} catch {
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
@@ -204,7 +204,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
},
|
||||
path: pathname,
|
||||
});
|
||||
} catch (error) {
|
||||
} catch {
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
@@ -245,7 +245,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
},
|
||||
path: pathname,
|
||||
});
|
||||
} catch (error) {
|
||||
} catch {
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_UPDATED,
|
||||
payload: { state: "FAILED", element: "Issue detail page" },
|
||||
@@ -281,7 +281,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
},
|
||||
path: pathname,
|
||||
});
|
||||
} catch (error) {
|
||||
} catch {
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_UPDATED,
|
||||
payload: { id: issueId, state: "FAILED", element: "Issue detail page" },
|
||||
@@ -373,7 +373,6 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* peek overview */}
|
||||
<IssuePeekOverview />
|
||||
</>
|
||||
|
||||
82
web/core/components/issues/issue-detail/version-history.tsx
Normal file
82
web/core/components/issues/issue-detail/version-history.tsx
Normal file
@@ -0,0 +1,82 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useParams, useRouter, useSearchParams } from "next/navigation";
|
||||
// plane editor
|
||||
import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/editor";
|
||||
// components
|
||||
import { EditorVersionHistoryOverlay, IssueVersionEditor } from "@/components/editor";
|
||||
// hooks
|
||||
import { useQueryParams } from "@/hooks/use-query-params";
|
||||
// services
|
||||
import { IssueVersionService } from "@/services/issue";
|
||||
const issueVersionService = new IssueVersionService();
|
||||
|
||||
type Props = {
|
||||
disabled: boolean;
|
||||
editorRef: EditorRefApi;
|
||||
issueId: string;
|
||||
readOnlyEditorRef: EditorReadOnlyRefApi;
|
||||
};
|
||||
|
||||
export const IssueVersionHistory: React.FC<Props> = (props) => {
|
||||
const { disabled, editorRef, issueId, readOnlyEditorRef } = props;
|
||||
// states
|
||||
const [isVersionsOverlayOpen, setIsVersionsOverlayOpen] = useState(false);
|
||||
// search params
|
||||
const searchParams = useSearchParams();
|
||||
// params
|
||||
const { projectId, workspaceSlug } = useParams();
|
||||
// router
|
||||
const router = useRouter();
|
||||
// update query params
|
||||
const { updateQueryParams } = useQueryParams();
|
||||
|
||||
const version = searchParams.get("version");
|
||||
useEffect(() => {
|
||||
if (!version) {
|
||||
setIsVersionsOverlayOpen(false);
|
||||
return;
|
||||
}
|
||||
setIsVersionsOverlayOpen(true);
|
||||
}, [version]);
|
||||
|
||||
const handleCloseVersionsOverlay = () => {
|
||||
const updatedRoute = updateQueryParams({
|
||||
paramsToRemove: ["version"],
|
||||
});
|
||||
router.push(updatedRoute);
|
||||
};
|
||||
|
||||
const handleRestoreVersion = async (descriptionHTML: string) => {
|
||||
editorRef?.clearEditor();
|
||||
editorRef?.setEditorValue(descriptionHTML);
|
||||
};
|
||||
const currentVersionDescription = disabled ? readOnlyEditorRef?.getDocument().html : editorRef?.getDocument().html;
|
||||
|
||||
return (
|
||||
<EditorVersionHistoryOverlay
|
||||
activeVersion={version}
|
||||
currentVersionDescription={currentVersionDescription ?? null}
|
||||
editorComponent={IssueVersionEditor}
|
||||
entityId={issueId}
|
||||
fetchAllVersions={async (issueId) => {
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
return await issueVersionService.fetchAllVersions(workspaceSlug.toString(), projectId.toString(), issueId);
|
||||
}}
|
||||
fetchVersionDetails={async (issueId, versionId) => {
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
return await issueVersionService.fetchVersionById(
|
||||
workspaceSlug.toString(),
|
||||
projectId.toString(),
|
||||
issueId,
|
||||
versionId
|
||||
);
|
||||
}}
|
||||
handleRestore={handleRestoreVersion}
|
||||
isOpen={isVersionsOverlayOpen}
|
||||
onClose={handleCloseVersionsOverlay}
|
||||
restoreEnabled={!disabled}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -8,7 +8,8 @@ import { TPage } from "@plane/types";
|
||||
// ui
|
||||
import { setToast, TOAST_TYPE } from "@plane/ui";
|
||||
// components
|
||||
import { PageEditorHeaderRoot, PageEditorBody, PageVersionsOverlay, PagesVersionEditor } from "@/components/pages";
|
||||
import { EditorVersionHistoryOverlay, PageVersionEditor } from "@/components/editor";
|
||||
import { PageEditorHeaderRoot, PageEditorBody } from "@/components/pages";
|
||||
// hooks
|
||||
import { useProjectPages } from "@/hooks/store";
|
||||
import { useAppRouter } from "@/hooks/use-app-router";
|
||||
@@ -105,10 +106,11 @@ export const PageRoot = observer((props: TPageRootProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageVersionsOverlay
|
||||
<EditorVersionHistoryOverlay
|
||||
activeVersion={version}
|
||||
currentVersionDescription={currentVersionDescription ?? null}
|
||||
editorComponent={PagesVersionEditor}
|
||||
editorComponent={PageVersionEditor}
|
||||
entityId={page.id ?? ""}
|
||||
fetchAllVersions={async (pageId) => {
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
return await projectPageVersionService.fetchAllVersions(
|
||||
@@ -129,7 +131,6 @@ export const PageRoot = observer((props: TPageRootProps) => {
|
||||
handleRestore={handleRestoreVersion}
|
||||
isOpen={isVersionsOverlayOpen}
|
||||
onClose={handleCloseVersionsOverlay}
|
||||
pageId={page.id ?? ""}
|
||||
restoreEnabled={isContentEditable}
|
||||
/>
|
||||
<PageEditorHeaderRoot
|
||||
|
||||
@@ -7,4 +7,5 @@ export * from "./issue_attachment.service";
|
||||
export * from "./issue_activity.service";
|
||||
export * from "./issue_comment.service";
|
||||
export * from "./issue_relation.service";
|
||||
export * from "./issue_version.service";
|
||||
export * from "./workspace_draft.service";
|
||||
|
||||
33
web/core/services/issue/issue_version.service.ts
Normal file
33
web/core/services/issue/issue_version.service.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
// plane types
|
||||
import { TEditorVersion } from "@plane/types";
|
||||
// helpers
|
||||
import { API_BASE_URL } from "@/helpers/common.helper";
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class IssueVersionService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async fetchAllVersions(workspaceSlug: string, projectId: string, issueId: string): Promise<TEditorVersion[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/versions/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async fetchVersionById(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
versionId: string
|
||||
): Promise<TEditorVersion> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/versions/${versionId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// plane types
|
||||
import { TPageVersion } from "@plane/types";
|
||||
import { TEditorVersion } from "@plane/types";
|
||||
// helpers
|
||||
import { API_BASE_URL } from "@/helpers/common.helper";
|
||||
// services
|
||||
@@ -10,7 +10,7 @@ export class ProjectPageVersionService extends APIService {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async fetchAllVersions(workspaceSlug: string, projectId: string, pageId: string): Promise<TPageVersion[]> {
|
||||
async fetchAllVersions(workspaceSlug: string, projectId: string, pageId: string): Promise<TEditorVersion[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/versions/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
@@ -23,7 +23,7 @@ export class ProjectPageVersionService extends APIService {
|
||||
projectId: string,
|
||||
pageId: string,
|
||||
versionId: string
|
||||
): Promise<TPageVersion> {
|
||||
): Promise<TEditorVersion> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/versions/${versionId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
|
||||
Reference in New Issue
Block a user