Browse Source

styled bootstrap css

mfdok43 2 years ago
parent
commit
4c34516a02

+ 31 - 0
package-lock.json

@@ -8,12 +8,14 @@
       "name": "music-player",
       "version": "0.1.0",
       "dependencies": {
+        "@popperjs/core": "^2.11.2",
         "@testing-library/jest-dom": "^5.16.1",
         "@testing-library/react": "^12.1.2",
         "@testing-library/user-event": "^13.5.0",
         "array-move": "^4.0.0",
         "jwt-decode": "^3.1.2",
         "node-sass": "^7.0.1",
+        "popper.js": "^1.16.1",
         "react": "^17.0.2",
         "react-dom": "^17.0.2",
         "react-dropzone": "^11.5.1",
@@ -2732,6 +2734,15 @@
         "node": ">= 8"
       }
     },
+    "node_modules/@popperjs/core": {
+      "version": "2.11.2",
+      "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz",
+      "integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==",
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/popperjs"
+      }
+    },
     "node_modules/@redux-saga/core": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/@redux-saga/core/-/core-1.1.3.tgz",
@@ -12787,6 +12798,16 @@
         "node": ">=4"
       }
     },
+    "node_modules/popper.js": {
+      "version": "1.16.1",
+      "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
+      "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
+      "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1",
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/popperjs"
+      }
+    },
     "node_modules/portfinder": {
       "version": "1.0.28",
       "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz",
@@ -19691,6 +19712,11 @@
         }
       }
     },
+    "@popperjs/core": {
+      "version": "2.11.2",
+      "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz",
+      "integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA=="
+    },
     "@redux-saga/core": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/@redux-saga/core/-/core-1.1.3.tgz",
@@ -27119,6 +27145,11 @@
         }
       }
     },
+    "popper.js": {
+      "version": "1.16.1",
+      "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
+      "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ=="
+    },
     "portfinder": {
       "version": "1.0.28",
       "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz",

+ 2 - 0
package.json

@@ -3,12 +3,14 @@
   "version": "0.1.0",
   "private": true,
   "dependencies": {
+    "@popperjs/core": "^2.11.2",
     "@testing-library/jest-dom": "^5.16.1",
     "@testing-library/react": "^12.1.2",
     "@testing-library/user-event": "^13.5.0",
     "array-move": "^4.0.0",
     "jwt-decode": "^3.1.2",
     "node-sass": "^7.0.1",
+    "popper.js": "^1.16.1",
     "react": "^17.0.2",
     "react-dom": "^17.0.2",
     "react-dropzone": "^11.5.1",

+ 8 - 22
public/index.html

@@ -10,34 +10,20 @@
       content="Web site created using create-react-app"
     />
     <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
-    <!--
-      manifest.json provides metadata used when your web app is installed on a
-      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-    -->
     <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
-    <!--
-      Notice the use of %PUBLIC_URL% in the tags above.
-      It will be replaced with the URL of the `public` folder during the build.
-      Only files inside the `public` folder can be referenced from the HTML.
 
-      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
-      work correctly both with client-side routing and a non-root public URL.
-      Learn how to configure a non-root public URL by running `npm run build`.
-    -->
+    <!-- Bootstrap CSS (Cloudflare CDN) -->
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.1/css/bootstrap.min.css" integrity="sha512-T584yQ/tdRR5QwOpfvDfVQUidzfgc2339Lc8uBDtcp/wYu80d7jwBgAxbyMh0a9YM9F8N3tdErpFI8iaGx6x5g==" crossorigin="anonymous" referrerpolicy="no-referrer">
+    <!-- jQuery (Cloudflare CDN) -->
+    <script defer src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
+    <!-- Bootstrap Bundle JS (Cloudflare CDN) -->
+    <script defer src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.1/js/bootstrap.min.js" integrity="sha512-UR25UO94eTnCVwjbXozyeVd6ZqpaAE9naiEUBK/A+QDbfSTQFhPGj5lOR6d8tsgbBk84Ggb5A3EkjsOgPRPcKA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js"></script>
+
     <title>React App</title>
   </head>
   <body>
     <noscript>You need to enable JavaScript to run this app.</noscript>
     <div id="root"></div>
-    <!--
-      This HTML file is a template.
-      If you open it directly in the browser, you will see an empty page.
-
-      You can add webfonts, meta tags, or analytics to this file.
-      The build step will place the bundled scripts into the <body> tag.
-
-      To begin the development, run `npm start` or `yarn start`.
-      To create a production bundle, use `npm run build` or `yarn build`.
-    -->
   </body>
 </html>

+ 101 - 6
src/App.scss

@@ -1,28 +1,94 @@
 .App {
   height: auto;
   text-align: center;
+  background: black;
+
+}
+
+a {
+  text-decoration: none;
+  color: white;
+}
+
+span {
+  color: #dbc9c9;
+  margin-left: 5px;
+}
+
+a:hover {
+  color: lawngreen;
+  text-decoration: none;
+}
+
+
+button {
+  color: white;
+  background: none;
+  font-weight: 70;
+  text-decoration: none;
+  outline: none;
+  border: 2px solid;
+  border-radius: 1px;
+  transition: 0.2s;
+}
+button:hover { background: rgba(255,255,255,.2); }
+button:active { background: white; }
+
+input {
+  background: rgba(26, 26, 26, 0.82);
+  color: white;
 }
 
 .App-logo {
+  margin: 6px;
   height: 100px;
 }
 
 .Header {
+  position: fixed;
+  top: 0px;
+  width: 100%;
   display: flex;
   justify-content: space-between;
-  background: #fc0874;
-height: 100px;
+  background: #000000;
+  -webkit-box-shadow: 0.2em 0.2em 5px rgba(122, 122, 122, 0.37);
+  box-shadow: 0.2em 0.2em 5px rgba(122, 122, 122, 0.376);
+
+
+  h2 {
+    color: white;
+    margin-top: 30px;
+  }
+  h2:hover {
+    color: lawngreen;
+  }
+
 }
 
 main {
+  background-image: url("background.jpg");
+  background-repeat: no-repeat;
+  background-attachment:fixed;
+  background-position:  200px 0px;
+  overflow: auto;
+  margin-top: 112px;
   width: 99%;
+  min-height: 840px;
   display: flex;
   flex-direction: row;
 }
 
 .Aside {
-  width: 20%;
-  background-color: cyan;
+  min-height: 1000px;
+  top: 114px;
+  position: fixed;
+  width: 430px;
+  background-color: red;
+}
+
+.Content {
+  margin-left: 440px;
+  margin-bottom: 120px;
 }
 
 .Avatar {
@@ -46,12 +112,12 @@ main {
 
 footer {
   width: 100%;
+  height: 100px;
   background-color: #303030;
   position: fixed;
  bottom: 0px;
   .Player {
-    background: white;
-
+    margin-top: 30px;
     button {
       margin: 5px;
     }
@@ -93,3 +159,32 @@ footer {
 
 
 
+
+.btn {
+  background: none;
+  border: none;
+}
+
+
+.dropdown-menu {
+  background: #000000;
+  text-align: center;
+  h3 {
+    color: lawngreen;
+  }
+}
+
+
+.dropdown-button {
+  font-size: 20px;
+  width: 100%;
+  border-radius: 3px;
+}
+
+.checkpass {
+  color: white;
+}
+
+.my-playlists {
+  margin-top: 8px;
+}

+ 0 - 2
src/actions/login-reg-actions.js

@@ -29,9 +29,7 @@ export function* fullLoginWorker (action) {
         yield put(actionUserFind())
         yield put(actionFindMyTracks())
         yield put(actionAboutMe())
-
     }
-
 }
 
 export function* fullLoginWatcher() {

BIN
src/background.jpg


File diff suppressed because it is too large
+ 1 - 1
src/next.svg


+ 0 - 1
src/pages/footer.js

@@ -3,6 +3,5 @@ import {CPlayer} from "./player";
 
 export const Footer = () =>
     <footer>
-        <Logo />
         <CPlayer />
     </footer>

+ 2 - 2
src/pages/header/avatar.js

@@ -19,9 +19,9 @@ function AvatarDropzone({onLoad}) {
         <div {...getRootProps()}>
             <input {...getInputProps()} />
             {isDragActive ? (
-                <p className=''>Перетащите файл сюда ...</p>
+               <button><p className=''>Перетащите файл сюда ...</p></button>
             ) : (
-                <p>Сменить аву, нажмите или перетащите файл</p>
+                <button>  <p>Сменить аву, нажмите или перетащите файл</p></button>
             )}
         </div>
     );

+ 16 - 26
src/pages/header/header-build.js

@@ -40,8 +40,8 @@ const ChangePasswordForm = ({onChangePassword}) => {
     const [p, setP] = useState ('')
     return (
         <div>
-            <input type='password' placeholder='Введите пароль' style={{backgroundColor:"skyblue"}} onChange={e => setP(e.target.value)}></input>
-            <button onClick={() => {onChangePassword(p); history.push('/')}}>Сменить пароль</button>
+            <input type='password' placeholder='Введите пароль' onChange={e => setP(e.target.value)}></input>
+            <button className='dropdown-button' onClick={() => {onChangePassword(p); history.push('/')}}>Сменить пароль</button>
         </div>
     )
 }
@@ -63,22 +63,6 @@ export const Header = () =>
     </header>
 
 
-const Spoiler = ({ header, children, open=false }) => {
-    const [openSpoiler, setOpenSpoiler] = useState(open)
-    return (
-        <>
-            <section className="Spoiler" onClick={() => setOpenSpoiler(!openSpoiler)}>
-                {header}
-            </section>
-            {openSpoiler && (
-                <div className="SpoilerContent">
-                    {children}
-                </div>
-            )}
-        </>
-    );
-};
-
 
 const LoginButtons = ({onLogout, history, token}) => {
     return (
@@ -87,14 +71,20 @@ const LoginButtons = ({onLogout, history, token}) => {
                 ( <div className='LoginButtons'>
                     <Link to='/login'><button onClick={() => history.push('/')}>Вход</button></Link>
                     <Link to='/registration'><button>Регистрация</button></Link></div>) :
-                (<div className='LoginColumn'>
-                    <Spoiler header={<CAvatar/>}>
-                        <strong>{JSON.parse(atob(token.split(".")[1])).sub.login}</strong>
-                        <CAvatarDropZone />
-                        <CChangePasswordForm/>
-                        <button onClick={() => {onLogout(); history.push('/')}}>Выйти</button>
-                    </Spoiler>
-                </div>)
+                (<div className="btn-group">
+                        <button type="button" className="btn btn-secondary dropdown-toggle" data-toggle="dropdown"
+                                aria-haspopup="true" aria-expanded="false">
+                            <CAvatar/>
+                        </button>
+                        <div className="dropdown-menu dropdown-menu-right">
+                            <h3>{JSON.parse(atob(token.split(".")[1])).sub.login}</h3>
+                            <CAvatarDropZone />
+                            <CChangePasswordForm/>
+                            <button className='dropdown-button' onClick={() => {onLogout(); history.push('/')}}>Выйти</button>
+                        </div>
+                    </div>
+
+                )
             }
         </>
     )

+ 2 - 2
src/pages/header/login.js

@@ -11,8 +11,8 @@ const LoginForm = ({onLogin, history}) => {
 
     return (
         <div className='LoginColumn'>
-            <input placeholder='Введите имя' style={{backgroundColor:"skyblue"}} onChange={e => setL(e.target.value)}></input>
-            <input type='password' placeholder='Введите пароль' style={{backgroundColor:"skyblue"}} onChange={e => setP(e.target.value)}></input>
+            <input placeholder='Введите имя' onChange={e => setL(e.target.value)}></input>
+            <input type='password' placeholder='Введите пароль' onChange={e => setP(e.target.value)}></input>
             <button onClick={() => {onLogin(l,p); history.push('/')}}>Войти</button>
         </div>
     )

+ 2 - 5
src/pages/header/registration.js

@@ -13,20 +13,17 @@ const RegForm = ({ onReg }) => {
 
             <div className='RegColumn'>
                 <input placeholder='Введите имя'
-                       style={{ backgroundColor: "skyblue" }}
                        onChange={(e) => setL(e.target.value)}></input>
 
                 <input placeholder='Введите пароль'
-                       style={{ backgroundColor: "skyblue" }}
                        onChange={(e) => setP(e.target.value)}></input>
-                <div>{p.length < 6 ? 'Короткий пароль' : 'Хороший пароль'}</div>
+                <div className='checkpass'>{p.length < 6 ? 'Короткий пароль' : 'Хороший пароль'}</div>
             </div>
             <div className='RegColumn'>
                 <button disabled={p.length >= 6 && p === p2 && l !== "" ? false : true} onClick={() => {onReg(l, p); history.push('/')}}>Регистрация</button>
                 <input placeholder='Подтвердите пароль'
-                       style={{ backgroundColor: "skyblue" }}
                        onChange={(e) => setP2(e.target.value)}></input>
-                <div>{p === p2 ? 'Пароли совпадают' : 'Пароли не совпадают'}</div>
+                <div className='checkpass'>{p === p2 ? 'Пароли совпадают' : 'Пароли не совпадают'}</div>
             </div>
         </div>
     );

+ 1 - 1
src/pages/main.js

@@ -14,7 +14,7 @@ export const Aside = ({children}) =>
     </div>
 
 export const Content = ({children}) =>
-    <div>
+    <div className='Content'>
         {children}
     </div>
 

+ 1 - 1
src/pages/my-tracks/my-playlists.js

@@ -10,7 +10,7 @@ const Playlist = ({playlist:{_id, name}={}}) =>
 const MyPlaylists =  ({playlists={},onCreatePlaylist}) => {
     const [p, setP] = useState ('')
     return (
-        <div>
+        <div className='my-playlists'>
             <input placeholder='Название' onChange={e => setP(e.target.value)}/>
             <button disabled={p.length >= 6  && p !== "" ? false : true} onClick={() => {onCreatePlaylist(p)}}>Создать плейлист</button>
             <ul className='Users'>

+ 5 - 7
src/pages/my-tracks/my-tracks.js

@@ -5,27 +5,25 @@ import {SortableContainer, SortableElement} from 'react-sortable-hoc';
 import {arrayMoveImmutable} from 'array-move';
 import {useState,useEffect} from "react";
 import {CPreloaded} from "../preloader";
-
-
-
-
+import {actionSetPlaylist} from "../../reducers";
 
 
 const MyTracks = ({playlist:{_id, name, tracks}={}}) =>
     <div className='Category'>
         <h1>{name}</h1>
+        <CPreloaded promiseName='playlistById'>
         {(tracks || []).map(track => <CTrack track={track}/>)}
+        </CPreloaded>
     </div>
 
-const CMyTracks = connect(state => ({playlist: state.promise.playlistById?.payload || []}))(MyTracks)
+const CMyTracks = connect(state => ({playlist: state.promise.playlistById?.payload || []}),
+    {setPlaylist: actionSetPlaylist})(MyTracks)
 
 
 export const MyPlaylistTracks = ({match:{params:{_id}}}) =>
     <>
         <CPlaylistDropZone >
-            <CPreloaded promiseName='playlistById'>
             <CMyTracks />
-            </CPreloaded>
      </CPlaylistDropZone >
     </>
 

+ 5 - 5
src/pages/player.js

@@ -6,7 +6,7 @@ import {connect} from "react-redux";
 import {actionTrackPlay, actionTrackStop,actionTrackVolume,actionTrackCurrentTime} from "../reducers";
 
 
-export const Player = ({player:{volume,duration,currentTime},
+export const Player = ({player:{volume,duration,currentTime,isPlaying},
                                 trackPlay, trackStop,trackVolume,trackCurrentTime}) => {
     return (
         <div className='Player'>
@@ -20,12 +20,12 @@ export const Player = ({player:{volume,duration,currentTime},
                 value={currentTime}/>
 
             <button><img src={prev}/></button>
+            {!isPlaying ? (   <button onClick={() => trackPlay()}>
+                <img src={play}/></button>) : (     <button onClick={() => trackStop()}>
+                <img src={pause}/></button>)}
+
 
-            <button onClick={() => trackPlay()}>
-                <img src={play}/></button>
 
-            <button onClick={() => trackStop()}>
-                <img src={pause}/></button>
 
             <button><img src={next}/></button>
             <input

+ 2 - 2
src/pages/preloader/preloader.css

@@ -11,15 +11,15 @@
     top: 20px;
     left: 20px;
     border-radius: 50%;
-    box-shadow: 0 4px 0 0 #e15b64;
+    box-shadow: 0 4px 0 0 #bde15b;
     transform-origin: 80px 82px;
 }
 .loadingio-spinner-eclipse-leb3x7lyjtj {
+    position: fixed;
     width: 200px;
     height: 200px;
     display: inline-block;
     overflow: hidden;
-    background: #ffffff;
 }
 .ldio-vhhfhwlovld {
     width: 100%;

+ 1 - 2
src/pages/preloader/preloader.js

@@ -10,9 +10,8 @@ export const Preloader = () =>
         </div>
     </div>
 
-const RejectAlert = ({error}) =>
+const RejectAlert = () =>
     <div>
-        <h2>{error}</h2>
         <img src={logo} alt='logo'/>
     </div>
 

+ 2 - 2
src/pages/track.js

@@ -1,7 +1,7 @@
 import {useState,useEffect,useRef} from "react";
 import play from '../play.svg'
 import pause from '../pause.svg'
-import {store,actionTrackPlay,actionTrackStop,actionFullSetPlaylist} from "../reducers";
+import {store,actionTrackPlay,actionTrackStop,actionSetPlaylist} from "../reducers";
 import {connect} from "react-redux";
 import {backURL} from "../actions";
 
@@ -31,4 +31,4 @@ export const Track = ({playlist=['fdgdf','dgdfgfd','dgdfgdfgdf'],track:{_id,url,
 
 
 export const CTrack = connect(state => ({playlist: state.promise.playlistById?.payload?.tracks || []}),
-    {trackPlay: actionTrackPlay, trackStop: actionTrackStop,setPlaylist:actionFullSetPlaylist})(Track)
+    {trackPlay: actionTrackPlay, trackStop: actionTrackStop,setPlaylist:actionSetPlaylist})(Track)

File diff suppressed because it is too large
+ 1 - 1
src/pause.svg


+ 1 - 1
src/play.svg

@@ -1,3 +1,3 @@
 <svg width="14" height="16" viewBox="0 0 14 16" fill="none" xmlns="http://www.w3.org/2000/svg">
-    <path fill-rule="evenodd" clip-rule="evenodd" d="M11.907 7.99997L1.75 2.10772V13.8922L11.907 7.99997ZM13.293 6.78197C13.5076 6.90481 13.6858 7.08214 13.8098 7.29602C13.9339 7.5099 13.9992 7.75275 13.9992 7.99997C13.9992 8.2472 13.9339 8.49004 13.8098 8.70392C13.6858 8.9178 13.5076 9.09514 13.293 9.21797L2.15775 15.679C1.24775 16.2075 0 15.6037 0 14.461V1.53897C0 0.396223 1.24775 -0.207528 2.15775 0.320972L13.293 6.78197Z" fill="black"/>
+    <path fill-rule="evenodd" clip-rule="evenodd" d="M11.907 7.99997L1.75 2.10772V13.8922L11.907 7.99997ZM13.293 6.78197C13.5076 6.90481 13.6858 7.08214 13.8098 7.29602C13.9339 7.5099 13.9992 7.75275 13.9992 7.99997C13.9992 8.2472 13.9339 8.49004 13.8098 8.70392C13.6858 8.9178 13.5076 9.09514 13.293 9.21797L2.15775 15.679C1.24775 16.2075 0 15.6037 0 14.461V1.53897C0 0.396223 1.24775 -0.207528 2.15775 0.320972L13.293 6.78197Z" fill="white"/>
 </svg>

File diff suppressed because it is too large
+ 1 - 1
src/prev.svg


+ 1 - 1
src/reducers/index.js

@@ -2,7 +2,7 @@ export {store} from './store'
 export {actionPromise} from './promiseReducer'
 
 export {playerReducer,actionTrackPlay,actionTrackStop,
-    actionTrackVolume,actionTrackCurrentTime,actionFullSetPlaylist} from "./playerReducer";
+    actionTrackVolume,actionTrackCurrentTime,actionSetPlaylist} from "./playerReducer";
 
 export {actionAuthLogin, actionAuthLogout} from './authReducer'
 export {CProtectedRoute} from "./routeReducer";

+ 19 - 19
src/reducers/playerReducer.js

@@ -66,7 +66,7 @@ export const actionTrackPlay = (audioSrc) => {
     audio.ontimeupdate = function(){actionTrackCurrentTime()}
     audio.play()
     store.dispatch({type:"TRACK_PLAY",isPlaying:true,isPaused:false})
-    store.dispatch(actionFullSetPlaylist())
+    store.dispatch(actionSetPlaylist())
 }
 
 
@@ -92,26 +92,26 @@ export const actionTrackCurrentTime = () => {
     store.dispatch({type:"TRACK_CURRENT_TIME", currentTime:e})
 }
 
-const actionSetPlaylist = (tracks) => {
-    console.log(tracks)
+export const actionSetPlaylist = (tracks) => {
+    console.log(tracks,'lol')
         store.dispatch({type:"SET_PLAYLIST",playlist:tracks})
     }
 
 
 
-const actionPlaylistByIdForPlayer = (match) =>
-    actionPromise('playlistByIdForPlayer', gql(`query playlistByIdForPlayer($q: String){
-    PlaylistFindOne(query: $q){
-        _id name owner {login} tracks {_id url originalFileName}
-    }
-}`, { q: JSON.stringify([{ _id: match.params._id}]) }))
-
-
-
-export const actionFullSetPlaylist = (_id) =>
-    async function i(dispatch) {
-        let playlist = await dispatch(actionPlaylistByIdForPlayer(_id));
-        if (playlist) {
-            dispatch(actionSetPlaylist(playlist));
-        }
-    }
+// const actionPlaylistByIdForPlayer = (match) =>
+//     actionPromise('playlistByIdForPlayer', gql(`query playlistByIdForPlayer($q: String){
+//     PlaylistFindOne(query: $q){
+//         _id name owner {login} tracks {_id url originalFileName}
+//     }
+// }`, { q: JSON.stringify([{ _id: match.params._id}]) }))
+//
+//
+//
+// export const actionFullSetPlaylist = (_id) =>
+//     async function i(dispatch) {
+//         let playlist = await dispatch(actionPlaylistByIdForPlayer(_id));
+//         if (playlist) {
+//             dispatch(actionSetPlaylist(playlist));
+//         }
+//     }