Merge branch '199-disabled-play' into 'develop'
Resolve "Unplayable tracks are not disabled in the interface" Closes #199 See merge request funkwhale/funkwhale!191
This commit is contained in:
commit
2f44dd0eb7
|
@ -38,6 +38,7 @@ class ImportBatchAdmin(admin.ModelAdmin):
|
|||
search_fields = [
|
||||
'import_request__name', 'source', 'batch__pk', 'mbid']
|
||||
|
||||
|
||||
@admin.register(models.ImportJob)
|
||||
class ImportJobAdmin(admin.ModelAdmin):
|
||||
list_display = ['source', 'batch', 'track_file', 'status', 'mbid']
|
||||
|
@ -77,5 +78,10 @@ class TrackFileAdmin(admin.ModelAdmin):
|
|||
list_select_related = [
|
||||
'track'
|
||||
]
|
||||
search_fields = ['source', 'acoustid_track_id']
|
||||
search_fields = [
|
||||
'source',
|
||||
'acoustid_track_id',
|
||||
'track__title',
|
||||
'track__album__title',
|
||||
'track__artist__name']
|
||||
list_filter = ['mimetype']
|
||||
|
|
|
@ -15,6 +15,9 @@ class SubsonicJSONRenderer(renderers.JSONRenderer):
|
|||
}
|
||||
}
|
||||
final['subsonic-response'].update(data)
|
||||
if 'error' in final:
|
||||
# an error was returned
|
||||
final['subsonic-response']['status'] = 'failed'
|
||||
return super().render(final, accepted_media_type, renderer_context)
|
||||
|
||||
|
||||
|
@ -31,6 +34,9 @@ class SubsonicXMLRenderer(renderers.JSONRenderer):
|
|||
'version': '1.16.0',
|
||||
}
|
||||
final.update(data)
|
||||
if 'error' in final:
|
||||
# an error was returned
|
||||
final['status'] = 'failed'
|
||||
tree = dict_to_xml_tree('subsonic-response', final)
|
||||
return b'<?xml version="1.0" encoding="UTF-8"?>\n' + ET.tostring(tree, encoding='utf-8')
|
||||
|
||||
|
|
|
@ -31,15 +31,19 @@ def find_object(queryset, model_field='pk', field='id', cast=int):
|
|||
raw_value = data[field]
|
||||
except KeyError:
|
||||
return response.Response({
|
||||
'code': 10,
|
||||
'message': "required parameter '{}' not present".format(field)
|
||||
'error': {
|
||||
'code': 10,
|
||||
'message': "required parameter '{}' not present".format(field)
|
||||
}
|
||||
})
|
||||
try:
|
||||
value = cast(raw_value)
|
||||
except (TypeError, ValidationError):
|
||||
return response.Response({
|
||||
'code': 0,
|
||||
'message': 'For input string "{}"'.format(raw_value)
|
||||
'error': {
|
||||
'code': 0,
|
||||
'message': 'For input string "{}"'.format(raw_value)
|
||||
}
|
||||
})
|
||||
qs = queryset
|
||||
if hasattr(qs, '__call__'):
|
||||
|
@ -48,9 +52,11 @@ def find_object(queryset, model_field='pk', field='id', cast=int):
|
|||
obj = qs.get(**{model_field: value})
|
||||
except qs.model.DoesNotExist:
|
||||
return response.Response({
|
||||
'code': 70,
|
||||
'message': '{} not found'.format(
|
||||
qs.model.__class__.__name__)
|
||||
'error': {
|
||||
'code': 70,
|
||||
'message': '{} not found'.format(
|
||||
qs.model.__class__.__name__)
|
||||
}
|
||||
})
|
||||
kwargs['obj'] = obj
|
||||
return func(self, request, *args, **kwargs)
|
||||
|
@ -83,15 +89,14 @@ class SubsonicViewSet(viewsets.GenericViewSet):
|
|||
payload = {
|
||||
'status': 'failed'
|
||||
}
|
||||
try:
|
||||
if exc.__class__ in mapping:
|
||||
code, message = mapping[exc.__class__]
|
||||
except KeyError:
|
||||
return super().handle_exception(exc)
|
||||
else:
|
||||
payload['error'] = {
|
||||
'code': code,
|
||||
'message': message
|
||||
}
|
||||
return super().handle_exception(exc)
|
||||
payload['error'] = {
|
||||
'code': code,
|
||||
'message': message
|
||||
}
|
||||
|
||||
return response.Response(payload, status=200)
|
||||
|
||||
|
@ -450,8 +455,10 @@ class SubsonicViewSet(viewsets.GenericViewSet):
|
|||
name = data.get('name', '')
|
||||
if not name:
|
||||
return response.Response({
|
||||
'code': 10,
|
||||
'message': 'Playlist ID or name must be specified.'
|
||||
'error': {
|
||||
'code': 10,
|
||||
'message': 'Playlist ID or name must be specified.'
|
||||
}
|
||||
}, data)
|
||||
|
||||
playlist = request.user.playlists.create(
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Uplayable tracks are now properly disabled in the interface (#199)
|
|
@ -1,8 +1,9 @@
|
|||
<template>
|
||||
<div :class="['ui', {'tiny': discrete}, 'buttons']">
|
||||
<div :title="title" :class="['ui', {'tiny': discrete}, 'buttons']">
|
||||
<button
|
||||
:title="$t('Add to current queue')"
|
||||
@click="addNext(true)"
|
||||
:disabled="!playable"
|
||||
:class="['ui', {loading: isLoading}, {'mini': discrete}, {disabled: !playable}, 'button']">
|
||||
<i class="ui play icon"></i>
|
||||
<template v-if="!discrete"><slot><i18next path="Play"/></slot></template>
|
||||
|
@ -10,9 +11,9 @@
|
|||
<div v-if="!discrete" :class="['ui', {disabled: !playable}, 'floating', 'dropdown', 'icon', 'button']">
|
||||
<i class="dropdown icon"></i>
|
||||
<div class="menu">
|
||||
<div class="item"@click="add"><i class="plus icon"></i><i18next path="Add to queue"/></div>
|
||||
<div class="item"@click="addNext()"><i class="step forward icon"></i><i18next path="Play next"/></div>
|
||||
<div class="item"@click="addNext(true)"><i class="arrow down icon"></i><i18next path="Play now"/></div>
|
||||
<div class="item" :disabled="!playable" @click="add"><i class="plus icon"></i><i18next path="Add to queue"/></div>
|
||||
<div class="item" :disabled="!playable" @click="addNext()"><i class="step forward icon"></i><i18next path="Play next"/></div>
|
||||
<div class="item" :disabled="!playable" @click="addNext(true)"><i class="arrow down icon"></i><i18next path="Play now"/></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -45,9 +46,18 @@ export default {
|
|||
jQuery(this.$el).find('.ui.dropdown').dropdown()
|
||||
},
|
||||
computed: {
|
||||
title () {
|
||||
if (this.playable) {
|
||||
return this.$t('Play immediatly')
|
||||
} else {
|
||||
if (this.track) {
|
||||
return this.$t('This track is not imported and cannot be played')
|
||||
}
|
||||
}
|
||||
},
|
||||
playable () {
|
||||
if (this.track) {
|
||||
return true
|
||||
return this.track.files.length > 0
|
||||
} else if (this.tracks) {
|
||||
return this.tracks.length > 0
|
||||
} else if (this.playlist) {
|
||||
|
|
Loading…
Reference in New Issue