mirror of
https://github.com/owntone/owntone-server.git
synced 2025-11-07 04:42:58 -05:00
[web-src] Artists/albums list sort + filter
This commit is contained in:
50
web-src/src/components/DropdownMenu.vue
Normal file
50
web-src/src/components/DropdownMenu.vue
Normal file
@@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<div class="dropdown" :class="{ 'is-active': is_active }" v-click-outside="onClickOutside">
|
||||
<div class="dropdown-trigger">
|
||||
<button class="button" aria-haspopup="true" aria-controls="dropdown-menu" @click="is_active = !is_active">
|
||||
<span>{{ value }}</span>
|
||||
<span class="icon is-small">
|
||||
<i class="mdi mdi-chevron-down" aria-hidden="true"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="dropdown-menu" id="dropdown-menu" role="menu">
|
||||
<div class="dropdown-content">
|
||||
<a class="dropdown-item"
|
||||
v-for="option in options" :key="option"
|
||||
:class="{'is-active': value === option}"
|
||||
@click="select(option)">
|
||||
{{ option }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'DropdownMenu',
|
||||
|
||||
props: ['value', 'options'],
|
||||
|
||||
data () {
|
||||
return {
|
||||
is_active: false
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onClickOutside (event) {
|
||||
this.is_active = false
|
||||
},
|
||||
|
||||
select (option) {
|
||||
this.is_active = false
|
||||
this.$emit('input', option)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -1,25 +1,52 @@
|
||||
<template>
|
||||
<div>
|
||||
<list-item-album v-for="album in albums"
|
||||
:key="album.id"
|
||||
:album="album"
|
||||
@click="open_album(album)">
|
||||
<template slot="artwork" v-if="is_visible_artwork">
|
||||
<p class="image is-64x64 fd-has-shadow fd-has-action">
|
||||
<cover-artwork
|
||||
:artwork_url="album.artwork_url"
|
||||
:artist="album.artist"
|
||||
:album="album.name"
|
||||
:maxwidth="64"
|
||||
:maxheight="64" />
|
||||
</p>
|
||||
</template>
|
||||
<template slot="actions">
|
||||
<a @click="open_dialog(album)">
|
||||
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
|
||||
</a>
|
||||
</template>
|
||||
</list-item-album>
|
||||
<div v-if="is_grouped">
|
||||
<div v-for="idx in albums.indexList" :key="idx" class="mb-6">
|
||||
<span class="tag is-info is-light is-small has-text-weight-bold" :id="'index_' + idx">{{ idx }}</span>
|
||||
<list-item-album v-for="album in albums.grouped[idx]"
|
||||
:key="album.id"
|
||||
:album="album"
|
||||
@click="open_album(album)">
|
||||
<template slot="artwork" v-if="is_visible_artwork">
|
||||
<p class="image is-64x64 fd-has-shadow fd-has-action">
|
||||
<cover-artwork
|
||||
:artwork_url="album.artwork_url"
|
||||
:artist="album.artist"
|
||||
:album="album.name"
|
||||
:maxwidth="64"
|
||||
:maxheight="64" />
|
||||
</p>
|
||||
</template>
|
||||
<template slot="actions">
|
||||
<a @click="open_dialog(album)">
|
||||
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
|
||||
</a>
|
||||
</template>
|
||||
</list-item-album>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<list-item-album v-for="album in albums_list"
|
||||
:key="album.id"
|
||||
:album="album"
|
||||
@click="open_album(album)">
|
||||
<template slot="artwork" v-if="is_visible_artwork">
|
||||
<p class="image is-64x64 fd-has-shadow fd-has-action">
|
||||
<cover-artwork
|
||||
:artwork_url="album.artwork_url"
|
||||
:artist="album.artist"
|
||||
:album="album.name"
|
||||
:maxwidth="64"
|
||||
:maxheight="64" />
|
||||
</p>
|
||||
</template>
|
||||
<template slot="actions">
|
||||
<a @click="open_dialog(album)">
|
||||
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
|
||||
</a>
|
||||
</template>
|
||||
</list-item-album>
|
||||
</div>
|
||||
<modal-dialog-album
|
||||
:show="show_details_modal"
|
||||
:album="selected_album"
|
||||
@@ -46,6 +73,7 @@ import ModalDialogAlbum from '@/components/ModalDialogAlbum'
|
||||
import ModalDialog from '@/components/ModalDialog'
|
||||
import CoverArtwork from '@/components/CoverArtwork'
|
||||
import webapi from '@/webapi'
|
||||
import Albums from '@/lib/Albums'
|
||||
|
||||
export default {
|
||||
name: 'ListAlbums',
|
||||
@@ -70,6 +98,17 @@ export default {
|
||||
|
||||
media_kind_resolved: function () {
|
||||
return this.media_kind ? this.media_kind : this.selected_album.media_kind
|
||||
},
|
||||
|
||||
albums_list: function () {
|
||||
if (Array.isArray(this.albums)) {
|
||||
return this.albums
|
||||
}
|
||||
return this.albums.sortedAndFiltered
|
||||
},
|
||||
|
||||
is_grouped: function () {
|
||||
return (this.albums instanceof Albums && this.albums.options.group)
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -1,15 +1,32 @@
|
||||
<template>
|
||||
<div>
|
||||
<list-item-artist v-for="artist in artists"
|
||||
:key="artist.id"
|
||||
:artist="artist"
|
||||
@click="open_artist(artist)">
|
||||
<template slot="actions">
|
||||
<a @click="open_dialog(artist)">
|
||||
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
|
||||
</a>
|
||||
</template>
|
||||
</list-item-artist>
|
||||
<div v-if="is_grouped">
|
||||
<div v-for="idx in artists.indexList" :key="idx" class="mb-6">
|
||||
<span class="tag is-info is-light is-small has-text-weight-bold" :id="'index_' + idx">{{ idx }}</span>
|
||||
<list-item-artist v-for="artist in artists.grouped[idx]"
|
||||
:key="artist.id"
|
||||
:artist="artist"
|
||||
@click="open_artist(artist)">
|
||||
<template slot="actions">
|
||||
<a @click="open_dialog(artist)">
|
||||
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
|
||||
</a>
|
||||
</template>
|
||||
</list-item-artist>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<list-item-artist v-for="artist in artists_list"
|
||||
:key="artist.id"
|
||||
:artist="artist"
|
||||
@click="open_artist(artist)">
|
||||
<template slot="actions">
|
||||
<a @click="open_dialog(artist)">
|
||||
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
|
||||
</a>
|
||||
</template>
|
||||
</list-item-artist>
|
||||
</div>
|
||||
<modal-dialog-artist :show="show_details_modal" :artist="selected_artist" :media_kind="media_kind" @close="show_details_modal = false" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -17,6 +34,7 @@
|
||||
<script>
|
||||
import ListItemArtist from '@/components/ListItemArtist'
|
||||
import ModalDialogArtist from '@/components/ModalDialogArtist'
|
||||
import Artists from '@/lib/Artists'
|
||||
|
||||
export default {
|
||||
name: 'ListArtists',
|
||||
@@ -34,6 +52,17 @@ export default {
|
||||
computed: {
|
||||
media_kind_resolved: function () {
|
||||
return this.media_kind ? this.media_kind : this.selected_artist.media_kind
|
||||
},
|
||||
|
||||
artists_list: function () {
|
||||
if (Array.isArray(this.artists)) {
|
||||
return this.artists
|
||||
}
|
||||
return this.artists.sortedAndFiltered
|
||||
},
|
||||
|
||||
is_grouped: function () {
|
||||
return (this.artists instanceof Artists && this.artists.options.group)
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template functional>
|
||||
<div class="media" :id="'index_' + props.artist.name_sort.charAt(0).toUpperCase()">
|
||||
<div class="media">
|
||||
<div class="media-content fd-has-action is-clipped" @click="listeners.click">
|
||||
<h1 class="title is-6">{{ props.artist.name }}</h1>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user