forked from github/plane
refactored editor to not require workspace slug
This commit is contained in:
parent
d639a0126d
commit
4298b0500e
@ -6,7 +6,10 @@
|
||||
"web",
|
||||
"space",
|
||||
"packages/editor/*",
|
||||
"packages/*"
|
||||
"packages/eslint-config-custom",
|
||||
"packages/tailwind-config-custom",
|
||||
"packages/tsconfig",
|
||||
"packages/ui"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "turbo run build",
|
||||
|
@ -1 +1 @@
|
||||
export type UploadImage = (workspaceSlug: string, formData: FormData) => Promise<any>;
|
||||
export type UploadImage = (file: File) => Promise<string>;
|
||||
|
@ -32,7 +32,6 @@ import "highlight.js/styles/github-dark.css";
|
||||
lowlight.registerLanguage("ts", ts);
|
||||
|
||||
export const TiptapExtensions = (
|
||||
workspaceSlug: string,
|
||||
uploadFile: UploadImage,
|
||||
deleteFile: DeleteImage,
|
||||
setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void
|
||||
@ -126,7 +125,7 @@ export const TiptapExtensions = (
|
||||
},
|
||||
includeChildren: true,
|
||||
}),
|
||||
SlashCommand(workspaceSlug, uploadFile, setIsSubmitting),
|
||||
SlashCommand(uploadFile, setIsSubmitting),
|
||||
TiptapUnderline,
|
||||
TextStyle,
|
||||
Color,
|
||||
|
@ -59,7 +59,6 @@ const Command = Extension.create({
|
||||
|
||||
const getSuggestionItems =
|
||||
(
|
||||
workspaceSlug: string,
|
||||
uploadFile: UploadImage,
|
||||
setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void
|
||||
) =>
|
||||
@ -185,7 +184,7 @@ const getSuggestionItems =
|
||||
if (input.files?.length) {
|
||||
const file = input.files[0];
|
||||
const pos = editor.view.state.selection.from;
|
||||
startImageUpload(file, editor.view, pos, workspaceSlug, uploadFile, setIsSubmitting);
|
||||
startImageUpload(file, editor.view, pos, uploadFile, setIsSubmitting);
|
||||
}
|
||||
};
|
||||
input.click();
|
||||
@ -351,13 +350,12 @@ const renderItems = () => {
|
||||
};
|
||||
|
||||
export const SlashCommand = (
|
||||
workspaceSlug: string,
|
||||
uploadFile: UploadImage,
|
||||
setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void
|
||||
) =>
|
||||
Command.configure({
|
||||
suggestion: {
|
||||
items: getSuggestionItems(workspaceSlug, uploadFile, setIsSubmitting),
|
||||
items: getSuggestionItems(uploadFile, setIsSubmitting),
|
||||
render: renderItems,
|
||||
},
|
||||
});
|
||||
|
@ -24,7 +24,6 @@ interface ITiptapEditor {
|
||||
onChange?: (json: any, html: string) => void;
|
||||
setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void;
|
||||
setShouldShowAlert?: (showAlert: boolean) => void;
|
||||
workspaceSlug: string;
|
||||
editable?: boolean;
|
||||
forwardedRef?: any;
|
||||
debouncedUpdatesEnabled?: boolean;
|
||||
@ -59,7 +58,6 @@ const TiptapEditor = ({
|
||||
uploadFile,
|
||||
deleteFile,
|
||||
noBorder,
|
||||
workspaceSlug,
|
||||
borderOnFocus,
|
||||
customClassName,
|
||||
forwardedRef,
|
||||
@ -69,9 +67,9 @@ const TiptapEditor = ({
|
||||
}: TiptapProps) => {
|
||||
const editor = useEditor({
|
||||
editable: editable ?? true,
|
||||
editorProps: TiptapEditorProps(workspaceSlug, uploadFile, setIsSubmitting),
|
||||
editorProps: TiptapEditorProps(uploadFile, setIsSubmitting),
|
||||
// @ts-expect-err
|
||||
extensions: TiptapExtensions(workspaceSlug, uploadFile, deleteFile, setIsSubmitting),
|
||||
extensions: TiptapExtensions(uploadFile, deleteFile, setIsSubmitting),
|
||||
content: (typeof value === "string" && value.trim() !== "") ? value : "<p></p>",
|
||||
onUpdate: async ({ editor }) => {
|
||||
// for instant feedback loop
|
||||
|
@ -57,7 +57,6 @@ export async function startImageUpload(
|
||||
file: File,
|
||||
view: EditorView,
|
||||
pos: number,
|
||||
workspaceSlug: string,
|
||||
uploadFile: UploadImage,
|
||||
setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void
|
||||
) {
|
||||
@ -83,11 +82,8 @@ export async function startImageUpload(
|
||||
view.dispatch(tr);
|
||||
};
|
||||
|
||||
if (!workspaceSlug) {
|
||||
return;
|
||||
}
|
||||
setIsSubmitting?.("submitting");
|
||||
const src = await UploadImageHandler(file, workspaceSlug, uploadFile);
|
||||
const src = await UploadImageHandler(file, uploadFile);
|
||||
const { schema } = view.state;
|
||||
pos = findPlaceholder(view.state, id);
|
||||
|
||||
@ -101,21 +97,13 @@ export async function startImageUpload(
|
||||
view.dispatch(transaction);
|
||||
}
|
||||
|
||||
const UploadImageHandler = (file: File, workspaceSlug: string,
|
||||
const UploadImageHandler = (file: File,
|
||||
uploadFile: UploadImage
|
||||
): Promise<string> => {
|
||||
if (!workspaceSlug) {
|
||||
return Promise.reject("Workspace slug is missing");
|
||||
}
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append("asset", file);
|
||||
formData.append("attributes", JSON.stringify({}));
|
||||
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const imageUrl = await uploadFile(workspaceSlug, formData)
|
||||
.then((response: { asset: string }) => response.asset);
|
||||
const imageUrl = await uploadFile(file)
|
||||
|
||||
const image = new Image();
|
||||
image.src = imageUrl;
|
||||
|
@ -4,7 +4,6 @@ import { startImageUpload } from "@/ui/plugins/upload-image";
|
||||
import { UploadImage } from "@/types/upload-image";
|
||||
|
||||
export function TiptapEditorProps(
|
||||
workspaceSlug: string,
|
||||
uploadFile: UploadImage,
|
||||
setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void
|
||||
): EditorProps {
|
||||
@ -37,7 +36,7 @@ export function TiptapEditorProps(
|
||||
event.preventDefault();
|
||||
const file = event.clipboardData.files[0];
|
||||
const pos = view.state.selection.from;
|
||||
startImageUpload(file, view, pos, workspaceSlug, uploadFile, setIsSubmitting);
|
||||
startImageUpload(file, view, pos, uploadFile, setIsSubmitting);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -61,7 +60,7 @@ export function TiptapEditorProps(
|
||||
});
|
||||
// here we deduct 1 from the pos or else the image will create an extra node
|
||||
if (coordinates) {
|
||||
startImageUpload(file, view, coordinates.pos - 1, workspaceSlug, uploadFile, setIsSubmitting);
|
||||
startImageUpload(file, view, coordinates.pos - 1, uploadFile, setIsSubmitting);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import {
|
||||
useEditor as useEditorCore,
|
||||
} from "@tiptap/react";
|
||||
} from "@tiptap/react";
|
||||
import { findTableAncestor } from "@/lib/utils";
|
||||
|
||||
export const useEditor = (props: any) => useEditorCore({
|
||||
|
@ -135,10 +135,9 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = ({
|
||||
|
||||
return (
|
||||
<TiptapEditor
|
||||
uploadFile={fileService.uploadFile}
|
||||
uploadFile={fileService.getUploadFileFunction(workspaceSlug)}
|
||||
deleteFile={fileService.deleteImage}
|
||||
value={value}
|
||||
workspaceSlug={workspaceSlug}
|
||||
debouncedUpdatesEnabled={true}
|
||||
setShouldShowAlert={setShowAlert}
|
||||
setIsSubmitting={setIsSubmitting}
|
||||
|
@ -34,13 +34,29 @@ class FileService extends APIService {
|
||||
}
|
||||
|
||||
async uploadFile(workspaceSlug: string, file: FormData): Promise<any> {
|
||||
return this.mediaUpload(`/api/workspaces/${workspaceSlug}/file-assets/`, file)
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/file-assets/`, file, {
|
||||
headers: {
|
||||
...this.getHeaders(),
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
getUploadFileFunction(workspaceSlug: string): (file: File) => Promise<string> {
|
||||
return async (file: File) => {
|
||||
const formData = new FormData();
|
||||
formData.append("asset", file);
|
||||
formData.append("attributes", JSON.stringify({}));
|
||||
|
||||
const data = await this.uploadFile(workspaceSlug, formData);
|
||||
return data.asset;
|
||||
};
|
||||
}
|
||||
|
||||
async deleteImage(assetUrlWithWorkspaceId: string): Promise<any> {
|
||||
return this.delete(`/api/workspaces/file-assets/${assetUrlWithWorkspaceId}/`)
|
||||
.then((response) => response?.status)
|
||||
@ -59,6 +75,7 @@ class FileService extends APIService {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async uploadUserFile(file: FormData): Promise<any> {
|
||||
return this.mediaUpload(`/api/users/file-assets/`, file)
|
||||
.then((response) => response?.data)
|
||||
|
Loading…
Reference in New Issue
Block a user