Merge branch 'round-of-bugfixes' into 'develop'
Round of bugfixes for 0.21-rc2 Closes #1079 See merge request funkwhale/funkwhale!1100
This commit is contained in:
		
						commit
						35e2cb243c
					
				|  | @ -4,6 +4,7 @@ import django_filters | ||||||
| 
 | 
 | ||||||
| from funkwhale_api.common import fields | from funkwhale_api.common import fields | ||||||
| from funkwhale_api.common import filters as common_filters | from funkwhale_api.common import filters as common_filters | ||||||
|  | from funkwhale_api.federation import actors | ||||||
| from funkwhale_api.moderation import filters as moderation_filters | from funkwhale_api.moderation import filters as moderation_filters | ||||||
| 
 | 
 | ||||||
| from . import models | from . import models | ||||||
|  | @ -28,6 +29,7 @@ class ChannelFilter(moderation_filters.HiddenContentFilterSet): | ||||||
|     subscribed = django_filters.BooleanFilter( |     subscribed = django_filters.BooleanFilter( | ||||||
|         field_name="_", method="filter_subscribed" |         field_name="_", method="filter_subscribed" | ||||||
|     ) |     ) | ||||||
|  |     external = django_filters.BooleanFilter(field_name="_", method="filter_external") | ||||||
|     ordering = django_filters.OrderingFilter( |     ordering = django_filters.OrderingFilter( | ||||||
|         # tuple-mapping retains order |         # tuple-mapping retains order | ||||||
|         fields=( |         fields=( | ||||||
|  | @ -38,7 +40,7 @@ class ChannelFilter(moderation_filters.HiddenContentFilterSet): | ||||||
| 
 | 
 | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = models.Channel |         model = models.Channel | ||||||
|         fields = ["q", "scope", "tag", "subscribed", "ordering"] |         fields = ["q", "scope", "tag", "subscribed", "ordering", "external"] | ||||||
|         hidden_content_fields_mapping = moderation_filters.USER_FILTER_CONFIG["CHANNEL"] |         hidden_content_fields_mapping = moderation_filters.USER_FILTER_CONFIG["CHANNEL"] | ||||||
| 
 | 
 | ||||||
|     def filter_subscribed(self, queryset, name, value): |     def filter_subscribed(self, queryset, name, value): | ||||||
|  | @ -56,6 +58,18 @@ class ChannelFilter(moderation_filters.HiddenContentFilterSet): | ||||||
|         else: |         else: | ||||||
|             return queryset.exclude(query) |             return queryset.exclude(query) | ||||||
| 
 | 
 | ||||||
|  |     def filter_external(self, queryset, name, value): | ||||||
|  |         query = Q( | ||||||
|  |             attributed_to=actors.get_service_actor(), | ||||||
|  |             actor__preferred_username__startswith="rssfeed-", | ||||||
|  |         ) | ||||||
|  |         if value is True: | ||||||
|  |             queryset = queryset.filter(query) | ||||||
|  |         if value is False: | ||||||
|  |             queryset = queryset.exclude(query) | ||||||
|  | 
 | ||||||
|  |         return queryset | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class IncludeChannelsFilterSet(django_filters.FilterSet): | class IncludeChannelsFilterSet(django_filters.FilterSet): | ||||||
|     """ |     """ | ||||||
|  |  | ||||||
|  | @ -200,11 +200,9 @@ class ChannelUpdateSerializer(serializers.Serializer): | ||||||
|         obj.save(update_fields=["metadata"]) |         obj.save(update_fields=["metadata"]) | ||||||
| 
 | 
 | ||||||
|         if "description" in validated_data: |         if "description" in validated_data: | ||||||
|             description_obj = common_utils.attach_content( |             common_utils.attach_content( | ||||||
|                 obj.artist, "description", validated_data["description"] |                 obj.artist, "description", validated_data["description"] | ||||||
|             ) |             ) | ||||||
|             if description_obj: |  | ||||||
|                 actor_update_fields.append(("summary", description_obj.rendered)) |  | ||||||
| 
 | 
 | ||||||
|         if "name" in validated_data: |         if "name" in validated_data: | ||||||
|             actor_update_fields.append(("name", validated_data["name"])) |             actor_update_fields.append(("name", validated_data["name"])) | ||||||
|  |  | ||||||
|  | @ -204,7 +204,8 @@ def get_api_response(request, url): | ||||||
|     except urls.exceptions.Resolver404: |     except urls.exceptions.Resolver404: | ||||||
|         return http.HttpResponseNotFound() |         return http.HttpResponseNotFound() | ||||||
|     response = match.func(request, *match.args, **match.kwargs) |     response = match.func(request, *match.args, **match.kwargs) | ||||||
|     response.render() |     if hasattr(response, "render"): | ||||||
|  |         response.render() | ||||||
|     return response |     return response | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,5 @@ | ||||||
|  | import pytest | ||||||
|  | 
 | ||||||
| from funkwhale_api.audio import filters | from funkwhale_api.audio import filters | ||||||
| from funkwhale_api.audio import models | from funkwhale_api.audio import models | ||||||
| 
 | 
 | ||||||
|  | @ -30,3 +32,17 @@ def test_channel_filter_subscribed_false(factories, mocker, queryset_equal_list) | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     assert filterset.qs == [other_channel] |     assert filterset.qs == [other_channel] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @pytest.mark.parametrize("external, expected_index", [("true", 0), ("false", 1)]) | ||||||
|  | def test_channel_filter_external( | ||||||
|  |     external, expected_index, factories, mocker, queryset_equal_list | ||||||
|  | ): | ||||||
|  |     user = factories["users.User"](with_actor=True) | ||||||
|  |     channels = [factories["audio.Channel"](external=True), factories["audio.Channel"]()] | ||||||
|  |     qs = models.Channel.objects.all() | ||||||
|  |     filterset = filters.ChannelFilter( | ||||||
|  |         {"external": external}, request=mocker.Mock(user=user), queryset=qs | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     assert filterset.qs == [channels[expected_index]] | ||||||
|  |  | ||||||
|  | @ -184,9 +184,6 @@ def test_channel_serializer_update(factories, mocker): | ||||||
|         sorted(channel.artist.tagged_items.values_list("tag__name", flat=True)) |         sorted(channel.artist.tagged_items.values_list("tag__name", flat=True)) | ||||||
|         == data["tags"] |         == data["tags"] | ||||||
|     ) |     ) | ||||||
|     assert channel.actor.summary == common_utils.render_html( |  | ||||||
|         data["description"]["text"], "text/markdown" |  | ||||||
|     ) |  | ||||||
|     assert channel.artist.description.text == data["description"]["text"] |     assert channel.artist.description.text == data["description"]["text"] | ||||||
|     assert channel.artist.description.content_type == "text/markdown" |     assert channel.artist.description.content_type == "text/markdown" | ||||||
|     assert channel.actor.name == data["name"] |     assert channel.actor.name == data["name"] | ||||||
|  |  | ||||||
|  | @ -352,7 +352,7 @@ $sidebar-color: #2D2F33; | ||||||
| 
 | 
 | ||||||
| .sidebar { | .sidebar { | ||||||
|   background: $sidebar-color; |   background: $sidebar-color; | ||||||
|   z-index: auto; |   z-index: 1; | ||||||
|   @include media(">desktop") { |   @include media(">desktop") { | ||||||
|     display: flex; |     display: flex; | ||||||
|     flex-direction: column; |     flex-direction: column; | ||||||
|  |  | ||||||
|  | @ -13,12 +13,11 @@ | ||||||
|       </button> |       </button> | ||||||
|     </template> |     </template> | ||||||
|     <template v-if="!isLoading && objects.length === 0"> |     <template v-if="!isLoading && objects.length === 0"> | ||||||
|       <div class="ui placeholder segment"> |       <empty-state @refresh="fetchData('tracks/')" :refresh="true"> | ||||||
|         <div class="ui icon header"> |         <p> | ||||||
|           <i class="music icon"></i> |           <translate translate-context="Content/Channels/*">You may need to subscribe to this channel to see its content.</translate> | ||||||
|           No results matching your query |         </p> | ||||||
|         </div> |       </empty-state> | ||||||
|       </div> |  | ||||||
|     </template> |     </template> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|  | @ -18,12 +18,11 @@ | ||||||
|       </button> |       </button> | ||||||
|     </template> |     </template> | ||||||
|     <template v-if="!isLoading && objects.length === 0"> |     <template v-if="!isLoading && objects.length === 0"> | ||||||
|       <div class="ui placeholder segment"> |       <empty-state @refresh="fetchData('albums/')" :refresh="true"> | ||||||
|         <div class="ui icon header"> |         <p> | ||||||
|           <i class="compact disc icon"></i> |           <translate translate-context="Content/Channels/*">You may need to subscribe to this channel to see its contents.</translate> | ||||||
|           No results matching your query |         </p> | ||||||
|         </div> |       </empty-state> | ||||||
|       </div> |  | ||||||
|     </template> |     </template> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ | ||||||
|         <h3 class="ui header" > |         <h3 class="ui header" > | ||||||
|           <translate translate-context="*/*/*">New channels</translate> |           <translate translate-context="*/*/*">New channels</translate> | ||||||
|         </h3> |         </h3> | ||||||
|         <channels-widget :show-modification-date="true" :limit="12" :filters="{ordering: '-creation_date'}"></channels-widget> |         <channels-widget :show-modification-date="true" :limit="12" :filters="{ordering: '-creation_date', external: 'false'}"></channels-widget> | ||||||
|       </template> |       </template> | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ | ||||||
|     <div class="ui head vertical stripe segment container"> |     <div class="ui head vertical stripe segment container"> | ||||||
|       <div class="ui stackable grid" v-if="object"> |       <div class="ui stackable grid" v-if="object"> | ||||||
|         <div class="ui five wide column"> |         <div class="ui five wide column"> | ||||||
|           <div class="ui pointing dropdown icon small basic right floated button" ref="dropdown" v-dropdown="{direction: 'downward'}" style="position: absolute; right: 1em; top: 1em; z-index: 5"> |           <div class="ui pointing dropdown icon small basic right floated button" ref="dropdown" v-dropdown="{direction: 'downward'}" style="position: absolute; right: 1em; top: 1em;"> | ||||||
|             <i class="ellipsis vertical icon"></i> |             <i class="ellipsis vertical icon"></i> | ||||||
|             <div class="menu"> |             <div class="menu"> | ||||||
|               <div |               <div | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
|       <div v-if="isLoading" class="ui centered active inline loader"></div> |       <div v-if="isLoading" class="ui centered active inline loader"></div> | ||||||
|       <div class="ui stackable grid" v-else-if="object"> |       <div class="ui stackable grid" v-else-if="object"> | ||||||
|         <div class="ui five wide column"> |         <div class="ui five wide column"> | ||||||
|           <div class="ui pointing dropdown icon small basic right floated button" ref="dropdown" v-dropdown="{direction: 'downward'}" style="position: absolute; right: 1em; top: 1em; z-index: 5"> |           <div class="ui pointing dropdown icon small basic right floated button" ref="dropdown" v-dropdown="{direction: 'downward'}" style="position: absolute; right: 1em; top: 1em;"> | ||||||
|             <i class="ellipsis vertical icon"></i> |             <i class="ellipsis vertical icon"></i> | ||||||
|             <div class="menu"> |             <div class="menu"> | ||||||
|               <div |               <div | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Agate
						Agate