Verified Commit f66dff35 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Added playlist list in library

parent 38a45590
......@@ -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>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment