Browse Source

Merge branch 'component-file-managament' of Sergei-Levshnia/player-project into dev

Sergei-Levshnia 2 years ago
parent
commit
16fe97a6e6
4 changed files with 271 additions and 246 deletions
  1. 85 246
      src/App.js
  2. 67 0
      src/components/Login/index.js
  3. 57 0
      src/components/Page/index.js
  4. 62 0
      src/components/Sidebar/index.js

+ 85 - 246
src/App.js

@@ -1,14 +1,30 @@
 import './App.css';
 import * as action from './actions'
 import * as reducer from './reducers'
+import * as Logcomp from './components/Login'
+import * as Sidebar from './components/Sidebar'
+import * as Page from './components/Page'
 
 import thunk from 'redux-thunk';
 import { useEffect, useState } from 'react';
 import { createStore, combineReducers, applyMiddleware } from 'redux';
 import { Provider, connect } from 'react-redux';
-import { Link, Route, Router, Switch, Redirect } from 'react-router-dom';
+import { Link, Route, Router, Switch } from 'react-router-dom';
 import createHistory from 'history/createBrowserHistory'
 
+export function jwtDecode(token) {
+  try {
+    let decoded = token.split('.')
+    decoded = decoded[1]
+    decoded = atob(decoded)
+    decoded = JSON.parse(decoded)
+    return decoded
+  } 
+  catch (e) {
+    return;
+  }
+}
+
 export const getGQL = url =>
   (query, variables = {}) =>
     fetch(url, {
@@ -25,7 +41,7 @@ export const getGQL = url =>
         return data.data[Object.keys(data.data)[0]]
       })
 
-const history = createHistory()
+export const history = createHistory()
 const backendURL = "http://player.asmer.fs.a-level.com.ua"
 export const gql = getGQL(backendURL + '/graphql')
 
@@ -38,10 +54,7 @@ const store = createStore(
     }
   ), applyMiddleware(thunk)
 )
-
 store.subscribe(() => console.log(store.getState()))
-
-
 //works only once on start of page
 if(store.getState().auth?.token) {
   history.push('/player')
@@ -51,251 +64,77 @@ if(store.getState().auth?.token) {
   history.push('/login')
 }
 
-export function jwtDecode(token) {
-  try {
-    let decoded = token.split('.')
-    decoded = decoded[1]
-    decoded = atob(decoded)
-    decoded = JSON.parse(decoded)
-    return decoded
-
-  } catch (e) {
-    return;
-  }
-}
-
-const LoginForm = ({ loged, onLogin }) => {
-  let [login, setLogin] = useState()
-  let [password, setPassword] = useState()
-  let [log, setLog] = useState()
-
-  useEffect(() => {
-    setLog(loged)
-    if (log?.payload && localStorage.authToken) history.push('/player')
-  }, [loged, log])
-
-  return (
-    <>
-      <h1>Web-player</h1>
-      <div>
-        <h2>Log-in</h2>
-        <input type="text" placeholder='Login' onChange={(e) => setLogin(e.target.value)} />
-        <br />
-        <input type="password" placeholder='Password' onChange={(e) => setPassword(e.target.value)} />
-        <br />
-        <small style={{ color: 'red' }}>{loged.status === 'REJECTED' || (loged.status === 'RESOLVED' && !loged.payload) ? 'invalid login or password' : ''}</small>
-        <br />
-        <button
-          disabled={!password || !login}
-          onClick={() => { onLogin(login, password) }}
-        >Login</button>
-        <p>- OR -</p>
-        <Link to="/registration">Register new user</Link>
-      </div>
-    </>
-  )
-}
-const LoginFormConnect = connect(state => ({ loged: state.promise.login || {} }), { onLogin: action.actionFullLogin })(LoginForm)
-
-const RegisterForm = ({ onRegister }) => {
-  let [login, setLogin] = useState()
-  let [password, setPassword] = useState()
-  let [password2, setPassword2] = useState()
-  return (
-    <>
-      <h1>Web-player</h1>
-      <div>
-        <h2>Registration</h2>
-        <input type="text" placeholder='Login' onChange={(e) => setLogin(e.target.value)} />
-        <br />
-        <input type="password" placeholder='Password' onChange={(e) => setPassword(e.target.value)} />
-        <br />
-        <input disabled={!password} type="password" placeholder='Repeat Password' onChange={(e) => setPassword2(e.target.value)} />
-        <br />
-        <small style={{ color: 'red' }}>{password2 && password2 !== password ? 'Passwords do not match' : ''}</small>
-        <br />
-        <button disabled={!password || !login || password2 !== password} onClick={() => onRegister(login, password)}>Register</button>
-        <br />
-        <Link to="/login">Back to log-in page</Link>
-      </div>
-    </>
-  )
-}
-const RegisterFormConnect = connect(null, { onRegister: action.actionRegister })(RegisterForm)
-
-const PlaylistAdd = ({addPlaylist}) => {
-  let [clicked, setClicked] = useState(false)
-  let [name, setName] = useState()
-  return (
-    <div>
-      {
-        !clicked?
-          <button 
-            style={{ border: '1px solid black', backgroundColor: 'mediumseagreen',width : '95%',padding: '5px', margin: '5px' }}
-            onClick={() => setClicked(true)}
-          >NEW PLAYLIST</button>
-          :
-          <div style={{width : '95%', margin:'0 auto'}}>
-            <input 
-              style={{width:'72%', padding:'5px'}} 
-              placeholder='Playlist name'
-              value={name}
-              onChange={(e) => setName(e.target.value)}
-            />
-
-            <button
-              disabled={!name}
-              style={{padding:'5px', backgroundColor:'mediumseagreen'}}
-              onClick={() => {addPlaylist(name); setClicked(false); setName('');}}
-            >+</button>
-
-            <button
-              style={{padding:'5px', backgroundColor:'red'}} 
-              onClick={() => {setClicked(false); setName('')}}
-            >X</button>
-          </div>
-      }
-    </div>
-  )
-}
-const PlaylistAddConnect = connect(null, {addPlaylist: action.actionAddPlaylist})(PlaylistAdd)
-
-const Playlists = ({playlists}) => {
-  return (
-    <div style={{backgroundColor: 'lightcyan'}}>
-      <PlaylistAddConnect />
-      {
-        playlists?.payload? playlists.payload.map(item => {
-          return (
-            <Link 
-              style={{display:'block', backgroundColor: 'darkcyan', color: 'cyan', margin: '5px', padding:'5px'}} 
-              to={`${history.location.pathname}/playlist/:${item._id}`}
-            >{item.name}</Link>
-          )
-        }) : '' 
-      } 
-    </div>
-  )
-}
-const PlaylistsConnect = connect(state => ({playlists: state.promise.userPlaylists || {}}))(Playlists)
-
-const Track = ({track:{url, originalFileName, id3:{title, artist, album}}}) =>
-    <li style={{border: '1px solid black', display:'flex', alignItems:'center'}}>
-      <div style={{marginRight:'2%'}}>
-        <button style={{padding: '10px', margin:'2px'}}> {`>`} </button>
-        <button style={{padding: '10px', margin:'2px'}}>| |</button>
-        <br/>
-        <button style={{padding: '10px', margin:'2px'}}>Add to...</button>
-      </div>
-      <div style={{textAlign: 'left'}}>
-        <h5>{artist || 'Artist: unknown'}</h5> 
-        <h6>{album || 'Album: unknown'}</h6>
-        <h5>{title || originalFileName}</h5>
-        <p>{url}</p>
-      </div>
-    </li>
-
-const Playlist = ({playlist}) =>
-    <>
-      <h2>{playlist[0]?.name || 'Playlist'}</h2>
-      <ul>
-        {(playlist[0]?.tracks || []).map(track => <Track track={track}/>)}
-      </ul>
-    </>
-
-const PlaylistConnect = connect(state => ({playlist: state.promise.playlistTracks?.payload || []}))(Playlist)
-
-const PlaylistPage = ({match: {params: {_id}}, getTracks}) => {
-  useEffect(() => {
-    console.log('BANG', _id)
-    getTracks(_id.substring(1))
-    //getTracks()
-  }, [_id])
-  return(<PlaylistConnect />)
-}
-const PlaylistPageConnect = connect(null, {getTracks: action.actionGetPlaylistById})(PlaylistPage)
-
-
-const UserTracks = ({user, tracks}) =>
-  <>
-    <h2>{ user.login || 'My' } tracks:</h2>
-    <ul>
-      {(tracks || []).map(track => <Track track={track}/>)}
-    </ul>
-  </>
-
-const UserTracksConnect = connect(state => ({
-    tracks: state.promise.userTracks?.payload || [], 
-    user: state.promise.userData?.payload || {}
-  })
-)(UserTracks)
-
-const UserTracksPage = ({match: {params: {_id}}, getUserTracks}) => {
-  useEffect(() => {
-    getUserTracks()
-  },[_id])
-  return(<UserTracksConnect/>)
-}
-const UserTracksPageConnect = connect(null, {getUserTracks: action.actionGetUserTracks})(UserTracksPage)
-
-const Player = ({ user, playlists, onLogout }) => {
+const ProfileWindow = ({user, onLogout}) => {
   let [userInfo, setUserInfo] = useState(user.payload)
-  let [userPlaylists, setPlaylists] = useState(user.payload)
 
   useEffect(()=> {
     setUserInfo(user.payload)
-    setPlaylists(playlists.payload)
-    console.log(userPlaylists)
-  },[user, playlists, userInfo, userPlaylists])
-  
-  return (
-    <>
-      <header>Player</header>
-      <div style={{ display: 'flex' }}>
-        <aside style={{ border: '1px solid black', width: '30%' }}>
-          <div
-            style={{ border: '1px solid black', backgroundColor: 'red', color: 'white' }}
-            onClick={() => { onLogout(); history.push('/login') }}
-          >log-out[X]</div>
-          {/* profile window */}
-          <div style={{border:'1px solid chartreuse'}}>
-            <h3>{userInfo?.login || 'user'}</h3>         
-            <img 
-              width={100} 
-              height={100}  
-              style={{ border: '1px solid black', display:'block', margin:'5% auto', marginBottom:'2px'}}
-              src={ userInfo?.avatar?.url ? backendURL + '/' + userInfo?.avatar?.url : ''}
-              alt='avatar' 
-            />
-            <small>change avavtar</small>
-          </div>
-          <Link 
-            style={{display:'block', backgroundColor: 'purple', color: 'white', margin: '5px', padding:'5px'}} 
-            to={`/player/tracks/:${userInfo?._id}`}
-          >My tracks</Link>
-          <PlaylistsConnect />
-        </aside>
-        <main style={{ border: '1px solid black', width: '80%' }}>
-          <Switch>
-            <Route path="/player/playlist/:_id" component={PlaylistPageConnect} exact/>
-            <Route path="/player/tracks/:_id" component={UserTracksPageConnect} exact/>
-          </Switch>
-        </main>
+  },[user, userInfo])
+
+  return(
+    <section>
+      <div
+        style={{ border: '1px solid black', backgroundColor: 'red', color: 'white' }}
+        onClick={() => { onLogout(); history.push('/login') }}
+      >log-out[X]</div>
+      <div style={{border:'1px solid chartreuse'}}>
+        <h3>{userInfo?.login || 'user'}</h3>         
+        <img 
+          width={100} 
+          height={100}  
+          style={{ border: '1px solid black', display:'block', margin:'5% auto', marginBottom:'2px'}}
+          src={ userInfo?.avatar?.url ? backendURL + '/' + userInfo?.avatar?.url : ''}
+          alt='avatar' 
+        />
+        <small>change avavtar</small>
       </div>
-      <footer> back stop forw</footer>
-    </>
-  )
+      <Link
+        to={`/player/tracks/:${userInfo?._id}`} 
+        style={{
+          display:'block', 
+          backgroundColor: 'purple', 
+          color: 'white', 
+          margin: '5px', 
+          padding:'5px'
+        }} 
+      >My tracks</Link>
+    </section>
+   )
 }
+const ProfileWindowConnect = connect(state => ({ user: state.promise.userData || {} }),{ onLogout: action.actionAuthLogout })(ProfileWindow)
+  
 
-const PlayerConnect = connect(
-  state => ({
-    user: state.promise.userData || {},
-    playlists: state.promise.userPlaylists || {}
-  }),
-  { 
-    onLogout: action.actionAuthLogout,
-  }
-)(Player)
+const Player = () => 
+  <>
+    <header>Player</header>
+    <div style={{ display: 'flex' }}>
+      <aside style={{ border: '1px solid black', width: '30%' }}>
+        <ProfileWindowConnect />
+        <Sidebar.PlaylistsConnect />
+      </aside>
+      <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/>
+          <>
+            <h2>Welcome to online Player!</h2>
+            <div style={{width:'50%',margin: '0 auto'}}>
+              <ul style={{textAlign:'start'}}>
+                <li><strong>To create playlist: </strong>click "NEW PLAYLIST"</li>
+                <li><strong>To upload track: </strong>drag and drop it to playlist area</li>
+                <li><strong>To see list of all your tracks: </strong>click "My tracks"</li>
+              </ul>
+            </div>
+          </>
+        </Switch>
+      </main>
+    </div>
+    <footer> back stop forw</footer>
+  </>
+
+// const PlayerConnect = connect(
+//   state => ({ user: state.promise.userData || {} }),{ onLogout: action.actionAuthLogout}
+// )(Player)
 
 
 function App() {
@@ -304,9 +143,9 @@ function App() {
       <Provider store={store}>
         <div className="App">
           <Switch>
-            <Route path="/login" component={LoginFormConnect} exact />
-            <Route path="/registration" component={RegisterFormConnect} exact />
-            <Route path='/player' component={PlayerConnect} />
+            <Route path="/login" component={Logcomp.LoginFormConnect} exact />
+            <Route path="/registration" component={Logcomp.RegisterFormConnect} exact />
+            <Route path='/player' component={Player} />
           </Switch>
         </div>
       </Provider>

+ 67 - 0
src/components/Login/index.js

@@ -0,0 +1,67 @@
+import * as action from '../../actions'
+
+import { useEffect, useState } from 'react';
+import { connect } from 'react-redux';
+import { Link } from 'react-router-dom';
+import { history } from '../../App';
+
+const RegisterForm = ({ onRegister }) => {
+  let [login, setLogin] = useState()
+  let [password, setPassword] = useState()
+  let [password2, setPassword2] = useState()
+  return (
+    <>
+      <h1>Web-player</h1>
+      <div>
+        <h2>Registration</h2>
+        <input type="text" placeholder='Login' onChange={(e) => setLogin(e.target.value)} />
+        <br />
+        <input type="password" placeholder='Password' onChange={(e) => setPassword(e.target.value)} />
+        <br />
+        <input disabled={!password} type="password" placeholder='Repeat Password' onChange={(e) => setPassword2(e.target.value)} />
+        <br />
+        <small style={{ color: 'red' }}>{password2 && password2 !== password ? 'Passwords do not match' : ''}</small>
+        <br />
+        <button disabled={!password || !login || password2 !== password} onClick={() => onRegister(login, password)}>Register</button>
+        <br />
+        <Link to="/login">Back to log-in page</Link>
+      </div>
+    </>
+  )
+}
+export const RegisterFormConnect = connect(null, { onRegister: action.actionRegister })(RegisterForm)
+
+const LoginForm = ({ loged, onLogin }) => {
+  let [login, setLogin] = useState()
+  let [password, setPassword] = useState()
+  let [log, setLog] = useState()
+
+  useEffect(() => {
+    setLog(loged)
+    if (log?.payload && localStorage.authToken) history.push('/player')
+  }, [loged, log])
+
+  return (
+    <>
+      <h1>Web-player</h1>
+      <div>
+        <h2>Log-in</h2>
+        <input type="text" placeholder='Login' onChange={(e) => setLogin(e.target.value)} />
+        <br />
+        <input type="password" placeholder='Password' onChange={(e) => setPassword(e.target.value)} />
+        <br />
+        <small style={{ color: 'red' }}>
+          {loged.status === 'REJECTED' || (loged.status === 'RESOLVED' && !loged.payload)? 'invalid login or password' : ''}
+        </small>
+        <br />
+        <button
+          disabled={!password || !login}
+          onClick={() => { onLogin(login, password) }}
+        >Login</button>
+        <p>- OR -</p>
+        <Link to="/registration">Register new user</Link>
+      </div>
+    </>
+  )
+}
+export const LoginFormConnect = connect(state => ({ loged: state.promise.login || {} }), { onLogin: action.actionFullLogin })(LoginForm)

+ 57 - 0
src/components/Page/index.js

@@ -0,0 +1,57 @@
+import * as action from '../../actions'
+
+import { useEffect} from 'react';
+import { connect } from 'react-redux';
+
+const Track = ({track:{url, originalFileName, id3:{title, artist, album}}}) =>
+    <li style={{border: '1px solid black', display:'flex', alignItems:'center'}}>
+      <div style={{marginRight:'2%'}}>
+        <button style={{padding: '10px', margin:'2px'}}> {`>`} </button>
+        <button style={{padding: '10px', margin:'2px'}}>| |</button>
+        <br/>
+        <button style={{padding: '10px', margin:'2px'}}>Add to...</button>
+      </div>
+      <div style={{textAlign: 'left'}}>
+        <h5>{artist || 'Artist: unknown'}</h5> 
+        <h6>{album || 'Album: unknown'}</h6>
+        <h5>{title || originalFileName}</h5>
+        <p>{url}</p>
+      </div>
+    </li>
+
+const Playlist = ({playlist}) =>
+    <>
+      <h2>{playlist[0]?.name || 'Playlist'}</h2>
+      <ul>
+        {(playlist[0]?.tracks || []).map(track => <Track track={track}/>)}
+      </ul>
+    </>
+
+export const PlaylistConnect = connect(state => ({playlist: state.promise.playlistTracks?.payload || []}))(Playlist)
+
+const PlaylistPage = ({match: {params: {_id}}, getTracks}) => {
+  useEffect(() => { getTracks(_id.substring(1)) }, [_id, getTracks])
+  return(<PlaylistConnect />)
+}
+export const PlaylistPageConnect = connect(null, {getTracks: action.actionGetPlaylistById})(PlaylistPage)
+
+
+const UserTracks = ({user, tracks}) =>
+  <>
+    <h2>{ user.login || 'My' } tracks:</h2>
+    <ul>
+      {(tracks || []).map(track => <Track track={track}/>)}
+    </ul>
+  </>
+
+const UserTracksConnect = connect(state => ({
+    tracks: state.promise.userTracks?.payload || [], 
+    user: state.promise.userData?.payload || {}
+  })
+)(UserTracks)
+
+const UserTracksPage = ({match: {params: {_id}}, getUserTracks}) => {
+  useEffect(() => { getUserTracks() },[_id, getUserTracks])
+  return(<UserTracksConnect/>)
+}
+export const UserTracksPageConnect = connect(null, {getUserTracks: action.actionGetUserTracks})(UserTracksPage)

+ 62 - 0
src/components/Sidebar/index.js

@@ -0,0 +1,62 @@
+import * as action from '../../actions'
+
+import { useState } from 'react';
+import { connect } from 'react-redux';
+import { Link } from 'react-router-dom';
+import { history } from '../../App';
+
+const PlaylistAdd = ({addPlaylist}) => {
+  let [clicked, setClicked] = useState(false)
+  let [name, setName] = useState()
+  return (
+    <div>
+      {
+        !clicked?
+          <button 
+            style={{ border: '1px solid black', backgroundColor: 'mediumseagreen',width : '95%',padding: '5px', margin: '5px' }}
+            onClick={() => setClicked(true)}
+          >NEW PLAYLIST</button>
+          :
+          <div style={{width : '95%', margin:'0 auto'}}>
+            <input 
+              style={{width:'72%', padding:'5px'}} 
+              placeholder='Playlist name'
+              value={name}
+              onChange={(e) => setName(e.target.value)}
+            />
+
+            <button
+              disabled={!name}
+              style={{padding:'5px', backgroundColor:'mediumseagreen'}}
+              onClick={() => {addPlaylist(name); setClicked(false); setName('');}}
+            >+</button>
+
+            <button
+              style={{padding:'5px', backgroundColor:'red'}} 
+              onClick={() => {setClicked(false); setName('')}}
+            >X</button>
+          </div>
+      }
+    </div>
+  )
+}
+const PlaylistAddConnect = connect(null, {addPlaylist: action.actionAddPlaylist})(PlaylistAdd)
+
+const Playlists = ({playlists}) => {
+  return (
+    <div style={{backgroundColor: 'lightcyan'}}>
+      <PlaylistAddConnect />
+      {
+        playlists?.payload? playlists.payload.map(item => {
+          return (
+            <Link 
+              style={{display:'block', backgroundColor: 'darkcyan', color: 'cyan', margin: '5px', padding:'5px'}} 
+              to={`${history.location.pathname}/playlist/:${item._id}`}
+            >{item.name}</Link>
+          )
+        }) : '' 
+      }
+    </div>
+  )
+}
+export const PlaylistsConnect = connect(state => ({playlists: state.promise.userPlaylists || {}}))(Playlists)