From 6ad8b212cff39072c8890796b31dbb19c306a41c Mon Sep 17 00:00:00 2001 From: Eliot Berriot <contact@eliotberriot.com> Date: Sun, 17 Dec 2017 20:07:18 +0100 Subject: [PATCH] Fixed #50: ordering for favorites --- api/funkwhale_api/music/views.py | 7 +- front/src/components/favorites/List.vue | 76 ++++++++++++++++++++-- front/src/components/library/Artists.vue | 31 +++------ front/src/components/mixins/Ordering.vue | 26 ++++++++ front/src/components/mixins/Pagination.vue | 8 +++ front/src/router/index.js | 6 +- 6 files changed, 124 insertions(+), 30 deletions(-) create mode 100644 front/src/components/mixins/Ordering.vue create mode 100644 front/src/components/mixins/Pagination.vue diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py index 5bfefc29..532942e2 100644 --- a/api/funkwhale_api/music/views.py +++ b/api/funkwhale_api/music/views.py @@ -95,7 +95,12 @@ class TrackViewSet(TagViewSetMixin, SearchMixin, viewsets.ReadOnlyModelViewSet): serializer_class = serializers.TrackSerializerNested permission_classes = [ConditionalAuthentication] search_fields = ['title', 'artist__name'] - ordering_fields = ('creation_date',) + ordering_fields = ( + 'creation_date', + 'title', + 'album__title', + 'artist__name', + ) def get_queryset(self): queryset = super().get_queryset() diff --git a/front/src/components/favorites/List.vue b/front/src/components/favorites/List.vue index 63c3ba79..91efd729 100644 --- a/front/src/components/favorites/List.vue +++ b/front/src/components/favorites/List.vue @@ -9,9 +9,36 @@ {{ favoriteTracks.count }} favorites </h2> <radio-button type="favorites"></radio-button> - </div> <div class="ui vertical stripe segment"> + <div :class="['ui', {'loading': isLoading}, 'form']"> + <div class="fields"> + <div class="field"> + <label>Ordering</label> + <select class="ui dropdown" v-model="ordering"> + <option v-for="option in orderingOptions" :value="option[0]"> + {{ option[1] }} + </option> + </select> + </div> + <div class="field"> + <label>Ordering direction</label> + <select class="ui dropdown" v-model="orderingDirection"> + <option value="">Ascending</option> + <option value="-">Descending</option> + </select> + </div> + <div class="field"> + <label>Results per page</label> + <select class="ui dropdown" v-model="paginateBy"> + <option :value="parseInt(12)">12</option> + <option :value="parseInt(25)">25</option> + <option :value="parseInt(50)">50</option> + </select> + </div> + </div> + </div> + <track-table v-if="results" :tracks="results.results"></track-table> <div class="ui center aligned basic segment"> <pagination @@ -27,6 +54,7 @@ </template> <script> +import $ from 'jquery' import Vue from 'vue' import logger from '@/logging' import config from '@/config' @@ -34,37 +62,60 @@ import favoriteTracks from '@/favorites/tracks' import TrackTable from '@/components/audio/track/Table' import RadioButton from '@/components/radios/Button' import Pagination from '@/components/Pagination' - +import OrderingMixin from '@/components/mixins/Ordering' +import PaginationMixin from '@/components/mixins/Pagination' const FAVORITES_URL = config.API_URL + 'tracks/' export default { + mixins: [OrderingMixin, PaginationMixin], components: { TrackTable, RadioButton, Pagination }, data () { + let defaultOrdering = this.getOrderingFromString(this.defaultOrdering || 'artist__name') return { results: null, isLoading: false, nextLink: null, previousLink: null, - page: 1, - paginateBy: 25, - favoriteTracks + favoriteTracks, + page: parseInt(this.defaultPage), + paginateBy: parseInt(this.defaultPaginateBy || 25), + orderingDirection: defaultOrdering.direction, + ordering: defaultOrdering.field, + orderingOptions: [ + ['title', 'Track name'], + ['album__title', 'Album name'], + ['artist__name', 'Artist name'] + ] } }, created () { this.fetchFavorites(FAVORITES_URL) }, + mounted () { + $('.ui.dropdown').dropdown() + }, methods: { + updateQueryString: function () { + this.$router.replace({ + query: { + page: this.page, + paginateBy: this.paginateBy, + ordering: this.getOrderingAsString() + } + }) + }, fetchFavorites (url) { var self = this this.isLoading = true let params = { favorites: 'true', page: this.page, - page_size: this.paginateBy + page_size: this.paginateBy, + ordering: this.getOrderingAsString() } logger.default.time('Loading user favorites') this.$http.get(url, {params: params}).then((response) => { @@ -86,6 +137,19 @@ export default { }, watch: { page: function () { + this.updateQueryString() + this.fetchFavorites(FAVORITES_URL) + }, + paginateBy: function () { + this.updateQueryString() + this.fetchFavorites(FAVORITES_URL) + }, + orderingDirection: function () { + this.updateQueryString() + this.fetchFavorites(FAVORITES_URL) + }, + ordering: function () { + this.updateQueryString() this.fetchFavorites(FAVORITES_URL) } } diff --git a/front/src/components/library/Artists.vue b/front/src/components/library/Artists.vue index c3e9f1d1..8d0a4f55 100644 --- a/front/src/components/library/Artists.vue +++ b/front/src/components/library/Artists.vue @@ -63,30 +63,31 @@ import $ from 'jquery' import config from '@/config' import backend from '@/audio/backend' import logger from '@/logging' + +import OrderingMixin from '@/components/mixins/Ordering' +import PaginationMixin from '@/components/mixins/Pagination' import ArtistCard from '@/components/audio/artist/Card' import Pagination from '@/components/Pagination' const FETCH_URL = config.API_URL + 'artists/' export default { + mixins: [OrderingMixin, PaginationMixin], props: { - defaultOrdering: {type: String, required: false, default: '-creation_date'}, - defaultQuery: {type: String, required: false, default: ''}, - defaultPage: {required: false, default: 1}, - defaultPaginateBy: {required: false, default: 12} + defaultQuery: {type: String, required: false, default: ''} }, components: { ArtistCard, Pagination }, data () { - let defaultOrdering = this.getOrderingFromString(this.defaultOrdering) + let defaultOrdering = this.getOrderingFromString(this.defaultOrdering || '-creation_date') return { isLoading: true, result: null, page: parseInt(this.defaultPage), query: this.defaultQuery, - paginateBy: parseInt(this.defaultPaginateBy), + paginateBy: parseInt(this.defaultPaginateBy || 12), orderingDirection: defaultOrdering.direction, ordering: defaultOrdering.field, orderingOptions: [ @@ -102,27 +103,13 @@ export default { $('.ui.dropdown').dropdown() }, methods: { - getOrderingFromString (s) { - let parts = s.split('-') - if (parts.length > 1) { - return { - direction: '-', - field: parts.slice(1).join('-') - } - } else { - return { - direction: '', - field: s - } - } - }, updateQueryString: function () { this.$router.replace({ query: { query: this.query, page: this.page, paginateBy: this.paginateBy, - ordering: [this.orderingDirection, this.ordering].join('') + ordering: this.getOrderingAsString() } }) }, @@ -134,7 +121,7 @@ export default { page: this.page, page_size: this.paginateBy, name__icontains: this.query, - ordering: [this.orderingDirection, this.ordering].join('') + ordering: this.getOrderingAsString() } logger.default.debug('Fetching artists') this.$http.get(url, {params: params}).then((response) => { diff --git a/front/src/components/mixins/Ordering.vue b/front/src/components/mixins/Ordering.vue new file mode 100644 index 00000000..494dddce --- /dev/null +++ b/front/src/components/mixins/Ordering.vue @@ -0,0 +1,26 @@ +<script> +export default { + props: { + defaultOrdering: {type: String, required: false} + }, + methods: { + getOrderingFromString (s) { + let parts = s.split('-') + if (parts.length > 1) { + return { + direction: '-', + field: parts.slice(1).join('-') + } + } else { + return { + direction: '', + field: s + } + } + }, + getOrderingAsString () { + return [this.orderingDirection, this.ordering].join('') + } + } +} +</script> diff --git a/front/src/components/mixins/Pagination.vue b/front/src/components/mixins/Pagination.vue new file mode 100644 index 00000000..532faaaa --- /dev/null +++ b/front/src/components/mixins/Pagination.vue @@ -0,0 +1,8 @@ +<script> +export default { + props: { + defaultPage: {required: false, default: 1}, + defaultPaginateBy: {required: false} + } +} +</script> diff --git a/front/src/router/index.js b/front/src/router/index.js index f6653e73..7db5da6b 100644 --- a/front/src/router/index.js +++ b/front/src/router/index.js @@ -47,7 +47,11 @@ export default new Router({ }, { path: '/favorites', - component: Favorites + component: Favorites, + props: (route) => ({ + defaultOrdering: route.query.ordering, + defaultPage: route.query.page + }) }, { path: '/library', -- GitLab