fix player + add playlist
This commit is contained in:
parent
6680fd8792
commit
7f8d3e6f86
|
|
@ -7,7 +7,7 @@ ROBOTS_USER_AGENT=*
|
|||
ROBOTS_ALLOW=
|
||||
ROBOTS_DISALLOW=["/"]
|
||||
SERVICE_SELF_URL=//it-radio.flexidev.ru
|
||||
SERVICE_URL=//it-radio.flexidev.ru
|
||||
SERVICE_URL=//82.97.242.49
|
||||
SERVICE_URL_AUDIO=//82.97.242.49:10084
|
||||
SERVICE_PROTOCOL=http
|
||||
SERVICE_PORT=8000
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
<AppFooter/>
|
||||
</div>
|
||||
<Authentication/>
|
||||
<ChangingUser/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -17,13 +18,15 @@ import Page404 from '@/views/Page404.vue';
|
|||
import Page500 from '@/views/Page500.vue';
|
||||
import AppHeader from "@/components/app-header.vue";
|
||||
import AppFooter from "@/components/app-footer.vue";
|
||||
import Authentication from "@/components/authentication.vue";
|
||||
import Authentication from "@/components/modal/authentication.vue";
|
||||
import Player from "@/components/player.vue";
|
||||
import ChangingUser from "@/components/modal/сhanging-user.vue";
|
||||
|
||||
export default {
|
||||
async preFetch({store, currentRoute, previousRoute, redirect, ssrContext, urlPath, publicPath}) {
|
||||
},
|
||||
components: {
|
||||
ChangingUser,
|
||||
Player,
|
||||
Authentication,
|
||||
AppFooter,
|
||||
|
|
@ -47,10 +50,15 @@ export default {
|
|||
showErrorPage500() {
|
||||
return false
|
||||
// return this.$store.state.showErrorPage?.response?.status === 500;
|
||||
}
|
||||
},
|
||||
currentPlay() {
|
||||
return this.$store.state.currentPlay
|
||||
},
|
||||
},
|
||||
watch: {},
|
||||
created() {
|
||||
this.$store.dispatch('setCurrentPlay', {...this.currentPlay, isPlay: false});
|
||||
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
@import "./module/tabs.scss";
|
||||
@import "./module/about.scss";
|
||||
@import "./module/playlists.scss";
|
||||
@import "./module/playlist.scss";
|
||||
@import "./module/contacts.scss";
|
||||
@import "./module/support.scss";
|
||||
@import "./module/player.scss";
|
||||
|
|
|
|||
|
|
@ -95,13 +95,15 @@
|
|||
|
||||
&:hover::after {
|
||||
background: svg-load('./assets/img/icon/ArrowRight.svg', stroke=#232323) no-repeat 100%;
|
||||
}
|
||||
|
||||
&.m--active::after,
|
||||
&:active::after {
|
||||
width: 45px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
&.m--active,
|
||||
&:active {
|
||||
background:transparent;
|
||||
color: var(--color-white);
|
||||
}
|
||||
}
|
||||
|
||||
&.m--w-100 {
|
||||
|
|
@ -135,6 +137,7 @@
|
|||
pad: 0;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
padding: 0;
|
||||
&:hover{
|
||||
background: transparent;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,24 @@
|
|||
.input {
|
||||
@mixin input;
|
||||
}
|
||||
&__input{
|
||||
&.m--search {
|
||||
position: relative;
|
||||
&:before{
|
||||
content: '';
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
top: 16px;
|
||||
left: 16px;
|
||||
position: absolute;
|
||||
background: svg-load('./assets/img/icon/search-icon.svg') no-repeat 100%;
|
||||
}
|
||||
.input{
|
||||
padding: 1rem 1.2rem 1rem 3rem;
|
||||
border: 1px solid var(--color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
&__checkbox {
|
||||
&-label{
|
||||
padding-left: 50px;
|
||||
|
|
|
|||
|
|
@ -48,7 +48,13 @@
|
|||
max-width: 420px;
|
||||
}
|
||||
}
|
||||
|
||||
&__content{
|
||||
min-width: 360px;
|
||||
}
|
||||
&__title{
|
||||
font-size: 2rem;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
&__close{
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
|
|
|
|||
|
|
@ -30,11 +30,13 @@
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-left: 20px;
|
||||
min-width: 135px;
|
||||
gap: 0.25rem;
|
||||
span {
|
||||
color: var(--color-white-opacity);
|
||||
}
|
||||
&.m--skeleton{
|
||||
min-width: 135px;
|
||||
}
|
||||
}
|
||||
|
||||
&__favorites {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
.playlist {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
&-roster {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: calc(var(--space-between-block) / 2);
|
||||
width: 100%;
|
||||
}
|
||||
&-edit{
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
&__search{
|
||||
margin-bottom: var(--space-between-block);
|
||||
}
|
||||
&__search{
|
||||
min-width: 320px;
|
||||
width: 40%;
|
||||
}
|
||||
&__list{
|
||||
display: flex;
|
||||
gap: var(--space-between-block);
|
||||
}
|
||||
&__item{
|
||||
width: calc(50% - var(--space-between-block) / 2) ;
|
||||
}
|
||||
&__title{
|
||||
color: transparent;
|
||||
font-size: 2rem;
|
||||
background-clip: text;
|
||||
background-image: var(--linear-gradient);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
&-item {
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 220px;
|
||||
cursor: url("./assets/img/icon/cursor.svg"), auto;
|
||||
|
||||
&__cover {
|
||||
background: svg-load('./assets/img/icon/playlist-item.svg', fill=$color-white) no-repeat 100%;
|
||||
border-radius: 10px;
|
||||
margin-bottom: 10px;
|
||||
transition: all .3s ease;
|
||||
min-height: 220px;
|
||||
&:hover{
|
||||
background: svg-load('./assets/img/icon/playlist-item.svg', fill=$color-white-opacity) no-repeat 100%;
|
||||
border-radius: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&.m--create &__cover {
|
||||
position: relative;
|
||||
background: var(--bg-opacity);
|
||||
&:after {
|
||||
content: '';
|
||||
width: 63px;
|
||||
height: 63px;
|
||||
background: svg-load('./assets/img/icon/playlist-item-create.svg', fill=$color-white-opacity) no-repeat 100%;
|
||||
transition: all .3s ease;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
}
|
||||
&:hover{
|
||||
background: var(--color-primary);
|
||||
&:after{
|
||||
background: svg-load('./assets/img/icon/playlist-item-create.svg', fill=$color-white) no-repeat 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
&__title {
|
||||
margin-bottom: 0.5rem;
|
||||
padding: 0;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
&__tabs{
|
||||
margin-top: var(--space-between-block);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@
|
|||
flex-wrap: wrap;
|
||||
gap: 0 var(--space-between-block);
|
||||
}
|
||||
.m--column &-item{
|
||||
width: 100%;
|
||||
}
|
||||
&-item {
|
||||
width: calc(50% - var(--space-between-block) / 2);
|
||||
position: relative;
|
||||
|
|
@ -12,38 +15,48 @@
|
|||
z-index: 2;
|
||||
border-left: 3px solid transparent;
|
||||
padding: 10px;
|
||||
transition: all .5s ease;
|
||||
transition: border .5s ease, background .5s ease;
|
||||
background: transparent;
|
||||
@mixin responsive-m {
|
||||
width: 100%;
|
||||
}
|
||||
&.m--select &__selected {
|
||||
margin-right: 20px;
|
||||
width: 35px;
|
||||
height: 33px;
|
||||
|
||||
&.m--stop {
|
||||
path {
|
||||
animation-play-state: paused;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__selected {
|
||||
width: 0;
|
||||
overflow: hidden;
|
||||
transition: all .2s ease;
|
||||
|
||||
path:nth-child(n) {
|
||||
animation: play-transform 3s infinite linear;
|
||||
}
|
||||
|
||||
path:nth-child(2n) {
|
||||
animation: play-transform 2s infinite linear;
|
||||
}
|
||||
|
||||
path:nth-child(3n) {
|
||||
animation: play-transform 1.5s infinite linear;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: url("./assets/img/icon/cursor.svg"), auto;
|
||||
border-color: var(--color-primary);
|
||||
background: linear-gradient(90deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%);
|
||||
}
|
||||
|
||||
&__btn {
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
|
|
@ -53,11 +66,13 @@
|
|||
border: none;
|
||||
background: var(--color-primary);
|
||||
position: relative;
|
||||
|
||||
&.m--small {
|
||||
background: transparent;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
}
|
||||
|
||||
&.m--favorites {
|
||||
&:after {
|
||||
content: '';
|
||||
|
|
@ -75,6 +90,7 @@
|
|||
background-size: contain;
|
||||
}
|
||||
}
|
||||
|
||||
&.m--add {
|
||||
&:after {
|
||||
content: '';
|
||||
|
|
@ -92,6 +108,24 @@
|
|||
background-size: contain;
|
||||
}
|
||||
}
|
||||
&.m--already{
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
margin: auto;
|
||||
background: svg-load('./assets/img/icon/icon-trash.svg', stroke=$color-primary) no-repeat 100%;
|
||||
background-size: contain;
|
||||
transition: all .3s ease;
|
||||
}
|
||||
|
||||
&:hover:after {
|
||||
background: svg-load('./assets/img/icon/icon-trash.svg', stroke=#FFF) no-repeat 100%;
|
||||
background-size: contain;
|
||||
}
|
||||
}
|
||||
|
||||
&.m--play {
|
||||
&:after {
|
||||
content: '';
|
||||
|
|
@ -128,6 +162,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
@ -135,10 +170,12 @@
|
|||
color: var(--color-white-opacity);
|
||||
line-height: 21px;
|
||||
margin-left: 20px;
|
||||
|
||||
span {
|
||||
color: var(--color-white);
|
||||
}
|
||||
}
|
||||
|
||||
&__tools {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
|
|
@ -147,6 +184,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes play-transform {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,15 @@
|
|||
.tabs {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: var(--space-between-block);
|
||||
&.m--btns{
|
||||
gap: 10px;
|
||||
@mixin responsive-xs {
|
||||
.button{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
&__item {
|
||||
border: none;
|
||||
|
|
|
|||
|
|
@ -6,16 +6,17 @@ $document-width-xs: 640px;
|
|||
$document-width-xxs: 480px;
|
||||
$color-primary: #5E5BFC;
|
||||
$color-white: #FFFFFF;
|
||||
$color-white-opacity: #BBB9CA;
|
||||
:root {
|
||||
--color-black: #232323;
|
||||
--color-white: $color-white;
|
||||
--color-white-darker: #E7E7E7;
|
||||
--color-white-opacity: #BBB9CA;
|
||||
--color-white-opacity: $color-white-opacity;
|
||||
--bg-wrapper-modal: #000000E5;
|
||||
--color-primary: $color-primary;
|
||||
--color-black-cc: #000000CC;
|
||||
--color-emmit: #E81717;
|
||||
--bg-opacity: rgba(255, 255, 255, 0.15);
|
||||
--bg-opacity: #74767D;
|
||||
--base-fz: 18px;
|
||||
--base-lh: 1.3;
|
||||
--font-family-base: 'Manrope', 'Tahoma', sans-serif;
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ export default {
|
|||
methods:{
|
||||
handlerClick(methods){
|
||||
if (methods==='login'){
|
||||
this.$store.dispatch('setShowAuthModal', true);
|
||||
this.$store.dispatch('setModal', {auth: true});
|
||||
}
|
||||
if (methods==='profile'){
|
||||
this.next('profile')
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
show() {
|
||||
return this.$store.state.showAuthModal
|
||||
return this.$store.state.modal.auth
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -192,7 +192,7 @@ export default {
|
|||
|
||||
},
|
||||
close() {
|
||||
this.$store.dispatch('setShowAuthModal', false);
|
||||
this.$store.dispatch('setModal', {auth: false});
|
||||
},
|
||||
next(name) {
|
||||
this.$router.push({name});
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
<template>
|
||||
<vue-final-modal
|
||||
v-model="show"
|
||||
class="modal__container"
|
||||
content-class="modal__block"
|
||||
content-transition="vfm-fade"
|
||||
overlay-transition="vfm-fade"
|
||||
:clickToClose="false"
|
||||
@click-outside="close()"
|
||||
>
|
||||
<button
|
||||
class="button modal__close"
|
||||
@click="close"
|
||||
>
|
||||
</button>
|
||||
<div class="modal__content">
|
||||
<div class="modal__title">Изменение данных</div>
|
||||
<FormKit
|
||||
v-model="formData"
|
||||
type="form"
|
||||
data-loading="showLoaderSending"
|
||||
form-class="$reset registration__form form"
|
||||
submit-label="Войти"
|
||||
:disabled="showLoaderSending"
|
||||
:loading="showLoaderSending ? true : undefined"
|
||||
:submit-attrs="{
|
||||
inputClass: '$reset button m--white m--w-100',
|
||||
wrapperClass: '$reset registration__form-submit form__submit',
|
||||
outerClass: '$reset',
|
||||
}"
|
||||
@submit="submitHandler"
|
||||
>
|
||||
<FormKitSchema :schema="userForm"/>
|
||||
</FormKit>
|
||||
</div>
|
||||
</vue-final-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {app} from "@/services";
|
||||
|
||||
export default {
|
||||
name: 'recovery',
|
||||
data(){
|
||||
return{
|
||||
userForm:[
|
||||
{
|
||||
$formkit: 'text',
|
||||
name: 'email',
|
||||
label: 'Ваша почта',
|
||||
placeholder: 'Ваша почта',
|
||||
validation: 'required',
|
||||
outerClass: 'field--required'
|
||||
},
|
||||
{
|
||||
$formkit: 'password',
|
||||
name: 'old_password',
|
||||
label: 'Введите старый пароль',
|
||||
placeholder: 'Введите старый пароль',
|
||||
validation: 'required',
|
||||
outerClass: 'field--required'
|
||||
},
|
||||
{
|
||||
$formkit: 'password',
|
||||
name: 'password',
|
||||
label: 'Введите новый пароль',
|
||||
placeholder: 'Введите новый пароль',
|
||||
validation: 'required',
|
||||
outerClass: 'field--required'
|
||||
}
|
||||
],
|
||||
formData: {},
|
||||
showLoaderSending: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
user() {
|
||||
return this.$store.state.user;
|
||||
},
|
||||
show(){
|
||||
return this.$store.state.modal.changingUser;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.formData.email = this.user.email;
|
||||
},
|
||||
methods:{
|
||||
submitHandler(data, node){
|
||||
this.showLoaderSending = true;
|
||||
app.updateUser(this.formData).then(user=>{
|
||||
this.showLoaderSending = false;
|
||||
this.$store.dispatch('setUser', user);
|
||||
}).catch(err=>{
|
||||
this.showLoaderSending = false;
|
||||
node.setErrors(
|
||||
[err.detail],
|
||||
err.error
|
||||
)
|
||||
})
|
||||
},
|
||||
close() {
|
||||
this.$store.dispatch('setModal', {changingUser: false});
|
||||
},
|
||||
next(name){
|
||||
this.$router.push({name});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
</button>
|
||||
</template>
|
||||
<div class="player__executor">
|
||||
<q-skeleton v-if="loaderPlay"/>
|
||||
<q-skeleton v-if="loaderPlay" class="player__executor m--skeleton"/>
|
||||
<template v-else>
|
||||
{{ currentPlay.title || '—' }}
|
||||
</template>
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
v-model="isUserMusic"
|
||||
type="toggle"
|
||||
label="Включить мою музыку"
|
||||
:disabled="!user?.id"
|
||||
:disabled="!user?.id || userSongList.length === 0"
|
||||
/>
|
||||
<q-skeleton v-if="loaderPlay" class="player__tools m--skeleton"/>
|
||||
<div v-else class="player__volume">
|
||||
|
|
@ -71,7 +71,6 @@ export default {
|
|||
components: {},
|
||||
data() {
|
||||
return {
|
||||
audioUrl: 'http://82.97.242.49:18000/radio.mp3',
|
||||
isFavorites: false,
|
||||
isPlayRadio: false,
|
||||
connection: null,
|
||||
|
|
@ -108,7 +107,7 @@ export default {
|
|||
if (this.isUserMusic === this.currentPlay.live) {
|
||||
this.isUserMusic = !this.currentPlay.live;
|
||||
}
|
||||
if (to.id !== from.id && this.user?.id) {
|
||||
if (this.user?.id && to.id !== from.id) {
|
||||
this.checkSongIsFavorite();
|
||||
}
|
||||
if (!this.currentPlay.live && to.id !== from.id) {
|
||||
|
|
@ -116,6 +115,14 @@ export default {
|
|||
}
|
||||
},
|
||||
},
|
||||
'userSongList': {
|
||||
immediate: false,
|
||||
handler(to, from) {
|
||||
if (this.user?.id && to.length !== from.length) {
|
||||
this.checkSongIsFavorite();
|
||||
}
|
||||
},
|
||||
},
|
||||
'isUserMusic': {
|
||||
immediate: false,
|
||||
handler() {
|
||||
|
|
@ -133,16 +140,19 @@ export default {
|
|||
this.$store.dispatch('initPlayer');
|
||||
if (this.user?.id) {
|
||||
this.checkSongIsFavorite();
|
||||
this.getSongList();
|
||||
}
|
||||
this.playerInfo.progress = this.currentPlay.live ? 100 : 0;
|
||||
console.log(this.currentPlay)
|
||||
if (!this.currentPlay.live && this.userSongList?.length > 0) {
|
||||
this.$store.dispatch('setCurrentPlay', {...this.userSongList[0], live: false});
|
||||
this.getAudio(this.userSongList[0]?.azura_id);
|
||||
this.$store.dispatch('setCurrentPlay', {...this.userSongList[this.currentPlay.currentIndex || 0], live: false});
|
||||
this.getAudio(this.userSongList[this.currentPlay.currentIndex || 0]?.azura_id);
|
||||
if (this.player.target) {
|
||||
this.player.target.addEventListener('timeupdate', this.updateProgress)
|
||||
}
|
||||
}
|
||||
if (!this.user?.id){
|
||||
this.$store.dispatch('setCurrentPlay', {...this.currentPlay, live: true, isLoader: true, currentIndex: null});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
connectionPlayer() {
|
||||
|
|
@ -154,7 +164,6 @@ export default {
|
|||
this.connection.onHandler(this.getPlaying);
|
||||
},
|
||||
checkSongIsFavorite() {
|
||||
console.debug(this.currentPlay.azura_id || this.currentPlay.id, this.currentPlay.title)
|
||||
app.getCheckFavoriteSong(this.currentPlay.azura_id || this.currentPlay.id).then(res => {
|
||||
this.isFavorites = res.is_favorite;
|
||||
}).catch(err => {
|
||||
|
|
@ -177,18 +186,19 @@ export default {
|
|||
if (data.np.station.listen_url !== this.player.target.src) {
|
||||
console.log('data.np.station.listen_url', data.np.station.listen_url)
|
||||
this.$store.dispatch('changePlayer', data.np.station.listen_url);
|
||||
}
|
||||
const params = {
|
||||
...this.currentPlay,
|
||||
...data.np.now_playing.song,
|
||||
azura_id: data.np.now_playing.song.id,
|
||||
isLoader: false,
|
||||
live: true,
|
||||
currentIndex: null
|
||||
}
|
||||
delete params.unique_id;
|
||||
this.$store.dispatch('setCurrentPlay', params);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
updateProgress(e) {
|
||||
this.playerInfo = {
|
||||
|
|
@ -197,10 +207,16 @@ export default {
|
|||
currentTime: this.player.target.currentTime
|
||||
}
|
||||
if (this.player.target.currentTime === this.player.target.duration){
|
||||
this.getAudio(this.userSongList[1]?.azura_id);
|
||||
let currentIndex = this.currentPlay.currentIndex + 1;
|
||||
if (!this.userSongList[currentIndex]?.azura_id || currentIndex === null){
|
||||
currentIndex = 0;
|
||||
}
|
||||
this.$store.dispatch('setCurrentPlay', {...this.currentPlay, ...this.userSongList[currentIndex], currentIndex})
|
||||
}
|
||||
},
|
||||
handlerPlay() {
|
||||
console.log(this.currentPlay)
|
||||
console.log(this.player)
|
||||
this.$store.dispatch('handlerPlayer', {play: true});
|
||||
},
|
||||
handlerPause() {
|
||||
|
|
@ -209,13 +225,17 @@ export default {
|
|||
getSongList() {
|
||||
app.getFavoriteList().then(res => {
|
||||
this.$store.dispatch('setUserFavorite', {songs: res})
|
||||
console.log('res.length' ,res.length)
|
||||
if (res.length === 0){
|
||||
this.$store.dispatch('setCurrentPlay', {...this.currentPlay, live: true, isLoader: true});
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error(err)
|
||||
})
|
||||
},
|
||||
handlerFavorites() {
|
||||
if (this.user?.id) {
|
||||
const params = {...this.currentPlay, azura_id: this.currentPlay.id};
|
||||
const params = {...this.currentPlay, azura_id: Number(this.currentPlay.id)?this.currentPlay.azura_id:this.currentPlay.id};
|
||||
if (!this.isFavorites) {
|
||||
delete params.id;
|
||||
app.createFavoriteForUser(params).then(() => {
|
||||
|
|
@ -252,7 +272,6 @@ export default {
|
|||
app.getAudio(id).then(res => {
|
||||
const blob = new Blob([res], {type: 'application/audio'});
|
||||
const audioUrl = URL.createObjectURL(blob);
|
||||
this.$store.dispatch('setCurrentPlay', {...this.currentPlay, isLoader: false})
|
||||
this.$store.dispatch('changePlayer', audioUrl);
|
||||
this.player.target.addEventListener('timeupdate', this.updateProgress);
|
||||
|
||||
|
|
@ -263,6 +282,7 @@ export default {
|
|||
this.playerInfo.duration = decodedData.duration;
|
||||
});
|
||||
});
|
||||
this.$store.dispatch('setCurrentPlay', {...this.currentPlay, isLoader: false})
|
||||
}).catch(err => {
|
||||
this.$store.dispatch('setCurrentPlay', {...this.currentPlay, isLoader: false})
|
||||
console.debug(err)
|
||||
|
|
@ -271,9 +291,10 @@ export default {
|
|||
changeLive() {
|
||||
if (this.currentPlay.live) {
|
||||
console.log('избранное')
|
||||
this.getAudio(this.userSongList[0].azura_id);
|
||||
this.playerInfo.progress = 0;
|
||||
this.$store.dispatch('setCurrentPlay', {...this.userSongList[0], live: false, isLoader: true});
|
||||
const params = {...this.userSongList[this.currentPlay.currentIndex || 0], live: false, isLoader: true};
|
||||
if (!this.currentPlay.currentIndex) params.currentIndex = 0;
|
||||
this.$store.dispatch('setCurrentPlay', params);
|
||||
} else {
|
||||
this.playerInfo.progress = 100;
|
||||
this.$store.dispatch('setCurrentPlay', {...this.currentPlay, live: true, isLoader: true});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<div class="playlist-item" @click="selectPlaylist">
|
||||
<div class="playlist-item__cover"></div>
|
||||
<div>{{playlist.title}}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'playlist-item',
|
||||
props:{
|
||||
playlist:{
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
selectPlaylist(){
|
||||
this.$emit('selectPlaylist', this.playlist)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<template>
|
||||
<div class="playlist-roster">
|
||||
<PlaylistItem
|
||||
v-for="item in list"
|
||||
:key="`playlist_${item.id}`"
|
||||
:playlist="item"
|
||||
@selectPlaylist="selectPlaylist"
|
||||
/>
|
||||
<div class="playlist-item m--create" @click="createPlaylist">
|
||||
<div class="playlist-item__cover"></div>
|
||||
<div>Создать плейлист</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PlaylistItem from "@/components/playlist-item.vue";
|
||||
|
||||
export default {
|
||||
name: 'playlist-roster',
|
||||
components: {PlaylistItem},
|
||||
props: {
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
createPlaylist() {
|
||||
this.$emit('createPlaylist')
|
||||
},
|
||||
selectPlaylist(params) {
|
||||
this.$router.push({name: 'playlist', params: {id: params.id}})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import RubricModal from "@/components/rubric-modal.vue";
|
||||
import RubricModal from "@/components/modal/rubric-modal.vue";
|
||||
import {app} from "@/services";
|
||||
|
||||
export default {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
</div>
|
||||
<div class="song-item__tools">
|
||||
<button class="button song-item__btn m--small m--favorites" @click.stop="removeSong"></button>
|
||||
<button class="button song-item__btn m--small m--add"></button>
|
||||
<button class="button song-item__btn m--small m--add" :class="songAlreadyAddPlaylist&&'m--already'" @click.stop="songAlreadyAddPlaylist?removeToPlaylist:addPlaylist"></button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -48,6 +48,12 @@ export default {
|
|||
return false
|
||||
}
|
||||
},
|
||||
songAlreadyAddPlaylist:{
|
||||
type: Boolean,
|
||||
default(){
|
||||
return false
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'playSong': {
|
||||
|
|
@ -74,6 +80,12 @@ export default {
|
|||
},
|
||||
removeSong(){
|
||||
this.$emit('removeSong', this.song);
|
||||
},
|
||||
addPlaylist(){
|
||||
this.$emit('addPlaylist', this.song);
|
||||
},
|
||||
removeToPlaylist(){
|
||||
this.$emit('removePlaylist', this.song);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,13 @@
|
|||
:song="song"
|
||||
:playSong="song.azura_id === currentPlay.azura_id? currentPlay.isPlay: false"
|
||||
:selectSong="song.azura_id === currentPlay.azura_id"
|
||||
:songAlreadyAddPlaylist="songAlreadyAdd"
|
||||
@selectSong="handlerSelectSong"
|
||||
@playSong="handlerPlaySong"
|
||||
@pauseSong="handlerPauseSong"
|
||||
@removeSong="removeSong"
|
||||
@addPlaylist="addPlaylist"
|
||||
@removePlaylist="removePlaylist"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -24,6 +27,10 @@ export default {
|
|||
songList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
songAlreadyAdd: {
|
||||
type: Boolean,
|
||||
default: () => false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
|
@ -36,7 +43,9 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
handlerSelectSong(params) {
|
||||
this.$store.dispatch('setCurrentPlay', {...this.currentPlay, ...params, isLoader: true});
|
||||
const data = {...this.currentPlay, ...params, isLoader: true};
|
||||
data.currentIndex = this.songList.findIndex(el=>el.azura_id === params.azura_id);
|
||||
this.$store.dispatch('setCurrentPlay', data);
|
||||
console.log('handlerSelectSong')
|
||||
},
|
||||
handlerPlaySong(params) {
|
||||
|
|
@ -51,6 +60,12 @@ export default {
|
|||
},
|
||||
removeSong(song){
|
||||
this.$emit('removeSong', song)
|
||||
},
|
||||
addPlaylist(song){
|
||||
this.$emit('addPlaylist', song)
|
||||
},
|
||||
removePlaylist(song){
|
||||
this.$emit('removePlaylist', song)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import contacts from "@/views/contacts.vue";
|
|||
import podcasts from "@/views/podcasts.vue";
|
||||
import about from "@/views/about.vue";
|
||||
import profile from "@/views/profile.vue";
|
||||
import playlist from "@/views/playlist.vue";
|
||||
import playlistCreate from "@/views/playlist-edit.vue";
|
||||
|
||||
|
||||
const routes = [
|
||||
|
|
@ -80,6 +82,37 @@ const routes = [
|
|||
title: 'Личный кабинет',
|
||||
isAuth: false
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'playlist/:id',
|
||||
name: 'playlist',
|
||||
component: playlist,
|
||||
meta: {
|
||||
title: 'Плейлист',
|
||||
requiresAuth: true
|
||||
},
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: 'playlist-create/:id',
|
||||
name: 'playlist-create',
|
||||
component: playlistCreate,
|
||||
meta: {
|
||||
title: 'Плейлист',
|
||||
requiresAuth: true
|
||||
},
|
||||
props: true,
|
||||
},{
|
||||
path: 'playlist-edit/:id',
|
||||
name: 'playlist-edit',
|
||||
component: playlistCreate,
|
||||
meta: {
|
||||
title: 'Плейлист',
|
||||
requiresAuth: true
|
||||
},
|
||||
props: true,
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
// {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,14 @@ export default class extends REST {
|
|||
});
|
||||
}
|
||||
|
||||
static updateUser(params) {
|
||||
return this._post(`user/update_user`, {}, params).then((data) => {
|
||||
return data;
|
||||
}).catch((error) => {
|
||||
throw new RESTError(error, 'Не удалось создать пользователя');
|
||||
});
|
||||
}
|
||||
|
||||
static getTeams(station, params) {
|
||||
return this._get(`radio/teams`, params, {}).then((data) => {
|
||||
return data;
|
||||
|
|
@ -42,7 +50,13 @@ export default class extends REST {
|
|||
throw new RESTError(error, 'Ошибка при проверке песни');
|
||||
});
|
||||
}
|
||||
|
||||
static getAllSong(){
|
||||
return this._get(`radio/song/get_all_song`, {}, {}).then((data) => {
|
||||
return data;
|
||||
}).catch((error) => {
|
||||
throw new RESTError(error, 'Ошибка при получениии всех песен');
|
||||
});
|
||||
}
|
||||
static getAudio(id){
|
||||
return this._get(`radio/song/get_audio/${id}`, {}, {}, false, true).then((data) => {
|
||||
return data;
|
||||
|
|
@ -96,8 +110,35 @@ export default class extends REST {
|
|||
});
|
||||
}
|
||||
|
||||
static getPlaylists() {
|
||||
return this._get(`radio/playlists`, {}, {}).then((data) => {
|
||||
return data;
|
||||
}).catch((error) => {
|
||||
throw new RESTError(error, 'Ошибка при получении плейлистов');
|
||||
});
|
||||
}
|
||||
static getPlaylist(id) {
|
||||
return this._get(`radio/playlists/${id}`, {}, {}).then((data) => {
|
||||
return data;
|
||||
}).catch((error) => {
|
||||
throw new RESTError(error, 'Ошибка при получении плейлистов');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static addSongToPlaylist(params) {
|
||||
return this._post(`radio/playlists/add_to_playlist`, {}, params).then((data) => {
|
||||
return data;
|
||||
}).catch((error) => {
|
||||
throw new RESTError(error, 'Ошибка при получении плейлистов');
|
||||
});
|
||||
}
|
||||
static createPlaylists() {
|
||||
return this._post(`radio/playlists/create_playlist`, {}, {}).then((data) => {
|
||||
return data;
|
||||
}).catch((error) => {
|
||||
throw new RESTError(error, 'Ошибка при получении плейлистов');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static getNews(station, params) {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ export default createStore({
|
|||
token: null,
|
||||
refreshToken: null,
|
||||
user: null,
|
||||
modal:{
|
||||
auth: false,
|
||||
changingUser: false
|
||||
},
|
||||
showAuthModal: false,
|
||||
station: {
|
||||
id: 1
|
||||
|
|
@ -23,6 +27,7 @@ export default createStore({
|
|||
isLoader: false,
|
||||
live: true,
|
||||
volume: 50,
|
||||
currentIndex: null,
|
||||
},
|
||||
player: {
|
||||
target: null,
|
||||
|
|
@ -50,8 +55,8 @@ export default createStore({
|
|||
setCurrentPlay(state, song) {
|
||||
state.currentPlay = song;
|
||||
},
|
||||
setShowAuthModal(state, show) {
|
||||
state.showAuthModal = show
|
||||
setModal(state, show) {
|
||||
state.modal = {...state.modal, ...show}
|
||||
},
|
||||
setPlayer(state, params) {
|
||||
state.player = {...state.player, ...params}
|
||||
|
|
@ -117,8 +122,8 @@ export default createStore({
|
|||
setCurrentPlay(context, song) {
|
||||
context.commit('setCurrentPlay', song);
|
||||
},
|
||||
setShowAuthModal(context, show) {
|
||||
context.commit('setShowAuthModal', show);
|
||||
setModal(context, show) {
|
||||
context.commit('setModal', show);
|
||||
},
|
||||
setPlayer(context, params) {
|
||||
context.commit('setPlayer', params);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
<template>
|
||||
<div class="playlist-edit">
|
||||
<AppBreadcrumbs
|
||||
:breadcrumbs="[
|
||||
{ name: 'Главная', route: { name: 'home' } },
|
||||
{ name: 'Личный кабинет', route: { name: 'profile' } },
|
||||
$route.name==='playlist-create'?
|
||||
{ name: 'Добавление плейлиста', route: { name: 'playlist-create' } }:
|
||||
{ name: 'Редактирование плейлиста', route: { name: 'playlist-edit' } },
|
||||
]"/>
|
||||
<h1 class="h2">{{ $route.name==='playlist-create'?'Новый плейлист':playlist.name }}</h1>
|
||||
<FormKit
|
||||
v-model="playlist.name"
|
||||
type="text"
|
||||
outer-class="playlist-edit__search"
|
||||
inner-class="m--search"
|
||||
placeholder="Название плейлиста"
|
||||
></FormKit>
|
||||
<div class="playlist-edit__list">
|
||||
<div class="playlist-edit__item">
|
||||
<div class="playlist-edit__title">Поиск по каталогу</div>
|
||||
<template v-if="showLoaderSongs">
|
||||
<div class="loader">
|
||||
<div class="spinner"/>
|
||||
Загрузка данных
|
||||
</div>
|
||||
</template>
|
||||
<SongList v-else-if="songs.length>0" :songList="songs" class="m--column" @addPlaylist="addPlaylist"/>
|
||||
<div v-else>Каталог музыки пуст!</div>
|
||||
</div>
|
||||
<div class="playlist-edit__item">
|
||||
<div class="playlist-edit__title">Добавленные треки</div>
|
||||
<template v-if="showLoaderPlaylist">
|
||||
<div class="loader">
|
||||
<div class="spinner"/>
|
||||
Загрузка данных
|
||||
</div>
|
||||
</template>
|
||||
<SongList v-else-if="playlist.song?.length>0" :songList="playlist.song" class="m--column" :songAlreadyAdd="true" @removePlaylist="removePlaylist"/>
|
||||
<div v-else>Добавьте музыку в плейлист!</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {app} from "@/services";
|
||||
import AppBreadcrumbs from "@/components/app-breadcrumbs.vue";
|
||||
import SongList from "@/components/song-list.vue";
|
||||
|
||||
export default {
|
||||
name: 'playlist-edit',
|
||||
components: {SongList, AppBreadcrumbs},
|
||||
data() {
|
||||
return {
|
||||
playlist: {},
|
||||
songs: [],
|
||||
showLoaderSongs: false,
|
||||
showLoaderPlaylist: false,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getAllSong();
|
||||
this.getPlaylist();
|
||||
},
|
||||
methods:{
|
||||
getPlaylist(){
|
||||
this.showLoaderPlaylist = true;
|
||||
app.getPlaylist(this.$route.params.id).then(res=>{
|
||||
this.showLoaderPlaylist = false;
|
||||
this.playlist = res;
|
||||
}).catch(err=>{
|
||||
this.showLoaderPlaylist = false;
|
||||
console.error(err)
|
||||
})
|
||||
},
|
||||
getAllSong(){
|
||||
this.showLoaderSongs = true;
|
||||
app.getAllSong().then(res=>{
|
||||
this.showLoaderSongs = false;
|
||||
this.songs = res;
|
||||
}).catch(err=>{
|
||||
this.showLoaderSongs = false;
|
||||
console.error(err)
|
||||
})
|
||||
},
|
||||
addPlaylist(song){
|
||||
console.log(song)
|
||||
const params = {
|
||||
playlist_id: this.$route.params.id,
|
||||
azura_id: song.azura_id
|
||||
}
|
||||
this.showLoaderPlaylist = true;
|
||||
app.addSongToPlaylist(params).then(()=>{
|
||||
this.showLoaderPlaylist = false;
|
||||
this.getPlaylist();
|
||||
}).catch(err=>{
|
||||
this.showLoaderPlaylist = false;
|
||||
console.error(err)
|
||||
})
|
||||
},
|
||||
removePlaylist(){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<template>
|
||||
<div class="playlist">
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'playlist'
|
||||
}
|
||||
</script>
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<div class="app__content profile">
|
||||
<template v-if="$route.name !== 'playlist-edit'">
|
||||
<AppBreadcrumbs
|
||||
:breadcrumbs="[
|
||||
{ name: 'Главная', route: { name: 'home' } },
|
||||
|
|
@ -7,7 +8,7 @@
|
|||
]"
|
||||
/>
|
||||
<h1 class="h2 profile__title">{{ user.email }}</h1>
|
||||
<button class="button m--text-link">Редактировать профиль</button>
|
||||
<button class="button m--text-link" @click="showRecovery">Редактировать профиль</button>
|
||||
<div class="profile__tabs tabs m--btns">
|
||||
<button
|
||||
v-for="item in tabsItems"
|
||||
|
|
@ -19,8 +20,10 @@
|
|||
{{ item.label }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="$route.name === 'profile'">
|
||||
<template v-if="currentTabsItem==='music'">
|
||||
<template v-if="showLoader">
|
||||
<template v-if="showLoaderSong">
|
||||
<div class="loader">
|
||||
<div class="spinner"/>
|
||||
Загрузка данных
|
||||
|
|
@ -28,6 +31,21 @@
|
|||
</template>
|
||||
<SongList v-else :songList="userFavorite.songs" @removeSong="removeFavorites"/>
|
||||
</template>
|
||||
<template v-if="currentTabsItem==='playlists'">
|
||||
<template v-if="showLoaderPlaylist">
|
||||
<div class="loader">
|
||||
<div class="spinner"/>
|
||||
Загрузка данных
|
||||
</div>
|
||||
</template>
|
||||
<PlaylistRoster
|
||||
v-else
|
||||
:list="userFavorite.playlist"
|
||||
@createPlaylist="createPlayList"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
<routerView v-else/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -35,10 +53,11 @@
|
|||
import AppBreadcrumbs from "@/components/app-breadcrumbs.vue";
|
||||
import SongList from "@/components/song-list.vue";
|
||||
import {app} from "@/services";
|
||||
import PlaylistRoster from "@/components/playlist-roster.vue";
|
||||
|
||||
export default {
|
||||
name: 'profile',
|
||||
components: {SongList, AppBreadcrumbs},
|
||||
components: {PlaylistRoster, SongList, AppBreadcrumbs},
|
||||
data() {
|
||||
return {
|
||||
currentTabsItem: 'music',
|
||||
|
|
@ -56,8 +75,9 @@ export default {
|
|||
name: 'playlists'
|
||||
},
|
||||
],
|
||||
songList: [],
|
||||
showLoader: true,
|
||||
showLoaderSong: false,
|
||||
showLoaderPlaylist: false,
|
||||
showLoaderPodcast: true,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -78,31 +98,66 @@ export default {
|
|||
this.currentTabsItem = 'music';
|
||||
}
|
||||
},
|
||||
},
|
||||
'$route.name': {
|
||||
immediate: false,
|
||||
handler(to) {
|
||||
if (to === 'playlist') {
|
||||
this.currentTabsItem = 'playlists'
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.getSongList();
|
||||
this.getPlaylists();
|
||||
},
|
||||
methods: {
|
||||
getSongList() {
|
||||
this.showLoader = true;
|
||||
this.showLoaderSong = true;
|
||||
app.getFavoriteList().then(res => {
|
||||
this.showLoader = false;
|
||||
this.$store.dispatch('setUserFavorite', {songs: res})
|
||||
this.showLoaderSong = false;
|
||||
this.$store.dispatch('setUserFavorite', {songs: res});
|
||||
}).catch(err => {
|
||||
this.showLoader = false;
|
||||
this.showLoaderSong = false;
|
||||
console.error(err)
|
||||
})
|
||||
},
|
||||
changeTab(tab) {
|
||||
this.currentTabsItem = tab;
|
||||
if (this.$route.name === 'profile') {
|
||||
this.$router.push({name: this.$route.name, hash: `#${tab}`});
|
||||
} else {
|
||||
this.$router.push({name: 'profile', hash: `#${tab}`});
|
||||
}
|
||||
},
|
||||
removeFavorites(song) {
|
||||
this.showLoaderSong = true;
|
||||
app.removeFavorites(song).then(() => {
|
||||
this.showLoaderSong = false;
|
||||
this.getSongList();
|
||||
}).catch(err => {
|
||||
this.showLoader = false;
|
||||
this.showLoaderSong = false;
|
||||
console.error(err)
|
||||
})
|
||||
},
|
||||
showRecovery() {
|
||||
this.$store.dispatch('setModal', {changingUser: true});
|
||||
},
|
||||
getPlaylists() {
|
||||
this.showLoaderPlaylist = true;
|
||||
app.getPlaylists().then(res => {
|
||||
this.showLoaderPlaylist = false;
|
||||
this.$store.dispatch('setUserFavorite', {playlist: res});
|
||||
}).catch(err => {
|
||||
this.showLoaderPlaylist = false;
|
||||
console.error(err)
|
||||
})
|
||||
},
|
||||
createPlayList() {
|
||||
app.createPlaylists().then(res=>{
|
||||
this.$router.push({name: 'playlist-edit'});
|
||||
}).catch(err=>{
|
||||
console.error(err)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue