Skip to content
Snippets Groups Projects
Verified Commit f66dff35 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Added playlist list in library

parent 38a45590
No related branches found
No related tags found
No related merge requests found
......@@ -4,6 +4,7 @@
<router-link class="ui item" to="/library" exact>Browse</router-link>
<router-link class="ui item" to="/library/artists" exact>Artists</router-link>
<router-link class="ui item" to="/library/radios" exact>Radios</router-link>
<router-link class="ui item" to="/library/playlists" exact>Playlists</router-link>
<div class="ui secondary right menu">
<router-link v-if="$store.state.auth.authenticated" class="ui item" to="/library/requests/" exact>
Requests
......
<template>
<div class="ui card">
<div class="content">
<div class="header">
<router-link class="discrete link" :to="{name: 'library.playlists.detail', params: {id: playlist.id }}">
{{ playlist.name }}
</router-link>
</div>
<div class="meta">
<i class="user icon"></i> {{ playlist.user.username }}
</div>
<div class="meta">
<i class="clock icon"></i> Updated <human-date :date="playlist.modification_date"></human-date>
</div>
</div>
<div class="extra content">
<span>
<i class="sound icon"></i>
{{ playlist.tracks_count }} tracks
</span>
<play-button class="mini basic orange right floated" :playlist="playlist">Play all</play-button>
</div>
</div>
</template>
<script>
import PlayButton from '@/components/audio/PlayButton'
export default {
props: ['playlist'],
components: {
PlayButton
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
<template>
<div
v-if="playlists.length > 0"
v-masonry
transition-duration="0"
item-selector=".column"
percent-position="true"
stagger="0"
class="ui stackable three column doubling grid">
<div
v-masonry-tile
v-for="playlist in playlists"
:key="playlist.id"
class="column">
<playlist-card class="fluid" :playlist="playlist"></playlist-card>
</div>
</div>
</template>
<script>
import PlaylistCard from '@/components/playlists/Card'
export default {
props: ['playlists'],
components: {
PlaylistCard
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
......@@ -21,8 +21,11 @@
<option :value="c.value" v-for="c in privacyLevelChoices">{{ c.label }}</option>
</select>
</div>
<div class="field">
<label>&nbsp;</label>
<button :class="['ui', {'loading': isLoading}, 'button']" type="submit">Create playlist</button>
</div>
</div>
<button :class="['ui', {'loading': isLoading}, 'button']" type="submit">Create playlist</button>
</form>
</template>
......
......@@ -22,6 +22,7 @@ import BatchList from '@/components/library/import/BatchList'
import BatchDetail from '@/components/library/import/BatchDetail'
import RequestsList from '@/components/requests/RequestsList'
import PlaylistDetail from '@/views/playlists/Detail'
import PlaylistList from '@/views/playlists/List'
import Favorites from '@/components/favorites/List'
Vue.use(Router)
......@@ -110,6 +111,17 @@ export default new Router({
},
{ path: 'radios/build', name: 'library.radios.build', component: RadioBuilder, props: true },
{ path: 'radios/build/:id', name: 'library.radios.edit', component: RadioBuilder, props: true },
{
path: 'playlists/',
name: 'library.playlists.browse',
component: PlaylistList,
props: (route) => ({
defaultOrdering: route.query.ordering,
defaultQuery: route.query.query,
defaultPaginateBy: route.query.paginateBy,
defaultPage: route.query.page
})
},
{
path: 'playlists/:id',
name: 'library.playlists.detail',
......
......@@ -34,7 +34,7 @@
</dangerous-button>
</div>
</div>
<div v-if="tracks.length > 0" class="ui vertical stripe segment">
<div class="ui vertical stripe segment">
<template v-if="edit">
<playlist-editor @tracks-updated="updatePlts" :playlist="playlist" :playlist-tracks="playlistTracks"></playlist-editor>
</template>
......
<template>
<div>
<div class="ui vertical stripe segment">
<h2 class="ui header">Browsing playlists</h2>
<div :class="['ui', {'loading': isLoading}, 'form']">
<template v-if="$store.state.auth.authenticated">
<button
@click="$store.commit('playlists/chooseTrack', null)"
class="ui basic green button">Manage your playlists</button>
<div class="ui hidden divider"></div>
</template>
<div class="fields">
<div class="field">
<label>Search</label>
<input type="text" v-model="query" placeholder="Enter an playlist name..."/>
</div>
<div class="field">
<label>Ordering</label>
<select class="ui dropdown" v-model="ordering">
<option v-for="option in orderingOptions" :value="option[0]">
{{ option[1] }}
</option>
</select>
</div>
<div class="field">
<label>Ordering direction</label>
<select class="ui dropdown" v-model="orderingDirection">
<option value="">Ascending</option>
<option value="-">Descending</option>
</select>
</div>
<div class="field">
<label>Results per page</label>
<select class="ui dropdown" v-model="paginateBy">
<option :value="parseInt(12)">12</option>
<option :value="parseInt(25)">25</option>
<option :value="parseInt(50)">50</option>
</select>
</div>
</div>
</div>
<div class="ui hidden divider"></div>
<playlist-card-list v-if="result" :playlists="result.results"></playlist-card-list>
<div class="ui center aligned basic segment">
<pagination
v-if="result && result.results.length > 0"
@page-changed="selectPage"
:current="page"
:paginate-by="paginateBy"
:total="result.count"
></pagination>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
import _ from 'lodash'
import $ from 'jquery'
import OrderingMixin from '@/components/mixins/Ordering'
import PaginationMixin from '@/components/mixins/Pagination'
import PlaylistCardList from '@/components/playlists/CardList'
import Pagination from '@/components/Pagination'
const FETCH_URL = 'playlists/'
export default {
mixins: [OrderingMixin, PaginationMixin],
props: {
defaultQuery: {type: String, required: false, default: ''}
},
components: {
PlaylistCardList,
Pagination
},
data () {
let defaultOrdering = this.getOrderingFromString(this.defaultOrdering || '-creation_date')
return {
isLoading: true,
result: null,
page: parseInt(this.defaultPage),
query: this.defaultQuery,
paginateBy: parseInt(this.defaultPaginateBy || 12),
orderingDirection: defaultOrdering.direction,
ordering: defaultOrdering.field,
orderingOptions: [
['creation_date', 'Creation date'],
['modification_date', 'Last modification date'],
['name', 'Name']
]
}
},
created () {
this.fetchData()
},
mounted () {
$('.ui.dropdown').dropdown()
},
methods: {
updateQueryString: _.debounce(function () {
this.$router.replace({
query: {
query: this.query,
page: this.page,
paginateBy: this.paginateBy,
ordering: this.getOrderingAsString()
}
})
}, 500),
fetchData: _.debounce(function () {
var self = this
this.isLoading = true
let url = FETCH_URL
let params = {
page: this.page,
page_size: this.paginateBy,
q: this.query,
ordering: this.getOrderingAsString()
}
axios.get(url, {params: params}).then((response) => {
self.result = response.data
self.isLoading = false
})
}, 500),
selectPage: function (page) {
this.page = page
}
},
watch: {
page () {
this.updateQueryString()
this.fetchData()
},
paginateBy () {
this.updateQueryString()
this.fetchData()
},
ordering () {
this.updateQueryString()
this.fetchData()
},
orderingDirection () {
this.updateQueryString()
this.fetchData()
},
query () {
this.updateQueryString()
this.fetchData()
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment