[web-src] Refactor details modal dialogs into separate components

This will allow to open a dialog outside of the ListItem component. Also
reduces the size of the generated DOM tree by only including one dialog
per page (per object type) and not for each list item.
This commit is contained in:
chme 2018-12-15 09:56:09 +01:00
parent 0cc4699128
commit 5e85e0b024
31 changed files with 997 additions and 506 deletions

View File

@ -5,56 +5,15 @@
<h2 class="subtitle is-7 has-text-grey"><b>{{ album.artist }}</b></h2>
</div>
<div class="media-right">
<a @click="show_details_modal = true">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
<modal-dialog :show="show_details_modal" @close="show_details_modal = false">
<template slot="modal-content">
<div class="card">
<div class="card-content">
<p class="title is-4">
<a class="has-text-link" @click="open_album">{{ album.name }}</a>
</p>
<div class="content is-small">
<p v-if="album.artist && media_kind !== 'audiobook'">
<span class="heading">Album artist</span>
<a class="title is-6 has-text-link" @click="open_artist">{{ album.artist }}</a>
</p>
<p v-if="album.artist && media_kind === 'audiobook'">
<span class="heading">Album artist</span>
<span class="title is-6">{{ album.artist }}</span>
</p>
<p>
<span class="heading">Tracks</span>
<span class="title is-6">{{ album.track_count }}</span>
</p>
</div>
</div>
<footer class="card-footer">
<a class="card-footer-item has-text-dark" @click="queue_add">
<span class="icon"><i class="mdi mdi-playlist-plus mdi-18px"></i></span> <span>Add</span>
</a>
<a class="card-footer-item has-text-dark" @click="queue_add_next">
<span class="icon"><i class="mdi mdi-playlist-play mdi-18px"></i></span> <span>Add Next</span>
</a>
<a class="card-footer-item has-text-dark" @click="play">
<span class="icon"><i class="mdi mdi-play mdi-18px"></i></span> <span>Play</span>
</a>
</footer>
</div>
</template>
</modal-dialog>
<slot name="actions"></slot>
</div>
</div>
</template>
<script>
import ModalDialog from '@/components/ModalDialog'
import webapi from '@/webapi'
export default {
name: 'ListItemAlbum',
components: { ModalDialog },
components: {},
props: ['album', 'media_kind', 'anchor'],
@ -65,25 +24,6 @@ export default {
},
methods: {
play: function () {
this.show_details_modal = false
webapi.player_play_uri(this.album.uri, false)
},
queue_add: function () {
this.show_details_modal = false
webapi.queue_add(this.album.uri).then(() =>
this.$store.dispatch('add_notification', { text: 'Album tracks appended to queue', type: 'info', timeout: 2000 })
)
},
queue_add_next: function () {
this.show_details_modal = false
webapi.queue_add_next(this.album.uri).then(() =>
this.$store.dispatch('add_notification', { text: 'Album tracks appended to queue', type: 'info', timeout: 2000 })
)
},
open_album: function () {
this.show_details_modal = false
if (this.media_kind === 'podcast') {
@ -93,11 +33,6 @@ export default {
} else {
this.$router.push({ path: '/music/albums/' + this.album.id })
}
},
open_artist: function () {
this.show_details_modal = false
this.$router.push({ path: '/music/artists/' + this.album.artist_id })
}
}
}

View File

@ -4,83 +4,20 @@
<h1 class="title is-6">{{ artist.name }}</h1>
</div>
<div class="media-right">
<a @click="show_details_modal = true">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
<modal-dialog :show="show_details_modal" @close="show_details_modal = false">
<template slot="modal-content">
<div class="card">
<div class="card-content">
<p class="title is-4">
<a class="has-text-link" @click="open_artist">{{ artist.name }}</a>
</p>
<div class="content is-small">
<p>
<span class="heading">Albums</span>
<span class="title is-6">{{ artist.album_count }}</span>
</p>
<p>
<span class="heading">Tracks</span>
<span class="title is-6">{{ artist.track_count }}</span>
</p>
</div>
</div>
<footer class="card-footer">
<a class="card-footer-item has-text-dark" @click="queue_add">
<span class="icon"><i class="mdi mdi-playlist-plus mdi-18px"></i></span> <span>Add</span>
</a>
<a class="card-footer-item has-text-dark" @click="queue_add_next">
<span class="icon"><i class="mdi mdi-playlist-play mdi-18px"></i></span> <span>Add Next</span>
</a>
<a class="card-footer-item has-text-dark" @click="play">
<span class="icon"><i class="mdi mdi-play mdi-18px"></i></span> <span>Play</span>
</a>
</footer>
</div>
</template>
</modal-dialog>
<slot name="actions"></slot>
</div>
</div>
</template>
<script>
import ModalDialog from '@/components/ModalDialog'
import webapi from '@/webapi'
export default {
name: 'PartArtist',
components: { ModalDialog },
name: 'ListItemArtist',
components: {},
props: ['artist', 'anchor'],
data () {
return {
show_details_modal: false
}
},
methods: {
play: function () {
this.show_details_modal = false
webapi.player_play_uri(this.artist.uri, false)
},
queue_add: function () {
this.show_details_modal = false
webapi.queue_add(this.artist.uri).then(() =>
this.$store.dispatch('add_notification', { text: 'Artist tracks appended to queue', type: 'info', timeout: 2000 })
)
},
queue_add_next: function () {
this.show_details_modal = false
webapi.queue_add_next(this.artist.uri).then(() =>
this.$store.dispatch('add_notification', { text: 'Album tracks appended to queue', type: 'info', timeout: 2000 })
)
},
open_artist: function () {
this.show_details_modal = false
this.$router.push({ path: '/music/artists/' + this.artist.id })
}
}

View File

@ -4,89 +4,19 @@
<h1 class="title is-6">{{ genre.name }}</h1>
</div>
<div class="media-right">
<a @click="show_details_modal = true">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
<modal-dialog :show="show_details_modal" @close="show_details_modal = false">
<template slot="modal-content">
<div class="card">
<div class="card-content">
<p class="title is-4">
<a class="has-text-link" @click="open_genre">{{ genre.name }}</a>
</p>
<!--
<div class="content is-small">
<p>
<span class="heading">Albums</span>
<span class="title is-6">{{ genre.album_count }}</span>
</p>
<p>
<span class="heading">Tracks</span>
<span class="title is-6">{{ genre.track_count }}</span>
</p>
</div>
-->
</div>
<footer class="card-footer">
<a class="card-footer-item has-text-dark" @click="queue_add">
<span class="icon"><i class="mdi mdi-playlist-plus mdi-12px"></i></span> <span>Add</span>
</a>
<a class="card-footer-item has-text-dark" @click="queue_add_next">
<span class="icon"><i class="mdi mdi-playlist-play mdi-12px"></i></span> <span>Add Next</span>
</a>
<a class="card-footer-item has-text-dark" @click="play">
<span class="icon"><i class="mdi mdi-play mdi-12px"></i></span> <span>Play</span>
</a>
</footer>
</div>
</template>
</modal-dialog>
<slot name="actions"></slot>
</div>
</div>
</template>
<script>
import ModalDialog from '@/components/ModalDialog'
import webapi from '@/webapi'
export default {
name: 'PartGenre',
components: { ModalDialog },
name: 'ListItemGenre',
components: {},
props: [ 'genre', 'anchor' ],
data () {
return {
show_details_modal: false
}
},
methods: {
play: function () {
this.show_details_modal = false
webapi.library_genre(this.genre.name).then(({ data }) =>
webapi.player_play_uri(data.albums.items.map(a => a.uri).join(','), false)
)
},
queue_add: function () {
this.show_details_modal = false
webapi.library_genre(this.genre.name).then(({ data }) =>
webapi.queue_add(data.albums.items.map(a => a.uri).join(',')).then(() =>
this.$store.dispatch('add_notification', { text: 'Genre albums appended to queue', type: 'info', timeout: 1500 })
)
)
},
queue_add_next: function () {
this.show_details_modal = false
webapi.library_genre(this.genre.name).then(({ data }) =>
webapi.queue_add_next(data.albums.items.map(a => a.uri).join(',')).then(() =>
this.$store.dispatch('add_notification', { text: 'Genre albums playing next', type: 'info', timeout: 1500 })
)
)
},
open_genre: function () {
this.show_details_modal = false
this.$router.push({ name: 'Genre', params: { genre: this.genre.name } })

View File

@ -4,77 +4,19 @@
<h1 class="title is-6">{{ playlist.name }}</h1>
</div>
<div class="media-right">
<a @click="show_details_modal = true">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
<modal-dialog :show="show_details_modal" @close="show_details_modal = false">
<template slot="modal-content">
<div class="card">
<div class="card-content">
<p class="title is-4">
<a class="has-text-link" @click="open_playlist">{{ playlist.name }}</a>
</p>
<div class="content is-small">
<p>
<span class="heading">Path</span>
<span class="title is-6">{{ playlist.path }}</span>
</p>
</div>
</div>
<footer class="card-footer">
<a class="card-footer-item has-text-dark" @click="queue_add">
<span class="icon"><i class="mdi mdi-playlist-plus mdi-18px"></i></span> <span>Add</span>
</a>
<a class="card-footer-item has-text-dark" @click="queue_add_next">
<span class="icon"><i class="mdi mdi-playlist-play mdi-18px"></i></span> <span>Add Next</span>
</a>
<a class="card-footer-item has-text-dark" @click="play">
<span class="icon"><i class="mdi mdi-play mdi-18px"></i></span> <span>Play</span>
</a>
</footer>
</div>
</template>
</modal-dialog>
<slot name="actions"></slot>
</div>
</div>
</template>
<script>
import ModalDialog from '@/components/ModalDialog'
import webapi from '@/webapi'
export default {
name: 'PartPlaylist',
components: { ModalDialog },
name: 'ListItemPlaylist',
components: {},
props: ['playlist'],
data () {
return {
show_details_modal: false
}
},
methods: {
play: function () {
this.show_details_modal = false
webapi.player_play_uri(this.playlist.uri, false)
},
queue_add: function () {
this.show_details_modal = false
webapi.queue_add(this.playlist.uri).then(() =>
this.$store.dispatch('add_notification', { text: 'Playlist appended to queue', type: 'info', timeout: 2000 })
)
},
queue_add_next: function () {
this.show_details_modal = false
webapi.queue_add_next(this.playlist.uri).then(() =>
this.$store.dispatch('add_notification', { text: 'Album tracks appended to queue', type: 'info', timeout: 2000 })
)
},
open_playlist: function () {
this.show_details_modal = false
this.$router.push({ path: '/playlists/' + this.playlist.id })

View File

@ -1,6 +1,5 @@
<template>
<div class="media" v-if="is_next || !show_only_next_items">
<!---->
<div class="media-left" v-if="edit_mode">
<span class="icon has-text-grey fd-is-movable handle"><i class="mdi mdi-drag-horizontal mdi-18px"></i></span>
</div>
@ -11,75 +10,17 @@
<h2 class="subtitle is-7" :class="{ 'has-text-primary': item.id === state.item_id, 'has-text-grey-light': !is_next, 'has-text-grey': is_next && item.id !== state.item_id }">{{ item.album }}</h2>
</div>
<div class="media-right">
<a v-on:click="remove" v-if="item.id !== state.item_id && edit_mode">
<span class="icon has-text-grey"><i class="mdi mdi-delete mdi-18px"></i></span>
</a>
<a @click="show_details_modal = true" v-if="!edit_mode">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
<modal-dialog v-if="!edit_mode" :show="show_details_modal" @close="show_details_modal = false">
<template slot="modal-content">
<div class="card">
<div class="card-content">
<p class="title is-4">
{{ item.title }}
</p>
<p class="subtitle">
{{ item.artist }}
</p>
<div class="content is-small">
<p>
<span class="heading">Album</span>
<span class="title is-6">{{ item.album }}</span>
</p>
<p v-if="item.album_artist">
<span class="heading">Album artist</span>
<span class="title is-6">{{ item.album_artist }}</span>
</p>
<p v-if="item.year > 0">
<span class="heading">Year</span>
<span class="title is-6">{{ item.year }}</span>
</p>
<p>
<span class="heading">Genre</span>
<span class="title is-6">{{ item.genre }}</span>
</p>
<p>
<span class="heading">Track / Disc</span>
<span class="title is-6">{{ item.track_number }} / {{ item.disc_number }}</span>
</p>
<p>
<span class="heading">Length</span>
<span class="title is-6">{{ item.length_ms | duration }}</span>
</p>
<p>
<span class="heading">Path</span>
<span class="title is-6">{{ item.path }}</span>
</p>
</div>
</div>
<footer class="card-footer">
<a class="card-footer-item has-text-dark" @click="remove">
<span class="icon"><i class="mdi mdi-delete mdi-18px"></i></span> <span>Remove</span>
</a>
<a class="card-footer-item has-text-dark" @click="play">
<span class="icon"><i class="mdi mdi-play mdi-18px"></i></span> <span>Play</span>
</a>
</footer>
</div>
</template>
</modal-dialog>
<slot name="actions"></slot>
</div>
</div>
</template>
<script>
import ModalDialog from '@/components/ModalDialog'
import webapi from '@/webapi'
export default {
name: 'PartQueueItem',
components: { ModalDialog },
name: 'ListItemQueueItem',
components: {},
props: ['item', 'position', 'current_position', 'show_only_next_items', 'edit_mode'],
@ -100,11 +41,6 @@ export default {
},
methods: {
remove: function () {
this.show_details_modal = false
webapi.queue_remove(this.item.id)
},
play: function () {
this.show_details_modal = false
webapi.player_play({ 'item_id': this.item.id })

View File

@ -6,135 +6,28 @@
<h2 class="subtitle is-7 has-text-grey">{{ track.album }}</h2>
</div>
<div class="media-right">
<a @click="show_details_modal = true">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
<modal-dialog :show="show_details_modal" @close="show_details_modal = false">
<template slot="modal-content">
<div class="card">
<div class="card-content">
<p class="title is-4">
{{ track.title }}
</p>
<p class="subtitle">
{{ track.artist }}
</p>
<div class="content is-small">
<p>
<span class="heading">Album</span>
<a class="title is-6 has-text-link" @click="open_album">{{ track.album }}</a>
</p>
<p v-if="track.album_artist && track.media_kind !== 'audiobook'">
<span class="heading">Album artist</span>
<a class="title is-6 has-text-link" @click="open_artist">{{ track.album_artist }}</a>
</p>
<p v-if="track.date_released">
<span class="heading">Release date</span>
<span class="title is-6">{{ track.date_released | time('L')}}</span>
</p>
<p v-else-if="track.year > 0">
<span class="heading">Year</span>
<span class="title is-6">{{ track.year }}</span>
</p>
<p>
<span class="heading">Genre</span>
<span class="title is-6">{{ track.genre }}</span>
</p>
<p>
<span class="heading">Track / Disc</span>
<span class="title is-6">{{ track.track_number }} / {{ track.disc_number }}</span>
</p>
<p>
<span class="heading">Length</span>
<span class="title is-6">{{ track.length_ms | duration }}</span>
</p>
<p>
<span class="heading">Path</span>
<span class="title is-6">{{ track.path }}</span>
</p>
<p>
<span class="heading">Type</span>
<span class="title is-6">{{ track.media_kind }} - {{ track.data_kind }}</span>
</p>
<p>
<span class="heading">Added at</span>
<span class="title is-6">{{ track.time_added | time('L LT')}}</span>
</p>
</div>
</div>
<footer class="card-footer">
<a class="card-footer-item has-text-dark" @click="queue_add">
<span class="icon"><i class="mdi mdi-playlist-plus mdi-18px"></i></span> <span>Add</span>
</a>
<a class="card-footer-item has-text-dark" @click="queue_add_next">
<span class="icon"><i class="mdi mdi-playlist-play mdi-18px"></i></span> <span>Add Next</span>
</a>
<a class="card-footer-item has-text-dark" @click="play_track">
<span class="icon"><i class="mdi mdi-play mdi-18px"></i></span> <span>Play</span>
</a>
</footer>
</div>
</template>
</modal-dialog>
<slot name="actions"></slot>
</div>
</div>
</template>
<script>
import ModalDialog from '@/components/ModalDialog'
import webapi from '@/webapi'
export default {
name: 'PartTrack',
components: { ModalDialog },
name: 'ListItemTrack',
components: {},
props: ['track', 'position', 'context_uri'],
data () {
return {
show_details_modal: false
}
},
methods: {
play: function () {
this.show_details_modal = false
webapi.player_play_uri(this.context_uri, false, this.position)
},
play_track: function () {
this.show_details_modal = false
webapi.player_play_uri(this.track.uri, false)
},
queue_add: function () {
this.show_details_modal = false
webapi.queue_add(this.track.uri).then(() =>
this.$store.dispatch('add_notification', { text: 'Track appended to queue', type: 'info', timeout: 2000 })
)
},
queue_add_next: function () {
this.show_details_modal = false
webapi.queue_add_next(this.track.uri).then(() =>
this.$store.dispatch('add_notification', { text: 'Album tracks appended to queue', type: 'info', timeout: 2000 })
)
},
open_album: function () {
this.show_details_modal = false
if (this.track.media_kind === 'podcast') {
this.$router.push({ path: '/podcasts/' + this.track.album_id })
} else if (this.track.media_kind === 'audiobook') {
this.$router.push({ path: '/audiobooks/' + this.track.album_id })
} else {
this.$router.push({ path: '/music/albums/' + this.track.album_id })
}
},
open_artist: function () {
this.show_details_modal = false
this.$router.push({ path: '/music/artists/' + this.track.album_artist_id })
}
}
}

View File

@ -0,0 +1,93 @@
<template>
<div>
<transition name="fade">
<div class="modal is-active" v-if="show">
<div class="modal-background" @click="$emit('close')"></div>
<div class="modal-content fd-modal-card">
<div class="card">
<div class="card-content">
<p class="title is-4">
<a class="has-text-link" @click="open_album">{{ album.name }}</a>
</p>
<div class="content is-small">
<p v-if="album.artist && media_kind !== 'audiobook'">
<span class="heading">Album artist</span>
<a class="title is-6 has-text-link" @click="open_artist">{{ album.artist }}</a>
</p>
<p v-if="album.artist && media_kind === 'audiobook'">
<span class="heading">Album artist</span>
<span class="title is-6">{{ album.artist }}</span>
</p>
<p>
<span class="heading">Tracks</span>
<span class="title is-6">{{ album.track_count }}</span>
</p>
</div>
</div>
<footer class="card-footer">
<a class="card-footer-item has-text-dark" @click="queue_add">
<span class="icon"><i class="mdi mdi-playlist-plus mdi-18px"></i></span> <span>Add</span>
</a>
<a class="card-footer-item has-text-dark" @click="queue_add_next">
<span class="icon"><i class="mdi mdi-playlist-play mdi-18px"></i></span> <span>Add Next</span>
</a>
<a class="card-footer-item has-text-dark" @click="play">
<span class="icon"><i class="mdi mdi-play mdi-18px"></i></span> <span>Play</span>
</a>
</footer>
</div>
</div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')"></button>
</div>
</transition>
</div>
</template>
<script>
import webapi from '@/webapi'
export default {
name: 'ModalDialogAlbum',
props: [ 'show', 'album', 'media_kind' ],
methods: {
play: function () {
this.$emit('close')
webapi.player_play_uri(this.album.uri, false)
},
queue_add: function () {
this.$emit('close')
webapi.queue_add(this.album.uri).then(() =>
this.$store.dispatch('add_notification', { text: 'Album tracks appended to queue', type: 'info', timeout: 2000 })
)
},
queue_add_next: function () {
this.$emit('close')
webapi.queue_add_next(this.album.uri).then(() =>
this.$store.dispatch('add_notification', { text: 'Album tracks appended to queue', type: 'info', timeout: 2000 })
)
},
open_album: function () {
this.show_details_modal = false
if (this.media_kind === 'podcast') {
this.$router.push({ path: '/podcasts/' + this.album.id })
} else if (this.media_kind === 'audiobook') {
this.$router.push({ path: '/audiobooks/' + this.album.id })
} else {
this.$router.push({ path: '/music/albums/' + this.album.id })
}
},
open_artist: function () {
this.show_details_modal = false
this.$router.push({ path: '/music/artists/' + this.album.artist_id })
}
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,78 @@
<template>
<div>
<transition name="fade">
<div class="modal is-active" v-if="show">
<div class="modal-background" @click="$emit('close')"></div>
<div class="modal-content fd-modal-card">
<div class="card">
<div class="card-content">
<p class="title is-4">
<a class="has-text-link" @click="open_artist">{{ artist.name }}</a>
</p>
<div class="content is-small">
<p>
<span class="heading">Albums</span>
<span class="title is-6">{{ artist.album_count }}</span>
</p>
<p>
<span class="heading">Tracks</span>
<span class="title is-6">{{ artist.track_count }}</span>
</p>
</div>
</div>
<footer class="card-footer">
<a class="card-footer-item has-text-dark" @click="queue_add">
<span class="icon"><i class="mdi mdi-playlist-plus mdi-18px"></i></span> <span>Add</span>
</a>
<a class="card-footer-item has-text-dark" @click="queue_add_next">
<span class="icon"><i class="mdi mdi-playlist-play mdi-18px"></i></span> <span>Add Next</span>
</a>
<a class="card-footer-item has-text-dark" @click="play">
<span class="icon"><i class="mdi mdi-play mdi-18px"></i></span> <span>Play</span>
</a>
</footer>
</div>
</div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')"></button>
</div>
</transition>
</div>
</template>
<script>
import webapi from '@/webapi'
export default {
name: 'ModalDialogArtist',
props: [ 'show', 'artist' ],
methods: {
play: function () {
this.$emit('close')
webapi.player_play_uri(this.artist.uri, false)
},
queue_add: function () {
this.$emit('close')
webapi.queue_add(this.artist.uri).then(() =>
this.$store.dispatch('add_notification', { text: 'Artist tracks appended to queue', type: 'info', timeout: 2000 })
)
},
queue_add_next: function () {
this.$emit('close')
webapi.queue_add_next(this.artist.uri).then(() =>
this.$store.dispatch('add_notification', { text: 'Album tracks appended to queue', type: 'info', timeout: 2000 })
)
},
open_artist: function () {
this.$emit('close')
this.$router.push({ path: '/music/artists/' + this.artist.id })
}
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,74 @@
<template>
<div>
<transition name="fade">
<div class="modal is-active" v-if="show">
<div class="modal-background" @click="$emit('close')"></div>
<div class="modal-content fd-modal-card">
<div class="card">
<div class="card-content">
<p class="title is-4">
<a class="has-text-link" @click="open_genre">{{ genre.name }}</a>
</p>
</div>
<footer class="card-footer">
<a class="card-footer-item has-text-dark" @click="queue_add">
<span class="icon"><i class="mdi mdi-playlist-plus mdi-12px"></i></span> <span>Add</span>
</a>
<a class="card-footer-item has-text-dark" @click="queue_add_next">
<span class="icon"><i class="mdi mdi-playlist-play mdi-12px"></i></span> <span>Add Next</span>
</a>
<a class="card-footer-item has-text-dark" @click="play">
<span class="icon"><i class="mdi mdi-play mdi-12px"></i></span> <span>Play</span>
</a>
</footer>
</div>
</div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')"></button>
</div>
</transition>
</div>
</template>
<script>
import webapi from '@/webapi'
export default {
name: 'ModalDialogGenre',
props: [ 'show', 'genre' ],
methods: {
play: function () {
this.$emit('close')
webapi.library_genre(this.genre.name).then(({ data }) =>
webapi.player_play_uri(data.albums.items.map(a => a.uri).join(','), false)
)
},
queue_add: function () {
this.$emit('close')
webapi.library_genre(this.genre.name).then(({ data }) =>
webapi.queue_add(data.albums.items.map(a => a.uri).join(',')).then(() =>
this.$store.dispatch('add_notification', { text: 'Genre albums appended to queue', type: 'info', timeout: 1500 })
)
)
},
queue_add_next: function () {
this.$emit('close')
webapi.library_genre(this.genre.name).then(({ data }) =>
webapi.queue_add_next(data.albums.items.map(a => a.uri).join(',')).then(() =>
this.$store.dispatch('add_notification', { text: 'Genre albums playing next', type: 'info', timeout: 1500 })
)
)
},
open_genre: function () {
this.$emit('close')
this.$router.push({ name: 'Genre', params: { genre: this.genre.name } })
}
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,74 @@
<template>
<div>
<transition name="fade">
<div class="modal is-active" v-if="show">
<div class="modal-background" @click="$emit('close')"></div>
<div class="modal-content fd-modal-card">
<div class="card">
<div class="card-content">
<p class="title is-4">
<a class="has-text-link" @click="open_playlist">{{ playlist.name }}</a>
</p>
<div class="content is-small">
<p>
<span class="heading">Path</span>
<span class="title is-6">{{ playlist.path }}</span>
</p>
</div>
</div>
<footer class="card-footer">
<a class="card-footer-item has-text-dark" @click="queue_add">
<span class="icon"><i class="mdi mdi-playlist-plus mdi-18px"></i></span> <span>Add</span>
</a>
<a class="card-footer-item has-text-dark" @click="queue_add_next">
<span class="icon"><i class="mdi mdi-playlist-play mdi-18px"></i></span> <span>Add Next</span>
</a>
<a class="card-footer-item has-text-dark" @click="play">
<span class="icon"><i class="mdi mdi-play mdi-18px"></i></span> <span>Play</span>
</a>
</footer>
</div>
</div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')"></button>
</div>
</transition>
</div>
</template>
<script>
import webapi from '@/webapi'
export default {
name: 'ModalDialogPlaylist',
props: [ 'show', 'playlist' ],
methods: {
play: function () {
this.$emit('close')
webapi.player_play_uri(this.playlist.uri, false)
},
queue_add: function () {
this.$emit('close')
webapi.queue_add(this.playlist.uri).then(() =>
this.$store.dispatch('add_notification', { text: 'Playlist appended to queue', type: 'info', timeout: 2000 })
)
},
queue_add_next: function () {
this.$emit('close')
webapi.queue_add_next(this.playlist.uri).then(() =>
this.$store.dispatch('add_notification', { text: 'Album tracks appended to queue', type: 'info', timeout: 2000 })
)
},
open_playlist: function () {
this.$emit('close')
this.$router.push({ path: '/playlists/' + this.playlist.id })
}
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,84 @@
<template>
<div>
<transition name="fade">
<div class="modal is-active" v-if="show">
<div class="modal-background" @click="$emit('close')"></div>
<div class="modal-content fd-modal-card">
<div class="card">
<div class="card-content">
<p class="title is-4">
{{ item.title }}
</p>
<p class="subtitle">
{{ item.artist }}
</p>
<div class="content is-small">
<p>
<span class="heading">Album</span>
<span class="title is-6">{{ item.album }}</span>
</p>
<p v-if="item.album_artist">
<span class="heading">Album artist</span>
<span class="title is-6">{{ item.album_artist }}</span>
</p>
<p v-if="item.year > 0">
<span class="heading">Year</span>
<span class="title is-6">{{ item.year }}</span>
</p>
<p>
<span class="heading">Genre</span>
<span class="title is-6">{{ item.genre }}</span>
</p>
<p>
<span class="heading">Track / Disc</span>
<span class="title is-6">{{ item.track_number }} / {{ item.disc_number }}</span>
</p>
<p>
<span class="heading">Length</span>
<span class="title is-6">{{ item.length_ms | duration }}</span>
</p>
<p>
<span class="heading">Path</span>
<span class="title is-6">{{ item.path }}</span>
</p>
</div>
</div>
<footer class="card-footer">
<a class="card-footer-item has-text-dark" @click="remove">
<span class="icon"><i class="mdi mdi-delete mdi-18px"></i></span> <span>Remove</span>
</a>
<a class="card-footer-item has-text-dark" @click="play">
<span class="icon"><i class="mdi mdi-play mdi-18px"></i></span> <span>Play</span>
</a>
</footer>
</div>
</div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')"></button>
</div>
</transition>
</div>
</template>
<script>
import webapi from '@/webapi'
export default {
name: 'ModalDialogQueueItem',
props: [ 'show', 'item' ],
methods: {
remove: function () {
this.$emit('close')
webapi.queue_remove(this.item.id)
},
play: function () {
this.$emit('close')
webapi.player_play({ 'item_id': this.item.id })
}
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,130 @@
<template>
<div>
<transition name="fade">
<div class="modal is-active" v-if="show">
<div class="modal-background" @click="$emit('close')"></div>
<div class="modal-content fd-modal-card">
<div class="card">
<div class="card-content">
<p class="title is-4">
{{ track.title }}
</p>
<p class="subtitle">
{{ track.artist }}
</p>
<div class="content is-small">
<p>
<span class="heading">Album</span>
<a class="title is-6 has-text-link" @click="open_album">{{ track.album }}</a>
</p>
<p v-if="track.album_artist && track.media_kind !== 'audiobook'">
<span class="heading">Album artist</span>
<a class="title is-6 has-text-link" @click="open_artist">{{ track.album_artist }}</a>
</p>
<p v-if="track.date_released">
<span class="heading">Release date</span>
<span class="title is-6">{{ track.date_released | time('L')}}</span>
</p>
<p v-else-if="track.year > 0">
<span class="heading">Year</span>
<span class="title is-6">{{ track.year }}</span>
</p>
<p>
<span class="heading">Genre</span>
<span class="title is-6">{{ track.genre }}</span>
</p>
<p>
<span class="heading">Track / Disc</span>
<span class="title is-6">{{ track.track_number }} / {{ track.disc_number }}</span>
</p>
<p>
<span class="heading">Length</span>
<span class="title is-6">{{ track.length_ms | duration }}</span>
</p>
<p>
<span class="heading">Path</span>
<span class="title is-6">{{ track.path }}</span>
</p>
<p>
<span class="heading">Type</span>
<span class="title is-6">{{ track.media_kind }} - {{ track.data_kind }}</span>
</p>
<p>
<span class="heading">Added at</span>
<span class="title is-6">{{ track.time_added | time('L LT')}}</span>
</p>
</div>
</div>
<footer class="card-footer">
<a class="card-footer-item has-text-dark" @click="queue_add">
<span class="icon"><i class="mdi mdi-playlist-plus mdi-18px"></i></span> <span>Add</span>
</a>
<a class="card-footer-item has-text-dark" @click="queue_add_next">
<span class="icon"><i class="mdi mdi-playlist-play mdi-18px"></i></span> <span>Add Next</span>
</a>
<a class="card-footer-item has-text-dark" @click="play_track">
<span class="icon"><i class="mdi mdi-play mdi-18px"></i></span> <span>Play</span>
</a>
</footer>
</div>
</div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')"></button>
</div>
</transition>
</div>
</template>
<script>
import webapi from '@/webapi'
export default {
name: 'ModalDialogTrack',
props: ['show', 'track'],
data () {
return {
}
},
methods: {
play_track: function () {
this.$emit('close')
webapi.player_play_uri(this.track.uri, false)
},
queue_add: function () {
this.$emit('close')
webapi.queue_add(this.track.uri).then(() =>
this.$store.dispatch('add_notification', { text: 'Track appended to queue', type: 'info', timeout: 2000 })
)
},
queue_add_next: function () {
this.$emit('close')
webapi.queue_add_next(this.track.uri).then(() =>
this.$store.dispatch('add_notification', { text: 'Album tracks appended to queue', type: 'info', timeout: 2000 })
)
},
open_album: function () {
this.$emit('close')
if (this.track.media_kind === 'podcast') {
this.$router.push({ path: '/podcasts/' + this.track.album_id })
} else if (this.track.media_kind === 'audiobook') {
this.$router.push({ path: '/audiobooks/' + this.track.album_id })
} else {
this.$router.push({ path: '/music/albums/' + this.track.album_id })
}
},
open_artist: function () {
this.$emit('close')
this.$router.push({ path: '/music/artists/' + this.track.album_artist_id })
}
}
}
</script>
<style>
</style>

View File

@ -18,7 +18,14 @@
</template>
<template slot="content">
<p class="heading has-text-centered-mobile">{{ album.track_count }} tracks</p>
<list-item-track v-for="(track, index) in tracks" :key="track.id" :track="track" :position="index" :context_uri="album.uri"></list-item-track>
<list-item-track v-for="(track, index) in tracks" :key="track.id" :track="track" :position="index" :context_uri="album.uri">
<template slot="actions">
<a @click="open_dialog(track)">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
</template>
</list-item-track>
<modal-dialog-track :show="show_details_modal" :track="selected_track" @close="show_details_modal = false" />
</template>
</content-with-heading>
</template>
@ -27,6 +34,7 @@
import { LoadDataBeforeEnterMixin } from './mixin'
import ContentWithHeading from '@/templates/ContentWithHeading'
import ListItemTrack from '@/components/ListItemTrack'
import ModalDialogTrack from '@/components/ModalDialogTrack'
import webapi from '@/webapi'
const albumData = {
@ -46,12 +54,15 @@ const albumData = {
export default {
name: 'PageAlbum',
mixins: [ LoadDataBeforeEnterMixin(albumData) ],
components: { ContentWithHeading, ListItemTrack },
components: { ContentWithHeading, ListItemTrack, ModalDialogTrack },
data () {
return {
album: {},
tracks: []
tracks: [],
show_details_modal: false,
selected_track: {}
}
},
@ -63,6 +74,11 @@ export default {
play: function () {
webapi.player_play_uri(this.album.uri, true)
},
open_dialog: function (track) {
this.selected_track = track
this.show_details_modal = true
}
}
}

View File

@ -19,7 +19,14 @@
</a>
</template>
<template slot="content">
<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>
<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">
<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>
<modal-dialog-album :show="show_details_modal" :album="selected_album" @close="show_details_modal = false" />
</template>
</content-with-heading>
</div>
@ -31,6 +38,7 @@ import ContentWithHeading from '@/templates/ContentWithHeading'
import TabsMusic from '@/components/TabsMusic'
import IndexButtonList from '@/components/IndexButtonList'
import ListItemAlbum from '@/components/ListItemAlbum'
import ModalDialogAlbum from '@/components/ModalDialogAlbum'
import webapi from '@/webapi'
import * as types from '@/store/mutation_types'
@ -47,11 +55,14 @@ const albumsData = {
export default {
name: 'PageAlbums',
mixins: [ LoadDataBeforeEnterMixin(albumsData) ],
components: { ContentWithHeading, TabsMusic, IndexButtonList, ListItemAlbum },
components: { ContentWithHeading, TabsMusic, IndexButtonList, ListItemAlbum, ModalDialogAlbum },
data () {
return {
albums: { items: [] }
albums: { items: [] },
show_details_modal: false,
selected_album: {}
}
},
@ -74,6 +85,11 @@ export default {
anchor: function (album, index) {
return album.name_sort.charAt(0).toUpperCase()
},
open_dialog: function (album) {
this.selected_album = album
this.show_details_modal = true
}
}
}

View File

@ -10,7 +10,14 @@
</template>
<template slot="content">
<p class="heading has-text-centered-mobile">{{ artist.album_count }} albums | <a class="has-text-link" @click="open_tracks">{{ artist.track_count }} tracks</a></p>
<list-item-album v-for="album in albums.items" :key="album.id" :album="album"></list-item-album>
<list-item-album v-for="album in albums.items" :key="album.id" :album="album">
<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>
<modal-dialog-album :show="show_details_modal" :album="selected_album" @close="show_details_modal = false" />
</template>
</content-with-heading>
</template>
@ -19,6 +26,7 @@
import { LoadDataBeforeEnterMixin } from './mixin'
import ContentWithHeading from '@/templates/ContentWithHeading'
import ListItemAlbum from '@/components/ListItemAlbum'
import ModalDialogAlbum from '@/components/ModalDialogAlbum'
import webapi from '@/webapi'
const artistData = {
@ -38,12 +46,15 @@ const artistData = {
export default {
name: 'PageArtist',
mixins: [ LoadDataBeforeEnterMixin(artistData) ],
components: { ContentWithHeading, ListItemAlbum },
components: { ContentWithHeading, ListItemAlbum, ModalDialogAlbum },
data () {
return {
artist: {},
albums: {}
albums: {},
show_details_modal: false,
selected_album: {}
}
},
@ -54,6 +65,11 @@ export default {
play: function () {
webapi.player_play_uri(this.albums.items.map(a => a.uri).join(','), true)
},
open_dialog: function (album) {
this.selected_album = album
this.show_details_modal = true
}
}
}

View File

@ -19,7 +19,14 @@
</a>
</template>
<template slot="content">
<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>
<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)">
<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>
<modal-dialog-artist :show="show_details_modal" :artist="selected_artist" @close="show_details_modal = false" />
</template>
</content-with-heading>
</div>
@ -31,6 +38,7 @@ import ContentWithHeading from '@/templates/ContentWithHeading'
import TabsMusic from '@/components/TabsMusic'
import IndexButtonList from '@/components/IndexButtonList'
import ListItemArtist from '@/components/ListItemArtist'
import ModalDialogArtist from '@/components/ModalDialogArtist'
import webapi from '@/webapi'
import * as types from '@/store/mutation_types'
@ -47,11 +55,14 @@ const artistsData = {
export default {
name: 'PageArtists',
mixins: [ LoadDataBeforeEnterMixin(artistsData) ],
components: { ContentWithHeading, TabsMusic, IndexButtonList, ListItemArtist },
components: { ContentWithHeading, TabsMusic, IndexButtonList, ListItemArtist, ModalDialogArtist },
data () {
return {
artists: { items: [] }
artists: { items: [] },
show_details_modal: false,
selected_artist: {}
}
},
@ -74,6 +85,11 @@ export default {
anchor: function (artist, index) {
return artist.name_sort.charAt(0).toUpperCase()
},
open_dialog: function (artist) {
this.selected_artist = artist
this.show_details_modal = true
}
}
}

View File

@ -14,7 +14,14 @@
</template>
<template slot="content">
<p class="heading has-text-centered-mobile">{{ album.track_count }} tracks</p>
<list-item-track v-for="(track, index) in tracks" :key="track.id" :track="track" :position="index" :context_uri="album.uri"></list-item-track>
<list-item-track v-for="(track, index) in tracks" :key="track.id" :track="track" :position="index" :context_uri="album.uri">
<template slot="actions">
<a @click="open_dialog(track)">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
</template>
</list-item-track>
<modal-dialog-track :show="show_details_modal" :track="selected_track" @close="show_details_modal = false" />
</template>
</content-with-heading>
</template>
@ -23,6 +30,7 @@
import { LoadDataBeforeEnterMixin } from './mixin'
import ContentWithHeading from '@/templates/ContentWithHeading'
import ListItemTrack from '@/components/ListItemTrack'
import ModalDialogTrack from '@/components/ModalDialogTrack'
import webapi from '@/webapi'
const albumData = {
@ -42,18 +50,26 @@ const albumData = {
export default {
name: 'PageAudiobook',
mixins: [ LoadDataBeforeEnterMixin(albumData) ],
components: { ContentWithHeading, ListItemTrack },
components: { ContentWithHeading, ListItemTrack, ModalDialogTrack },
data () {
return {
album: {},
tracks: []
tracks: [],
show_details_modal: false,
selected_track: {}
}
},
methods: {
play: function () {
webapi.player_play_uri(this.album.uri, false)
},
open_dialog: function (track) {
this.selected_track = track
this.show_details_modal = true
}
}
}

View File

@ -6,7 +6,14 @@
<p class="heading">{{ albums.total }} audiobooks</p>
</template>
<template slot="content">
<list-item-album v-for="album in albums.items" :key="album.id" :album="album" :media_kind="'audiobook'"></list-item-album>
<list-item-album v-for="album in albums.items" :key="album.id" :album="album" :media_kind="'audiobook'">
<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>
<modal-dialog-album :show="show_details_modal" :album="selected_album" :media_kind="'audiobook'" @close="show_details_modal = false" />
</template>
</content-with-heading>
</div>
@ -16,6 +23,7 @@
import { LoadDataBeforeEnterMixin } from './mixin'
import ContentWithHeading from '@/templates/ContentWithHeading'
import ListItemAlbum from '@/components/ListItemAlbum'
import ModalDialogAlbum from '@/components/ModalDialogAlbum'
import webapi from '@/webapi'
const albumsData = {
@ -31,11 +39,21 @@ const albumsData = {
export default {
name: 'PageAudiobooks',
mixins: [ LoadDataBeforeEnterMixin(albumsData) ],
components: { ContentWithHeading, ListItemAlbum },
components: { ContentWithHeading, ListItemAlbum, ModalDialogAlbum },
data () {
return {
albums: {}
albums: {},
show_details_modal: false,
selected_album: {}
}
},
methods: {
open_dialog: function (album) {
this.selected_album = album
this.show_details_modal = true
}
}
}

View File

@ -9,7 +9,14 @@
<p class="heading">albums</p>
</template>
<template slot="content">
<list-item-album v-for="album in recently_added.items" :key="album.id" :album="album"></list-item-album>
<list-item-album v-for="album in recently_added.items" :key="album.id" :album="album">
<template slot="actions">
<a @click="open_album_dialog(album)">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
</template>
</list-item-album>
<modal-dialog-album :show="show_album_details_modal" :album="selected_album" @close="show_album_details_modal = false" />
</template>
<template slot="footer">
<nav class="level">
@ -27,7 +34,14 @@
<p class="heading">tracks</p>
</template>
<template slot="content">
<list-item-track v-for="track in recently_played.items" :key="track.id" :track="track" :position="0" :context_uri="track.uri"></list-item-track>
<list-item-track v-for="track in recently_played.items" :key="track.id" :track="track" :position="0" :context_uri="track.uri">
<template slot="actions">
<a @click="open_track_dialog(track)">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
</template>
</list-item-track>
<modal-dialog-track :show="show_track_details_modal" :track="selected_track" @close="show_track_details_modal = false" />
</template>
<template slot="footer">
<nav class="level">
@ -46,6 +60,8 @@ import ContentWithHeading from '@/templates/ContentWithHeading'
import TabsMusic from '@/components/TabsMusic'
import ListItemAlbum from '@/components/ListItemAlbum'
import ListItemTrack from '@/components/ListItemTrack'
import ModalDialogTrack from '@/components/ModalDialogTrack'
import ModalDialogAlbum from '@/components/ModalDialogAlbum'
import webapi from '@/webapi'
const browseData = {
@ -65,18 +81,34 @@ const browseData = {
export default {
name: 'PageBrowse',
mixins: [ LoadDataBeforeEnterMixin(browseData) ],
components: { ContentWithHeading, TabsMusic, ListItemAlbum, ListItemTrack },
components: { ContentWithHeading, TabsMusic, ListItemAlbum, ListItemTrack, ModalDialogTrack, ModalDialogAlbum },
data () {
return {
recently_added: {},
recently_played: {}
recently_played: {},
show_track_details_modal: false,
selected_track: {},
show_album_details_modal: false,
selected_album: {}
}
},
methods: {
open_browse: function (type) {
this.$router.push({ path: '/music/browse/' + type })
},
open_track_dialog: function (track) {
this.selected_track = track
this.show_track_details_modal = true
},
open_album_dialog: function (album) {
this.selected_album = album
this.show_album_details_modal = true
}
}
}

View File

@ -8,7 +8,14 @@
<p class="heading">albums</p>
</template>
<template slot="content">
<list-item-album v-for="album in recently_added.items" :key="album.id" :album="album"></list-item-album>
<list-item-album v-for="album in recently_added.items" :key="album.id" :album="album">
<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>
<modal-dialog-album :show="show_details_modal" :album="selected_album" @close="show_details_modal = false" />
</template>
</content-with-heading>
</div>
@ -19,6 +26,7 @@ import { LoadDataBeforeEnterMixin } from './mixin'
import ContentWithHeading from '@/templates/ContentWithHeading'
import TabsMusic from '@/components/TabsMusic'
import ListItemAlbum from '@/components/ListItemAlbum'
import ModalDialogAlbum from '@/components/ModalDialogAlbum'
import webapi from '@/webapi'
const browseData = {
@ -38,11 +46,21 @@ const browseData = {
export default {
name: 'PageBrowseType',
mixins: [ LoadDataBeforeEnterMixin(browseData) ],
components: { ContentWithHeading, TabsMusic, ListItemAlbum },
components: { ContentWithHeading, TabsMusic, ListItemAlbum, ModalDialogAlbum },
data () {
return {
recently_added: {}
recently_added: {},
show_details_modal: false,
selected_album: {}
}
},
methods: {
open_dialog: function (album) {
this.selected_album = album
this.show_details_modal = true
}
}
}

View File

@ -8,7 +8,14 @@
<p class="heading">tracks</p>
</template>
<template slot="content">
<list-item-track v-for="track in recently_played.items" :key="track.id" :track="track" :position="0" :context_uri="track.uri"></list-item-track>
<list-item-track v-for="track in recently_played.items" :key="track.id" :track="track" :position="0" :context_uri="track.uri">
<template slot="actions">
<a @click="open_dialog(track)">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
</template>
</list-item-track>
<modal-dialog-track :show="show_details_modal" :track="selected_track" @close="show_details_modal = false" />
</template>
</content-with-heading>
</div>
@ -19,6 +26,7 @@ import { LoadDataBeforeEnterMixin } from './mixin'
import ContentWithHeading from '@/templates/ContentWithHeading'
import TabsMusic from '@/components/TabsMusic'
import ListItemTrack from '@/components/ListItemTrack'
import ModalDialogTrack from '@/components/ModalDialogTrack'
import webapi from '@/webapi'
const browseData = {
@ -38,11 +46,21 @@ const browseData = {
export default {
name: 'PageBrowseType',
mixins: [ LoadDataBeforeEnterMixin(browseData) ],
components: { ContentWithHeading, TabsMusic, ListItemTrack },
components: { ContentWithHeading, TabsMusic, ListItemTrack, ModalDialogTrack },
data () {
return {
recently_played: {}
recently_played: {},
show_details_modal: false,
selected_track: {}
}
},
methods: {
open_dialog: function (track) {
this.selected_track = track
this.show_details_modal = true
}
}
}

View File

@ -10,8 +10,15 @@
</a>
</template>
<template slot="content">
<p class="heading has-text-centered-mobile">{{ genreAlbums.total }} albums | <a class="has-text-link" @click="open_tracks">{{ tracks }} tracks</a></p>
<list-item-albums v-for="album in genreAlbums.items" :key="album.id" :album="album" :links="links"></list-item-albums>
<p class="heading has-text-centered-mobile">{{ genreAlbums.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">
<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-albums>
<modal-dialog-album :show="show_details_modal" :album="selected_album" @close="show_details_modal = false" />
</template>
</content-with-heading>
</div>
@ -22,6 +29,7 @@ import { LoadDataBeforeEnterMixin } from './mixin'
import ContentWithHeading from '@/templates/ContentWithHeading'
import TabsMusic from '@/components/TabsMusic'
import ListItemAlbums from '@/components/ListItemAlbum'
import ModalDialogAlbum from '@/components/ModalDialogAlbum'
import webapi from '@/webapi'
const genreData = {
@ -52,13 +60,16 @@ const genreData = {
export default {
name: 'PageGenre',
mixins: [ LoadDataBeforeEnterMixin(genreData) ],
components: { ContentWithHeading, TabsMusic, ListItemAlbums },
components: { ContentWithHeading, TabsMusic, ListItemAlbums, ModalDialogAlbum },
data () {
return {
name: '',
genreAlbums: {},
links: []
links: [],
show_details_modal: false,
selected_album: {}
}
},
@ -70,6 +81,11 @@ export default {
play: function () {
webapi.player_play_uri(this.genreAlbums.items.map(a => a.uri).join(','), true)
},
open_dialog: function (album) {
this.selected_album = album
this.show_details_modal = true
}
}
}

View File

@ -11,7 +11,14 @@
</template>
<template slot="content">
<p class="heading has-text-centered-mobile"><a class="has-text-link" @click="open_genre">albums</a> | {{ tracks.total }} tracks</p>
<list-item-track v-for="(track, index) in tracks.items" :key="track.id" :track="track" :position="index" :context_uri="tracks.items.map(a => a.uri).join(',')" :links="links"></list-item-track>
<list-item-track v-for="(track, index) in tracks.items" :key="track.id" :track="track" :position="index" :context_uri="tracks.items.map(a => a.uri).join(',')" :links="links">
<template slot="actions">
<a @click="open_dialog(track)">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
</template>
</list-item-track>
<modal-dialog-track :show="show_details_modal" :track="selected_track" @close="show_details_modal = false" />
</template>
</content-with-heading>
</div>
@ -21,6 +28,7 @@
import { LoadDataBeforeEnterMixin } from './mixin'
import ContentWithHeading from '@/templates/ContentWithHeading'
import ListItemTrack from '@/components/ListItemTrack'
import ModalDialogTrack from '@/components/ModalDialogTrack'
import webapi from '@/webapi'
const tracksData = {
@ -37,13 +45,16 @@ const tracksData = {
export default {
name: 'PageGenreTracks',
mixins: [ LoadDataBeforeEnterMixin(tracksData) ],
components: { ContentWithHeading, ListItemTrack },
components: { ContentWithHeading, ListItemTrack, ModalDialogTrack },
data () {
return {
tracks: {},
genre: '',
links: []
links: [],
show_details_modal: false,
selected_track: {}
}
},
@ -55,6 +66,11 @@ export default {
play: function () {
webapi.player_play_uri(this.tracks.items.map(a => a.uri).join(','), true)
},
open_dialog: function (track) {
this.selected_track = track
this.show_details_modal = true
}
}
}

View File

@ -11,7 +11,14 @@
<p class="heading">{{ genres.total }} genres</p>
</template>
<template slot="content">
<list-item-genre v-for="(genre, index) in genres.items" :key="genre.name" :genre="genre" :anchor="anchor(genre, index)"></list-item-genre>
<list-item-genre v-for="(genre, index) in genres.items" :key="genre.name" :genre="genre" :anchor="anchor(genre, index)">
<template slot="actions">
<a @click="open_dialog(genre)">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
</template>
</list-item-genre>
<modal-dialog-genre :show="show_details_modal" :genre="selected_genre" @close="show_details_modal = false" />
</template>
</content-with-heading>
</div>
@ -23,6 +30,7 @@ import ContentWithHeading from '@/templates/ContentWithHeading'
import TabsMusic from '@/components/TabsMusic'
import IndexButtonList from '@/components/IndexButtonList'
import ListItemGenre from '@/components/ListItemGenre'
import ModalDialogGenre from '@/components/ModalDialogGenre'
import webapi from '@/webapi'
const genresData = {
@ -38,11 +46,14 @@ const genresData = {
export default {
name: 'PageGenres',
mixins: [ LoadDataBeforeEnterMixin(genresData) ],
components: { ContentWithHeading, TabsMusic, IndexButtonList, ListItemGenre },
components: { ContentWithHeading, TabsMusic, IndexButtonList, ListItemGenre, ModalDialogGenre },
data () {
return {
genres: { items: [] }
genres: { items: [] },
show_details_modal: false,
selected_genre: {}
}
},
@ -56,6 +67,11 @@ export default {
methods: {
anchor: function (genre, index) {
return genre.name.charAt(0).toUpperCase()
},
open_dialog: function (genre) {
this.selected_genre = genre
this.show_details_modal = true
}
}
}

View File

@ -10,7 +10,14 @@
</template>
<template slot="content">
<p class="heading has-text-centered-mobile">{{ tracks.length }} tracks</p>
<list-item-track v-for="(track, index) in tracks" :key="track.id" :track="track" :position="index" :context_uri="playlist.uri"></list-item-track>
<list-item-track v-for="(track, index) in tracks" :key="track.id" :track="track" :position="index" :context_uri="playlist.uri">
<template slot="actions">
<a @click="open_dialog(track)">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
</template>
</list-item-track>
<modal-dialog-track :show="show_details_modal" :track="selected_track" @close="show_details_modal = false" />
</template>
</content-with-heading>
</template>
@ -19,6 +26,7 @@
import { LoadDataBeforeEnterMixin } from './mixin'
import ContentWithHeading from '@/templates/ContentWithHeading'
import ListItemTrack from '@/components/ListItemTrack'
import ModalDialogTrack from '@/components/ModalDialogTrack'
import webapi from '@/webapi'
const playlistData = {
@ -38,18 +46,26 @@ const playlistData = {
export default {
name: 'PagePlaylist',
mixins: [ LoadDataBeforeEnterMixin(playlistData) ],
components: { ContentWithHeading, ListItemTrack },
components: { ContentWithHeading, ListItemTrack, ModalDialogTrack },
data () {
return {
playlist: {},
tracks: []
tracks: [],
show_details_modal: false,
selected_track: {}
}
},
methods: {
play: function () {
webapi.player_play_uri(this.playlist.uri, true)
},
open_dialog: function (track) {
this.selected_track = track
this.show_details_modal = true
}
}
}

View File

@ -5,7 +5,14 @@
<p class="heading">{{ playlists.total }} playlists</p>
</template>
<template slot="content">
<list-item-playlist v-for="playlist in playlists.items" :key="playlist.id" :playlist="playlist"></list-item-playlist>
<list-item-playlist v-for="playlist in playlists.items" :key="playlist.id" :playlist="playlist">
<template slot="actions">
<a @click="open_dialog(playlist)">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
</template>
</list-item-playlist>
<modal-dialog-playlist :show="show_details_modal" :playlist="selected_playlist" @close="show_details_modal = false" />
</template>
</content-with-heading>
</template>
@ -15,6 +22,7 @@ import { LoadDataBeforeEnterMixin } from './mixin'
import ContentWithHeading from '@/templates/ContentWithHeading'
import TabsMusic from '@/components/TabsMusic'
import ListItemPlaylist from '@/components/ListItemPlaylist'
import ModalDialogPlaylist from '@/components/ModalDialogPlaylist'
import webapi from '@/webapi'
const playlistsData = {
@ -30,11 +38,21 @@ const playlistsData = {
export default {
name: 'PagePlaylists',
mixins: [ LoadDataBeforeEnterMixin(playlistsData) ],
components: { ContentWithHeading, TabsMusic, ListItemPlaylist },
components: { ContentWithHeading, TabsMusic, ListItemPlaylist, ModalDialogPlaylist },
data () {
return {
playlists: {}
playlists: {},
show_details_modal: false,
selected_playlist: {}
}
},
methods: {
open_dialog: function (playlist) {
this.selected_playlist = playlist
this.show_details_modal = true
}
}
}

View File

@ -13,7 +13,14 @@
</template>
<template slot="content">
<p class="heading has-text-centered-mobile">{{ album.track_count }} tracks</p>
<list-item-track v-for="(track, index) in tracks" :key="track.id" :track="track" :position="index" :context_uri="album.uri"></list-item-track>
<list-item-track v-for="(track, index) in tracks" :key="track.id" :track="track" :position="index" :context_uri="album.uri">
<template slot="actions">
<a @click="open_dialog(track)">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
</template>
</list-item-track>
<modal-dialog-track :show="show_details_modal" :track="selected_track" @close="show_details_modal = false" />
</template>
</content-with-heading>
</template>
@ -22,6 +29,7 @@
import { LoadDataBeforeEnterMixin } from './mixin'
import ContentWithHeading from '@/templates/ContentWithHeading'
import ListItemTrack from '@/components/ListItemTrack'
import ModalDialogTrack from '@/components/ModalDialogTrack'
import webapi from '@/webapi'
const albumData = {
@ -41,18 +49,26 @@ const albumData = {
export default {
name: 'PagePodcast',
mixins: [ LoadDataBeforeEnterMixin(albumData) ],
components: { ContentWithHeading, ListItemTrack },
components: { ContentWithHeading, ListItemTrack, ModalDialogTrack },
data () {
return {
album: {},
tracks: []
tracks: [],
show_details_modal: false,
selected_track: {}
}
},
methods: {
play: function () {
webapi.player_play_uri(this.album.uri, false)
},
open_dialog: function (track) {
this.selected_track = track
this.show_details_modal = true
}
}
}

View File

@ -6,7 +6,14 @@
<p class="heading">{{ albums.total }} podcasts</p>
</template>
<template slot="content">
<list-item-album v-for="album in albums.items" :key="album.id" :album="album" :media_kind="'podcast'"></list-item-album>
<list-item-album v-for="album in albums.items" :key="album.id" :album="album" :media_kind="'podcast'">
<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>
<modal-dialog-album :show="show_details_modal" :album="selected_album" :media_kind="'podcast'" @close="show_details_modal = false" />
</template>
</content-with-heading>
</div>
@ -16,6 +23,7 @@
import { LoadDataBeforeEnterMixin } from './mixin'
import ContentWithHeading from '@/templates/ContentWithHeading'
import ListItemAlbum from '@/components/ListItemAlbum'
import ModalDialogAlbum from '@/components/ModalDialogAlbum'
import webapi from '@/webapi'
const albumsData = {
@ -31,11 +39,21 @@ const albumsData = {
export default {
name: 'PagePodcasts',
mixins: [ LoadDataBeforeEnterMixin(albumsData) ],
components: { ContentWithHeading, ListItemAlbum },
components: { ContentWithHeading, ListItemAlbum, ModalDialogAlbum },
data () {
return {
albums: {}
albums: {},
show_details_modal: false,
selected_album: {}
}
},
methods: {
open_dialog: function (album) {
this.selected_album = album
this.show_details_modal = true
}
}
}

View File

@ -40,8 +40,18 @@
:key="item.id" :item="item" :position="index"
:current_position="current_position"
:show_only_next_items="show_only_next_items"
:edit_mode="edit_mode"></list-item-queue-item>
:edit_mode="edit_mode">
<template slot="actions">
<a @click="open_dialog(item)" v-if="!edit_mode">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
<a @click="remove(item)" v-if="item.id !== state.item_id && edit_mode">
<span class="icon has-text-grey"><i class="mdi mdi-delete mdi-18px"></i></span>
</a>
</template>
</list-item-queue-item>
</draggable>
<modal-dialog-queue-item :show="show_details_modal" :item="selected_item" @close="show_details_modal = false" />
</template>
</content-with-heading>
</template>
@ -49,17 +59,21 @@
<script>
import ContentWithHeading from '@/templates/ContentWithHeading'
import ListItemQueueItem from '@/components/ListItemQueueItem'
import ModalDialogQueueItem from '@/components/ModalDialogQueueItem'
import webapi from '@/webapi'
import * as types from '@/store/mutation_types'
import draggable from 'vuedraggable'
export default {
name: 'PageQueue',
components: { ContentWithHeading, ListItemQueueItem, draggable },
components: { ContentWithHeading, ListItemQueueItem, draggable, ModalDialogQueueItem },
data () {
return {
edit_mode: false
edit_mode: false,
show_details_modal: false,
selected_item: {}
}
},
@ -92,6 +106,10 @@ export default {
this.$store.commit(types.SHOW_ONLY_NEXT_ITEMS, !this.show_only_next_items)
},
remove: function (item) {
webapi.queue_remove(item.id)
},
move_item: function (e) {
var oldPosition = !this.show_only_next_items ? e.oldIndex : e.oldIndex + this.current_position
var item = this.queue_items[oldPosition]
@ -99,6 +117,11 @@ export default {
if (newPosition !== oldPosition) {
webapi.queue_move(item.id, newPosition)
}
},
open_dialog: function (item) {
this.selected_item = item
this.show_details_modal = true
}
}
}

View File

@ -31,7 +31,14 @@
<p class="title is-4">Tracks</p>
</template>
<template slot="content">
<list-item-track v-for="track in tracks.items" :key="track.id" :track="track" :position="0" :context_uri="track.uri"></list-item-track>
<list-item-track v-for="track in tracks.items" :key="track.id" :track="track" :position="0" :context_uri="track.uri">
<template slot="actions">
<a @click="open_track_dialog(track)">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
</template>
</list-item-track>
<modal-dialog-track :show="show_track_details_modal" :track="selected_track" @close="show_track_details_modal = false" />
</template>
<template slot="footer">
<nav v-if="show_all_tracks_button" class="level">
@ -49,7 +56,14 @@
<p class="title is-4">Artists</p>
</template>
<template slot="content">
<list-item-artist v-for="artist in artists.items" :key="artist.id" :artist="artist"></list-item-artist>
<list-item-artist v-for="artist in artists.items" :key="artist.id" :artist="artist">
<template slot="actions">
<a @click="open_artist_dialog(artist)">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
</template>
</list-item-artist>
<modal-dialog-artist :show="show_artist_details_modal" :artist="selected_artist" @close="show_artist_details_modal = false" />
</template>
<template slot="footer">
<nav v-if="show_all_artists_button" class="level">
@ -67,7 +81,14 @@
<p class="title is-4">Albums</p>
</template>
<template slot="content">
<list-item-album v-for="album in albums.items" :key="album.id" :album="album"></list-item-album>
<list-item-album v-for="album in albums.items" :key="album.id" :album="album">
<template slot="actions">
<a @click="open_album_dialog(album)">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
</template>
</list-item-album>
<modal-dialog-album :show="show_album_details_modal" :album="selected_album" @close="show_album_details_modal = false" />
</template>
<template slot="footer">
<nav v-if="show_all_albums_button" class="level">
@ -85,7 +106,14 @@
<p class="title is-4">Playlists</p>
</template>
<template slot="content">
<list-item-playlist v-for="playlist in playlists.items" :key="playlist.id" :playlist="playlist"></list-item-playlist>
<list-item-playlist v-for="playlist in playlists.items" :key="playlist.id" :playlist="playlist">
<template slot="actions">
<a @click="open_playlist_dialog(playlist)">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
</template>
</list-item-playlist>
<modal-dialog-playlist :show="show_playlist_details_modal" :playlist="selected_playlist" @close="show_playlist_details_modal = false" />
</template>
<template slot="footer">
<nav v-if="show_all_playlists_button" class="level">
@ -106,12 +134,16 @@ import ListItemTrack from '@/components/ListItemTrack'
import ListItemArtist from '@/components/ListItemArtist'
import ListItemAlbum from '@/components/ListItemAlbum'
import ListItemPlaylist from '@/components/ListItemPlaylist'
import ModalDialogTrack from '@/components/ModalDialogTrack'
import ModalDialogAlbum from '@/components/ModalDialogAlbum'
import ModalDialogArtist from '@/components/ModalDialogArtist'
import ModalDialogPlaylist from '@/components/ModalDialogPlaylist'
import webapi from '@/webapi'
import * as types from '@/store/mutation_types'
export default {
name: 'PageSearch',
components: { ContentWithHeading, TabsSearch, ListItemTrack, ListItemArtist, ListItemAlbum, ListItemPlaylist },
components: { ContentWithHeading, TabsSearch, ListItemTrack, ListItemArtist, ListItemAlbum, ListItemPlaylist, ModalDialogTrack, ModalDialogAlbum, ModalDialogArtist, ModalDialogPlaylist },
data () {
return {
@ -119,7 +151,19 @@ export default {
tracks: { items: [], total: 0 },
artists: { items: [], total: 0 },
albums: { items: [], total: 0 },
playlists: { items: [], total: 0 }
playlists: { items: [], total: 0 },
show_track_details_modal: false,
selected_track: {},
show_album_details_modal: false,
selected_album: {},
show_artist_details_modal: false,
selected_artist: {},
show_playlist_details_modal: false,
selected_playlist: {}
}
},
@ -241,6 +285,26 @@ export default {
open_recent_search: function (query) {
this.search_query = query
this.new_search()
},
open_track_dialog: function (track) {
this.selected_track = track
this.show_track_details_modal = true
},
open_album_dialog: function (album) {
this.selected_album = album
this.show_album_details_modal = true
},
open_artist_dialog: function (artist) {
this.selected_artist = artist
this.show_artist_details_modal = true
},
open_playlist_dialog: function (playlist) {
this.selected_playlist = playlist
this.show_playlist_details_modal = true
}
},

View File

@ -11,7 +11,14 @@
</template>
<template slot="content">
<p class="heading has-text-centered-mobile"><a class="has-text-link" @click="open_artist">{{ artist.album_count }} albums</a> | {{ artist.track_count }} tracks</p>
<list-item-track v-for="(track, index) in tracks.items" :key="track.id" :track="track" :position="index" :context_uri="tracks.items.map(a => a.uri).join(',')"></list-item-track>
<list-item-track v-for="(track, index) in tracks.items" :key="track.id" :track="track" :position="index" :context_uri="tracks.items.map(a => a.uri).join(',')">
<template slot="actions">
<a @click="open_dialog(track)">
<span class="icon has-text-dark"><i class="mdi mdi-dots-vertical mdi-18px"></i></span>
</a>
</template>
</list-item-track>
<modal-dialog-track :show="show_details_modal" :track="selected_track" @close="show_details_modal = false" />
</template>
</content-with-heading>
</div>
@ -21,6 +28,7 @@
import { LoadDataBeforeEnterMixin } from './mixin'
import ContentWithHeading from '@/templates/ContentWithHeading'
import ListItemTrack from '@/components/ListItemTrack'
import ModalDialogTrack from '@/components/ModalDialogTrack'
import webapi from '@/webapi'
const tracksData = {
@ -40,12 +48,15 @@ const tracksData = {
export default {
name: 'PageTracks',
mixins: [ LoadDataBeforeEnterMixin(tracksData) ],
components: { ContentWithHeading, ListItemTrack },
components: { ContentWithHeading, ListItemTrack, ModalDialogTrack },
data () {
return {
artist: {},
tracks: {}
tracks: {},
show_details_modal: false,
selected_track: {}
}
},
@ -57,6 +68,11 @@ export default {
play: function () {
webapi.player_play_uri(this.tracks.items.map(a => a.uri).join(','), true)
},
open_dialog: function (track) {
this.selected_track = track
this.show_details_modal = true
}
}
}