kopia lustrzana https://dev.funkwhale.audio/funkwhale/funkwhale
				
				
				
			Merge branch '798-load-additional-albums-tracks' into 'develop'
Fix #719: Added a "load more" button on artist pages to load more tracks/albums Closes #719 See merge request funkwhale/funkwhale!734merge-requests/757/head
						commit
						31d990499d
					
				| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue