Merge branch 'radio-details' into 'develop'
Add a detail page for radios Closes #64 See merge request funkwhale/funkwhale!119
This commit is contained in:
commit
19bfd98e81
|
@ -1,6 +1,7 @@
|
|||
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(
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Add a detail page for radios (#64)
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
<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',
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
<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>
|
Loading…
Reference in New Issue