forked from github/plane
saving with debounce logic added and it's stored in backend
This commit is contained in:
parent
50e7c5924c
commit
a6ae849a81
@ -1,21 +1,11 @@
|
||||
import { FC, useCallback, useEffect, useState } from "react";
|
||||
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
// react-hook-form
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
// hooks
|
||||
import useReloadConfirmations from "hooks/use-reload-confirmation";
|
||||
// components
|
||||
import { Loader, TextArea } from "components/ui";
|
||||
// const RemirrorRichTextEditor = dynamic(() => import("components/rich-text-editor"), {
|
||||
// ssr: false,
|
||||
// loading: () => (
|
||||
// <Loader>
|
||||
// <Loader.Item height="12rem" width="100%" />
|
||||
// </Loader>
|
||||
// ),
|
||||
// });
|
||||
import { TextArea } from "components/ui";
|
||||
|
||||
import Tiptap from "./tiptap";
|
||||
// types
|
||||
@ -65,7 +55,8 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = ({
|
||||
|
||||
const handleDescriptionFormSubmit = useCallback(
|
||||
async (formData: Partial<IIssue>) => {
|
||||
if (!formData.name || formData.name.length === 0 || formData.name.length > 255) return;
|
||||
console.log("formdata", formData)
|
||||
if (!formData?.name || formData?.name.length === 0 || formData?.name.length > 255) return;
|
||||
|
||||
await handleFormSubmit({
|
||||
name: formData.name ?? "",
|
||||
@ -122,51 +113,29 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = ({
|
||||
<Controller
|
||||
name="description"
|
||||
control={control}
|
||||
render={({ field: { value } }) => {
|
||||
render={({ field: { value, onChange } }) => {
|
||||
if (!value && !watch("description_html")) return <></>;
|
||||
|
||||
return (
|
||||
<Tiptap value={
|
||||
!value ||
|
||||
value === "" ||
|
||||
(typeof value === "object" && Object.keys(value).length === 0)
|
||||
? watch("description_html")
|
||||
: value
|
||||
}
|
||||
<Tiptap
|
||||
value={
|
||||
!value || value === "" || (typeof value === "object" && Object.keys(value).length === 0)
|
||||
? watch("description_html")
|
||||
: value
|
||||
}
|
||||
setIsSubmitting={setIsSubmitting}
|
||||
onChange={(description: Object, description_html: string) => {
|
||||
onChange(description);
|
||||
setValue("description_html", description_html);
|
||||
handleSubmit(handleDescriptionFormSubmit)().finally(() => setIsSubmitting(false));
|
||||
}}
|
||||
/>
|
||||
// <RemirrorRichTextEditor
|
||||
// value = {
|
||||
// !value ||
|
||||
// value === "" ||
|
||||
// (typeof value === "object" && Object.keys(value).length === 0)
|
||||
// ? watch("description_html")
|
||||
// : value
|
||||
// }
|
||||
// onJSONChange={(jsonValue) => {
|
||||
// setShowAlert(true);
|
||||
// setValue("description", jsonValue);
|
||||
// }}
|
||||
// onHTMLChange={(htmlValue) => {
|
||||
// setShowAlert(true);
|
||||
// setValue("description_html", htmlValue);
|
||||
// }}
|
||||
// onBlur={() => {
|
||||
// setIsSubmitting(true);
|
||||
// handleSubmit(handleDescriptionFormSubmit)()
|
||||
// .then(() => setShowAlert(false))
|
||||
// .finally(() => setIsSubmitting(false));
|
||||
// }}
|
||||
// placeholder="Description"
|
||||
// editable={isAllowed}
|
||||
// />
|
||||
);
|
||||
}}
|
||||
/>
|
||||
{isSubmitting && (
|
||||
<div className="absolute bottom-1 right-1 text-xs text-custom-text-200 bg-custom-background-100 p-3 z-10">
|
||||
Saving...
|
||||
</div>
|
||||
)}
|
||||
<div className="absolute right-5 top-5 text-xs text-custom-text-200 border border-custom-border-400 rounded-xl w-[6.5rem] py-1 z-10 flex items-center justify-center">
|
||||
{isSubmitting ? "Saving..." : "Saved"}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,6 +1,5 @@
|
||||
import Placeholder from '@tiptap/extension-placeholder';
|
||||
import { useEditor, EditorContent } from '@tiptap/react';
|
||||
import StarterKit from '@tiptap/starter-kit';
|
||||
import { useDebouncedCallback } from 'use-debounce';
|
||||
import { EditorBubbleMenu } from './EditorBubbleMenu';
|
||||
import { TiptapExtensions } from './extensions';
|
||||
import { TiptapEditorProps } from "./props";
|
||||
@ -10,21 +9,29 @@ type TiptapProps = {
|
||||
noBorder?: boolean;
|
||||
borderOnFocus?: boolean;
|
||||
customClassName?: string;
|
||||
onChange?: (json: any, html: string) => void;
|
||||
setIsSubmitting?: (isSubmitting: boolean) => void;
|
||||
}
|
||||
|
||||
const Tiptap = ({ value, noBorder, borderOnFocus, customClassName }: TiptapProps) => {
|
||||
const Tiptap = ({ onChange, setIsSubmitting, value, noBorder, borderOnFocus, customClassName }: TiptapProps) => {
|
||||
const editor = useEditor({
|
||||
editorProps: TiptapEditorProps,
|
||||
extensions: TiptapExtensions,
|
||||
// extensions: [
|
||||
// StarterKit,
|
||||
// Placeholder.configure({
|
||||
// placeholder: 'Description...',
|
||||
// })
|
||||
// ],
|
||||
content: value,
|
||||
onUpdate: async ({ editor }) => {
|
||||
setIsSubmitting(true);
|
||||
debouncedUpdates({ onChange, editor });
|
||||
}
|
||||
});
|
||||
|
||||
const debouncedUpdates = useDebouncedCallback(async ({ onChange, editor }) => {
|
||||
setTimeout(async () => {
|
||||
if (onChange) {
|
||||
onChange(editor.getJSON(), editor.getHTML());
|
||||
}
|
||||
}, 500);
|
||||
}, 1000);
|
||||
|
||||
const editorClassNames = `mt-2 p-3 relative focus:outline-none rounded-md focus:border-custom-border-200
|
||||
${noBorder ? '' : 'border border-custom-border-200'
|
||||
} ${borderOnFocus ? 'focus:border border-custom-border-200' : 'focus:border-0'
|
||||
|
Loading…
Reference in New Issue
Block a user