[web] Refactor hero template

This commit is contained in:
Alain Nussbaumer 2025-03-15 13:55:14 +01:00
parent 2e38df1c40
commit 9e2c9fddcb
6 changed files with 100 additions and 87 deletions

View File

@ -0,0 +1,27 @@
<template>
<div class="title is-5" v-text="content.title" />
<div class="subtitle is-6">
<a @click="content.handler" v-text="content.subtitle" />
</div>
<div
class="is-size-7 is-uppercase has-text-centered-mobile"
v-text="content.count"
/>
<div class="buttons is-centered-mobile mt-5">
<control-button
v-for="(action, index) in content.actions"
:key="index"
:button="action"
/>
</div>
</template>
<script>
import ControlButton from '@/components/ControlButton.vue'
export default {
name: 'HeadingHero',
components: { ControlButton },
props: { content: { required: true, type: Object } }
}
</script>

View File

@ -1,25 +1,10 @@
<template> <template>
<div> <div>
<content-with-hero> <content-with-hero>
<template #heading-left> <template #heading>
<div class="title is-5" v-text="album.name" /> <heading-hero :content="heading" />
<div class="subtitle is-6">
<a @click="openArtist" v-text="album.artist" />
</div>
<div
class="is-size-7 is-uppercase has-text-centered-mobile"
v-text="$t('count.tracks', { count: album.track_count })"
/>
<div class="buttons is-centered-mobile mt-5">
<control-button
:button="{ handler: play, icon: 'shuffle', key: 'actions.shuffle' }"
/>
<control-button
:button="{ handler: openDetails, icon: 'dots-horizontal' }"
/>
</div>
</template> </template>
<template #heading-right> <template #image>
<control-image <control-image
:url="album.artwork_url" :url="album.artwork_url"
:artist="album.artist" :artist="album.artist"
@ -42,9 +27,9 @@
<script> <script>
import ContentWithHero from '@/templates/ContentWithHero.vue' import ContentWithHero from '@/templates/ContentWithHero.vue'
import ControlButton from '@/components/ControlButton.vue'
import ControlImage from '@/components/ControlImage.vue' import ControlImage from '@/components/ControlImage.vue'
import { GroupedList } from '@/lib/GroupedList' import { GroupedList } from '@/lib/GroupedList'
import HeadingHero from '@/components/HeadingHero.vue'
import ListTracks from '@/components/ListTracks.vue' import ListTracks from '@/components/ListTracks.vue'
import ModalDialogAlbum from '@/components/ModalDialogAlbum.vue' import ModalDialogAlbum from '@/components/ModalDialogAlbum.vue'
import webapi from '@/webapi' import webapi from '@/webapi'
@ -56,7 +41,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, {
@ -73,8 +57,8 @@ export default {
name: 'PageAlbum', name: 'PageAlbum',
components: { components: {
ContentWithHero, ContentWithHero,
ControlButton,
ControlImage, ControlImage,
HeadingHero,
ListTracks, ListTracks,
ModalDialogAlbum ModalDialogAlbum
}, },
@ -90,6 +74,20 @@ export default {
tracks: new GroupedList() tracks: new GroupedList()
} }
}, },
computed: {
heading() {
return {
count: this.$t('count.tracks', { count: this.album.track_count }),
handler: this.openArtist,
subtitle: this.album.artist,
title: this.album.name,
actions: [
{ handler: this.play, icon: 'shuffle', key: 'actions.shuffle' },
{ handler: this.openDetails, icon: 'dots-horizontal' }
]
}
}
},
methods: { methods: {
openArtist() { openArtist() {
this.showDetailsModal = false this.showDetailsModal = false

View File

@ -1,25 +1,10 @@
<template> <template>
<div> <div>
<content-with-hero> <content-with-hero>
<template #heading-left> <template #heading>
<div class="title is-5" v-text="album.name" /> <heading-hero :content="heading" />
<div class="subtitle is-6">
<a @click="openArtist" v-text="album.artists[0].name" />
</div>
<div
class="is-size-7 is-uppercase has-text-centered-mobile"
v-text="$t('count.tracks', { count: album.tracks.total })"
/>
<div class="buttons is-centered-mobile mt-5">
<control-button
:button="{ handler: play, icon: 'shuffle', key: 'actions.shuffle' }"
/>
<control-button
:button="{ handler: openDetails, icon: 'dots-horizontal' }"
/>
</div>
</template> </template>
<template #heading-right> <template #image>
<control-image <control-image
:url="album.images?.[0]?.url ?? ''" :url="album.images?.[0]?.url ?? ''"
:artist="album.artists[0].name" :artist="album.artists[0].name"
@ -42,8 +27,8 @@
<script> <script>
import ContentWithHero from '@/templates/ContentWithHero.vue' import ContentWithHero from '@/templates/ContentWithHero.vue'
import ControlButton from '@/components/ControlButton.vue'
import ControlImage from '@/components/ControlImage.vue' import ControlImage from '@/components/ControlImage.vue'
import HeadingHero from '@/components/HeadingHero.vue'
import ListTracksSpotify from '@/components/ListTracksSpotify.vue' import ListTracksSpotify from '@/components/ListTracksSpotify.vue'
import ModalDialogAlbumSpotify from '@/components/ModalDialogAlbumSpotify.vue' import ModalDialogAlbumSpotify from '@/components/ModalDialogAlbumSpotify.vue'
import SpotifyWebApi from 'spotify-web-api-js' import SpotifyWebApi from 'spotify-web-api-js'
@ -67,8 +52,8 @@ export default {
name: 'PageAlbumSpotify', name: 'PageAlbumSpotify',
components: { components: {
ContentWithHero, ContentWithHero,
ControlButton,
ControlImage, ControlImage,
HeadingHero,
ListTracksSpotify, ListTracksSpotify,
ModalDialogAlbumSpotify ModalDialogAlbumSpotify
}, },
@ -87,6 +72,18 @@ export default {
} }
}, },
computed: { computed: {
heading() {
return {
count: this.$t('count.tracks', { count: this.album.tracks.total }),
handler: this.openArtist,
subtitle: this.album.artists[0].name,
title: this.album.name,
actions: [
{ handler: this.play, icon: 'shuffle', key: 'actions.shuffle' },
{ handler: this.openDetails, icon: 'dots-horizontal' }
]
}
},
tracks() { tracks() {
const { album } = this const { album } = this
if (album.tracks.total) { if (album.tracks.total) {

View File

@ -1,29 +1,10 @@
<template> <template>
<div> <div>
<content-with-hero> <content-with-hero>
<template #heading-left> <template #heading>
<div class="title is-5" v-text="album.name" /> <heading-hero :content="heading" />
<div class="subtitle is-6">
<a @click="openArtist" v-text="album.artist" />
</div>
<div
class="is-size-7 is-uppercase has-text-centered-mobile"
v-text="$t('count.tracks', { count: album.track_count })"
/>
<div class="buttons is-centered-mobile mt-5">
<control-button
:button="{
handler: play,
icon: 'play',
key: 'actions.play'
}"
/>
<control-button
:button="{ handler: openDetails, icon: 'dots-horizontal' }"
/>
</div>
</template> </template>
<template #heading-right> <template #image>
<control-image <control-image
:url="album.artwork_url" :url="album.artwork_url"
:artist="album.artist" :artist="album.artist"
@ -47,9 +28,9 @@
<script> <script>
import ContentWithHero from '@/templates/ContentWithHero.vue' import ContentWithHero from '@/templates/ContentWithHero.vue'
import ControlButton from '@/components/ControlButton.vue'
import ControlImage from '@/components/ControlImage.vue' import ControlImage from '@/components/ControlImage.vue'
import { GroupedList } from '@/lib/GroupedList' import { GroupedList } from '@/lib/GroupedList'
import HeadingHero from '@/components/HeadingHero.vue'
import ListTracks from '@/components/ListTracks.vue' import ListTracks from '@/components/ListTracks.vue'
import ModalDialogAlbum from '@/components/ModalDialogAlbum.vue' import ModalDialogAlbum from '@/components/ModalDialogAlbum.vue'
import webapi from '@/webapi' import webapi from '@/webapi'
@ -71,8 +52,8 @@ export default {
name: 'PageAudiobooksAlbum', name: 'PageAudiobooksAlbum',
components: { components: {
ContentWithHero, ContentWithHero,
ControlButton,
ControlImage, ControlImage,
HeadingHero,
ListTracks, ListTracks,
ModalDialogAlbum ModalDialogAlbum
}, },
@ -88,6 +69,20 @@ export default {
tracks: new GroupedList() tracks: new GroupedList()
} }
}, },
computed: {
heading() {
return {
count: this.$t('count.tracks', { count: this.album.track_count }),
handler: this.openArtist,
subtitle: this.album.artist,
title: this.album.name,
actions: [
{ handler: this.play, icon: 'play', key: 'actions.play' },
{ handler: this.openDetails, icon: 'dots-horizontal' }
]
}
}
},
methods: { methods: {
openArtist() { openArtist() {
this.showDetailsModal = false this.showDetailsModal = false

View File

@ -1,25 +1,10 @@
<template> <template>
<div> <div>
<content-with-hero> <content-with-hero>
<template #heading-left> <template #heading>
<div class="title is-5" v-text="album.name" /> <heading-hero :content="heading" />
<div class="subtitle is-6">
<br />
</div>
<div
class="is-size-7 is-uppercase has-text-centered-mobile"
v-text="$t('count.tracks', { count: album.track_count })"
/>
<div class="buttons is-centered-mobile mt-5">
<control-button
:button="{ handler: play, icon: 'play', key: 'actions.play' }"
/>
<control-button
:button="{ handler: openDetails, icon: 'dots-horizontal' }"
/>
</div>
</template> </template>
<template #heading-right> <template #image>
<control-image <control-image
:url="album.artwork_url" :url="album.artwork_url"
:artist="album.artist" :artist="album.artist"
@ -67,9 +52,9 @@
<script> <script>
import ContentWithHero from '@/templates/ContentWithHero.vue' import ContentWithHero from '@/templates/ContentWithHero.vue'
import ControlButton from '@/components/ControlButton.vue'
import ControlImage from '@/components/ControlImage.vue' import ControlImage from '@/components/ControlImage.vue'
import { GroupedList } from '@/lib/GroupedList' import { GroupedList } from '@/lib/GroupedList'
import HeadingHero from '@/components/HeadingHero.vue'
import ListTracks from '@/components/ListTracks.vue' import ListTracks from '@/components/ListTracks.vue'
import ModalDialog from '@/components/ModalDialog.vue' import ModalDialog from '@/components/ModalDialog.vue'
import ModalDialogAlbum from '@/components/ModalDialogAlbum.vue' import ModalDialogAlbum from '@/components/ModalDialogAlbum.vue'
@ -92,8 +77,8 @@ export default {
name: 'PagePodcast', name: 'PagePodcast',
components: { components: {
ContentWithHero, ContentWithHero,
ControlButton,
ControlImage, ControlImage,
HeadingHero,
ListTracks, ListTracks,
ModalDialog, ModalDialog,
ModalDialogAlbum ModalDialogAlbum
@ -126,6 +111,17 @@ export default {
key: this.$t('page.podcast.remove') key: this.$t('page.podcast.remove')
} }
] ]
},
heading() {
return {
count: this.$t('count.tracks', { count: this.album.track_count }),
subtitle: '',
title: this.album.name,
actions: [
{ handler: this.play, icon: 'play', key: 'actions.play' },
{ handler: this.openDetails, icon: 'dots-horizontal' }
]
}
} }
}, },
methods: { methods: {

View File

@ -5,10 +5,10 @@
<div class="column is-four-fifths"> <div class="column is-four-fifths">
<div class="columns is-flex-direction-row-reverse"> <div class="columns is-flex-direction-row-reverse">
<div class="column is-flex has-image"> <div class="column is-flex has-image">
<slot name="heading-right" /> <slot name="image" />
</div> </div>
<div class="column m-auto is-three-fifths has-text-centered-mobile"> <div class="column m-auto is-three-fifths has-text-centered-mobile">
<slot name="heading-left" /> <slot name="heading" />
</div> </div>
</div> </div>
</div> </div>