Fix #719: Added a "load more" button on artist pages to load more tracks/albums

merge-requests/757/head
Eliot Berriot 2019-04-23 12:51:31 +02:00
rodzic 51d94a13fa
commit 6da85ce0e9
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: DD6965E2476E5C27
4 zmienionych plików z 97 dodań i 31 usunięć

Wyświetl plik

@ -0,0 +1 @@
Added a "load more" button on artist pages to load more tracks/albums (#719)

Wyświetl plik

@ -19,14 +19,18 @@
:track="track" :track="track"
:artist="artist" :artist="artist"
:key="index + '-' + track.id" :key="index + '-' + track.id"
v-for="(track, index) in tracks"></track-row> v-for="(track, index) in allTracks"></track-row>
</tbody> </tbody>
</table> </table>
<button :class="['ui', {loading: isLoadingMore}, 'button']" v-if="loadMoreUrl" @click="loadMore(loadMoreUrl)">
<translate translate-context="Content/*/Button.Label">Load more</translate>
</button>
</div> </div>
</template> </template>
<script> <script>
import backend from '@/audio/backend' import backend from '@/audio/backend'
import axios from 'axios'
import TrackRow from '@/components/audio/track/Row' import TrackRow from '@/components/audio/track/Row'
import Modal from '@/components/semantic/Modal' import Modal from '@/components/semantic/Modal'
@ -35,6 +39,7 @@ export default {
props: { props: {
tracks: {type: Array, required: true}, tracks: {type: Array, required: true},
playable: {type: Boolean, required: false, default: false}, playable: {type: Boolean, required: false, default: false},
nextUrl: {type: String, required: false, default: null},
artist: {type: Object, required: false}, artist: {type: Object, required: false},
displayPosition: {type: Boolean, default: false} displayPosition: {type: Boolean, default: false}
}, },
@ -44,7 +49,29 @@ export default {
}, },
data () { data () {
return { return {
backend: backend backend: backend,
loadMoreUrl: this.nextUrl,
isLoadingMore: false,
additionalTracks: []
}
},
computed: {
allTracks () {
return this.tracks.concat(this.additionalTracks)
}
},
methods: {
loadMore (url) {
let self = this
self.isLoadingMore = true
axios.get(url).then((response) => {
self.additionalTracks = self.additionalTracks.concat(response.data.results)
self.loadMoreUrl = response.data.next
self.isLoadingMore = false
}, (error) => {
self.isLoadingMore = false
})
} }
} }
} }

Wyświetl plik

@ -3,7 +3,7 @@
<div v-if="isLoading" class="ui vertical segment"> <div v-if="isLoading" class="ui vertical segment">
<div :class="['ui', 'centered', 'active', 'inline', 'loader']"></div> <div :class="['ui', 'centered', 'active', 'inline', 'loader']"></div>
</div> </div>
<template v-if="object"> <template v-if="object && !isLoading">
<section :class="['ui', 'head', {'with-background': cover}, 'vertical', 'center', 'aligned', 'stripe', 'segment']" :style="headerStyle" v-title="object.name"> <section :class="['ui', 'head', {'with-background': cover}, 'vertical', 'center', 'aligned', 'stripe', 'segment']" :style="headerStyle" v-title="object.name">
<div class="segment-content"> <div class="segment-content">
<h2 class="ui center aligned icon header"> <h2 class="ui center aligned icon header">
@ -98,7 +98,15 @@
</div> </div>
</div> </div>
</section> </section>
<router-view v-if="object" :tracks="tracks" :albums="albums" :is-loading-albums="isLoadingAlbums" @libraries-loaded="libraries = $event" :object="object" object-type="artist" :key="$route.fullPath"></router-view> <router-view
:tracks="tracks"
:next-tracks-url="nextTracksUrl"
:next-albums-url="nextAlbumsUrl"
:albums="albums"
:is-loading-albums="isLoadingAlbums"
@libraries-loaded="libraries = $event"
:object="object" object-type="artist"
:key="$route.fullPath"></router-view>
</template> </template>
</main> </main>
</template> </template>
@ -132,38 +140,45 @@ export default {
libraries: [], libraries: [],
showEmbedModal: false, showEmbedModal: false,
tracks: [], tracks: [],
nextAlbumsUrl: null,
nextTracksUrl: null,
totalAlbums: null,
totalTracks: null,
} }
}, },
created() { async created() {
this.fetchData() await this.fetchData()
}, },
methods: { methods: {
fetchData() { async fetchData() {
var self = this var self = this
this.isLoading = true this.isLoading = true
logger.default.debug('Fetching artist "' + this.id + '"') logger.default.debug('Fetching artist "' + this.id + '"')
axios.get("tracks/", { params: { artist: this.id, hidden: '' } }).then(response => { let trackPromise = axios.get("tracks/", { params: { artist: this.id, hidden: '' } }).then(response => {
self.tracks = response.data.results self.tracks = response.data.results
self.nextTracksUrl = response.data.next
self.totalTracks = response.data.count self.totalTracks = response.data.count
}) })
axios.get("artists/" + this.id + "/").then(response => { let albumPromise = axios.get("albums/", {
self.object = response.data params: { artist: self.id, ordering: "-release_date", hidden: '' }
self.isLoading = false }).then(response => {
self.isLoadingAlbums = true self.nextAlbumsUrl = response.data.next
axios self.totalAlbums = response.data.count
.get("albums/", { let parsed = JSON.parse(JSON.stringify(response.data.results))
params: { artist: self.id, ordering: "-release_date", hidden: '' } self.albums = parsed.map(album => {
}) return backend.Album.clean(album)
.then(response => { })
self.totalAlbums = response.data.count
let parsed = JSON.parse(JSON.stringify(response.data.results))
self.albums = parsed.map(album => {
return backend.Album.clean(album)
})
self.isLoadingAlbums = false
})
}) })
let artistPromise = axios.get("artists/" + this.id + "/").then(response => {
self.object = response.data
})
await trackPromise
await albumPromise
await artistPromise
self.isLoadingAlbums = false
self.isLoading = false
} }
}, },
computed: { computed: {

Wyświetl plik

@ -21,15 +21,19 @@
<h2> <h2>
<translate translate-context="Content/Artist/Title">Albums by this artist</translate> <translate translate-context="Content/Artist/Title">Albums by this artist</translate>
</h2> </h2>
<div class="ui cards" > <div class="ui cards">
<album-card :mode="'rich'" :album="album" :key="album.id" v-for="album in albums"></album-card> <album-card :mode="'rich'" :album="album" :key="album.id" v-for="album in allAlbums"></album-card>
</div> </div>
<div class="ui hidden divider"></div>
<button :class="['ui', {loading: isLoadingMoreAlbums}, 'button']" v-if="nextAlbumsUrl && loadMoreAlbumsUrl" @click="loadMoreAlbums(loadMoreAlbumsUrl)">
<translate translate-context="Content/*/Button.Label">Load more</translate>
</button>
</section> </section>
<section v-if="tracks.length > 0" class="ui vertical stripe segment"> <section v-if="tracks.length > 0" class="ui vertical stripe segment">
<h2> <h2>
<translate translate-context="Content/Artist/Title">Tracks by this artist</translate> <translate translate-context="Content/Artist/Title">Tracks by this artist</translate>
</h2> </h2>
<track-table :display-position="true" :tracks="tracks"></track-table> <track-table :display-position="true" :tracks="tracks" :next-url="nextTracksUrl"></track-table>
</section> </section>
<section class="ui vertical stripe segment"> <section class="ui vertical stripe segment">
<h2> <h2>
@ -52,23 +56,42 @@ import TrackTable from "@/components/audio/track/Table"
import LibraryWidget from "@/components/federation/LibraryWidget" import LibraryWidget from "@/components/federation/LibraryWidget"
export default { export default {
props: ["object", "tracks", "albums", "isLoadingAlbums"], props: ["object", "tracks", "albums", "isLoadingAlbums", "nextTracksUrl", "nextAlbumsUrl"],
components: { components: {
AlbumCard, AlbumCard,
TrackTable, TrackTable,
LibraryWidget, LibraryWidget,
}, },
data () {
return {
loadMoreAlbumsUrl: this.nextAlbumsUrl,
additionalAlbums: [],
isLoadingMoreAlbums: false
}
},
computed: { computed: {
contentFilter () { contentFilter () {
let self = this let self = this
return this.$store.getters['moderation/artistFilters']().filter((e) => { return this.$store.getters['moderation/artistFilters']().filter((e) => {
return e.target.id === this.object.id return e.target.id === this.object.id
})[0] })[0]
},
allAlbums () {
return this.albums.concat(this.additionalAlbums)
} }
}, },
watch: { methods: {
id() { loadMoreAlbums (url) {
this.fetchData() let self = this
self.isLoadingMoreAlbums = true
axios.get(url).then((response) => {
self.additionalAlbums = self.additionalAlbums.concat(response.data.results)
self.loadMoreAlbumsUrl = response.data.next
self.isLoadingMoreAlbums = false
}, (error) => {
self.isLoadingMoreAlbums = false
})
} }
} }
} }