diff --git a/api/funkwhale_api/radios/filters.py b/api/funkwhale_api/radios/filters.py index 126701311..23ac8dba1 100644 --- a/api/funkwhale_api/radios/filters.py +++ b/api/funkwhale_api/radios/filters.py @@ -6,6 +6,7 @@ from django.db.models import Q, functions from django.urls import reverse_lazy from funkwhale_api.music import models +from funkwhale_api.playlists import models as plt_models class RadioFilterRegistry(persisting_theory.Registry): @@ -226,3 +227,20 @@ class TagFilter(RadioFilter): raise ValidationError("You must provide a name") except AssertionError: raise ValidationError('No tag matching names "{}"'.format(diff)) + + +@registry.register +class PlaylistFilter(RadioFilter): + code = "playlist" + label = "Playlist" + + def get_query(self, candidates, ids, **kwargs): + playlists = plt_models.Playlist.objects.filter(id__in=ids) + ids_plts = [] + for playlist in playlists: + ids = playlist.playlist_tracks.select_related("track").values_list( + "track_id", flat=True + ) + for id in ids: + ids_plts.append(id) + return Q(id__in=ids_plts) diff --git a/api/tests/radios/test_radios.py b/api/tests/radios/test_radios.py index 2745bb368..c45c17177 100644 --- a/api/tests/radios/test_radios.py +++ b/api/tests/radios/test_radios.py @@ -418,7 +418,7 @@ def test_get_choices_for_custom_radio_exclude_tag(factories): def test_can_start_custom_multiple_radio_from_api(api_client, factories): tracks = factories["music.Track"].create_batch(5) url = reverse("api:v1:radios:sessions-list") - map_filters_to_type = {"tags": "names", "artists": "ids"} + map_filters_to_type = {"tags": "names", "artists": "ids", "playlists": "names"} for (key, value) in map_filters_to_type.items(): attr = value[:-1] track_filter_key = [getattr(a.artist, attr) for a in tracks] diff --git a/changes/changelog.d/1968.enhancement b/changes/changelog.d/1968.enhancement new file mode 100644 index 000000000..0eddf3d02 --- /dev/null +++ b/changes/changelog.d/1968.enhancement @@ -0,0 +1 @@ +Add playlists radio to search page (#1968) \ No newline at end of file diff --git a/front/src/components/radios/Button.vue b/front/src/components/radios/Button.vue index 77d256e4b..f0cec52d5 100644 --- a/front/src/components/radios/Button.vue +++ b/front/src/components/radios/Button.vue @@ -47,6 +47,10 @@ const buttonLabel = computed(() => { return running.value ? $pgettext('*/Player/Button.Label/Short, Verb', 'Stop artists radio') : $pgettext('*/Player/Button.Label/Short, Verb', 'Start artists radio') + case 'playlist': + return running.value + ? $pgettext('*/Player/Button.Label/Short, Verb', 'Stop playlists radio') + : $pgettext('*/Player/Button.Label/Short, Verb', 'Start playlists radio') default: return running.value ? $pgettext('*/Player/Button.Label/Short, Verb', 'Stop radio') diff --git a/front/src/store/radios.ts b/front/src/store/radios.ts index 669dfa288..85b79e5ee 100644 --- a/front/src/store/radios.ts +++ b/front/src/store/radios.ts @@ -30,7 +30,7 @@ export interface CurrentRadio { objectId: ObjectId | null } -export type RadioConfig = { type: 'tag', names: string[] } | { type: 'artist', ids: string[] } +export type RadioConfig = { type: 'tag', names: string[] } | { type: 'artist' | 'playlist', ids: string[] } const logger = useLogger() diff --git a/front/src/views/Search.vue b/front/src/views/Search.vue index 6112c6658..bc53fe549 100644 --- a/front/src/views/Search.vue +++ b/front/src/views/Search.vue @@ -191,18 +191,19 @@ const labels = computed(() => ({ const radioConfig = computed(() => { const results = Object.values(currentResults.value?.results ?? {}) if (results.length) { - if (currentType.value?.id === 'tags') { - return { - type: 'tag', - names: results.map(({ name }) => name) - } as RadioConfig - } + switch (currentType.value?.id) { + case 'tags': + return { + type: 'tag', + names: results.map(({ name }) => name) + } as RadioConfig - if (currentType.value?.id === 'artists') { - return { - type: 'artist', - ids: results.map(({ id }) => id) - } as RadioConfig + case 'playlists': + case 'artists': + return { + type: currentType.value.id.slice(0, -1), + ids: results.map(({ id }) => id) + } as RadioConfig } // TODO (wvffle): Use logger