mirror of
https://github.com/makeplane/plane
synced 2025-08-07 19:59:33 +00:00
Compare commits
3 Commits
master
...
refactor/w
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
704a36b418 | ||
|
|
b44723adfe | ||
|
|
8a23a384d9 |
@@ -1,4 +1,5 @@
|
||||
export { RichTextEditor, RichTextEditorWithRef } from "src/ui";
|
||||
export { RichReadOnlyEditor, RichReadOnlyEditorWithRef } from "src/ui/read-only";
|
||||
export { RichTextReadOnlyEditor, RichTextReadOnlyEditorWithRef } from "src/ui/read-only";
|
||||
export type { RichTextEditorProps, IRichTextEditor } from "src/ui";
|
||||
export type { IMentionHighlight, IMentionSuggestion } from "@plane/editor-core";
|
||||
export type { IRichTextReadOnlyEditor } from "src/ui/read-only";
|
||||
export type { IMentionSuggestion, IMentionHighlight } from "@plane/editor-core";
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { EditorContainer, EditorContentWrapper, getEditorClassNames, useReadOnlyEditor } from "@plane/editor-core";
|
||||
import * as React from "react";
|
||||
|
||||
interface IRichTextReadOnlyEditor {
|
||||
export interface IRichTextReadOnlyEditor {
|
||||
value: string;
|
||||
editorContentCustomClassNames?: string;
|
||||
noBorder?: boolean;
|
||||
@@ -21,7 +21,7 @@ interface EditorHandle {
|
||||
setEditorValue: (content: string) => void;
|
||||
}
|
||||
|
||||
const RichReadOnlyEditor = ({
|
||||
const RichTextReadOnlyEditor = ({
|
||||
editorContentCustomClassNames,
|
||||
noBorder,
|
||||
borderOnFocus,
|
||||
@@ -53,10 +53,10 @@ const RichReadOnlyEditor = ({
|
||||
);
|
||||
};
|
||||
|
||||
const RichReadOnlyEditorWithRef = React.forwardRef<EditorHandle, IRichTextReadOnlyEditor>((props, ref) => (
|
||||
<RichReadOnlyEditor {...props} forwardedRef={ref} />
|
||||
const RichTextReadOnlyEditorWithRef = React.forwardRef<EditorHandle, IRichTextReadOnlyEditor>((props, ref) => (
|
||||
<RichTextReadOnlyEditor {...props} forwardedRef={ref} />
|
||||
));
|
||||
|
||||
RichReadOnlyEditorWithRef.displayName = "RichReadOnlyEditorWithRef";
|
||||
RichTextReadOnlyEditorWithRef.displayName = "RichTextReadOnlyEditorWithRef";
|
||||
|
||||
export { RichReadOnlyEditor, RichReadOnlyEditorWithRef };
|
||||
export { RichTextReadOnlyEditor, RichTextReadOnlyEditorWithRef };
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Placement } from "@popperjs/core";
|
||||
import { useRouter } from "next/router";
|
||||
import { Controller, useForm } from "react-hook-form"; // services
|
||||
import { usePopper } from "react-popper";
|
||||
import { RichReadOnlyEditorWithRef } from "@plane/rich-text-editor";
|
||||
import { RichTextReadOnlyEditor } from "components/editor/rich-text-read-only-editor";
|
||||
import { Popover, Transition } from "@headlessui/react";
|
||||
// hooks
|
||||
// ui
|
||||
@@ -201,7 +201,7 @@ export const GptAssistantPopover: React.FC<Props> = (props) => {
|
||||
{prompt && (
|
||||
<div className="text-sm">
|
||||
Content:
|
||||
<RichReadOnlyEditorWithRef
|
||||
<RichTextReadOnlyEditor
|
||||
value={prompt}
|
||||
customClassName="-m-3"
|
||||
noBorder
|
||||
@@ -213,7 +213,7 @@ export const GptAssistantPopover: React.FC<Props> = (props) => {
|
||||
{response !== "" && (
|
||||
<div className="page-block-section max-h-[8rem] text-sm">
|
||||
Response:
|
||||
<RichReadOnlyEditorWithRef
|
||||
<RichTextReadOnlyEditor
|
||||
value={`<p>${response}</p>`}
|
||||
customClassName={response ? "-mx-3 -my-3" : ""}
|
||||
noBorder
|
||||
|
||||
43
web/components/editor/rich-text-editor.tsx
Normal file
43
web/components/editor/rich-text-editor.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import React from "react";
|
||||
import { RichTextEditorWithRef, IRichTextEditor } from "@plane/rich-text-editor";
|
||||
|
||||
import { useMention } from "hooks/store";
|
||||
|
||||
import { FileService } from "services/file.service";
|
||||
|
||||
interface EditorHandle {
|
||||
clearEditor: () => void;
|
||||
setEditorValue: (content: string) => void;
|
||||
}
|
||||
|
||||
interface RichTextEditorWrapperProps
|
||||
extends Omit<
|
||||
IRichTextEditor,
|
||||
"uploadFile" | "deleteFile" | "cancelUploadImage" | "restoreFile" | "mentionSuggestions" | "mentionHighlights"
|
||||
> {
|
||||
workspaceSlug: string;
|
||||
workspaceId: string;
|
||||
}
|
||||
|
||||
const fileService = new FileService();
|
||||
|
||||
export const RichTextEditor = React.forwardRef<EditorHandle, RichTextEditorWrapperProps>(
|
||||
({ workspaceSlug, workspaceId, ...props }, ref) => {
|
||||
const editorSuggestions = useMention();
|
||||
|
||||
return (
|
||||
<RichTextEditorWithRef
|
||||
ref={ref}
|
||||
uploadFile={fileService.getUploadFileFunction(workspaceSlug)}
|
||||
deleteFile={fileService.getDeleteImageFunction(workspaceId)}
|
||||
restoreFile={fileService.getRestoreImageFunction(workspaceId)}
|
||||
cancelUploadImage={fileService.cancelUpload}
|
||||
mentionSuggestions={editorSuggestions.mentionSuggestions}
|
||||
mentionHighlights={editorSuggestions.mentionHighlights}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
RichTextEditor.displayName = "RichTextEditor";
|
||||
23
web/components/editor/rich-text-read-only-editor.tsx
Normal file
23
web/components/editor/rich-text-read-only-editor.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import React from "react";
|
||||
import { IRichTextReadOnlyEditor, RichTextReadOnlyEditorWithRef } from "@plane/rich-text-editor";
|
||||
|
||||
import { useMention } from "hooks/store";
|
||||
|
||||
interface EditorHandle {
|
||||
clearEditor: () => void;
|
||||
setEditorValue: (content: string) => void;
|
||||
}
|
||||
|
||||
interface RichTextReadOnlyEditorWrapperProps extends Omit<IRichTextReadOnlyEditor, "mentionHighlights"> {}
|
||||
|
||||
export const RichTextReadOnlyEditor = React.forwardRef<EditorHandle, RichTextReadOnlyEditorWrapperProps>(
|
||||
({ ...props }, ref) => {
|
||||
const editorSuggestions = useMention();
|
||||
|
||||
return (
|
||||
<RichTextReadOnlyEditorWithRef ref={ref} mentionHighlights={editorSuggestions.mentionHighlights} {...props} />
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
RichTextReadOnlyEditor.displayName = "RichTextReadOnlyEditor";
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Fragment, useRef, useState } from "react";
|
||||
import { RichTextEditorWithRef } from "@plane/rich-text-editor";
|
||||
import { RichTextEditor } from "components/editor/rich-text-editor";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useRouter } from "next/router";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
@@ -35,7 +35,6 @@ const defaultValues: Partial<TIssue> = {
|
||||
|
||||
// services
|
||||
const aiService = new AIService();
|
||||
const fileService = new FileService();
|
||||
|
||||
export const CreateInboxIssueModal: React.FC<Props> = observer((props) => {
|
||||
const { isOpen, onClose } = props;
|
||||
@@ -53,7 +52,6 @@ export const CreateInboxIssueModal: React.FC<Props> = observer((props) => {
|
||||
inboxId: string;
|
||||
};
|
||||
// hooks
|
||||
const { mentionHighlights, mentionSuggestions } = useMention();
|
||||
const workspaceStore = useWorkspace();
|
||||
const workspaceId = workspaceStore.getWorkspaceBySlug(workspaceSlug as string)?.id as string;
|
||||
|
||||
@@ -270,11 +268,9 @@ export const CreateInboxIssueModal: React.FC<Props> = observer((props) => {
|
||||
name="description_html"
|
||||
control={control}
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<RichTextEditorWithRef
|
||||
cancelUploadImage={fileService.cancelUpload}
|
||||
uploadFile={fileService.getUploadFileFunction(workspaceSlug as string)}
|
||||
deleteFile={fileService.getDeleteImageFunction(workspaceId)}
|
||||
restoreFile={fileService.getRestoreImageFunction(workspaceId)}
|
||||
<RichTextEditor
|
||||
workspaceId={workspaceId}
|
||||
workspaceSlug={workspaceSlug}
|
||||
ref={editorRef}
|
||||
debouncedUpdatesEnabled={false}
|
||||
value={!value || value === "" ? "<p></p>" : value}
|
||||
@@ -282,8 +278,6 @@ export const CreateInboxIssueModal: React.FC<Props> = observer((props) => {
|
||||
onChange={(description, description_html: string) => {
|
||||
onChange(description_html);
|
||||
}}
|
||||
mentionSuggestions={mentionSuggestions}
|
||||
mentionHighlights={mentionHighlights}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ChangeEvent, FC, useCallback, useEffect, useState } from "react";
|
||||
import { RichReadOnlyEditor, RichTextEditor } from "@plane/rich-text-editor";
|
||||
import { RichTextEditor } from "components/editor/rich-text-editor";
|
||||
import { RichTextReadOnlyEditor } from "components/editor/rich-text-read-only-editor";
|
||||
import debounce from "lodash/debounce";
|
||||
import { observer } from "mobx-react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
@@ -163,10 +164,8 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = observer((props) => {
|
||||
render={({ field: { onChange } }) =>
|
||||
!disabled ? (
|
||||
<RichTextEditor
|
||||
cancelUploadImage={fileService.cancelUpload}
|
||||
uploadFile={fileService.getUploadFileFunction(workspaceSlug)}
|
||||
deleteFile={fileService.getDeleteImageFunction(workspaceId)}
|
||||
restoreFile={fileService.getRestoreImageFunction(workspaceId)}
|
||||
workspaceId={workspaceId}
|
||||
workspaceSlug={workspaceSlug}
|
||||
value={localIssueDescription.description_html}
|
||||
rerenderOnPropsChange={localIssueDescription}
|
||||
setShouldShowAlert={setShowAlert}
|
||||
@@ -179,15 +178,12 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = observer((props) => {
|
||||
onChange(description_html);
|
||||
debouncedFormSave();
|
||||
}}
|
||||
mentionSuggestions={mentionSuggestions}
|
||||
mentionHighlights={mentionHighlights}
|
||||
/>
|
||||
) : (
|
||||
<RichReadOnlyEditor
|
||||
<RichTextReadOnlyEditor
|
||||
value={localIssueDescription.description_html}
|
||||
customClassName="!p-0 !pt-2 text-custom-text-200"
|
||||
noBorder={disabled}
|
||||
mentionHighlights={mentionHighlights}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -200,4 +196,4 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = observer((props) => {
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { FC, useState, useRef, useEffect, Fragment } from "react";
|
||||
import { RichTextEditorWithRef } from "@plane/rich-text-editor";
|
||||
import { RichTextEditor } from "components/editor/rich-text-editor";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useRouter } from "next/router";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
@@ -22,7 +22,7 @@ import { ParentIssuesListModal } from "components/issues";
|
||||
import { IssueLabelSelect } from "components/issues/select";
|
||||
import { CreateLabelModal } from "components/labels";
|
||||
import { renderFormattedPayloadDate } from "helpers/date-time.helper";
|
||||
import { useApplication, useEstimate, useIssueDetail, useMention, useProject, useWorkspace } from "hooks/store";
|
||||
import { useApplication, useEstimate, useIssueDetail, useProject, useWorkspace } from "hooks/store";
|
||||
// services
|
||||
import { AIService } from "services/ai.service";
|
||||
import { FileService } from "services/file.service";
|
||||
@@ -62,7 +62,6 @@ export interface IssueFormProps {
|
||||
|
||||
// services
|
||||
const aiService = new AIService();
|
||||
const fileService = new FileService();
|
||||
|
||||
const TAB_INDICES = [
|
||||
"name",
|
||||
@@ -121,7 +120,6 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
||||
} = useApplication();
|
||||
const { getProjectById } = useProject();
|
||||
const { areEstimatesEnabledForProject } = useEstimate();
|
||||
const { mentionHighlights, mentionSuggestions } = useMention();
|
||||
const {
|
||||
issue: { getIssueById },
|
||||
} = useIssueDetail();
|
||||
@@ -447,11 +445,9 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
||||
name="description_html"
|
||||
control={control}
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<RichTextEditorWithRef
|
||||
cancelUploadImage={fileService.cancelUpload}
|
||||
uploadFile={fileService.getUploadFileFunction(workspaceSlug as string)}
|
||||
deleteFile={fileService.getDeleteImageFunction(workspaceId)}
|
||||
restoreFile={fileService.getRestoreImageFunction(workspaceId)}
|
||||
<RichTextEditor
|
||||
workspaceId={workspaceId}
|
||||
workspaceSlug={workspaceSlug}
|
||||
ref={editorRef}
|
||||
debouncedUpdatesEnabled={false}
|
||||
value={
|
||||
@@ -465,8 +461,6 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
||||
onChange(description_html);
|
||||
handleFormChange();
|
||||
}}
|
||||
mentionHighlights={mentionHighlights}
|
||||
mentionSuggestions={mentionSuggestions}
|
||||
tabIndex={getTabIndex("description_html")}
|
||||
/>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user