diff --git a/api/funkwhale_api/music/fake_data.py b/api/funkwhale_api/music/fake_data.py new file mode 100644 index 0000000000000000000000000000000000000000..ef5eaf4be811f580d82378c17ab838694df52ea7 --- /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 d4ec048101984419b5b1459943be5998f43f261a..ea680b3bd5d4da58e63f5ee4c861fec7972117f4 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 7cec50319a142649dedfb00645418b195c9bf339..cc686926752aad7c6627b83c515eb078b866e9e9 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 0000000000000000000000000000000000000000..3ac7c59af5817413c13a97e569065ca48cb95b91 --- /dev/null +++ b/front/src/components/Pagination.vue @@ -0,0 +1,52 @@ +<template> + <div class="ui pagination borderless menu"> + <a + @click="selectPage(1)" + :class="[{'disabled': current === 1}, 'item']"><i class="angle double left icon"></i></a> + <a + @click="selectPage(current - 1)" + :class="[{'disabled': current - 1 < 1}, 'item']"><i class="angle left icon"></i></a> + <a + v-for="page in pages" + @click="selectPage(page)" + :class="[{'active': page === current}, 'item']"> + {{ page }} + </a> + <a + @click="selectPage(current + 1)" + :class="[{'disabled': current + 1 > maxPage}, 'item']"><i class="angle right icon"></i></a> + <a + @click="selectPage(maxPage)" + :class="[{'disabled': current === maxPage}, 'item']"><i class="angle double right icon"></i></a> + </div> +</template> + +<script> +import _ from 'lodash' + +export default { + props: { + current: {type: Number, default: 1}, + paginateBy: {type: Number, default: 25}, + total: {type: Number} + }, + computed: { + pages: function () { + return _.range(1, this.maxPage + 1) + }, + maxPage: function () { + return Math.ceil(this.total / this.paginateBy) + } + }, + methods: { + selectPage: function (page) { + if (this.current !== page) { + this.$emit('page-changed', page) + } + } + } +} +</script> + +<style scoped> +</style> diff --git a/front/src/components/favorites/List.vue b/front/src/components/favorites/List.vue index f7972a07c9243863e025af3f2103e0af6e47c891..053f62bc653c7cfa2fa223f6857fa0df2bd12ae8 100644 --- a/front/src/components/favorites/List.vue +++ b/front/src/components/favorites/List.vue @@ -12,11 +12,14 @@ </div> <div class="ui vertical stripe segment"> - <button class="ui left floated labeled icon button" @click="fetchFavorites(previousLink)" :disabled="!previousLink"><i class="left arrow icon"></i> Previous</button> - <button class="ui right floated right labeled icon button" @click="fetchFavorites(nextLink)" :disabled="!nextLink">Next <i class="right arrow icon"></i></button> - <div class="ui hidden clearing divider"></div> - <div class="ui hidden clearing divider"></div> <track-table v-if="results" :tracks="results.results"></track-table> + <div class="ui center aligned basic segment"> + <pagination + @page-changed="selectPage" + :current="page" + :total="results.count" + ></pagination> + </div> </div> </div> </template> @@ -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) } } }