diff --git a/packages/editor/document-editor/src/ui/extensions/index.tsx b/packages/editor/document-editor/src/ui/extensions/index.tsx
index 7de1e2922..2576d0d74 100644
--- a/packages/editor/document-editor/src/ui/extensions/index.tsx
+++ b/packages/editor/document-editor/src/ui/extensions/index.tsx
@@ -1,56 +1,29 @@
import Placeholder from "@tiptap/extension-placeholder";
-import { IssueWidgetExtension } from "src/ui/extensions/widgets/issue-embed-widget";
-
-import { IIssueEmbedConfig } from "src/ui/extensions/widgets/issue-embed-widget/types";
+import { IssueWidgetPlaceholder } from "src/ui/extensions/widgets/issue-embed-widget";
import { SlashCommand, DragAndDrop } from "@plane/editor-extensions";
-import { ISlashCommandItem, UploadImage } from "@plane/editor-core";
-import { IssueSuggestions } from "src/ui/extensions/widgets/issue-embed-suggestion-list";
-import { LayersIcon } from "@plane/ui";
+import { UploadImage } from "@plane/editor-core";
export const DocumentEditorExtensions = (
uploadFile: UploadImage,
- issueEmbedConfig?: IIssueEmbedConfig,
- setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void,
- setHideDragHandle?: (hideDragHandlerFromDragDrop: () => void) => void
-) => {
- const additionalOptions: ISlashCommandItem[] = [
- {
- key: "issue_embed",
- title: "Issue embed",
- description: "Embed an issue from the project.",
- searchTerms: ["issue", "link", "embed"],
- icon: ,
- command: ({ editor, range }) => {
- editor
- .chain()
- .focus()
- .insertContentAt(
- range,
- "
#issue_
\n"
- )
- .run();
- },
+ setHideDragHandle?: (hideDragHandlerFromDragDrop: () => void) => void,
+ setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void
+) => [
+ SlashCommand(uploadFile, setIsSubmitting),
+ DragAndDrop(setHideDragHandle),
+ Placeholder.configure({
+ placeholder: ({ node }) => {
+ if (node.type.name === "heading") {
+ return `Heading ${node.attrs.level}`;
+ }
+ if (node.type.name === "image" || node.type.name === "table") {
+ return "";
+ }
+
+ return "Press '/' for commands...";
},
- ];
+ includeChildren: true,
+ }),
+ IssueWidgetPlaceholder(),
+];
- return [
- SlashCommand(uploadFile, setIsSubmitting, additionalOptions),
- DragAndDrop(setHideDragHandle),
- Placeholder.configure({
- placeholder: ({ node }) => {
- if (node.type.name === "heading") {
- return `Heading ${node.attrs.level}`;
- }
- if (node.type.name === "image" || node.type.name === "table") {
- return "";
- }
-
- return "Press '/' for commands...";
- },
- includeChildren: true,
- }),
- IssueWidgetExtension({ issueEmbedConfig }),
- IssueSuggestions(issueEmbedConfig ? issueEmbedConfig.issues : []),
- ];
-};
diff --git a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-suggestion-list/issue-suggestion-renderer.tsx b/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-suggestion-list/issue-suggestion-renderer.tsx
index 637afe29c..869c7a8c6 100644
--- a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-suggestion-list/issue-suggestion-renderer.tsx
+++ b/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-suggestion-list/issue-suggestion-renderer.tsx
@@ -78,7 +78,6 @@ const IssueSuggestionList = ({
const navigationKeys = ["ArrowUp", "ArrowDown", "Enter", "Tab"];
const onKeyDown = (e: KeyboardEvent) => {
if (navigationKeys.includes(e.key)) {
- e.preventDefault();
// if (editor.isFocused) {
// editor.chain().blur();
// commandListContainer.current?.focus();
@@ -87,7 +86,6 @@ const IssueSuggestionList = ({
setSelectedIndex(
(selectedIndex + displayedItems[currentSection].length - 1) % displayedItems[currentSection].length
);
- e.stopPropagation();
return true;
}
if (e.key === "ArrowDown") {
@@ -102,12 +100,10 @@ const IssueSuggestionList = ({
[currentSection]: [...prevItems[currentSection], ...nextItems],
}));
}
- e.stopPropagation();
return true;
}
if (e.key === "Enter") {
selectItem(currentSection, selectedIndex);
- e.stopPropagation();
return true;
}
if (e.key === "Tab") {
@@ -115,7 +111,6 @@ const IssueSuggestionList = ({
const nextSectionIndex = (currentSectionIndex + 1) % sections.length;
setCurrentSection(sections[nextSectionIndex]);
setSelectedIndex(0);
- e.stopPropagation();
return true;
}
return false;
@@ -150,7 +145,7 @@ const IssueSuggestionList = ({
{sections.map((section) => {
const sectionItems = displayedItems[section];
@@ -193,29 +188,35 @@ const IssueSuggestionList = ({
) : null;
};
-
export const IssueListRenderer = () => {
let component: ReactRenderer | null = null;
let popup: any | null = null;
return {
onStart: (props: { editor: Editor; clientRect?: (() => DOMRect | null) | null }) => {
+ const container = document.querySelector(".frame-renderer") as HTMLElement;
component = new ReactRenderer(IssueSuggestionList, {
props,
// @ts-ignore
editor: props.editor,
});
-
// @ts-ignore
- popup = tippy("body", {
+ popup = tippy(".frame-renderer", {
+ flipbehavior: ["bottom", "top"],
+ appendTo: () => document.querySelector(".frame-renderer") as HTMLElement,
+ flip: true,
+ flipOnUpdate: true,
getReferenceClientRect: props.clientRect,
- appendTo: () => document.querySelector("#editor-container"),
content: component.element,
showOnCreate: true,
interactive: true,
trigger: "manual",
placement: "bottom-start",
});
+
+ container.addEventListener("scroll", () => {
+ popup?.[0].destroy();
+ });
},
onUpdate: (props: { editor: Editor; clientRect?: (() => DOMRect | null) | null }) => {
component?.updateProps(props);
@@ -230,10 +231,20 @@ export const IssueListRenderer = () => {
popup?.[0].hide();
return true;
}
- // @ts-ignore
- return component?.ref?.onKeyDown(props);
+
+ const navigationKeys = ["ArrowUp", "ArrowDown", "Enter", "Tab"];
+ if (navigationKeys.includes(props.event.key)) {
+ // @ts-ignore
+ component?.ref?.onKeyDown(props);
+ return true;
+ }
+ return false;
},
onExit: (e) => {
+ const container = document.querySelector(".frame-renderer") as HTMLElement;
+ if (container) {
+ container.removeEventListener("scroll", () => {});
+ }
popup?.[0].destroy();
setTimeout(() => {
component?.destroy();
diff --git a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/index.tsx b/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/index.tsx
index 9bbb34aa5..264a70152 100644
--- a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/index.tsx
+++ b/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/index.tsx
@@ -1,11 +1,3 @@
import { IssueWidget } from "src/ui/extensions/widgets/issue-embed-widget/issue-widget-node";
-import { IIssueEmbedConfig } from "src/ui/extensions/widgets/issue-embed-widget/types";
-interface IssueWidgetExtensionProps {
- issueEmbedConfig?: IIssueEmbedConfig;
-}
-
-export const IssueWidgetExtension = ({ issueEmbedConfig }: IssueWidgetExtensionProps) =>
- IssueWidget.configure({
- issueEmbedConfig,
- });
+export const IssueWidgetPlaceholder = () => IssueWidget.configure({});
diff --git a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/issue-widget-card.tsx b/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/issue-widget-card.tsx
index caca2ded7..d3b6fd04f 100644
--- a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/issue-widget-card.tsx
+++ b/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/issue-widget-card.tsx
@@ -1,77 +1,33 @@
// @ts-nocheck
-import { useState, useEffect } from "react";
+import { Button } from "@plane/ui";
import { NodeViewWrapper } from "@tiptap/react";
-import { Avatar, AvatarGroup, Loader, PriorityIcon } from "@plane/ui";
-import { Calendar, AlertTriangle } from "lucide-react";
+import { Crown } from "lucide-react";
-export const IssueWidgetCard = (props) => {
- const [loading, setLoading] = useState(1);
- const [issueDetails, setIssueDetails] = useState();
-
- useEffect(() => {
- props.issueEmbedConfig
- .fetchIssue(props.node.attrs.entity_identifier)
- .then((issue) => {
- setIssueDetails(issue);
- setLoading(0);
- })
- .catch(() => {
- setLoading(-1);
- });
- }, []);
-
- const completeIssueEmbedAction = () => {
- props.issueEmbedConfig.clickAction(issueDetails.id, props.node.attrs.title);
- };
-
- return (
-
- {loading == 0 ? (
-
-
- {issueDetails.project_detail.identifier}-{issueDetails.sequence_id}
-
-
{issueDetails.name}
-
-
-
+export const IssueWidgetCard = (props) => (
+
+
+
+ {props.node.attrs.project_identifier}-{props.node.attrs.sequence_id}
+
+
+
+
+
+
-
-
- {issueDetails.assignee_details.map((assignee) => (
-
- ))}
-
+
+ Embed and access issues in pages seamlessly, upgrade to plane pro now.
- {issueDetails.target_date && (
-
-
- {new Date(issueDetails.target_date).toLocaleDateString()}
-
- )}
+
+
+
- ) : loading == -1 ? (
-
-
- {"This Issue embed is not found in any project. It can no longer be updated or accessed from here."}
-
- ) : (
-
- )}
-
- );
-};
+
+
+
+);
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 c13637bd9..6c744927a 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,9 +34,7 @@ export const IssueWidget = Node.create({
},
addNodeView() {
- return ReactNodeViewRenderer((props: Object) => (
-
- ));
+ return ReactNodeViewRenderer((props: Object) =>
);
},
parseHTML() {
diff --git a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/types.ts b/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/types.ts
deleted file mode 100644
index 615b55dee..000000000
--- a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/types.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-export interface IEmbedConfig {
- issueEmbedConfig: IIssueEmbedConfig;
-}
-
-export interface IIssueEmbedConfig {
- fetchIssue: (issueId: string) => Promise
;
- clickAction: (issueId: string, issueTitle: string) => void;
- issues: Array;
-}
diff --git a/packages/editor/document-editor/src/ui/index.tsx b/packages/editor/document-editor/src/ui/index.tsx
index e88632c3b..d1bdbc935 100644
--- a/packages/editor/document-editor/src/ui/index.tsx
+++ b/packages/editor/document-editor/src/ui/index.tsx
@@ -10,7 +10,6 @@ import { DocumentDetails } from "src/types/editor-types";
import { PageRenderer } from "src/ui/components/page-renderer";
import { getMenuOptions } from "src/utils/menu-options";
import { useRouter } from "next/router";
-import { IEmbedConfig } from "src/ui/extensions/widgets/issue-embed-widget/types";
interface IDocumentEditor {
// document info
@@ -47,7 +46,6 @@ interface IDocumentEditor {
duplicationConfig?: IDuplicationConfig;
pageLockConfig?: IPageLockConfig;
pageArchiveConfig?: IPageArchiveConfig;
- embedConfig?: IEmbedConfig;
}
interface DocumentEditorProps extends IDocumentEditor {
forwardedRef?: React.Ref;
@@ -75,13 +73,11 @@ const DocumentEditor = ({
duplicationConfig,
pageLockConfig,
pageArchiveConfig,
- embedConfig,
updatePageTitle,
cancelUploadImage,
onActionCompleteHandler,
rerenderOnPropsChange,
}: IDocumentEditor) => {
- // const [alert, setAlert] = useState("")
const { markings, updateMarkings } = useEditorMarkings();
const [sidePeekVisible, setSidePeekVisible] = useState(true);
const router = useRouter();
@@ -112,12 +108,7 @@ const DocumentEditor = ({
cancelUploadImage,
rerenderOnPropsChange,
forwardedRef,
- extensions: DocumentEditorExtensions(
- uploadFile,
- embedConfig?.issueEmbedConfig,
- setIsSubmitting,
- setHideDragHandleFunction
- ),
+ extensions: DocumentEditorExtensions(uploadFile, setHideDragHandleFunction, setIsSubmitting),
});
if (!editor) {
@@ -158,11 +149,11 @@ const DocumentEditor = ({
documentDetails={documentDetails}
isSubmitting={isSubmitting}
/>
-
+
-
+
void;
- embedConfig?: IEmbedConfig;
}
interface DocumentReadOnlyEditorProps extends IDocumentReadOnlyEditor {
@@ -51,7 +49,6 @@ const DocumentReadOnlyEditor = ({
pageDuplicationConfig,
pageLockConfig,
pageArchiveConfig,
- embedConfig,
rerenderOnPropsChange,
onActionCompleteHandler,
}: DocumentReadOnlyEditorProps) => {
@@ -63,7 +60,7 @@ const DocumentReadOnlyEditor = ({
value,
forwardedRef,
rerenderOnPropsChange,
- extensions: [IssueWidgetExtension({ issueEmbedConfig: embedConfig?.issueEmbedConfig })],
+ extensions: [IssueWidgetPlaceholder()],
});
useEffect(() => {
@@ -105,11 +102,11 @@ const DocumentReadOnlyEditor = ({
documentDetails={documentDetails}
archivedAt={pageArchiveConfig && pageArchiveConfig.archived_at}
/>
-
+
-
+
Promise.resolve()}
diff --git a/web/hooks/use-issue-embeds.tsx b/web/hooks/use-issue-embeds.tsx
deleted file mode 100644
index 2c8f7700b..000000000
--- a/web/hooks/use-issue-embeds.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import { TIssue } from "@plane/types";
-import { PROJECT_ISSUES_LIST, STATES_LIST } from "constants/fetch-keys";
-import { EIssuesStoreType } from "constants/issue";
-import { StoreContext } from "contexts/store-context";
-import { autorun, toJS } from "mobx";
-import { useContext } from "react";
-import { IssueService } from "services/issue";
-import useSWR from "swr";
-import { useIssueDetail, useIssues, 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 } = 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 = async (issueId: string) => issuesWithStateAndProject.find((issue) => issue.id === issueId);
-
- const issueWidgetClickAction = (issueId: string) => {
- if (!workspaceSlug || !projectId) return;
-
- setPeekIssue({ workspaceSlug, projectId: projectId, issueId });
- };
-
- return {
- issues: issuesWithStateAndProject,
- fetchIssue,
- issueWidgetClickAction,
- };
-};
diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx b/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx
index 4d335f3b8..be512dda0 100644
--- a/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx
+++ b/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx
@@ -5,7 +5,8 @@ import { useRouter } from "next/router";
import { ReactElement, useEffect, useRef, useState } from "react";
import { Controller, useForm } from "react-hook-form";
// hooks
-import { useApplication, useIssues, usePage, useUser, useWorkspace } from "hooks/store";
+
+import { useApplication, usePage, useUser, useWorkspace } from "hooks/store";
import useReloadConfirmations from "hooks/use-reload-confirmation";
import useToast from "hooks/use-toast";
// services
@@ -27,15 +28,10 @@ import { NextPageWithLayout } from "lib/types";
// constants
import { EUserProjectRoles } from "constants/project";
import { useProjectPages } from "hooks/store/use-project-specific-pages";
-import { useIssueEmbeds } from "hooks/use-issue-embeds";
import { IssuePeekOverview } from "components/issues";
-import { PROJECT_ISSUES_LIST } from "constants/fetch-keys";
-import { IssueService } from "services/issue";
-import { EIssuesStoreType } from "constants/issue";
// services
const fileService = new FileService();
-const issueService = new IssueService();
const PageDetailsPage: NextPageWithLayout = observer(() => {
// states
@@ -91,8 +87,6 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
: null
);
- const { issues, fetchIssue, issueWidgetClickAction } = useIssueEmbeds();
-
const pageStore = usePage(pageId as string);
useEffect(
@@ -262,7 +256,7 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
const userCanLock =
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
- return pageIdMobx && issues ? (
+ return pageIdMobx ? (
{isPageReadOnly ? (
@@ -291,13 +285,6 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
}
: undefined
}
- embedConfig={{
- issueEmbedConfig: {
- issues: issues,
- fetchIssue: fetchIssue,
- clickAction: issueWidgetClickAction,
- },
- }}
/>
) : (
@@ -341,13 +328,6 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
: undefined
}
pageLockConfig={userCanLock ? { is_locked: false, action: lockPage } : undefined}
- embedConfig={{
- issueEmbedConfig: {
- issues: issues,
- fetchIssue: fetchIssue,
- clickAction: issueWidgetClickAction,
- },
- }}
/>
)}
/>