[web] Use "button" tag instead of "a" tag

This commit is contained in:
Alain Nussbaumer 2025-03-01 22:03:28 +01:00
parent ad2ec2252f
commit 43f4a23b1e
24 changed files with 317 additions and 273 deletions

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,22 @@
<template>
<button
class="button is-small is-rounded"
:disabled="disabled"
@click="handler"
>
<mdicon v-if="icon" class="icon" :name="icon" size="16" />
<span v-if="label" v-text="$t(label)" />
</button>
</template>
<script>
export default {
name: 'ControlButton',
props: {
disabled: { default: false, type: Boolean },
handler: { required: true, type: Function },
icon: { default: '', type: String },
label: { default: '', type: String }
}
}
</script>

View File

@ -1,9 +1,9 @@
<template> <template>
<div class="media is-align-items-center mb-0"> <div class="media is-align-items-center mb-0">
<div class="media-left"> <div class="media-left">
<a class="button is-small" @click="toggle"> <button class="button is-small" @click="toggle">
<mdicon class="icon" :name="icon" /> <mdicon class="icon" :name="icon" />
</a> </button>
</div> </div>
<div class="media-content"> <div class="media-content">
<div class="is-size-7 is-uppercase" v-text="$t('navigation.volume')" /> <div class="is-size-7 is-uppercase" v-text="$t('navigation.volume')" />

View File

@ -1,13 +1,13 @@
<template> <template>
<div class="media is-align-items-center mb-0"> <div class="media is-align-items-center mb-0">
<div class="media-left"> <div class="media-left">
<a <button
class="button is-small" class="button is-small"
:class="{ 'has-text-grey-light': !output.selected }" :class="{ 'has-text-grey-light': !output.selected }"
@click="toggle" @click="toggle"
> >
<mdicon class="icon" :name="icon" :title="output.type" /> <mdicon class="icon" :name="icon" :title="output.type" />
</a> </button>
</div> </div>
<div class="media-content"> <div class="media-content">
<div <div

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="media is-align-items-center mb-0"> <div class="media is-align-items-center mb-0">
<div class="media-left"> <div class="media-left">
<a <button
class="button is-small" class="button is-small"
:class="{ :class="{
'has-text-grey-light': !playing && !loading, 'has-text-grey-light': !playing && !loading,
@ -10,7 +10,7 @@
@click="togglePlay" @click="togglePlay"
> >
<mdicon class="icon" name="broadcast" /> <mdicon class="icon" name="broadcast" />
</a> </button>
</div> </div>
<div class="media-content is-align-items-center"> <div class="media-content is-align-items-center">
<div class="is-flex" :class="{ 'has-text-grey-light': !playing }"> <div class="is-flex" :class="{ 'has-text-grey-light': !playing }">

View File

@ -4,12 +4,11 @@
<list-properties :item="item"> <list-properties :item="item">
<template v-if="buttons.length" #buttons> <template v-if="buttons.length" #buttons>
<div class="buttons"> <div class="buttons">
<a <control-button
v-for="button in buttons" v-for="button in buttons"
:key="button.label" :key="button.label"
class="button is-small is-rounded" :handler="button.handler"
@click="button.handler" label="button.label"
v-text="$t(button.label)"
/> />
</div> </div>
</template> </template>
@ -19,13 +18,14 @@
</template> </template>
<script> <script>
import ControlButton from '@/components/ControlButton.vue'
import ListProperties from '@/components/ListProperties.vue' import ListProperties from '@/components/ListProperties.vue'
import ModalDialog from '@/components/ModalDialog.vue' import ModalDialog from '@/components/ModalDialog.vue'
import webapi from '@/webapi' import webapi from '@/webapi'
export default { export default {
name: 'ModalDialogPlayable', name: 'ModalDialogPlayable',
components: { ListProperties, ModalDialog }, components: { ControlButton, ListProperties, ModalDialog },
props: { props: {
buttons: { default: () => [], type: Array }, buttons: { default: () => [], type: Array },
item: { required: true, type: Object }, item: { required: true, type: Object },

View File

@ -11,20 +11,14 @@
</div> </div>
</div> </div>
<div class="level-right"> <div class="level-right">
<div v-if="libraryStore.updating"> <control-button
<a :class="{ 'is-loading': libraryStore.updating }"
class="button is-small is-rounded is-loading" :disabled="libraryStore.updating"
v-text="$t('page.about.update')" :handler="showUpdateDialog"
icon="refresh"
label="page.about.update"
/> />
</div> </div>
<div v-else>
<a
class="button is-small is-rounded"
@click="showUpdateDialog()"
v-text="$t('page.about.update')"
/>
</div>
</div>
</nav> </nav>
<div <div
v-for="property in properties" v-for="property in properties"
@ -105,12 +99,14 @@
</template> </template>
<script> <script>
import ControlButton from '@/components/ControlButton.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 },
setup() { setup() {
return { return {
configurationStore: useConfigurationStore(), configurationStore: useConfigurationStore(),

View File

@ -11,16 +11,12 @@
v-text="$t('count.tracks', { count: album.track_count })" v-text="$t('count.tracks', { count: album.track_count })"
/> />
<div class="buttons is-centered-mobile mt-5"> <div class="buttons is-centered-mobile mt-5">
<a class="button is-small is-rounded" @click="play"> <control-button
<mdicon class="icon" name="shuffle" size="16" /> :handler="play"
<span v-text="$t('page.album.shuffle')" /> icon="shuffle"
</a> label="page.album.shuffle"
<a />
class="button is-small is-rounded" <control-button :handler="showDetails" icon="dots-horizontal" />
@click="show_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" />
</a>
</div> </div>
</template> </template>
<template #heading-right> <template #heading-right>
@ -29,7 +25,7 @@
:artist="album.artist" :artist="album.artist"
:album="album.name" :album="album.name"
class="is-clickable is-medium" class="is-clickable is-medium"
@click="show_details_modal = true" @click="showDetails"
/> />
</template> </template>
<template #content> <template #content>
@ -46,6 +42,7 @@
<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 ListTracks from '@/components/ListTracks.vue' import ListTracks from '@/components/ListTracks.vue'
@ -74,7 +71,13 @@ const dataObject = {
export default { export default {
name: 'PageAlbum', name: 'PageAlbum',
components: { ContentWithHero, ControlImage, ListTracks, ModalDialogAlbum }, components: {
ContentWithHero,
ControlButton,
ControlImage,
ListTracks,
ModalDialogAlbum
},
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))
@ -97,6 +100,9 @@ export default {
}, },
play() { play() {
webapi.player_play_uri(this.album.uri, true) webapi.player_play_uri(this.album.uri, true)
},
showDetails() {
this.show_details_modal = true
} }
} }
} }

View File

@ -11,16 +11,12 @@
v-text="$t('count.tracks', { count: album.tracks.total })" v-text="$t('count.tracks', { count: album.tracks.total })"
/> />
<div class="buttons is-centered-mobile mt-5"> <div class="buttons is-centered-mobile mt-5">
<a class="button is-small is-rounded" @click="play"> <control-button
<mdicon class="icon" name="shuffle" size="16" /> :handler="play"
<span v-text="$t('page.spotify.album.shuffle')" /> icon="shuffle"
</a> label="page.spotify.album.shuffle"
<a />
class="button is-small is-rounded" <control-button :handler="showDetails" icon="dots-horizontal" />
@click="show_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" />
</a>
</div> </div>
</template> </template>
<template #heading-right> <template #heading-right>
@ -29,7 +25,7 @@
:artist="album.artists[0].name" :artist="album.artists[0].name"
:album="album.name" :album="album.name"
class="is-clickable is-medium" class="is-clickable is-medium"
@click="show_details_modal = true" @click="showDetails"
/> />
</template> </template>
<template #content> <template #content>
@ -46,6 +42,7 @@
<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 ListTracksSpotify from '@/components/ListTracksSpotify.vue' import ListTracksSpotify from '@/components/ListTracksSpotify.vue'
import ModalDialogAlbumSpotify from '@/components/ModalDialogAlbumSpotify.vue' import ModalDialogAlbumSpotify from '@/components/ModalDialogAlbumSpotify.vue'
@ -70,6 +67,7 @@ export default {
name: 'PageAlbumSpotify', name: 'PageAlbumSpotify',
components: { components: {
ContentWithHero, ContentWithHero,
ControlButton,
ControlImage, ControlImage,
ListTracksSpotify, ListTracksSpotify,
ModalDialogAlbumSpotify ModalDialogAlbumSpotify
@ -107,6 +105,9 @@ export default {
play() { play() {
this.show_details_modal = false this.show_details_modal = false
webapi.player_play_uri(this.album.uri, true) webapi.player_play_uri(this.album.uri, true)
},
showDetails() {
this.show_details_modal = true
} }
} }
} }

View File

@ -45,16 +45,12 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a <control-button :handler="showDetails" icon="dots-horizontal" />
class="button is-small is-rounded" <control-button
@click="show_details_modal = true" :handler="play"
> icon="shuffle"
<mdicon class="icon" name="dots-horizontal" size="16" /> label="page.artist.shuffle"
</a> />
<a class="button is-small is-rounded" @click="play">
<mdicon class="icon" name="shuffle" size="16" />
<span v-text="$t('page.artist.shuffle')" />
</a>
</div> </div>
</template> </template>
<template #content> <template #content>
@ -71,6 +67,7 @@
<script> <script>
import ContentWithHeading from '@/templates/ContentWithHeading.vue' import ContentWithHeading from '@/templates/ContentWithHeading.vue'
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'
@ -98,6 +95,7 @@ export default {
name: 'PageArtist', name: 'PageArtist',
components: { components: {
ContentWithHeading, ContentWithHeading,
ControlButton,
ControlDropdown, ControlDropdown,
ControlSwitch, ControlSwitch,
ListAlbums, ListAlbums,
@ -168,6 +166,9 @@ export default {
this.albums.items.map((item) => item.uri).join(), this.albums.items.map((item) => item.uri).join(),
true true
) )
},
showDetails() {
this.show_details_modal = true
} }
} }
} }

View File

@ -10,16 +10,12 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a <control-button :handler="showDetails" icon="dots-horizontal" />
class="button is-small is-rounded" <control-button
@click="show_details_modal = true" :handler="play"
> icon="shuffle"
<mdicon class="icon" name="dots-horizontal" size="16" /> label="page.spotify.artist.shuffle"
</a> />
<a class="button is-small is-rounded" @click="play">
<mdicon class="icon" name="shuffle" size="16" />
<span v-text="$t('page.spotify.artist.shuffle')" />
</a>
</div> </div>
</template> </template>
<template #content> <template #content>
@ -51,6 +47,7 @@
<script> <script>
import ContentWithHeading from '@/templates/ContentWithHeading.vue' import ContentWithHeading from '@/templates/ContentWithHeading.vue'
import ControlButton from '@/components/ControlButton.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'
@ -88,6 +85,7 @@ export default {
name: 'PageArtistSpotify', name: 'PageArtistSpotify',
components: { components: {
ContentWithHeading, ContentWithHeading,
ControlButton,
ListAlbumsSpotify, ListAlbumsSpotify,
ModalDialogArtistSpotify, ModalDialogArtistSpotify,
VueEternalLoading VueEternalLoading
@ -136,6 +134,9 @@ export default {
play() { play() {
this.show_album_details_modal = false this.show_album_details_modal = false
webapi.player_play_uri(this.artist.uri, true) webapi.player_play_uri(this.artist.uri, true)
},
showDetails() {
this.show_details_modal = true
} }
} }
} }

View File

@ -46,16 +46,12 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a <control-button :handler="showDetails" icon="dots-horizontal" />
class="button is-small is-rounded" <control-button
@click="show_details_modal = true" :handler="play"
> icon="shuffle"
<mdicon class="icon" name="dots-horizontal" size="16" /> label="page.artist.shuffle"
</a> />
<a class="button is-small is-rounded" @click="play">
<mdicon class="icon" name="shuffle" size="16" />
<span v-text="$t('page.artist.shuffle')" />
</a>
</div> </div>
</template> </template>
<template #content> <template #content>
@ -72,6 +68,7 @@
<script> <script>
import ContentWithHeading from '@/templates/ContentWithHeading.vue' import ContentWithHeading from '@/templates/ContentWithHeading.vue'
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'
@ -100,6 +97,7 @@ export default {
name: 'PageArtistTracks', name: 'PageArtistTracks',
components: { components: {
ContentWithHeading, ContentWithHeading,
ControlButton,
ControlDropdown, ControlDropdown,
ControlSwitch, ControlSwitch,
IndexButtonList, IndexButtonList,
@ -178,6 +176,9 @@ export default {
this.tracks_list.items.map((item) => item.uri).join(), this.tracks_list.items.map((item) => item.uri).join(),
true true
) )
},
showDetails() {
this.show_details_modal = true
} }
} }
} }

View File

@ -11,16 +11,12 @@
v-text="$t('count.tracks', { count: album.track_count })" v-text="$t('count.tracks', { count: album.track_count })"
/> />
<div class="buttons is-centered-mobile mt-5"> <div class="buttons is-centered-mobile mt-5">
<a class="button is-small is-rounded" @click="play"> <control-button
<mdicon class="icon" name="play" size="16" /> :handler="play"
<span v-text="$t('page.audiobooks.album.play')" /> icon="play"
</a> label="page.audiobooks.album.play"
<a />
class="button is-small is-rounded" <control-button :handler="showDetails" icon="dots-horizontal" />
@click="show_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" />
</a>
</div> </div>
</template> </template>
<template #heading-right> <template #heading-right>
@ -29,7 +25,7 @@
:artist="album.artist" :artist="album.artist"
:album="album.name" :album="album.name"
class="is-clickable is-medium" class="is-clickable is-medium"
@click="show_details_modal = true" @click="showDetails"
/> />
</template> </template>
<template #content> <template #content>
@ -47,6 +43,7 @@
<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 ListTracks from '@/components/ListTracks.vue' import ListTracks from '@/components/ListTracks.vue'
@ -69,7 +66,13 @@ const dataObject = {
export default { export default {
name: 'PageAudiobooksAlbum', name: 'PageAudiobooksAlbum',
components: { ContentWithHero, ControlImage, ListTracks, ModalDialogAlbum }, components: {
ContentWithHero,
ControlButton,
ControlImage,
ListTracks,
ModalDialogAlbum
},
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))
@ -92,6 +95,9 @@ export default {
}, },
play() { play() {
webapi.player_play_uri(this.album.uri, false) webapi.player_play_uri(this.album.uri, false)
},
showDetails() {
this.show_details_modal = true
} }
} }
} }

View File

@ -10,16 +10,13 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a <control-button :handle="showDetails" icon="dots-horizontal" />
class="button is-small is-rounded" <control-button
@click="show_details_modal = true" :handle="play"
> icon="play"
<mdicon class="icon" name="dots-horizontal" size="16" /> label="page.audiobooks.artist.play"
</a> />
<a class="button is-small is-rounded" @click="play"> />
<mdicon class="icon" name="play" size="16" />
<span v-text="$t('page.audiobooks.artist.play')" />
</a>
</div> </div>
</template> </template>
<template #content> <template #content>
@ -36,6 +33,7 @@
<script> <script>
import ContentWithHeading from '@/templates/ContentWithHeading.vue' import ContentWithHeading from '@/templates/ContentWithHeading.vue'
import ControlButton from '@/components/ControlButton.vue'
import { GroupedList } from '@/lib/GroupedList' import { GroupedList } from '@/lib/GroupedList'
import ListAlbums from '@/components/ListAlbums.vue' import ListAlbums from '@/components/ListAlbums.vue'
import ModalDialogArtist from '@/components/ModalDialogArtist.vue' import ModalDialogArtist from '@/components/ModalDialogArtist.vue'
@ -56,7 +54,12 @@ const dataObject = {
export default { export default {
name: 'PageAudiobooksArtist', name: 'PageAudiobooksArtist',
components: { ContentWithHeading, ListAlbums, ModalDialogArtist }, components: {
ContentWithHeading,
ControlButton,
ListAlbums,
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))
@ -75,6 +78,9 @@ export default {
this.albums.items.map((item) => item.uri).join(), this.albums.items.map((item) => item.uri).join(),
false false
) )
},
showDetails() {
this.show_details_modal = true
} }
} }
} }

View File

@ -14,16 +14,12 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a <control-button :handler="showDetails" icon="dots-horizontal" />
class="button is-small is-rounded" <control-button
@click="show_details_modal = true" :handler="play"
> icon="shuffle"
<mdicon class="icon" name="dots-horizontal" size="16" /> label="page.composer.shuffle"
</a> />
<a class="button is-small is-rounded" @click="play">
<mdicon class="icon" name="shuffle" size="16" />
<span v-text="$t('page.composer.shuffle')" />
</a>
</div> </div>
</template> </template>
<template #content> <template #content>
@ -40,6 +36,7 @@
<script> <script>
import ContentWithHeading from '@/templates/ContentWithHeading.vue' import ContentWithHeading from '@/templates/ContentWithHeading.vue'
import ControlButton from '@/components/ControlButton.vue'
import { GroupedList } from '@/lib/GroupedList' import { GroupedList } from '@/lib/GroupedList'
import ListAlbums from '@/components/ListAlbums.vue' import ListAlbums from '@/components/ListAlbums.vue'
import ModalDialogComposer from '@/components/ModalDialogComposer.vue' import ModalDialogComposer from '@/components/ModalDialogComposer.vue'
@ -63,6 +60,7 @@ export default {
name: 'PageComposerAlbums', name: 'PageComposerAlbums',
components: { components: {
ContentWithHeading, ContentWithHeading,
ControlButton,
ListAlbums, ListAlbums,
ModalDialogComposer ModalDialogComposer
}, },
@ -92,6 +90,9 @@ export default {
}, },
play() { play() {
webapi.player_play_expression(this.expression, true) webapi.player_play_expression(this.expression, true)
},
showDetails() {
this.show_details_modal = true
} }
} }
} }

View File

@ -29,16 +29,12 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a <control-button :handler="showDetails" icon="dots-horizontal" />
class="button is-small is-rounded" <control-button
@click="show_details_modal = true" :handler="play"
> icon="shuffle"
<mdicon class="icon" name="dots-horizontal" size="16" /> label="page.composer.shuffle"
</a> />
<a class="button is-small is-rounded" @click="play">
<mdicon class="icon" name="shuffle" size="16" />
<span v-text="$t('page.composer.shuffle')" />
</a>
</div> </div>
</template> </template>
<template #content> <template #content>
@ -55,6 +51,7 @@
<script> <script>
import ContentWithHeading from '@/templates/ContentWithHeading.vue' import ContentWithHeading from '@/templates/ContentWithHeading.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 IndexButtonList from '@/components/IndexButtonList.vue' import IndexButtonList from '@/components/IndexButtonList.vue'
@ -81,6 +78,7 @@ export default {
name: 'PageComposerTracks', name: 'PageComposerTracks',
components: { components: {
ContentWithHeading, ContentWithHeading,
ControlButton,
ControlDropdown, ControlDropdown,
IndexButtonList, IndexButtonList,
ListTracks, ListTracks,
@ -136,6 +134,9 @@ export default {
}, },
play() { play() {
webapi.player_play_expression(this.expression, true) webapi.player_play_expression(this.expression, true)
},
showDetails() {
this.show_details_modal = true
} }
} }
} }

View File

@ -6,16 +6,8 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a <control-button :handler="showDetails" icon="dots-horizontal" />
class="button is-small is-rounded" <control-button :handler="play" icon="play" label="page.files.play" />
@click="show_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" />
</a>
<a class="button is-small is-rounded" @click="play">
<mdicon class="icon" name="play" size="16" />
<span v-text="$t('page.files.play')" />
</a>
</div> </div>
</template> </template>
<template #content> <template #content>
@ -38,6 +30,7 @@
<script> <script>
import ContentWithHeading from '@/templates/ContentWithHeading.vue' import ContentWithHeading from '@/templates/ContentWithHeading.vue'
import ControlButton from '@/components/ControlButton.vue'
import { GroupedList } from '@/lib/GroupedList' import { GroupedList } from '@/lib/GroupedList'
import ListDirectories from '@/components/ListDirectories.vue' import ListDirectories from '@/components/ListDirectories.vue'
import ListPlaylists from '@/components/ListPlaylists.vue' import ListPlaylists from '@/components/ListPlaylists.vue'
@ -78,6 +71,7 @@ export default {
name: 'PageFiles', name: 'PageFiles',
components: { components: {
ContentWithHeading, ContentWithHeading,
ControlButton,
ListDirectories, ListDirectories,
ListPlaylists, ListPlaylists,
ListTracks, ListTracks,
@ -125,6 +119,9 @@ export default {
play() { play() {
webapi.player_play_expression(this.expression, false) webapi.player_play_expression(this.expression, false)
}, },
showDetails() {
this.show_details_modal = true
},
transform(path) { transform(path) {
return { name: path.slice(path.lastIndexOf('/') + 1), path } return { name: path.slice(path.lastIndexOf('/') + 1), path }
} }

View File

@ -17,16 +17,12 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a <control-button :handler="showDetails" icon="dots-horizontal" />
class="button is-small is-rounded" <control-button
@click="show_details_modal = true" :handler="play"
> icon="shuffle"
<mdicon class="icon" name="dots-horizontal" size="16" /> label="page.genre.shuffle"
</a> />
<a class="button is-small is-rounded" @click="play">
<mdicon class="icon" name="shuffle" size="16" />
<span v-text="$t('page.genre.shuffle')" />
</a>
</div> </div>
</template> </template>
<template #content> <template #content>
@ -44,6 +40,7 @@
<script> <script>
import ContentWithHeading from '@/templates/ContentWithHeading.vue' import ContentWithHeading from '@/templates/ContentWithHeading.vue'
import ControlButton from '@/components/ControlButton.vue'
import { GroupedList } from '@/lib/GroupedList' import { GroupedList } from '@/lib/GroupedList'
import IndexButtonList from '@/components/IndexButtonList.vue' import IndexButtonList from '@/components/IndexButtonList.vue'
import ListAlbums from '@/components/ListAlbums.vue' import ListAlbums from '@/components/ListAlbums.vue'
@ -69,6 +66,7 @@ export default {
name: 'PageGenreAlbums', name: 'PageGenreAlbums',
components: { components: {
ContentWithHeading, ContentWithHeading,
ControlButton,
IndexButtonList, IndexButtonList,
ListAlbums, ListAlbums,
ModalDialogGenre ModalDialogGenre
@ -100,6 +98,9 @@ export default {
`genre is "${this.genre.name}" and media_kind is ${this.media_kind}`, `genre is "${this.genre.name}" and media_kind is ${this.media_kind}`,
true true
) )
},
showDetails() {
this.show_details_modal = true
} }
} }
} }

View File

@ -29,16 +29,12 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a <control-button :handler="showDetails" icon="dots-horizontal" />
class="button is-small is-rounded" <control-button
@click="show_details_modal = true" :handler="play"
> icon="shuffle"
<mdicon class="icon" name="dots-horizontal" size="16" /> label="page.genre.shuffle"
</a> />
<a class="button is-small is-rounded" @click="play">
<mdicon class="icon" name="shuffle" size="16" />
<span v-text="$t('page.genre.shuffle')" />
</a>
</div> </div>
</template> </template>
<template #content> <template #content>
@ -56,6 +52,7 @@
<script> <script>
import ContentWithHeading from '@/templates/ContentWithHeading.vue' import ContentWithHeading from '@/templates/ContentWithHeading.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 IndexButtonList from '@/components/IndexButtonList.vue' import IndexButtonList from '@/components/IndexButtonList.vue'
@ -82,6 +79,7 @@ export default {
name: 'PageGenreTracks', name: 'PageGenreTracks',
components: { components: {
ContentWithHeading, ContentWithHeading,
ControlButton,
ControlDropdown, ControlDropdown,
IndexButtonList, IndexButtonList,
ListTracks, ListTracks,
@ -140,6 +138,9 @@ export default {
}, },
play() { play() {
webapi.player_play_expression(this.expression, true) webapi.player_play_expression(this.expression, true)
},
showDetails() {
this.show_details_modal = true
} }
} }
} }

View File

@ -10,16 +10,13 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a <control-button :handler="showDetails" icon="dots-horizontal" />
class="button is-small is-rounded" <control-button
@click="show_details_modal = true" :disabled="tracks.count === 0"
> :handler="play"
<mdicon class="icon" name="dots-horizontal" size="16" /> icon="shuffle"
</a> label="page.playlist.shuffle"
<a class="button is-small is-rounded" @click="play"> />
<mdicon class="icon" name="shuffle" size="16" />
<span v-text="$t('page.playlist.shuffle')" />
</a>
</div> </div>
</template> </template>
<template #content> <template #content>
@ -37,6 +34,7 @@
<script> <script>
import ContentWithHeading from '@/templates/ContentWithHeading.vue' import ContentWithHeading from '@/templates/ContentWithHeading.vue'
import ControlButton from '@/components/ControlButton.vue'
import { GroupedList } from '@/lib/GroupedList' import { GroupedList } from '@/lib/GroupedList'
import ListTracks from '@/components/ListTracks.vue' import ListTracks from '@/components/ListTracks.vue'
import ModalDialogPlaylist from '@/components/ModalDialogPlaylist.vue' import ModalDialogPlaylist from '@/components/ModalDialogPlaylist.vue'
@ -58,7 +56,12 @@ const dataObject = {
export default { export default {
name: 'PagePlaylistTracks', name: 'PagePlaylistTracks',
components: { ContentWithHeading, ListTracks, ModalDialogPlaylist }, components: {
ContentWithHeading,
ControlButton,
ListTracks,
ModalDialogPlaylist
},
beforeRouteEnter(to, from, next) { beforeRouteEnter(to, from, next) {
dataObject.load(to).then((response) => { dataObject.load(to).then((response) => {
@ -86,6 +89,9 @@ export default {
methods: { methods: {
play() { play() {
webapi.player_play_uri(this.uris, true) webapi.player_play_uri(this.uris, true)
},
showDetails() {
this.show_details_modal = true
} }
} }
} }

View File

@ -10,16 +10,13 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a <control-button :handler="showDetails" icon="dots-horizontal" />
class="button is-small is-rounded" <control-button
@click="show_playlist_details_modal = true" :disabled="playlist.tracks.total === 0"
> :handler="play"
<mdicon class="icon" name="dots-horizontal" size="16" /> icon="shuffle"
</a> label="page.spotify.playlist.shuffle"
<a class="button is-small is-rounded" @click="play"> />
<mdicon class="icon" name="shuffle" size="16" />
<span v-text="$t('page.spotify.playlist.shuffle')" />
</a>
</div> </div>
</template> </template>
<template #content> <template #content>
@ -48,6 +45,7 @@
<script> <script>
import ContentWithHeading from '@/templates/ContentWithHeading.vue' import ContentWithHeading from '@/templates/ContentWithHeading.vue'
import ControlButton from '@/components/ControlButton.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'
@ -84,6 +82,7 @@ export default {
name: 'PagePlaylistTracksSpotify', name: 'PagePlaylistTracksSpotify',
components: { components: {
ContentWithHeading, ContentWithHeading,
ControlButton,
ListTracksSpotify, ListTracksSpotify,
ModalDialogPlaylistSpotify, ModalDialogPlaylistSpotify,
VueEternalLoading VueEternalLoading
@ -145,6 +144,9 @@ export default {
play() { play() {
this.show_details_modal = false this.show_details_modal = false
webapi.player_play_uri(this.playlist.uri, true) webapi.player_play_uri(this.playlist.uri, true)
},
showDetails() {
this.show_playlist_details_modal = true
} }
} }
} }

View File

@ -11,16 +11,12 @@
v-text="$t('count.tracks', { count: album.track_count })" v-text="$t('count.tracks', { count: album.track_count })"
/> />
<div class="buttons is-centered-mobile mt-5"> <div class="buttons is-centered-mobile mt-5">
<a class="button is-small is-rounded" @click="play"> <control-button
<mdicon class="icon" name="play" size="16" /> :handler="play"
<span v-text="$t('page.podcast.play')" /> icon="play"
</a> label="page.podcast.play"
<a />
class="button is-small is-rounded" <control-button :handler="showDetails" icon="dots-horizontal" />
@click="show_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" />
</a>
</div> </div>
</template> </template>
<template #heading-right> <template #heading-right>
@ -29,7 +25,7 @@
:artist="album.artist" :artist="album.artist"
:album="album.name" :album="album.name"
class="is-clickable is-medium" class="is-clickable is-medium"
@click="show_details_modal = true" @click="showDetails"
/> />
</template> </template>
<template #content> <template #content>
@ -71,6 +67,7 @@
<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 ListTracks from '@/components/ListTracks.vue' import ListTracks from '@/components/ListTracks.vue'
@ -96,6 +93,7 @@ export default {
name: 'PagePodcast', name: 'PagePodcast',
components: { components: {
ContentWithHero, ContentWithHero,
ControlButton,
ControlImage, ControlImage,
ListTracks, ListTracks,
ModalDialog, ModalDialog,
@ -160,6 +158,9 @@ export default {
.then(() => { .then(() => {
this.$router.replace({ name: 'podcasts' }) this.$router.replace({ name: 'podcasts' })
}) })
},
showDetails() {
this.show_details_modal = true
} }
} }
} }

View File

@ -6,10 +6,11 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a class="button is-small is-rounded" @click="mark_all_played"> <control-button
<mdicon class="icon" name="pencil" size="16" /> :handler="mark_all_played"
<span v-text="$t('page.podcasts.mark-all-played')" /> icon="pencil"
</a> label="page.podcasts.mark-all-played"
/>
</div> </div>
</template> </template>
<template #content> <template #content>
@ -30,21 +31,17 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a <control-button
v-if="rss.tracks > 0" v-if="rss.tracks > 0"
class="button is-small is-rounded" :handler="update_rss"
@click="update_rss" icon="refresh"
> label="page.podcasts.update"
<mdicon class="icon" name="refresh" size="16" /> />
<span v-text="$t('page.podcasts.update')" /> <control-button
</a> :handler="open_add_podcast_dialog"
<a icon="rss"
class="button is-small is-rounded" label="page.podcasts.add"
@click="open_add_podcast_dialog" />
>
<mdicon class="icon" name="rss" size="16" />
<span v-text="$t('page.podcasts.add')" />
</a>
</div> </div>
</template> </template>
<template #content> <template #content>
@ -65,6 +62,7 @@
<script> <script>
import ContentWithHeading from '@/templates/ContentWithHeading.vue' import ContentWithHeading from '@/templates/ContentWithHeading.vue'
import ControlButton from '@/components/ControlButton.vue'
import { GroupedList } from '@/lib/GroupedList' import { GroupedList } from '@/lib/GroupedList'
import ListAlbums from '@/components/ListAlbums.vue' import ListAlbums from '@/components/ListAlbums.vue'
import ListTracks from '@/components/ListTracks.vue' import ListTracks from '@/components/ListTracks.vue'
@ -91,6 +89,7 @@ export default {
name: 'PagePodcasts', name: 'PagePodcasts',
components: { components: {
ContentWithHeading, ContentWithHeading,
ControlButton,
ListAlbums, ListAlbums,
ListTracks, ListTracks,
ModalDialogAddRss ModalDialogAddRss

View File

@ -10,47 +10,37 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<button <control-button
class="button is-small is-rounded" :handler="update_show_next_items"
:class="{ 'is-dark': show_only_next_items }" :class="{ 'is-dark': show_only_next_items }"
@click="update_show_next_items" icon="eye-off-outline"
> label="page.queue.hide-previous"
<mdicon class="icon" name="eye-off-outline" size="16" /> />
<span v-text="$t('page.queue.hide-previous')" /> <control-button
</button> :handler="open_add_stream_dialog"
<button icon="web"
class="button is-small is-rounded" label="page.queue.add-stream"
@click="open_add_stream_dialog" />
> <control-button
<mdicon class="icon" name="web" size="16" />
<span v-text="$t('page.queue.add-stream')" />
</button>
<button
class="button is-small is-rounded"
:class="{ 'is-dark': edit_mode }" :class="{ 'is-dark': edit_mode }"
:disabled="queue_items.length === 0" :disabled="queue_items.length === 0"
@click="edit_mode = !edit_mode" :handler="toggleEdit"
> icon="pencil"
<mdicon class="icon" name="pencil" size="16" /> label="page.queue.edit"
<span v-text="$t('page.queue.edit')" /> />
</button> <control-button
<button
class="button is-small is-rounded"
:disabled="queue_items.length === 0" :disabled="queue_items.length === 0"
@click="queue_clear" :handler="queue_clear"
> icon="delete-empty"
<mdicon class="icon" name="delete-empty" size="16" /> label="page.queue.clear"
<span v-text="$t('page.queue.clear')" /> />
</button> <control-button
<button
v-if="is_queue_save_allowed" v-if="is_queue_save_allowed"
class="button is-small is-rounded"
:disabled="queue_items.length === 0" :disabled="queue_items.length === 0"
@click="save_dialog" :handler="save_dialog"
> icon="download"
<mdicon class="icon" name="download" size="16" /> label="page.queue.save"
<span v-text="$t('page.queue.save')" /> />
</button>
</div> </div>
</template> </template>
<template #content> <template #content>
@ -102,6 +92,7 @@
<script> <script>
import ContentWithHeading from '@/templates/ContentWithHeading.vue' import ContentWithHeading from '@/templates/ContentWithHeading.vue'
import ControlButton from '@/components/ControlButton.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'
@ -117,6 +108,7 @@ export default {
name: 'PageQueue', name: 'PageQueue',
components: { components: {
ContentWithHeading, ContentWithHeading,
ControlButton,
ListItemQueueItem, ListItemQueueItem,
ModalDialogAddStream, ModalDialogAddStream,
ModalDialogPlaylistSave, ModalDialogPlaylistSave,
@ -200,6 +192,9 @@ export default {
this.show_pls_save_modal = true this.show_pls_save_modal = true
} }
}, },
toggleEdit() {
this.edit_mode = !this.edit_mode
},
update_show_next_items() { update_show_next_items() {
this.uiStore.show_only_next_items = !this.uiStore.show_only_next_items this.uiStore.show_only_next_items = !this.uiStore.show_only_next_items
} }