Browse Source

dropzone for track upload implementation 1st try

miskson 2 years ago
parent
commit
af9bef726c
5 changed files with 136 additions and 35 deletions
  1. 91 29
      package-lock.json
  2. 1 0
      package.json
  3. 2 2
      src/App.js
  4. 24 2
      src/actions/index.js
  5. 18 2
      src/components/Page/index.js

+ 91 - 29
package-lock.json

@@ -14,6 +14,7 @@
         "node-sass": "^7.0.1",
         "react": "^17.0.2",
         "react-dom": "^17.0.2",
+        "react-dropzone": "^11.5.1",
         "react-redux": "^7.2.6",
         "react-router-dom": "^5.3.0",
         "react-scripts": "5.0.0",
@@ -4395,6 +4396,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": "10.4.2",
       "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz",
@@ -7542,6 +7551,17 @@
         "webpack": "^4.0.0 || ^5.0.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/filelist": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz",
@@ -7648,9 +7668,9 @@
       "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw=="
     },
     "node_modules/follow-redirects": {
-      "version": "1.14.6",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz",
-      "integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==",
+      "version": "1.14.7",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz",
+      "integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==",
       "funding": [
         {
           "type": "individual",
@@ -11726,11 +11746,11 @@
       }
     },
     "node_modules/node-forge": {
-      "version": "0.10.0",
-      "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
-      "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.2.1.tgz",
+      "integrity": "sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==",
       "engines": {
-        "node": ">= 6.0.0"
+        "node": ">= 6.13.0"
       }
     },
     "node_modules/node-gyp": {
@@ -13975,6 +13995,22 @@
         "react": "17.0.2"
       }
     },
+    "node_modules/react-dropzone": {
+      "version": "11.5.1",
+      "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-11.5.1.tgz",
+      "integrity": "sha512-eNhttdq4ZDe3eKbXAe54Opt+sbtqmNK5NWTHf/l5d+1TdZqShJ8gMjBrya00qx5zkI//TYxRhu1d9pemTgaWwg==",
+      "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.10",
       "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz",
@@ -14919,11 +14955,14 @@
       "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo="
     },
     "node_modules/selfsigned": {
-      "version": "1.10.11",
-      "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz",
-      "integrity": "sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.0.tgz",
+      "integrity": "sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ==",
       "dependencies": {
-        "node-forge": "^0.10.0"
+        "node-forge": "^1.2.0"
+      },
+      "engines": {
+        "node": ">=10"
       }
     },
     "node_modules/semver": {
@@ -16680,9 +16719,9 @@
       }
     },
     "node_modules/webpack-dev-server": {
-      "version": "4.7.2",
-      "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.7.2.tgz",
-      "integrity": "sha512-s6yEOSfPpB6g1T2+C5ZOUt5cQOMhjI98IVmmvMNb5cdiqHoxSUfACISHqU/wZy+q4ar/A9jW0pbNj7sa50XRVA==",
+      "version": "4.7.3",
+      "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.7.3.tgz",
+      "integrity": "sha512-mlxq2AsIw2ag016nixkzUkdyOE8ST2GTy34uKSABp1c4nhjZvH90D5ZRR+UOLSsG4Z3TFahAi72a3ymRtfRm+Q==",
       "dependencies": {
         "@types/bonjour": "^3.5.9",
         "@types/connect-history-api-fallback": "^1.3.5",
@@ -16706,7 +16745,7 @@
         "p-retry": "^4.5.0",
         "portfinder": "^1.0.28",
         "schema-utils": "^4.0.0",
-        "selfsigned": "^1.10.11",
+        "selfsigned": "^2.0.0",
         "serve-index": "^1.9.1",
         "sockjs": "^0.3.21",
         "spdy": "^4.0.2",
@@ -20570,6 +20609,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": "10.4.2",
       "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz",
@@ -22917,6 +22961,14 @@
         "schema-utils": "^3.0.0"
       }
     },
+    "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"
+      }
+    },
     "filelist": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz",
@@ -23001,9 +23053,9 @@
       "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw=="
     },
     "follow-redirects": {
-      "version": "1.14.6",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz",
-      "integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A=="
+      "version": "1.14.7",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz",
+      "integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ=="
     },
     "forever-agent": {
       "version": "0.6.1",
@@ -25954,9 +26006,9 @@
       }
     },
     "node-forge": {
-      "version": "0.10.0",
-      "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
-      "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA=="
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.2.1.tgz",
+      "integrity": "sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w=="
     },
     "node-gyp": {
       "version": "8.4.1",
@@ -27465,6 +27517,16 @@
         "scheduler": "^0.20.2"
       }
     },
+    "react-dropzone": {
+      "version": "11.5.1",
+      "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-11.5.1.tgz",
+      "integrity": "sha512-eNhttdq4ZDe3eKbXAe54Opt+sbtqmNK5NWTHf/l5d+1TdZqShJ8gMjBrya00qx5zkI//TYxRhu1d9pemTgaWwg==",
+      "requires": {
+        "attr-accept": "^2.2.1",
+        "file-selector": "^0.2.2",
+        "prop-types": "^15.7.2"
+      }
+    },
     "react-error-overlay": {
       "version": "6.0.10",
       "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz",
@@ -28159,11 +28221,11 @@
       "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo="
     },
     "selfsigned": {
-      "version": "1.10.11",
-      "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz",
-      "integrity": "sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.0.tgz",
+      "integrity": "sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ==",
       "requires": {
-        "node-forge": "^0.10.0"
+        "node-forge": "^1.2.0"
       }
     },
     "semver": {
@@ -29534,9 +29596,9 @@
       }
     },
     "webpack-dev-server": {
-      "version": "4.7.2",
-      "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.7.2.tgz",
-      "integrity": "sha512-s6yEOSfPpB6g1T2+C5ZOUt5cQOMhjI98IVmmvMNb5cdiqHoxSUfACISHqU/wZy+q4ar/A9jW0pbNj7sa50XRVA==",
+      "version": "4.7.3",
+      "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.7.3.tgz",
+      "integrity": "sha512-mlxq2AsIw2ag016nixkzUkdyOE8ST2GTy34uKSABp1c4nhjZvH90D5ZRR+UOLSsG4Z3TFahAi72a3ymRtfRm+Q==",
       "requires": {
         "@types/bonjour": "^3.5.9",
         "@types/connect-history-api-fallback": "^1.3.5",
@@ -29560,7 +29622,7 @@
         "p-retry": "^4.5.0",
         "portfinder": "^1.0.28",
         "schema-utils": "^4.0.0",
-        "selfsigned": "^1.10.11",
+        "selfsigned": "^2.0.0",
         "serve-index": "^1.9.1",
         "sockjs": "^0.3.21",
         "spdy": "^4.0.2",

+ 1 - 0
package.json

@@ -9,6 +9,7 @@
     "node-sass": "^7.0.1",
     "react": "^17.0.2",
     "react-dom": "^17.0.2",
+    "react-dropzone": "^11.5.1",
     "react-redux": "^7.2.6",
     "react-router-dom": "^5.3.0",
     "react-scripts": "5.0.0",

+ 2 - 2
src/App.js

@@ -42,7 +42,7 @@ export const getGQL = url =>
       })
 
 export const history = createHistory()
-const backendURL = "http://player.asmer.fs.a-level.com.ua"
+export const backendURL = "http://player.asmer.fs.a-level.com.ua"
 export const gql = getGQL(backendURL + '/graphql')
 
 const store = createStore(
@@ -115,7 +115,7 @@ const Player = () =>
       <main style={{ border: '1px solid black', width: '80%' }}>
         <Switch>
           <Route path="/player/playlist/:_id" component={Page.PlaylistPageConnect} exact/>
-          <Route path="/player/tracks/:_id" component={Page.UserTracksPageConnect} exact/>
+          <Route path="/player/tracks/:_id" component={Page.UserTrackDropzoneConnect} exact/>
           <>
             <h2>Welcome to online Player!</h2>
             <div style={{width:'50%',margin: '0 auto'}}>

+ 24 - 2
src/actions/index.js

@@ -1,4 +1,4 @@
-import { jwtDecode, gql } from '../App'
+import { jwtDecode, gql, backendURL } from '../App'
 
 const actionPending = name => ({ type: 'PROMISE', status: 'PENDING', name })
 const actionResolved = (name, payload) => ({ type: 'PROMISE', status: 'RESOLVED', name, payload })
@@ -116,4 +116,26 @@ export const actionAddPlaylist = playlistName =>
             }
         `, {playlistName: playlistName})))
         dispatch(actionGetUserPlaylists())
-    }
+    }
+
+export const actionLoadFile = (file, type) => {
+    let fd = new FormData()
+    console.log('TYPE', type)
+    fd.append(type === 'upload'? 'photo' : type, file)
+    
+    return (
+        actionPromise('loadFile', fetch(backendURL + `/${type}`,{
+        method: "POST",
+        headers: localStorage.authToken ? {Authorization: 'Bearer ' + localStorage.authToken} : {},
+        body: fd
+        })
+        .then(res => res.json())
+        )
+    )
+}
+
+export const actionUploadUserTrack = file =>
+    async dispatch => {
+        await dispatch(actionLoadFile(file, 'track'))
+        dispatch(actionGetUserTracks())
+    }

+ 18 - 2
src/components/Page/index.js

@@ -2,6 +2,8 @@ import * as action from '../../actions'
 
 import { useEffect} from 'react';
 import { connect } from 'react-redux';
+import { useDropzone } from 'react-dropzone'
+import React, {useCallback} from 'react'
 
 const Track = ({track:{url, originalFileName, id3:{title, artist, album}}}) =>
     <li style={{border: '1px solid black', display:'flex', alignItems:'center'}}>
@@ -35,7 +37,6 @@ const PlaylistPage = ({match: {params: {_id}}, getTracks}) => {
 }
 export const PlaylistPageConnect = connect(null, {getTracks: action.actionGetPlaylistById})(PlaylistPage)
 
-
 const UserTracks = ({user, tracks}) =>
   <>
     <h2>{ user.login || 'My' } tracks:</h2>
@@ -54,4 +55,19 @@ const UserTracksPage = ({match: {params: {_id}}, getUserTracks}) => {
   useEffect(() => { getUserTracks() },[_id, getUserTracks])
   return(<UserTracksConnect/>)
 }
-export const UserTracksPageConnect = connect(null, {getUserTracks: action.actionGetUserTracks})(UserTracksPage)
+export const UserTracksPageConnect = connect(null, {getUserTracks: action.actionGetUserTracks})(UserTracksPage)
+
+const UserTracksDropzone = ({onLoad}) => {
+  const onDrop = useCallback(acceptedFiles => {
+    onLoad(acceptedFiles[0])
+  }, [])
+  const {getRootProps, getInputProps, isDragActive} = useDropzone({onDrop})
+
+  return (
+    <div {...getRootProps()}>
+      <input {...getInputProps()} />
+      { isDragActive ? <p>Drop the files here ...</p> : <UserTracksPageConnect /> }
+    </div>
+  )
+}
+export const UserTrackDropzoneConnect = connect(null, {onLoad: action.actionLoadFile})(UserTracksDropzone)