diff --git a/front/src/components/audio/AlbumEntries.vue b/front/src/components/audio/AlbumEntries.vue index a7658d5a0c0520a56f1e2b0cce96633dc41a648d..c1725895154e1f148eb6cd6ccde010e1a3b4cf10 100644 --- a/front/src/components/audio/AlbumEntries.vue +++ b/front/src/components/audio/AlbumEntries.vue @@ -16,6 +16,9 @@ </template> <human-duration v-if="track.uploads[0] && track.uploads[0].duration" :duration="track.uploads[0].duration"></human-duration> </div> + <div class="actions"> + <play-button class="play-button basic icon" :dropdown-only="true" :is-playable="track.is_playable" :dropdown-icon-classes="['ellipsis', 'vertical', 'large really discrete']" :track="track"></play-button> + </div> </div> </div> </template> diff --git a/front/src/components/audio/ChannelEntries.vue b/front/src/components/audio/ChannelEntries.vue index 23f70cbed61817983494974fb782dedbe00b905e..6d14408647d7c1483c8f9284c7d3820726948331 100644 --- a/front/src/components/audio/ChannelEntries.vue +++ b/front/src/components/audio/ChannelEntries.vue @@ -6,11 +6,16 @@ <div class="ui loader"></div> </div> <channel-entry-card v-for="entry in objects" :entry="entry" :key="entry.id" /> - <template v-if="nextPage"> + <template v-if="count > limit"> <div class="ui hidden divider"></div> - <button v-if="nextPage" @click="fetchData(nextPage)" :class="['ui', 'basic', 'button']"> - <translate translate-context="*/*/Button,Label">Show more</translate> - </button> + <div class = "ui center aligned basic segment"> + <pagination + @page-changed="updatePage" + :current="page" + :paginate-by="limit" + :total="count" + ></pagination> + </div> </template> <template v-if="!isLoading && objects.length === 0"> <empty-state @refresh="fetchData('tracks/')" :refresh="true"> @@ -26,6 +31,8 @@ import _ from '@/lodash' import axios from 'axios' import ChannelEntryCard from '@/components/audio/ChannelEntryCard' +import Pagination from "@/components/Pagination" +import PaginationMixin from "@/components/mixins/Pagination" export default { props: { @@ -33,7 +40,8 @@ export default { limit: {type: Number, default: 10}, }, components: { - ChannelEntryCard + ChannelEntryCard, + Pagination }, data () { return { @@ -41,7 +49,8 @@ export default { count: 0, isLoading: false, errors: null, - nextPage: null + nextPage: null, + page: 1 } }, created () { @@ -56,11 +65,12 @@ export default { let self = this let params = _.clone(this.filters) params.page_size = this.limit + params.page = this.page params.include_channels = true axios.get(url, {params: params}).then((response) => { self.nextPage = response.data.next self.isLoading = false - self.objects = self.objects.concat(response.data.results) + self.objects = response.data.results self.count = response.data.count self.$emit('fetched', response.data) }, error => { @@ -68,6 +78,14 @@ export default { self.errors = error.backendErrors }) }, + updatePage: function(page) { + this.page = page + } + }, + watch: { + page() { + this.fetchData('tracks/') + } } } </script> diff --git a/front/src/components/audio/ChannelEntryCard.vue b/front/src/components/audio/ChannelEntryCard.vue index 430f205f4b2a707e37df87cd365d437b23b6f913..5efc812e02595b019b092792afe45cde11e82810 100644 --- a/front/src/components/audio/ChannelEntryCard.vue +++ b/front/src/components/audio/ChannelEntryCard.vue @@ -36,7 +36,9 @@ <track-favorite-icon class="tiny" :track="entry"></track-favorite-icon> </template> <human-duration v-if="duration" :duration="duration"></human-duration> - + </div> + <div class="controls"> + <play-button class="play-button basic icon" :dropdown-only="true" :is-playable="entry.is_playable" :dropdown-icon-classes="['ellipsis', 'vertical', 'large really discrete']" :track="entry"></play-button> </div> </div> </template> diff --git a/front/src/components/library/AlbumBase.vue b/front/src/components/library/AlbumBase.vue index 7b572e145616ba0435b96db10a9dc3b22c1f7b68..b6bc2bb47fb13be8bd2a483bfe6e1f8042dd99fe 100644 --- a/front/src/components/library/AlbumBase.vue +++ b/front/src/components/library/AlbumBase.vue @@ -117,7 +117,7 @@ </template> </div> <div class="nine wide column"> - <router-view v-if="object" :is-serie="isSerie" :artist="artist" :discs="discs" @libraries-loaded="libraries = $event" :object="object" object-type="album" :key="$route.fullPath"></router-view> + <router-view v-if="object" :paginate-by="paginateBy" :page="page" :total-tracks="totalTracks" :is-serie="isSerie" :artist="artist" :discs="discs" @libraries-loaded="libraries = $event" :object="object" object-type="album" :key="$route.fullPath" @page-changed="page = $event"></router-view> </div> </div> </section> @@ -134,7 +134,6 @@ import TagsList from "@/components/tags/List" import ArtistLabel from '@/components/audio/ArtistLabel' import AlbumDropdown from './AlbumDropdown' - function groupByDisc(acc, track) { var dn = track.disc_number - 1 if (dn < 0) dn = 0 @@ -152,7 +151,7 @@ export default { PlayButton, TagsList, ArtistLabel, - AlbumDropdown, + AlbumDropdown }, data() { return { @@ -161,6 +160,8 @@ export default { artist: null, discs: [], libraries: [], + page: 1, + paginateBy: 50, } }, async created() { @@ -169,7 +170,7 @@ export default { methods: { async fetchData() { this.isLoading = true - let tracksResponse = axios.get(`tracks/`, {params: {ordering: 'disc_number,position', album: this.id, page_size: 100}}) + let tracksResponse = axios.get(`tracks/`, {params: {ordering: 'disc_number,position', album: this.id, page_size: this.paginateBy, page:this.page, include_channels: 'true'}}) let albumResponse = await axios.get(`albums/${this.id}/`, {params: {refresh: 'true'}}) let artistResponse = await axios.get(`artists/${albumResponse.data.artist.id}/`) this.artist = artistResponse.data @@ -181,7 +182,6 @@ export default { this.object.tracks = tracksResponse.data.results this.discs = this.object.tracks.reduce(groupByDisc, []) this.isLoading = false - }, remove () { let self = this @@ -232,6 +232,9 @@ export default { watch: { id() { this.fetchData() + }, + page() { + this.fetchData() } } } diff --git a/front/src/components/library/AlbumDetail.vue b/front/src/components/library/AlbumDetail.vue index dff0d1948cc3b72790fc79c19658180bd750379f..559a4a330f8feb666375fa54452ecd5f1b0a5f9a 100644 --- a/front/src/components/library/AlbumDetail.vue +++ b/front/src/components/library/AlbumDetail.vue @@ -20,6 +20,15 @@ <template v-else> <album-entries :tracks="object.tracks"></album-entries> </template> + <div class="ui center aligned basic segment"> + <pagination + v-if="!isSerie && object.tracks && totalTracks > paginateBy" + @page-changed="updatePage" + :current="page" + :paginate-by="paginateBy" + :total="totalTracks" + ></pagination> + </div> <template v-if="!artist.channel && !isSerie"> <h2> <translate translate-context="Content/*/Title/Noun">User libraries</translate> @@ -41,14 +50,17 @@ import LibraryWidget from "@/components/federation/LibraryWidget" import TrackTable from "@/components/audio/track/Table" import ChannelEntries from '@/components/audio/ChannelEntries' import AlbumEntries from '@/components/audio/AlbumEntries' +import Pagination from "@/components/Pagination" +import PaginationMixin from "@/components/mixins/Pagination" export default { - props: ["object", "libraries", "discs", "isSerie", "artist"], + props: ["object", "libraries", "discs", "isSerie", "artist", "page", "paginateBy", "totalTracks"], components: { LibraryWidget, AlbumEntries, ChannelEntries, - TrackTable + TrackTable, + Pagination }, data() { return { @@ -56,5 +68,10 @@ export default { id: this.object.id, } }, + methods: { + updatePage: function(page) { + this.$emit('page-changed', page) + } + }, } </script> diff --git a/front/src/style/components/_pagination.scss b/front/src/style/components/_pagination.scss index 822c29d63f44a250091f071527e8aab5b89ade19..d00e924a9de28ef3a555787a2b139fdbe68cf62b 100644 --- a/front/src/style/components/_pagination.scss +++ b/front/src/style/components/_pagination.scss @@ -9,4 +9,9 @@ + span { margin-left: 1em; } + color: var(--text-color); + background-color: var(--light-background-color); + .active.item { + color: var(--discrete-background-color); + } } diff --git a/front/src/views/channels/DetailBase.vue b/front/src/views/channels/DetailBase.vue index c5b796195765c9d6e1b99799ec709e8260606fd7..627c5010b8699fb9aa889c866c78def03c5b0ec9 100644 --- a/front/src/views/channels/DetailBase.vue +++ b/front/src/views/channels/DetailBase.vue @@ -209,7 +209,7 @@ <translate translate-context="Content/Channels/Link">Overview</translate> </router-link> <router-link class="item" :exact="true" :to="{name: 'channels.detail.episodes', params: {id: id}}"> - <translate key="1" v-if="isPodcast" translate-context="Content/Channels/*">Episodes</translate> + <translate key="1" v-if="isPodcast" translate-context="Content/Channels/*">All Episodes</translate> <translate key="2" v-else translate-context="*/*/*">Tracks</translate> </router-link> </div> diff --git a/front/src/views/channels/DetailEpisodes.vue b/front/src/views/channels/DetailEpisodes.vue index 7535d7edf640b260ddf3f95ebda8cdd8a406ef61..385e58a672f7b73d946f63393b1fd4d3b6fbd925 100644 --- a/front/src/views/channels/DetailEpisodes.vue +++ b/front/src/views/channels/DetailEpisodes.vue @@ -1,6 +1,6 @@ <template> <section> - <channel-entries :limit="25" :filters="{channel: object.uuid, ordering: '-creation_date'}"> + <channel-entries :limit="25" :filters="{channel: object.uuid, ordering: 'creation_date'}"> </channel-entries> </section> </template> diff --git a/front/src/views/channels/DetailOverview.vue b/front/src/views/channels/DetailOverview.vue index 7d12127530e5a4425e794612031a9a11d922b253..f25645a3a598d5ed8263d38f2bbc4c389a8d810b 100644 --- a/front/src/views/channels/DetailOverview.vue +++ b/front/src/views/channels/DetailOverview.vue @@ -49,7 +49,7 @@ :can-update="false"></rendered-description> <div class="ui hidden divider"></div> </div> - <channel-entries :key="String(episodesKey) + 'entries'" :filters="{channel: object.uuid, ordering: '-creation_date'}"> + <channel-entries :key="String(episodesKey) + 'entries'" :limit='25' :filters="{channel: object.uuid, ordering: '-creation_date', page_size: '25'}"> <h2 class="ui header"> <translate key="1" v-if="isPodcast" translate-context="Content/Channel/Paragraph">Latest episodes</translate> <translate key="2" v-else translate-context="Content/Channel/Paragraph">Latest tracks</translate>