Commit 037efe86 authored by Agate's avatar Agate 💬

Added favorite list view / handling

parent 2b252325
......@@ -8,7 +8,7 @@ services:
context: .
environment:
- "HOST=0.0.0.0"
- "BACKEND_URL=https://funkwhaleapi.eliotberriot.com"
- "BACKEND_URL=http://localhost:6001"
ports:
- "8080:8080"
volumes:
......
......@@ -25,7 +25,11 @@ export default {
if (url.startsWith('http')) {
return url
}
return config.BACKEND_URL + url
if (url.startsWith('/')) {
return config.BACKEND_URL + url.substr(1)
} else {
return config.BACKEND_URL + url
}
},
Artist: Artist,
Album: Album
......
import logger from '@/logging'
import Audio from '@/audio'
import config from '@/config'
import backend from '@/audio/backend'
class Queue {
constructor (options = {}) {
......@@ -78,7 +78,7 @@ class Queue {
if (!file) {
return this.next()
}
this.audio = new Audio(config.BACKEND_URL + file.path, {
this.audio = new Audio(backend.absoluteUrl(file.path), {
preload: true,
autoplay: true,
rate: 1,
......
......@@ -22,10 +22,11 @@
<div class="tabs">
<div class="ui bottom attached active tab" data-tab="browse">
<div class="ui inverted vertical fluid menu">
<router-link class="item" v-if="auth.user.authenticated" :to="{name: 'logout'}">Logged in as {{ auth.user.username }}</router-link>
<router-link class="item" v-if="auth.user.authenticated" :to="{name: 'logout'}">Logout</router-link>
<router-link class="item" v-else :to="{name: 'login'}">Login</router-link>
<router-link class="item" :to="{path: '/browse'}">Browse library</router-link>
<router-link class="item" v-if="auth.user.authenticated" :to="{name: 'logout'}"><i class="user icon"></i> Logged in as {{ auth.user.username }}</router-link>
<router-link class="item" v-if="auth.user.authenticated" :to="{name: 'logout'}"><i class="sign out icon"></i> Logout</router-link>
<router-link class="item" v-else :to="{name: 'login'}"><i class="sign in icon"></i> Login</router-link>
<router-link class="item" :to="{path: '/browse'}"><i class="sound icon"> </i>Browse library</router-link>
<router-link class="item" :to="{path: '/favorites'}"><i class="heart icon"></i> Favorites</router-link>
</div>
</div>
<div class="ui bottom attached tab" data-tab="queue">
......
<template>
<table class="ui compact very basic fixed single line table">
<thead>
<tr>
<th></th>
<th></th>
<th colspan="6">Title</th>
<th colspan="6">Album</th>
<th colspan="6">Artist</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="track in tracks">
<td>
<button @click="queue.append(track)" class="ui tiny teal icon button">
<i class="play icon"></i>
</button>
</td>
<td>
<img class="ui mini image" v-if="track.album.cover" :src="backend.absoluteUrl(track.album.cover)">
<img class="ui mini image" v-else src="../../..//assets/audio/default-cover.png">
</td>
<td colspan="6">{{ track.title }}</td>
<td colspan="6">{{ track.album.title }}</td>
<td colspan="6">{{ track.artist.name }}</td>
<td><track-favorite-icon :track="track"></track-favorite-icon></td>
</tr>
</tbody>
</table>
</template>
<script>
import queue from '@/audio/queue'
import backend from '@/audio/backend'
import TrackFavoriteIcon from '@/components/favorites/TrackFavoriteIcon'
export default {
props: ['tracks'],
components: {
TrackFavoriteIcon
},
data () {
return {
backend: backend,
queue: queue
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
<template>
<div class="main pusher">
<div class="ui vertical center aligned stripe segment">
<div :class="['ui', {'active': isLoading}, 'inverted', 'dimmer']">
<div class="ui text loader">Loading your favorites...</div>
</div>
<h2 v-if="results" class="ui center aligned icon header">
<i class="circular inverted heart pink icon"></i>
{{ favoriteTracks.count }} favorites
</h2>
</div>
<div class="ui vertical stripe segment">
<button class="ui left floated labeled icon button" @click="fetchFavorites(previousLink)" :disabled="!previousLink"><i class="left arrow icon"></i> Previous</button>
<button class="ui right floated right labeled icon button" @click="fetchFavorites(nextLink)" :disabled="!nextLink">Next <i class="right arrow icon"></i></button>
<div class="ui hidden clearing divider"></div>
<div class="ui hidden clearing divider"></div>
<track-table v-if="results" :tracks="results.results"></track-table>
</div>
</div>
</template>
<script>
import Vue from 'vue'
import logger from '@/logging'
import config from '@/config'
import favoriteTracks from '@/favorites/tracks'
import TrackTable from '@/components/audio/track/Table'
const FAVORITES_URL = config.API_URL + 'tracks/'
export default {
components: {
TrackTable
},
data () {
return {
results: null,
isLoading: false,
nextLink: null,
previousLink: null,
favoriteTracks
}
},
created () {
this.fetchFavorites(FAVORITES_URL)
},
methods: {
fetchFavorites (url) {
var self = this
this.isLoading = true
let params = {
favorites: 'true'
}
logger.default.time('Loading user favorites')
this.$http.get(url, {params: params}).then((response) => {
self.results = response.data
self.nextLink = response.data.next
self.previousLink = response.data.previous
Vue.set(favoriteTracks, 'count', response.data.count)
favoriteTracks.count = response.data.count
self.results.results.forEach((track) => {
Vue.set(favoriteTracks.objects, track.id, true)
})
logger.default.timeEnd('Loading user favorites')
self.isLoading = false
})
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
<template>
<i @click="favoriteTracks.set(track.id, !isFavorite)" :class="['circular', 'heart', {'pink': isFavorite}, 'icon']" :title="title"></i>
</template>
<script>
import favoriteTracks from '@/favorites/tracks'
export default {
props: {
track: {type: Object}
},
data () {
return {
favoriteTracks
}
},
methods: {
toggleFavorite () {
this.isFavorite = !this.isFavorite
}
},
computed: {
title () {
if (this.isFavorite) {
return 'Remove from favorites'
} else {
return 'Add to favorites'
}
},
isFavorite () {
return favoriteTracks.objects[this.track.id]
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
i {
cursor: pointer;
}
</style>
import config from '@/config'
import logger from '@/logging'
import Vue from 'vue'
const REMOVE_URL = config.API_URL + 'favorites/tracks/remove/'
const ADD_URL = config.API_URL + 'favorites/tracks/'
export default {
objects: {},
count: 0,
set (id, newValue) {
let self = this
Vue.set(self.objects, id, newValue)
if (newValue) {
Vue.set(self, 'count', self.count + 1)
let resource = Vue.resource(ADD_URL)
resource.save({}, {'track': id}).then((response) => {
logger.default.info('Successfully added track to favorites')
}, (response) => {
logger.default.info('Error while adding track to favorites')
Vue.set(self.objects, id, !newValue)
Vue.set(self, 'count', self.count - 1)
})
} else {
Vue.set(self, 'count', self.count - 1)
let resource = Vue.resource(REMOVE_URL)
resource.delete({}, {'track': id}).then((response) => {
logger.default.info('Successfully removed track from favorites')
}, (response) => {
logger.default.info('Error while removing track from favorites')
Vue.set(self.objects, id, !newValue)
Vue.set(self, 'count', self.count + 1)
})
}
}
}
......@@ -6,6 +6,7 @@ import Logout from '@/components/auth/Logout'
import Browse from '@/components/browse/Browse'
import BrowseHome from '@/components/browse/Home'
import BrowseArtist from '@/components/browse/Artist'
import Favorites from '@/components/favorites/List'
Vue.use(Router)
......@@ -27,6 +28,10 @@ export default new Router({
name: 'logout',
component: Logout
},
{
path: '/favorites',
component: Favorites
},
{
path: '/browse',
component: Browse,
......
Markdown is supported
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