From 37383a53b2dee663db02281dbb48ca977da94191 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 12 Dec 2017 22:15:50 +0100 Subject: [PATCH 1/8] Ensure shortcuts don't collide in inputs --- front/package.json | 1 - front/src/components/Sidebar.vue | 2 +- front/src/components/audio/Player.vue | 2 +- front/src/components/utils/global-events.vue | 52 ++++++++++++++++++++ 4 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 front/src/components/utils/global-events.vue diff --git a/front/package.json b/front/package.json index 55e773fba..7cec50319 100644 --- a/front/package.json +++ b/front/package.json @@ -18,7 +18,6 @@ "js-logger": "^1.3.0", "semantic-ui-css": "^2.2.10", "vue": "^2.3.3", - "vue-global-events": "^1.0.2", "vue-resource": "^1.3.4", "vue-router": "^2.3.1", "vuedraggable": "^2.14.1" diff --git a/front/src/components/Sidebar.vue b/front/src/components/Sidebar.vue index 0ce16a75f..68927a37b 100644 --- a/front/src/components/Sidebar.vue +++ b/front/src/components/Sidebar.vue @@ -94,7 +94,7 @@ From 45152101625473d6c74a3eb91b382a4efa221a8f Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 12 Dec 2017 22:58:17 +0100 Subject: [PATCH 2/8] better pagination on favorites --- api/funkwhale_api/music/fake_data.py | 22 +++++++++ api/funkwhale_api/music/tests/factories.py | 6 +-- front/package.json | 1 + front/src/components/Pagination.vue | 52 ++++++++++++++++++++++ front/src/components/favorites/List.vue | 27 ++++++++--- 5 files changed, 99 insertions(+), 9 deletions(-) create mode 100644 api/funkwhale_api/music/fake_data.py create mode 100644 front/src/components/Pagination.vue diff --git a/api/funkwhale_api/music/fake_data.py b/api/funkwhale_api/music/fake_data.py new file mode 100644 index 000000000..ef5eaf4be --- /dev/null +++ b/api/funkwhale_api/music/fake_data.py @@ -0,0 +1,22 @@ +""" +Populates the database with fake data +""" +import random + +from funkwhale_api.music import models +from funkwhale_api.music.tests import factories + + +def create_data(count=25): + artists = factories.ArtistFactory.create_batch(size=count) + for artist in artists: + print('Creating data for', artist) + albums = factories.AlbumFactory.create_batch( + artist=artist, size=random.randint(1, 5)) + for album in albums: + factories.TrackFileFactory.create_batch( + track__album=album, size=random.randint(3, 18)) + + +if __name__ == '__main__': + main() diff --git a/api/funkwhale_api/music/tests/factories.py b/api/funkwhale_api/music/tests/factories.py index d4ec04810..ea680b3bd 100644 --- a/api/funkwhale_api/music/tests/factories.py +++ b/api/funkwhale_api/music/tests/factories.py @@ -5,7 +5,7 @@ SAMPLES_PATH = os.path.dirname(os.path.abspath(__file__)) class ArtistFactory(factory.django.DjangoModelFactory): - name = factory.Sequence(lambda n: 'artist-{0}'.format(n)) + name = factory.Faker('name') mbid = factory.Faker('uuid4') class Meta: @@ -13,7 +13,7 @@ class ArtistFactory(factory.django.DjangoModelFactory): class AlbumFactory(factory.django.DjangoModelFactory): - title = factory.Sequence(lambda n: 'album-{0}'.format(n)) + title = factory.Faker('sentence', nb_words=3) mbid = factory.Faker('uuid4') release_date = factory.Faker('date') cover = factory.django.ImageField() @@ -24,7 +24,7 @@ class AlbumFactory(factory.django.DjangoModelFactory): class TrackFactory(factory.django.DjangoModelFactory): - title = factory.Sequence(lambda n: 'track-{0}'.format(n)) + title = factory.Faker('sentence', nb_words=3) mbid = factory.Faker('uuid4') album = factory.SubFactory(AlbumFactory) artist = factory.SelfAttribute('album.artist') diff --git a/front/package.json b/front/package.json index 7cec50319..cc6869267 100644 --- a/front/package.json +++ b/front/package.json @@ -16,6 +16,7 @@ "dependencies": { "dateformat": "^2.0.0", "js-logger": "^1.3.0", + "lodash": "^4.17.4", "semantic-ui-css": "^2.2.10", "vue": "^2.3.3", "vue-resource": "^1.3.4", diff --git a/front/src/components/Pagination.vue b/front/src/components/Pagination.vue new file mode 100644 index 000000000..3ac7c59af --- /dev/null +++ b/front/src/components/Pagination.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/front/src/components/favorites/List.vue b/front/src/components/favorites/List.vue index f7972a07c..053f62bc6 100644 --- a/front/src/components/favorites/List.vue +++ b/front/src/components/favorites/List.vue @@ -12,11 +12,14 @@
- - - - +
+ +
@@ -28,13 +31,15 @@ import config from '@/config' import favoriteTracks from '@/favorites/tracks' import TrackTable from '@/components/audio/track/Table' import RadioButton from '@/components/radios/Button' +import Pagination from '@/components/Pagination' const FAVORITES_URL = config.API_URL + 'tracks/' export default { components: { TrackTable, - RadioButton + RadioButton, + Pagination }, data () { return { @@ -42,6 +47,7 @@ export default { isLoading: false, nextLink: null, previousLink: null, + page: 1, favoriteTracks } }, @@ -53,7 +59,8 @@ export default { var self = this this.isLoading = true let params = { - favorites: 'true' + favorites: 'true', + page: this.page } logger.default.time('Loading user favorites') this.$http.get(url, {params: params}).then((response) => { @@ -68,6 +75,14 @@ export default { logger.default.timeEnd('Loading user favorites') self.isLoading = false }) + }, + selectPage: function (page) { + this.page = page + } + }, + watch: { + page: function () { + this.fetchFavorites(FAVORITES_URL) } } } From c6d408924b2c8ea7fc505546fd3f94005859fd58 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 12 Dec 2017 22:04:39 +0100 Subject: [PATCH 3/8] Added artist filtering on API --- api/config/settings/common.py | 1 + api/funkwhale_api/music/filters.py | 12 ++++++++++++ api/funkwhale_api/music/tests/test_api.py | 15 +++++++++++++++ api/funkwhale_api/music/views.py | 5 ++++- api/requirements/base.txt | 1 + 5 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 api/funkwhale_api/music/filters.py diff --git a/api/config/settings/common.py b/api/config/settings/common.py index 3f7cc7503..87740e818 100644 --- a/api/config/settings/common.py +++ b/api/config/settings/common.py @@ -309,6 +309,7 @@ REST_FRAMEWORK = { ), 'DEFAULT_FILTER_BACKENDS': ( 'rest_framework.filters.OrderingFilter', + 'django_filters.rest_framework.DjangoFilterBackend', ) } diff --git a/api/funkwhale_api/music/filters.py b/api/funkwhale_api/music/filters.py new file mode 100644 index 000000000..ba3fa453d --- /dev/null +++ b/api/funkwhale_api/music/filters.py @@ -0,0 +1,12 @@ +import django_filters + +from . import models + + +class ArtistFilter(django_filters.FilterSet): + + class Meta: + model = models.Artist + fields = { + 'name': ['exact', 'iexact', 'startswith'] + } diff --git a/api/funkwhale_api/music/tests/test_api.py b/api/funkwhale_api/music/tests/test_api.py index 21a567084..b7c25424f 100644 --- a/api/funkwhale_api/music/tests/test_api.py +++ b/api/funkwhale_api/music/tests/test_api.py @@ -182,6 +182,21 @@ class TestAPI(TMPDirTestCaseMixin, TestCase): self.assertJSONEqual(expected, json.loads(response.content.decode('utf-8'))) + def test_can_search_artist_by_name_start(self): + artist1 = factories.ArtistFactory(name='alpha') + artist2 = factories.ArtistFactory(name='beta') + results = { + 'next': None, + 'previous': None, + 'count': 1, + 'results': [serializers.ArtistSerializerNested(artist1).data] + } + expected = json.dumps(results) + url = self.reverse('api:v1:artists-list') + response = self.client.get(url, {'name__startswith': 'a'}) + + self.assertJSONEqual(expected, json.loads(response.content.decode('utf-8'))) + def test_can_search_tracks(self): artist1 = models.Artist.objects.create(name='Test1') artist2 = models.Artist.objects.create(name='Test2') diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py index 983192552..d149b5d1b 100644 --- a/api/funkwhale_api/music/views.py +++ b/api/funkwhale_api/music/views.py @@ -21,8 +21,10 @@ from taggit.models import Tag from . import models from . import serializers from . import importers +from . import filters from . import utils + class SearchMixin(object): search_fields = [] @@ -52,7 +54,8 @@ class ArtistViewSet(SearchMixin, viewsets.ReadOnlyModelViewSet): serializer_class = serializers.ArtistSerializerNested permission_classes = [ConditionalAuthentication] search_fields = ['name'] - ordering_fields = ('creation_date',) + ordering_fields = ('creation_date', 'name') + filter_class = filters.ArtistFilter class AlbumViewSet(SearchMixin, viewsets.ReadOnlyModelViewSet): diff --git a/api/requirements/base.txt b/api/requirements/base.txt index e7bc870cf..3a11afadf 100644 --- a/api/requirements/base.txt +++ b/api/requirements/base.txt @@ -45,6 +45,7 @@ django-taggit==0.22.1 persisting-theory==0.2.1 django-versatileimagefield==1.7.1 django-cachalot==1.5.0 +django-filter==1.1 django-rest-auth==0.9.1 beautifulsoup4==4.6.0 Markdown==2.6.8 From 74926114e49630c5e2df03997ea8424db4140531 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 12 Dec 2017 23:03:58 +0100 Subject: [PATCH 4/8] Updated library routes to handle both detail and browse views --- front/src/components/audio/Player.vue | 6 +++--- front/src/components/audio/SearchBar.vue | 6 +++--- front/src/components/audio/album/Card.vue | 6 +++--- front/src/components/audio/artist/Card.vue | 4 ++-- front/src/components/audio/track/Table.vue | 6 +++--- front/src/components/library/Album.vue | 2 +- front/src/components/library/Track.vue | 4 ++-- front/src/router/index.js | 6 +++--- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/front/src/components/audio/Player.vue b/front/src/components/audio/Player.vue index 72b7d7ef9..423c9d12f 100644 --- a/front/src/components/audio/Player.vue +++ b/front/src/components/audio/Player.vue @@ -7,14 +7,14 @@
- + {{ queue.currentTrack.title }}
- + {{ queue.currentTrack.artist.name }} / - + {{ queue.currentTrack.album.title }}
diff --git a/front/src/components/audio/SearchBar.vue b/front/src/components/audio/SearchBar.vue index 6f4629296..2324c8839 100644 --- a/front/src/components/audio/SearchBar.vue +++ b/front/src/components/audio/SearchBar.vue @@ -35,7 +35,7 @@ export default { let categories = [ { code: 'artists', - route: 'library.artist', + route: 'library.artists.detail', name: 'Artist', getTitle (r) { return r.name @@ -46,7 +46,7 @@ export default { }, { code: 'albums', - route: 'library.album', + route: 'library.albums.detail', name: 'Album', getTitle (r) { return r.title @@ -57,7 +57,7 @@ export default { }, { code: 'tracks', - route: 'library.track', + route: 'library.tracks.detail', name: 'Track', getTitle (r) { return r.title diff --git a/front/src/components/audio/album/Card.vue b/front/src/components/audio/album/Card.vue index 7fd60d963..6902612dd 100644 --- a/front/src/components/audio/album/Card.vue +++ b/front/src/components/audio/album/Card.vue @@ -6,10 +6,10 @@
- {{ album.title }} + {{ album.title }}
- By + By {{ album.artist.name }}
@@ -21,7 +21,7 @@ - + diff --git a/front/src/components/audio/artist/Card.vue b/front/src/components/audio/artist/Card.vue index a9701c07e..8a02163fb 100644 --- a/front/src/components/audio/artist/Card.vue +++ b/front/src/components/audio/artist/Card.vue @@ -2,7 +2,7 @@
- + {{ artist.name }}
@@ -15,7 +15,7 @@ - + {{ album.title }}
{{ album.tracks.length }} tracks diff --git a/front/src/components/audio/track/Table.vue b/front/src/components/audio/track/Table.vue index e9beaa05a..ac903ad52 100644 --- a/front/src/components/audio/track/Table.vue +++ b/front/src/components/audio/track/Table.vue @@ -20,7 +20,7 @@ - + @@ -28,12 +28,12 @@ - + {{ track.artist.name }} - + {{ track.album.title }} diff --git a/front/src/components/library/Album.vue b/front/src/components/library/Album.vue index cf3403400..dcfea5600 100644 --- a/front/src/components/library/Album.vue +++ b/front/src/components/library/Album.vue @@ -12,7 +12,7 @@ {{ album.title }}
Album containing {{ album.tracks.length }} tracks, - by + by {{ album.artist.name }}
diff --git a/front/src/components/library/Track.vue b/front/src/components/library/Track.vue index 3c627c13c..36a76e822 100644 --- a/front/src/components/library/Track.vue +++ b/front/src/components/library/Track.vue @@ -12,10 +12,10 @@ {{ track.title }}
From album - + {{ track.album.title }} - by + by {{ track.artist.name }}
diff --git a/front/src/router/index.js b/front/src/router/index.js index b3d90731f..cb8f9c1b5 100644 --- a/front/src/router/index.js +++ b/front/src/router/index.js @@ -51,9 +51,9 @@ export default new Router({ component: Library, children: [ { path: '', component: LibraryHome }, - { path: 'artist/:id', name: 'library.artist', component: LibraryArtist, props: true }, - { path: 'album/:id', name: 'library.album', component: LibraryAlbum, props: true }, - { path: 'track/:id', name: 'library.track', component: LibraryTrack, props: true }, + { path: 'artists/:id', name: 'library.artists.detail', component: LibraryArtist, props: true }, + { path: 'albums/:id', name: 'library.albums.detail', component: LibraryAlbum, props: true }, + { path: 'tracks/:id', name: 'library.tracks.detail', component: LibraryTrack, props: true }, { path: 'import/launch', name: 'library.import.launch', From 926db0f366576235d0d967ebd7bfb2ff7e61e31a Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 12 Dec 2017 23:41:47 +0100 Subject: [PATCH 5/8] Fixed #40: added artist browsing view --- api/config/settings/common.py | 3 +- api/funkwhale_api/common/pagination.py | 6 ++ front/src/components/favorites/List.vue | 5 +- front/src/components/library/Artists.vue | 86 ++++++++++++++++++++++++ front/src/components/library/Library.vue | 7 +- front/src/router/index.js | 2 + 6 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 api/funkwhale_api/common/pagination.py create mode 100644 front/src/components/library/Artists.vue diff --git a/api/config/settings/common.py b/api/config/settings/common.py index 87740e818..6a2299bb4 100644 --- a/api/config/settings/common.py +++ b/api/config/settings/common.py @@ -54,6 +54,7 @@ THIRD_PARTY_APPS = ( 'rest_auth.registration', 'mptt', 'dynamic_preferences', + 'django_filters', ) # Apps specific for this project go here. @@ -298,7 +299,7 @@ REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ), - 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', + 'DEFAULT_PAGINATION_CLASS': 'funkwhale_api.common.pagination.FunkwhalePagination', 'PAGE_SIZE': 25, 'DEFAULT_AUTHENTICATION_CLASSES': ( diff --git a/api/funkwhale_api/common/pagination.py b/api/funkwhale_api/common/pagination.py new file mode 100644 index 000000000..224c470dc --- /dev/null +++ b/api/funkwhale_api/common/pagination.py @@ -0,0 +1,6 @@ +from rest_framework.pagination import PageNumberPagination + + +class FunkwhalePagination(PageNumberPagination): + page_size_query_param = 'page_size' + max_page_size = 25 diff --git a/front/src/components/favorites/List.vue b/front/src/components/favorites/List.vue index 053f62bc6..7e3e23505 100644 --- a/front/src/components/favorites/List.vue +++ b/front/src/components/favorites/List.vue @@ -17,6 +17,7 @@
@@ -48,6 +49,7 @@ export default { nextLink: null, previousLink: null, page: 1, + paginateBy: 25, favoriteTracks } }, @@ -60,7 +62,8 @@ export default { this.isLoading = true let params = { favorites: 'true', - page: this.page + page: this.page, + page_size: this.paginateBy } logger.default.time('Loading user favorites') this.$http.get(url, {params: params}).then((response) => { diff --git a/front/src/components/library/Artists.vue b/front/src/components/library/Artists.vue new file mode 100644 index 000000000..a9890dada --- /dev/null +++ b/front/src/components/library/Artists.vue @@ -0,0 +1,86 @@ + + + + + + diff --git a/front/src/components/library/Library.vue b/front/src/components/library/Library.vue index 56b750a4a..da9ac19b3 100644 --- a/front/src/components/library/Library.vue +++ b/front/src/components/library/Library.vue @@ -2,8 +2,11 @@
diff --git a/front/src/router/index.js b/front/src/router/index.js index cb8f9c1b5..e546172b5 100644 --- a/front/src/router/index.js +++ b/front/src/router/index.js @@ -7,6 +7,7 @@ import Logout from '@/components/auth/Logout' import Library from '@/components/library/Library' import LibraryHome from '@/components/library/Home' import LibraryArtist from '@/components/library/Artist' +import LibraryArtists from '@/components/library/Artists' import LibraryAlbum from '@/components/library/Album' import LibraryTrack from '@/components/library/Track' import LibraryImport from '@/components/library/import/Main' @@ -51,6 +52,7 @@ export default new Router({ component: Library, children: [ { path: '', component: LibraryHome }, + { path: 'artists/', name: 'library.artists.browse', component: LibraryArtists }, { path: 'artists/:id', name: 'library.artists.detail', component: LibraryArtist, props: true }, { path: 'albums/:id', name: 'library.albums.detail', component: LibraryAlbum, props: true }, { path: 'tracks/:id', name: 'library.tracks.detail', component: LibraryTrack, props: true }, From cdcfcc1e9774ac5c376db9219a19121363cbd829 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 12 Dec 2017 23:49:54 +0100 Subject: [PATCH 6/8] Fixed #41: lazyload track and album images --- front/package.json | 1 + front/src/components/audio/album/Card.vue | 2 +- front/src/components/audio/track/Table.vue | 2 +- front/src/main.js | 2 ++ 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/front/package.json b/front/package.json index cc6869267..bad90430f 100644 --- a/front/package.json +++ b/front/package.json @@ -19,6 +19,7 @@ "lodash": "^4.17.4", "semantic-ui-css": "^2.2.10", "vue": "^2.3.3", + "vue-lazyload": "^1.1.4", "vue-resource": "^1.3.4", "vue-router": "^2.3.1", "vuedraggable": "^2.14.1" diff --git a/front/src/components/audio/album/Card.vue b/front/src/components/audio/album/Card.vue index 7fd60d963..bd3b70e67 100644 --- a/front/src/components/audio/album/Card.vue +++ b/front/src/components/audio/album/Card.vue @@ -2,7 +2,7 @@
- +
diff --git a/front/src/components/audio/track/Table.vue b/front/src/components/audio/track/Table.vue index e9beaa05a..630225e33 100644 --- a/front/src/components/audio/track/Table.vue +++ b/front/src/components/audio/track/Table.vue @@ -16,7 +16,7 @@ - + diff --git a/front/src/main.js b/front/src/main.js index 4ffbdb2f7..a214c3881 100644 --- a/front/src/main.js +++ b/front/src/main.js @@ -10,6 +10,7 @@ import App from './App' import router from './router' import VueResource from 'vue-resource' import auth from './auth' +import VueLazyload from 'vue-lazyload' window.$ = window.jQuery = require('jquery') @@ -19,6 +20,7 @@ window.$ = window.jQuery = require('jquery') require('semantic-ui-css/semantic.js') Vue.use(VueResource) +Vue.use(VueLazyload) Vue.config.productionTip = false Vue.http.interceptors.push(function (request, next) { From 2e5c714a5937e14a771dfdb34bcb9fbe07c0b48e Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 12 Dec 2017 23:52:26 +0100 Subject: [PATCH 7/8] Fixed various warnings --- front/src/components/favorites/List.vue | 1 + front/src/components/library/Artists.vue | 86 ++++++++++++++++++++++++ front/src/components/library/Home.vue | 2 +- 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 front/src/components/library/Artists.vue diff --git a/front/src/components/favorites/List.vue b/front/src/components/favorites/List.vue index 053f62bc6..08e8747fe 100644 --- a/front/src/components/favorites/List.vue +++ b/front/src/components/favorites/List.vue @@ -15,6 +15,7 @@
+
+
+
+
+
+

Browsing artists

+
+
+ +
+
+
+ +
+
+
+ + + + + + diff --git a/front/src/components/library/Home.vue b/front/src/components/library/Home.vue index 651f7cb63..624da62c5 100644 --- a/front/src/components/library/Home.vue +++ b/front/src/components/library/Home.vue @@ -8,7 +8,7 @@

Latest artists

-
+
From 4be052c0e7cabe25b6c1bf8db54cf42c5acfc5a5 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 12 Dec 2017 23:54:57 +0100 Subject: [PATCH 8/8] version bump --- api/funkwhale_api/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/funkwhale_api/__init__.py b/api/funkwhale_api/__init__.py index 0168bc25a..d961973d3 100644 --- a/api/funkwhale_api/__init__.py +++ b/api/funkwhale_api/__init__.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- -__version__ = '0.2.2' +__version__ = '0.2.3' __version_info__ = tuple([int(num) if num.isdigit() else num for num in __version__.replace('-', '.', 1).split('.')])