From b36b03383eb8cc108d3c57ccf755cf6eb478fe86 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 9 Apr 2019 09:34:59 +0200 Subject: [PATCH 1/4] Fixed broken metadata update on track without license --- api/funkwhale_api/common/mutations.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/api/funkwhale_api/common/mutations.py b/api/funkwhale_api/common/mutations.py index 11624e9f6..25abaede2 100644 --- a/api/funkwhale_api/common/mutations.py +++ b/api/funkwhale_api/common/mutations.py @@ -114,7 +114,10 @@ class UpdateMutationSerializer(serializers.ModelSerializer, MutationSerializer): # to ensure we store ids instead of model instances in our json # payload for field, attr in self.serialized_relations.items(): - data[field] = getattr(data[field], attr) + try: + data[field] = getattr(data[field], attr) + except KeyError: + continue return data def create(self, validated_data): From a3ad476c88d64bb6c5f70e7925cbb5a1da29aa23 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 9 Apr 2019 10:30:26 +0200 Subject: [PATCH 2/4] More configurable pagination --- api/funkwhale_api/common/pagination.py | 27 ++++++++++++++++++++++-- api/funkwhale_api/music/views.py | 1 + api/tests/common/test_pagination.py | 29 ++++++++++++++++++++++++++ api/tests/music/test_views.py | 2 +- 4 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 api/tests/common/test_pagination.py diff --git a/api/funkwhale_api/common/pagination.py b/api/funkwhale_api/common/pagination.py index e5068bce2..ec7c27dc4 100644 --- a/api/funkwhale_api/common/pagination.py +++ b/api/funkwhale_api/common/pagination.py @@ -1,6 +1,29 @@ -from rest_framework.pagination import PageNumberPagination +from rest_framework.pagination import PageNumberPagination, _positive_int class FunkwhalePagination(PageNumberPagination): page_size_query_param = "page_size" - max_page_size = 50 + default_max_page_size = 50 + default_page_size = None + view = None + + def paginate_queryset(self, queryset, request, view=None): + self.view = view + return super().paginate_queryset(queryset, request, view) + + def get_page_size(self, request): + max_page_size = ( + getattr(self.view, "max_page_size", 0) or self.default_max_page_size + ) + page_size = getattr(self.view, "default_page_size", 0) or max_page_size + if self.page_size_query_param: + try: + return _positive_int( + request.query_params[self.page_size_query_param], + strict=True, + cutoff=max_page_size, + ) + except (KeyError, ValueError): + pass + + return page_size diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py index b5242eeb1..2f0e67cb9 100644 --- a/api/funkwhale_api/music/views.py +++ b/api/funkwhale_api/music/views.py @@ -524,6 +524,7 @@ class LicenseViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = serializers.LicenseSerializer queryset = models.License.objects.all().order_by("code") lookup_value_regex = ".*" + max_page_size = 1000 def get_queryset(self): # ensure our licenses are up to date in DB diff --git a/api/tests/common/test_pagination.py b/api/tests/common/test_pagination.py new file mode 100644 index 000000000..cacbe740c --- /dev/null +++ b/api/tests/common/test_pagination.py @@ -0,0 +1,29 @@ +import pytest + +from funkwhale_api.common import pagination + + +@pytest.mark.parametrize( + "view_max_page_size, view_default_page_size, request_page_size, expected", + [ + (50, 50, None, 50), + (50, 25, None, 25), + (25, None, None, 25), + (50, 25, 100, 50), + (50, None, 100, 50), + (50, 25, 33, 33), + ], +) +def test_funkwhale_pagination_uses_view_page_size( + view_max_page_size, view_default_page_size, request_page_size, expected, mocker +): + p = pagination.FunkwhalePagination() + + p.view = mocker.Mock( + max_page_size=view_max_page_size, default_page_size=view_default_page_size + ) + query = {} + if request_page_size: + query["page_size"] = request_page_size + request = mocker.Mock(query_params=query) + assert p.get_page_size(request) == expected diff --git a/api/tests/music/test_views.py b/api/tests/music/test_views.py index 7b12c6c8f..2c3a61c05 100644 --- a/api/tests/music/test_views.py +++ b/api/tests/music/test_views.py @@ -612,7 +612,7 @@ def test_list_licenses(api_client, preferences, mocker): expected = [ serializers.LicenseSerializer(l.conf).data - for l in models.License.objects.order_by("code")[:25] + for l in models.License.objects.order_by("code") ] url = reverse("api:v1:licenses-list") From 45142bf24b72825621c9a3f2bb9f82c85d8bc9dc Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 9 Apr 2019 11:03:45 +0200 Subject: [PATCH 3/4] Added better dropdown for choosing licenses --- api/funkwhale_api/common/mutations.py | 6 +++- api/tests/music/test_mutations.py | 12 ++++++++ front/src/components/library/EditForm.vue | 35 ++++++++++++++++++++-- front/src/components/library/TrackEdit.vue | 24 +++++++++++++-- front/src/edits.js | 4 +-- 5 files changed, 74 insertions(+), 7 deletions(-) diff --git a/api/funkwhale_api/common/mutations.py b/api/funkwhale_api/common/mutations.py index 25abaede2..c3e92c15b 100644 --- a/api/funkwhale_api/common/mutations.py +++ b/api/funkwhale_api/common/mutations.py @@ -115,9 +115,13 @@ class UpdateMutationSerializer(serializers.ModelSerializer, MutationSerializer): # payload for field, attr in self.serialized_relations.items(): try: - data[field] = getattr(data[field], attr) + obj = data[field] except KeyError: continue + if obj is None: + data[field] = None + else: + data[field] = getattr(obj, attr) return data def create(self, validated_data): diff --git a/api/tests/music/test_mutations.py b/api/tests/music/test_mutations.py index d6b8223d4..062d00f98 100644 --- a/api/tests/music/test_mutations.py +++ b/api/tests/music/test_mutations.py @@ -13,6 +13,18 @@ def test_track_license_mutation(factories, now): assert track.license.code == "cc-by-sa-4.0" +def test_track_null_license_mutation(factories, now): + track = factories["music.Track"](license="cc-by-sa-4.0") + mutation = factories["common.Mutation"]( + type="update", target=track, payload={"license": None} + ) + licenses.load(licenses.LICENSES) + mutation.apply() + track.refresh_from_db() + + assert track.license is None + + def test_track_title_mutation(factories, now): track = factories["music.Track"](title="foo") mutation = factories["common.Mutation"]( diff --git a/front/src/components/library/EditForm.vue b/front/src/components/library/EditForm.vue index 000108119..a2df96c00 100644 --- a/front/src/components/library/EditForm.vue +++ b/front/src/components/library/EditForm.vue @@ -59,10 +59,28 @@ +
@@ -87,6 +105,7 @@ diff --git a/front/src/components/library/TrackEdit.vue b/front/src/components/library/TrackEdit.vue index 7e26d1df1..32b3a627a 100644 --- a/front/src/components/library/TrackEdit.vue +++ b/front/src/components/library/TrackEdit.vue @@ -6,7 +6,12 @@ Edit this track Suggest an edit on this track - + @@ -19,12 +24,27 @@ export default { props: ["objectType", "object", "libraries"], data() { return { - id: this.object.id + id: this.object.id, + isLoadingLicenses: false, + licenses: [] } }, components: { EditForm }, + created () { + this.fetchLicenses() + }, + methods: { + fetchLicenses () { + let self = this + self.isLoadingLicenses = true + axios.get('licenses/').then((response) => { + self.isLoadingLicenses = false + self.licenses = response.data.results + }) + } + }, computed: { canEdit () { return true diff --git a/front/src/edits.js b/front/src/edits.js index ccc9c16b3..4e6a85c73 100644 --- a/front/src/edits.js +++ b/front/src/edits.js @@ -12,10 +12,10 @@ export default { }, { id: 'license', - type: 'text', + type: 'license', required: false, label: this.$pgettext('Content/*/*/Noun', 'License'), - getValue: (obj) => { return obj.license } + getValue: (obj) => { return obj.license }, }, { id: 'position', From 0ce51d25d493e8c691eadbdfb7791d205e00e2ed Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 9 Apr 2019 11:11:05 +0200 Subject: [PATCH 4/4] Can now edit track copyright information --- api/funkwhale_api/music/mutations.py | 2 +- api/tests/music/test_mutations.py | 11 +++++++++++ front/src/components/library/TrackEdit.vue | 5 ++++- front/src/edits.js | 23 ++++++++++++++-------- 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/api/funkwhale_api/music/mutations.py b/api/funkwhale_api/music/mutations.py index 51efa0ab8..4d78b8ea9 100644 --- a/api/funkwhale_api/music/mutations.py +++ b/api/funkwhale_api/music/mutations.py @@ -21,4 +21,4 @@ class TrackMutationSerializer(mutations.UpdateMutationSerializer): class Meta: model = models.Track - fields = ["license", "title", "position"] + fields = ["license", "title", "position", "copyright"] diff --git a/api/tests/music/test_mutations.py b/api/tests/music/test_mutations.py index 062d00f98..bc9e81f8e 100644 --- a/api/tests/music/test_mutations.py +++ b/api/tests/music/test_mutations.py @@ -36,6 +36,17 @@ def test_track_title_mutation(factories, now): assert track.title == "bar" +def test_track_copyright_mutation(factories, now): + track = factories["music.Track"](copyright="foo") + mutation = factories["common.Mutation"]( + type="update", target=track, payload={"copyright": "bar"} + ) + mutation.apply() + track.refresh_from_db() + + assert track.copyright == "bar" + + def test_track_position_mutation(factories): track = factories["music.Track"](position=4) mutation = factories["common.Mutation"]( diff --git a/front/src/components/library/TrackEdit.vue b/front/src/components/library/TrackEdit.vue index 32b3a627a..945bae961 100644 --- a/front/src/components/library/TrackEdit.vue +++ b/front/src/components/library/TrackEdit.vue @@ -12,8 +12,11 @@ :object="object" :can-edit="canEdit" :licenses="licenses"> +
+
- + +