diff --git a/packages/editor/core/src/hooks/use-editor.tsx b/packages/editor/core/src/hooks/use-editor.tsx index 647b79929..93d745347 100644 --- a/packages/editor/core/src/hooks/use-editor.tsx +++ b/packages/editor/core/src/hooks/use-editor.tsx @@ -56,6 +56,8 @@ export const useEditor = ({ mentionHandler, placeholder, }: CustomEditorProps) => { + const [error, setError] = useState(null); + const editor = useCustomEditor({ editorProps: { ...CoreEditorProps(editorClassName), @@ -86,6 +88,10 @@ export const useEditor = ({ setSavedSelection(editor.state.selection); }, onUpdate: async ({ editor }) => { + const shouldError = Math.random() < 0.05; // 10% chance to generate an error + if (shouldError) { + setError("Randomly generated error for testing purposes."); + } onChange?.(editor.getJSON(), getTrimmedHTML(editor.getHTML())); }, onDestroy: async () => { @@ -203,6 +209,11 @@ export const useEditor = ({ [editorRef, savedSelection, uploadFile] ); + if (error) { + console.log("threw error from core"); + throw new Error(error); + } + if (!editor) { return null; } diff --git a/packages/editor/rich-text-editor/src/ui/index.tsx b/packages/editor/rich-text-editor/src/ui/index.tsx index e82615b95..53ec38058 100644 --- a/packages/editor/rich-text-editor/src/ui/index.tsx +++ b/packages/editor/rich-text-editor/src/ui/index.tsx @@ -49,7 +49,6 @@ const RichTextEditor = (props: IRichTextEditor) => { containerClassName, editorClassName = "", forwardedRef, - // rerenderOnPropsChange, id = "", placeholder, tabIndex, @@ -58,8 +57,6 @@ const RichTextEditor = (props: IRichTextEditor) => { const [hideDragHandleOnMouseLeave, setHideDragHandleOnMouseLeave] = React.useState<() => void>(() => {}); - // this essentially sets the hideDragHandle function from the DragAndDrop extension as the Plugin - // loads such that we can invoke it from react when the cursor leaves the container const setHideDragHandleFunction = (hideDragHandlerFromDragDrop: () => void) => { setHideDragHandleOnMouseLeave(() => hideDragHandlerFromDragDrop); }; @@ -75,7 +72,6 @@ const RichTextEditor = (props: IRichTextEditor) => { initialValue, value, forwardedRef, - // rerenderOnPropsChange, extensions: RichTextEditorExtensions({ uploadFile: fileHandler.upload, dragDropEnabled, diff --git a/web/components/editor/rich-text-editor/rich-text-editor.tsx b/web/components/editor/rich-text-editor/rich-text-editor.tsx index e2173445d..f9a4af7aa 100644 --- a/web/components/editor/rich-text-editor/rich-text-editor.tsx +++ b/web/components/editor/rich-text-editor/rich-text-editor.tsx @@ -1,4 +1,4 @@ -import React, { forwardRef } from "react"; +import { forwardRef } from "react"; // editor import { EditorRefApi, IRichTextEditor, RichTextEditorWithRef } from "@plane/rich-text-editor"; // types @@ -9,6 +9,7 @@ import { cn } from "@/helpers/common.helper"; import { useMember, useMention, useUser } from "@/hooks/store"; // services import { FileService } from "@/services/file.service"; +import ErrorBoundaryWithFallback from "./rich-text-fallback"; interface RichTextEditorWrapperProps extends Omit { workspaceSlug: string; @@ -20,6 +21,7 @@ const fileService = new FileService(); export const RichTextEditor = forwardRef((props, ref) => { const { containerClassName, workspaceSlug, workspaceId, projectId, ...rest } = props; + console.log("eeeeeeee", rest.value); // store hooks const { currentUser } = useUser(); const { @@ -38,21 +40,23 @@ export const RichTextEditor = forwardRef + + + ); }); diff --git a/web/components/editor/rich-text-editor/rich-text-fallback.tsx b/web/components/editor/rich-text-editor/rich-text-fallback.tsx new file mode 100644 index 000000000..1e2229ce9 --- /dev/null +++ b/web/components/editor/rich-text-editor/rich-text-fallback.tsx @@ -0,0 +1,41 @@ +import React, { useEffect } from "react"; +import { ErrorBoundary } from "react-error-boundary"; + +interface FallbackProps { + error: Error; + resetErrorBoundary: () => void; +} + +const Fallback: React.FC = ({ error, resetErrorBoundary }) => { + useEffect(() => { + const timer = setTimeout(() => { + resetErrorBoundary(); + }, 1000); + + return () => clearTimeout(timer); + }, [resetErrorBoundary]); + + return ( +
+

Something went wrong:

+
{error.message}
+
+ ); +}; + +interface ErrorBoundaryWithFallbackProps { + children: React.ReactNode; +} + +const ErrorBoundaryWithFallback: React.FC = ({ children }) => { + return ( + console.log("Error occurred:", error, errorInfo)} + > + {children} + + ); +}; + +export default ErrorBoundaryWithFallback; diff --git a/web/package.json b/web/package.json index a4c94d051..2a27be4df 100644 --- a/web/package.json +++ b/web/package.json @@ -54,13 +54,13 @@ "react-day-picker": "^8.10.0", "react-dom": "18.2.0", "react-dropzone": "^14.2.3", + "react-error-boundary": "^4.0.13", "react-hook-form": "^7.38.0", "react-markdown": "^8.0.7", "react-popper": "^2.3.0", "sharp": "^0.32.1", "swr": "^2.1.3", "tailwind-merge": "^2.0.0", - "use-debounce": "^9.0.4", "uuid": "^9.0.0" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index a33c24f88..66149d110 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2755,7 +2755,7 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@18.2.42", "@types/react@^18.2.42": +"@types/react@*", "@types/react@^18.2.42": version "18.2.42" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.42.tgz#6f6b11a904f6d96dda3c2920328a97011a00aba7" integrity sha512-c1zEr96MjakLYus/wPnuWDo1/zErfdU9rNsIGmE+NV71nx88FG9Ttgo5dqorXTu/LImX2f63WBP986gJkMPNbA== @@ -7194,6 +7194,13 @@ react-dropzone@^14.2.3: file-selector "^0.6.0" prop-types "^15.8.1" +react-error-boundary@^4.0.13: + version "4.0.13" + resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-4.0.13.tgz#80386b7b27b1131c5fbb7368b8c0d983354c7947" + integrity sha512-b6PwbdSv8XeOSYvjt8LpgpKrZ0yGdtZokYwkwV2wlcZbxgopHX/hgPl5VgpnoVOWd868n1hktM8Qm4b+02MiLQ== + dependencies: + "@babel/runtime" "^7.12.5" + react-fast-compare@^3.0.1: version "3.2.2" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49" @@ -8628,11 +8635,6 @@ use-callback-ref@^1.3.0: dependencies: tslib "^2.0.0" -use-debounce@^9.0.4: - version "9.0.4" - resolved "https://registry.yarnpkg.com/use-debounce/-/use-debounce-9.0.4.tgz#51d25d856fbdfeb537553972ce3943b897f1ac85" - integrity sha512-6X8H/mikbrt0XE8e+JXRtZ8yYVvKkdYRfmIhWZYsP8rcNs9hk3APV8Ua2mFkKRLcJKVdnX2/Vwrmg2GWKUQEaQ== - use-memo-one@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.3.tgz#2fd2e43a2169eabc7496960ace8c79efef975e99"