mirror of
https://github.com/owntone/owntone-server.git
synced 2025-07-14 11:21:55 -04:00
[web-src] Add index button list to genre album/tracks page and generate index-id-tag in ListItemXXX
This commit is contained in:
parent
1d21b7cc1d
commit
1d5d6f4858
@ -1,5 +1,5 @@
|
|||||||
<template functional>
|
<template functional>
|
||||||
<div class="media" :id="'index_' + props.anchor">
|
<div class="media" :id="'index_' + props.album.name.charAt(0).toUpperCase()">
|
||||||
<div class="media-content fd-has-action is-clipped" @click="listeners.click">
|
<div class="media-content fd-has-action is-clipped" @click="listeners.click">
|
||||||
<h1 class="title is-6">{{ props.album.name }}</h1>
|
<h1 class="title is-6">{{ props.album.name }}</h1>
|
||||||
<h2 class="subtitle is-7 has-text-grey"><b>{{ props.album.artist }}</b></h2>
|
<h2 class="subtitle is-7 has-text-grey"><b>{{ props.album.artist }}</b></h2>
|
||||||
@ -13,7 +13,7 @@
|
|||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'ListItemAlbum',
|
name: 'ListItemAlbum',
|
||||||
props: ['album', 'media_kind', 'anchor']
|
props: ['album', 'media_kind']
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template functional>
|
<template functional>
|
||||||
<div class="media" :id="'index_' + props.anchor">
|
<div class="media" :id="'index_' + props.artist.name.charAt(0).toUpperCase()">
|
||||||
<div class="media-content fd-has-action is-clipped" @click="listeners.click">
|
<div class="media-content fd-has-action is-clipped" @click="listeners.click">
|
||||||
<h1 class="title is-6">{{ props.artist.name }}</h1>
|
<h1 class="title is-6">{{ props.artist.name }}</h1>
|
||||||
</div>
|
</div>
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'ListItemArtist',
|
name: 'ListItemArtist',
|
||||||
props: ['artist', 'anchor']
|
props: ['artist']
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template functional>
|
<template functional>
|
||||||
<div class="media" :id="'index_' + props.anchor">
|
<div class="media" :id="'index_' + props.genre.name.charAt(0).toUpperCase()">
|
||||||
<div class="media-content fd-has-action is-clipped" @click="listeners.click">
|
<div class="media-content fd-has-action is-clipped" @click="listeners.click">
|
||||||
<h1 class="title is-6">{{ props.genre.name }}</h1>
|
<h1 class="title is-6">{{ props.genre.name }}</h1>
|
||||||
</div>
|
</div>
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'ListItemGenre',
|
name: 'ListItemGenre',
|
||||||
props: [ 'genre', 'anchor' ]
|
props: [ 'genre' ]
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template functional>
|
<template functional>
|
||||||
<div class="media">
|
<div class="media" :id="'index_' + props.track.title.charAt(0).toUpperCase()">
|
||||||
<div class="media-content fd-has-action is-clipped" @click="listeners.click">
|
<div class="media-content fd-has-action is-clipped" @click="listeners.click">
|
||||||
<h1 class="title is-6">{{ props.track.title }}</h1>
|
<h1 class="title is-6">{{ props.track.title }}</h1>
|
||||||
<h2 class="subtitle is-7 has-text-grey"><b>{{ props.track.artist }}</b></h2>
|
<h2 class="subtitle is-7 has-text-grey"><b>{{ props.track.artist }}</b></h2>
|
||||||
|
@ -19,10 +19,9 @@
|
|||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
<template slot="content">
|
<template slot="content">
|
||||||
<list-item-album v-for="(album, index) in albums.items"
|
<list-item-album v-for="album in albums.items"
|
||||||
:key="album.id"
|
:key="album.id"
|
||||||
:album="album"
|
:album="album"
|
||||||
:anchor="anchor(album, index)"
|
|
||||||
@click="open_album(album)"
|
@click="open_album(album)"
|
||||||
v-if="!hide_singles || album.track_count > 2">
|
v-if="!hide_singles || album.track_count > 2">
|
||||||
<template slot="actions">
|
<template slot="actions">
|
||||||
@ -86,10 +85,6 @@ export default {
|
|||||||
this.$store.commit(types.HIDE_SINGLES, !this.hide_singles)
|
this.$store.commit(types.HIDE_SINGLES, !this.hide_singles)
|
||||||
},
|
},
|
||||||
|
|
||||||
anchor: function (album, index) {
|
|
||||||
return album.name_sort.charAt(0).toUpperCase()
|
|
||||||
},
|
|
||||||
|
|
||||||
open_album: function (album) {
|
open_album: function (album) {
|
||||||
this.$router.push({ path: '/music/albums/' + album.id })
|
this.$router.push({ path: '/music/albums/' + album.id })
|
||||||
},
|
},
|
||||||
|
@ -19,10 +19,9 @@
|
|||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
<template slot="content">
|
<template slot="content">
|
||||||
<list-item-artist v-for="(artist, index) in artists.items"
|
<list-item-artist v-for="artist in artists.items"
|
||||||
:key="artist.id"
|
:key="artist.id"
|
||||||
:artist="artist"
|
:artist="artist"
|
||||||
:anchor="anchor(artist, index)"
|
|
||||||
@click="open_artist(artist)"
|
@click="open_artist(artist)"
|
||||||
v-if="!hide_singles || artist.track_count > (artist.album_count * 2)">
|
v-if="!hide_singles || artist.track_count > (artist.album_count * 2)">
|
||||||
<template slot="actions">
|
<template slot="actions">
|
||||||
@ -88,10 +87,6 @@ export default {
|
|||||||
this.$store.commit(types.HIDE_SINGLES, !this.hide_singles)
|
this.$store.commit(types.HIDE_SINGLES, !this.hide_singles)
|
||||||
},
|
},
|
||||||
|
|
||||||
anchor: function (artist, index) {
|
|
||||||
return artist.name_sort.charAt(0).toUpperCase()
|
|
||||||
},
|
|
||||||
|
|
||||||
open_artist: function (artist) {
|
open_artist: function (artist) {
|
||||||
this.$router.push({ path: '/music/artists/' + artist.id })
|
this.$router.push({ path: '/music/artists/' + artist.id })
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
|
<template slot="options">
|
||||||
|
<index-button-list :index="index_list"></index-button-list>
|
||||||
|
</template>
|
||||||
<template slot="heading-left">
|
<template slot="heading-left">
|
||||||
<p class="title is-4">{{ name }}</p>
|
<p class="title is-4">{{ name }}</p>
|
||||||
</template>
|
</template>
|
||||||
@ -10,8 +13,8 @@
|
|||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
<template slot="content">
|
<template slot="content">
|
||||||
<p class="heading has-text-centered-mobile">{{ genreAlbums.total }} albums | <a class="has-text-link" @click="open_tracks">tracks</a></p>
|
<p class="heading has-text-centered-mobile">{{ genre_albums.total }} albums | <a class="has-text-link" @click="open_tracks">tracks</a></p>
|
||||||
<list-item-albums v-for="album in genreAlbums.items" :key="album.id" :album="album" :links="links" @click="open_album(album)">
|
<list-item-albums v-for="album in genre_albums.items" :key="album.id" :album="album" @click="open_album(album)">
|
||||||
<template slot="actions">
|
<template slot="actions">
|
||||||
<a @click="open_dialog(album)">
|
<a @click="open_dialog(album)">
|
||||||
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
|
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
|
||||||
@ -28,6 +31,7 @@
|
|||||||
import { LoadDataBeforeEnterMixin } from './mixin'
|
import { LoadDataBeforeEnterMixin } from './mixin'
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading'
|
import ContentWithHeading from '@/templates/ContentWithHeading'
|
||||||
import TabsMusic from '@/components/TabsMusic'
|
import TabsMusic from '@/components/TabsMusic'
|
||||||
|
import IndexButtonList from '@/components/IndexButtonList'
|
||||||
import ListItemAlbums from '@/components/ListItemAlbum'
|
import ListItemAlbums from '@/components/ListItemAlbum'
|
||||||
import ModalDialogAlbum from '@/components/ModalDialogAlbum'
|
import ModalDialogAlbum from '@/components/ModalDialogAlbum'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
@ -39,40 +43,32 @@ const genreData = {
|
|||||||
|
|
||||||
set: function (vm, response) {
|
set: function (vm, response) {
|
||||||
vm.name = vm.$route.params.genre
|
vm.name = vm.$route.params.genre
|
||||||
vm.genreAlbums = response.data.albums
|
vm.genre_albums = response.data.albums
|
||||||
var li = 0
|
|
||||||
var v = null
|
|
||||||
var i
|
|
||||||
for (i = 0; i < vm.genreAlbums.items.length; i++) {
|
|
||||||
var n = vm.genreAlbums.items[i].name_sort.charAt(0).toUpperCase()
|
|
||||||
if (n !== v) {
|
|
||||||
var obj = {}
|
|
||||||
obj.n = n
|
|
||||||
obj.a = 'idx_nav_' + li
|
|
||||||
vm.links.push(obj)
|
|
||||||
li++
|
|
||||||
v = n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PageGenre',
|
name: 'PageGenre',
|
||||||
mixins: [ LoadDataBeforeEnterMixin(genreData) ],
|
mixins: [ LoadDataBeforeEnterMixin(genreData) ],
|
||||||
components: { ContentWithHeading, TabsMusic, ListItemAlbums, ModalDialogAlbum },
|
components: { ContentWithHeading, TabsMusic, IndexButtonList, ListItemAlbums, ModalDialogAlbum },
|
||||||
|
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
name: '',
|
name: '',
|
||||||
genreAlbums: {},
|
genre_albums: { items: [] },
|
||||||
links: [],
|
|
||||||
|
|
||||||
show_details_modal: false,
|
show_details_modal: false,
|
||||||
selected_album: {}
|
selected_album: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
index_list () {
|
||||||
|
return [...new Set(this.genre_albums.items
|
||||||
|
.map(album => album.name.charAt(0).toUpperCase()))]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
open_tracks: function () {
|
open_tracks: function () {
|
||||||
this.show_details_modal = false
|
this.show_details_modal = false
|
||||||
@ -80,7 +76,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
play: function () {
|
play: function () {
|
||||||
webapi.player_play_uri(this.genreAlbums.items.map(a => a.uri).join(','), true)
|
webapi.player_play_uri(this.genre_albums.items.map(a => a.uri).join(','), true)
|
||||||
},
|
},
|
||||||
|
|
||||||
open_album: function (album) {
|
open_album: function (album) {
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
|
<template slot="options">
|
||||||
|
<index-button-list :index="index_list"></index-button-list>
|
||||||
|
</template>
|
||||||
<template slot="heading-left">
|
<template slot="heading-left">
|
||||||
<p class="title is-4">{{ genre }}</p>
|
<p class="title is-4">{{ genre }}</p>
|
||||||
</template>
|
</template>
|
||||||
@ -27,6 +30,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { LoadDataBeforeEnterMixin } from './mixin'
|
import { LoadDataBeforeEnterMixin } from './mixin'
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading'
|
import ContentWithHeading from '@/templates/ContentWithHeading'
|
||||||
|
import IndexButtonList from '@/components/IndexButtonList'
|
||||||
import ListItemTrack from '@/components/ListItemTrack'
|
import ListItemTrack from '@/components/ListItemTrack'
|
||||||
import ModalDialogTrack from '@/components/ModalDialogTrack'
|
import ModalDialogTrack from '@/components/ModalDialogTrack'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
@ -45,11 +49,11 @@ const tracksData = {
|
|||||||
export default {
|
export default {
|
||||||
name: 'PageGenreTracks',
|
name: 'PageGenreTracks',
|
||||||
mixins: [ LoadDataBeforeEnterMixin(tracksData) ],
|
mixins: [ LoadDataBeforeEnterMixin(tracksData) ],
|
||||||
components: { ContentWithHeading, ListItemTrack, ModalDialogTrack },
|
components: { ContentWithHeading, ListItemTrack, IndexButtonList, ModalDialogTrack },
|
||||||
|
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
tracks: {},
|
tracks: { items: [] },
|
||||||
genre: '',
|
genre: '',
|
||||||
|
|
||||||
show_details_modal: false,
|
show_details_modal: false,
|
||||||
@ -57,6 +61,13 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
index_list () {
|
||||||
|
return [...new Set(this.tracks.items
|
||||||
|
.map(track => track.title.charAt(0).toUpperCase()))]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
open_genre: function () {
|
open_genre: function () {
|
||||||
this.show_details_modal = false
|
this.show_details_modal = false
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<p class="heading">{{ genres.total }} genres</p>
|
<p class="heading">{{ genres.total }} genres</p>
|
||||||
</template>
|
</template>
|
||||||
<template slot="content">
|
<template slot="content">
|
||||||
<list-item-genre v-for="(genre, index) in genres.items" :key="genre.name" :genre="genre" :anchor="anchor(genre, index)" @click="open_genre(genre)">
|
<list-item-genre v-for="genre in genres.items" :key="genre.name" :genre="genre" @click="open_genre(genre)">
|
||||||
<template slot="actions">
|
<template slot="actions">
|
||||||
<a @click="open_dialog(genre)">
|
<a @click="open_dialog(genre)">
|
||||||
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
|
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
|
||||||
@ -65,10 +65,6 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
anchor: function (genre, index) {
|
|
||||||
return genre.name.charAt(0).toUpperCase()
|
|
||||||
},
|
|
||||||
|
|
||||||
open_genre: function (genre) {
|
open_genre: function (genre) {
|
||||||
this.$router.push({ name: 'Genre', params: { genre: genre.name } })
|
this.$router.push({ name: 'Genre', params: { genre: genre.name } })
|
||||||
},
|
},
|
||||||
|
@ -112,13 +112,13 @@ export const router = new VueRouter({
|
|||||||
path: '/music/genres/:genre',
|
path: '/music/genres/:genre',
|
||||||
name: 'Genre',
|
name: 'Genre',
|
||||||
component: PageGenre,
|
component: PageGenre,
|
||||||
meta: { show_progress: true }
|
meta: { show_progress: true, has_index: true }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/music/genres/:genre/tracks',
|
path: '/music/genres/:genre/tracks',
|
||||||
name: 'GenreTracks',
|
name: 'GenreTracks',
|
||||||
component: PageGenreTracks,
|
component: PageGenreTracks,
|
||||||
meta: { show_progress: true }
|
meta: { show_progress: true, has_index: true }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/podcasts',
|
path: '/podcasts',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user