Fix #719: Added a "load more" button on artist pages to load more tracks/albums
This commit is contained in:
parent
51d94a13fa
commit
6da85ce0e9
|
@ -0,0 +1 @@
|
|||
Added a "load more" button on artist pages to load more tracks/albums (#719)
|
|
@ -19,14 +19,18 @@
|
|||
:track="track"
|
||||
:artist="artist"
|
||||
:key="index + '-' + track.id"
|
||||
v-for="(track, index) in tracks"></track-row>
|
||||
v-for="(track, index) in allTracks"></track-row>
|
||||
</tbody>
|
||||
</table>
|
||||
<button :class="['ui', {loading: isLoadingMore}, 'button']" v-if="loadMoreUrl" @click="loadMore(loadMoreUrl)">
|
||||
<translate translate-context="Content/*/Button.Label">Load more…</translate>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import backend from '@/audio/backend'
|
||||
import axios from 'axios'
|
||||
|
||||
import TrackRow from '@/components/audio/track/Row'
|
||||
import Modal from '@/components/semantic/Modal'
|
||||
|
@ -35,6 +39,7 @@ export default {
|
|||
props: {
|
||||
tracks: {type: Array, required: true},
|
||||
playable: {type: Boolean, required: false, default: false},
|
||||
nextUrl: {type: String, required: false, default: null},
|
||||
artist: {type: Object, required: false},
|
||||
displayPosition: {type: Boolean, default: false}
|
||||
},
|
||||
|
@ -44,7 +49,29 @@ export default {
|
|||
},
|
||||
data () {
|
||||
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
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div v-if="isLoading" class="ui vertical segment">
|
||||
<div :class="['ui', 'centered', 'active', 'inline', 'loader']"></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">
|
||||
<div class="segment-content">
|
||||
<h2 class="ui center aligned icon header">
|
||||
|
@ -98,7 +98,15 @@
|
|||
</div>
|
||||
</div>
|
||||
</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>
|
||||
</main>
|
||||
</template>
|
||||
|
@ -132,38 +140,45 @@ export default {
|
|||
libraries: [],
|
||||
showEmbedModal: false,
|
||||
tracks: [],
|
||||
nextAlbumsUrl: null,
|
||||
nextTracksUrl: null,
|
||||
totalAlbums: null,
|
||||
totalTracks: null,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
async created() {
|
||||
await this.fetchData()
|
||||
},
|
||||
methods: {
|
||||
fetchData() {
|
||||
async fetchData() {
|
||||
var self = this
|
||||
this.isLoading = true
|
||||
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.nextTracksUrl = response.data.next
|
||||
self.totalTracks = response.data.count
|
||||
})
|
||||
axios.get("artists/" + this.id + "/").then(response => {
|
||||
self.object = response.data
|
||||
self.isLoading = false
|
||||
self.isLoadingAlbums = true
|
||||
axios
|
||||
.get("albums/", {
|
||||
params: { artist: self.id, ordering: "-release_date", hidden: '' }
|
||||
})
|
||||
.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)
|
||||
})
|
||||
let albumPromise = axios.get("albums/", {
|
||||
params: { artist: self.id, ordering: "-release_date", hidden: '' }
|
||||
}).then(response => {
|
||||
self.nextAlbumsUrl = response.data.next
|
||||
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: {
|
||||
|
|
|
@ -21,15 +21,19 @@
|
|||
<h2>
|
||||
<translate translate-context="Content/Artist/Title">Albums by this artist</translate>
|
||||
</h2>
|
||||
<div class="ui cards" >
|
||||
<album-card :mode="'rich'" :album="album" :key="album.id" v-for="album in albums"></album-card>
|
||||
<div class="ui cards">
|
||||
<album-card :mode="'rich'" :album="album" :key="album.id" v-for="album in allAlbums"></album-card>
|
||||
</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 v-if="tracks.length > 0" class="ui vertical stripe segment">
|
||||
<h2>
|
||||
<translate translate-context="Content/Artist/Title">Tracks by this artist</translate>
|
||||
</h2>
|
||||
<track-table :display-position="true" :tracks="tracks"></track-table>
|
||||
<track-table :display-position="true" :tracks="tracks" :next-url="nextTracksUrl"></track-table>
|
||||
</section>
|
||||
<section class="ui vertical stripe segment">
|
||||
<h2>
|
||||
|
@ -52,23 +56,42 @@ import TrackTable from "@/components/audio/track/Table"
|
|||
import LibraryWidget from "@/components/federation/LibraryWidget"
|
||||
|
||||
export default {
|
||||
props: ["object", "tracks", "albums", "isLoadingAlbums"],
|
||||
props: ["object", "tracks", "albums", "isLoadingAlbums", "nextTracksUrl", "nextAlbumsUrl"],
|
||||
components: {
|
||||
AlbumCard,
|
||||
TrackTable,
|
||||
LibraryWidget,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
loadMoreAlbumsUrl: this.nextAlbumsUrl,
|
||||
additionalAlbums: [],
|
||||
isLoadingMoreAlbums: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
contentFilter () {
|
||||
let self = this
|
||||
return this.$store.getters['moderation/artistFilters']().filter((e) => {
|
||||
return e.target.id === this.object.id
|
||||
})[0]
|
||||
},
|
||||
allAlbums () {
|
||||
return this.albums.concat(this.additionalAlbums)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
id() {
|
||||
this.fetchData()
|
||||
methods: {
|
||||
loadMoreAlbums (url) {
|
||||
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
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue