From 2e0883d44cecc53a5469f5aeefa9a4244200a13a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ciar=C3=A1n=20Ainsworth?= <ciaranainsworth@posteo.net>
Date: Tue, 20 Aug 2019 12:12:41 +0200
Subject: [PATCH] Fix #895: "Display tracks count instead of albums count for
 artists with no albums"

---
 api/funkwhale_api/music/serializers.py     |  5 +++++
 api/funkwhale_api/music/views.py           |  6 +++++-
 api/tests/music/test_serializers.py        |  3 ++-
 api/tests/music/test_views.py              |  3 ++-
 changes/changelog.d/895.enhancement        |  1 +
 docs/swagger.yml                           |  4 ++++
 front/src/components/audio/artist/Card.vue | 11 +++++++----
 7 files changed, 26 insertions(+), 7 deletions(-)
 create mode 100644 changes/changelog.d/895.enhancement

diff --git a/api/funkwhale_api/music/serializers.py b/api/funkwhale_api/music/serializers.py
index dac50960c..813d2656e 100644
--- a/api/funkwhale_api/music/serializers.py
+++ b/api/funkwhale_api/music/serializers.py
@@ -79,6 +79,7 @@ class ArtistWithAlbumsSerializer(serializers.ModelSerializer):
     albums = ArtistAlbumSerializer(many=True, read_only=True)
     tags = serializers.SerializerMethodField()
     attributed_to = serializers.SerializerMethodField()
+    tracks_count = serializers.SerializerMethodField()
 
     class Meta:
         model = models.Artist
@@ -92,6 +93,7 @@ class ArtistWithAlbumsSerializer(serializers.ModelSerializer):
             "is_local",
             "tags",
             "attributed_to",
+            "tracks_count",
         )
 
     def get_tags(self, obj):
@@ -100,6 +102,9 @@ class ArtistWithAlbumsSerializer(serializers.ModelSerializer):
 
     get_attributed_to = serialize_attributed_to
 
+    def get_tracks_count(self, o):
+        return getattr(o, "_tracks_count", None)
+
 
 class ArtistSimpleSerializer(serializers.ModelSerializer):
     class Meta:
diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py
index 15a2559da..33d3663c1 100644
--- a/api/funkwhale_api/music/views.py
+++ b/api/funkwhale_api/music/views.py
@@ -94,7 +94,11 @@ def refetch_obj(obj, queryset):
 
 
 class ArtistViewSet(common_views.SkipFilterForGetObject, viewsets.ReadOnlyModelViewSet):
-    queryset = models.Artist.objects.all().select_related("attributed_to")
+    queryset = (
+        models.Artist.objects.all()
+        .select_related("attributed_to")
+        .annotate(_tracks_count=Count("tracks"))
+    )
     serializer_class = serializers.ArtistWithAlbumsSerializer
     permission_classes = [oauth_permissions.ScopePermission]
     required_scope = "libraries"
diff --git a/api/tests/music/test_serializers.py b/api/tests/music/test_serializers.py
index fd0c312e5..333881037 100644
--- a/api/tests/music/test_serializers.py
+++ b/api/tests/music/test_serializers.py
@@ -62,7 +62,7 @@ def test_artist_with_albums_serializer(factories, to_api_date):
     artist = track.artist
     artist = artist.__class__.objects.with_albums().get(pk=artist.pk)
     album = list(artist.albums.all())[0]
-
+    setattr(artist, "_tracks_count", 42)
     expected = {
         "id": artist.id,
         "fid": artist.fid,
@@ -73,6 +73,7 @@ def test_artist_with_albums_serializer(factories, to_api_date):
         "albums": [serializers.ArtistAlbumSerializer(album).data],
         "tags": [],
         "attributed_to": federation_serializers.APIActorSerializer(actor).data,
+        "tracks_count": 42,
     }
     serializer = serializers.ArtistWithAlbumsSerializer(artist)
     assert serializer.data == expected
diff --git a/api/tests/music/test_views.py b/api/tests/music/test_views.py
index 7382e4f78..6f05c6700 100644
--- a/api/tests/music/test_views.py
+++ b/api/tests/music/test_views.py
@@ -6,6 +6,7 @@ import urllib.parse
 import uuid
 
 import pytest
+from django.db.models import Count
 from django.urls import reverse
 from django.utils import timezone
 
@@ -27,7 +28,7 @@ def test_artist_list_serializer(api_request, factories, logged_in_api_client):
     ).track
     artist = track.artist
     request = api_request.get("/")
-    qs = artist.__class__.objects.with_albums()
+    qs = artist.__class__.objects.with_albums().annotate(_tracks_count=Count("tracks"))
     serializer = serializers.ArtistWithAlbumsSerializer(
         qs, many=True, context={"request": request}
     )
diff --git a/changes/changelog.d/895.enhancement b/changes/changelog.d/895.enhancement
new file mode 100644
index 000000000..d79abc598
--- /dev/null
+++ b/changes/changelog.d/895.enhancement
@@ -0,0 +1 @@
+Artists with no albums will now show track count on artist card (#895)
\ No newline at end of file
diff --git a/docs/swagger.yml b/docs/swagger.yml
index 8ea7d00a7..d7a0230c0 100644
--- a/docs/swagger.yml
+++ b/docs/swagger.yml
@@ -1190,6 +1190,10 @@ definitions:
       - $ref: "#/definitions/BaseArtist"
       - type: "object"
         properties:
+          tracks_count:
+            type: "integer"
+            format: "int64"
+            example: 42
           albums:
             type: "array"
             items:
diff --git a/front/src/components/audio/artist/Card.vue b/front/src/components/audio/artist/Card.vue
index 21c62cf34..6fe70e266 100644
--- a/front/src/components/audio/artist/Card.vue
+++ b/front/src/components/audio/artist/Card.vue
@@ -7,10 +7,14 @@
       <router-link :title="artist.name" :to="{name: 'library.artists.detail', params: {id: artist.id}}">
         {{ artist.name|truncate(30) }}
       </router-link>
-      <div>
+      <div v-if="artist.albums.length > 0">
         <i class="small sound icon"></i>
         <translate translate-context="Content/Artist/Card" :translate-params="{count: artist.albums.length}" :translate-n="artist.albums.length" translate-plural="%{ count } albums">1 album</translate>
       </div>
+      <div v-else-if="artist.tracks_count">
+        <i class="small sound icon"></i>
+        <translate translate-context="Content/Artist/Card" :translate-params="{count: artist.tracks_count}" :translate-n="artist.tracks_count" translate-plural="%{ count } tracks">1 track</translate>
+      </div>
       <tags-list label-classes="tiny" :truncate-size="20" :limit="2" :show-more="false" :tags="artist.tags"></tags-list>
 
       <play-button
@@ -38,11 +42,10 @@ export default {
     return {
       backend: backend,
       initialAlbums: 30,
-      showAllAlbums: true
+      showAllAlbums: true,
     }
   },
   computed: {
-
     imageUrl () {
       let url = '../../../assets/audio/default-cover.png'
       let cover = this.cover
@@ -59,7 +62,7 @@ export default {
       }).filter((c) => {
         return !!c
       })[0] || {}
-    }
+    },
   }
 }
 </script>
-- 
GitLab