gregfenton

Firebase and Firestore and Dropzone

Apr 7th, 2020
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import React, { Fragment, useState, useEffect } from "react";
  2. import { Segment, Header, Divider, Grid, Button } from "semantic-ui-react";
  3. import { connect } from "react-redux";
  4. import { compose } from "redux";
  5. import { toastr } from "react-redux-toastr";
  6. import DropzoneInput from "./DropzoneInputs";
  7. import CropperInput from "./CropperInput";
  8.  
  9. import { firestoreConnect, withFirestore } from "react-redux-firebase";
  10.  
  11. import {
  12.   uploadProfileImage,
  13.   deletePhoto,
  14.   setMainPhoto
  15. } from "../../userActions";
  16. import UserPhotos from "./UserPhotos";
  17.  
  18. import * as MiscConstants from "../../../../app/common/constants/misc";
  19.  
  20. const query = ({ auth }) => {
  21.   return [
  22.     {
  23.       collection: "users",
  24.       doc: auth.uid,
  25.       subcollections: [{ collection: "photos" }],
  26.       storeAs: "photos"
  27.     }
  28.   ];
  29. };
  30.  
  31. const actions = {
  32.   uploadProfileImage,
  33.   deletePhoto,
  34.   setMainPhoto
  35. };
  36.  
  37. const mapState = state => ({
  38.   auth: state.firebase.auth,
  39.   profile: state.firebase.profile,
  40.   photos: state.firestore.ordered.photos,
  41.   loading: state.async.loading
  42. });
  43.  
  44. const PhotosPage = ({
  45.   uploadProfileImage,
  46.   photos,
  47.   profile,
  48.   loading,
  49.   deletePhoto,
  50.   setMainPhoto,
  51.   firebase,
  52.   firestore
  53. }) => {
  54.   const [files, setFiles] = useState([]);
  55.   const [image, setImage] = useState(null);
  56.  
  57.   useEffect(() => {
  58.     return () => {
  59.       files.forEach(file => URL.revokeObjectURL(file.preview));
  60.     };
  61.   }, [files]);
  62.  
  63.   const handleUploadImage = async () => {
  64.     try {
  65.       await uploadProfileImage(firebase, firestore, image, files[0].name);
  66.       handleCancelCrop();
  67.       toastr.success(
  68.         MiscConstants.LABEL_SUCCESS,
  69.         MiscConstants.LABEL_PHOTO_UPLOADED
  70.       );
  71.     } catch (error) {
  72.       console.log(error);
  73.       toastr.error(
  74.         MiscConstants.LABEL_OOPS,
  75.         MiscConstants.LABEL_SOMETHING_WENT_WRONG
  76.       );
  77.     }
  78.   };
  79.  
  80.   const handleCancelCrop = () => {
  81.     setFiles([]);
  82.     setImage(null);
  83.   };
  84.  
  85.   const handleDeletePhoto = async photo => {
  86.     try {
  87.       await deletePhoto(photo);
  88.     } catch (error) {
  89.       toastr.error(MiscConstants.LABEL_OOPS, error.message);
  90.     }
  91.   };
  92.  
  93.   const handleSetMainPhoto = async photo => {
  94.     try {
  95.       await setMainPhoto(photo);
  96.     } catch (error) {
  97.       toastr.error(MiscConstants.LABEL_OOPS, error.message);
  98.     }
  99.   };
  100.  
  101.   return (
  102.     <Segment>
  103.       <Header dividing size='large' content='Your Photos' />
  104.       <Grid>
  105.         <Grid.Row />
  106.         <Grid.Column width={4}>
  107.           <Header
  108.             color='teal'
  109.             sub
  110.             content={MiscConstants.LABEL_STEP1_ADD_PHOTO}
  111.           />
  112.           <DropzoneInput setFiles={setFiles} />
  113.         </Grid.Column>
  114.         <Grid.Column width={1} />
  115.         <Grid.Column width={4}>
  116.           <Header
  117.             sub
  118.             color='teal'
  119.             content={MiscConstants.LABEL_STEP2_RESIZE_PHOTO}
  120.           />
  121.           {files.length > 0 && (
  122.             <CropperInput setImage={setImage} imagePreview={files[0].preview} />
  123.           )}
  124.         </Grid.Column>
  125.         <Grid.Column width={1} />
  126.         <Grid.Column width={4}>
  127.           <Header
  128.             sub
  129.             color='teal'
  130.             content={MiscConstants.LABEL_STEP3_PREVIEW_AND_UPLOAD}
  131.           />
  132.           {files.length > 0 && (
  133.             <Fragment>
  134.               <div
  135.                 className='img-preview'
  136.                 style={{
  137.                   minHeight: "200px",
  138.                   minWidth: "200px",
  139.                   overflow: "hidden"
  140.                 }}
  141.               />
  142.               <Button.Group>
  143.                 <Button
  144.                   loading={loading}
  145.                   onClick={handleUploadImage}
  146.                   style={{ width: "100px" }}
  147.                   positive
  148.                   icon='check'
  149.                 />
  150.                 <Button
  151.                   disabled={loading}
  152.                   onClick={handleCancelCrop}
  153.                   style={{ width: "100px" }}
  154.                   icon='close'
  155.                 />
  156.               </Button.Group>
  157.             </Fragment>
  158.           )}
  159.         </Grid.Column>
  160.       </Grid>
  161.  
  162.       <Divider />
  163.       <UserPhotos
  164.         photos={photos}
  165.         profile={profile}
  166.         deletePhoto={handleDeletePhoto}
  167.         setMainPhoto={handleSetMainPhoto}
  168.         loading={loading}
  169.       />
  170.     </Segment>
  171.   );
  172. };
  173.  
  174. export default withFirestore(compose(
  175.   connect(mapState, actions),
  176.   firestoreConnect(auth => query(auth))
  177. )(PhotosPage));
  178.  
  179.  
  180. //
  181. // AND THIS CODE COMES FROM ../../userActions.js
  182. //
  183. export const uploadProfileImage = (firebase, firestore, file, fileName) => async (
  184.   dispatch,
  185.   getState,
  186.   { getFirebase, getFirestore }
  187. ) => {
  188.   const imageName = cuid();
  189.   const user = firebase.auth().currentUser;
  190.   const path = `${user.uid}/user_images`;
  191.   const options = {
  192.     name: imageName
  193.   };
  194.   try {
  195.     dispatch(asyncActionStart());
  196.  
  197.     // upload the file to firebase storage
  198.     let uploadedFile = await firebase.uploadFile(path, file, null, options);
  199.  
  200.     // get URL of the image
  201.     let downloadURL = await uploadedFile.uploadTaskSnapshot.ref.getDownloadURL();
  202.  
  203.     // get the "document" for the user record
  204.     let userDoc = await firestore.get(`users/${user.uid}`);
  205.  
  206.     // check if user has photo, if not update profile
  207.     if (!userDoc.data().photoURL) {
  208.       await firebase.updateProfile({
  209.         photoURL: downloadURL
  210.       });
  211.       await user.updateProfile({
  212.         photoURL: downloadURL
  213.       });
  214.     }
  215.  
  216.     // add image to firestore
  217.     await firestore.add(
  218.       {
  219.         collection: "users",
  220.         doc: user.uid,
  221.         subcollections: [{ collection: "photos" }]
  222.       },
  223.       {
  224.         name: imageName,
  225.         url: downloadURL
  226.       }
  227.     );
  228.  
  229.     dispatch(asyncActionFinish());
  230.   } catch (error) {
  231.     console.log(error);
  232.     dispatch(asyncActionError());
  233.   }
  234. };
Add Comment
Please, Sign In to add comment