Merge branch '2456-alpha1-followup' into 'develop'
alha release followup Closes #2456 See merge request funkwhale/funkwhale!2921
This commit is contained in:
commit
9fe379d55b
|
@ -1,7 +1,7 @@
|
|||
openapi: 3.0.3
|
||||
info:
|
||||
title: Funkwhale API
|
||||
version: 1.4.0
|
||||
version: 2.0.0a1
|
||||
description: |
|
||||
# Funkwhale API
|
||||
|
||||
|
|
|
@ -56,12 +56,8 @@ class Migration(migrations.Migration):
|
|||
model_name="trackfavorite",
|
||||
name="fid",
|
||||
field=models.URLField(
|
||||
db_index=True,
|
||||
default="https://default.fid",
|
||||
max_length=500,
|
||||
unique=True,
|
||||
),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="trackfavorite",
|
||||
|
@ -90,6 +86,15 @@ class Migration(migrations.Migration):
|
|||
related_name="track_favorites",
|
||||
to="federation.actor",
|
||||
), ),
|
||||
migrations.AlterField(
|
||||
model_name="trackfavorite",
|
||||
name="fid",
|
||||
field=models.URLField(
|
||||
db_index=True,
|
||||
max_length=500,
|
||||
unique=True,
|
||||
),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name="trackfavorite",
|
||||
unique_together={("track", "actor")},
|
||||
|
|
|
@ -20,6 +20,7 @@ from funkwhale_api.music import utils as music_utils
|
|||
from funkwhale_api.users.oauth import permissions as oauth_permissions
|
||||
|
||||
from . import filters, models, parsers, renderers, serializers
|
||||
from rest_framework.pagination import PageNumberPagination
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -138,9 +139,15 @@ class PlaylistViewSet(
|
|||
plugins.TRIGGER_THIRD_PARTY_UPLOAD,
|
||||
track=plt.track,
|
||||
)
|
||||
serializer = serializers.PlaylistTrackSerializer(plts, many=True)
|
||||
data = {"count": len(plts), "results": serializer.data}
|
||||
return Response(data, status=200)
|
||||
|
||||
# Apply pagination
|
||||
paginator = PageNumberPagination()
|
||||
paginator.page_size = 100 # Set the page size (number of items per page)
|
||||
paginated_plts = paginator.paginate_queryset(plts, request)
|
||||
|
||||
# Serialize the paginated data
|
||||
serializer = serializers.PlaylistTrackSerializer(paginated_plts, many=True)
|
||||
return paginator.get_paginated_response(serializer.data)
|
||||
|
||||
@extend_schema(
|
||||
operation_id="add_to_playlist", request=serializers.PlaylistAddManySerializer
|
||||
|
|
|
@ -25,7 +25,6 @@ interface Props extends PlayOptionsProps {
|
|||
|
||||
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
||||
isPlayable?: boolean
|
||||
tracks?: Track[]
|
||||
artist?: Artist | null
|
||||
album?: Album | null
|
||||
playlist?: Playlist | null
|
||||
|
@ -39,7 +38,6 @@ const props = withDefaults(defineProps<Props>(), {
|
|||
isArtist: false,
|
||||
isAlbum: false,
|
||||
|
||||
tracks: () => [],
|
||||
artist: null,
|
||||
album: null,
|
||||
playlist: null,
|
||||
|
|
|
@ -245,7 +245,7 @@ const updatePage = (page: number) => {
|
|||
<Loader v-if="isLoading" />
|
||||
|
||||
<!-- For each item, build a row -->
|
||||
|
||||
<!--
|
||||
<track-mobile-row
|
||||
v-for="(track, index) in allTracks"
|
||||
:key="track.id"
|
||||
|
@ -258,7 +258,7 @@ const updatePage = (page: number) => {
|
|||
:is-artist="isArtist"
|
||||
:is-album="isAlbum"
|
||||
:is-podcast="isPodcast"
|
||||
/>
|
||||
/> -->
|
||||
<Pagination
|
||||
v-if="paginateResults"
|
||||
:pages="paginateBy"
|
||||
|
|
|
@ -176,7 +176,6 @@ const isOpen = useModal('artist-description').isOpen
|
|||
class="description"
|
||||
:content="{ ...object.description, text: object.description.text ?? undefined }"
|
||||
:truncate-length="100"
|
||||
:more-link="false"
|
||||
/>
|
||||
<Spacer grow />
|
||||
<Link
|
||||
|
|
|
@ -4597,7 +4597,8 @@
|
|||
"edit": "Edit",
|
||||
"embed": "Embed",
|
||||
"playAll": "Play all",
|
||||
"stopEdit": "Stop Editing"
|
||||
"stopEdit": "Stop Editing",
|
||||
"loadMoreTracks": "Load more tracks"
|
||||
},
|
||||
"empty": {
|
||||
"noTracks": "There are no tracks in this playlist yet"
|
||||
|
|
|
@ -190,7 +190,6 @@ const isOpen = useModal('artist-description').isOpen
|
|||
class="description"
|
||||
:content="{ html: object?.summary.html || '' }"
|
||||
:truncate-length="100"
|
||||
:more-link="false"
|
||||
/>
|
||||
<Spacer grow />
|
||||
<Link
|
||||
|
|
|
@ -31,7 +31,7 @@ import useErrorHandler from '~/composables/useErrorHandler'
|
|||
// }
|
||||
|
||||
interface Props {
|
||||
id: number
|
||||
id: string
|
||||
defaultEdit?: boolean
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||
})
|
||||
|
||||
const store = useStore()
|
||||
|
||||
const isLoadingMoreTracks = ref(false)
|
||||
const edit = ref(props.defaultEdit)
|
||||
const playlist = ref<Playlist | null>(null)
|
||||
const playlistTracks = ref<PlaylistTrack[]>([])
|
||||
|
@ -57,17 +57,24 @@ const labels = computed(() => ({
|
|||
}))
|
||||
|
||||
const isLoading = ref(false)
|
||||
const nextPage = ref<string | null>(null) // Tracks the next page URL
|
||||
const previousPage = ref<string | null>(null) // Tracks the previous page URL
|
||||
const totalTracks = ref<number>(0) // Total number of tracks
|
||||
|
||||
const fetchData = async () => {
|
||||
isLoading.value = true
|
||||
|
||||
try {
|
||||
const [playlistResponse, tracksResponse] = await Promise.all([
|
||||
axios.get(`playlists/${props.id}/`),
|
||||
axios.get(`playlists/${props.id}/tracks/`)
|
||||
axios.get(`playlists/${props.id}/tracks?page=1`)
|
||||
])
|
||||
|
||||
playlist.value = playlistResponse.data
|
||||
fullPlaylistTracks.value = tracksResponse.data.results
|
||||
nextPage.value = tracksResponse.data.next
|
||||
previousPage.value = tracksResponse.data.previous
|
||||
totalTracks.value = tracksResponse.data.count
|
||||
} catch (error) {
|
||||
useErrorHandler(error as Error)
|
||||
}
|
||||
|
@ -75,6 +82,25 @@ const fetchData = async () => {
|
|||
isLoading.value = false
|
||||
}
|
||||
|
||||
const loadMoreTracks = async () => {
|
||||
if (nextPage.value) {
|
||||
isLoadingMoreTracks.value = true; // Set loading state for the button
|
||||
try {
|
||||
const response = await axios.get(nextPage.value);
|
||||
|
||||
// Append new tracks to the existing list
|
||||
fullPlaylistTracks.value = [...fullPlaylistTracks.value, ...response.data.results];
|
||||
|
||||
// Update pagination metadata
|
||||
nextPage.value = response.data.next;
|
||||
} catch (error) {
|
||||
useErrorHandler(error as Error)
|
||||
} finally {
|
||||
isLoadingMoreTracks.value = false; // Reset loading state
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fetchData()
|
||||
|
||||
const images = computed(() => {
|
||||
|
@ -113,17 +139,6 @@ const randomizedColors = computed(() => shuffleArray(bgcolors.value))
|
|||
// return t('components.audio.ChannelCard.title', { date })
|
||||
// })
|
||||
|
||||
// TODO: Check if this function is still needed
|
||||
// const deletePlaylist = async () => {
|
||||
// try {
|
||||
// await axios.delete(`playlists/${props.id}/`)
|
||||
// store.dispatch('playlists/fetchOwn')
|
||||
// return router.push({ path: '/library' })
|
||||
// } catch (error) {
|
||||
// useErrorHandler(error as Error)
|
||||
// }
|
||||
// }
|
||||
|
||||
// TODO: Implement shuffle
|
||||
const shuffle = () => {}
|
||||
</script>
|
||||
|
@ -178,7 +193,6 @@ const shuffle = () => {}
|
|||
<RenderedDescription
|
||||
:content="{ html: playlist.description }"
|
||||
:truncate-length="100"
|
||||
:show-more="true"
|
||||
/>
|
||||
<Layout
|
||||
flex
|
||||
|
@ -240,6 +254,14 @@ const shuffle = () => {}
|
|||
:tracks="tracks"
|
||||
:unique="false"
|
||||
/>
|
||||
<Button
|
||||
v-if="nextPage"
|
||||
primary
|
||||
:is-loading="isLoadingMoreTracks"
|
||||
@click="loadMoreTracks"
|
||||
>
|
||||
{{ t('views.playlists.Detail.button.loadMoreTracks') }}
|
||||
</Button>
|
||||
</template>
|
||||
<Alert
|
||||
v-else-if="!isLoading"
|
||||
|
|
Loading…
Reference in New Issue