Merge branch 'license-metadata-update' into 'develop'

License metadata update

See merge request funkwhale/funkwhale!712
merge-requests/757/head
Eliot Berriot 2019-04-09 11:18:47 +02:00
commit 8687a64873
10 zmienionych plików z 162 dodań i 18 usunięć

Wyświetl plik

@ -114,7 +114,14 @@ 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:
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):

Wyświetl plik

@ -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

Wyświetl plik

@ -21,4 +21,4 @@ class TrackMutationSerializer(mutations.UpdateMutationSerializer):
class Meta:
model = models.Track
fields = ["license", "title", "position"]
fields = ["license", "title", "position", "copyright"]

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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"](
@ -24,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"](

Wyświetl plik

@ -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")

Wyświetl plik

@ -59,10 +59,28 @@
<label :for="fieldConfig.id">{{ fieldConfig.label }}</label>
<input :type="fieldConfig.inputType || 'text'" v-model="values[fieldConfig.id]" :required="fieldConfig.required" :name="fieldConfig.id" :id="fieldConfig.id">
</template>
<template v-else-if="fieldConfig.type === 'license'">
<label :for="fieldConfig.id">{{ fieldConfig.label }}</label>
<select
ref="license"
v-model="values[fieldConfig.id]"
:required="fieldConfig.required"
:id="fieldConfig.id"
class="ui fluid search dropdown">
<option :value="null"><translate translate-context="*/*/*">N/A</translate></option>
<option v-for="license in licenses" :key="license.code" :value="license.code">{{ license.name}}</option>
</select>
<button class="ui tiny basic left floated button" form="noop" @click.prevent="values[fieldConfig.id] = null">
<i class="x icon"></i>
<translate translate-context="Content/Library/Button.Label">Clear</translate>
</button>
</template>
<div v-if="values[fieldConfig.id] != initialValues[fieldConfig.id]">
<button class="ui tiny basic right floated reset button" form="noop" @click.prevent="values[fieldConfig.id] = initialValues[fieldConfig.id]">
<i class="undo icon"></i>
<translate translate-context="Content/Library/Button.Label" :translate-params="{value: initialValues[fieldConfig.id]}">Reset to initial value: %{ value }</translate>
<translate translate-context="Content/Library/Button.Label" :translate-params="{value: initialValues[fieldConfig.id] || ''}">Reset to initial value: %{ value }</translate>
</button>
</div>
</div>
@ -87,6 +105,7 @@
</template>
<script>
import $ from 'jquery'
import _ from '@/lodash'
import axios from "axios"
import EditList from '@/components/library/EditList'
@ -94,7 +113,7 @@ import EditCard from '@/components/library/EditCard'
import edits from '@/edits'
export default {
props: ["objectType", "object"],
props: ["objectType", "object", "licenses"],
components: {
EditList,
EditCard
@ -113,6 +132,9 @@ export default {
created () {
this.setValues()
},
mounted() {
$(".ui.dropdown").dropdown({fullTextSearch: true})
},
computed: {
configs: edits.getConfigs,
config: edits.getConfig,
@ -182,6 +204,15 @@ export default {
}
)
}
},
watch: {
'values.license' (newValue) {
if (newValue === null) {
$(this.$refs.license).dropdown('clear')
} else {
$(this.$refs.license).dropdown('set selected', newValue)
}
}
}
}
</script>

Wyświetl plik

@ -6,9 +6,17 @@
<translate v-if="canEdit" key="1" translate-context="Content/*/Title">Edit this track</translate>
<translate v-else key="2" translate-context="Content/*/Title">Suggest an edit on this track</translate>
</h2>
<edit-form :object-type="objectType" :object="object" :can-edit="canEdit"></edit-form>
<edit-form
v-if="!isLoadingLicenses"
:object-type="objectType"
:object="object"
:can-edit="canEdit"
:licenses="licenses"></edit-form>
<div v-else class="ui inverted active dimmer">
<div class="ui loader"></div>
</div>
</section>
</div>
</section>
</template>
<script>
@ -19,12 +27,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

Wyświetl plik

@ -10,13 +10,6 @@ export default {
label: this.$pgettext('Content/Track/*/Noun', 'Title'),
getValue: (obj) => { return obj.title }
},
{
id: 'license',
type: 'text',
required: false,
label: this.$pgettext('Content/*/*/Noun', 'License'),
getValue: (obj) => { return obj.license }
},
{
id: 'position',
type: 'text',
@ -24,7 +17,21 @@ export default {
required: false,
label: this.$pgettext('*/*/*/Short, Noun', 'Position'),
getValue: (obj) => { return obj.position }
}
},
{
id: 'copyright',
type: 'text',
required: false,
label: this.$pgettext('Content/Track/*/Noun', 'Copyright'),
getValue: (obj) => { return obj.copyright }
},
{
id: 'license',
type: 'license',
required: false,
label: this.$pgettext('Content/*/*/Noun', 'License'),
getValue: (obj) => { return obj.license },
},
]
}
}