Browse Source

plaing player, styles, privates

Stepanova Asya 1 year ago
parent
commit
4df86d68a3

+ 3 - 2
src/App.js

@@ -7,7 +7,7 @@ import createHistory from "history/createBrowserHistory";
 import {Provider, connect}   from 'react-redux';
 //import {createStore, combineReducers, applyMiddleware} from 'redux';
 import { store } from './store/store';
-import { actionAllPlaylists } from './store/promiseReducer';
+import { actionAllPlaylists, actionUsersPlaylists } from './store/promiseReducer';
 import { Header } from './components/header';
 import { Main } from './components/Routs';
 import {CAllPlaylists} from './components/Playlist';
@@ -18,7 +18,8 @@ import {СNowPlayingPlayer} from './components/playing';
 export let history = createHistory();
 
 store.subscribe(() => console.log(store.getState()));
-store.dispatch(actionAllPlaylists());
+store.getState().auth.token && store.dispatch(actionAllPlaylists());
+store.getState().auth.token && store.dispatch(actionUsersPlaylists(store.getState().auth?.user?.id));
 
 
 // export const CPlaylistById = connect(state => ({playlist: state.promise.plstById?.payload || {}}), )(PlaylistById);

+ 4 - 5
src/components/EditPlaylistModal.js

@@ -1,9 +1,10 @@
 import Button from 'react-bootstrap/Button';
 import Modal from 'react-bootstrap/Modal';
 import React, {useState} from 'react';
-// import { sendForm } from './LoadTrackModal';
+import { actionPlaylistById } from '../store/promiseReducer';
+import { store } from '../store/store';
 import { sendForm } from './SendForm';
-import {Form, Image} from "react-bootstrap";
+import {Form} from "react-bootstrap";
 
 
 export function EditPlaylistModal  (props)  {
@@ -22,6 +23,7 @@ export function EditPlaylistModal  (props)  {
         image.name && data.append("photo",  image, image.name);
 
         sendForm('playlists/' + props.playlist?.id + '/edit', data);  
+        setTimeout(() => store.dispatch(actionPlaylistById(props.playlist?.id)), 100) ;
     } 
     const PreViewImage = (image) => {
         if (image && typeof (image) !== "string") {
@@ -64,6 +66,3 @@ export function EditPlaylistModal  (props)  {
         </Modal.Footer>
     </Modal>)
 }
-
-
-//export const CEditPlaylistModal = connect(state => ({playlist: state.promise.plstById?.payload || []}), )(EditPlaylistModal);

+ 3 - 48
src/components/Playlist.js

@@ -1,57 +1,12 @@
 import React from 'react';
 import 'bootstrap/dist/css/bootstrap.min.css';
-import { Link} from 'react-router-dom';
 import {connect}   from 'react-redux';
-import { store } from '../store/store';
-import { actionFullSetPlaylist, actionFullSetTrack } from '../store/playerReducer';
-import { actionPlaylistById} from '../store/promiseReducer';
-import image from '../images/card.png';
 import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
-import {faCompactDisc, faPlay} from "@fortawesome/free-solid-svg-icons";
-import Button from "react-bootstrap/Button";
-
-const Playlist = ({playlist = {}}) => 
-  <div className="">
-      <div className="me-4 mb-4 p-4 playlist-img-box rounded-5 position-relative"
-           style={{backgroundImage: `url(${playlist.photo || image})`, backgroundSize: "cover", backgroundRepeat: "no-repeat", backgroundPosition: "center", width:250, height:250}}
-      >
-          <div className="playlist-grey-box"></div>
-          <Link className="d-flex border-0 link-light position-relative text-decoration-none h4 text-wrap"
-                to={`/playlist/${playlist.id}`}>
-              {playlist.name}
-          </Link>
-          <Button variant="outline-light" className='rounded-5 position-absolute playlist-play-box'  title='Play'>
-              <FontAwesomeIcon className='' icon={faPlay}
-                onClick={() => {
-                  store.dispatch(actionPlaylistById(playlist.id));
-                  setTimeout(() => {
-                      if(store.getState().promise?.plstById?.payload?.tracks) {
-                        let tracks = store.getState().promise?.plstById?.payload?.tracks;
-                        store.dispatch(actionFullSetPlaylist(tracks));
-                        store.dispatch(actionFullSetTrack(store.getState().player?.playlist[0]));
-                    }
-                    }
-                    , 500) 
-                }}
-              />
-          </Button>
-      </div>
-  </div>
-
-// const Playlist = ({playlist: {id, user_id, name, photo, description, tracks} = {}}) =>
-// <div className="col-sm-3">
-//   <Link className="card" to= {`/playlist/${id}`} onClick={() => store.dispatch(actionFullSetPlaylist({id, user_id, name, photo, description, tracks}) )}>
-//     <img src={photo} className="card-img-top" alt="..." height={'150px'}/>
-//     <div className="card-body">
-//       <h5 className="card-title"> {name}</h5>
-//       {/* <p className="card-text">{description? description :  '.' }</p> */}
-//       {/* <button className="btn btn-primary" >Go somewhere</button> */}
-//     </div>
-//   </Link>
-// </div>
+import {faCompactDisc} from "@fortawesome/free-solid-svg-icons";
+import { Playlist } from './userPlaylists';
 
 
-const PlaylistsAll = ({playlists= []}) => 
+export const PlaylistsAll = ({playlists}) => 
 <>
   <div className="d-flex justify-content-between align-items-center py-3">
     <h3 className="text-uppercase"> <FontAwesomeIcon icon={faCompactDisc} className="me-2"/>Playlists</h3>

+ 5 - 4
src/components/Routs.js

@@ -4,12 +4,13 @@ import {LoginForm} from './authorization';
 import {CRegisterForm} from './authRegistration';
 import { store } from '../store/store';
 import { Aside } from '../App';
-import { UserPage} from './userPage';
+import { CUserPage } from '../pages/userPage';
+// import { UserPage} from './userPage';
 import {CPlaylistById}  from './playlistById';
 import {СNowPlayingPlayer} from './playing'
 import { CEditProfile } from './EditProfile';
 import { Header } from './header';
-import { ArtistPage } from '../pages/artistPage';
+import { CArtistPage } from '../pages/artistPage';
 import { AlbumPage } from '../pages/albumPage';
 
 export const Main = ({auth}) =>
@@ -27,8 +28,8 @@ export const Main = ({auth}) =>
           <Route path={'/editprofile'} component={CEditProfile}/>
           <Route path={'/allplaylists'} component={Aside}/>
           <Route path={'/playlist'} component={CPlaylistById} />
-          <Route path={'/user'} component={UserPage} />
-          <Route path={'/artist'} component={ArtistPage} />
+          <Route path={'/user'} component={CUserPage} />
+          <Route path={'/artist'} component={CArtistPage} />
           <Route path={'/album'} component={AlbumPage} />
           <Route exact path="/">{auth ? <Redirect to="/user"/> : <Redirect to="/login" /> }</Route>
         </Switch>

+ 11 - 15
src/components/Tracks.js

@@ -1,6 +1,6 @@
 import {connect}   from 'react-redux';
 import {actionFullSetTrack, actionFullPlay, actionFullSetPlaylist , actionAddTrackToQueue} from '../store/playerReducer';
-import { actionNowPlaylist, actionPlaylistById} from '../store/promiseReducer';
+import { actionNowPlaylist, actionPlaylistById, actionArtistById} from '../store/promiseReducer';
 import { store } from '../store/store';
 import Button from 'react-bootstrap/Button';
 import Modal from 'react-bootstrap/Modal';
@@ -59,14 +59,14 @@ const ButtonDeleteTrack = (track) => {
 }
 
 
-const Track = ({track = {}, trackone={}, playlist={}, plstnow={}},  key) => 
+const Track = ({track,  playlist}) => 
 <tr>
 <td scope="row" width={30} data-id={track.id}>
     <div className="col">
         <Button variant="outline-light" className='rounded-5'  title='Play' onClick={async () => {
-            store.dispatch(actionFullSetPlaylist(playlist.tracks));
-            store.dispatch(actionFullSetTrack(playlist.tracks[playlist.tracks.indexOf(track)]));
-            store.dispatch(actionNowPlaylist(store.getState().player?.track?.pivot?.playlist_id));
+            console.log(playlist.tracks, playlist?.tracks[playlist?.tracks.indexOf(track)]);
+            playlist.tracks && store.dispatch(actionFullSetPlaylist(playlist?.tracks));
+            playlist.tracks ? store.dispatch(actionFullSetTrack(playlist?.tracks[playlist?.tracks.indexOf(track)])) : store.dispatch(actionFullSetTrack(track))
             store.dispatch(actionFullPlay());
         }}>
             <FontAwesomeIcon className='' icon={faPlay}/>
@@ -76,8 +76,8 @@ const Track = ({track = {}, trackone={}, playlist={}, plstnow={}},  key) =>
     <td>          
         <Link className="link-light" to='#'>  {track.name}</Link>
     </td>
-    <td>
-        <Link className="link-light" to='#'>  {track.id3.artist}</Link>
+    <td onClick={() => store.dispatch(actionArtistById(track.artist_id))}>
+        <Link className="link-light" to={`/artist/${track.artist_id}`}>  {track.id3.artist}</Link>
     </td>
     <td> 
         <Link className="link-light" to='#'> {track.id3.getAlbum}</Link>
@@ -107,7 +107,7 @@ const Track = ({track = {}, trackone={}, playlist={}, plstnow={}},  key) =>
 </tr>
 
 
-const TracksAll = ({tracks=[], playlist={}}) => 
+export const TracksAll = ({tracks, playlist}) => 
 <table className="table table-dark table-hover align-middle">
     <thead>
         <tr>
@@ -119,16 +119,12 @@ const TracksAll = ({tracks=[], playlist={}}) =>
         </tr>
 </thead>
     <tbody>
-        {tracks.map((tracks, i) => <CTrack key={i} track={tracks}/>)}
+        {tracks.map((tracks, i) => <CTrack key={i} track={tracks} playlist={playlist}/>)}
     </tbody>
 </table>
 
 export const СAllTracks = connect(state => ({playlist: state.promise.plstById?.payload || {},
-                                 tracks: state.promise?.plstById?.payload?.tracks || [],
-                                 trackone: state.player?.playlist || [],
-                                 plstnow: state.promise?.plstnow || {}} ), )(TracksAll);
+                                 tracks: state.promise?.plstById?.payload?.tracks || []} ), )(TracksAll);
 
 export const CTrack = connect(state => ({playlist: state.promise.plstById?.payload || {},
-                                tracks: state.promise?.plstById?.payload?.tracks || [],
-                                trackone: state.player?.playlist || [],
-                                plstnow: state.promise?.plstnow || {}} ), )(Track);
+                                tracks: state.promise?.plstById?.payload?.tracks || []} ), )(Track);

+ 3 - 2
src/components/createPlaylist.js

@@ -2,6 +2,7 @@ import React, {useState} from 'react';
 import { sendForm } from './SendForm';
 import Modal from 'react-bootstrap/Modal';
 import Button from 'react-bootstrap/Button';
+import { actionUsersPlaylists } from '../store/promiseReducer';
 import { store } from '../store/store';
 import { history } from '../App';
 
@@ -22,8 +23,8 @@ export const CreatePlaylist = (props) => {
     image && data.append("photo",  image, image.name);
     let result = await sendForm('playlists/create', data);
     console.log(result);
-    
-    history.push(`/playlist/${result.playlist.id}`)
+    store.dispatch(actionUsersPlaylists(store.getState().auth?.user?.id));
+    //history.push(`/playlist/${result.playlist.id}`)
   }
 
   return <>

+ 106 - 81
src/components/playing.js

@@ -5,7 +5,8 @@ import { store } from '../store/store';
 import {actionPlayerRandom, actionFullPlay, actionFullPause, actionFullSetVolume, actionPrevTrack, actionNextTrack, actionSetRepeat, actionSetRandom} from '../store/playerReducer';
 import {Provider, connect}   from 'react-redux';
 import { audio } from './Tracks';
-import img_album from '../images/default_album.gif'
+import img_album from '../images/default_album.gif';
+import {Nav, Tab, Tabs} from "react-bootstrap";
 
 function msToTime(duration) {
     let hours,minutes,seconds;
@@ -29,88 +30,112 @@ export let NowPlayingPlayer = (props) => {
     }, [newCurrent]);
     
     let album_photo = (props.track?.album?.photo) ? `http://player-api/storage/albums/${props.track?.album?.photo}` : img_album 
-
-return(
-<div className="player">
-    <div className="wrapper">
-        <div className="details">
-            <div className="now-playing"></div>
-            <div className="track-art" style={{backgroundImage:`url(${album_photo})`}} ></div>
-            <div className="track-name">{props.track?.name|| 'Track Name'  }</div>
-            <div className="now-playing">{props.track?.id3?.artist || 'Artist'  }</div>
-        </div>
-
-        <div className="slider-container duration">
-            <span className="current-time">{props.currentTime ? 
-            `0${((props.currentTime - props.currentTime % 60) / 60 % 60).toFixed() !== 'NaN' ? 
-            ((props.currentTime - props.currentTime % 60) / 60 % 60).toFixed() : '0'}:${(props.currentTime % 60).toFixed() > 9 ?
-             '' : '0'}${(props.currentTime % 60).toFixed() !== 'NaN' ? (props.currentTime % 60).toFixed() : '0'}` : '--:--'}
-             </span>
-
-            <input type='range' min={0} max={props.duration} className="seek-slider" 
-            value={props.currentTime || 0} onChange={(e) => setNewCurrent(e.target.value)}
-             onMouseUp={() => store.dispatch(actionFullPlay())} onMouseDown={() => store.dispatch(actionFullPause())}
-            />
-
-            <span className="total-duration">{props.track?.id3?.time || (msToTime(props.duration) !== 'NaN:NaN'? msToTime(props.duration) : '00:00')}</span>
-            
-        </div>
-
-        <div className="slider-container">
-        <FontAwesomeIcon icon={faVolumeDown} />
-            <input type='range' min={1} max='99' value={volume} className="volume-slider"
-            onChange={(e) => {
-                setVolume(e.target.value);
-                if (store.getState()?.player?.track) store.dispatch(actionFullSetVolume(volume)) }}
-
-             />
-            <FontAwesomeIcon icon={faVolumeUp} />  
-        </div>
-
-        <div className="buttons">
-            <div className="random-track" 
-             onClick={() => {
-                props.random === 1 ? store.dispatch(actionSetRandom(2)) : store.dispatch(actionSetRandom(1))
-                store.dispatch(actionPlayerRandom());
-             }}
-            >
-                <FontAwesomeIcon icon={faRandom} className={props.random === 1 ? 'fa-2x' : 'fa-3x'}/>
-            </div>
-            <div className="prev-track" 
-                onClick={ () => store.dispatch(actionPrevTrack(props.track))}
-            > 
-                <FontAwesomeIcon icon={faStepBackward} className='fa-2x'/>
+    const [key, setKey] = useState('home');
+    return(
+        <div className="player col-xxl-3 col-lg-5 ">
+            <div className="wrapper ">
+                <Tabs
+                    id="fill-tab-example"
+                    activeKey={key}
+                    onSelect={(k) => setKey(k)}
+                    className="mb-3 justify-content-center text-white"
+                    tabClassName="btn-dark"
+                    fill
+                >
+                    <Tab className="text-white bg-dark" tabClassName="text-white bg-dark" eventKey="home" title="Player">
+                        <div className="flex-column justify-content-center align-items-center d-flex">
+                            <div className="details w-100">
+                                <div className="now-playing"></div>
+                                <div className="track-art" style={{backgroundImage:`url(${album_photo})`}} ></div>
+                                {/*<div className="track-name">{props.track?.name|| 'Track Name'  }</div>*/}
+                                <div className="track-name w-100 text-center">
+                                    <div className='line w-75'>
+                                        <div className='second w-100'>
+                                            <span className="w-100">
+                                            {props.track?.name|| 'Track Name'  }
+                                            </span>
+                                        </div>
+                                    </div>
+                                </div>
+                                <div className="now-playing">{props.track?.id3?.artist || 'Artist'  }</div>
+                            </div>
+        
+                            <div className="slider-container duration">
+        
+                                <div className="d-flex align-items-end justify-content-between">
+                                    <div className="slider-container d-flex flex-column w-75 pe-2" >
+                                        <div className="d-flex justify-content-between">
+                                            <span className="text-secondary">{props.currentTime ?
+                                                `0${((props.currentTime - props.currentTime % 60) / 60 % 60).toFixed() !== 'NaN' ?
+                                                    ((props.currentTime - props.currentTime % 60) / 60 % 60).toFixed() : '0'}:${(props.currentTime % 60).toFixed() > 9 ?
+                                                    '' : '0'}${(props.currentTime % 60).toFixed() !== 'NaN' ? (props.currentTime % 60).toFixed() : '0'}` : '--:--'}
+                                            </span>
+                                            <span className="text-secondary">{props.track?.id3?.time || (msToTime(props.duration) !== 'NaN:NaN'? msToTime(props.duration) : '00:00')}</span>
+                                        </div>
+                                        <input type='range' min={0} max={props.duration} className="seek-slider w-100 cursor-pointer"
+                                               value={props.currentTime || 0} onChange={(e) => setNewCurrent(e.target.value)}
+                                               onMouseUp={() => store.dispatch(actionFullPlay())} onMouseDown={() => store.dispatch(actionFullPause())}/>
+                                    </div>
+        
+                                    <div className="slider-container d-flex flex-column w-25" >
+                                        <div className="d-flex justify-content-between">
+                                            <FontAwesomeIcon icon={faVolumeDown} className="text-secondary"/><FontAwesomeIcon icon={faVolumeUp} className="text-secondary"/>
+                                        </div>
+        
+                                        <input type='range' min={1} max='99' value={volume} className="volume-slider cursor-pointer"
+                                               onChange={(e) => {
+                                                   setVolume(e.target.value);
+                                                   if (store.getState()?.player?.track) store.dispatch(actionFullSetVolume(volume)) }}/>
+                                    </div>
+                                </div>
+        
+                            </div>
+        
+                            <div className="buttons">
+                                <div className="random-track">
+                                    <FontAwesomeIcon icon={faRandom} className={props.random === 1 ? 'fa-2x text-white-50 cursor-pointer' : 'fa-2x text-primary cursor-pointer'}
+                                         onClick={() => {
+                                             props.random === 1 ? store.dispatch(actionSetRandom(2)) : store.dispatch(actionSetRandom(1))
+                                             store.dispatch(actionPlayerRandom());
+                                         }}/>
+                                </div>
+                                <div className="prev-track">
+                                    <FontAwesomeIcon icon={faStepBackward} className='fa-2x cursor-pointer'
+                                                     onClick={ () => store.dispatch(actionPrevTrack(props.track))}/>
+        
+                                </div>
+                                <div className="play-track">
+                                    <FontAwesomeIcon icon={(!props.isPlaying) ? faPlayCircle : faStopCircle} className='fa-5x cursor-pointer'
+                                         onClick={() => {
+                                             if(store.getState()?.player?.isPlaying === true) {
+                                                 store.dispatch(actionFullPause());
+                                             } else{
+                                                 store.dispatch(actionFullPlay());
+                                             }
+                                         }}/>
+                                </div>
+                                <div className="next-track">
+                                    <FontAwesomeIcon icon={faStepForward} className='fa-2x cursor-pointer' onClick={() => {
+                                        store.dispatch(actionNextTrack({track: props.track, end:'false'}));
+                                    }}/>
+                                </div>
+                                <div className="random-track">
+                                    <FontAwesomeIcon icon={faRepeat} className={props.repeat === 1 ? 'fa-2x text-white-50 cursor-pointer' : 'fa-2x text-primary cursor-pointer'}
+                                                     onClick={() => (props.repeat === 1 ? store.dispatch(actionSetRepeat(2)) : store.dispatch(actionSetRepeat(1)))}/>
+                                </div>
+        
+                            </div>
+                        </div>
+        
+                    </Tab>
+                    <Tab className="text-white bg-dark" tabClassName="text-white bg-dark"  eventKey="profile" title="Queue">
+                        asdasd
+                    </Tab>
+                </Tabs>
+        
                 
             </div>
-            <div className="play-track" 
-              onClick={() => {
-                if(store.getState()?.player?.isPlaying === true) {
-                    store.dispatch(actionFullPause());
-                 } else{
-                    store.dispatch(actionFullPlay());
-                 } 
-                }}
-            >
-                <FontAwesomeIcon icon={(!props.isPlaying) ? faPlayCircle : faStopCircle} className='fa-5x' />
-            </div>
-            <div className="next-track"
-              onClick={() => {
-                store.dispatch(actionNextTrack({track: props.track, end:'false'}));
-                }
-              }
-             >
-                <FontAwesomeIcon icon={faStepForward} className='fa-2x'/>
-            </div>
-            <div className="random-track" 
-             onClick={() => (props.repeat === 1 ? store.dispatch(actionSetRepeat(2)) : store.dispatch(actionSetRepeat(1)))}
-            >
-                <FontAwesomeIcon icon={faRepeat} className={props.repeat === 1 ? 'fa-2x' : 'fa-3x'}/>
-            </div>
-
-        </div>
-        
-    </div>
-</div>)
+        </div>)
 }
 
   export const СNowPlayingPlayer = connect(state => ({track: state.player?.track || [], 

+ 21 - 34
src/components/playlistById.js

@@ -1,39 +1,29 @@
 import React, {useState, useEffect} from 'react';
 import { store } from '../store/store';
-import { actionPlaylistById} from '../store/promiseReducer';
 import Button from 'react-bootstrap/Button';
 import Modal from 'react-bootstrap/Modal';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import {faTrash,
-    faPen,
-    faUserAstronaut,
-    faCompactDisc,
-    faPlus,
-    faAlignCenter,
-    faPlay, faHeart} from '@fortawesome/free-solid-svg-icons'
+import {faTrash, faPen, faUserAstronaut, faCompactDisc,
+    faPlus, faAlignCenter, faPlay, faHeart} from '@fortawesome/free-solid-svg-icons';
 import { actionFullSetPlaylist, actionFullSetTrack, actionAddPlaylistToQueue} from '../store/playerReducer';
 import {connect}   from 'react-redux';
-import {СAllTracks } from './Tracks'
+import { TracksAll } from './Tracks';
 import { LoadTrackModal } from './LoadTrackModal';
 import { EditPlaylistModal } from './EditPlaylistModal';
 import { Link } from 'react-router-dom';
 import { sendForm } from './SendForm';
 import { history } from '../App';
 import {ButtonGroup, Dropdown} from "react-bootstrap";
+import { actionPlaylistById, actionUsersPlaylists } from '../store/promiseReducer';
 
 
-let listToPlay;
-export const PlaylistById = ({playlist = {}, tracks={}}) => {
-    
+export const PlaylistById = ({playlist, tracks}) => {
     let id = window.location.href.split('/')[4];
-    
-    const getAnswer = async () => {
-      listToPlay = await store.dispatch(actionPlaylistById(id));
-      return listToPlay;
+    const getAnswer =  () => {
+      store.dispatch(actionPlaylistById(id));
     };
 
     useEffect(() => {
-  
       getAnswer();
     }, []);
 
@@ -61,14 +51,16 @@ export const PlaylistById = ({playlist = {}, tracks={}}) => {
                                             <Button  variant="outline-success" title='Add tracks' onClick={() => setModalShow(true)}>
                                                 <FontAwesomeIcon icon={faPlus} />
                                             </Button>
-                                            <LoadTrackModal id={id} show={modalShow} onHide={() => setModalShow(false)} />
+                                            <LoadTrackModal id={playlist?.id} show={modalShow} onHide={() => setModalShow(false)} />
                                         </div>
                                         <div className="col">
                                             <Button  variant="outline-secondary" title='Edit playlist' onClick={() => setModalTrackShow(true)}>
                                                 <FontAwesomeIcon icon={faPen} />
                                             </Button>
                                             <EditPlaylistModal  tracks={tracks}  show={modalTrackShow} playlist={playlist}
-                                                                onHide={() => setModalTrackShow(false)}></EditPlaylistModal>
+                                                                onHide={() => {setModalTrackShow(false);
+                                                                    setTimeout(() => store.dispatch(actionPlaylistById(playlist?.id)), 100) 
+                                                                }}></EditPlaylistModal>
                                         </div>
                                         <div className="col">
                                             <Button  variant="outline-danger" title='Delete playlist' onClick={() => setDeletePllstModal(true)}>
@@ -90,16 +82,17 @@ export const PlaylistById = ({playlist = {}, tracks={}}) => {
                                             <Button className='mx-2' variant="secondary" onClick={() => setDeletePllstModal(false)}>
                                                 Close
                                             </Button>
-                                            <Button className='mx-2' variant="danger" onClick={async() => {
-                                                await sendForm(`playlists/${playlist.id}/delete`);
+                                            <Button className='mx-2' variant="danger" onClick={() => {
+                                                sendForm(`playlists/${playlist.id}/delete`);
                                                 setDeletePllstModal(false)
-                                                history.push('/user')}}>Delete</Button>
+                                                setTimeout(() => {
+                                                    store.dispatch(actionUsersPlaylists(store.getState().auth?.user?.id));
+                                                    history.push('/user');}, 100) }}>Delete</Button>
                                         </Modal.Footer>
                                     </Modal>
                                 </>: <></>
                                 }
                             </div>
-
                             <Link className="link-secondary mb-2" title='Author' to='#'><FontAwesomeIcon className='me-2' icon={faUserAstronaut} />  {playlist.user_name}</Link>
                             <p className='text-white-50 mb-2'>
                                 <FontAwesomeIcon className='me-2' icon={faCompactDisc} /> {playlist?.tracks?.length} Tracks
@@ -108,8 +101,6 @@ export const PlaylistById = ({playlist = {}, tracks={}}) => {
                                 <FontAwesomeIcon className='me-2' icon={faAlignCenter} /> {playlist.description ?? "There could be a description here, but I'm too lazy"}
                             </p>
                         </div>
-
-                    
                         <div className="w-100">
                             <div className='d-flex'>
                                 <div className='row g-2'>
@@ -142,23 +133,19 @@ export const PlaylistById = ({playlist = {}, tracks={}}) => {
                                 </div>
                             </div>
                         </div>
-
-
                     </div>
                 </div>
             </div>
-            <СAllTracks />
+            <CAllTracks />
         </div>
     </div>
-      
-    </>
-  )}
+    </>)}
 
-  
-//   export const CPlaylistById = connect(state => ({playlist: state.promise.plstById?.payload || {},
-//     tracks: state.player?.playlist?.tracks}) || [] )(PlaylistById);
 
 export const CPlaylistById = connect(state => ({playlist: state.promise.plstById?.payload || {},
     tracks: state.promise.plstById?.payload?.tracks}) || [] )(PlaylistById);
 
+const CAllTracks = connect(state => ({tracks: state.promise?.plstById?.payload?.tracks || [],
+    playlist: state.promise.plstById?.payload || {},} ) )(TracksAll);
+
     

+ 0 - 107
src/components/userPage.js

@@ -1,107 +0,0 @@
-import React, {useEffect} from 'react';
-import {Link} from 'react-router-dom';
-import {connect}   from 'react-redux';
-import { actionUsersPlaylists } from '../store/promiseReducer';
-import { actionPlaylistById} from '../store/promiseReducer';
-import { actionFullSetPlaylist, actionFullSetTrack} from '../store/playerReducer';
-import { store } from '../store/store';
-import image from '../images/card.png';
-import {CreatePlaylist} from './createPlaylist';
-import { history } from '../App';
-import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
-import {
-    faAlignCenter,
-    faCompactDisc,
-    faHeadphonesSimple, faPlay,
-    faPlus,
-} from "@fortawesome/free-solid-svg-icons";
-import Button from "react-bootstrap/Button";
-
-
-
-const Playlist = ({playlist = {}}) => 
-  <div className="">
-      <div className="me-4 mb-4 p-4 playlist-img-box rounded-5 position-relative"
-           style={{backgroundImage: `url(${playlist.photo || image})`, backgroundSize: "cover", backgroundRepeat: "no-repeat", backgroundPosition: "center", width:250, height:250}}
-      >
-          <div className="playlist-grey-box"></div>
-          <Link className="d-flex border-0 link-light position-relative text-decoration-none h4 text-wrap"
-                to={`/playlist/${playlist.id}`}>
-              {playlist.name}
-          </Link>
-          <Button variant="outline-light" className='rounded-5 position-absolute playlist-play-box'  title='Play'>
-              <FontAwesomeIcon className='' icon={faPlay}
-                onClick={() => {
-                  store.dispatch(actionPlaylistById(playlist.id));
-                  setTimeout(() => {
-                      if(store.getState().promise?.plstById?.payload?.tracks) {
-                        let tracks = store.getState().promise?.plstById?.payload?.tracks;
-                        store.dispatch(actionFullSetPlaylist(tracks));
-                        store.dispatch(actionFullSetTrack(store.getState().player?.playlist[0]));
-                    }
-                    }
-                    , 500) 
-                }}
-              />
-          </Button>
-      </div>
-  </div>
-  
-  export const UsersPlaylistsAll = ({playlists= []}) => {
-    const [modalShow, setModalShow] = React.useState(false);
-    return (
-  <> 
-      <div className="d-flex justify-content-between align-items-center py-3">
-          <h3 className="text-uppercase"> <FontAwesomeIcon icon={faHeadphonesSimple} className="me-2"/>My playlists</h3>
-          <Button  variant="outline-success" title='Delete playlist' onClick={() => setModalShow(true)}>
-              <FontAwesomeIcon icon={faPlus} />
-          </Button>
-          <CreatePlaylist
-              show={modalShow}
-              onHide={() => setModalShow(false)}
-          />
-      </div>
-    <div className='RootCategories d-flex justify-content-start flex-wrap'>
-      {playlists.map((playlist, i) => <Playlist key={i} playlist={playlist}/>)}
-    </div> 
-  </>)
-  }
-
-const СUsersPlaylists = connect(state => ({playlists: state.promise.usersPlaylists?.payload?.playlists|| []}))(UsersPlaylistsAll);
-                                              
-
-export const UserPage = () => {
-let id = store.getState().auth?.user?.id;
-  const getAnswer = async () => {
-    await store.dispatch(actionUsersPlaylists(id));	
-  };
-
-  useEffect(() => {
-    getAnswer();
-  }, []);
-
-    return(<>
-    
-    <div className='d-flex  w-100'>
-            <div className='me-4 playlist-img-box rounded-5' style={{backgroundImage: `url(${store.getState().auth?.user?.avatar || image})`, backgroundSize: "cover", backgroundRepeat: "no-repeat", backgroundPosition: "center"}}>
-            </div>
-            <div className='w-100'>
-                <div className="d-flex flex-column justify-content-between h-100">
-                    <div className="w-100 row">
-                            <p className='h4 m-0'>{store.getState().auth?.user?.name}</p>
-
-                            <Link to={'/editprofile'} className="mb-3" >Edit Profile</Link>
-
-                            <p className='text-white-50 mb-2'><FontAwesomeIcon className='me-2' icon={faHeadphonesSimple} /> 100 Tracks</p>
-                            <p className='text-white-50 mb-2'><FontAwesomeIcon className='me-2' icon={faCompactDisc} /> 8 PLaylists</p>
-                            <p className='text-white-50 mb-2'><FontAwesomeIcon className='me-2' icon={faAlignCenter} />
-                                Lorem ipsum dolor sit amet, consectetur adipisicing elit. A aliquid amet animi aspernatur facere iste nisi omnis optio, vel vitae? Accusantium assumenda autem cumque ducimus eum ipsa, maiores pariatur repudiandae?
-                            </p>
-                    </div>
-                </div>
-            </div>
-        </div>
-    <СUsersPlaylists/>
-
-    </>)
-}

+ 68 - 0
src/components/userPlaylists.js

@@ -0,0 +1,68 @@
+import React from 'react';
+import {Link} from 'react-router-dom';
+import { actionPlaylistById} from '../store/promiseReducer';
+import { actionFullSetPlaylist, actionFullSetTrack} from '../store/playerReducer';
+import { store } from '../store/store';
+import image from '../images/card.jpg';
+import {CreatePlaylist} from './createPlaylist';
+import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
+import {faHeadphonesSimple, faPlay, faPlus, faLock,} from "@fortawesome/free-solid-svg-icons";
+import Button from "react-bootstrap/Button";
+
+
+
+export const Playlist = ({playlist}) => 
+  <div className="">
+      <div className="me-4 mb-4 p-4 playlist-img-box rounded-5 position-relative"
+           style={{backgroundImage: `url(${playlist.photo || image})`, backgroundSize: "cover", backgroundRepeat: "no-repeat", backgroundPosition: "center", width:250, height:250}}
+      >
+          <div className="playlist-grey-box"></div>
+          <Link className="d-flex justify-content-between flex-wrap border-0 link-light position-relative text-decoration-none h4 text-wrap"
+                to={`/playlist/${playlist.id}`} onClick={() => {
+                  store.dispatch(actionPlaylistById(playlist.id));
+                }}>
+              <span className="playlist-title w-75">{playlist.name}</span>
+              {store.getState().auth?.user?.id === playlist.user_id && playlist.private === 1 ?
+                  <span>
+                    <FontAwesomeIcon icon={faLock}></FontAwesomeIcon>
+                  </span> : null
+              }
+          </Link>
+          <Button variant="outline-light" className='rounded-5 position-absolute playlist-play-box'  title='Play'>
+              <FontAwesomeIcon className='' icon={faPlay}
+                onClick={() => {
+                  store.dispatch(actionPlaylistById(playlist.id));
+                  setTimeout(() => {
+                      if(store.getState().promise?.plstById?.payload?.tracks) {
+                        let tracks = store.getState().promise?.plstById?.payload?.tracks;
+                        store.dispatch(actionFullSetPlaylist(tracks));
+                        store.dispatch(actionFullSetTrack(store.getState().player?.playlist[0]));
+                    }
+                    }
+                    , 500) 
+                }}
+              />
+          </Button>
+      </div>
+  </div>
+  
+  export const UsersPlaylistsAll = ({playlists}) => {
+    const [modalShow, setModalShow] = React.useState(false);
+    return (
+  <> 
+      <div className="d-flex justify-content-between align-items-center py-3">
+          <h3 className="text-uppercase"> <FontAwesomeIcon icon={faHeadphonesSimple} className="me-2"/>My playlists</h3>
+          <Button  variant="outline-success" title='Create playlist' onClick={() => setModalShow(true)}>
+              <FontAwesomeIcon icon={faPlus} />
+          </Button>
+          <CreatePlaylist
+              show={modalShow}
+              onHide={() => setModalShow(false)}
+          />
+      </div>
+    <div className='RootCategories d-flex justify-content-start flex-wrap'>
+      {playlists.map((playlist, i) => <Playlist key={i} playlist={playlist}/>)}
+    </div> 
+  </>)
+  }
+

BIN
src/images/card.jpg


+ 33 - 0
src/index.css

@@ -38,6 +38,39 @@ code {
 .cursor-pointer {
   cursor: pointer;
 }
+.playlist-title {
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.track-name .line {
+  /*width: 100px;*/
+  display: inline-flex;
+}
+
+.track-name .second {
+  display: inline-flex;
+  white-space: nowrap;
+  overflow: hidden;
+  animation-play-state: paused;
+}
+
+.track-name .line .second span {
+  animation: ticker 6s linear infinite;
+}
+
+@keyframes ticker {
+  0% {
+    transform: translate(40%, 0);
+  }
+  50% {
+    transform: translate(-40%, 0);
+  }
+  100% {
+    transform: translate(40%, 0);
+  }
+}
+
 .playlist-play-box{
   bottom: 15px;
   right: 15px;

+ 15 - 2
src/pages/artistPage.js

@@ -1,5 +1,18 @@
+import { connect } from "react-redux"
+import { store } from "../store/store";
+import { PlaylistsAll } from "../components/Playlist";
+import { TracksAll } from "../components/Tracks";
 
+export const ArtistPage = ({artist}) => 
+<>
+ <>{artist.name}</>
+ <CArtistPlaylists/>
+ <CArtistTracks/>
+ </>
 
+ 
 
-export const ArtistPage = () => 
- <>Artist</>
+export const CArtistPage = connect(state => ({artist: state.promise.artistById?.payload || {}} ), )(ArtistPage);
+const CArtistPlaylists = connect(state => ({playlists: state.promise.artistById?.payload?.albums || []} ), )(PlaylistsAll);
+const CArtistTracks = connect(state => ({tracks: state.promise.artistById?.payload?.tracks || [],
+                                        playlist: state.promise.artistById?.payload || {},} ), )(TracksAll);

+ 39 - 0
src/pages/userPage.js

@@ -0,0 +1,39 @@
+import { store } from "../store/store";
+import { connect } from "react-redux";
+import { Link } from "react-router-dom";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import image from '../images/card.png';
+import {
+    faAlignCenter,
+    faCompactDisc,
+    faHeadphonesSimple} from "@fortawesome/free-solid-svg-icons";
+import {UsersPlaylistsAll} from '../components/userPlaylists';
+
+
+export const UserPage = ({user}) => {
+        return(<>
+        <div className='d-flex  w-100'>
+                <div className='me-4 playlist-img-box rounded-5' style={{backgroundImage: `url(${user?.avatar || image})`, backgroundSize: "cover", backgroundRepeat: "no-repeat", backgroundPosition: "center"}}>
+                </div>
+                <div className='w-100'>
+                    <div className="d-flex flex-column justify-content-between h-100">
+                        <div className="w-100 row">
+                                <p className='h4 m-0'>{store.getState().auth?.user?.name}</p>
+    
+                                <Link to={'/editprofile'} className="mb-3" >Edit Profile</Link>
+    
+                                <p className='text-white-50 mb-2'><FontAwesomeIcon className='me-2' icon={faHeadphonesSimple} /> 100 Tracks</p>
+                                <p className='text-white-50 mb-2'><FontAwesomeIcon className='me-2' icon={faCompactDisc} /> 8 PLaylists</p>
+                                <p className='text-white-50 mb-2'><FontAwesomeIcon className='me-2' icon={faAlignCenter} />
+                                    Lorem ipsum dolor sit amet, consectetur adipisicing elit. A aliquid amet animi aspernatur facere iste nisi omnis optio, vel vitae? Accusantium assumenda autem cumque ducimus eum ipsa, maiores pariatur repudiandae?
+                                </p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        <СUsersPlaylists/>
+        </>)
+    }
+    
+export const CUserPage = connect(state => ({user: state.auth?.user || {}} ) )(UserPage);
+export const СUsersPlaylists = connect(state => ({playlists: state.promise?.usersPlaylists?.payload?.playlists|| []}))(UsersPlaylistsAll);

+ 1 - 0
src/store/playerReducer.js

@@ -88,6 +88,7 @@ export const actionFullSetVolume = (volume) =>
 const actionSetTrack = (track) => ({type:'SET_TRACK', track})
 export const actionFullSetTrack = (track) =>
     dispatch => {
+        console.log(track)
         audio.src = `http://player-api/storage/tracks/${track?.file}`;
         dispatch(actionSetTrack(track));
         dispatch(actionFullPlay());

+ 4 - 1
src/store/promiseReducer.js

@@ -74,4 +74,7 @@ export const actionPlaylistById = (_id) =>
     {"login": login, "password": password});
 
     store.dispatch(actionAuthLogin(token));
-};
+};
+
+export const actionArtistById = (_id) => 
+actionPromise('artistById', gql('/artist/'+_id))