From 07e69a3b7686cd00667b5302cdf4da70e19f696a Mon Sep 17 00:00:00 2001
From: Gana016 <jayam.ganapathi12@gmail.com>
Date: Thu, 1 Apr 2021 14:11:16 +0530
Subject: [PATCH] dropzone done

---
 digital-course-file/package-lock.json    |  70 ++++++-
 digital-course-file/package.json         |   1 +
 digital-course-file/src/user/Dropzone.js | 221 +++++++++++++++++++++++
 digital-course-file/src/user/Hero.js     |   4 +
 4 files changed, 294 insertions(+), 2 deletions(-)
 create mode 100644 digital-course-file/src/user/Dropzone.js

diff --git a/digital-course-file/package-lock.json b/digital-course-file/package-lock.json
index 79f64b6..926d82a 100644
--- a/digital-course-file/package-lock.json
+++ b/digital-course-file/package-lock.json
@@ -24,6 +24,7 @@
         "react-contexify": "^5.0.0",
         "react-copy-to-clipboard": "^5.0.3",
         "react-dom": "^17.0.1",
+        "react-dropzone": "^11.3.2",
         "react-github-login-button": "^1.0.1",
         "react-google-button": "^0.7.2",
         "react-icons": "^4.2.0",
@@ -1960,6 +1961,7 @@
         "jest-resolve": "^26.6.2",
         "jest-util": "^26.6.2",
         "jest-worker": "^26.6.2",
+        "node-notifier": "^8.0.0",
         "slash": "^3.0.0",
         "source-map": "^0.6.0",
         "string-length": "^4.0.1",
@@ -3917,6 +3919,14 @@
         "node": ">= 4.5.0"
       }
     },
+    "node_modules/attr-accept": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.2.tgz",
+      "integrity": "sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg==",
+      "engines": {
+        "node": ">=4"
+      }
+    },
     "node_modules/autoprefixer": {
       "version": "9.8.6",
       "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz",
@@ -6932,7 +6942,8 @@
         "esprima": "^4.0.1",
         "estraverse": "^4.2.0",
         "esutils": "^2.0.2",
-        "optionator": "^0.8.1"
+        "optionator": "^0.8.1",
+        "source-map": "~0.6.1"
       },
       "bin": {
         "escodegen": "bin/escodegen.js",
@@ -8062,6 +8073,17 @@
         "node": ">= 10.13.0"
       }
     },
+    "node_modules/file-selector": {
+      "version": "0.2.4",
+      "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.2.4.tgz",
+      "integrity": "sha512-ZDsQNbrv6qRi1YTDOEWzf5J2KjZ9KMI1Q2SGeTkCJmNNW25Jg4TW4UMcmoqcg4WrAyKRcpBXdbWRxkfrOzVRbA==",
+      "dependencies": {
+        "tslib": "^2.0.3"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
     "node_modules/file-uri-to-path": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
@@ -10726,6 +10748,7 @@
         "@types/node": "*",
         "anymatch": "^3.0.3",
         "fb-watchman": "^2.0.0",
+        "fsevents": "^2.1.2",
         "graceful-fs": "^4.2.4",
         "jest-regex-util": "^26.0.0",
         "jest-serializer": "^26.6.2",
@@ -15676,6 +15699,22 @@
         "scheduler": "^0.20.1"
       }
     },
+    "node_modules/react-dropzone": {
+      "version": "11.3.2",
+      "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-11.3.2.tgz",
+      "integrity": "sha512-Z0l/YHcrNK1r85o6RT77Z5XgTARmlZZGfEKBl3tqTXL9fZNQDuIdRx/J0QjvR60X+yYu26dnHeaG2pWU+1HHvw==",
+      "dependencies": {
+        "attr-accept": "^2.2.1",
+        "file-selector": "^0.2.2",
+        "prop-types": "^15.7.2"
+      },
+      "engines": {
+        "node": ">= 10"
+      },
+      "peerDependencies": {
+        "react": ">= 16.8"
+      }
+    },
     "node_modules/react-error-overlay": {
       "version": "6.0.9",
       "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz",
@@ -15837,6 +15876,7 @@
         "eslint-webpack-plugin": "^2.1.0",
         "file-loader": "6.1.1",
         "fs-extra": "^9.0.1",
+        "fsevents": "^2.1.3",
         "html-webpack-plugin": "4.5.0",
         "identity-obj-proxy": "3.0.0",
         "jest": "26.6.0",
@@ -19185,8 +19225,10 @@
       "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
       "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==",
       "dependencies": {
+        "chokidar": "^3.4.1",
         "graceful-fs": "^4.1.2",
-        "neo-async": "^2.5.0"
+        "neo-async": "^2.5.0",
+        "watchpack-chokidar2": "^2.0.1"
       },
       "optionalDependencies": {
         "chokidar": "^3.4.1",
@@ -19683,6 +19725,7 @@
         "anymatch": "^2.0.0",
         "async-each": "^1.0.1",
         "braces": "^2.3.2",
+        "fsevents": "^1.2.7",
         "glob-parent": "^3.1.0",
         "inherits": "^2.0.3",
         "is-binary-path": "^1.0.0",
@@ -24469,6 +24512,11 @@
       "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
       "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg=="
     },
+    "attr-accept": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.2.tgz",
+      "integrity": "sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg=="
+    },
     "autoprefixer": {
       "version": "9.8.6",
       "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz",
@@ -27980,6 +28028,14 @@
         }
       }
     },
+    "file-selector": {
+      "version": "0.2.4",
+      "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.2.4.tgz",
+      "integrity": "sha512-ZDsQNbrv6qRi1YTDOEWzf5J2KjZ9KMI1Q2SGeTkCJmNNW25Jg4TW4UMcmoqcg4WrAyKRcpBXdbWRxkfrOzVRbA==",
+      "requires": {
+        "tslib": "^2.0.3"
+      }
+    },
     "file-uri-to-path": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
@@ -34184,6 +34240,16 @@
         "scheduler": "^0.20.1"
       }
     },
+    "react-dropzone": {
+      "version": "11.3.2",
+      "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-11.3.2.tgz",
+      "integrity": "sha512-Z0l/YHcrNK1r85o6RT77Z5XgTARmlZZGfEKBl3tqTXL9fZNQDuIdRx/J0QjvR60X+yYu26dnHeaG2pWU+1HHvw==",
+      "requires": {
+        "attr-accept": "^2.2.1",
+        "file-selector": "^0.2.2",
+        "prop-types": "^15.7.2"
+      }
+    },
     "react-error-overlay": {
       "version": "6.0.9",
       "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz",
diff --git a/digital-course-file/package.json b/digital-course-file/package.json
index 5c03f0e..9c11193 100644
--- a/digital-course-file/package.json
+++ b/digital-course-file/package.json
@@ -20,6 +20,7 @@
     "react-contexify": "^5.0.0",
     "react-copy-to-clipboard": "^5.0.3",
     "react-dom": "^17.0.1",
+    "react-dropzone": "^11.3.2",
     "react-github-login-button": "^1.0.1",
     "react-google-button": "^0.7.2",
     "react-icons": "^4.2.0",
diff --git a/digital-course-file/src/user/Dropzone.js b/digital-course-file/src/user/Dropzone.js
new file mode 100644
index 0000000..1e42498
--- /dev/null
+++ b/digital-course-file/src/user/Dropzone.js
@@ -0,0 +1,221 @@
+import React, { useState, useEffect } from 'react'
+import { Button, Modal, ModalFooter } from 'react-bootstrap'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { faHandRock } from '@fortawesome/free-solid-svg-icons'
+import { database } from '../fire.js'
+import firebase from 'firebase'
+import { Link } from 'react-router-dom'
+import { useDropzone } from 'react-dropzone'
+import { v4 as uuidV4 } from 'uuid'
+import { ProgressBar, Toast } from 'react-bootstrap'
+import { storage } from '../fire.js'
+import { ROOT_FOLDER } from '../hooks/useFolder'
+import ReactDOM from 'react-dom'
+
+// {currentFolder}
+export default function Dropzone({ currentFolder }) {
+  const [open, setOpen] = useState(false)
+  const temp_parent = '' + currentFolder.parentId
+  const [path, setpath] = useState(``)
+  const { acceptedFiles, getRootProps, getInputProps } = useDropzone()
+  const [uploadingFiles, setUploadingFiles] = useState([])
+
+  const files = acceptedFiles.map((file) => (
+    <li key={file.path}>
+      {file.path} - {file.size} bytes
+    </li>
+  ))
+
+  function openModal() {
+    {
+      temp_parent != 'null' && setpath(`/folder/${temp_parent}`)
+    }
+    setOpen(true)
+  }
+
+  function closeModal() {
+    setOpen(false)
+    acceptedFiles.length = 0
+  }
+
+  function uploadinghelp() {
+    const files = acceptedFiles.map((file) => handleUpload(file))
+    closeModal()
+  }
+
+  function handleUpload(file) {
+    if (currentFolder == null || file == null) return
+
+    const id = uuidV4()
+    setUploadingFiles((prevUploadingFiles) => [
+      ...prevUploadingFiles,
+      { id: id, name: file.name, progress: 0, error: false },
+    ])
+    const filePath =
+      currentFolder === ROOT_FOLDER
+        ? `${currentFolder.path.join('/')}/${file.name}`
+        : `${currentFolder.path.join('/')}/${currentFolder.name}/${file.name}`
+
+    const uploadTask = storage
+      .ref(`/files/${firebase.auth().currentUser.uid}/${filePath}`)
+      .put(file)
+
+    uploadTask.on(
+      'state_changed',
+      (snapshot) => {
+        const progress = snapshot.bytesTransferred / snapshot.totalBytes
+        setUploadingFiles((prevUploadingFiles) => {
+          return prevUploadingFiles.map((uploadFile) => {
+            if (uploadFile.id === id) {
+              return { ...uploadFile, progress: progress }
+            }
+
+            return uploadFile
+          })
+        })
+      },
+      () => {
+        setUploadingFiles((prevUploadingFiles) => {
+          return prevUploadingFiles.map((uploadFile) => {
+            if (uploadFile.id === id) {
+              return { ...uploadFile, error: true }
+            }
+            return uploadFile
+          })
+        })
+      },
+      () => {
+        setUploadingFiles((prevUploadingFiles) => {
+          return prevUploadingFiles.filter((uploadFile) => {
+            return uploadFile.id !== id
+          })
+        })
+
+        uploadTask.snapshot.ref.getDownloadURL().then((url) => {
+          database.files
+            .where('name', '==', file.name)
+            .where('userId', '==', firebase.auth().currentUser.uid)
+            .where('folderId', '==', currentFolder.id)
+            .get()
+            .then((existingFiles) => {
+              const existingFile = existingFiles.docs[0]
+              if (existingFile) {
+                existingFile.ref.update({ url: url })
+              } else {
+                database.files.add({
+                  url: url,
+                  name: file.name,
+                  createdAt: database.getTime(),
+                  folderId: currentFolder.id,
+                  userId: firebase.auth().currentUser.uid,
+                })
+              }
+            })
+        })
+      }
+    )
+  }
+
+  return (
+    <>
+      <Button
+        name='drag-and-drop'
+        style={{ maxWidth: '80px' }}
+        className='mr-2'
+        onClick={openModal}
+        variant='warning'
+        size='sm'
+      >
+        <FontAwesomeIcon icon={faHandRock} />
+      </Button>
+      <Modal
+        show={open}
+        onHide={closeModal}
+        size='xl'
+        aria-labelledby='example-custom-modal-styling-title'
+        centered
+        dialogClassName='modal-90w'
+      >
+        <Modal.Body>
+          {/* <div>
+                  Drag and Drop files Here!!  
+              </div> */}
+
+          <section className='container'>
+            <div {...getRootProps({ className: 'dropzone' })}>
+              <input {...getInputProps()} />
+              <p>Drag 'n' drop some files here, or click to select files</p>
+            </div>
+            <aside>
+              <ul>{files}</ul>
+            </aside>
+          </section>
+        </Modal.Body>
+        <ModalFooter>
+          <Button
+            name='del_confirm'
+            style={{ float: 'left' }}
+            className='mr-2'
+            variant='primary'
+            onClick={uploadinghelp}
+            as={Link}
+          >
+            Done
+          </Button>
+          <Button
+            style={{ maxWidth: '80px' }}
+            className='mr-2'
+            variant='danger'
+            onClick={closeModal}
+          >
+            Cancel
+          </Button>
+        </ModalFooter>
+      </Modal>
+      {uploadingFiles.length > 0 &&
+        ReactDOM.createPortal(
+          <div
+            style={{
+              position: 'absolute',
+              bottom: '4rem',
+              right: '2rem',
+              maxWidth: '250px',
+            }}
+          >
+            {uploadingFiles.map((file) => (
+              <Toast
+                key={file.id}
+                onClose={() => {
+                  setUploadingFiles((prevUploadingFiles) => {
+                    return prevUploadingFiles.filter((uploadFile) => {
+                      return uploadFile.id !== file.id
+                    })
+                  })
+                }}
+              >
+                <Toast.Header
+                  closeButton={file.error}
+                  className='text-truncate w-100 d-block'
+                >
+                  {file.name}
+                </Toast.Header>
+                <Toast.Body>
+                  <ProgressBar
+                    animated={!file.error}
+                    variant={file.error ? 'danger' : 'primary'}
+                    now={file.error ? 100 : file.progress * 100}
+                    label={
+                      file.error
+                        ? 'Error'
+                        : `${Math.round(file.progress * 100)}%`
+                    }
+                  />
+                </Toast.Body>
+              </Toast>
+            ))}
+          </div>,
+          document.body
+        )}
+    </>
+  )
+}
diff --git a/digital-course-file/src/user/Hero.js b/digital-course-file/src/user/Hero.js
index 9f6432a..c91969c 100644
--- a/digital-course-file/src/user/Hero.js
+++ b/digital-course-file/src/user/Hero.js
@@ -15,6 +15,7 @@ import 'firebase/storage';
 import ReactDOM from "react-dom"
 import firebase from "../fire";
 import Loader from 'react-loader-spinner'
+import Dropzone from './Dropzone'
 
 
 const Hero = ({ handleLogout }) => {
@@ -40,7 +41,9 @@ const Hero = ({ handleLogout }) => {
 
   if(folder.id!=="copyright"){
     return (
+
     <>
+    
       <Container fluid>
         <div className='d-flex align-items-center'>
           <FolderNav currentFolder={folder} />
@@ -52,6 +55,7 @@ const Hero = ({ handleLogout }) => {
           {folder.id!=null &&  ( <Sharelink currentFolder={folder} /> )}
           {folder.id!=null &&  ( <Deletefolder currentFolder={folder} /> )}
           {folder.id!=null &&  ( <AddFile currentFolder={folder} /> )}
+          {folder.id!=null &&  ( <Dropzone currentFolder={folder} /> )}
         </div>
 
         {childFolders.length > 0 && (
-- 
GitLab