123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- import logo from './logo.svg';
- import './App.css';
- import React, {useCallback} from 'react'
- import thunk from 'redux-thunk';
- import {createStore, combineReducers, applyMiddleware} from 'redux';
- import {Provider, connect} from 'react-redux';
- import {useDropzone} from 'react-dropzone'
- const actionPending = name => ({type: 'PROMISE', status: 'PENDING', name})
- const actionResolved = (name, payload) => ({type: 'PROMISE', status: 'RESOLVED', name, payload})
- const actionRejected = (name, error) => ({type: 'PROMISE', status: 'REJECTED', name, error})
- const actionPromise = (name, promise) =>
- async dispatch => {
- dispatch(actionPending(name)) // 1. {delay1000: {status: 'PENDING'}}
- try{
- let payload = await promise
- dispatch(actionResolved(name, payload))
- return payload
- }
- catch(error){
- dispatch(actionRejected(name, error))
- }
- }
- const getGQL = url =>
- (query, variables = {}) =>
- fetch(url, {
- method: 'POST',
- headers: {
- "Content-Type": "application/json",
- ...(localStorage.authToken ? { "Authorization": "Bearer " + localStorage.authToken } :
- {})
- },
- body: JSON.stringify({ query, variables })
- })
- .then(res => res.json())
- .then(data => {
- if (data.errors && !data.data)
- throw new Error(JSON.stringify(data.errors))
- return data.data[Object.keys(data.data)[0]]
- })
- const backendURL = "http://player.asmer.fs.a-level.com.ua"
- const gql = getGQL(backendURL + '/graphql')
- function jwtDecode(token) {
- try {
- let decoded = token.split('.')
- decoded = decoded[1]
- decoded = atob(decoded)
- decoded = JSON.parse(decoded)
- return decoded
- } catch (e) {
- return;
- }
- }
- 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())
- )
- )
- }
- const actionAboutMe = () => {
- let _id = jwtDecode(localStorage.authToken).sub.id
- return (
- actionPromise('aboutUser', gql(`
- query($userId: String!) {
- UserFindOne(query: $userId){
- login, _id, avatar {_id, url, originalFileName}
- }
- }
- `, { userId: JSON.stringify([{_id}]) }))
- )
- }
- const actionSetAvatar = (file) =>
- async (dispatch, getState) => {
- await dispatch(actionLoadFile(file, 'upload'))
- let picId = getState().promise?.loadFile?.payload?._id
- let userId = jwtDecode(localStorage.authToken).sub.id
- await dispatch(actionPromise('setAvatar', gql(`
- mutation {
- UserUpsert(user:{_id: "${userId}", avatar: {_id: "${picId}"}}){
- _id, login, avatar{
- _id, url
- }
- }
- }
- `)))
- dispatch(actionAboutMe())
- }
- const actionGetUserTracks = () => {
- //let _id = '5fe35e1ce926687ee86b0a3f' //newUserId
- let _id = jwtDecode(localStorage.authToken).sub.id
- return(
- actionPromise('userTracks', gql(`
- query getUserTracks($ownerId: String!) {
- TrackFind(query: $ownerId) {
- _id, originalFileName, url,
- id3 { title, artist, album }
- }
- }
- `, { ownerId: JSON.stringify([{ ___owner: _id }]) } ))
- )
- }
- const actionGetPlaylistById = (_id) =>
- actionPromise('playlistTracks', gql(`
- query playlistById($playlistId: String!) {
- PlaylistFind(query: $playlistId) {
- _id,
- name,
- tracks { _id, url, originalFileName }
- }
- }
- `, { playlistId: JSON.stringify([{ _id }]) }))
- const actionGetTrackById = (_id) =>
- actionPromise('track', gql(`
- query trackById($trackId: String!) {
- TrackFind(query: $trackId) {
- _id, url, originalFileName
- }
- }
- `, { trackId: JSON.stringify([{ _id }]) }))
- //add track to playlist
- const actionAddTrack = file =>
- async (dispatch, getState) => {
- let playlistId = "61e3506ac2305e2f502aca03"
- await dispatch(actionLoadFile(file, 'track'))
- await dispatch(actionGetTrackById(getState().promise.loadFile.payload?._id))
- await dispatch(actionGetPlaylistById(playlistId))
- let arr = [...getState().promise.track.payload]
- arr.push(...getState().promise.playlistTracks.payload[0].tracks)
- console.log('newarr', arr)
- //let updated = JSON.stringify(arr)
- //let trackId = getState().promise?.loadFile?.payload?._id
- // await dispatch(actionPromise('trackToPlaylist', gql(`
- // mutation {
- // PlaylistUpsert(playlist:{ _id: "${playlistId}", tracks: {_id: "${trackId}"}}) {
- // _id, name, tracks { _id, originalFileName }
- // }
- // }
- // `)))
- await dispatch(actionPromise('trackToPlaylist', gql(`
- mutation {
- PlaylistUpsert(playlist:{ _id: "${playlistId}", tracks: [{_id: "61e4b26ec2305e2f502acaae"}, {_id: "61e4a4cac2305e2f502aca98"}] })] {
- _id, name, tracks { _id, originalFileName }
- }
- }
- `)))
- // await dispatch(actionPromise('trackToPlaylist', gql(`
- // mutation {
- // PlaylistUpsert(playlist:{ _id: $playlistId, tracks: $tracks}}) {
- // _id, name, tracks { _id, originalFileName }
- // }
- // }
- // `, { playlistId:JSON.stringify([{ playlistId }]), tracks: JSON.stringify(arr) })))
- dispatch(actionGetUserTracks())
- }
- function promiseReducer(state={}, {type, name, status, payload, error}){
- if (type === 'PROMISE'){
- return { ...state, [name]:{status, payload, error} }
- }
- return state
- }
- const store = createStore(combineReducers({ promise: promiseReducer }), applyMiddleware(thunk))
- store.subscribe(() => console.log(store.getState()))
- function MyDropzone({uploadAvatar, userData, onLoad}) {
- const onDrop = useCallback(acceptedFiles => {
- uploadAvatar(acceptedFiles[0])
- }, [])
- const {getRootProps, getInputProps, isDragActive} = useDropzone({onDrop})
- return (
- <div {...getRootProps()} style={{backgroundColor:'mediumseagreen'}}>
- <input {...getInputProps()} />
- {
- isDragActive ?
- <p>Drop the files here ...</p> :
- <p>Drag 'n' drop some IMAGE here, or click to select files</p>
- }
- </div>
- )
- }
- const ConnectDropzone = connect(null, {uploadAvatar: actionSetAvatar, onLoad: actionLoadFile, userData: actionAboutMe})(MyDropzone)
- function TrackDropzone({uploadTrack, userData, onLoad}) {
- const onDrop = useCallback(acceptedFiles => {
- uploadTrack(acceptedFiles[0])
- }, [])
- const {getRootProps, getInputProps, isDragActive} = useDropzone({onDrop})
- return (
- <div {...getRootProps()} style={{backgroundColor:'mediumvioletred'}}>
- <input {...getInputProps()} />
- {
- isDragActive ?
- <p>Drop the files here ...</p> :
- <p>Drag 'n' drop some TRACK here, or click to select files</p>
- }
- </div>
- )
- }
- const ConnectTrackDropzone = connect(null, {uploadTrack: actionAddTrack, onLoad: actionLoadFile, userData: actionAboutMe})(TrackDropzone)
- function App() {
- return (
- <Provider store={store}>
- <div className="App">
- <ConnectDropzone />
- <ConnectTrackDropzone />
- </div>
- </Provider>
- );
- }
- export default App;
|