diff --git a/src/components/RichTextEditor.tsx b/src/components/RichTextEditor.tsx index e117be4b6..ada0afbca 100644 --- a/src/components/RichTextEditor.tsx +++ b/src/components/RichTextEditor.tsx @@ -29,6 +29,14 @@ import "tinymce/plugins/paste"; import "tinymce/plugins/help"; import "tinymce/plugins/code"; import "tinymce/plugins/fullscreen"; +import { useAtom } from "jotai"; +import { firebaseStorageAtom } from "@src/sources/ProjectSourceFirebase"; +import { projectScope } from "@src/atoms/projectScope"; +import { getDownloadURL, ref, uploadBytesResumable } from "firebase/storage"; +import { generateId } from "@src/utils/table"; +import { useSnackbar } from "notistack"; +import { ColumnConfig, TableRowRef } from "@src/types/table"; +import { IMAGE_MIME_TYPES } from "./fields/Image"; const Styles = styled("div", { shouldForwardProp: (prop) => prop !== "focus", @@ -136,6 +144,8 @@ export interface IRichTextEditorProps { id: string; onFocus?: () => void; onBlur?: () => void; + column: ColumnConfig; + _rowy_ref: TableRowRef; } export default function RichTextEditor({ @@ -145,10 +155,43 @@ export default function RichTextEditor({ id, onFocus, onBlur, + column, + _rowy_ref, }: IRichTextEditorProps) { const theme = useTheme(); const [focus, setFocus] = useState(false); + const [firebaseStorage] = useAtom(firebaseStorageAtom, projectScope); + const { enqueueSnackbar } = useSnackbar(); + + const handleImageUpload = (file: any) => { + return new Promise((resolve, reject) => { + const path = _rowy_ref.path; + const key = column.key; + const storageRef = ref( + firebaseStorage, + `${path}/${key}/${generateId()}-${file.name}` + ); + const uploadTask = uploadBytesResumable(storageRef, file, { + cacheControl: "public, max-age=31536000", + }); + uploadTask.on( + "state_changed", + null, + (error: any) => { + reject(error); + }, + () => { + getDownloadURL(uploadTask.snapshot.ref).then( + (downloadURL: string) => { + resolve(downloadURL); + } + ); + } + ); + }); + }; + return ( @@ -257,8 +300,37 @@ export default function RichTextEditor({ ], statusbar: false, toolbar: - "formatselect | bold italic forecolor | link | fullscreen | bullist numlist outdent indent | removeformat code | help", + "formatselect | bold italic forecolor | link | fullscreen | bullist numlist outdent indent | image | removeformat code | help", body_id: id, + file_picker_types: "image", + file_picker_callback: async (callback, value, meta) => { + const input = document.createElement("input"); + input.setAttribute("type", "file"); + input.setAttribute("accept", IMAGE_MIME_TYPES.join(",")); + + // Handle file selection + input.onchange = async () => { + const file = input && input.files && input.files[0]; + try { + const imageUrl = await handleImageUpload(file); // Upload the image to Firebase Storage + + // Create the image object to be inserted into the editor + const imageObj = { + src: imageUrl, + alt: file && file.name, + }; + + // Pass the image object to the callback function + callback(imageUrl, imageObj); + } catch (error) { + enqueueSnackbar("Error uploading image", { + variant: "error", + }); + } + }; + + input.click(); + }, }} value={value} onEditorChange={onChange} diff --git a/src/components/fields/RichText/SideDrawerField.tsx b/src/components/fields/RichText/SideDrawerField.tsx index 84a95f52c..c7aab0f42 100644 --- a/src/components/fields/RichText/SideDrawerField.tsx +++ b/src/components/fields/RichText/SideDrawerField.tsx @@ -8,6 +8,7 @@ export default function RichText({ onChange, onSubmit, disabled, + _rowy_ref, }: ISideDrawerFieldProps) { return ( ); }