mirror of
https://github.com/owntone/owntone-server.git
synced 2025-11-10 05:59:45 -05:00
[web-src] Index based navigation for artists, albums, genres
This commit is contained in:
@@ -3,6 +3,9 @@
|
||||
<tabs-music></tabs-music>
|
||||
|
||||
<content-with-heading>
|
||||
<template slot="options">
|
||||
<index-button-list :index="index_list"></index-button-list>
|
||||
</template>
|
||||
<template slot="heading-left">
|
||||
<p class="title is-4">Albums</p>
|
||||
<p class="heading">{{ albums.total }} albums</p>
|
||||
@@ -16,7 +19,7 @@
|
||||
</a>
|
||||
</template>
|
||||
<template slot="content">
|
||||
<list-item-album v-for="album in albums.items" :key="album.id" :album="album" v-if="!hide_singles || album.track_count > 2"></list-item-album>
|
||||
<list-item-album v-for="(album, index) in albums.items" :key="album.id" :album="album" :anchor="anchor(album, index)" v-if="!hide_singles || album.track_count > 2"></list-item-album>
|
||||
</template>
|
||||
</content-with-heading>
|
||||
</div>
|
||||
@@ -26,6 +29,7 @@
|
||||
import { LoadDataBeforeEnterMixin } from './mixin'
|
||||
import ContentWithHeading from '@/templates/ContentWithHeading'
|
||||
import TabsMusic from '@/components/TabsMusic'
|
||||
import IndexButtonList from '@/components/IndexButtonList'
|
||||
import ListItemAlbum from '@/components/ListItemAlbum'
|
||||
import webapi from '@/webapi'
|
||||
import * as types from '@/store/mutation_types'
|
||||
@@ -43,23 +47,33 @@ const albumsData = {
|
||||
export default {
|
||||
name: 'PageAlbums',
|
||||
mixins: [ LoadDataBeforeEnterMixin(albumsData) ],
|
||||
components: { ContentWithHeading, TabsMusic, ListItemAlbum },
|
||||
components: { ContentWithHeading, TabsMusic, IndexButtonList, ListItemAlbum },
|
||||
|
||||
data () {
|
||||
return {
|
||||
albums: {}
|
||||
albums: { items: [] }
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
hide_singles () {
|
||||
return this.$store.state.hide_singles
|
||||
},
|
||||
|
||||
index_list () {
|
||||
return [...new Set(this.albums.items
|
||||
.filter(album => !this.$store.state.hide_singles || album.track_count > 2)
|
||||
.map(album => album.name_sort.charAt(0).toUpperCase()))]
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
update_hide_singles: function (e) {
|
||||
this.$store.commit(types.HIDE_SINGLES, !this.hide_singles)
|
||||
},
|
||||
|
||||
anchor: function (album, index) {
|
||||
return album.name_sort.charAt(0).toUpperCase()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
<tabs-music></tabs-music>
|
||||
|
||||
<content-with-heading>
|
||||
<template slot="options">
|
||||
<index-button-list :index="index_list"></index-button-list>
|
||||
</template>
|
||||
<template slot="heading-left">
|
||||
<p class="title is-4">Artists</p>
|
||||
<p class="heading">{{ artists.total }} artists</p>
|
||||
@@ -16,7 +19,7 @@
|
||||
</a>
|
||||
</template>
|
||||
<template slot="content">
|
||||
<list-item-artist v-for="artist in artists.items" :key="artist.id" :artist="artist" v-if="!hide_singles || artist.track_count > (artist.album_count * 2)"></list-item-artist>
|
||||
<list-item-artist v-for="(artist, index) in artists.items" :key="artist.id" :artist="artist" :anchor="anchor(artist, index)" v-if="!hide_singles || artist.track_count > (artist.album_count * 2)"></list-item-artist>
|
||||
</template>
|
||||
</content-with-heading>
|
||||
</div>
|
||||
@@ -26,6 +29,7 @@
|
||||
import { LoadDataBeforeEnterMixin } from './mixin'
|
||||
import ContentWithHeading from '@/templates/ContentWithHeading'
|
||||
import TabsMusic from '@/components/TabsMusic'
|
||||
import IndexButtonList from '@/components/IndexButtonList'
|
||||
import ListItemArtist from '@/components/ListItemArtist'
|
||||
import webapi from '@/webapi'
|
||||
import * as types from '@/store/mutation_types'
|
||||
@@ -43,23 +47,33 @@ const artistsData = {
|
||||
export default {
|
||||
name: 'PageArtists',
|
||||
mixins: [ LoadDataBeforeEnterMixin(artistsData) ],
|
||||
components: { ContentWithHeading, TabsMusic, ListItemArtist },
|
||||
components: { ContentWithHeading, TabsMusic, IndexButtonList, ListItemArtist },
|
||||
|
||||
data () {
|
||||
return {
|
||||
artists: {}
|
||||
artists: { items: [] }
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
hide_singles () {
|
||||
return this.$store.state.hide_singles
|
||||
},
|
||||
|
||||
index_list () {
|
||||
return [...new Set(this.artists.items
|
||||
.filter(artist => !this.$store.state.hide_singles || artist.track_count > (artist.album_count * 2))
|
||||
.map(artist => artist.name_sort.charAt(0).toUpperCase()))]
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
update_hide_singles: function (e) {
|
||||
this.$store.commit(types.HIDE_SINGLES, !this.hide_singles)
|
||||
},
|
||||
|
||||
anchor: function (artist, index) {
|
||||
return artist.name_sort.charAt(0).toUpperCase()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,15 @@
|
||||
<tabs-music></tabs-music>
|
||||
|
||||
<content-with-heading>
|
||||
<template slot="options">
|
||||
<index-button-list :index="index_list"></index-button-list>
|
||||
</template>
|
||||
<template slot="heading-left">
|
||||
<p class="title is-4">Genres</p>
|
||||
<p class="heading">{{ genres.total }} genres</p>
|
||||
</template>
|
||||
<template slot="content">
|
||||
<list-item-genre v-for="genre in genres.items" :key="genre.name" :genre="genre"></list-item-genre>
|
||||
<list-item-genre v-for="(genre, index) in genres.items" :key="genre.name" :genre="genre" :anchor="anchor(genre, index)"></list-item-genre>
|
||||
</template>
|
||||
</content-with-heading>
|
||||
</div>
|
||||
@@ -18,6 +21,7 @@
|
||||
import { LoadDataBeforeEnterMixin } from './mixin'
|
||||
import ContentWithHeading from '@/templates/ContentWithHeading'
|
||||
import TabsMusic from '@/components/TabsMusic'
|
||||
import IndexButtonList from '@/components/IndexButtonList'
|
||||
import ListItemGenre from '@/components/ListItemGenre'
|
||||
import webapi from '@/webapi'
|
||||
|
||||
@@ -34,15 +38,25 @@ const genresData = {
|
||||
export default {
|
||||
name: 'PageGenres',
|
||||
mixins: [ LoadDataBeforeEnterMixin(genresData) ],
|
||||
components: { ContentWithHeading, TabsMusic, ListItemGenre },
|
||||
components: { ContentWithHeading, TabsMusic, IndexButtonList, ListItemGenre },
|
||||
|
||||
data () {
|
||||
return {
|
||||
genres: {}
|
||||
genres: { items: [] }
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
index_list () {
|
||||
return [...new Set(this.genres.items
|
||||
.map(genre => genre.name.charAt(0).toUpperCase()))]
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
anchor: function (genre, index) {
|
||||
return genre.name.charAt(0).toUpperCase()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- Search field + recent searches -->
|
||||
<section class="section fd-tabs-section">
|
||||
<section class="section fd-remove-padding-bottom">
|
||||
<div class="container">
|
||||
<div class="columns is-centered">
|
||||
<div class="column is-four-fifths">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- Search field + recent searches -->
|
||||
<section class="section fd-tabs-section">
|
||||
<section class="section fd-remove-padding-bottom">
|
||||
<div class="container">
|
||||
<div class="columns is-centered">
|
||||
<div class="column is-four-fifths">
|
||||
|
||||
Reference in New Issue
Block a user