diff --git a/src/components/Editor/QuillEditor.jsx b/src/components/Editor/QuillEditor.jsx index 1a7feb42..4a8756ab 100644 --- a/src/components/Editor/QuillEditor.jsx +++ b/src/components/Editor/QuillEditor.jsx @@ -24,7 +24,7 @@ const QuillEditor = ({ id, data, tutorial_id }) => { // This path in cloud firestore contains yjs documents storing content of a step // (actual data used to render is present in "steps" collection in the same doc) const basePath = ["tutorials", tutorial_id, "yjsStepDocs", id]; - let provider, binding, ydoc; + let provider, binding, ydoc, quill; const currentUserHandle = useSelector( ({ @@ -69,7 +69,7 @@ const QuillEditor = ({ id, data, tutorial_id }) => { container.removeChild(container.firstChild); } - const editor = new Quill(editorRef.current, { + quill = new Quill(editorRef.current, { modules: { cursors: true, toolbar: [ @@ -93,6 +93,32 @@ const QuillEditor = ({ id, data, tutorial_id }) => { ], history: { userOnly: true + }, + clipboard: { + matchers: [ + // Custom matcher to handle pasted image URLs + [ + Node.TEXT_NODE, + (node, delta) => { + const regex = /\!\[.*\]\((https?:\/\/[^\s]+)\)/; + const match = node.data.match(regex); + + if (match) { + const imageUrl = match[1]; + console.log("Image URL", imageUrl); + const Delta= Quill.import("delta") + const imageDelta = new Delta() + .retain(delta.length()) + .delete(node.data.length) + .insert({ image: imageUrl }, { alt: "Image" }); + + quill.updateContents(imageDelta, "silent"); + return true; + } + return false; + } + ] + ] } }, placeholder: "Start collaborating...", @@ -104,7 +130,7 @@ const QuillEditor = ({ id, data, tutorial_id }) => { // color: getColor(currentUserHandle) // }); - binding = new QuillBinding(ytext, editor, provider.awareness); + binding = new QuillBinding(ytext, quill, provider.awareness); } catch (err) { console.log(err); } diff --git a/src/components/Tutorials/subComps/ImageDrawer.jsx b/src/components/Tutorials/subComps/ImageDrawer.jsx index 6de8e472..1e3f2056 100644 --- a/src/components/Tutorials/subComps/ImageDrawer.jsx +++ b/src/components/Tutorials/subComps/ImageDrawer.jsx @@ -50,54 +50,44 @@ const ImageDrawer = ({ onClose, visible, owner, tutorial_id, imageURLs }) => { }) => deleting_error ); + const [uploadSnackbarOpen, setUploadSnackbarOpen] = React.useState(false); + const [uploadErrorSnackbarOpen, setUploadErrorSnackbarOpen] = + React.useState(false); + const [deleteSnackbarOpen, setDeleteSnackbarOpen] = React.useState(false); + const [deleteErrorSnackbarOpen, setDeleteErrorSnackbarOpen] = + React.useState(false); + useEffect(() => { if (uploading === false && uploading_error === false) { - ; + setUploadSnackbarOpen(true); } else if (uploading === false && uploading_error) { - ; + setUploadErrorSnackbarOpen(true); } }, [uploading, uploading_error]); useEffect(() => { if (deleting === false && deleting_error === false) { - ; + setDeleteSnackbarOpen(true); } else if (deleting === false && deleting_error) { - ; + setDeleteErrorSnackbarOpen(true); } }, [deleting, deleting_error]); + const handleSnackbarClose = type => { + switch (type) { + case "upload": + setUploadSnackbarOpen(false); + setUploadErrorSnackbarOpen(false); + break; + case "delete": + setDeleteSnackbarOpen(false); + setDeleteErrorSnackbarOpen(false); + break; + default: + break; + } + }; + useEffect(() => { clearTutorialImagesReducer()(dispatch); return () => { @@ -105,17 +95,15 @@ const ImageDrawer = ({ onClose, visible, owner, tutorial_id, imageURLs }) => { }; }, [dispatch]); - const props = { - name: "file", - multiple: true, - beforeUpload(file, files) { - uploadTutorialImages(owner, tutorial_id, files)( - firebase, - firestore, - dispatch - ); - return false; - } + const beforeUpload = async files => { + console.log("Image Upload Started!!!") + await uploadTutorialImages(owner, tutorial_id, files)( + firebase, + firestore, + dispatch + ); + console.log("Uploaded the Images"); + return false; }; const deleteFile = (name, url) => @@ -127,85 +115,129 @@ const ImageDrawer = ({ onClose, visible, owner, tutorial_id, imageURLs }) => { )(firebase, firestore, dispatch); return ( - -
- - - {uploading ? ( - <> - Please wait... -

Uploading image(s)...

- - ) : ( - <> -

- -

-

- Click or drag images to here to upload -

- - )} -
- {imageURLs && - imageURLs.length > 0 && - imageURLs.map((image, i) => ( - - - - - -

{image.name}

- - ( - - )} - > - - - - + <> + +
+ + beforeUpload(event.target.files)} + /> + {uploading ? ( + <> + Please wait... +

Uploading image(s)...

+ + ) : ( + <> +

+ +

+

+ Click or drag images to here to upload +

+ + )} +
+ {imageURLs && + imageURLs.length > 0 && + imageURLs.map((image, i) => ( + + + + + +

{image.name}

+ + ( + + )} + > + + + + +
- - ))} -
-
+ ))} +
+
+ handleSnackbarClose("upload")} + message="Image Uploaded successfully...." + /> + handleSnackbarClose("upload")} + message={uploading_error} + /> + handleSnackbarClose("delete")} + message="Deleted Successfully...." + /> + handleSnackbarClose("delete")} + message={deleting_error} + /> + ); }; diff --git a/src/store/actions/authActions.js b/src/store/actions/authActions.js index 5b748dee..668be900 100644 --- a/src/store/actions/authActions.js +++ b/src/store/actions/authActions.js @@ -179,9 +179,12 @@ export const resendVerifyEmail = email => async dispatch => { export const checkUserHandleExists = userHandle => async firebase => { try { const handle = await firebase - .ref(`/cl_user_handle/${userHandle}`) - .once("value"); - return handle.exists(); + .firestore() + .collection("cl_user") + .doc(userHandle) + .get(); + console.log("User Handle",handle) + return handle.exists; } catch (e) { throw e.message; } @@ -195,7 +198,7 @@ export const checkOrgHandleExists = orgHandle => async firebase => { .doc(orgHandle) .get(); - console.log(organizationHandle); + console.log("Organization Handle",organizationHandle); return organizationHandle.exists; } catch (e) { throw e.message; diff --git a/src/store/actions/tutorialsActions.js b/src/store/actions/tutorialsActions.js index 7d273c1d..1689a816 100644 --- a/src/store/actions/tutorialsActions.js +++ b/src/store/actions/tutorialsActions.js @@ -173,9 +173,9 @@ export const createTutorial = } }; -const checkUserOrOrgHandle = handle => async firestore => { - const userHandleExists = await checkUserHandleExists(handle)(firestore); - const orgHandleExists = await checkOrgHandleExists(handle)(firestore); +const checkUserOrOrgHandle = handle => async firebase => { + const userHandleExists = await checkUserHandleExists(handle)(firebase); + const orgHandleExists = await checkOrgHandleExists(handle)(firebase); if (userHandleExists && !orgHandleExists) { return "user"; @@ -388,8 +388,8 @@ export const uploadTutorialImages = (owner, tutorial_id, files) => async (firebase, firestore, dispatch) => { try { dispatch({ type: actions.TUTORIAL_IMAGE_UPLOAD_START }); - const type = await checkUserOrOrgHandle(owner)(firestore); - + const type = await checkUserOrOrgHandle(owner)(firebase); + const storagePath = `tutorials/${type}/${owner}/${tutorial_id}`; const dbPath = `tutorials`; await firebase.uploadFiles(storagePath, files, dbPath, {