diff --git a/packages/editor/document-editor/src/ui/components/editor-header.tsx b/packages/editor/document-editor/src/ui/components/editor-header.tsx index 3501785a7f..b70ce055db 100644 --- a/packages/editor/document-editor/src/ui/components/editor-header.tsx +++ b/packages/editor/document-editor/src/ui/components/editor-header.tsx @@ -76,7 +76,7 @@ export const EditorHeader = (props: IEditorHeader) => { /> )} - {!isLocked && !isArchived ? ( + {!isLocked && !isArchived && !readonly ? (
IssueWidget.configure({}); - interface IssueWidgetExtensionProps { issueEmbedConfig?: IIssueEmbedConfig; } diff --git a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/issue-widget-node.tsx b/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/issue-widget-node.tsx index 6c744927ad..c13637bd91 100644 --- a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/issue-widget-node.tsx +++ b/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/issue-widget-node.tsx @@ -34,7 +34,9 @@ export const IssueWidget = Node.create({ }, addNodeView() { - return ReactNodeViewRenderer((props: Object) => ); + return ReactNodeViewRenderer((props: Object) => ( + + )); }, parseHTML() { diff --git a/packages/editor/document-editor/src/ui/readonly/index.tsx b/packages/editor/document-editor/src/ui/readonly/index.tsx index 7c49ffa839..82179e3ef8 100644 --- a/packages/editor/document-editor/src/ui/readonly/index.tsx +++ b/packages/editor/document-editor/src/ui/readonly/index.tsx @@ -8,7 +8,8 @@ import { useEditorMarkings } from "src/hooks/use-editor-markings"; import { DocumentDetails } from "src/types/editor-types"; import { IPageArchiveConfig, IPageLockConfig, IDuplicationConfig } from "src/types/menu-actions"; import { getMenuOptions } from "src/utils/menu-options"; -import { IssueWidgetPlaceholder } from "../extensions/widgets/issue-embed-widget"; +import { IssueWidgetExtension } from "../extensions/widgets/issue-embed-widget"; +import { IEmbedConfig } from "../extensions/widgets/issue-embed-widget/types"; interface IDocumentReadOnlyEditor { value: string; @@ -28,6 +29,7 @@ interface IDocumentReadOnlyEditor { message: string; type: "success" | "error" | "warning" | "info"; }) => void; + embedConfig?: IEmbedConfig; } interface DocumentReadOnlyEditorProps extends IDocumentReadOnlyEditor { @@ -43,6 +45,7 @@ const DocumentReadOnlyEditor = ({ noBorder, borderOnFocus, customClassName, + embedConfig, value, documentDetails, forwardedRef, @@ -60,7 +63,7 @@ const DocumentReadOnlyEditor = ({ value, forwardedRef, rerenderOnPropsChange, - extensions: [IssueWidgetPlaceholder()], + extensions: [IssueWidgetExtension({ issueEmbedConfig: embedConfig?.issueEmbedConfig })], }); useEffect(() => { diff --git a/web/hooks/use-issue-embeds.tsx b/web/hooks/use-issue-embeds.tsx new file mode 100644 index 0000000000..99bc7e909f --- /dev/null +++ b/web/hooks/use-issue-embeds.tsx @@ -0,0 +1,47 @@ +import { PROJECT_ISSUES_LIST } from "constants/fetch-keys"; +import { StoreContext } from "contexts/store-context"; +import { toJS } from "mobx"; +import { useContext } from "react"; +import { IssueService } from "services/issue"; +import useSWR from "swr"; +import { useIssueDetail, useMember, useProject, useProjectState } from "./store"; + +const issueService = new IssueService(); + +export const useIssueEmbeds = () => { + const workspaceSlug = useContext(StoreContext).app.router.workspaceSlug; + const projectId = useContext(StoreContext).app.router.projectId; + + const { getProjectById } = useProject(); + const { setPeekIssue } = useIssueDetail(); + const { getStateById } = useProjectState(); + const { getUserDetails } = useMember(); + + const { data: issuesResponse, isLoading: issuesLoading } = useSWR( + workspaceSlug && projectId ? PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string) : null, + workspaceSlug && projectId ? () => issueService.getIssues(workspaceSlug as string, projectId as string) : null + ); + + const issues = Object.values(issuesResponse ?? {}); + const issuesWithStateAndProject = issues.map((issue) => ({ + ...issue, + state_detail: toJS(getStateById(issue.state_id)), + project_detail: toJS(getProjectById(issue.project_id)), + assignee_details: issue.assignee_ids.map((assigneeid) => toJS(getUserDetails(assigneeid))), + })); + + const fetchIssue = (issueId: string) => issuesWithStateAndProject.find((issue) => issue.id === issueId); + + const issueWidgetClickAction = (issueId: string) => { + if (!workspaceSlug || !projectId) return; + + setPeekIssue({ workspaceSlug, projectId: projectId, issueId }); + }; + + return { + issues: issuesWithStateAndProject, + issuesLoading, + fetchIssue, + issueWidgetClickAction, + }; +}; diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx b/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx index c0ed6c0b6c..81f3c8e4ea 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx @@ -18,6 +18,8 @@ import { PageDetailsHeader } from "components/headers/page-details"; // ui import { DocumentEditorWithRef, DocumentReadOnlyEditorWithRef } from "@plane/document-editor"; import { Spinner } from "@plane/ui"; +// hooks +import { useIssueEmbeds } from "hooks/use-issue-embeds"; // assets // helpers // types @@ -62,6 +64,8 @@ const PageDetailsPage: NextPageWithLayout = observer(() => { defaultValues: { name: "", description_html: "" }, }); + const { issues, fetchIssue, issueWidgetClickAction, issuesLoading } = useIssueEmbeds(); + const { archivePage: archivePageAction, restorePage: restorePageAction, @@ -255,7 +259,7 @@ const PageDetailsPage: NextPageWithLayout = observer(() => { const userCanLock = currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole); - return pageIdMobx ? ( + return pageIdMobx && issues && !issuesLoading ? (
{isPageReadOnly ? ( @@ -284,6 +288,13 @@ const PageDetailsPage: NextPageWithLayout = observer(() => { } : undefined } + embedConfig={{ + issueEmbedConfig: { + issues: issues, + fetchIssue: fetchIssue, + clickAction: issueWidgetClickAction, + }, + }} /> ) : (
@@ -327,6 +338,13 @@ const PageDetailsPage: NextPageWithLayout = observer(() => { : undefined } pageLockConfig={userCanLock ? { is_locked: false, action: lockPage } : undefined} + embedConfig={{ + issueEmbedConfig: { + issues: issues, + fetchIssue: fetchIssue, + clickAction: issueWidgetClickAction, + }, + }} /> )} />