forked from github/plane
added better syncing of "Saved" state of editor and Image uploads
This commit is contained in:
parent
aa1812b9e3
commit
aa5c118616
@ -75,6 +75,8 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = ({
|
|||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
setIsSubmitting("saved");
|
setIsSubmitting("saved");
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
} else if (isSubmitting === "submitting") {
|
||||||
|
setShowAlert(true);
|
||||||
}
|
}
|
||||||
}, [isSubmitting, setShowAlert]);
|
}, [isSubmitting, setShowAlert]);
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ import isValidHttpUrl from "../bubble-menu/utils/link-validator";
|
|||||||
|
|
||||||
lowlight.registerLanguage("ts", ts);
|
lowlight.registerLanguage("ts", ts);
|
||||||
|
|
||||||
export const TiptapExtensions = (workspaceSlug: string) => [
|
export const TiptapExtensions = (workspaceSlug: string, setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void) => [
|
||||||
StarterKit.configure({
|
StarterKit.configure({
|
||||||
bulletList: {
|
bulletList: {
|
||||||
HTMLAttributes: {
|
HTMLAttributes: {
|
||||||
@ -112,7 +112,7 @@ export const TiptapExtensions = (workspaceSlug: string) => [
|
|||||||
UniqueID.configure({
|
UniqueID.configure({
|
||||||
types: ["image"],
|
types: ["image"],
|
||||||
}),
|
}),
|
||||||
SlashCommand(workspaceSlug),
|
SlashCommand(workspaceSlug, setIsSubmitting),
|
||||||
TiptapUnderline,
|
TiptapUnderline,
|
||||||
TextStyle,
|
TextStyle,
|
||||||
Color,
|
Color,
|
||||||
|
@ -39,8 +39,8 @@ const Tiptap = (props: ITiptapRichTextEditor) => {
|
|||||||
|
|
||||||
const editor = useEditor({
|
const editor = useEditor({
|
||||||
editable: editable ?? true,
|
editable: editable ?? true,
|
||||||
editorProps: TiptapEditorProps(workspaceSlug),
|
editorProps: TiptapEditorProps(workspaceSlug, setIsSubmitting),
|
||||||
extensions: TiptapExtensions(workspaceSlug),
|
extensions: TiptapExtensions(workspaceSlug, setIsSubmitting),
|
||||||
content: value,
|
content: value,
|
||||||
onUpdate: async ({ editor }) => {
|
onUpdate: async ({ editor }) => {
|
||||||
// for instant feedback loop
|
// for instant feedback loop
|
||||||
|
@ -14,7 +14,6 @@ const TrackImageDeletionPlugin = () =>
|
|||||||
const removedImages: ProseMirrorNode[] = [];
|
const removedImages: ProseMirrorNode[] = [];
|
||||||
|
|
||||||
oldState.doc.descendants((oldNode, oldPos) => {
|
oldState.doc.descendants((oldNode, oldPos) => {
|
||||||
console.log(oldNode.type.name)
|
|
||||||
if (oldNode.type.name !== 'image') return;
|
if (oldNode.type.name !== 'image') return;
|
||||||
|
|
||||||
if (!newState.doc.resolve(oldPos).parent) return;
|
if (!newState.doc.resolve(oldPos).parent) return;
|
||||||
|
@ -57,7 +57,7 @@ function findPlaceholder(state: EditorState, id: {}) {
|
|||||||
return found.length ? found[0].from : null;
|
return found.length ? found[0].from : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function startImageUpload(file: File, view: EditorView, pos: number, workspaceSlug: string) {
|
export async function startImageUpload(file: File, view: EditorView, pos: number, workspaceSlug: string, setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void) {
|
||||||
if (!file.type.includes("image/")) {
|
if (!file.type.includes("image/")) {
|
||||||
return;
|
return;
|
||||||
} else if (file.size / 1024 / 1024 > 20) {
|
} else if (file.size / 1024 / 1024 > 20) {
|
||||||
@ -85,6 +85,7 @@ export async function startImageUpload(file: File, view: EditorView, pos: number
|
|||||||
if (!workspaceSlug) {
|
if (!workspaceSlug) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
setIsSubmitting?.("submitting")
|
||||||
const src = await UploadImageHandler(file, workspaceSlug);
|
const src = await UploadImageHandler(file, workspaceSlug);
|
||||||
const { schema } = view.state;
|
const { schema } = view.state;
|
||||||
pos = findPlaceholder(view.state, id);
|
pos = findPlaceholder(view.state, id);
|
||||||
@ -104,7 +105,6 @@ const UploadImageHandler = (file: File, workspaceSlug: string): Promise<string>
|
|||||||
return Promise.reject("Workspace slug is missing");
|
return Promise.reject("Workspace slug is missing");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
console.log("in here",workspaceSlug)
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("asset", file);
|
formData.append("asset", file);
|
||||||
formData.append("attributes", JSON.stringify({}));
|
formData.append("attributes", JSON.stringify({}));
|
||||||
@ -116,7 +116,6 @@ const UploadImageHandler = (file: File, workspaceSlug: string): Promise<string>
|
|||||||
|
|
||||||
const image = new Image();
|
const image = new Image();
|
||||||
image.src = imageUrl;
|
image.src = imageUrl;
|
||||||
console.log("image uploaded", imageUrl)
|
|
||||||
image.onload = () => {
|
image.onload = () => {
|
||||||
resolve(imageUrl);
|
resolve(imageUrl);
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { EditorProps } from "@tiptap/pm/view";
|
import { EditorProps } from "@tiptap/pm/view";
|
||||||
import { startImageUpload } from "./plugins/upload-image";
|
import { startImageUpload } from "./plugins/upload-image";
|
||||||
|
|
||||||
export function TiptapEditorProps(workspaceSlug: string): EditorProps {
|
export function TiptapEditorProps(workspaceSlug: string, setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void): EditorProps {
|
||||||
return {
|
return {
|
||||||
attributes: {
|
attributes: {
|
||||||
class: `prose prose-brand max-w-full prose-headings:font-display font-default focus:outline-none`,
|
class: `prose prose-brand max-w-full prose-headings:font-display font-default focus:outline-none`,
|
||||||
@ -26,8 +26,7 @@ export function TiptapEditorProps(workspaceSlug: string): EditorProps {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const file = event.clipboardData.files[0];
|
const file = event.clipboardData.files[0];
|
||||||
const pos = view.state.selection.from;
|
const pos = view.state.selection.from;
|
||||||
|
startImageUpload(file, view, pos, workspaceSlug, setIsSubmitting);
|
||||||
startImageUpload(file, view, pos, workspaceSlug);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -47,7 +46,7 @@ export function TiptapEditorProps(workspaceSlug: string): EditorProps {
|
|||||||
});
|
});
|
||||||
// here we deduct 1 from the pos or else the image will create an extra node
|
// here we deduct 1 from the pos or else the image will create an extra node
|
||||||
if (coordinates) {
|
if (coordinates) {
|
||||||
startImageUpload(file, view, coordinates.pos - 1, workspaceSlug);
|
startImageUpload(file, view, coordinates.pos - 1, workspaceSlug, setIsSubmitting);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ const Command = Extension.create({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const getSuggestionItems = (workspaceSlug: string) => ({ query }: { query: string }) =>
|
const getSuggestionItems = (workspaceSlug: string, setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void) => ({ query }: { query: string }) =>
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
title: "Text",
|
title: "Text",
|
||||||
@ -163,7 +163,7 @@ const getSuggestionItems = (workspaceSlug: string) => ({ query }: { query: strin
|
|||||||
if (input.files?.length) {
|
if (input.files?.length) {
|
||||||
const file = input.files[0];
|
const file = input.files[0];
|
||||||
const pos = editor.view.state.selection.from;
|
const pos = editor.view.state.selection.from;
|
||||||
startImageUpload(file, editor.view, pos, workspaceSlug);
|
startImageUpload(file, editor.view, pos, workspaceSlug, setIsSubmitting);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
input.click();
|
input.click();
|
||||||
@ -328,10 +328,10 @@ const renderItems = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SlashCommand = (workspaceSlug: string) =>
|
export const SlashCommand = (workspaceSlug: string, setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void) =>
|
||||||
Command.configure({
|
Command.configure({
|
||||||
suggestion: {
|
suggestion: {
|
||||||
items: getSuggestionItems(workspaceSlug),
|
items: getSuggestionItems(workspaceSlug, setIsSubmitting),
|
||||||
render: renderItems,
|
render: renderItems,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -135,7 +135,7 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 45%;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
Loading…
Reference in New Issue
Block a user