Skip to content

Commit

Permalink
chore: Removed Issue Embeds from the Document Editor (#3449)
Browse files Browse the repository at this point in the history
* fix: issue embed going to next line when selected on slash commands

* fix: issue suggestions selecting next embed on arrow down

* fix: pages crashing, because of incorrect data type

* chore: removed issue embeds from document editor and page interface

* fix: upgraded issue widget card to show only Placeholder

* fix: pricing url changes for issue embed placeholder

* fix: build errors
  • Loading branch information
henit-chobisa authored Jan 24, 2024
1 parent 8d3ea5b commit 1a1594e
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 241 deletions.
69 changes: 21 additions & 48 deletions packages/editor/document-editor/src/ui/extensions/index.tsx
Original file line number Diff line number Diff line change
@@ -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: <LayersIcon className="h-3.5 w-3.5" />,
command: ({ editor, range }) => {
editor
.chain()
.focus()
.insertContentAt(
range,
"<p class='text-sm bg-gray-300 w-fit pl-3 pr-3 pt-1 pb-1 rounded shadow-sm'>#issue_</p>\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 [
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,
}),
IssueWidgetPlaceholder(),
];

return "Press '/' for commands...";
},
includeChildren: true,
}),
IssueWidgetExtension({ issueEmbedConfig }),
IssueSuggestions(issueEmbedConfig ? issueEmbedConfig.issues : []),
];
};
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -87,7 +86,6 @@ const IssueSuggestionList = ({
setSelectedIndex(
(selectedIndex + displayedItems[currentSection].length - 1) % displayedItems[currentSection].length
);
e.stopPropagation();
return true;
}
if (e.key === "ArrowDown") {
Expand All @@ -102,20 +100,17 @@ 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") {
const currentSectionIndex = sections.indexOf(currentSection);
const nextSectionIndex = (currentSectionIndex + 1) % sections.length;
setCurrentSection(sections[nextSectionIndex]);
setSelectedIndex(0);
e.stopPropagation();
return true;
}
return false;
Expand Down Expand Up @@ -150,7 +145,7 @@ const IssueSuggestionList = ({
<div
id="issue-list-container"
ref={commandListContainer}
className="fixed z-[10] max-h-80 w-60 overflow-y-auto overflow-x-hidden rounded-md border border-custom-border-100 bg-custom-background-100 px-1 shadow-custom-shadow-xs transition-all"
className=" fixed z-[10] max-h-80 w-60 overflow-y-auto overflow-x-hidden rounded-md border border-custom-border-100 bg-custom-background-100 px-1 shadow-custom-shadow-xs transition-all"
>
{sections.map((section) => {
const sectionItems = displayedItems[section];
Expand Down Expand Up @@ -193,29 +188,35 @@ const IssueSuggestionList = ({
</div>
) : 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);
Expand All @@ -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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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({});
Original file line number Diff line number Diff line change
@@ -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<number>(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 (
<NodeViewWrapper className="issue-embed-component m-2">
{loading == 0 ? (
<div
onClick={completeIssueEmbedAction}
className={`${
props.selected ? "border-custom-primary-200 border-[2px]" : ""
} w-full cursor-pointer space-y-2 rounded-md border-[0.5px] border-custom-border-200 p-3 shadow-custom-shadow-2xs`}
>
<h5 className="text-xs text-custom-text-300">
{issueDetails.project_detail.identifier}-{issueDetails.sequence_id}
</h5>
<h4 className="break-words text-sm font-medium">{issueDetails.name}</h4>
<div className="flex flex-wrap items-center gap-x-3 gap-y-2">
<div>
<PriorityIcon priority={issueDetails.priority} />
export const IssueWidgetCard = (props) => (
<NodeViewWrapper className="issue-embed-component m-2">
<div
className={`${
props.selected ? "border-custom-primary-200 border-[2px]" : ""
} w-full h-[100px] cursor-pointer space-y-2 rounded-md border-[0.5px] border-custom-border-200 shadow-custom-shadow-2xs`}
>
<h5 className="h-[20%] text-xs text-custom-text-300 p-2">
{props.node.attrs.project_identifier}-{props.node.attrs.sequence_id}
</h5>
<div className="relative h-[71%]">
<div className="h-full backdrop-filter backdrop-blur-[30px] bg-custom-background-80 bg-opacity-30 flex items-center w-full justify-between gap-5 mt-2.5 pl-4 pr-5 py-3 max-md:max-w-full max-md:flex-wrap relative">
<div className="flex gap-2 items-center">
<div className="rounded">
<Crown className="m-2" size={16} color="#FFBA18" />
</div>
<div>
<AvatarGroup size="sm">
{issueDetails.assignee_details.map((assignee) => (
<Avatar key={assignee.id} name={assignee.display_name} src={assignee.avatar} className={"m-0"} />
))}
</AvatarGroup>
<div className="text-custom-text text-sm">
Embed and access issues in pages seamlessly, upgrade to plane pro now.
</div>
{issueDetails.target_date && (
<div className="flex h-5 items-center gap-1 rounded border-[0.5px] border-custom-border-300 px-2.5 py-1 text-xs text-custom-text-100">
<Calendar className="h-3 w-3" strokeWidth={1.5} />
{new Date(issueDetails.target_date).toLocaleDateString()}
</div>
)}
</div>
<a href="https://plane.so/pricing" target="_blank" rel="noreferrer">
<Button>Upgrade</Button>
</a>
</div>
) : loading == -1 ? (
<div className="flex items-center gap-[8px] rounded border-2 border-[#D97706] bg-[#FFFBEB] pb-[10px] pl-[13px] pt-[10px] text-[#D97706]">
<AlertTriangle color={"#D97706"} />
{"This Issue embed is not found in any project. It can no longer be updated or accessed from here."}
</div>
) : (
<div className="w-full space-y-2 rounded-md border-[0.5px] border-custom-border-200 p-3 shadow-custom-shadow-2xs">
<Loader className={"px-6"}>
<Loader.Item height={"30px"} />
<div className={"mt-3 space-y-2"}>
<Loader.Item height={"20px"} width={"70%"} />
<Loader.Item height={"20px"} width={"60%"} />
</div>
</Loader>
</div>
)}
</NodeViewWrapper>
);
};
</div>
</div>
</NodeViewWrapper>
);
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ export const IssueWidget = Node.create({
},

addNodeView() {
return ReactNodeViewRenderer((props: Object) => (
<IssueWidgetCard {...props} issueEmbedConfig={this.options.issueEmbedConfig} />
));
return ReactNodeViewRenderer((props: Object) => <IssueWidgetCard {...props} />);
},

parseHTML() {
Expand Down

This file was deleted.

15 changes: 3 additions & 12 deletions packages/editor/document-editor/src/ui/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -47,7 +46,6 @@ interface IDocumentEditor {
duplicationConfig?: IDuplicationConfig;
pageLockConfig?: IPageLockConfig;
pageArchiveConfig?: IPageArchiveConfig;
embedConfig?: IEmbedConfig;
}
interface DocumentEditorProps extends IDocumentEditor {
forwardedRef?: React.Ref<EditorHandle>;
Expand Down Expand Up @@ -75,13 +73,11 @@ const DocumentEditor = ({
duplicationConfig,
pageLockConfig,
pageArchiveConfig,
embedConfig,
updatePageTitle,
cancelUploadImage,
onActionCompleteHandler,
rerenderOnPropsChange,
}: IDocumentEditor) => {
// const [alert, setAlert] = useState<string>("")
const { markings, updateMarkings } = useEditorMarkings();
const [sidePeekVisible, setSidePeekVisible] = useState(true);
const router = useRouter();
Expand Down Expand Up @@ -112,12 +108,7 @@ const DocumentEditor = ({
cancelUploadImage,
rerenderOnPropsChange,
forwardedRef,
extensions: DocumentEditorExtensions(
uploadFile,
embedConfig?.issueEmbedConfig,
setIsSubmitting,
setHideDragHandleFunction
),
extensions: DocumentEditorExtensions(uploadFile, setHideDragHandleFunction, setIsSubmitting),
});

if (!editor) {
Expand Down Expand Up @@ -158,11 +149,11 @@ const DocumentEditor = ({
documentDetails={documentDetails}
isSubmitting={isSubmitting}
/>
<div className="flex h-full w-full overflow-y-auto">
<div className="flex h-full w-full overflow-y-auto frame-renderer">
<div className="sticky top-0 h-full w-56 flex-shrink-0 lg:w-72">
<SummarySideBar editor={editor} markings={markings} sidePeekVisible={sidePeekVisible} />
</div>
<div className="h-full w-[calc(100%-14rem)] lg:w-[calc(100%-18rem-18rem)]">
<div className="h-full w-[calc(100%-14rem)] lg:w-[calc(100%-18rem-18rem)] page-renderer">
<PageRenderer
onActionCompleteHandler={onActionCompleteHandler}
hideDragHandle={hideDragHandleOnMouseLeave}
Expand Down
Loading

0 comments on commit 1a1594e

Please sign in to comment.