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

Merge branch 'radio-details' into 'develop'

Add a detail page for radios

Closes #64

See merge request funkwhale/funkwhale!119
parents 876aee19 1d989209
No related branches found
No related tags found
No related merge requests found
from rest_framework import serializers
from funkwhale_api.music.serializers import TrackSerializerNested
from funkwhale_api.users.serializers import UserBasicSerializer
from . import filters
from . import models
......@@ -15,6 +16,8 @@ class FilterSerializer(serializers.Serializer):
class RadioSerializer(serializers.ModelSerializer):
user = UserBasicSerializer(read_only=True)
class Meta:
model = models.Radio
fields = (
......
......@@ -20,6 +20,7 @@ class RadioViewSet(
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.ListModelMixin,
mixins.DestroyModelMixin,
viewsets.GenericViewSet):
serializer_class = serializers.RadioSerializer
......@@ -40,6 +41,16 @@ class RadioViewSet(
raise Http404
return serializer.save(user=self.request.user)
@detail_route(methods=['get'])
def tracks(self, request, *args, **kwargs):
radio = self.get_object()
tracks = radio.get_candidates().for_nested_serialization()
page = self.paginate_queryset(tracks)
if page is not None:
serializer = TrackSerializerNested(page, many=True)
return self.get_paginated_response(serializer.data)
@list_route(methods=['get'])
def filters(self, request, *args, **kwargs):
serializer = serializers.FilterSerializer(
......
Add a detail page for radios (#64)
\ No newline at end of file
......@@ -180,7 +180,7 @@ export default {
let url = 'radios/radios/'
axios.post(url, final).then((response) => {
self.$router.push({
name: 'library.radios.edit',
name: 'library.radios.detail',
params: {
id: response.data.id
}
......
<template>
<div class="ui card">
<div class="content">
<div class="header">{{ radio.name }}</div>
<div class="header">
<router-link class="discrete link" :to="{name: 'library.radios.detail', params: {id: radio.id}}">
{{ radio.name }}
</router-link>
</div>
<div class="description">
{{ radio.description }}
</div>
......
......@@ -18,6 +18,7 @@ import LibraryTrack from '@/components/library/Track'
import LibraryImport from '@/components/library/import/Main'
import LibraryRadios from '@/components/library/Radios'
import RadioBuilder from '@/components/library/radios/Builder'
import RadioDetail from '@/views/radios/Detail'
import BatchList from '@/components/library/import/BatchList'
import BatchDetail from '@/components/library/import/BatchDetail'
import RequestsList from '@/components/requests/RequestsList'
......@@ -111,6 +112,7 @@ 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: 'radios/:id', name: 'library.radios.detail', component: RadioDetail, props: true },
{
path: 'playlists/',
name: 'library.playlists.browse',
......
<template>
<div>
<div v-if="isLoading" class="ui vertical segment" v-title="'Radio'">
<div :class="['ui', 'centered', 'active', 'inline', 'loader']"></div>
</div>
<div v-if="!isLoading && radio" class="ui head vertical center aligned stripe segment" v-title="radio.name">
<div class="segment-content">
<h2 class="ui center aligned icon header">
<i class="circular inverted feed blue icon"></i>
<div class="content">
{{ radio.name }}
<div class="sub header">
Radio containing {{ tracks.length }} tracks,
by <username :username="radio.user.username"></username>
</div>
</div>
</h2>
<div class="ui hidden divider"></div>
<radio-button type="custom" :custom-radio-id="radio.id"></radio-button>
<router-link class="ui icon button" :to="{name: 'library.radios.edit', params: {id: radio.id}}" exact>
<i class="pencil icon"></i>
Edit…
</router-link>
<dangerous-button class="labeled icon" :action="deleteRadio">
<i class="trash icon"></i> Delete
<p slot="modal-header">Do you want to delete the radio "{{ radio.name }}"?</p>
<p slot="modal-content">This will completely delete this radio and cannot be undone.</p>
<p slot="modal-confirm">Delete radio</p>
</dangerous-button>
</div>
</div>
<div class="ui vertical stripe segment">
<h2>Tracks</h2>
<track-table :tracks="tracks"></track-table>
<div class="ui center aligned basic segment">
<pagination
v-if="totalTracks > 25"
@page-changed="selectPage"
:current="page"
:paginate-by="25"
:total="totalTracks"
></pagination>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
import TrackTable from '@/components/audio/track/Table'
import RadioButton from '@/components/radios/Button'
import Pagination from '@/components/Pagination'
export default {
props: {
id: {required: true}
},
components: {
TrackTable,
RadioButton,
Pagination
},
data: function () {
return {
isLoading: false,
radio: null,
tracks: [],
totalTracks: 0,
page: 1
}
},
created: function () {
this.fetch()
},
methods: {
selectPage: function (page) {
this.page = page
},
fetch: function () {
let self = this
self.isLoading = true
let url = 'radios/radios/' + this.id + '/'
axios.get(url).then((response) => {
self.radio = response.data
axios.get(url + 'tracks', {params: {page: this.page}}).then((response) => {
console.log(response.data.count)
this.totalTracks = response.data.count
this.tracks = response.data.results
}).then(() => {
self.isLoading = false
})
})
},
deleteRadio () {
let self = this
let url = 'radios/radios/' + this.id + '/'
axios.delete(url).then((response) => {
self.$router.push({
path: '/library'
})
})
}
},
watch: {
page: function () {
this.fetch()
}
}
}
</script>
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