kopia lustrzana https://dev.funkwhale.audio/funkwhale/funkwhale
Fix #719: Added a "load more" button on artist pages to load more tracks/albums
rodzic
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"
|
: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
|
||||||
|
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue