mirror of
https://github.com/owntone/owntone-server.git
synced 2025-03-03 23:30:09 -05:00
[web] Refactor the heading title in the pages
This commit is contained in:
parent
ef3e64b9c9
commit
bdad6d61bf
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,11 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
class="button is-small is-rounded"
|
class="button is-small is-rounded"
|
||||||
:disabled="disabled"
|
:disabled="button.disabled"
|
||||||
@click="handler"
|
@click="button.handler"
|
||||||
>
|
>
|
||||||
<mdicon v-if="icon" class="icon" :name="icon" size="16" />
|
<mdicon v-if="button.icon" class="icon" :name="button.icon" size="16" />
|
||||||
<span v-if="label" v-text="$t(label)" />
|
<span v-if="button.key" v-text="$t(button.key)" />
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -13,10 +13,7 @@
|
|||||||
export default {
|
export default {
|
||||||
name: 'ControlButton',
|
name: 'ControlButton',
|
||||||
props: {
|
props: {
|
||||||
disabled: { default: false, type: Boolean },
|
button: { required: true, type: Object }
|
||||||
handler: { required: true, type: Function },
|
|
||||||
icon: { default: '', type: String },
|
|
||||||
label: { default: '', type: String }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
:class="{ 'is-hidden-mobile': link.icon }"
|
:class="{ 'is-hidden-mobile': link.icon }"
|
||||||
v-text="$t(link.label)"
|
v-text="$t(link.key)"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
24
web-src/src/components/HeadingTitle.vue
Normal file
24
web-src/src/components/HeadingTitle.vue
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="content.title" class="title is-4" v-text="content.title" />
|
||||||
|
<div class="is-size-7 is-uppercase">
|
||||||
|
<template v-for="(part, index) in content.subtitle" :key="index">
|
||||||
|
<a
|
||||||
|
v-if="part.handler"
|
||||||
|
@click="part.handler"
|
||||||
|
v-text="$t(part.key, { count: $n(part.count) }, part.count)"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
v-text="$t(part.key, { count: $n(part.count) }, part.count)"
|
||||||
|
/>
|
||||||
|
<span v-if="index !== content.subtitle.length - 1"> | </span>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'HeadingTitle',
|
||||||
|
props: { content: { required: true, type: Object } }
|
||||||
|
}
|
||||||
|
</script>
|
@ -100,16 +100,8 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
actions() {
|
actions() {
|
||||||
return [
|
return [
|
||||||
{
|
{ key: 'page.podcast.cancel', handler: 'cancel', icon: 'cancel' },
|
||||||
label: this.$t('page.podcast.cancel'),
|
{ key: 'page.podcast.remove', handler: 'remove', icon: 'delete' }
|
||||||
handler: 'cancel',
|
|
||||||
icon: 'cancel'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: this.$t('page.podcast.remove'),
|
|
||||||
handler: 'remove',
|
|
||||||
icon: 'delete'
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
media_kind_resolved() {
|
media_kind_resolved() {
|
||||||
|
@ -13,10 +13,10 @@
|
|||||||
<slot v-if="$slots.buttons" name="buttons" />
|
<slot v-if="$slots.buttons" name="buttons" />
|
||||||
<div
|
<div
|
||||||
v-for="property in item.properties?.filter((p) => p.value)"
|
v-for="property in item.properties?.filter((p) => p.value)"
|
||||||
:key="property.label"
|
:key="property.key"
|
||||||
class="mb-3"
|
class="mb-3"
|
||||||
>
|
>
|
||||||
<div class="is-size-7 is-uppercase" v-text="$t(property.label)" />
|
<div class="is-size-7 is-uppercase" v-text="$t(property.key)" />
|
||||||
<div class="title is-6">
|
<div class="title is-6">
|
||||||
<a
|
<a
|
||||||
v-if="property.handler"
|
v-if="property.handler"
|
||||||
|
@ -11,13 +11,13 @@
|
|||||||
<footer v-if="actions.length" class="card-footer">
|
<footer v-if="actions.length" class="card-footer">
|
||||||
<a
|
<a
|
||||||
v-for="action in actions"
|
v-for="action in actions"
|
||||||
:key="action.label"
|
:key="action.key"
|
||||||
class="card-footer-item"
|
class="card-footer-item"
|
||||||
:class="{ 'is-disabled': action.disabled }"
|
:class="{ 'is-disabled': action.disabled }"
|
||||||
@click="action.handler"
|
@click="action.handler"
|
||||||
>
|
>
|
||||||
<mdicon class="icon" :name="action.icon" size="16" />
|
<mdicon class="icon" :name="action.icon" size="16" />
|
||||||
<span class="is-size-7" v-text="action.label" />
|
<span class="is-size-7" v-text="$t(action.key)" />
|
||||||
</a>
|
</a>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
@ -37,16 +37,12 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
actions() {
|
actions() {
|
||||||
if (this.loading) {
|
if (this.loading) {
|
||||||
return [{ label: this.$t('dialog.add.rss.processing'), icon: 'web' }]
|
return [{ key: 'dialog.add.rss.processing', icon: 'web' }]
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
|
{ key: 'dialog.add.rss.cancel', handler: this.cancel, icon: 'cancel' },
|
||||||
{
|
{
|
||||||
label: this.$t('dialog.add.rss.cancel'),
|
key: 'dialog.add.rss.add',
|
||||||
handler: this.cancel,
|
|
||||||
icon: 'cancel'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: this.$t('dialog.add.rss.add'),
|
|
||||||
disabled: this.disabled,
|
disabled: this.disabled,
|
||||||
handler: this.add,
|
handler: this.add,
|
||||||
icon: 'playlist-plus'
|
icon: 'playlist-plus'
|
||||||
|
@ -38,22 +38,22 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
actions() {
|
actions() {
|
||||||
if (this.loading) {
|
if (this.loading) {
|
||||||
return [{ label: this.$t('dialog.add.stream.processing'), icon: 'web' }]
|
return [{ key: 'dialog.add.stream.processing', icon: 'web' }]
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: this.$t('dialog.add.stream.cancel'),
|
key: 'dialog.add.stream.cancel',
|
||||||
handler: this.cancel,
|
handler: this.cancel,
|
||||||
icon: 'cancel'
|
icon: 'cancel'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: this.$t('dialog.add.stream.add'),
|
key: 'dialog.add.stream.add',
|
||||||
disabled: this.disabled,
|
disabled: this.disabled,
|
||||||
handler: this.add,
|
handler: this.add,
|
||||||
icon: 'playlist-plus'
|
icon: 'playlist-plus'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: this.$t('dialog.add.stream.play'),
|
key: 'dialog.add.stream.play',
|
||||||
disabled: this.disabled,
|
disabled: this.disabled,
|
||||||
handler: this.play,
|
handler: this.play,
|
||||||
icon: 'play'
|
icon: 'play'
|
||||||
|
@ -25,15 +25,12 @@ export default {
|
|||||||
if (this.media_kind_resolved === 'podcast') {
|
if (this.media_kind_resolved === 'podcast') {
|
||||||
if (this.item.data_kind === 'url') {
|
if (this.item.data_kind === 'url') {
|
||||||
return [
|
return [
|
||||||
{ label: 'dialog.album.mark-as-played', handler: this.mark_played },
|
{ key: 'dialog.album.mark-as-played', handler: this.mark_played },
|
||||||
{
|
{ key: 'dialog.album.remove-podcast', handler: this.remove_podcast }
|
||||||
label: 'dialog.album.remove-podcast',
|
|
||||||
handler: this.remove_podcast
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
{ label: 'dialog.album.mark-as-played', handler: this.mark_played }
|
{ key: 'dialog.album.mark-as-played', handler: this.mark_played }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
@ -49,26 +46,26 @@ export default {
|
|||||||
uri: this.item.uri,
|
uri: this.item.uri,
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
label: 'property.artist',
|
key: 'property.artist',
|
||||||
value: this.item.artist,
|
value: this.item.artist,
|
||||||
handler: this.open_artist
|
handler: this.open_artist
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.release-date',
|
key: 'property.release-date',
|
||||||
value: this.$filters.toDate(this.item.date_released)
|
value: this.$filters.toDate(this.item.date_released)
|
||||||
},
|
},
|
||||||
{ label: 'property.year', value: this.item.year },
|
{ key: 'property.year', value: this.item.year },
|
||||||
{ label: 'property.tracks', value: this.item.track_count },
|
{ key: 'property.tracks', value: this.item.track_count },
|
||||||
{
|
{
|
||||||
label: 'property.duration',
|
key: 'property.duration',
|
||||||
value: this.$filters.toTimecode(this.item.length_ms)
|
value: this.$filters.toTimecode(this.item.length_ms)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.type',
|
key: 'property.type',
|
||||||
value: `${this.$t(`media.kind.${this.item.media_kind}`)} - ${this.$t(`data.kind.${this.item.data_kind}`)}`
|
value: `${this.$t(`media.kind.${this.item.media_kind}`)} - ${this.$t(`data.kind.${this.item.data_kind}`)}`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.added-on',
|
key: 'property.added-on',
|
||||||
value: this.$filters.toDateTime(this.item.time_added)
|
value: this.$filters.toDateTime(this.item.time_added)
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -23,18 +23,15 @@ export default {
|
|||||||
uri: this.item.uri,
|
uri: this.item.uri,
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
label: 'property.artist',
|
key: 'property.artist',
|
||||||
value: this.item?.artists?.[0]?.name,
|
value: this.item?.artists?.[0]?.name,
|
||||||
handler: this.open_artist
|
handler: this.open_artist
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.release-date',
|
key: 'property.release-date',
|
||||||
value: this.$filters.toDate(this.item.release_date)
|
value: this.$filters.toDate(this.item.release_date)
|
||||||
},
|
},
|
||||||
{
|
{ key: 'property.type', value: this.item.album_type }
|
||||||
label: 'property.type',
|
|
||||||
value: this.item.album_type
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,14 +21,14 @@ export default {
|
|||||||
handler: this.open,
|
handler: this.open,
|
||||||
uri: this.item.uri,
|
uri: this.item.uri,
|
||||||
properties: [
|
properties: [
|
||||||
{ label: 'property.albums', value: this.item.album_count },
|
{ key: 'property.albums', value: this.item.album_count },
|
||||||
{ label: 'property.tracks', value: this.item.track_count },
|
{ key: 'property.tracks', value: this.item.track_count },
|
||||||
{
|
{
|
||||||
label: 'property.type',
|
key: 'property.type',
|
||||||
value: this.$t(`data.kind.${this.item.data_kind}`)
|
value: this.$t(`data.kind.${this.item.data_kind}`)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.added-on',
|
key: 'property.added-on',
|
||||||
value: this.$filters.toDateTime(this.item.time_added)
|
value: this.$filters.toDateTime(this.item.time_added)
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -22,15 +22,12 @@ export default {
|
|||||||
uri: this.item.uri,
|
uri: this.item.uri,
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
label: 'property.popularity',
|
key: 'property.popularity',
|
||||||
value: [this.item.popularity, this.item.followers?.total].join(
|
value: [this.item.popularity, this.item.followers?.total].join(
|
||||||
' / '
|
' / '
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{ key: 'property.genres', value: this.item.genres?.join(', ') }
|
||||||
label: 'property.genres',
|
|
||||||
value: this.item.genres?.join(', ')
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,17 +22,17 @@ export default {
|
|||||||
expression: `composer is "${this.item.name}" and media_kind is music`,
|
expression: `composer is "${this.item.name}" and media_kind is music`,
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
label: 'property.albums',
|
key: 'property.albums',
|
||||||
value: this.item.album_count,
|
value: this.item.album_count,
|
||||||
handler: this.open_albums
|
handler: this.open_albums
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.tracks',
|
key: 'property.tracks',
|
||||||
value: this.item.track_count,
|
value: this.item.track_count,
|
||||||
handler: this.open_tracks
|
handler: this.open_tracks
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.duration',
|
key: 'property.duration',
|
||||||
value: this.$filters.toTimecode(this.item.length_ms)
|
value: this.$filters.toTimecode(this.item.length_ms)
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -25,16 +25,10 @@ export default {
|
|||||||
handler: this.open,
|
handler: this.open,
|
||||||
expression: `genre is "${this.item.name}" and media_kind is ${this.media_kind}`,
|
expression: `genre is "${this.item.name}" and media_kind is ${this.media_kind}`,
|
||||||
properties: [
|
properties: [
|
||||||
|
{ key: 'property.albums', value: this.item.album_count },
|
||||||
|
{ key: 'property.tracks', value: this.item.track_count },
|
||||||
{
|
{
|
||||||
label: 'property.albums',
|
key: 'property.duration',
|
||||||
value: this.item.album_count
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'property.tracks',
|
|
||||||
value: this.item.track_count
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'property.duration',
|
|
||||||
value: this.$filters.toTimecode(this.item.length_ms)
|
value: this.$filters.toTimecode(this.item.length_ms)
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -6,9 +6,8 @@
|
|||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<control-button
|
<control-button
|
||||||
v-for="button in buttons"
|
v-for="button in buttons"
|
||||||
:key="button.label"
|
:key="button.key"
|
||||||
:handler="button.handler"
|
:button="button"
|
||||||
label="button.label"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -36,20 +35,16 @@ export default {
|
|||||||
actions() {
|
actions() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: this.$t('dialog.playable.add'),
|
key: 'dialog.playable.add',
|
||||||
handler: this.queue_add,
|
handler: this.queue_add,
|
||||||
icon: 'playlist-plus'
|
icon: 'playlist-plus'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: this.$t('dialog.playable.add-next'),
|
key: 'dialog.playable.add-next',
|
||||||
handler: this.queue_add_next,
|
handler: this.queue_add_next,
|
||||||
icon: 'playlist-play'
|
icon: 'playlist-play'
|
||||||
},
|
},
|
||||||
{
|
{ key: 'dialog.playable.play', handler: this.play, icon: 'play' }
|
||||||
label: this.$t('dialog.playable.play'),
|
|
||||||
handler: this.play,
|
|
||||||
icon: 'play'
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -26,12 +26,12 @@ export default {
|
|||||||
uri: this.item.uri,
|
uri: this.item.uri,
|
||||||
uris: this.uris,
|
uris: this.uris,
|
||||||
properties: [
|
properties: [
|
||||||
{ label: 'property.tracks', value: this.item.item_count },
|
{ key: 'property.tracks', value: this.item.item_count },
|
||||||
{
|
{
|
||||||
label: 'property.type',
|
key: 'property.type',
|
||||||
value: this.$t(`playlist.type.${this.item.type}`)
|
value: this.$t(`playlist.type.${this.item.type}`)
|
||||||
},
|
},
|
||||||
{ label: 'property.path', value: this.item.path }
|
{ key: 'property.path', value: this.item.path }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,16 +47,16 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
actions() {
|
actions() {
|
||||||
if (this.loading) {
|
if (this.loading) {
|
||||||
return [{ label: this.$t('dialog.playlist.save.saving'), icon: 'web' }]
|
return [{ key: 'dialog.playlist.save.saving', icon: 'web' }]
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: this.$t('dialog.playlist.save.cancel'),
|
key: 'dialog.playlist.save.cancel',
|
||||||
handler: this.cancel,
|
handler: this.cancel,
|
||||||
icon: 'cancel'
|
icon: 'cancel'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: this.$t('dialog.playlist.save.save'),
|
key: 'dialog.playlist.save.save',
|
||||||
disabled: this.disabled,
|
disabled: this.disabled,
|
||||||
handler: this.save,
|
handler: this.save,
|
||||||
icon: 'download'
|
icon: 'download'
|
||||||
|
@ -21,15 +21,9 @@ export default {
|
|||||||
handler: this.open,
|
handler: this.open,
|
||||||
uri: this.item.uri,
|
uri: this.item.uri,
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{ key: 'property.owner', value: this.item.owner?.display_name },
|
||||||
label: 'property.owner',
|
{ key: 'property.tracks', value: this.item.tracks?.total },
|
||||||
value: this.item.owner?.display_name
|
{ key: 'property.path', value: this.item.uri }
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'property.tracks',
|
|
||||||
value: this.item.tracks?.total
|
|
||||||
},
|
|
||||||
{ label: 'property.path', value: this.item.uri }
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,12 +30,12 @@ export default {
|
|||||||
actions() {
|
actions() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: this.$t('dialog.queue-item.remove'),
|
key: this.$t('dialog.queue-item.remove'),
|
||||||
handler: this.remove,
|
handler: this.remove,
|
||||||
icon: 'delete'
|
icon: 'delete'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: this.$t('dialog.queue-item.play'),
|
key: this.$t('dialog.queue-item.play'),
|
||||||
handler: this.play,
|
handler: this.play,
|
||||||
icon: 'play'
|
icon: 'play'
|
||||||
}
|
}
|
||||||
@ -47,37 +47,37 @@ export default {
|
|||||||
uri: this.item.uri,
|
uri: this.item.uri,
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
label: 'property.album',
|
key: 'property.album',
|
||||||
value: this.item.album,
|
value: this.item.album,
|
||||||
handler: this.open_album
|
handler: this.open_album
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.album-artist',
|
key: 'property.album-artist',
|
||||||
value: this.item.album_artist,
|
value: this.item.album_artist,
|
||||||
handler: this.open_album_artist
|
handler: this.open_album_artist
|
||||||
},
|
},
|
||||||
{ label: 'property.composer', value: this.item.composer },
|
{ key: 'property.composer', value: this.item.composer },
|
||||||
{ label: 'property.year', value: this.item.year },
|
{ key: 'property.year', value: this.item.year },
|
||||||
{
|
{
|
||||||
label: 'property.genre',
|
key: 'property.genre',
|
||||||
value: this.item.genre,
|
value: this.item.genre,
|
||||||
handler: this.open_genre
|
handler: this.open_genre
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.position',
|
key: 'property.position',
|
||||||
value: [this.item.disc_number, this.item.track_number].join(' / ')
|
value: [this.item.disc_number, this.item.track_number].join(' / ')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.duration',
|
key: 'property.duration',
|
||||||
value: this.$filters.toTimecode(this.item.length_ms)
|
value: this.$filters.toTimecode(this.item.length_ms)
|
||||||
},
|
},
|
||||||
{ label: 'property.path', value: this.item.path },
|
{ key: 'property.path', value: this.item.path },
|
||||||
{
|
{
|
||||||
label: 'property.type',
|
key: 'property.type',
|
||||||
value: `${this.$t(`media.kind.${this.item.media_kind}`)} - ${this.$t(`data.kind.${this.item.data_kind}`)}`
|
value: `${this.$t(`media.kind.${this.item.media_kind}`)} - ${this.$t(`data.kind.${this.item.data_kind}`)}`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.quality',
|
key: 'property.quality',
|
||||||
value: this.$t('dialog.track.quality-value', {
|
value: this.$t('dialog.track.quality-value', {
|
||||||
format: this.item.type,
|
format: this.item.type,
|
||||||
bitrate: this.item.bitrate,
|
bitrate: this.item.bitrate,
|
||||||
|
@ -47,12 +47,12 @@ export default {
|
|||||||
actions() {
|
actions() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: this.$t('dialog.remote-pairing.cancel'),
|
key: 'dialog.remote-pairing.cancel',
|
||||||
handler: this.cancel,
|
handler: this.cancel,
|
||||||
icon: 'cancel'
|
icon: 'cancel'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: this.$t('dialog.remote-pairing.pair'),
|
key: 'dialog.remote-pairing.pair',
|
||||||
handler: this.pair,
|
handler: this.pair,
|
||||||
icon: 'cellphone'
|
icon: 'cellphone'
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,8 @@ export default {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
return this.item.play_count > 0
|
return this.item.play_count > 0
|
||||||
? [{ label: 'dialog.track.mark-as-new', handler: this.mark_new }]
|
? [{ key: 'dialog.track.mark-as-new', handler: this.mark_new }]
|
||||||
: [{ label: 'dialog.track.mark-as-played', handler: this.mark_played }]
|
: [{ key: 'dialog.track.mark-as-played', handler: this.mark_played }]
|
||||||
},
|
},
|
||||||
playable() {
|
playable() {
|
||||||
return {
|
return {
|
||||||
@ -31,36 +31,36 @@ export default {
|
|||||||
uri: this.item.uri,
|
uri: this.item.uri,
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
label: 'property.album',
|
key: 'property.album',
|
||||||
value: this.item.album,
|
value: this.item.album,
|
||||||
handler: this.open_album
|
handler: this.open_album
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.album-artist',
|
key: 'property.album-artist',
|
||||||
value: this.item.album_artist,
|
value: this.item.album_artist,
|
||||||
handler: this.open_artist
|
handler: this.open_artist
|
||||||
},
|
},
|
||||||
{ label: 'property.composer', value: this.item.composer },
|
{ key: 'property.composer', value: this.item.composer },
|
||||||
{
|
{
|
||||||
label: 'property.release-date',
|
key: 'property.release-date',
|
||||||
value: this.$filters.toDate(this.item.date_released)
|
value: this.$filters.toDate(this.item.date_released)
|
||||||
},
|
},
|
||||||
{ label: 'property.year', value: this.item.year },
|
{ key: 'property.year', value: this.item.year },
|
||||||
{ label: 'property.genre', value: this.item.genre },
|
{ key: 'property.genre', value: this.item.genre },
|
||||||
{
|
{
|
||||||
label: 'property.position',
|
key: 'property.position',
|
||||||
value: [this.item.disc_number, this.item.track_number].join(' / ')
|
value: [this.item.disc_number, this.item.track_number].join(' / ')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.duration',
|
key: 'property.duration',
|
||||||
value: this.$filters.toTimecode(this.item.length_ms)
|
value: this.$filters.toTimecode(this.item.length_ms)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.type',
|
key: 'property.type',
|
||||||
value: `${this.$t(`media.kind.${this.item.media_kind}`)} - ${this.$t(`data.kind.${this.item.data_kind}`)}`
|
value: `${this.$t(`media.kind.${this.item.media_kind}`)} - ${this.$t(`data.kind.${this.item.data_kind}`)}`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.quality',
|
key: 'property.quality',
|
||||||
value:
|
value:
|
||||||
this.item.data_kind !== 'spotify' &&
|
this.item.data_kind !== 'spotify' &&
|
||||||
this.$t('dialog.track.quality-value', {
|
this.$t('dialog.track.quality-value', {
|
||||||
@ -71,17 +71,17 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.added-on',
|
key: 'property.added-on',
|
||||||
value: this.$filters.toDateTime(this.item.time_added)
|
value: this.$filters.toDateTime(this.item.time_added)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.rating',
|
key: 'property.rating',
|
||||||
value: this.$t('dialog.track.rating-value', {
|
value: this.$t('dialog.track.rating-value', {
|
||||||
rating: Math.floor(this.item.rating / 10)
|
rating: Math.floor(this.item.rating / 10)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
{ label: 'property.comment', value: this.item.comment },
|
{ key: 'property.comment', value: this.item.comment },
|
||||||
{ label: 'property.path', value: this.item.path }
|
{ key: 'property.path', value: this.item.path }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,28 +24,28 @@ export default {
|
|||||||
uri: this.item.uri,
|
uri: this.item.uri,
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
label: 'property.album',
|
key: 'property.album',
|
||||||
value: this.item.album.name,
|
value: this.item.album.name,
|
||||||
handler: this.open_album
|
handler: this.open_album
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.album-artist',
|
key: 'property.album-artist',
|
||||||
value: this.item.artists[0]?.name,
|
value: this.item.artists[0]?.name,
|
||||||
handler: this.open_artist
|
handler: this.open_artist
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.release-date',
|
key: 'property.release-date',
|
||||||
value: this.$filters.toDate(this.item.album.release_date)
|
value: this.$filters.toDate(this.item.album.release_date)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.position',
|
key: 'property.position',
|
||||||
value: [this.item.disc_number, this.item.track_number].join(' / ')
|
value: [this.item.disc_number, this.item.track_number].join(' / ')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.duration',
|
key: 'property.duration',
|
||||||
value: this.$filters.toTimecode(this.item.duration_ms)
|
value: this.$filters.toTimecode(this.item.duration_ms)
|
||||||
},
|
},
|
||||||
{ label: 'property.path', value: this.item.uri }
|
{ key: 'property.path', value: this.item.uri }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,14 +68,14 @@ export default {
|
|||||||
actions() {
|
actions() {
|
||||||
const actions = [
|
const actions = [
|
||||||
{
|
{
|
||||||
label: this.$t('dialog.update.cancel'),
|
key: 'dialog.update.cancel',
|
||||||
handler: this.cancel,
|
handler: this.cancel,
|
||||||
icon: 'cancel'
|
icon: 'cancel'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
if (!this.libraryStore.updating) {
|
if (!this.libraryStore.updating) {
|
||||||
actions.push({
|
actions.push({
|
||||||
label: this.$t('dialog.update.rescan'),
|
key: 'dialog.update.rescan',
|
||||||
handler: this.analyse,
|
handler: this.analyse,
|
||||||
icon: 'check'
|
icon: 'check'
|
||||||
})
|
})
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
v-else-if="menu.action"
|
v-else-if="menu.action"
|
||||||
class="dropdown-item"
|
class="dropdown-item"
|
||||||
@click.stop.prevent="menu.action"
|
@click.stop.prevent="menu.action"
|
||||||
v-text="$t(menu.label)"
|
v-text="$t(menu.key)"
|
||||||
/>
|
/>
|
||||||
<control-link
|
<control-link
|
||||||
v-else
|
v-else
|
||||||
@ -48,7 +48,7 @@
|
|||||||
'pl-5': menu.sub,
|
'pl-5': menu.sub,
|
||||||
'has-text-weight-semibold': menu.icon
|
'has-text-weight-semibold': menu.icon
|
||||||
}"
|
}"
|
||||||
v-text="$t(menu.label)"
|
v-text="$t(menu.key)"
|
||||||
/>
|
/>
|
||||||
</control-link>
|
</control-link>
|
||||||
</template>
|
</template>
|
||||||
@ -82,82 +82,82 @@ export default {
|
|||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
name: 'playlists',
|
name: 'playlists',
|
||||||
label: 'navigation.playlists',
|
key: 'navigation.playlists',
|
||||||
icon: 'music-box-multiple',
|
icon: 'music-box-multiple',
|
||||||
show: this.settingsStore.show_menu_item_playlists
|
show: this.settingsStore.show_menu_item_playlists
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'music',
|
name: 'music',
|
||||||
label: 'navigation.music',
|
key: 'navigation.music',
|
||||||
icon: 'music',
|
icon: 'music',
|
||||||
show: this.settingsStore.show_menu_item_music
|
show: this.settingsStore.show_menu_item_music
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'music-artists',
|
name: 'music-artists',
|
||||||
label: 'navigation.artists',
|
key: 'navigation.artists',
|
||||||
show: true,
|
show: true,
|
||||||
sub: true
|
sub: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'music-albums',
|
name: 'music-albums',
|
||||||
label: 'navigation.albums',
|
key: 'navigation.albums',
|
||||||
show: true,
|
show: true,
|
||||||
sub: true
|
sub: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'music-genres',
|
name: 'music-genres',
|
||||||
label: 'navigation.genres',
|
key: 'navigation.genres',
|
||||||
show: true,
|
show: true,
|
||||||
sub: true
|
sub: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'music-spotify',
|
name: 'music-spotify',
|
||||||
label: 'navigation.spotify',
|
key: 'navigation.spotify',
|
||||||
show: this.servicesStore.spotify.webapi_token_valid,
|
show: this.servicesStore.spotify.webapi_token_valid,
|
||||||
sub: true
|
sub: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'podcasts',
|
name: 'podcasts',
|
||||||
label: 'navigation.podcasts',
|
key: 'navigation.podcasts',
|
||||||
icon: 'microphone',
|
icon: 'microphone',
|
||||||
show: this.settingsStore.show_menu_item_podcasts
|
show: this.settingsStore.show_menu_item_podcasts
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'audiobooks',
|
name: 'audiobooks',
|
||||||
label: 'navigation.audiobooks',
|
key: 'navigation.audiobooks',
|
||||||
icon: 'book-open-variant',
|
icon: 'book-open-variant',
|
||||||
show: this.settingsStore.show_menu_item_audiobooks
|
show: this.settingsStore.show_menu_item_audiobooks
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'radio',
|
name: 'radio',
|
||||||
label: 'navigation.radio',
|
key: 'navigation.radio',
|
||||||
icon: 'radio',
|
icon: 'radio',
|
||||||
show: this.settingsStore.show_menu_item_radio
|
show: this.settingsStore.show_menu_item_radio
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'files',
|
name: 'files',
|
||||||
label: 'navigation.files',
|
key: 'navigation.files',
|
||||||
icon: 'folder-open',
|
icon: 'folder-open',
|
||||||
show: this.settingsStore.show_menu_item_files
|
show: this.settingsStore.show_menu_item_files
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: this.searchStore.search_source,
|
name: this.searchStore.search_source,
|
||||||
label: 'navigation.search',
|
key: 'navigation.search',
|
||||||
icon: 'magnify',
|
icon: 'magnify',
|
||||||
show: this.settingsStore.show_menu_item_search
|
show: this.settingsStore.show_menu_item_search
|
||||||
},
|
},
|
||||||
{ separator: true, show: true },
|
{ separator: true, show: true },
|
||||||
{
|
{
|
||||||
name: 'settings-webinterface',
|
name: 'settings-webinterface',
|
||||||
label: 'navigation.settings',
|
key: 'navigation.settings',
|
||||||
show: true
|
show: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'navigation.update-library',
|
key: 'navigation.update-library',
|
||||||
action: this.open_update_dialog,
|
action: this.open_update_dialog,
|
||||||
show: true
|
show: true
|
||||||
},
|
},
|
||||||
{ name: 'about', label: 'navigation.about', show: true }
|
{ name: 'about', key: 'navigation.about', show: true }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
zindex() {
|
zindex() {
|
||||||
|
@ -14,17 +14,17 @@ export default {
|
|||||||
{
|
{
|
||||||
to: { name: 'audiobooks-artists' },
|
to: { name: 'audiobooks-artists' },
|
||||||
icon: 'account-music',
|
icon: 'account-music',
|
||||||
label: 'page.audiobooks.tabs.authors'
|
key: 'page.audiobooks.tabs.authors'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: { name: 'audiobooks-albums' },
|
to: { name: 'audiobooks-albums' },
|
||||||
icon: 'album',
|
icon: 'album',
|
||||||
label: 'page.audiobooks.tabs.audiobooks'
|
key: 'page.audiobooks.tabs.audiobooks'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: { name: 'audiobooks-genres' },
|
to: { name: 'audiobooks-genres' },
|
||||||
icon: 'speaker',
|
icon: 'speaker',
|
||||||
label: 'page.audiobooks.tabs.genres'
|
key: 'page.audiobooks.tabs.genres'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -18,34 +18,34 @@ export default {
|
|||||||
{
|
{
|
||||||
to: { name: 'music-history' },
|
to: { name: 'music-history' },
|
||||||
icon: 'history',
|
icon: 'history',
|
||||||
label: 'page.music.tabs.history'
|
key: 'page.music.tabs.history'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: { name: 'music-artists' },
|
to: { name: 'music-artists' },
|
||||||
icon: 'account-music',
|
icon: 'account-music',
|
||||||
label: 'page.music.tabs.artists'
|
key: 'page.music.tabs.artists'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: { name: 'music-albums' },
|
to: { name: 'music-albums' },
|
||||||
icon: 'album',
|
icon: 'album',
|
||||||
label: 'page.music.tabs.albums'
|
key: 'page.music.tabs.albums'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: { name: 'music-genres' },
|
to: { name: 'music-genres' },
|
||||||
icon: 'speaker',
|
icon: 'speaker',
|
||||||
label: 'page.music.tabs.genres'
|
key: 'page.music.tabs.genres'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: { name: 'music-composers' },
|
to: { name: 'music-composers' },
|
||||||
icon: 'book-open-page-variant',
|
icon: 'book-open-page-variant',
|
||||||
label: 'page.music.tabs.composers'
|
key: 'page.music.tabs.composers'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
if (this.servicesStore.spotify.webapi_token_valid) {
|
if (this.servicesStore.spotify.webapi_token_valid) {
|
||||||
links.push({
|
links.push({
|
||||||
to: { name: 'music-spotify' },
|
to: { name: 'music-spotify' },
|
||||||
icon: 'spotify',
|
icon: 'spotify',
|
||||||
label: 'page.music.tabs.spotify'
|
key: 'page.music.tabs.spotify'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return links
|
return links
|
||||||
|
@ -12,20 +12,20 @@ export default {
|
|||||||
links() {
|
links() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
to: { name: 'settings-webinterface' },
|
key: 'page.settings.tabs.general',
|
||||||
label: 'page.settings.tabs.general'
|
to: { name: 'settings-webinterface' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: { name: 'settings-remotes-outputs' },
|
key: 'page.settings.tabs.remotes-and-outputs',
|
||||||
label: 'page.settings.tabs.remotes-and-outputs'
|
to: { name: 'settings-remotes-outputs' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: { name: 'settings-artwork' },
|
key: 'page.settings.tabs.artwork',
|
||||||
label: 'page.settings.tabs.artwork'
|
to: { name: 'settings-artwork' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: { name: 'settings-online-services' },
|
key: 'page.settings.tabs.online-services',
|
||||||
label: 'page.settings.tabs.online-services'
|
to: { name: 'settings-online-services' }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,112 +1,100 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="section">
|
<div>
|
||||||
<div class="container">
|
<content-with-heading>
|
||||||
<div class="columns is-centered">
|
<template #heading-left>
|
||||||
<div class="column is-four-fifths">
|
<heading-title :content="{ title: $t('page.about.library') }" />
|
||||||
<div class="content">
|
</template>
|
||||||
<nav class="level">
|
<template #heading-right>
|
||||||
<div class="level-left">
|
<control-button
|
||||||
<div class="level-item">
|
:class="{ 'is-loading': libraryStore.updating }"
|
||||||
<p class="title is-4" v-text="$t('page.about.library')" />
|
:button="{
|
||||||
</div>
|
disabled: libraryStore.updating,
|
||||||
</div>
|
handler: showUpdateDialog,
|
||||||
<div class="level-right">
|
icon: 'refresh',
|
||||||
<control-button
|
key: 'page.about.update'
|
||||||
:class="{ 'is-loading': libraryStore.updating }"
|
}"
|
||||||
:disabled="libraryStore.updating"
|
/>
|
||||||
:handler="showUpdateDialog"
|
</template>
|
||||||
icon="refresh"
|
<template #content>
|
||||||
label="page.about.update"
|
<div
|
||||||
/>
|
v-for="property in properties"
|
||||||
</div>
|
:key="property.key"
|
||||||
</nav>
|
class="media is-align-items-center mb-0"
|
||||||
<div
|
>
|
||||||
v-for="property in properties"
|
<div
|
||||||
:key="property.label"
|
class="media-content has-text-weight-bold"
|
||||||
class="media is-align-items-center mb-0"
|
v-text="$t(property.key)"
|
||||||
>
|
/>
|
||||||
<div
|
<div class="media-right">
|
||||||
class="media-content has-text-weight-bold"
|
<span v-text="property.value" />
|
||||||
v-text="$t(property.label)"
|
<span
|
||||||
/>
|
v-if="property.alternate"
|
||||||
<div class="media-right">
|
class="has-text-grey"
|
||||||
<span v-text="property.value" />
|
v-text="` (${property.alternate})`"
|
||||||
<span
|
/>
|
||||||
v-if="property.alternate"
|
|
||||||
class="has-text-grey"
|
|
||||||
v-text="` (${property.alternate})`"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
</div>
|
<template #footer>
|
||||||
</section>
|
<div
|
||||||
<section class="section">
|
class="is-size-7 mt-6"
|
||||||
<div class="container">
|
v-text="
|
||||||
<div class="columns is-centered">
|
$t('page.about.version', {
|
||||||
<div class="column is-four-fifths">
|
version: configurationStore.version
|
||||||
<div class="content has-text-centered-mobile">
|
})
|
||||||
<p
|
"
|
||||||
class="is-size-7"
|
/>
|
||||||
v-text="
|
<div
|
||||||
$t('page.about.version', {
|
class="is-size-7"
|
||||||
version: configurationStore.version
|
v-text="
|
||||||
})
|
$t('page.about.compiled-with', {
|
||||||
"
|
options: configurationStore.buildoptions.join(', ')
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<i18n-t
|
||||||
|
tag="div"
|
||||||
|
class="is-size-7"
|
||||||
|
keypath="page.about.built-with"
|
||||||
|
scope="global"
|
||||||
|
>
|
||||||
|
<template #bulma>
|
||||||
|
<a href="https://bulma.io">Bulma</a>
|
||||||
|
</template>
|
||||||
|
<template #mdi>
|
||||||
|
<a href="https://pictogrammers.com/library/mdi/">
|
||||||
|
Material Design Icons
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
<template #vuejs>
|
||||||
|
<a href="https://vuejs.org/">Vue.js</a>
|
||||||
|
</template>
|
||||||
|
<template #axios>
|
||||||
|
<a href="https://github.com/axios/axios">axios</a>
|
||||||
|
</template>
|
||||||
|
<template #others>
|
||||||
|
<a
|
||||||
|
href="https://github.com/owntone/owntone-server/network/dependencies"
|
||||||
|
v-text="$t('page.about.more')"
|
||||||
/>
|
/>
|
||||||
<p
|
</template>
|
||||||
class="is-size-7"
|
</i18n-t>
|
||||||
v-text="
|
</template>
|
||||||
$t('page.about.compiled-with', {
|
</content-with-heading>
|
||||||
options: configurationStore.buildoptions.join(', ')
|
</div>
|
||||||
})
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<i18n-t
|
|
||||||
tag="p"
|
|
||||||
class="is-size-7"
|
|
||||||
keypath="page.about.built-with"
|
|
||||||
scope="global"
|
|
||||||
>
|
|
||||||
<template #bulma>
|
|
||||||
<a href="https://bulma.io">Bulma</a>
|
|
||||||
</template>
|
|
||||||
<template #mdi>
|
|
||||||
<a href="https://pictogrammers.com/library/mdi/">
|
|
||||||
Material Design Icons
|
|
||||||
</a>
|
|
||||||
</template>
|
|
||||||
<template #vuejs>
|
|
||||||
<a href="https://vuejs.org/">Vue.js</a>
|
|
||||||
</template>
|
|
||||||
<template #axios>
|
|
||||||
<a href="https://github.com/axios/axios">axios</a>
|
|
||||||
</template>
|
|
||||||
<template #others>
|
|
||||||
<a
|
|
||||||
href="https://github.com/owntone/owntone-server/network/dependencies"
|
|
||||||
v-text="$t('page.about.more')"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</i18n-t>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import ControlButton from '@/components/ControlButton.vue'
|
import ControlButton from '@/components/ControlButton.vue'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import { useConfigurationStore } from '@/stores/configuration'
|
import { useConfigurationStore } from '@/stores/configuration'
|
||||||
import { useLibraryStore } from '@/stores/library'
|
import { useLibraryStore } from '@/stores/library'
|
||||||
import { useUIStore } from '@/stores/ui'
|
import { useUIStore } from '@/stores/ui'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PageAbout',
|
name: 'PageAbout',
|
||||||
components: { ControlButton },
|
components: { ContentWithHeading, ControlButton, HeadingTitle },
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
configurationStore: useConfigurationStore(),
|
configurationStore: useConfigurationStore(),
|
||||||
@ -118,32 +106,32 @@ export default {
|
|||||||
properties() {
|
properties() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: 'property.name',
|
key: 'property.name',
|
||||||
value: this.configurationStore.library_name
|
value: this.configurationStore.library_name
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.artists',
|
key: 'property.artists',
|
||||||
value: this.$n(this.libraryStore.artists)
|
value: this.$n(this.libraryStore.artists)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.albums',
|
key: 'property.albums',
|
||||||
value: this.$n(this.libraryStore.albums)
|
value: this.$n(this.libraryStore.albums)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.tracks',
|
key: 'property.tracks',
|
||||||
value: this.$n(this.libraryStore.songs)
|
value: this.$n(this.libraryStore.songs)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.playtime',
|
key: 'property.playtime',
|
||||||
value: this.$filters.toDuration(this.libraryStore.db_playtime)
|
value: this.$filters.toDuration(this.libraryStore.db_playtime)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.updated',
|
key: 'property.updated',
|
||||||
value: this.$filters.toRelativeDuration(this.libraryStore.updated_at),
|
value: this.$filters.toRelativeDuration(this.libraryStore.updated_at),
|
||||||
alternate: this.$filters.toDateTime(this.libraryStore.updated_at)
|
alternate: this.$filters.toDateTime(this.libraryStore.updated_at)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'property.uptime',
|
key: 'property.uptime',
|
||||||
value: this.$filters.toDurationToNow(this.libraryStore.started_at),
|
value: this.$filters.toDurationToNow(this.libraryStore.started_at),
|
||||||
alternate: this.$filters.toDateTime(this.libraryStore.started_at)
|
alternate: this.$filters.toDateTime(this.libraryStore.started_at)
|
||||||
}
|
}
|
||||||
|
@ -12,11 +12,18 @@
|
|||||||
/>
|
/>
|
||||||
<div class="buttons is-centered-mobile mt-5">
|
<div class="buttons is-centered-mobile mt-5">
|
||||||
<control-button
|
<control-button
|
||||||
:handler="play"
|
:button="{
|
||||||
icon="shuffle"
|
handler: play,
|
||||||
label="page.album.shuffle"
|
icon: 'shuffle',
|
||||||
|
key: 'page.album.shuffle'
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<control-button
|
||||||
|
:button="{
|
||||||
|
handler: showDetails,
|
||||||
|
icon: 'dots-horizontal'
|
||||||
|
}"
|
||||||
/>
|
/>
|
||||||
<control-button :handler="showDetails" icon="dots-horizontal" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
|
@ -12,11 +12,15 @@
|
|||||||
/>
|
/>
|
||||||
<div class="buttons is-centered-mobile mt-5">
|
<div class="buttons is-centered-mobile mt-5">
|
||||||
<control-button
|
<control-button
|
||||||
:handler="play"
|
:button="{
|
||||||
icon="shuffle"
|
handler: play,
|
||||||
label="page.spotify.album.shuffle"
|
icon: 'shuffle',
|
||||||
|
key: 'page.spotify.album.shuffle'
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<control-button
|
||||||
|
:button="{ handler: showDetails, icon: 'dots-horizontal' }"
|
||||||
/>
|
/>
|
||||||
<control-button :handler="showDetails" icon="dots-horizontal" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
|
@ -43,11 +43,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="$t('page.albums.title')" />
|
<heading-title :content="heading" />
|
||||||
<div
|
|
||||||
class="is-size-7 is-uppercase"
|
|
||||||
v-text="$t('count.albums', { count: albums.count })"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-albums :items="albums" />
|
<list-albums :items="albums" />
|
||||||
@ -61,6 +57,7 @@ import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
|||||||
import ControlDropdown from '@/components/ControlDropdown.vue'
|
import ControlDropdown from '@/components/ControlDropdown.vue'
|
||||||
import ControlSwitch from '@/components/ControlSwitch.vue'
|
import ControlSwitch from '@/components/ControlSwitch.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import IndexButtonList from '@/components/IndexButtonList.vue'
|
import IndexButtonList from '@/components/IndexButtonList.vue'
|
||||||
import ListAlbums from '@/components/ListAlbums.vue'
|
import ListAlbums from '@/components/ListAlbums.vue'
|
||||||
import TabsMusic from '@/components/TabsMusic.vue'
|
import TabsMusic from '@/components/TabsMusic.vue'
|
||||||
@ -72,7 +69,6 @@ const dataObject = {
|
|||||||
load(to) {
|
load(to) {
|
||||||
return webapi.library_albums('music')
|
return webapi.library_albums('music')
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.albums_list = new GroupedList(response.data)
|
vm.albums_list = new GroupedList(response.data)
|
||||||
}
|
}
|
||||||
@ -84,21 +80,19 @@ export default {
|
|||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
ControlDropdown,
|
ControlDropdown,
|
||||||
ControlSwitch,
|
ControlSwitch,
|
||||||
|
HeadingTitle,
|
||||||
IndexButtonList,
|
IndexButtonList,
|
||||||
ListAlbums,
|
ListAlbums,
|
||||||
TabsMusic
|
TabsMusic
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return { uiStore: useUIStore(), servicesStore: useServicesStore() }
|
return { uiStore: useUIStore(), servicesStore: useServicesStore() }
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
albums_list: new GroupedList(),
|
albums_list: new GroupedList(),
|
||||||
@ -149,7 +143,6 @@ export default {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
albums() {
|
albums() {
|
||||||
const { options } = this.groupings.find(
|
const { options } = this.groupings.find(
|
||||||
@ -161,6 +154,12 @@ export default {
|
|||||||
]
|
]
|
||||||
return this.albums_list.group(options)
|
return this.albums_list.group(options)
|
||||||
},
|
},
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title: this.$t('page.albums.title'),
|
||||||
|
subtitle: [{ key: 'count.albums', count: this.albums.count }]
|
||||||
|
}
|
||||||
|
},
|
||||||
spotify_enabled() {
|
spotify_enabled() {
|
||||||
return this.servicesStore.spotify.webapi_token_valid
|
return this.servicesStore.spotify.webapi_token_valid
|
||||||
}
|
}
|
||||||
|
@ -33,25 +33,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="artist.name" />
|
<heading-title :content="heading" />
|
||||||
<div class="is-size-7 is-uppercase">
|
|
||||||
<span v-text="$t('count.albums', { count: albums.count })" />
|
|
||||||
<span> | </span>
|
|
||||||
<a
|
|
||||||
@click="open_tracks"
|
|
||||||
v-text="$t('count.tracks', { count: track_count })"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<control-button
|
||||||
<control-button :handler="showDetails" icon="dots-horizontal" />
|
:button="{ handler: showDetails, icon: 'dots-horizontal' }"
|
||||||
<control-button
|
/>
|
||||||
:handler="play"
|
<control-button
|
||||||
icon="shuffle"
|
:button="{
|
||||||
label="page.artist.shuffle"
|
handler: play,
|
||||||
/>
|
icon: 'shuffle',
|
||||||
</div>
|
key: 'page.artist.shuffle'
|
||||||
|
}"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-albums :items="albums" />
|
<list-albums :items="albums" />
|
||||||
@ -71,6 +65,7 @@ import ControlButton from '@/components/ControlButton.vue'
|
|||||||
import ControlDropdown from '@/components/ControlDropdown.vue'
|
import ControlDropdown from '@/components/ControlDropdown.vue'
|
||||||
import ControlSwitch from '@/components/ControlSwitch.vue'
|
import ControlSwitch from '@/components/ControlSwitch.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '../components/HeadingTitle.vue'
|
||||||
import ListAlbums from '@/components/ListAlbums.vue'
|
import ListAlbums from '@/components/ListAlbums.vue'
|
||||||
import ModalDialogArtist from '@/components/ModalDialogArtist.vue'
|
import ModalDialogArtist from '@/components/ModalDialogArtist.vue'
|
||||||
import { useServicesStore } from '@/stores/services'
|
import { useServicesStore } from '@/stores/services'
|
||||||
@ -84,7 +79,6 @@ const dataObject = {
|
|||||||
webapi.library_artist_albums(to.params.id)
|
webapi.library_artist_albums(to.params.id)
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.artist = response[0].data
|
vm.artist = response[0].data
|
||||||
vm.albums_list = new GroupedList(response[1].data)
|
vm.albums_list = new GroupedList(response[1].data)
|
||||||
@ -98,20 +92,18 @@ export default {
|
|||||||
ControlButton,
|
ControlButton,
|
||||||
ControlDropdown,
|
ControlDropdown,
|
||||||
ControlSwitch,
|
ControlSwitch,
|
||||||
|
HeadingTitle,
|
||||||
ListAlbums,
|
ListAlbums,
|
||||||
ModalDialogArtist
|
ModalDialogArtist
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return { servicesStore: useServicesStore(), uiStore: useUIStore() }
|
return { servicesStore: useServicesStore(), uiStore: useUIStore() }
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
albums_list: new GroupedList(),
|
albums_list: new GroupedList(),
|
||||||
@ -131,7 +123,6 @@ export default {
|
|||||||
show_details_modal: false
|
show_details_modal: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
albums() {
|
albums() {
|
||||||
const { options } = this.groupings.find(
|
const { options } = this.groupings.find(
|
||||||
@ -142,6 +133,19 @@ export default {
|
|||||||
]
|
]
|
||||||
return this.albums_list.group(options)
|
return this.albums_list.group(options)
|
||||||
},
|
},
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title: this.artist.name,
|
||||||
|
subtitle: [
|
||||||
|
{ key: 'count.albums', count: this.albums.count },
|
||||||
|
{
|
||||||
|
handler: this.open_tracks,
|
||||||
|
key: 'count.tracks',
|
||||||
|
count: this.track_count
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
spotify_enabled() {
|
spotify_enabled() {
|
||||||
return this.servicesStore.spotify.webapi_token_valid
|
return this.servicesStore.spotify.webapi_token_valid
|
||||||
},
|
},
|
||||||
@ -153,7 +157,6 @@ export default {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
open_tracks() {
|
open_tracks() {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
|
@ -2,21 +2,19 @@
|
|||||||
<div>
|
<div>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="artist.name" />
|
<heading-title :content="heading" />
|
||||||
<div
|
|
||||||
class="is-size-7 is-uppercase"
|
|
||||||
v-text="$t('count.albums', { count: total })"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<control-button
|
||||||
<control-button :handler="showDetails" icon="dots-horizontal" />
|
:button="{ handler: showDetails, icon: 'dots-horizontal' }"
|
||||||
<control-button
|
/>
|
||||||
:handler="play"
|
<control-button
|
||||||
icon="shuffle"
|
:button="{
|
||||||
label="page.spotify.artist.shuffle"
|
handler: play,
|
||||||
/>
|
icon: 'shuffle',
|
||||||
</div>
|
key: 'page.spotify.artist.shuffle'
|
||||||
|
}"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-albums-spotify :items="albums" />
|
<list-albums-spotify :items="albums" />
|
||||||
@ -48,6 +46,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import ControlButton from '@/components/ControlButton.vue'
|
import ControlButton from '@/components/ControlButton.vue'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import ListAlbumsSpotify from '@/components/ListAlbumsSpotify.vue'
|
import ListAlbumsSpotify from '@/components/ListAlbumsSpotify.vue'
|
||||||
import ModalDialogArtistSpotify from '@/components/ModalDialogArtistSpotify.vue'
|
import ModalDialogArtistSpotify from '@/components/ModalDialogArtistSpotify.vue'
|
||||||
import SpotifyWebApi from 'spotify-web-api-js'
|
import SpotifyWebApi from 'spotify-web-api-js'
|
||||||
@ -71,7 +70,6 @@ const dataObject = {
|
|||||||
})
|
})
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.artist = response.shift()
|
vm.artist = response.shift()
|
||||||
vm.albums = []
|
vm.albums = []
|
||||||
@ -86,21 +84,19 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
ControlButton,
|
ControlButton,
|
||||||
|
HeadingTitle,
|
||||||
ListAlbumsSpotify,
|
ListAlbumsSpotify,
|
||||||
ModalDialogArtistSpotify,
|
ModalDialogArtistSpotify,
|
||||||
VueEternalLoading
|
VueEternalLoading
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return { servicesStore: useServicesStore() }
|
return { servicesStore: useServicesStore() }
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
albums: [],
|
albums: [],
|
||||||
@ -110,7 +106,14 @@ export default {
|
|||||||
total: 0
|
total: 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title: this.$t('artist.name'),
|
||||||
|
subtitle: [{ key: 'count.albums', count: this.total }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
append_albums(data) {
|
append_albums(data) {
|
||||||
this.albums = this.albums.concat(data.items)
|
this.albums = this.albums.concat(data.items)
|
||||||
|
@ -34,25 +34,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="artist.name" />
|
<heading-title :content="heading" />
|
||||||
<div class="is-size-7 is-uppercase">
|
|
||||||
<a
|
|
||||||
@click="open_artist"
|
|
||||||
v-text="$t('count.albums', { count: album_count })"
|
|
||||||
/>
|
|
||||||
<span> | </span>
|
|
||||||
<span v-text="$t('count.tracks', { count: tracks.count })" />
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<control-button
|
||||||
<control-button :handler="showDetails" icon="dots-horizontal" />
|
:button="{ handler: showDetails, icon: 'dots-horizontal' }"
|
||||||
<control-button
|
/>
|
||||||
:handler="play"
|
<control-button
|
||||||
icon="shuffle"
|
:button="{
|
||||||
label="page.artist.shuffle"
|
handler: play,
|
||||||
/>
|
icon: 'shuffle',
|
||||||
</div>
|
key: 'page.artist.shuffle'
|
||||||
|
}"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-tracks :items="tracks" :uris="track_uris" />
|
<list-tracks :items="tracks" :uris="track_uris" />
|
||||||
@ -72,6 +66,7 @@ import ControlButton from '@/components/ControlButton.vue'
|
|||||||
import ControlDropdown from '@/components/ControlDropdown.vue'
|
import ControlDropdown from '@/components/ControlDropdown.vue'
|
||||||
import ControlSwitch from '@/components/ControlSwitch.vue'
|
import ControlSwitch from '@/components/ControlSwitch.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import IndexButtonList from '@/components/IndexButtonList.vue'
|
import IndexButtonList from '@/components/IndexButtonList.vue'
|
||||||
import ListTracks from '@/components/ListTracks.vue'
|
import ListTracks from '@/components/ListTracks.vue'
|
||||||
import ModalDialogArtist from '@/components/ModalDialogArtist.vue'
|
import ModalDialogArtist from '@/components/ModalDialogArtist.vue'
|
||||||
@ -86,7 +81,6 @@ const dataObject = {
|
|||||||
webapi.library_artist_tracks(to.params.id)
|
webapi.library_artist_tracks(to.params.id)
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.artist = response[0].data
|
vm.artist = response[0].data
|
||||||
vm.tracks_list = new GroupedList(response[1].data.tracks)
|
vm.tracks_list = new GroupedList(response[1].data.tracks)
|
||||||
@ -100,21 +94,19 @@ export default {
|
|||||||
ControlButton,
|
ControlButton,
|
||||||
ControlDropdown,
|
ControlDropdown,
|
||||||
ControlSwitch,
|
ControlSwitch,
|
||||||
|
HeadingTitle,
|
||||||
IndexButtonList,
|
IndexButtonList,
|
||||||
ListTracks,
|
ListTracks,
|
||||||
ModalDialogArtist
|
ModalDialogArtist
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return { servicesStore: useServicesStore(), uiStore: useUIStore() }
|
return { servicesStore: useServicesStore(), uiStore: useUIStore() }
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
artist: {},
|
artist: {},
|
||||||
@ -137,7 +129,6 @@ export default {
|
|||||||
tracks_list: new GroupedList()
|
tracks_list: new GroupedList()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
album_count() {
|
album_count() {
|
||||||
return new Set(
|
return new Set(
|
||||||
@ -146,6 +137,19 @@ export default {
|
|||||||
.map((track) => track.item.album_id)
|
.map((track) => track.item.album_id)
|
||||||
).size
|
).size
|
||||||
},
|
},
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title: this.artist.name,
|
||||||
|
subtitle: [
|
||||||
|
{
|
||||||
|
handler: this.openArtist,
|
||||||
|
key: 'count.albums',
|
||||||
|
count: this.album_count
|
||||||
|
},
|
||||||
|
{ key: 'count.tracks', count: this.tracks.count }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
spotify_enabled() {
|
spotify_enabled() {
|
||||||
return this.servicesStore.spotify.webapi_token_valid
|
return this.servicesStore.spotify.webapi_token_valid
|
||||||
},
|
},
|
||||||
@ -162,9 +166,8 @@ export default {
|
|||||||
return this.tracks_list.group(options)
|
return this.tracks_list.group(options)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
open_artist() {
|
openArtist() {
|
||||||
this.show_details_modal = false
|
this.show_details_modal = false
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: 'music-artist',
|
name: 'music-artist',
|
||||||
|
@ -42,11 +42,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="$t('page.artists.title')" />
|
<heading-title :content="heading" />
|
||||||
<div
|
|
||||||
class="is-size-7 is-uppercase"
|
|
||||||
v-text="$t('count.artists', { count: artists.count })"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-artists :items="artists" />
|
<list-artists :items="artists" />
|
||||||
@ -60,6 +56,7 @@ import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
|||||||
import ControlDropdown from '@/components/ControlDropdown.vue'
|
import ControlDropdown from '@/components/ControlDropdown.vue'
|
||||||
import ControlSwitch from '@/components/ControlSwitch.vue'
|
import ControlSwitch from '@/components/ControlSwitch.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import IndexButtonList from '@/components/IndexButtonList.vue'
|
import IndexButtonList from '@/components/IndexButtonList.vue'
|
||||||
import ListArtists from '@/components/ListArtists.vue'
|
import ListArtists from '@/components/ListArtists.vue'
|
||||||
import TabsMusic from '@/components/TabsMusic.vue'
|
import TabsMusic from '@/components/TabsMusic.vue'
|
||||||
@ -83,21 +80,19 @@ export default {
|
|||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
ControlDropdown,
|
ControlDropdown,
|
||||||
ControlSwitch,
|
ControlSwitch,
|
||||||
|
HeadingTitle,
|
||||||
IndexButtonList,
|
IndexButtonList,
|
||||||
ListArtists,
|
ListArtists,
|
||||||
TabsMusic
|
TabsMusic
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return { servicesStore: useServicesStore(), uiStore: useUIStore() }
|
return { servicesStore: useServicesStore(), uiStore: useUIStore() }
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
artists_list: new GroupedList(),
|
artists_list: new GroupedList(),
|
||||||
@ -118,7 +113,6 @@ export default {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
artists() {
|
artists() {
|
||||||
const { options } = this.groupings.find(
|
const { options } = this.groupings.find(
|
||||||
@ -132,6 +126,12 @@ export default {
|
|||||||
]
|
]
|
||||||
return this.artists_list.group(options)
|
return this.artists_list.group(options)
|
||||||
},
|
},
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title: this.$t('page.artists.title'),
|
||||||
|
subtitle: [{ key: 'count.artists', count: this.artists.count }]
|
||||||
|
}
|
||||||
|
},
|
||||||
spotify_enabled() {
|
spotify_enabled() {
|
||||||
return this.servicesStore.spotify.webapi_token_valid
|
return this.servicesStore.spotify.webapi_token_valid
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-5" v-text="album.name" />
|
<div class="title is-5" v-text="album.name" />
|
||||||
<div class="subtitle is-6">
|
<div class="subtitle is-6">
|
||||||
<a @click="open_artist" v-text="album.artist" />
|
<a @click="openArtist" v-text="album.artist" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="is-size-7 is-uppercase has-text-centered-mobile"
|
class="is-size-7 is-uppercase has-text-centered-mobile"
|
||||||
@ -12,11 +12,15 @@
|
|||||||
/>
|
/>
|
||||||
<div class="buttons is-centered-mobile mt-5">
|
<div class="buttons is-centered-mobile mt-5">
|
||||||
<control-button
|
<control-button
|
||||||
:handler="play"
|
:button="{
|
||||||
icon="play"
|
handler: play,
|
||||||
label="page.audiobooks.album.play"
|
icon: 'play',
|
||||||
|
key: 'page.audiobooks.album.play'
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<control-button
|
||||||
|
:button="{ handler: showDetails, icon: 'dots-horizontal' }"
|
||||||
/>
|
/>
|
||||||
<control-button :handler="showDetails" icon="dots-horizontal" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
@ -57,7 +61,6 @@ const dataObject = {
|
|||||||
webapi.library_album_tracks(to.params.id)
|
webapi.library_album_tracks(to.params.id)
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.album = response[0].data
|
vm.album = response[0].data
|
||||||
vm.tracks = new GroupedList(response[1].data)
|
vm.tracks = new GroupedList(response[1].data)
|
||||||
@ -86,7 +89,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
open_artist() {
|
openArtist() {
|
||||||
this.show_details_modal = false
|
this.show_details_modal = false
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: 'audiobooks-artist',
|
name: 'audiobooks-artist',
|
||||||
|
@ -6,11 +6,7 @@
|
|||||||
<index-button-list :indices="albums.indices" />
|
<index-button-list :indices="albums.indices" />
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t('page.audiobooks.albums.title')" />
|
<heading-title :content="heading" />
|
||||||
<p
|
|
||||||
class="is-size-7 is-uppercase"
|
|
||||||
v-text="$t('count.audiobooks', { count: albums.count })"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-albums :items="albums" />
|
<list-albums :items="albums" />
|
||||||
@ -22,6 +18,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import IndexButtonList from '@/components/IndexButtonList.vue'
|
import IndexButtonList from '@/components/IndexButtonList.vue'
|
||||||
import ListAlbums from '@/components/ListAlbums.vue'
|
import ListAlbums from '@/components/ListAlbums.vue'
|
||||||
import TabsAudiobooks from '@/components/TabsAudiobooks.vue'
|
import TabsAudiobooks from '@/components/TabsAudiobooks.vue'
|
||||||
@ -31,7 +28,6 @@ const dataObject = {
|
|||||||
load(to) {
|
load(to) {
|
||||||
return webapi.library_albums('audiobook')
|
return webapi.library_albums('audiobook')
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.albums = new GroupedList(response.data, {
|
vm.albums = new GroupedList(response.data, {
|
||||||
index: { field: 'name_sort', type: String }
|
index: { field: 'name_sort', type: String }
|
||||||
@ -45,19 +41,26 @@ export default {
|
|||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
IndexButtonList,
|
IndexButtonList,
|
||||||
ListAlbums,
|
ListAlbums,
|
||||||
TabsAudiobooks
|
TabsAudiobooks,
|
||||||
|
HeadingTitle
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
albums: new GroupedList()
|
albums: new GroupedList()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title: this.$t('page.audiobooks.albums.title'),
|
||||||
|
subtitle: [{ key: 'count.audiobooks', count: this.albums.count }]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -2,21 +2,19 @@
|
|||||||
<div>
|
<div>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="artist.name" />
|
<heading-title :content="heading" />
|
||||||
<div
|
|
||||||
class="is-size-7 is-uppercase"
|
|
||||||
v-text="$t('count.audiobooks', { count: artist.album_count })"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<control-button
|
||||||
<control-button :handler="showDetails" icon="dots-horizontal" />
|
:button="{ handler: showDetails, icon: 'dots-horizontal' }"
|
||||||
<control-button
|
/>
|
||||||
:handler="play"
|
<control-button
|
||||||
icon="play"
|
:button="{
|
||||||
label="page.audiobooks.artist.play"
|
handler: play,
|
||||||
/>
|
icon: 'play',
|
||||||
</div>
|
key: 'page.audiobooks.artist.play'
|
||||||
|
}"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-albums :items="albums" />
|
<list-albums :items="albums" />
|
||||||
@ -34,6 +32,7 @@
|
|||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import ControlButton from '@/components/ControlButton.vue'
|
import ControlButton from '@/components/ControlButton.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import ListAlbums from '@/components/ListAlbums.vue'
|
import ListAlbums from '@/components/ListAlbums.vue'
|
||||||
import ModalDialogArtist from '@/components/ModalDialogArtist.vue'
|
import ModalDialogArtist from '@/components/ModalDialogArtist.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
@ -56,6 +55,7 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
ControlButton,
|
ControlButton,
|
||||||
|
HeadingTitle,
|
||||||
ListAlbums,
|
ListAlbums,
|
||||||
ModalDialogArtist
|
ModalDialogArtist
|
||||||
},
|
},
|
||||||
@ -71,6 +71,19 @@ export default {
|
|||||||
show_details_modal: false
|
show_details_modal: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
heading() {
|
||||||
|
if (this.artist.name) {
|
||||||
|
return {
|
||||||
|
title: this.artist.name,
|
||||||
|
subtitle: [
|
||||||
|
{ key: 'count.audiobooks', count: this.artist.album_count }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
play() {
|
play() {
|
||||||
webapi.player_play_uri(
|
webapi.player_play_uri(
|
||||||
|
@ -6,11 +6,7 @@
|
|||||||
<index-button-list :indices="artists.indices" />
|
<index-button-list :indices="artists.indices" />
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="$t('page.audiobooks.artists.title')" />
|
<heading-title :content="heading" />
|
||||||
<div
|
|
||||||
class="is-size-7 is-uppercase"
|
|
||||||
v-text="$t('count.authors', { count: artists.count })"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-artists :items="artists" />
|
<list-artists :items="artists" />
|
||||||
@ -22,6 +18,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import IndexButtonList from '@/components/IndexButtonList.vue'
|
import IndexButtonList from '@/components/IndexButtonList.vue'
|
||||||
import ListArtists from '@/components/ListArtists.vue'
|
import ListArtists from '@/components/ListArtists.vue'
|
||||||
import TabsAudiobooks from '@/components/TabsAudiobooks.vue'
|
import TabsAudiobooks from '@/components/TabsAudiobooks.vue'
|
||||||
@ -31,7 +28,6 @@ const dataObject = {
|
|||||||
load(to) {
|
load(to) {
|
||||||
return webapi.library_artists('audiobook')
|
return webapi.library_artists('audiobook')
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.artists = new GroupedList(response.data, {
|
vm.artists = new GroupedList(response.data, {
|
||||||
index: { field: 'name_sort', type: String }
|
index: { field: 'name_sort', type: String }
|
||||||
@ -43,21 +39,28 @@ export default {
|
|||||||
name: 'PageAudiobooksArtists',
|
name: 'PageAudiobooksArtists',
|
||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
|
HeadingTitle,
|
||||||
IndexButtonList,
|
IndexButtonList,
|
||||||
ListArtists,
|
ListArtists,
|
||||||
TabsAudiobooks
|
TabsAudiobooks
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
artists: new GroupedList()
|
artists: new GroupedList()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title: this.$t('page.audiobooks.artists.title'),
|
||||||
|
subtitle: [{ key: 'count.authors', count: this.artists.count }]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -6,11 +6,7 @@
|
|||||||
<index-button-list :indices="genres.indices" />
|
<index-button-list :indices="genres.indices" />
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="$t('page.genres.title')" />
|
<heading-title :content="heading" />
|
||||||
<div
|
|
||||||
class="is-size-7 is-uppercase"
|
|
||||||
v-text="$t('count.genres', { count: genres.total })"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-genres :items="genres" :media_kind="'audiobook'" />
|
<list-genres :items="genres" :media_kind="'audiobook'" />
|
||||||
@ -22,6 +18,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import IndexButtonList from '@/components/IndexButtonList.vue'
|
import IndexButtonList from '@/components/IndexButtonList.vue'
|
||||||
import ListGenres from '@/components/ListGenres.vue'
|
import ListGenres from '@/components/ListGenres.vue'
|
||||||
import TabsAudiobooks from '@/components/TabsAudiobooks.vue'
|
import TabsAudiobooks from '@/components/TabsAudiobooks.vue'
|
||||||
@ -31,7 +28,6 @@ const dataObject = {
|
|||||||
load(to) {
|
load(to) {
|
||||||
return webapi.library_genres('audiobook')
|
return webapi.library_genres('audiobook')
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.genres = new GroupedList(response.data.genres, {
|
vm.genres = new GroupedList(response.data.genres, {
|
||||||
index: { field: 'name_sort', type: String }
|
index: { field: 'name_sort', type: String }
|
||||||
@ -43,21 +39,28 @@ export default {
|
|||||||
name: 'PageAudiobooksGenres',
|
name: 'PageAudiobooksGenres',
|
||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
|
HeadingTitle,
|
||||||
IndexButtonList,
|
IndexButtonList,
|
||||||
ListGenres,
|
ListGenres,
|
||||||
TabsAudiobooks
|
TabsAudiobooks
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
genres: new GroupedList()
|
genres: new GroupedList()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title: this.$t('page.genres.title'),
|
||||||
|
subtitle: [{ key: 'count.genres', count: this.genres.total }]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -2,25 +2,19 @@
|
|||||||
<div>
|
<div>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="composer.name" />
|
<heading-title :content="heading" />
|
||||||
<div class="is-size-7 is-uppercase">
|
|
||||||
<span v-text="$t('count.albums', { count: composer.album_count })" />
|
|
||||||
<span> | </span>
|
|
||||||
<a
|
|
||||||
@click="open_tracks"
|
|
||||||
v-text="$t('count.tracks', { count: composer.track_count })"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<control-button
|
||||||
<control-button :handler="showDetails" icon="dots-horizontal" />
|
:button="{ handler: showDetails, icon: 'dots-horizontal' }"
|
||||||
<control-button
|
/>
|
||||||
:handler="play"
|
<control-button
|
||||||
icon="shuffle"
|
:button="{
|
||||||
label="page.composer.shuffle"
|
handler: play,
|
||||||
/>
|
icon: 'shuffle',
|
||||||
</div>
|
key: 'page.composer.shuffle'
|
||||||
|
}"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-albums :items="albums" />
|
<list-albums :items="albums" />
|
||||||
@ -38,6 +32,7 @@
|
|||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import ControlButton from '@/components/ControlButton.vue'
|
import ControlButton from '@/components/ControlButton.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import ListAlbums from '@/components/ListAlbums.vue'
|
import ListAlbums from '@/components/ListAlbums.vue'
|
||||||
import ModalDialogComposer from '@/components/ModalDialogComposer.vue'
|
import ModalDialogComposer from '@/components/ModalDialogComposer.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
@ -49,7 +44,6 @@ const dataObject = {
|
|||||||
webapi.library_composer_albums(to.params.name)
|
webapi.library_composer_albums(to.params.name)
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.composer = response[0].data
|
vm.composer = response[0].data
|
||||||
vm.albums = new GroupedList(response[1].data.albums)
|
vm.albums = new GroupedList(response[1].data.albums)
|
||||||
@ -61,6 +55,7 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
ControlButton,
|
ControlButton,
|
||||||
|
HeadingTitle,
|
||||||
ListAlbums,
|
ListAlbums,
|
||||||
ModalDialogComposer
|
ModalDialogComposer
|
||||||
},
|
},
|
||||||
@ -79,6 +74,19 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
expression() {
|
expression() {
|
||||||
return `composer is "${this.composer.name}" and media_kind is music`
|
return `composer is "${this.composer.name}" and media_kind is music`
|
||||||
|
},
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title: this.composer.name,
|
||||||
|
subtitle: [
|
||||||
|
{ key: 'count.albums', count: this.composer.album_count },
|
||||||
|
{
|
||||||
|
handler: this.open_tracks,
|
||||||
|
key: 'count.tracks',
|
||||||
|
count: this.composer.track_count
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -17,25 +17,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="composer.name" />
|
<heading-title :content="heading" />
|
||||||
<div class="is-size-7 is-uppercase">
|
|
||||||
<a
|
|
||||||
@click="open_albums"
|
|
||||||
v-text="$t('count.albums', { count: composer.album_count })"
|
|
||||||
/>
|
|
||||||
<span> | </span>
|
|
||||||
<span v-text="$t('count.tracks', { count: composer.track_count })" />
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<control-button
|
||||||
<control-button :handler="showDetails" icon="dots-horizontal" />
|
:button="{ handler: showDetails, icon: 'dots-horizontal' }"
|
||||||
<control-button
|
/>
|
||||||
:handler="play"
|
<control-button
|
||||||
icon="shuffle"
|
:button="{
|
||||||
label="page.composer.shuffle"
|
handler: play,
|
||||||
/>
|
icon: 'shuffle',
|
||||||
</div>
|
key: 'page.composer.shuffle'
|
||||||
|
}"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-tracks :items="tracks" :expression="expression" />
|
<list-tracks :items="tracks" :expression="expression" />
|
||||||
@ -54,6 +48,7 @@ import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
|||||||
import ControlButton from '@/components/ControlButton.vue'
|
import ControlButton from '@/components/ControlButton.vue'
|
||||||
import ControlDropdown from '@/components/ControlDropdown.vue'
|
import ControlDropdown from '@/components/ControlDropdown.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import IndexButtonList from '@/components/IndexButtonList.vue'
|
import IndexButtonList from '@/components/IndexButtonList.vue'
|
||||||
import ListTracks from '@/components/ListTracks.vue'
|
import ListTracks from '@/components/ListTracks.vue'
|
||||||
import ModalDialogComposer from '@/components/ModalDialogComposer.vue'
|
import ModalDialogComposer from '@/components/ModalDialogComposer.vue'
|
||||||
@ -80,6 +75,7 @@ export default {
|
|||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
ControlButton,
|
ControlButton,
|
||||||
ControlDropdown,
|
ControlDropdown,
|
||||||
|
HeadingTitle,
|
||||||
IndexButtonList,
|
IndexButtonList,
|
||||||
ListTracks,
|
ListTracks,
|
||||||
ModalDialogComposer
|
ModalDialogComposer
|
||||||
@ -118,6 +114,19 @@ export default {
|
|||||||
expression() {
|
expression() {
|
||||||
return `composer is "${this.composer.name}" and media_kind is music`
|
return `composer is "${this.composer.name}" and media_kind is music`
|
||||||
},
|
},
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title: this.composer.name,
|
||||||
|
subtitle: [
|
||||||
|
{
|
||||||
|
handler: this.open_albums,
|
||||||
|
key: 'count.albums',
|
||||||
|
count: this.composer.album_count
|
||||||
|
},
|
||||||
|
{ key: 'count.tracks', count: composer.track_count }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
tracks() {
|
tracks() {
|
||||||
const { options } = this.groupings.find(
|
const { options } = this.groupings.find(
|
||||||
(grouping) => grouping.id === this.uiStore.composer_tracks_sort
|
(grouping) => grouping.id === this.uiStore.composer_tracks_sort
|
||||||
|
@ -6,11 +6,7 @@
|
|||||||
<index-button-list :indices="composers.indices" />
|
<index-button-list :indices="composers.indices" />
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="$t('page.composers.title')" />
|
<heading-title :content="heading" />
|
||||||
<div
|
|
||||||
class="is-size-7 is-uppercase"
|
|
||||||
v-text="$t('count.composers', { count: composers.total })"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-composers :items="composers" />
|
<list-composers :items="composers" />
|
||||||
@ -22,6 +18,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import IndexButtonList from '@/components/IndexButtonList.vue'
|
import IndexButtonList from '@/components/IndexButtonList.vue'
|
||||||
import ListComposers from '@/components/ListComposers.vue'
|
import ListComposers from '@/components/ListComposers.vue'
|
||||||
import TabsMusic from '@/components/TabsMusic.vue'
|
import TabsMusic from '@/components/TabsMusic.vue'
|
||||||
@ -31,7 +28,6 @@ const dataObject = {
|
|||||||
load(to) {
|
load(to) {
|
||||||
return webapi.library_composers('music')
|
return webapi.library_composers('music')
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.composers = new GroupedList(response.data, {
|
vm.composers = new GroupedList(response.data, {
|
||||||
index: { field: 'name_sort', type: String }
|
index: { field: 'name_sort', type: String }
|
||||||
@ -41,18 +37,30 @@ const dataObject = {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PageComposers',
|
name: 'PageComposers',
|
||||||
components: { ContentWithHeading, IndexButtonList, ListComposers, TabsMusic },
|
components: {
|
||||||
|
ContentWithHeading,
|
||||||
|
HeadingTitle,
|
||||||
|
IndexButtonList,
|
||||||
|
ListComposers,
|
||||||
|
TabsMusic
|
||||||
|
},
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
composers: new GroupedList()
|
composers: new GroupedList()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title: this.$t('page.composers.title'),
|
||||||
|
subtitle: [{ key: 'count.composers', count: this.composers.total }]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -2,13 +2,15 @@
|
|||||||
<div>
|
<div>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="name" />
|
<heading-title :content="{ title: name }" />
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<control-button
|
||||||
<control-button :handler="showDetails" icon="dots-horizontal" />
|
:button="{ handler: showDetails, icon: 'dots-horizontal' }"
|
||||||
<control-button :handler="play" icon="play" label="page.files.play" />
|
/>
|
||||||
</div>
|
<control-button
|
||||||
|
:button="{ handler: play, icon: 'play', key: 'page.files.play' }"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-directories :items="directories" />
|
<list-directories :items="directories" />
|
||||||
@ -32,6 +34,7 @@
|
|||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import ControlButton from '@/components/ControlButton.vue'
|
import ControlButton from '@/components/ControlButton.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import ListDirectories from '@/components/ListDirectories.vue'
|
import ListDirectories from '@/components/ListDirectories.vue'
|
||||||
import ListPlaylists from '@/components/ListPlaylists.vue'
|
import ListPlaylists from '@/components/ListPlaylists.vue'
|
||||||
import ListTracks from '@/components/ListTracks.vue'
|
import ListTracks from '@/components/ListTracks.vue'
|
||||||
@ -72,6 +75,7 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
ControlButton,
|
ControlButton,
|
||||||
|
HeadingTitle,
|
||||||
ListDirectories,
|
ListDirectories,
|
||||||
ListPlaylists,
|
ListPlaylists,
|
||||||
ListTracks,
|
ListTracks,
|
||||||
@ -105,14 +109,14 @@ export default {
|
|||||||
current() {
|
current() {
|
||||||
return this.$route.query?.directory || '/'
|
return this.$route.query?.directory || '/'
|
||||||
},
|
},
|
||||||
|
expression() {
|
||||||
|
return `path starts with "${this.current}" order by path asc`
|
||||||
|
},
|
||||||
name() {
|
name() {
|
||||||
if (this.current !== '/') {
|
if (this.current !== '/') {
|
||||||
return this.current?.slice(this.current.lastIndexOf('/') + 1)
|
return this.current?.slice(this.current.lastIndexOf('/') + 1)
|
||||||
}
|
}
|
||||||
return this.$t('page.files.title')
|
return this.$t('page.files.title')
|
||||||
},
|
|
||||||
expression() {
|
|
||||||
return `path starts with "${this.current}" order by path asc`
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -5,25 +5,19 @@
|
|||||||
<index-button-list :indices="albums.indices" />
|
<index-button-list :indices="albums.indices" />
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="genre.name" />
|
<heading-title :content="heading" />
|
||||||
<div class="is-size-7 is-uppercase">
|
|
||||||
<span v-text="$t('count.albums', { count: genre.album_count })" />
|
|
||||||
<span> | </span>
|
|
||||||
<a
|
|
||||||
@click="open_tracks"
|
|
||||||
v-text="$t('count.tracks', { count: genre.track_count })"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<control-button
|
||||||
<control-button :handler="showDetails" icon="dots-horizontal" />
|
:button="{ handler: showDetails, icon: 'dots-horizontal' }"
|
||||||
<control-button
|
/>
|
||||||
:handler="play"
|
<control-button
|
||||||
icon="shuffle"
|
:button="{
|
||||||
label="page.genre.shuffle"
|
handler: play,
|
||||||
/>
|
icon: 'shuffle',
|
||||||
</div>
|
key: 'page.genre.shuffle'
|
||||||
|
}"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-albums :items="albums" />
|
<list-albums :items="albums" />
|
||||||
@ -42,6 +36,7 @@
|
|||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import ControlButton from '@/components/ControlButton.vue'
|
import ControlButton from '@/components/ControlButton.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import IndexButtonList from '@/components/IndexButtonList.vue'
|
import IndexButtonList from '@/components/IndexButtonList.vue'
|
||||||
import ListAlbums from '@/components/ListAlbums.vue'
|
import ListAlbums from '@/components/ListAlbums.vue'
|
||||||
import ModalDialogGenre from '@/components/ModalDialogGenre.vue'
|
import ModalDialogGenre from '@/components/ModalDialogGenre.vue'
|
||||||
@ -67,6 +62,7 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
ControlButton,
|
ControlButton,
|
||||||
|
HeadingTitle,
|
||||||
IndexButtonList,
|
IndexButtonList,
|
||||||
ListAlbums,
|
ListAlbums,
|
||||||
ModalDialogGenre
|
ModalDialogGenre
|
||||||
@ -84,6 +80,21 @@ export default {
|
|||||||
show_details_modal: false
|
show_details_modal: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title: this.genre.name,
|
||||||
|
subtitle: [
|
||||||
|
{ key: 'count.albums', count: this.genre.album_count },
|
||||||
|
{
|
||||||
|
handler: this.open_tracks,
|
||||||
|
key: 'count.tracks',
|
||||||
|
count: this.genre.track_count
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
open_tracks() {
|
open_tracks() {
|
||||||
this.show_details_modal = false
|
this.show_details_modal = false
|
||||||
|
@ -17,25 +17,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="genre.name" />
|
<heading-title :content="heading" />
|
||||||
<div class="is-size-7 is-uppercase">
|
|
||||||
<a
|
|
||||||
@click="open_genre"
|
|
||||||
v-text="$t('count.albums', { count: genre.album_count })"
|
|
||||||
/>
|
|
||||||
<span> | </span>
|
|
||||||
<span v-text="$t('count.tracks', { count: genre.track_count })" />
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<control-button
|
||||||
<control-button :handler="showDetails" icon="dots-horizontal" />
|
:button="{ handler: showDetails, icon: 'dots-horizontal' }"
|
||||||
<control-button
|
/>
|
||||||
:handler="play"
|
<control-button
|
||||||
icon="shuffle"
|
:button="{
|
||||||
label="page.genre.shuffle"
|
handler: play,
|
||||||
/>
|
icon: 'shuffle',
|
||||||
</div>
|
key: 'page.genre.shuffle'
|
||||||
|
}"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-tracks :items="tracks" :expression="expression" />
|
<list-tracks :items="tracks" :expression="expression" />
|
||||||
@ -55,6 +49,7 @@ import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
|||||||
import ControlButton from '@/components/ControlButton.vue'
|
import ControlButton from '@/components/ControlButton.vue'
|
||||||
import ControlDropdown from '@/components/ControlDropdown.vue'
|
import ControlDropdown from '@/components/ControlDropdown.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import IndexButtonList from '@/components/IndexButtonList.vue'
|
import IndexButtonList from '@/components/IndexButtonList.vue'
|
||||||
import ListTracks from '@/components/ListTracks.vue'
|
import ListTracks from '@/components/ListTracks.vue'
|
||||||
import ModalDialogGenre from '@/components/ModalDialogGenre.vue'
|
import ModalDialogGenre from '@/components/ModalDialogGenre.vue'
|
||||||
@ -68,7 +63,6 @@ const dataObject = {
|
|||||||
webapi.library_genre_tracks(to.params.name, to.query.media_kind)
|
webapi.library_genre_tracks(to.params.name, to.query.media_kind)
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.genre = response[0].data.genres.items.shift()
|
vm.genre = response[0].data.genres.items.shift()
|
||||||
vm.tracks_list = new GroupedList(response[1].data.tracks)
|
vm.tracks_list = new GroupedList(response[1].data.tracks)
|
||||||
@ -81,6 +75,7 @@ export default {
|
|||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
ControlButton,
|
ControlButton,
|
||||||
ControlDropdown,
|
ControlDropdown,
|
||||||
|
HeadingTitle,
|
||||||
IndexButtonList,
|
IndexButtonList,
|
||||||
ListTracks,
|
ListTracks,
|
||||||
ModalDialogGenre
|
ModalDialogGenre
|
||||||
@ -120,6 +115,19 @@ export default {
|
|||||||
expression() {
|
expression() {
|
||||||
return `genre is "${this.genre.name}" and media_kind is ${this.media_kind}`
|
return `genre is "${this.genre.name}" and media_kind is ${this.media_kind}`
|
||||||
},
|
},
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title: this.genre.name,
|
||||||
|
subtitle: [
|
||||||
|
{
|
||||||
|
handler: this.openGenre,
|
||||||
|
key: 'count.albums',
|
||||||
|
count: this.genre.album_count
|
||||||
|
},
|
||||||
|
{ key: 'count.tracks', count: this.genre.track_count }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
tracks() {
|
tracks() {
|
||||||
const { options } = this.groupings.find(
|
const { options } = this.groupings.find(
|
||||||
(grouping) => grouping.id === this.uiStore.genre_tracks_sort
|
(grouping) => grouping.id === this.uiStore.genre_tracks_sort
|
||||||
@ -128,7 +136,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
open_genre() {
|
openGenre() {
|
||||||
this.show_details_modal = false
|
this.show_details_modal = false
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: 'genre-albums',
|
name: 'genre-albums',
|
||||||
|
@ -6,11 +6,7 @@
|
|||||||
<index-button-list :indices="genres.indices" />
|
<index-button-list :indices="genres.indices" />
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="$t('page.genres.title')" />
|
<heading-title :content="heading" />
|
||||||
<div
|
|
||||||
class="is-size-7 is-uppercase"
|
|
||||||
v-text="$t('count.genres', { count: genres.total })"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-genres :items="genres" :media_kind="'music'" />
|
<list-genres :items="genres" :media_kind="'music'" />
|
||||||
@ -22,6 +18,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import IndexButtonList from '@/components/IndexButtonList.vue'
|
import IndexButtonList from '@/components/IndexButtonList.vue'
|
||||||
import ListGenres from '@/components/ListGenres.vue'
|
import ListGenres from '@/components/ListGenres.vue'
|
||||||
import TabsMusic from '@/components/TabsMusic.vue'
|
import TabsMusic from '@/components/TabsMusic.vue'
|
||||||
@ -31,7 +28,6 @@ const dataObject = {
|
|||||||
load(to) {
|
load(to) {
|
||||||
return webapi.library_genres('music')
|
return webapi.library_genres('music')
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.genres = new GroupedList(response.data.genres, {
|
vm.genres = new GroupedList(response.data.genres, {
|
||||||
index: { field: 'name_sort', type: String }
|
index: { field: 'name_sort', type: String }
|
||||||
@ -43,21 +39,28 @@ export default {
|
|||||||
name: 'PageGenres',
|
name: 'PageGenres',
|
||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
|
HeadingTitle,
|
||||||
IndexButtonList,
|
IndexButtonList,
|
||||||
ListGenres,
|
ListGenres,
|
||||||
TabsMusic
|
TabsMusic
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
genres: new GroupedList()
|
genres: new GroupedList()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title: this.$t('page.genres.title'),
|
||||||
|
subtitle: [{ key: 'count.genres', count: this.genres.total }]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -3,42 +3,38 @@
|
|||||||
<tabs-music />
|
<tabs-music />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t('page.music.recently-added.title')" />
|
<heading-title
|
||||||
|
:content="{ title: $t('page.music.recently-added.title') }"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-albums :items="albums" />
|
<list-albums :items="albums" />
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<nav class="level">
|
<router-link
|
||||||
<p class="level-item">
|
class="button is-small is-rounded"
|
||||||
<router-link
|
:to="{ name: 'music-recently-added' }"
|
||||||
class="button is-small is-rounded"
|
>
|
||||||
:to="{ name: 'music-recently-added' }"
|
{{ $t('page.music.show-more') }}
|
||||||
>
|
</router-link>
|
||||||
{{ $t('page.music.show-more') }}
|
|
||||||
</router-link>
|
|
||||||
</p>
|
|
||||||
</nav>
|
|
||||||
</template>
|
</template>
|
||||||
</content-with-heading>
|
</content-with-heading>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t('page.music.recently-played.title')" />
|
<heading-title
|
||||||
|
:content="{ title: $t('page.music.recently-played.title') }"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-tracks :items="tracks" />
|
<list-tracks :items="tracks" />
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<nav class="level">
|
<router-link
|
||||||
<p class="level-item">
|
class="button is-small is-rounded"
|
||||||
<router-link
|
:to="{ name: 'music-recently-played' }"
|
||||||
class="button is-small is-rounded"
|
>
|
||||||
:to="{ name: 'music-recently-played' }"
|
{{ $t('page.music.show-more') }}
|
||||||
>
|
</router-link>
|
||||||
{{ $t('page.music.show-more') }}
|
|
||||||
</router-link>
|
|
||||||
</p>
|
|
||||||
</nav>
|
|
||||||
</template>
|
</template>
|
||||||
</content-with-heading>
|
</content-with-heading>
|
||||||
</div>
|
</div>
|
||||||
@ -47,6 +43,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import ListAlbums from '@/components/ListAlbums.vue'
|
import ListAlbums from '@/components/ListAlbums.vue'
|
||||||
import ListTracks from '@/components/ListTracks.vue'
|
import ListTracks from '@/components/ListTracks.vue'
|
||||||
import TabsMusic from '@/components/TabsMusic.vue'
|
import TabsMusic from '@/components/TabsMusic.vue'
|
||||||
@ -69,7 +66,6 @@ const dataObject = {
|
|||||||
})
|
})
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.albums = new GroupedList(response[0].data.albums)
|
vm.albums = new GroupedList(response[0].data.albums)
|
||||||
vm.tracks = new GroupedList(response[1].data.tracks)
|
vm.tracks = new GroupedList(response[1].data.tracks)
|
||||||
@ -78,14 +74,18 @@ const dataObject = {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PageMusic',
|
name: 'PageMusic',
|
||||||
components: { ContentWithHeading, ListAlbums, ListTracks, TabsMusic },
|
components: {
|
||||||
|
ContentWithHeading,
|
||||||
|
HeadingTitle,
|
||||||
|
ListAlbums,
|
||||||
|
ListTracks,
|
||||||
|
TabsMusic
|
||||||
|
},
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
albums: [],
|
albums: [],
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
<tabs-music />
|
<tabs-music />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t('page.music.recently-added.title')" />
|
<heading-title
|
||||||
|
:content="{ title: $t('page.music.recently-added.title') }"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-albums :items="albums" />
|
<list-albums :items="albums" />
|
||||||
@ -15,6 +17,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import ListAlbums from '@/components/ListAlbums.vue'
|
import ListAlbums from '@/components/ListAlbums.vue'
|
||||||
import TabsMusic from '@/components/TabsMusic.vue'
|
import TabsMusic from '@/components/TabsMusic.vue'
|
||||||
import { useSettingsStore } from '@/stores/settings'
|
import { useSettingsStore } from '@/stores/settings'
|
||||||
@ -30,7 +33,6 @@ const dataObject = {
|
|||||||
type: 'album'
|
type: 'album'
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.albums = new GroupedList(response.data.albums, {
|
vm.albums = new GroupedList(response.data.albums, {
|
||||||
criteria: [{ field: 'time_added', order: -1, type: Date }],
|
criteria: [{ field: 'time_added', order: -1, type: Date }],
|
||||||
@ -41,20 +43,17 @@ const dataObject = {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PageMusicRecentlyAdded',
|
name: 'PageMusicRecentlyAdded',
|
||||||
components: { ContentWithHeading, ListAlbums, TabsMusic },
|
components: { ContentWithHeading, HeadingTitle, ListAlbums, TabsMusic },
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
settingsStore: useSettingsStore()
|
settingsStore: useSettingsStore()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
albums: new GroupedList()
|
albums: new GroupedList()
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
<tabs-music />
|
<tabs-music />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t('page.music.recently-played.title')" />
|
<heading-title
|
||||||
|
:content="{ title: $t('page.music.recently-played.title') }"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-tracks :items="tracks" />
|
<list-tracks :items="tracks" />
|
||||||
@ -15,6 +17,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import ListTracks from '@/components/ListTracks.vue'
|
import ListTracks from '@/components/ListTracks.vue'
|
||||||
import TabsMusic from '@/components/TabsMusic.vue'
|
import TabsMusic from '@/components/TabsMusic.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
@ -28,7 +31,6 @@ const dataObject = {
|
|||||||
type: 'track'
|
type: 'track'
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.tracks = new GroupedList(response.data.tracks)
|
vm.tracks = new GroupedList(response.data.tracks)
|
||||||
}
|
}
|
||||||
@ -36,14 +38,12 @@ const dataObject = {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PageMusicRecentlyPlayed',
|
name: 'PageMusicRecentlyPlayed',
|
||||||
components: { ContentWithHeading, ListTracks, TabsMusic },
|
components: { ContentWithHeading, HeadingTitle, ListTracks, TabsMusic },
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tracks: {}
|
tracks: {}
|
||||||
|
@ -3,45 +3,38 @@
|
|||||||
<tabs-music />
|
<tabs-music />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t('page.spotify.music.new-releases')" />
|
<heading-title
|
||||||
|
:content="{ title: $t('page.spotify.music.new-releases') }"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-albums-spotify :items="albums" />
|
<list-albums-spotify :items="albums" />
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<nav class="level">
|
<router-link
|
||||||
<p class="level-item">
|
:to="{ name: 'music-spotify-new-releases' }"
|
||||||
<router-link
|
class="button is-small is-rounded"
|
||||||
:to="{ name: 'music-spotify-new-releases' }"
|
>
|
||||||
class="button is-small is-rounded"
|
{{ $t('page.spotify.music.show-more') }}
|
||||||
>
|
</router-link>
|
||||||
{{ $t('page.spotify.music.show-more') }}
|
|
||||||
</router-link>
|
|
||||||
</p>
|
|
||||||
</nav>
|
|
||||||
</template>
|
</template>
|
||||||
</content-with-heading>
|
</content-with-heading>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p
|
<heading-title
|
||||||
class="title is-4"
|
:content="{ title: $t('page.spotify.music.featured-playlists') }"
|
||||||
v-text="$t('page.spotify.music.featured-playlists')"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-playlists-spotify :items="playlists" />
|
<list-playlists-spotify :items="playlists" />
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<nav class="level">
|
<router-link
|
||||||
<p class="level-item">
|
:to="{ name: 'music-spotify-featured-playlists' }"
|
||||||
<router-link
|
class="button is-small is-rounded"
|
||||||
:to="{ name: 'music-spotify-featured-playlists' }"
|
>
|
||||||
class="button is-small is-rounded"
|
{{ $t('page.spotify.music.show-more') }}
|
||||||
>
|
</router-link>
|
||||||
{{ $t('page.spotify.music.show-more') }}
|
|
||||||
</router-link>
|
|
||||||
</p>
|
|
||||||
</nav>
|
|
||||||
</template>
|
</template>
|
||||||
</content-with-heading>
|
</content-with-heading>
|
||||||
</div>
|
</div>
|
||||||
@ -49,6 +42,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import ListAlbumsSpotify from '@/components/ListAlbumsSpotify.vue'
|
import ListAlbumsSpotify from '@/components/ListAlbumsSpotify.vue'
|
||||||
import ListPlaylistsSpotify from '@/components/ListPlaylistsSpotify.vue'
|
import ListPlaylistsSpotify from '@/components/ListPlaylistsSpotify.vue'
|
||||||
import SpotifyWebApi from 'spotify-web-api-js'
|
import SpotifyWebApi from 'spotify-web-api-js'
|
||||||
@ -72,7 +66,6 @@ const dataObject = {
|
|||||||
])
|
])
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.albums = response[0].albums.items
|
vm.albums = response[0].albums.items
|
||||||
vm.playlists = response[1].playlists.items
|
vm.playlists = response[1].playlists.items
|
||||||
@ -83,17 +76,16 @@ export default {
|
|||||||
name: 'PageMusicSpotify',
|
name: 'PageMusicSpotify',
|
||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
|
HeadingTitle,
|
||||||
ListAlbumsSpotify,
|
ListAlbumsSpotify,
|
||||||
ListPlaylistsSpotify,
|
ListPlaylistsSpotify,
|
||||||
TabsMusic
|
TabsMusic
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
playlists: [],
|
playlists: [],
|
||||||
|
@ -3,10 +3,7 @@
|
|||||||
<tabs-music />
|
<tabs-music />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p
|
<heading-title :content="heading" />
|
||||||
class="title is-4"
|
|
||||||
v-text="$t('page.spotify.music.featured-playlists')"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-playlists-spotify :items="playlists" />
|
<list-playlists-spotify :items="playlists" />
|
||||||
@ -17,6 +14,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import ListPlaylistsSpotify from '@/components/ListPlaylistsSpotify.vue'
|
import ListPlaylistsSpotify from '@/components/ListPlaylistsSpotify.vue'
|
||||||
import SpotifyWebApi from 'spotify-web-api-js'
|
import SpotifyWebApi from 'spotify-web-api-js'
|
||||||
import TabsMusic from '@/components/TabsMusic.vue'
|
import TabsMusic from '@/components/TabsMusic.vue'
|
||||||
@ -33,7 +31,6 @@ const dataObject = {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.playlists = response.playlists.items
|
vm.playlists = response.playlists.items
|
||||||
}
|
}
|
||||||
@ -43,20 +40,24 @@ export default {
|
|||||||
name: 'PageMusicSpotifyFeaturedPlaylists',
|
name: 'PageMusicSpotifyFeaturedPlaylists',
|
||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
|
HeadingTitle,
|
||||||
ListPlaylistsSpotify,
|
ListPlaylistsSpotify,
|
||||||
TabsMusic
|
TabsMusic
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
playlists: []
|
playlists: []
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
heading() {
|
||||||
|
return { title: this.$t('page.spotify.music.featured-playlists') }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<tabs-music />
|
<tabs-music />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t('page.spotify.music.new-releases')" />
|
<heading-title :content="heading" />
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-albums-spotify :items="albums" />
|
<list-albums-spotify :items="albums" />
|
||||||
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import ListAlbumsSpotify from '@/components/ListAlbumsSpotify.vue'
|
import ListAlbumsSpotify from '@/components/ListAlbumsSpotify.vue'
|
||||||
import SpotifyWebApi from 'spotify-web-api-js'
|
import SpotifyWebApi from 'spotify-web-api-js'
|
||||||
import TabsMusic from '@/components/TabsMusic.vue'
|
import TabsMusic from '@/components/TabsMusic.vue'
|
||||||
@ -30,7 +31,6 @@ const dataObject = {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.albums = response.albums.items
|
vm.albums = response.albums.items
|
||||||
}
|
}
|
||||||
@ -40,20 +40,24 @@ export default {
|
|||||||
name: 'PageMusicSpotifyNewReleases',
|
name: 'PageMusicSpotifyNewReleases',
|
||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
|
HeadingTitle,
|
||||||
ListAlbumsSpotify,
|
ListAlbumsSpotify,
|
||||||
TabsMusic
|
TabsMusic
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
albums: []
|
albums: []
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
heading() {
|
||||||
|
return { title: this.$t('page.spotify.music.new-releases') }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -2,16 +2,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div
|
<heading-title :content="heading" />
|
||||||
class="title is-4"
|
|
||||||
v-text="
|
|
||||||
playlist.id === 0 ? $t('page.playlists.title') : playlist.name
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
class="is-size-7 is-uppercase"
|
|
||||||
v-text="$t('count.playlists', { count: playlists.count })"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-playlists :items="playlists" />
|
<list-playlists :items="playlists" />
|
||||||
@ -23,6 +14,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import ListPlaylists from '@/components/ListPlaylists.vue'
|
import ListPlaylists from '@/components/ListPlaylists.vue'
|
||||||
import { useConfigurationStore } from '@/stores/configuration'
|
import { useConfigurationStore } from '@/stores/configuration'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
@ -34,7 +26,6 @@ const dataObject = {
|
|||||||
webapi.library_playlist_folder(to.params.id)
|
webapi.library_playlist_folder(to.params.id)
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.playlist = response[0].data
|
vm.playlist = response[0].data
|
||||||
vm.playlists_list = new GroupedList(response[1].data)
|
vm.playlists_list = new GroupedList(response[1].data)
|
||||||
@ -43,35 +34,39 @@ const dataObject = {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PagePlaylistFolder',
|
name: 'PagePlaylistFolder',
|
||||||
components: { ContentWithHeading, ListPlaylists },
|
components: { ContentWithHeading, ListPlaylists, HeadingTitle },
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeRouteUpdate(to, from, next) {
|
beforeRouteUpdate(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
dataObject.set(this, response)
|
dataObject.set(this, response)
|
||||||
next()
|
next()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
configurationStore: useConfigurationStore()
|
configurationStore: useConfigurationStore()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
playlist: {},
|
playlist: {},
|
||||||
playlists_list: new GroupedList()
|
playlists_list: new GroupedList()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title:
|
||||||
|
this.playlists.count === 0
|
||||||
|
? this.$t('page.playlists.title')
|
||||||
|
: this.playlist.name,
|
||||||
|
subtitle: [{ key: 'count.playlists', count: this.playlists.count }]
|
||||||
|
}
|
||||||
|
},
|
||||||
playlists() {
|
playlists() {
|
||||||
return this.playlists_list.group({
|
return this.playlists_list.group({
|
||||||
filters: [
|
filters: [
|
||||||
|
@ -2,22 +2,20 @@
|
|||||||
<div>
|
<div>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="playlist.name" />
|
<heading-title :content="heading" />
|
||||||
<div
|
|
||||||
class="is-size-7 is-uppercase"
|
|
||||||
v-text="$t('count.tracks', { count: tracks.count })"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<control-button
|
||||||
<control-button :handler="showDetails" icon="dots-horizontal" />
|
:button="{ handler: showDetails, icon: 'dots-horizontal' }"
|
||||||
<control-button
|
/>
|
||||||
:disabled="tracks.count === 0"
|
<control-button
|
||||||
:handler="play"
|
:button="{
|
||||||
icon="shuffle"
|
handler: play,
|
||||||
label="page.playlist.shuffle"
|
icon: 'shuffle',
|
||||||
/>
|
key: 'page.playlist.shuffle',
|
||||||
</div>
|
disabled: tracks.count === 0
|
||||||
|
}"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-tracks :items="tracks" :uris="uris" />
|
<list-tracks :items="tracks" :uris="uris" />
|
||||||
@ -36,6 +34,7 @@
|
|||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import ControlButton from '@/components/ControlButton.vue'
|
import ControlButton from '@/components/ControlButton.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import ListTracks from '@/components/ListTracks.vue'
|
import ListTracks from '@/components/ListTracks.vue'
|
||||||
import ModalDialogPlaylist from '@/components/ModalDialogPlaylist.vue'
|
import ModalDialogPlaylist from '@/components/ModalDialogPlaylist.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
@ -47,7 +46,6 @@ const dataObject = {
|
|||||||
webapi.library_playlist_tracks(to.params.id)
|
webapi.library_playlist_tracks(to.params.id)
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.playlist = response[0].data
|
vm.playlist = response[0].data
|
||||||
vm.tracks = new GroupedList(response[1].data)
|
vm.tracks = new GroupedList(response[1].data)
|
||||||
@ -59,16 +57,15 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
ControlButton,
|
ControlButton,
|
||||||
|
HeadingTitle,
|
||||||
ListTracks,
|
ListTracks,
|
||||||
ModalDialogPlaylist
|
ModalDialogPlaylist
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
playlist: {},
|
playlist: {},
|
||||||
@ -76,8 +73,13 @@ export default {
|
|||||||
tracks: new GroupedList()
|
tracks: new GroupedList()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title: this.playlist.name,
|
||||||
|
subtitle: [{ key: 'count.tracks', count: this.tracks.count }]
|
||||||
|
}
|
||||||
|
},
|
||||||
uris() {
|
uris() {
|
||||||
if (this.playlist.random) {
|
if (this.playlist.random) {
|
||||||
return this.tracks.map((item) => item.uri).join()
|
return this.tracks.map((item) => item.uri).join()
|
||||||
@ -85,7 +87,6 @@ export default {
|
|||||||
return this.playlist.uri
|
return this.playlist.uri
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
play() {
|
play() {
|
||||||
webapi.player_play_uri(this.uris, true)
|
webapi.player_play_uri(this.uris, true)
|
||||||
|
@ -2,22 +2,20 @@
|
|||||||
<div>
|
<div>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="playlist.name" />
|
<heading-title :content="heading" />
|
||||||
<div
|
|
||||||
class="is-size-7 is-uppercase"
|
|
||||||
v-text="$t('count.playlists', { count: playlist.tracks.total })"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<control-button
|
||||||
<control-button :handler="showDetails" icon="dots-horizontal" />
|
:button="{ handler: showDetails, icon: 'dots-horizontal' }"
|
||||||
<control-button
|
/>
|
||||||
:disabled="playlist.tracks.total === 0"
|
<control-button
|
||||||
:handler="play"
|
:button="{
|
||||||
icon="shuffle"
|
handler: play,
|
||||||
label="page.spotify.playlist.shuffle"
|
icon: 'shuffle',
|
||||||
/>
|
key: 'page.spotify.playlist.shuffle',
|
||||||
</div>
|
disabled: playlist.tracks.total === 0
|
||||||
|
}"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-tracks-spotify :items="tracks" :context_uri="playlist.uri" />
|
<list-tracks-spotify :items="tracks" :context_uri="playlist.uri" />
|
||||||
@ -46,6 +44,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import ControlButton from '@/components/ControlButton.vue'
|
import ControlButton from '@/components/ControlButton.vue'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import ListTracksSpotify from '@/components/ListTracksSpotify.vue'
|
import ListTracksSpotify from '@/components/ListTracksSpotify.vue'
|
||||||
import ModalDialogPlaylistSpotify from '@/components/ModalDialogPlaylistSpotify.vue'
|
import ModalDialogPlaylistSpotify from '@/components/ModalDialogPlaylistSpotify.vue'
|
||||||
import SpotifyWebApi from 'spotify-web-api-js'
|
import SpotifyWebApi from 'spotify-web-api-js'
|
||||||
@ -68,7 +67,6 @@ const dataObject = {
|
|||||||
})
|
})
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.playlist = response.shift()
|
vm.playlist = response.shift()
|
||||||
vm.tracks = []
|
vm.tracks = []
|
||||||
@ -85,19 +83,17 @@ export default {
|
|||||||
ControlButton,
|
ControlButton,
|
||||||
ListTracksSpotify,
|
ListTracksSpotify,
|
||||||
ModalDialogPlaylistSpotify,
|
ModalDialogPlaylistSpotify,
|
||||||
|
HeadingTitle,
|
||||||
VueEternalLoading
|
VueEternalLoading
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return { servicesStore: useServicesStore() }
|
return { servicesStore: useServicesStore() }
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
offset: 0,
|
offset: 0,
|
||||||
@ -107,7 +103,16 @@ export default {
|
|||||||
tracks: []
|
tracks: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title: this.playlist.name,
|
||||||
|
subtitle: [
|
||||||
|
{ key: 'count.playlists', count: this.playlist.tracks.total }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
append_tracks(data) {
|
append_tracks(data) {
|
||||||
let position = Math.max(
|
let position = Math.max(
|
||||||
|
@ -12,11 +12,11 @@
|
|||||||
/>
|
/>
|
||||||
<div class="buttons is-centered-mobile mt-5">
|
<div class="buttons is-centered-mobile mt-5">
|
||||||
<control-button
|
<control-button
|
||||||
:handler="play"
|
:button="{ handler: play, icon: 'play', key: 'page.podcast.play' }"
|
||||||
icon="play"
|
/>
|
||||||
label="page.podcast.play"
|
<control-button
|
||||||
|
:button="{ handler: showDetails, icon: 'dots-horizontal' }"
|
||||||
/>
|
/>
|
||||||
<control-button :handler="showDetails" icon="dots-horizontal" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
@ -119,12 +119,12 @@ export default {
|
|||||||
actions() {
|
actions() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: this.$t('page.podcast.cancel'),
|
key: this.$t('page.podcast.cancel'),
|
||||||
handler: 'cancel',
|
handler: 'cancel',
|
||||||
icon: 'cancel'
|
icon: 'cancel'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: this.$t('page.podcast.remove'),
|
key: this.$t('page.podcast.remove'),
|
||||||
handler: 'remove',
|
handler: 'remove',
|
||||||
icon: 'delete'
|
icon: 'delete'
|
||||||
}
|
}
|
||||||
|
@ -2,58 +2,56 @@
|
|||||||
<div>
|
<div>
|
||||||
<content-with-heading v-if="tracks.items.length > 0">
|
<content-with-heading v-if="tracks.items.length > 0">
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t('page.podcasts.new-episodes')" />
|
<heading-title :content="{ title: $t('page.podcasts.new-episodes') }" />
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<control-button
|
||||||
<control-button
|
:button="{
|
||||||
:handler="mark_all_played"
|
handler: markAllAsPlayed,
|
||||||
icon="pencil"
|
icon: 'pencil',
|
||||||
label="page.podcasts.mark-all-played"
|
key: 'page.podcasts.mark-all-played'
|
||||||
/>
|
}"
|
||||||
</div>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-tracks
|
<list-tracks
|
||||||
:items="tracks"
|
:items="tracks"
|
||||||
:show_progress="true"
|
:show_progress="true"
|
||||||
@play-count-changed="reload_new_episodes"
|
@play-count-changed="reloadNewEpisodes"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</content-with-heading>
|
</content-with-heading>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="$t('page.podcasts.title')" />
|
<heading-title :content="heading" />
|
||||||
<div
|
|
||||||
class="is-size-7 is-uppercase"
|
|
||||||
v-text="$t('count.podcasts', { count: albums.total })"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<control-button
|
||||||
<control-button
|
v-if="rss.tracks > 0"
|
||||||
v-if="rss.tracks > 0"
|
:button="{
|
||||||
:handler="update_rss"
|
handler: updateRss,
|
||||||
icon="refresh"
|
icon: 'refresh',
|
||||||
label="page.podcasts.update"
|
key: 'page.podcasts.update'
|
||||||
/>
|
}"
|
||||||
<control-button
|
/>
|
||||||
:handler="open_add_podcast_dialog"
|
<control-button
|
||||||
icon="rss"
|
:button="{
|
||||||
label="page.podcasts.add"
|
handler: 'openAddPodcastDialog',
|
||||||
/>
|
icon: 'rss',
|
||||||
</div>
|
key: 'page.podcasts.add'
|
||||||
|
}"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-albums
|
<list-albums
|
||||||
:items="albums"
|
:items="albums"
|
||||||
@play-count-changed="reload_new_episodes()"
|
@play-count-changed="reloadNewEpisodes()"
|
||||||
@podcast-deleted="reload_podcasts()"
|
@podcast-deleted="reloadPodcasts()"
|
||||||
/>
|
/>
|
||||||
<modal-dialog-add-rss
|
<modal-dialog-add-rss
|
||||||
:show="show_url_modal"
|
:show="show_url_modal"
|
||||||
@close="show_url_modal = false"
|
@close="show_url_modal = false"
|
||||||
@podcast-added="reload_podcasts()"
|
@podcast-added="reloadPodcasts()"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</content-with-heading>
|
</content-with-heading>
|
||||||
@ -64,6 +62,7 @@
|
|||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import ControlButton from '@/components/ControlButton.vue'
|
import ControlButton from '@/components/ControlButton.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import ListAlbums from '@/components/ListAlbums.vue'
|
import ListAlbums from '@/components/ListAlbums.vue'
|
||||||
import ListTracks from '@/components/ListTracks.vue'
|
import ListTracks from '@/components/ListTracks.vue'
|
||||||
import ModalDialogAddRss from '@/components/ModalDialogAddRss.vue'
|
import ModalDialogAddRss from '@/components/ModalDialogAddRss.vue'
|
||||||
@ -78,7 +77,6 @@ const dataObject = {
|
|||||||
webapi.library_podcasts_new_episodes()
|
webapi.library_podcasts_new_episodes()
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.albums = new GroupedList(response[0].data)
|
vm.albums = new GroupedList(response[0].data)
|
||||||
vm.tracks = new GroupedList(response[1].data.tracks)
|
vm.tracks = new GroupedList(response[1].data.tracks)
|
||||||
@ -90,21 +88,19 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
ControlButton,
|
ControlButton,
|
||||||
|
HeadingTitle,
|
||||||
ListAlbums,
|
ListAlbums,
|
||||||
ListTracks,
|
ListTracks,
|
||||||
ModalDialogAddRss
|
ModalDialogAddRss
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return { libraryStore: useLibraryStore(), uiStore: useUIStore() }
|
return { libraryStore: useLibraryStore(), uiStore: useUIStore() }
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
albums: [],
|
albums: [],
|
||||||
@ -112,39 +108,42 @@ export default {
|
|||||||
show_url_modal: false
|
show_url_modal: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
heading() {
|
||||||
|
if (this.albums.total) {
|
||||||
|
return {
|
||||||
|
title: this.$t('page.podcasts.title'),
|
||||||
|
subtitle: [{ key: 'count.podcasts', count: this.albums.count }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
},
|
||||||
rss() {
|
rss() {
|
||||||
return this.libraryStore.rss
|
return this.libraryStore.rss
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
mark_all_played() {
|
markAllAsPlayed() {
|
||||||
this.tracks.items.forEach((ep) => {
|
this.tracks.items.forEach((ep) => {
|
||||||
webapi.library_track_update(ep.id, { play_count: 'increment' })
|
webapi.library_track_update(ep.id, { play_count: 'increment' })
|
||||||
})
|
})
|
||||||
this.tracks.items = {}
|
this.tracks.items = {}
|
||||||
},
|
},
|
||||||
|
openAddPodcastDialog() {
|
||||||
open_add_podcast_dialog() {
|
|
||||||
this.show_url_modal = true
|
this.show_url_modal = true
|
||||||
},
|
},
|
||||||
|
reloadNewEpisodes() {
|
||||||
reload_new_episodes() {
|
|
||||||
webapi.library_podcasts_new_episodes().then(({ data }) => {
|
webapi.library_podcasts_new_episodes().then(({ data }) => {
|
||||||
this.tracks = new GroupedList(data.tracks)
|
this.tracks = new GroupedList(data.tracks)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
reloadPodcasts() {
|
||||||
reload_podcasts() {
|
|
||||||
webapi.library_albums('podcast').then(({ data }) => {
|
webapi.library_albums('podcast').then(({ data }) => {
|
||||||
this.albums = new GroupedList(data)
|
this.albums = new GroupedList(data)
|
||||||
this.reload_new_episodes()
|
this.reloadNewEpisodes()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
updateRss() {
|
||||||
update_rss() {
|
|
||||||
this.libraryStore.update_dialog_scan_kind = 'rss'
|
this.libraryStore.update_dialog_scan_kind = 'rss'
|
||||||
this.uiStore.show_update_dialog = true
|
this.uiStore.show_update_dialog = true
|
||||||
}
|
}
|
||||||
|
@ -2,46 +2,50 @@
|
|||||||
<div>
|
<div>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="$t('page.queue.title')" />
|
<heading-title :content="heading" />
|
||||||
<div
|
|
||||||
class="is-size-7 is-uppercase"
|
|
||||||
v-text="$t('count.tracks', { count: queue.count })"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<control-button
|
||||||
<control-button
|
:button="{
|
||||||
:handler="update_show_next_items"
|
handler: update_show_next_items,
|
||||||
:class="{ 'is-dark': show_only_next_items }"
|
icon: 'eye-off-outline',
|
||||||
icon="eye-off-outline"
|
key: 'page.queue.hide-previous',
|
||||||
label="page.queue.hide-previous"
|
class: { 'is-dark': show_only_next_items }
|
||||||
/>
|
}"
|
||||||
<control-button
|
/>
|
||||||
:handler="open_add_stream_dialog"
|
<control-button
|
||||||
icon="web"
|
:button="{
|
||||||
label="page.queue.add-stream"
|
handler: open_add_stream_dialog,
|
||||||
/>
|
icon: 'web',
|
||||||
<control-button
|
key: 'page.queue.add-stream'
|
||||||
:class="{ 'is-dark': edit_mode }"
|
}"
|
||||||
:disabled="queue_items.length === 0"
|
/>
|
||||||
:handler="toggleEdit"
|
<control-button
|
||||||
icon="pencil"
|
:button="{
|
||||||
label="page.queue.edit"
|
handler: toggleEdit,
|
||||||
/>
|
icon: 'pencil',
|
||||||
<control-button
|
key: 'page.queue.edit',
|
||||||
:disabled="queue_items.length === 0"
|
disabled: queue_items.length === 0,
|
||||||
:handler="queue_clear"
|
class: { 'is-dark': edit_mode }
|
||||||
icon="delete-empty"
|
}"
|
||||||
label="page.queue.clear"
|
/>
|
||||||
/>
|
<control-button
|
||||||
<control-button
|
:button="{
|
||||||
v-if="is_queue_save_allowed"
|
handler: queue_clear,
|
||||||
:disabled="queue_items.length === 0"
|
icon: 'delete-empty',
|
||||||
:handler="save_dialog"
|
key: 'page.queue.clear',
|
||||||
icon="download"
|
disabled: queue_items.length === 0
|
||||||
label="page.queue.save"
|
}"
|
||||||
/>
|
/>
|
||||||
</div>
|
<control-button
|
||||||
|
v-if="is_queue_save_allowed"
|
||||||
|
:button="{
|
||||||
|
handler: save_dialog,
|
||||||
|
icon: 'download',
|
||||||
|
key: 'page.queue.save',
|
||||||
|
disabled: queue_items.length === 0
|
||||||
|
}"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<draggable v-model="queue_items" item-key="id" @end="move_item">
|
<draggable v-model="queue_items" item-key="id" @end="move_item">
|
||||||
@ -93,6 +97,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import ControlButton from '@/components/ControlButton.vue'
|
import ControlButton from '@/components/ControlButton.vue'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import ListItemQueueItem from '@/components/ListItemQueueItem.vue'
|
import ListItemQueueItem from '@/components/ListItemQueueItem.vue'
|
||||||
import ModalDialogAddStream from '@/components/ModalDialogAddStream.vue'
|
import ModalDialogAddStream from '@/components/ModalDialogAddStream.vue'
|
||||||
import ModalDialogPlaylistSave from '@/components/ModalDialogPlaylistSave.vue'
|
import ModalDialogPlaylistSave from '@/components/ModalDialogPlaylistSave.vue'
|
||||||
@ -113,9 +118,9 @@ export default {
|
|||||||
ModalDialogAddStream,
|
ModalDialogAddStream,
|
||||||
ModalDialogPlaylistSave,
|
ModalDialogPlaylistSave,
|
||||||
ModalDialogQueueItem,
|
ModalDialogQueueItem,
|
||||||
|
HeadingTitle,
|
||||||
draggable
|
draggable
|
||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
configurationStore: useConfigurationStore(),
|
configurationStore: useConfigurationStore(),
|
||||||
@ -124,7 +129,6 @@ export default {
|
|||||||
uiStore: useUIStore()
|
uiStore: useUIStore()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
edit_mode: false,
|
edit_mode: false,
|
||||||
@ -134,11 +138,16 @@ export default {
|
|||||||
show_url_modal: false
|
show_url_modal: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
current_position() {
|
current_position() {
|
||||||
return this.queue.current?.position ?? -1
|
return this.queue.current?.position ?? -1
|
||||||
},
|
},
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title: this.$t('page.queue.title'),
|
||||||
|
subtitle: [{ key: 'count.tracks', count: this.queue.count }]
|
||||||
|
}
|
||||||
|
},
|
||||||
is_queue_save_allowed() {
|
is_queue_save_allowed() {
|
||||||
return (
|
return (
|
||||||
this.configurationStore.allow_modifying_stored_playlists &&
|
this.configurationStore.allow_modifying_stored_playlists &&
|
||||||
|
@ -2,11 +2,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="$t('page.radio.title')" />
|
<heading-title :content="heading" />
|
||||||
<div
|
|
||||||
class="is-size-7 is-uppercase"
|
|
||||||
v-text="$t('count.stations', { count: tracks.total })"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-tracks :items="tracks" />
|
<list-tracks :items="tracks" />
|
||||||
@ -18,6 +14,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import ListTracks from '@/components/ListTracks.vue'
|
import ListTracks from '@/components/ListTracks.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
@ -25,7 +22,6 @@ const dataObject = {
|
|||||||
load(to) {
|
load(to) {
|
||||||
return webapi.library_radio_streams()
|
return webapi.library_radio_streams()
|
||||||
},
|
},
|
||||||
|
|
||||||
set(vm, response) {
|
set(vm, response) {
|
||||||
vm.tracks = new GroupedList(response.data.tracks)
|
vm.tracks = new GroupedList(response.data.tracks)
|
||||||
}
|
}
|
||||||
@ -33,18 +29,24 @@ const dataObject = {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PageRadioStreams',
|
name: 'PageRadioStreams',
|
||||||
components: { ContentWithHeading, ListTracks },
|
components: { ContentWithHeading, ListTracks, HeadingTitle },
|
||||||
|
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
dataObject.load(to).then((response) => {
|
dataObject.load(to).then((response) => {
|
||||||
next((vm) => dataObject.set(vm, response))
|
next((vm) => dataObject.set(vm, response))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tracks: new GroupedList()
|
tracks: new GroupedList()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
heading() {
|
||||||
|
return {
|
||||||
|
title: this.$t('page.radio.title'),
|
||||||
|
subtitle: [{ key: 'count.stations', count: this.tracks.total }]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
<template v-for="[type, items] in results" :key="type">
|
<template v-for="[type, items] in results" :key="type">
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t(`page.search.${type}s`)" />
|
<heading-title :content="{ title: $t(`page.search.${type}s`) }" />
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<component :is="components[type]" :items="items" />
|
<component :is="components[type]" :items="items" />
|
||||||
@ -83,6 +83,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import ListAlbums from '@/components/ListAlbums.vue'
|
import ListAlbums from '@/components/ListAlbums.vue'
|
||||||
import ListArtists from '@/components/ListArtists.vue'
|
import ListArtists from '@/components/ListArtists.vue'
|
||||||
import ListComposers from '@/components/ListComposers.vue'
|
import ListComposers from '@/components/ListComposers.vue'
|
||||||
@ -107,6 +108,7 @@ export default {
|
|||||||
name: 'PageSearchLibrary',
|
name: 'PageSearchLibrary',
|
||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
|
HeadingTitle,
|
||||||
ListAlbums,
|
ListAlbums,
|
||||||
ListArtists,
|
ListArtists,
|
||||||
ListComposers,
|
ListComposers,
|
||||||
|
@ -34,7 +34,9 @@
|
|||||||
<template v-for="[type, items] in results" :key="type">
|
<template v-for="[type, items] in results" :key="type">
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t(`page.spotify.search.${type}s`)" />
|
<heading-title
|
||||||
|
:content="{ title: $t(`page.spotify.search.${type}s`) }"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<component :is="components[type]" :items="items.items" />
|
<component :is="components[type]" :items="items.items" />
|
||||||
@ -77,6 +79,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import ListAlbumsSpotify from '@/components/ListAlbumsSpotify.vue'
|
import ListAlbumsSpotify from '@/components/ListAlbumsSpotify.vue'
|
||||||
import ListArtistsSpotify from '@/components/ListArtistsSpotify.vue'
|
import ListArtistsSpotify from '@/components/ListArtistsSpotify.vue'
|
||||||
import ListPlaylistsSpotify from '@/components/ListPlaylistsSpotify.vue'
|
import ListPlaylistsSpotify from '@/components/ListPlaylistsSpotify.vue'
|
||||||
@ -95,6 +98,7 @@ export default {
|
|||||||
name: 'PageSearchSpotify',
|
name: 'PageSearchSpotify',
|
||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
|
HeadingTitle,
|
||||||
ListAlbumsSpotify,
|
ListAlbumsSpotify,
|
||||||
ListArtistsSpotify,
|
ListArtistsSpotify,
|
||||||
ListPlaylistsSpotify,
|
ListPlaylistsSpotify,
|
||||||
@ -102,11 +106,9 @@ export default {
|
|||||||
TabsSearch,
|
TabsSearch,
|
||||||
VueEternalLoading
|
VueEternalLoading
|
||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return { searchStore: useSearchStore() }
|
return { searchStore: useSearchStore() }
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
components: {
|
components: {
|
||||||
@ -121,7 +123,6 @@ export default {
|
|||||||
search_types: SEARCH_TYPES
|
search_types: SEARCH_TYPES
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
expanded() {
|
expanded() {
|
||||||
return this.search_types.length === 1
|
return this.search_types.length === 1
|
||||||
@ -132,20 +133,17 @@ export default {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
search_query() {
|
search_query() {
|
||||||
this.searchStore.search_query = this.search_query
|
this.searchStore.search_query = this.search_query
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.searchStore.search_source = this.$route.name
|
this.searchStore.search_source = this.$route.name
|
||||||
this.search_query = this.searchStore.search_query
|
this.search_query = this.searchStore.search_query
|
||||||
this.search_parameters.limit = PAGE_SIZE
|
this.search_parameters.limit = PAGE_SIZE
|
||||||
this.search()
|
this.search()
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
expand(type) {
|
expand(type) {
|
||||||
this.search_query = this.searchStore.search_query
|
this.search_query = this.searchStore.search_query
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
<tabs-settings />
|
<tabs-settings />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="$t('page.settings.artwork.title')" />
|
<heading-title
|
||||||
|
:content="{ title: $t('page.settings.artwork.title') }"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div
|
<div
|
||||||
@ -79,17 +81,21 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import ControlSettingSwitch from '@/components/ControlSettingSwitch.vue'
|
import ControlSettingSwitch from '@/components/ControlSettingSwitch.vue'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import TabsSettings from '@/components/TabsSettings.vue'
|
import TabsSettings from '@/components/TabsSettings.vue'
|
||||||
import { useServicesStore } from '@/stores/services'
|
import { useServicesStore } from '@/stores/services'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PageSettingsArtwork',
|
name: 'PageSettingsArtwork',
|
||||||
components: { ContentWithHeading, ControlSettingSwitch, TabsSettings },
|
components: {
|
||||||
|
ContentWithHeading,
|
||||||
|
ControlSettingSwitch,
|
||||||
|
HeadingTitle,
|
||||||
|
TabsSettings
|
||||||
|
},
|
||||||
setup() {
|
setup() {
|
||||||
return { servicesStore: useServicesStore() }
|
return { servicesStore: useServicesStore() }
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
spotify() {
|
spotify() {
|
||||||
return this.servicesStore.spotify
|
return this.servicesStore.spotify
|
||||||
|
@ -3,9 +3,8 @@
|
|||||||
<tabs-settings />
|
<tabs-settings />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div
|
<heading-title
|
||||||
class="title is-4"
|
:content="{ title: $t('page.settings.services.spotify.title') }"
|
||||||
v-text="$t('page.settings.services.spotify.title')"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
@ -59,9 +58,8 @@
|
|||||||
</content-with-heading>
|
</content-with-heading>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div
|
<heading-title
|
||||||
class="title is-4"
|
:content="{ title: $t('page.settings.services.lastfm.title') }"
|
||||||
v-text="$t('page.settings.services.lastfm.title')"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
@ -127,18 +125,17 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import TabsSettings from '@/components/TabsSettings.vue'
|
import TabsSettings from '@/components/TabsSettings.vue'
|
||||||
import { useServicesStore } from '@/stores/services'
|
import { useServicesStore } from '@/stores/services'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PageSettingsOnlineServices',
|
name: 'PageSettingsOnlineServices',
|
||||||
components: { ContentWithHeading, TabsSettings },
|
components: { ContentWithHeading, HeadingTitle, TabsSettings },
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return { servicesStore: useServicesStore() }
|
return { servicesStore: useServicesStore() }
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
lastfm_login: {
|
lastfm_login: {
|
||||||
@ -148,7 +145,6 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
lastfm() {
|
lastfm() {
|
||||||
return this.servicesStore.lastfm
|
return this.servicesStore.lastfm
|
||||||
@ -175,7 +171,6 @@ export default {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
login_lastfm() {
|
login_lastfm() {
|
||||||
webapi.lastfm_login(this.lastfm_login).then((response) => {
|
webapi.lastfm_login(this.lastfm_login).then((response) => {
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
<tabs-settings />
|
<tabs-settings />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t('page.settings.devices.pairing')" />
|
<heading-title
|
||||||
|
:content="{ title: $t('page.settings.devices.pairing') }"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div v-if="pairing.active">
|
<div v-if="pairing.active">
|
||||||
@ -39,9 +41,8 @@
|
|||||||
</content-with-heading>
|
</content-with-heading>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p
|
<heading-title
|
||||||
class="title is-4"
|
:content="{ title: $t('page.settings.devices.speaker-pairing') }"
|
||||||
v-text="$t('page.settings.devices.speaker-pairing')"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
@ -91,6 +92,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import ControlSwitch from '@/components/ControlSwitch.vue'
|
import ControlSwitch from '@/components/ControlSwitch.vue'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import TabsSettings from '@/components/TabsSettings.vue'
|
import TabsSettings from '@/components/TabsSettings.vue'
|
||||||
import { useOutputsStore } from '@/stores/outputs'
|
import { useOutputsStore } from '@/stores/outputs'
|
||||||
import { useRemotesStore } from '@/stores/remotes'
|
import { useRemotesStore } from '@/stores/remotes'
|
||||||
@ -98,19 +100,16 @@ import webapi from '@/webapi'
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PageSettingsRemotesOutputs',
|
name: 'PageSettingsRemotesOutputs',
|
||||||
components: { ContentWithHeading, ControlSwitch, TabsSettings },
|
components: { ContentWithHeading, ControlSwitch, HeadingTitle, TabsSettings },
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return { outputsStore: useOutputsStore(), remotesStore: useRemotesStore() }
|
return { outputsStore: useOutputsStore(), remotesStore: useRemotesStore() }
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
pairing_req: { pin: '' },
|
pairing_req: { pin: '' },
|
||||||
verification_req: { pin: '' }
|
verification_req: { pin: '' }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
outputs() {
|
outputs() {
|
||||||
return this.outputsStore.outputs
|
return this.outputsStore.outputs
|
||||||
@ -119,7 +118,6 @@ export default {
|
|||||||
return this.remotesStore.pairing
|
return this.remotesStore.pairing
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
kickoff_pairing() {
|
kickoff_pairing() {
|
||||||
webapi.pairing_kickoff(this.pairing_req)
|
webapi.pairing_kickoff(this.pairing_req)
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
<tabs-settings />
|
<tabs-settings />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div class="title is-4" v-text="$t('page.settings.general.language')" />
|
<heading-title
|
||||||
|
:content="{ title: $t('page.settings.general.language') }"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<control-dropdown v-model:value="locale" :options="locales" />
|
<control-dropdown v-model:value="locale" :options="locales" />
|
||||||
@ -11,9 +13,8 @@
|
|||||||
</content-with-heading>
|
</content-with-heading>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div
|
<heading-title
|
||||||
class="title is-4"
|
:content="{ title: $t('page.settings.general.navigation-items') }"
|
||||||
v-text="$t('page.settings.general.navigation-items')"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
@ -85,9 +86,8 @@
|
|||||||
</content-with-heading>
|
</content-with-heading>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div
|
<heading-title
|
||||||
class="title is-4"
|
:content="{ title: $t('page.settings.general.now-playing-page') }"
|
||||||
v-text="$t('page.settings.general.now-playing-page')"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
@ -134,9 +134,8 @@
|
|||||||
</content-with-heading>
|
</content-with-heading>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<div
|
<heading-title
|
||||||
class="title is-4"
|
:content="{ title: $t('page.settings.general.recently-added-page') }"
|
||||||
v-text="$t('page.settings.general.recently-added-page')"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
@ -161,6 +160,7 @@ import ControlDropdown from '@/components/ControlDropdown.vue'
|
|||||||
import ControlSettingIntegerField from '@/components/ControlSettingIntegerField.vue'
|
import ControlSettingIntegerField from '@/components/ControlSettingIntegerField.vue'
|
||||||
import ControlSettingSwitch from '@/components/ControlSettingSwitch.vue'
|
import ControlSettingSwitch from '@/components/ControlSettingSwitch.vue'
|
||||||
import ControlSettingTextField from '@/components/ControlSettingTextField.vue'
|
import ControlSettingTextField from '@/components/ControlSettingTextField.vue'
|
||||||
|
import HeadingTitle from '@/components/HeadingTitle.vue'
|
||||||
import TabsSettings from '@/components/TabsSettings.vue'
|
import TabsSettings from '@/components/TabsSettings.vue'
|
||||||
import { useSettingsStore } from '@/stores/settings'
|
import { useSettingsStore } from '@/stores/settings'
|
||||||
|
|
||||||
@ -172,6 +172,7 @@ export default {
|
|||||||
ControlSettingIntegerField,
|
ControlSettingIntegerField,
|
||||||
ControlSettingSwitch,
|
ControlSettingSwitch,
|
||||||
ControlSettingTextField,
|
ControlSettingTextField,
|
||||||
|
HeadingTitle,
|
||||||
TabsSettings
|
TabsSettings
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -24,14 +24,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="level-right has-text-centered-mobile">
|
<div
|
||||||
<slot name="heading-right" />
|
v-if="$slots['heading-right']"
|
||||||
|
class="level-right has-text-centered-mobile"
|
||||||
|
>
|
||||||
|
<div class="buttons">
|
||||||
|
<slot name="heading-right" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<slot name="content" />
|
<slot name="content" />
|
||||||
<div class="mt-4">
|
<nav v-if="$slots.footer" class="level mt-4">
|
||||||
<slot name="footer" />
|
<div class="level-item">
|
||||||
</div>
|
<slot name="footer" />
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user