diff --git a/api/funkwhale_api/music/mutations.py b/api/funkwhale_api/music/mutations.py index d95d35702..c26feaec7 100644 --- a/api/funkwhale_api/music/mutations.py +++ b/api/funkwhale_api/music/mutations.py @@ -9,6 +9,8 @@ from funkwhale_api.tags import serializers as tags_serializers from . import models +NOOP = object() + def can_suggest(obj, actor): return obj.is_local @@ -34,9 +36,10 @@ class TagMutation(mutations.UpdateMutationSerializer): return handlers def update(self, instance, validated_data): - tags = validated_data.pop("tags", []) + tags = validated_data.pop("tags", NOOP) r = super().update(instance, validated_data) - tags_models.set_tags(instance, *tags) + if tags != NOOP: + tags_models.set_tags(instance, *tags) return r @@ -53,9 +56,10 @@ class DescriptionMutation(mutations.UpdateMutationSerializer): return handlers def update(self, instance, validated_data): - description = validated_data.pop("description", None) + description = validated_data.pop("description", NOOP) r = super().update(instance, validated_data) - common_utils.attach_content(instance, "description", description) + if description != NOOP: + common_utils.attach_content(instance, "description", description) return r diff --git a/api/funkwhale_api/playlists/filters.py b/api/funkwhale_api/playlists/filters.py index 43029a360..f49e9bd1a 100644 --- a/api/funkwhale_api/playlists/filters.py +++ b/api/funkwhale_api/playlists/filters.py @@ -2,6 +2,7 @@ from django.db.models import Count from django_filters import rest_framework as filters from funkwhale_api.common import filters as common_filters +from funkwhale_api.music import models as music_models from funkwhale_api.music import utils from . import models @@ -10,6 +11,21 @@ from . import models class PlaylistFilter(filters.FilterSet): q = filters.CharFilter(field_name="_", method="filter_q") playable = filters.BooleanFilter(field_name="_", method="filter_playable") + track = filters.ModelChoiceFilter( + "playlist_tracks__track", + queryset=music_models.Track.objects.all(), + distinct=True, + ) + album = filters.ModelChoiceFilter( + "playlist_tracks__track__album", + queryset=music_models.Album.objects.all(), + distinct=True, + ) + artist = filters.ModelChoiceFilter( + "playlist_tracks__track__artist", + queryset=music_models.Artist.objects.all(), + distinct=True, + ) scope = common_filters.ActorScopeFilter(actor_field="user__actor", distinct=True) class Meta: diff --git a/api/tests/music/test_mutations.py b/api/tests/music/test_mutations.py index 14e71494c..93e77d114 100644 --- a/api/tests/music/test_mutations.py +++ b/api/tests/music/test_mutations.py @@ -220,3 +220,40 @@ def test_album_mutation_description(factory_name, factories, mocker): mutation.previous_state["description"] == common_serializers.ContentSerializer(content).data ) + + +@pytest.mark.parametrize( + "factory_name", ["music.Track", "music.Album", "music.Artist"], +) +def test_mutation_description_keep_tags(factory_name, factories, mocker): + mocker.patch("funkwhale_api.federation.routes.outbox.dispatch") + content = factories["common.Content"]() + obj = factories[factory_name](description=content, set_tags=["punk", "rock"]) + mutation = factories["common.Mutation"]( + type="update", + target=obj, + payload={"description": {"content_type": "text/plain", "text": "hello there"}}, + ) + mutation.apply() + obj.refresh_from_db() + + assert obj.description.content_type == "text/plain" + assert obj.description.text == "hello there" + assert obj.get_tags() == ["punk", "rock"] + + +@pytest.mark.parametrize( + "factory_name", ["music.Track", "music.Album", "music.Artist"], +) +def test_mutation_tags_keep_descriptions(factory_name, factories, mocker): + mocker.patch("funkwhale_api.federation.routes.outbox.dispatch") + content = factories["common.Content"]() + obj = factories[factory_name](description=content) + mutation = factories["common.Mutation"]( + type="update", target=obj, payload={"tags": ["punk", "rock"]}, + ) + mutation.apply() + obj.refresh_from_db() + + assert obj.description == content + assert obj.get_tags() == ["punk", "rock"] diff --git a/api/tests/playlists/test_filters.py b/api/tests/playlists/test_filters.py new file mode 100644 index 000000000..ad6a7e2f6 --- /dev/null +++ b/api/tests/playlists/test_filters.py @@ -0,0 +1,29 @@ +from funkwhale_api.playlists import filters +from funkwhale_api.playlists import models + + +def test_playlist_filter_track(factories, queryset_equal_list): + plt = factories["playlists.PlaylistTrack"]() + factories["playlists.PlaylistTrack"]() + qs = models.Playlist.objects.all() + filterset = filters.PlaylistFilter({"track": plt.track.pk}, queryset=qs) + + assert filterset.qs == [plt.playlist] + + +def test_playlist_filter_album(factories, queryset_equal_list): + plt = factories["playlists.PlaylistTrack"]() + factories["playlists.PlaylistTrack"]() + qs = models.Playlist.objects.all() + filterset = filters.PlaylistFilter({"album": plt.track.album.pk}, queryset=qs) + + assert filterset.qs == [plt.playlist] + + +def test_playlist_filter_artist(factories, queryset_equal_list): + plt = factories["playlists.PlaylistTrack"]() + factories["playlists.PlaylistTrack"]() + qs = models.Playlist.objects.all() + filterset = filters.PlaylistFilter({"artist": plt.track.artist.pk}, queryset=qs) + + assert filterset.qs == [plt.playlist] diff --git a/front/package.json b/front/package.json index e631ead69..99c143852 100644 --- a/front/package.json +++ b/front/package.json @@ -28,6 +28,7 @@ "register-service-worker": "^1.6.2", "sanitize-html": "^1.20.1", "showdown": "^1.8.6", + "text-clipper": "^1.3.0", "vue": "^2.6.10", "vue-gettext": "^2.1.0", "vue-lazyload": "^1.2.6", diff --git a/front/src/components/audio/PlayButton.vue b/front/src/components/audio/PlayButton.vue index b8c1e42fe..62f72bc95 100644 --- a/front/src/components/audio/PlayButton.vue +++ b/front/src/components/audio/PlayButton.vue @@ -7,7 +7,7 @@ :disabled="!playable" :class="buttonClasses.concat(['ui', {loading: isLoading}, {'mini': discrete}, {disabled: !playable}])"> - +
-
+

No description available

@@ -33,6 +45,7 @@