Form, modal and player icon to add track to playlist

This commit is contained in:
Eliot Berriot 2018-03-19 17:39:03 +01:00
parent a34b1afd6c
commit d6f2c7d4c4
No known key found for this signature in database
GPG Key ID: DD6965E2476E5C27
4 changed files with 231 additions and 1 deletions

View File

@ -30,7 +30,12 @@
</router-link> </router-link>
</div> </div>
<div class="description"> <div class="description">
<track-favorite-icon :track="currentTrack"></track-favorite-icon> <track-favorite-icon
v-if="$store.state.auth.authenticated"
:track="currentTrack"></track-favorite-icon>
<track-playlist-icon
v-if="$store.state.auth.authenticated"
:track="currentTrack"></track-playlist-icon>
</div> </div>
</div> </div>
</div> </div>
@ -140,11 +145,13 @@ import ColorThief from '@/vendor/color-thief'
import Track from '@/audio/track' import Track from '@/audio/track'
import AudioTrack from '@/components/audio/Track' import AudioTrack from '@/components/audio/Track'
import TrackFavoriteIcon from '@/components/favorites/TrackFavoriteIcon' import TrackFavoriteIcon from '@/components/favorites/TrackFavoriteIcon'
import TrackPlaylistIcon from '@/components/playlists/TrackPlaylistIcon'
export default { export default {
name: 'player', name: 'player',
components: { components: {
TrackFavoriteIcon, TrackFavoriteIcon,
TrackPlaylistIcon,
GlobalEvents, GlobalEvents,
AudioTrack AudioTrack
}, },
@ -281,6 +288,7 @@ export default {
cursor: pointer cursor: pointer
} }
.track-area { .track-area {
margin-top: 0;
.header, .meta, .artist, .album { .header, .meta, .artist, .album {
color: white !important; color: white !important;
} }
@ -384,4 +392,5 @@ export default {
.ui.feed.icon { .ui.feed.icon {
margin: 0; margin: 0;
} }
</style> </style>

View File

@ -0,0 +1,90 @@
<template>
<form class="ui form" @submit.prevent="submit()">
<h4 class="ui header">Create a new playlist</h4>
<div v-if="success" class="ui positive message">
<div class="header">Playlist created</div>
</div>
<div v-if="errors.length > 0" class="ui negative message">
<div class="header">We cannot create the playlist</div>
<ul class="list">
<li v-for="error in errors">{{ error }}</li>
</ul>
</div>
<div class="fields">
<div class="field">
<label>Playlist name</label>
<input v-model="name" required type="text" placeholder="My awesome playlist" />
</div>
<div class="field">
<label>Playlist visibility</label>
<select class="ui dropdown" v-model="privacyLevel">
<option :value="c.value" v-for="c in privacyLevelChoices">{{ c.label }}</option>
</select>
</div>
</div>
<button :class="['ui', {'loading': isLoading}, 'button']" type="submit">Create playlist</button>
</form>
</template>
<script>
import $ from 'jquery'
import axios from 'axios'
import logger from '@/logging'
export default {
mounted () {
$(this.$el).find('.dropdown').dropdown()
},
data () {
return {
privacyLevel: this.$store.state.auth.profile.privacy_level,
name: '',
errors: [],
success: false,
isLoading: false,
privacyLevelChoices: [
{
value: 'me',
label: 'Nobody except me'
},
{
value: 'instance',
label: 'Everyone on this instance'
},
{
value: 'everyone',
label: 'Everyone'
}
]
}
},
methods: {
submit () {
this.isLoading = true
this.success = false
this.errors = []
let self = this
let payload = {
name: this.name,
privacy_level: this.privacyLevel
}
let url = `playlists/`
return axios.post(url, payload).then(response => {
logger.default.info('Successfully created playlist')
self.success = true
self.isLoading = false
self.$store.dispatch('playlists/fetchOwn')
}, error => {
logger.default.error('Error while creating playlist')
self.isLoading = false
self.errors = error.backendErrors
})
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

View File

@ -0,0 +1,91 @@
<template>
<modal @update:show="update" :show="show">
<div class="header">
Add track "{{ track.title }}" by {{ track.artist.name }} to playlist
</div>
<div class="content">
<div class="description">
<playlist-form></playlist-form>
<div class="ui divider"></div>
<div v-if="errors.length > 0" class="ui negative message">
<div class="header">We cannot add the track to a playlist</div>
<ul class="list">
<li v-for="error in errors">{{ error }}</li>
</ul>
</div>
<div class="ui items">
<div class="item" v-for="playlist in sortedPlaylists">
<div class="content">
<div class="header">{{ playlist.name }}</div>
<div class="meta">
<span class="tracks">45 tracks</span>
</div>
<div class="extra">
<div class="ui basic green button" @click="addToPlaylist(playlist.id)">
Add to this playlist
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</modal>
</template>
<script>
import axios from 'axios'
import {mapState} from 'vuex'
import logger from '@/logging'
import Modal from '@/components/semantic/Modal'
import PlaylistForm from '@/components/playlists/Form'
export default {
components: {
Modal,
PlaylistForm
},
props: {
track: {type: Object},
show: {type: Boolean}
},
data () {
return {
errors: []
}
},
methods: {
update (v) {
this.$emit('update:show', v)
},
addToPlaylist (playlistId) {
let self = this
let payload = {
track: this.track.id,
playlist: playlistId
}
return axios.post('playlist-tracks/', payload).then(response => {
logger.default.info('Successfully added track to playlist')
self.$emit('update:show', false)
self.$store.dispatch('playlists/fetchOwn')
}, error => {
logger.default.error('Error while adding track to playlist')
self.errors = error.backendErrors
})
}
},
computed: {
...mapState({
playlists: state => state.playlists.playlists
}),
sortedPlaylists () {
return this.playlists
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

View File

@ -0,0 +1,40 @@
<template>
<button
@click="showModal = true"
v-if="button"
:class="['ui', 'button']">
<i class="list icon"></i>
Add to playlist...
<playlist-modal :track="track" :show.sync="showModal"></playlist-modal>
</button>
<i
v-else
@click="showModal = true"
:class="['favorite-icon', 'list', 'link', 'icon']"
title="Add to playlist...">
<playlist-modal :track="track" :show.sync="showModal"></playlist-modal>
</i>
</template>
<script>
import PlaylistModal from '@/components/playlists/PlaylistModal'
export default {
components: {
PlaylistModal
},
props: {
track: {type: Object},
button: {type: Boolean, default: false}
},
data () {
return {
showModal: false
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>